commit 1707dc634979b46f202a680240d5a8fbd0f47c4c Author: jhchun Date: Fri Apr 24 10:52:47 2026 +0900 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9d7f9a3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,53 @@ +# Archives +*.rar +*.zip +*.7z +*.tar +*.tar.gz +*.tgz + +# Claude AI +.claude/ +docs/ + +# Compiled binaries +*.o +*.hex +*.bin +*.elf +*.map +*.lst + +# Build directories +_build/ +build/ +output/ + +# IDE/Editor +.vscode/ +*.swp +*.swo +*~ +*.uvguix.* +JLinkLog.txt +*.crf +*.d +*.htm +*.lnp +*.dep +*.axf + +# Segger/J-Link +*.jlink + +# nRF specific +sdk_config.h.bak + +# Windows +Thumbs.db +desktop.ini +.DS_Store + +# Temporary files +*.tmp +*.bak diff --git a/README.md b/README.md new file mode 100644 index 0000000..27cd12c --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +# Medithings VesiScan BASIC + +nRF52840 기반 초음파(Piezo) 방광 모니터링 패치 펌웨어 + +## Version +VBTFW0111 +VesiScan-Basic Tester Ver1.2.2 + +## Overview + +VesiScan BASIC은 피에조 초음파 트랜스듀서와 IMU 센서를 이용하여 방광 상태를 측정하고, BLE를 통해 모바일 클라이언트로 데이터를 전송하는 웨어러블 패치 디바이스 펌웨어입니다. + +## Hardware + +| 구분 | 칩/센서 | 사양 | 인터페이스 | +|------|--------|------|-----------| +| MCU | nRF52840 | ARM Cortex-M4, SoftDevice S140 | - | +| Piezo TX | MD1822K6-G + TC7920K6-G | MOSFET Driver, +/-20V | GPIO (Timer+PPI) | +| Piezo MUX | 8ch MUX (MUXA/MUXB) | 채널 선택 (CH0~CH7) | GPIO | +| Echo AFE | ADA2200 | Lock-in Amplifier | SPI | +| Echo ADC | ADC121S051 | 12-bit, Echo 신호 샘플링 | SPI | +| DAC | MCP4725 | 12-bit, 바이어스 전압 | I2C (SW) | +| DigiPot | AD5272 | 가변저항, AGC 제어 | I2C (SW) | +| IMU | ICM42670P | 6축 가속도/자이로 | I2C (HW) | + +### Piezo 주파수 옵션 + +| freq | 주파수 | +|------|--------| +| 0 | 1.8 MHz | +| 1 (기본) | 2.1 MHz | +| 2 | 2.0 MHz | +| 3 | 1.7 MHz | +| 4 | 2.2 MHz | + +### 8채널 MUX 매핑 + +| Channel | MUX | SEL1 | SEL0 | EN_MUXA | EN_MUXB | +|---------|-----|------|------|---------|---------| +| CH0 | A0 | 0 | 0 | 1 | 0 | +| CH1 | A2 | 0 | 1 | 1 | 0 | +| CH2 | A1 | 1 | 0 | 1 | 0 | +| CH3 | A3 | 1 | 1 | 1 | 0 | +| CH4 | B0 | 1 | 1 | 0 | 1 | +| CH5 | B1 | 0 | 1 | 0 | 1 | + +### Echo 수신 체인 + +``` +Piezo → MUX(8ch) → ADA2200(AFE) → ADC121S051 → nRF52840 + ↑ + MCP4725(Bias) + AD5272(AGC) +``` + +### IMU 사양 + +| 항목 | 설정 | +|------|------| +| 센서 | ICM42670P (6축: 3축 가속도 + 3축 자이로) | +| 인터페이스 | I2C (HW) | +| 모드 | Low-Noise Mode | +| 해상도 | 16-bit | + +## Build + +- **IDE**: Keil uVision5 (ARM5) +- **SDK**: nRF5 SDK + SoftDevice S140 + +## Project Structure + +```text +project/ +|-- ble_peripheral/ +| `-- ble_app_bladder_patch/ +| |-- main.c / main.h # Application entry, BLE init, main loop +| |-- command/ # Command parser, command table, handlers +| | `-- handlers/ # Device / sensor / piezo command handlers +| |-- measurement/ # Sensor and acquisition modules +| | |-- piezo/ # Piezo TX driver and mux channel control +| | |-- adc121s051/ # Echo ADC sampling / acquisition +| | |-- imu/ # ICM42670P support and motion libraries +| | |-- battery/ # Battery voltage measurement +| | `-- temperature/ # TMP235-Q1 temperature sensing +| |-- hal/ +| | |-- i2c/ # Shared I2C manager +| | `-- fds/ # Flash data storage helpers +| |-- system/ +| | |-- power/ # Power control +| | |-- led/ # LED control +| | |-- security/ # BLE security / bonding +| | `-- main_timer.c # Periodic timing / scheduler logic +| |-- pca10056/s140/arm5_no_packs/ # Keil project files and local build output +| `-- download/ # Flashing / DFU scripts and generated images +`-- dfu/ + `-- secure_bootloader/ # BLE DFU bootloader project +``` + +## License + +Proprietary - Medithings Co., Ltd. diff --git a/components/ble/ble_advertising/ble_advertising.c b/components/ble/ble_advertising/ble_advertising.c new file mode 100644 index 0000000..c87f12d --- /dev/null +++ b/components/ble/ble_advertising/ble_advertising.c @@ -0,0 +1,813 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(BLE_ADVERTISING) +#include "ble_advdata.h" +#include "ble_advertising.h" +#include "nrf_soc.h" +#include "nrf_log.h" +#include "sdk_errors.h" +#include "nrf_sdh_ble.h" + +#define BLE_ADV_MODES (5) /**< Total number of possible advertising modes. */ + + +/**@brief Function for checking if the whitelist is in use. + * + * @param[in] p_advertising Advertising module instance. + */ +static bool whitelist_has_entries(ble_advertising_t * const p_advertising) +{ + return p_advertising->whitelist_in_use; +} + + +/**@brief Function for checking if an address is valid. + * + * @param[in] p_addr Pointer to a bluetooth address. + */ +static bool addr_is_valid(uint8_t const * const p_addr) +{ + for (uint32_t i = 0; i < BLE_GAP_ADDR_LEN; i++) + { + if (p_addr[i] != 0) + { + return true; + } + } + return false; +} + + +/**@brief Function for checking the next advertising mode. + * + * @param[in] adv_mode Current advertising mode. + */ +static ble_adv_mode_t adv_mode_next_get(ble_adv_mode_t adv_mode) +{ + return (ble_adv_mode_t)((adv_mode + 1) % BLE_ADV_MODES); +} + + +/**@brief Function for handling the Connected event. + * + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_connected(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt) +{ + if (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_PERIPH) + { + p_advertising->current_slave_link_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + } +} + + +/**@brief Function for handling the Disconnected event. + * + * @param[in] p_advertising Advertising module instance. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_disconnected(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt) +{ + uint32_t ret; + + p_advertising->whitelist_temporarily_disabled = false; + + if (p_ble_evt->evt.gap_evt.conn_handle == p_advertising->current_slave_link_conn_handle && + p_advertising->adv_modes_config.ble_adv_on_disconnect_disabled == false) + { + ret = ble_advertising_start(p_advertising, BLE_ADV_MODE_DIRECTED_HIGH_DUTY); + if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) + { + p_advertising->error_handler(ret); + } + } +} + + +/**@brief Function for handling the Timeout event. + * + * @param[in] p_advertising Advertising module instance. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_terminated(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt) +{ + ret_code_t ret; + + if (p_ble_evt->header.evt_id != BLE_GAP_EVT_ADV_SET_TERMINATED) + { + // Nothing to do. + return; + } + + if ( p_ble_evt->evt.gap_evt.params.adv_set_terminated.reason == BLE_GAP_EVT_ADV_SET_TERMINATED_REASON_TIMEOUT + ||p_ble_evt->evt.gap_evt.params.adv_set_terminated.reason == BLE_GAP_EVT_ADV_SET_TERMINATED_REASON_LIMIT_REACHED) + { + // Start advertising in the next mode. + ret = ble_advertising_start(p_advertising, adv_mode_next_get(p_advertising->adv_mode_current)); + + if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) + { + p_advertising->error_handler(ret); + } + } +} + + +/**@brief Get the next available advertising mode. + * + * @param[in] p_advertising Advertising module instance. + * @param[in] adv_mode Requested advertising mode. + * + * @returns adv_mode if possible, or the best available mode if not. + */ +static ble_adv_mode_t adv_mode_next_avail_get(ble_advertising_t * const p_advertising, + ble_adv_mode_t adv_mode) +{ + bool peer_addr_is_valid = addr_is_valid(p_advertising->peer_address.addr); + + // If a mode is disabled, continue to the next mode. + + switch (adv_mode) + { + case BLE_ADV_MODE_DIRECTED_HIGH_DUTY: + if ( (p_advertising->adv_modes_config.ble_adv_directed_high_duty_enabled) + && (!p_advertising->adv_modes_config.ble_adv_extended_enabled) + && (peer_addr_is_valid)) + { + return BLE_ADV_MODE_DIRECTED_HIGH_DUTY; + } + // Fallthrough. + + case BLE_ADV_MODE_DIRECTED: + if ((p_advertising->adv_modes_config.ble_adv_directed_enabled) && peer_addr_is_valid) + { + return BLE_ADV_MODE_DIRECTED; + } + // Fallthrough. + + case BLE_ADV_MODE_FAST: + if (p_advertising->adv_modes_config.ble_adv_fast_enabled) + { + return BLE_ADV_MODE_FAST; + } + // Fallthrough. + + case BLE_ADV_MODE_SLOW: + if (p_advertising->adv_modes_config.ble_adv_slow_enabled) + { + return BLE_ADV_MODE_SLOW; + } + // Fallthrough. + + default: + return BLE_ADV_MODE_IDLE; + } +} + + +/**@brief Function for starting high duty directed advertising. + * + * @param[in] p_advertising Advertising instance. + * @param[out] p_adv_params Advertising parameters. + * + * @return NRF_SUCCESS + */ +static ret_code_t set_adv_mode_directed_high_duty(ble_advertising_t * const p_advertising, + ble_gap_adv_params_t * p_adv_params) +{ + p_advertising->adv_evt = BLE_ADV_EVT_DIRECTED_HIGH_DUTY; + p_advertising->p_adv_data = NULL; + + p_adv_params->p_peer_addr = &(p_advertising->peer_address); + p_adv_params->interval = 0; + p_adv_params->properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED_HIGH_DUTY_CYCLE; + p_adv_params->duration = BLE_GAP_ADV_TIMEOUT_HIGH_DUTY_MAX; + + return NRF_SUCCESS; +} + + +/**@brief Function for starting directed slow advertising. + * + * @param[in] p_advertising Advertising module instance. + * @param[out] p_adv_params Advertising parameters. + * + * @return NRF_SUCCESS + */ +static ret_code_t set_adv_mode_directed(ble_advertising_t * const p_advertising, + ble_gap_adv_params_t * p_adv_params) +{ + p_advertising->adv_evt = BLE_ADV_EVT_DIRECTED; +#if !defined (S112) && !defined(S312) && !defined(S113) + if (p_advertising->adv_modes_config.ble_adv_extended_enabled) + { + p_adv_params->properties.type = BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_DIRECTED; + } + else + { +#endif // !defined (S112) && !defined(S312) + p_adv_params->properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED; +#if !defined (S112) && !defined(S312) && !defined(S113) + } +#endif // !defined (S112) && !defined(S312) && !defined(S113) + p_adv_params->duration = p_advertising->adv_modes_config.ble_adv_directed_timeout; + + p_advertising->p_adv_data = NULL; + + p_adv_params->p_peer_addr = &p_advertising->peer_address; + p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_directed_interval; + + return NRF_SUCCESS; +} + + +/**@brief Function for indicating whether to use whitelist for advertising. + * + * @param[in] p_advertising Advertising module instance. + * + * @return Whether to use whitelist. + */ +static bool use_whitelist(ble_advertising_t * const p_advertising) +{ + return((p_advertising->adv_modes_config.ble_adv_whitelist_enabled) && + (!p_advertising->whitelist_temporarily_disabled) && + (whitelist_has_entries(p_advertising))); +} + + +/**@brief Function for setting new advertising flags in the advertising parameters. + * + * @param[in] p_advertising Advertising module instance. + * @param[in] flags New flags. + * + * @return Any error from @ref sd_ble_gap_adv_set_configure. + */ +static ret_code_t flags_set(ble_advertising_t * const p_advertising, uint8_t flags) +{ + uint8_t * p_flags = ble_advdata_parse(p_advertising->adv_data.adv_data.p_data, + p_advertising->adv_data.adv_data.len, + BLE_GAP_AD_TYPE_FLAGS); + + if (p_flags != NULL) + { + *p_flags = flags; + } + + return sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, &p_advertising->adv_data, &p_advertising->adv_params); +} + + +/**@brief Function for starting fast advertising. + * + * @param[in] p_advertising Advertising module instance. + * @param[out] p_adv_params Advertising parameters. + * + * @return NRF_SUCCESS or an error from @ref flags_set(). + */ +static ret_code_t set_adv_mode_fast(ble_advertising_t * const p_advertising, + ble_gap_adv_params_t * p_adv_params) +{ + ret_code_t ret; + + p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_fast_interval; + p_adv_params->duration = p_advertising->adv_modes_config.ble_adv_fast_timeout; + +#if !defined (S112) && !defined(S312) && !defined(S113) + if (p_advertising->adv_modes_config.ble_adv_extended_enabled) + { + p_advertising->adv_params.properties.type = BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_UNDIRECTED; + } + else + { +#endif // !defined (S112) && !defined(S312) && !defined(S113) + p_advertising->adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; +#if !defined (S112) && !defined(S312) && !defined(S113) + } +#endif // !defined (S112) && !defined(S312) && !defined(S113) + + if (use_whitelist(p_advertising)) + { + p_adv_params->filter_policy = BLE_GAP_ADV_FP_FILTER_CONNREQ; + + // Set correct flags. + ret = flags_set(p_advertising, BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED); + VERIFY_SUCCESS(ret); + + p_advertising->adv_evt = BLE_ADV_EVT_FAST_WHITELIST; + } + else + { + p_advertising->adv_evt = BLE_ADV_EVT_FAST; + } + p_advertising->p_adv_data = &(p_advertising->adv_data); + return NRF_SUCCESS; +} + + +/**@brief Function for starting slow advertising. + * + * @param[in] p_advertising Advertising module instance. + * @param[out] p_adv_params Advertising parameters. + * + * @return NRF_SUCCESS or an error from @ref flags_set(). + */ +static ret_code_t set_adv_mode_slow(ble_advertising_t * const p_advertising, + ble_gap_adv_params_t * p_adv_params) +{ + ret_code_t ret; + + p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_slow_interval; + p_adv_params->duration = p_advertising->adv_modes_config.ble_adv_slow_timeout; + +#if !defined (S112) && !defined(S312) && !defined(S113) + if (p_advertising->adv_modes_config.ble_adv_extended_enabled) + { + p_advertising->adv_params.properties.type = BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_UNDIRECTED; + } + else + { +#endif // !defined (S112) && !defined(S312) && !defined(S113) + p_advertising->adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; +#if !defined (S112) && !defined(S312) && !defined(S113) + } +#endif // !defined (S112) && !defined(S312) && !defined(S113) + + if (use_whitelist(p_advertising)) + { + p_adv_params->filter_policy = BLE_GAP_ADV_FP_FILTER_CONNREQ; + + // Set correct flags. + ret = flags_set(p_advertising, BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED); + VERIFY_SUCCESS(ret); + + p_advertising->adv_evt = BLE_ADV_EVT_SLOW_WHITELIST; + } + else + { + p_advertising->adv_evt = BLE_ADV_EVT_SLOW; + } + p_advertising->p_adv_data = &(p_advertising->adv_data); + return NRF_SUCCESS; +} + + +/**@brief Function for checking if an advertising module configuration is legal. + * + * @details Advertising module can not be initialized if high duty directed advertising is used + * together with extended advertising. + * + * @param[in] p_config Pointer to the configuration. + * + * @return True If the configuration is valid. + * @return False If the configuration is invalid. + */ +static bool config_is_valid(ble_adv_modes_config_t const * const p_config) +{ + if ((p_config->ble_adv_directed_high_duty_enabled == true) && + (p_config->ble_adv_extended_enabled == true)) + { + return false; + } +#if !defined (S140) + else if ( p_config->ble_adv_primary_phy == BLE_GAP_PHY_CODED || + p_config->ble_adv_secondary_phy == BLE_GAP_PHY_CODED) + { + return false; + } +#endif // !defined (S140) + else + { + return true; + } +} + + +/**@brief Function for getting the maximum size of the advertising data buffer. + * + * @param[in] p_advertising Advertising module instance. + * + * @returns The maximum size of the advertising data buffer. + */ +static uint16_t adv_set_data_size_max_get(ble_advertising_t const * const p_advertising) +{ + uint16_t adv_set_data_size_max; + + if (p_advertising->adv_modes_config.ble_adv_extended_enabled == true) + { +#ifdef BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED + adv_set_data_size_max = BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED; +#else + adv_set_data_size_max = BLE_GAP_ADV_SET_DATA_SIZE_MAX; +#endif // BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED + } + else + { + adv_set_data_size_max = BLE_GAP_ADV_SET_DATA_SIZE_MAX; + } + + return adv_set_data_size_max; +} + + +void ble_advertising_conn_cfg_tag_set(ble_advertising_t * const p_advertising, + uint8_t ble_cfg_tag) +{ + p_advertising->conn_cfg_tag = ble_cfg_tag; +} + + +uint32_t ble_advertising_init(ble_advertising_t * const p_advertising, + ble_advertising_init_t const * const p_init) +{ + uint32_t ret; + if ((p_init == NULL) || (p_advertising == NULL)) + { + return NRF_ERROR_NULL; + } + if (!config_is_valid(&p_init->config)) + { + return NRF_ERROR_INVALID_PARAM; + } + + p_advertising->adv_mode_current = BLE_ADV_MODE_IDLE; + p_advertising->adv_modes_config = p_init->config; + p_advertising->conn_cfg_tag = BLE_CONN_CFG_TAG_DEFAULT; + p_advertising->evt_handler = p_init->evt_handler; + p_advertising->error_handler = p_init->error_handler; + p_advertising->current_slave_link_conn_handle = BLE_CONN_HANDLE_INVALID; + p_advertising->p_adv_data = &p_advertising->adv_data; + + memset(&p_advertising->peer_address, 0, sizeof(p_advertising->peer_address)); + + // Copy advertising data. + if (!p_advertising->initialized) + { + p_advertising->adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; + } + p_advertising->adv_data.adv_data.p_data = p_advertising->enc_advdata[0]; + p_advertising->adv_data.adv_data.len = adv_set_data_size_max_get(p_advertising); + + ret = ble_advdata_encode(&p_init->advdata, p_advertising->enc_advdata[0], &p_advertising->adv_data.adv_data.len); + VERIFY_SUCCESS(ret); + + p_advertising->adv_data.scan_rsp_data.p_data = p_advertising->enc_scan_rsp_data[0]; + p_advertising->adv_data.scan_rsp_data.len = adv_set_data_size_max_get(p_advertising); + + ret = ble_advdata_encode(&p_init->srdata, + p_advertising->adv_data.scan_rsp_data.p_data, + &p_advertising->adv_data.scan_rsp_data.len); + VERIFY_SUCCESS(ret); + + // Configure a initial advertising configuration. The advertising data and and advertising + // parameters will be changed later when we call @ref ble_advertising_start, but must be set + // to legal values here to define an advertising handle. + p_advertising->adv_params.primary_phy = BLE_GAP_PHY_1MBPS; + p_advertising->adv_params.duration = p_advertising->adv_modes_config.ble_adv_fast_timeout; + p_advertising->adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; + p_advertising->adv_params.p_peer_addr = NULL; + p_advertising->adv_params.filter_policy = BLE_GAP_ADV_FP_ANY; + p_advertising->adv_params.interval = p_advertising->adv_modes_config.ble_adv_fast_interval; + + ret = sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, NULL, &p_advertising->adv_params); + VERIFY_SUCCESS(ret); + + p_advertising->initialized = true; + return ret; +} + + +/**@brief Function for checking that a phy define value matches one of the valid phys from the SD. + * + * @param[in] PHY to be validated. + * + * @retval true If the PHY value is valid (1mbit, 2mbit, coded). + * @retval false If the PHY value is invalid. + */ +static bool phy_is_valid(uint32_t const * const p_phy) +{ + if ((*p_phy) == BLE_GAP_PHY_1MBPS || + (*p_phy) == BLE_GAP_PHY_2MBPS +#if defined (S140) + || (*p_phy) == BLE_GAP_PHY_CODED +#endif // !defined (S140) + ) + { + return true; + } + else + { + return false; + } +} + + +uint32_t ble_advertising_start(ble_advertising_t * const p_advertising, + ble_adv_mode_t advertising_mode) +{ + uint32_t ret; + + if (p_advertising->initialized == false) + { + return NRF_ERROR_INVALID_STATE; + } + + p_advertising->adv_mode_current = advertising_mode; + + memset(&p_advertising->peer_address, 0, sizeof(p_advertising->peer_address)); + + if ( ((p_advertising->adv_modes_config.ble_adv_directed_high_duty_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED_HIGH_DUTY)) + ||((p_advertising->adv_modes_config.ble_adv_directed_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED_HIGH_DUTY)) + ||((p_advertising->adv_modes_config.ble_adv_directed_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED)) + ) + { + if (p_advertising->evt_handler != NULL) + { + p_advertising->peer_addr_reply_expected = true; + p_advertising->evt_handler(BLE_ADV_EVT_PEER_ADDR_REQUEST); + } + else + { + p_advertising->peer_addr_reply_expected = false; + } + } + + p_advertising->adv_mode_current = adv_mode_next_avail_get(p_advertising, advertising_mode); + + // Fetch the whitelist. + if ((p_advertising->evt_handler != NULL) && + (p_advertising->adv_mode_current == BLE_ADV_MODE_FAST || p_advertising->adv_mode_current == BLE_ADV_MODE_SLOW) && + (p_advertising->adv_modes_config.ble_adv_whitelist_enabled) && + (!p_advertising->whitelist_temporarily_disabled)) + { + p_advertising->whitelist_in_use = false; + p_advertising->whitelist_reply_expected = true; + p_advertising->evt_handler(BLE_ADV_EVT_WHITELIST_REQUEST); + } + else + { + p_advertising->whitelist_reply_expected = false; + } + + // Initialize advertising parameters with default values. + memset(&p_advertising->adv_params, 0, sizeof(p_advertising->adv_params)); + + p_advertising->adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; + + // Use 1MBIT as primary phy if no phy was selected. + if (phy_is_valid(&p_advertising->adv_modes_config.ble_adv_primary_phy)) + { + p_advertising->adv_params.primary_phy = p_advertising->adv_modes_config.ble_adv_primary_phy; + } + else + { + p_advertising->adv_params.primary_phy = BLE_GAP_PHY_1MBPS; + } + + if (p_advertising->adv_modes_config.ble_adv_extended_enabled) + { + // Use 1MBIT as secondary phy if no phy was selected. + if (phy_is_valid(&p_advertising->adv_modes_config.ble_adv_secondary_phy)) + { + p_advertising->adv_params.secondary_phy = p_advertising->adv_modes_config.ble_adv_secondary_phy; + } + else + { + p_advertising->adv_params.secondary_phy = BLE_GAP_PHY_1MBPS; + } + } + p_advertising->adv_params.filter_policy = BLE_GAP_ADV_FP_ANY; + + // Set advertising parameters and events according to selected advertising mode. + switch (p_advertising->adv_mode_current) + { + case BLE_ADV_MODE_DIRECTED_HIGH_DUTY: + ret = set_adv_mode_directed_high_duty(p_advertising, &p_advertising->adv_params); + break; + + case BLE_ADV_MODE_DIRECTED: + ret = set_adv_mode_directed(p_advertising, &p_advertising->adv_params); + break; + + case BLE_ADV_MODE_FAST: + ret = set_adv_mode_fast(p_advertising, &p_advertising->adv_params); + break; + + case BLE_ADV_MODE_SLOW: + ret = set_adv_mode_slow(p_advertising, &p_advertising->adv_params); + break; + + case BLE_ADV_MODE_IDLE: + p_advertising->adv_evt = BLE_ADV_EVT_IDLE; + break; + + default: + break; + } + + if (p_advertising->adv_mode_current != BLE_ADV_MODE_IDLE) + { + + ret = sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, p_advertising->p_adv_data, &p_advertising->adv_params); + if (ret != NRF_SUCCESS) + { + return ret; + } + ret = sd_ble_gap_adv_start(p_advertising->adv_handle, p_advertising->conn_cfg_tag); + + if (ret != NRF_SUCCESS) + { + return ret; + } + } + + if (p_advertising->evt_handler != NULL) + { + p_advertising->evt_handler(p_advertising->adv_evt); + } + + return NRF_SUCCESS; +} + + +void ble_advertising_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) +{ + ble_advertising_t * p_advertising = (ble_advertising_t *)p_context; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + on_connected(p_advertising, p_ble_evt); + break; + + // Upon disconnection, whitelist will be activated and direct advertising is started. + case BLE_GAP_EVT_DISCONNECTED: + on_disconnected(p_advertising, p_ble_evt); + break; + + // Upon terminated advertising (time-out), the next advertising mode is started. + case BLE_GAP_EVT_ADV_SET_TERMINATED: + on_terminated(p_advertising, p_ble_evt); + break; + + default: + break; + } +} + + +uint32_t ble_advertising_peer_addr_reply(ble_advertising_t * const p_advertising, + ble_gap_addr_t * p_peer_address) +{ + if (!p_advertising->peer_addr_reply_expected) + { + return NRF_ERROR_INVALID_STATE; + } + + p_advertising->peer_addr_reply_expected = false; + + memcpy(&p_advertising->peer_address, p_peer_address, sizeof(p_advertising->peer_address)); + + return NRF_SUCCESS; +} + + +uint32_t ble_advertising_whitelist_reply(ble_advertising_t * const p_advertising, + ble_gap_addr_t const * p_gap_addrs, + uint32_t addr_cnt, + ble_gap_irk_t const * p_gap_irks, + uint32_t irk_cnt) +{ + if (!p_advertising->whitelist_reply_expected) + { + return NRF_ERROR_INVALID_STATE; + } + + p_advertising->whitelist_reply_expected = false; + p_advertising->whitelist_in_use = ((addr_cnt > 0) || (irk_cnt > 0)); + + return NRF_SUCCESS; +} + + +uint32_t ble_advertising_restart_without_whitelist(ble_advertising_t * const p_advertising) +{ + ret_code_t ret; + + (void) sd_ble_gap_adv_stop(p_advertising->adv_handle); + + p_advertising->whitelist_temporarily_disabled = true; + p_advertising->whitelist_in_use = false; + p_advertising->adv_params.filter_policy = BLE_GAP_ADV_FP_ANY; + // Set correct flags. + ret = flags_set(p_advertising, BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); + VERIFY_SUCCESS(ret); + + ret = ble_advertising_start(p_advertising, p_advertising->adv_mode_current); + if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) + { + p_advertising->error_handler(ret); + } + + return NRF_SUCCESS; +} + + +void ble_advertising_modes_config_set(ble_advertising_t * const p_advertising, + ble_adv_modes_config_t const * const p_adv_modes_config) +{ + p_advertising->adv_modes_config = *p_adv_modes_config; +} + + +ret_code_t ble_advertising_advdata_update(ble_advertising_t * const p_advertising, + ble_advdata_t const * const p_advdata, + ble_advdata_t const * const p_srdata) +{ + VERIFY_PARAM_NOT_NULL(p_advertising); + if (p_advertising->initialized == false) + { + return NRF_ERROR_INVALID_STATE; + } + + if ((p_advdata == NULL) && (p_srdata == NULL)) + { + return NRF_ERROR_NULL; + } + + ble_gap_adv_data_t new_adv_data; + memset(&new_adv_data, 0, sizeof(new_adv_data)); + + if (p_advdata != NULL) + { + new_adv_data.adv_data.p_data = + (p_advertising->p_adv_data->adv_data.p_data != p_advertising->enc_advdata[0]) ? + p_advertising->enc_advdata[0] : p_advertising->enc_advdata[1]; + new_adv_data.adv_data.len = adv_set_data_size_max_get(p_advertising); + + ret_code_t ret = ble_advdata_encode(p_advdata, + new_adv_data.adv_data.p_data, + &new_adv_data.adv_data.len); + VERIFY_SUCCESS(ret); + } + + if (p_srdata != NULL) + { + new_adv_data.scan_rsp_data.p_data = + (p_advertising->p_adv_data->scan_rsp_data.p_data != p_advertising->enc_scan_rsp_data[0]) ? + p_advertising->enc_scan_rsp_data[0] : p_advertising->enc_scan_rsp_data[1]; + new_adv_data.scan_rsp_data.len = adv_set_data_size_max_get(p_advertising); + + ret_code_t ret = ble_advdata_encode(p_srdata, + new_adv_data.scan_rsp_data.p_data, + &new_adv_data.scan_rsp_data.len); + VERIFY_SUCCESS(ret); + } + + memcpy(&p_advertising->adv_data, &new_adv_data, sizeof(p_advertising->adv_data)); + p_advertising->p_adv_data = &p_advertising->adv_data; + + return sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, + p_advertising->p_adv_data, + NULL); +} + + +#endif // NRF_MODULE_ENABLED(BLE_ADVERTISING) diff --git a/components/ble/ble_advertising/ble_advertising.h b/components/ble/ble_advertising/ble_advertising.h new file mode 100644 index 0000000..f419f87 --- /dev/null +++ b/components/ble/ble_advertising/ble_advertising.h @@ -0,0 +1,355 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup ble_advertising Advertising Module + * @{ + * @ingroup ble_sdk_lib + * @brief Module for handling connectable BLE advertising. + * + * @details The Advertising Module handles connectable advertising for your application. It can + * be configured with advertising modes to suit most typical use cases. + * Your main application can react to changes in advertising modes + * if an event handler is provided. + * + * @note The Advertising Module supports only applications with a single peripheral link. + * + */ + +#ifndef BLE_ADVERTISING_H__ +#define BLE_ADVERTISING_H__ + +#include +#include "nrf_error.h" +#include "ble.h" +#include "ble_gap.h" +#include "ble_gattc.h" +#include "ble_advdata.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Macro for defining a ble_advertising instance. + * + * @param _name Name of the instance. + * @hideinitializer + */ +#define BLE_ADVERTISING_DEF(_name) \ +static ble_advertising_t _name; \ +NRF_SDH_BLE_OBSERVER(_name ## _ble_obs, \ + BLE_ADV_BLE_OBSERVER_PRIO, \ + ble_advertising_on_ble_evt, &_name) + + +/**@brief Advertising modes. */ +typedef enum +{ + BLE_ADV_MODE_IDLE, /**< Idle; no connectable advertising is ongoing. */ + BLE_ADV_MODE_DIRECTED_HIGH_DUTY, /**< Directed advertising (high duty cycle) attempts to connect to the most recently disconnected peer. */ + BLE_ADV_MODE_DIRECTED, /**< Directed advertising (low duty cycle) attempts to connect to the most recently disconnected peer. */ + BLE_ADV_MODE_FAST, /**< Fast advertising will connect to any peer device, or filter with a whitelist if one exists. */ + BLE_ADV_MODE_SLOW, /**< Slow advertising is similar to fast advertising. By default, it uses a longer advertising interval and time-out than fast advertising. However, these options are defined by the user. */ +} ble_adv_mode_t; + +/**@brief Advertising events. + * + * @details These events are propagated to the main application if a handler was provided during + * initialization of the Advertising Module. Events for modes that are not used can be + * ignored. Similarly, BLE_ADV_EVT_WHITELIST_REQUEST and BLE_ADV_EVT_PEER_ADDR_REQUEST + * can be ignored if whitelist and direct advertising is not used. + */ +typedef enum +{ + BLE_ADV_EVT_IDLE, /**< Idle; no connectable advertising is ongoing.*/ + BLE_ADV_EVT_DIRECTED_HIGH_DUTY, /**< Direct advertising mode has started. */ + BLE_ADV_EVT_DIRECTED, /**< Directed advertising (low duty cycle) has started. */ + BLE_ADV_EVT_FAST, /**< Fast advertising mode has started. */ + BLE_ADV_EVT_SLOW, /**< Slow advertising mode has started. */ + BLE_ADV_EVT_FAST_WHITELIST, /**< Fast advertising mode using the whitelist has started. */ + BLE_ADV_EVT_SLOW_WHITELIST, /**< Slow advertising mode using the whitelist has started. */ + BLE_ADV_EVT_WHITELIST_REQUEST, /**< Request a whitelist from the main application. For whitelist advertising to work, the whitelist must be set when this event occurs. */ + BLE_ADV_EVT_PEER_ADDR_REQUEST /**< Request a peer address from the main application. For directed advertising to work, the peer address must be set when this event occurs. */ +} ble_adv_evt_t; + +/**@brief Options for the different advertisement modes. + * + * @details This structure is used to enable or disable advertising modes and to configure time-out + * periods and advertising intervals. + */ +typedef struct +{ + bool ble_adv_on_disconnect_disabled; /**< Enable or disable automatic return to advertising upon disconnecting.*/ + bool ble_adv_whitelist_enabled; /**< Enable or disable use of the whitelist. */ + bool ble_adv_directed_high_duty_enabled; /**< Enable or disable high duty direct advertising mode. Can not be used together with extended advertising. */ + bool ble_adv_directed_enabled; /**< Enable or disable direct advertising mode. */ + bool ble_adv_fast_enabled; /**< Enable or disable fast advertising mode. */ + bool ble_adv_slow_enabled; /**< Enable or disable slow advertising mode. */ + uint32_t ble_adv_directed_interval; /**< Advertising interval for directed advertising. */ + uint32_t ble_adv_directed_timeout; /**< Time-out (number of tries) for direct advertising. */ + uint32_t ble_adv_fast_interval; /**< Advertising interval for fast advertising. */ + uint32_t ble_adv_fast_timeout; /**< Time-out (in units of 10ms) for fast advertising. */ + uint32_t ble_adv_slow_interval; /**< Advertising interval for slow advertising. */ + uint32_t ble_adv_slow_timeout; /**< Time-out (in units of 10ms) for slow advertising. */ + bool ble_adv_extended_enabled; /**< Enable or disable extended advertising. */ + uint32_t ble_adv_secondary_phy; /**< PHY for the secondary (extended) advertising @ref BLE_GAP_PHYS (BLE_GAP_PHY_1MBPS, BLE_GAP_PHY_2MBPS or BLE_GAP_PHY_CODED). */ + uint32_t ble_adv_primary_phy; /**< PHY for the primary advertising. @ref BLE_GAP_PHYS (BLE_GAP_PHY_1MBPS, BLE_GAP_PHY_2MBPS or BLE_GAP_PHY_CODED). */ +} ble_adv_modes_config_t; + +/**@brief BLE advertising event handler type. */ +typedef void (*ble_adv_evt_handler_t) (ble_adv_evt_t const adv_evt); + +/**@brief BLE advertising error handler type. */ +typedef void (*ble_adv_error_handler_t) (uint32_t nrf_error); + +typedef struct +{ + bool initialized; + bool advertising_start_pending; /**< Flag to keep track of ongoing operations in flash. */ + ble_adv_mode_t adv_mode_current; /**< Variable to keep track of the current advertising mode. */ + ble_adv_modes_config_t adv_modes_config; /**< Struct to keep track of disabled and enabled advertising modes, as well as time-outs and intervals.*/ + uint8_t conn_cfg_tag; /**< Variable to keep track of what connection settings will be used if the advertising results in a connection. */ + + ble_adv_evt_t adv_evt; /**< Advertising event propogated to the main application. The event is either a transaction to a new advertising mode, or a request for whitelist or peer address. */ + ble_adv_evt_handler_t evt_handler; /**< Handler for the advertising events. Can be initialized as NULL if no handling is implemented on in the main application. */ + ble_adv_error_handler_t error_handler; /**< Handler for the advertising error events. */ + + ble_gap_adv_params_t adv_params; /**< GAP advertising parameters. */ + uint8_t adv_handle; /**< Handle for the advertising set. */ + +#ifdef BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED + uint8_t enc_advdata[2][BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED]; /**< Advertising data sets in encoded form. Current and swap buffer. */ + uint8_t enc_scan_rsp_data[2][BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED]; /**< Scan response data sets in encoded form. Current and swap buffer. */ +#else + uint8_t enc_advdata[2][BLE_GAP_ADV_SET_DATA_SIZE_MAX]; /**< Current advertising data in encoded form. */ + uint8_t enc_scan_rsp_data[2][BLE_GAP_ADV_SET_DATA_SIZE_MAX]; /**< Current scan response data in encoded form. */ +#endif // BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED + + ble_gap_adv_data_t adv_data; /**< Advertising data. */ + ble_gap_adv_data_t *p_adv_data; /**< Will be set to point to @ref ble_advertising_t::adv_data for undirected advertising, and will be set to NULL for directed advertising. */ + + uint16_t current_slave_link_conn_handle; /**< Connection handle for the active link. */ + ble_gap_addr_t peer_address; /**< Address of the most recently connected peer, used for direct advertising. */ + bool peer_addr_reply_expected; /**< Flag to verify that peer address is only set when requested. */ + bool whitelist_temporarily_disabled; /**< Flag to keep track of temporary disabling of the whitelist. */ + bool whitelist_reply_expected; /**< Flag to verify that the whitelist is only set when requested. */ + bool whitelist_in_use; /**< This module needs to be aware of whether or not a whitelist has been set (e.g. using the Peer Manager) in order to start advertising with the proper advertising params (filter policy). */ +} ble_advertising_t; + +typedef struct +{ + uint32_t interval; + uint32_t timeout; + bool enabled; +} ble_adv_mode_config_t; + +/**@brief Initialization parameters for the Advertising Module. + * @details This structure is used to pass advertising options, advertising data, + * and an event handler to the Advertising Module during initialization. + */ +typedef struct +{ + ble_advdata_t advdata; /**< Advertising data: name, appearance, discovery flags, and more. */ + ble_advdata_t srdata; /**< Scan response data: Supplement to advertising data. */ + ble_adv_modes_config_t config; /**< Select which advertising modes and intervals will be utilized.*/ + ble_adv_evt_handler_t evt_handler; /**< Event handler that will be called upon advertising events. */ + ble_adv_error_handler_t error_handler; /**< Error handler that will propogate internal errors to the main applications. */ +} ble_advertising_init_t; + + +/**@brief Function for handling BLE events. + * + * @details This function must be called from the BLE stack event dispatcher for + * the module to handle BLE events that are relevant for the Advertising Module. + * + * @param[in] p_ble_evt BLE stack event. + * @param[in] p_adv Advertising Module instance. + */ +void ble_advertising_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_adv); + + +/**@brief Function for initializing the Advertising Module. + * + * @details Encodes the required advertising data and passes it to the stack. + * Also builds a structure to be passed to the stack when starting advertising. + * Most of the supplied data is copied into a local structure where it is manipulated + * depending on what advertising modes are started in @ref ble_advertising_start. + * The exception is advdata_t::uuids_more_available, advdata_t::uuids_complete, and + * advdata_t::uuids_solicited which are stored as pointers. The main application must + * store these UUIDs. + * + * @param[out] p_advertising Advertising Module instance. This structure must be supplied by + * the application. It is initialized by this function and will later + * be used to identify this particular module instance. + * @param[in] p_init Information needed to initialize the module. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_PARAM If the advertising configuration in \p p_init is invalid. + * @return If functions from other modules return errors to this function, the @ref nrf_error are propagated. + */ +uint32_t ble_advertising_init(ble_advertising_t * const p_advertising, + ble_advertising_init_t const * const p_init); + + + /**@brief Function for changing the connection settings tag that will be used for upcoming connections. + * + * @details See @ref sd_ble_cfg_set for more details about changing connection settings. If this + * function is never called, @ref BLE_CONN_CFG_TAG_DEFAULT will be used. + * + * @param[in] p_advertising Advertising Module instance. + * @param[in] ble_cfg_tag Configuration for the connection settings (see @ref sd_ble_cfg_set). + */ +void ble_advertising_conn_cfg_tag_set(ble_advertising_t * const p_advertising, uint8_t ble_cfg_tag); + +/**@brief Function for starting advertising. + * + * @details You can start advertising in any of the advertising modes that you enabled + * during initialization. + * + * @param[in] p_advertising Advertising Module instance. + * @param[in] advertising_mode Advertising mode. + * + * @retval @ref NRF_SUCCESS On success, else an error code indicating reason for failure. + * @retval @ref NRF_ERROR_INVALID_STATE If the module is not initialized. + */ +uint32_t ble_advertising_start(ble_advertising_t * const p_advertising, + ble_adv_mode_t advertising_mode); + + +/**@brief Function for setting the peer address. + * + * @details The peer address must be set by the application upon receiving a + * @ref BLE_ADV_EVT_PEER_ADDR_REQUEST event. Without the peer address, the directed + * advertising mode will not be run. + * + * @param[in] p_advertising Advertising Module instance. + * @param[in] p_peer_addr Pointer to a peer address. + * + * @retval @ref NRF_SUCCESS Successfully stored the peer address pointer in the Advertising Module. + * @retval @ref NRF_ERROR_INVALID_STATE If a reply was not expected. + */ +uint32_t ble_advertising_peer_addr_reply(ble_advertising_t * const p_advertising, + ble_gap_addr_t * p_peer_addr); + + +/**@brief Function for setting a whitelist. + * + * @details The whitelist must be set by the application upon receiving a + * @ref BLE_ADV_EVT_WHITELIST_REQUEST event. Without the whitelist, the whitelist + * advertising for fast and slow modes will not be run. + * + * @param[in] p_advertising Advertising Module instance. + * @param[in] p_gap_addrs The list of GAP addresses to whitelist. + * @param[in] addr_cnt The number of GAP addresses to whitelist. + * @param[in] p_gap_irks The list of peer IRK to whitelist. + * @param[in] irk_cnt The number of peer IRK to whitelist. + * + * @retval @ref NRF_SUCCESS If the operation was successful. + * @retval @ref NRF_ERROR_INVALID_STATE If a call to this function was made without a + * BLE_ADV_EVT_WHITELIST_REQUEST event being received. + */ +uint32_t ble_advertising_whitelist_reply(ble_advertising_t * const p_advertising, + ble_gap_addr_t const * p_gap_addrs, + uint32_t addr_cnt, + ble_gap_irk_t const * p_gap_irks, + uint32_t irk_cnt); + + +/**@brief Function for disabling whitelist advertising. + * + * @details This function temporarily disables whitelist advertising. + * Calling this function resets the current time-out countdown. + * + * @param[in] p_advertising Advertising Module instance. + * + * @retval @ref NRF_SUCCESS On success, else an error message propogated from the Softdevice. + */ +uint32_t ble_advertising_restart_without_whitelist(ble_advertising_t * const p_advertising); + + +/**@brief Function for changing advertising modes configuration. + * + * @details This function can be called if you wish to reconfigure the advertising modes that the + * Advertising Module will cycle through. Enable or disable modes as listed in + * @ref ble_adv_mode_t; or change the duration of the advertising and use of whitelist. + * + * Keep in mind that @ref ble_adv_modes_config_t is also supplied when calling + * @ref ble_advertising_init. Calling @ref ble_advertising_modes_config_set + * is only necessary if your application requires this behaviour to change. + * + * @param[in] p_advertising Advertising Module instance. + * @param[in] p_adv_modes_config Struct to keep track of disabled and enabled advertising modes, + * as well as time-outs and intervals. + */ +void ble_advertising_modes_config_set(ble_advertising_t * const p_advertising, + ble_adv_modes_config_t const * const p_adv_modes_config); + + +/**@brief Function for updating advertising data. + * + * @details This function can be called if you wish to reconfigure the advertising data The update + * will be effective even if advertising has already been started. + * + * @param[in] p_advertising Advertising Module instance. + * @param[in] p_advdata Pointer to the structure for specifying the content of advertising data. + * Or null if there should be no advertising data. + * @param[in] p_srdata Pointer to the structure for specifying the content of scan response data. + * Or null if there should be no advertising data. + * + * @retval @ref NRF_ERROR_NULL If advertising instance was null. + * If both \p p_advdata and \p p_srdata are null. + * @retval @ref NRF_ERROR_INVALID_STATE If advertising instance was not initialized. + * @retval @ref NRF_SUCCESS or any error from @ref ble_advdata_encode or + * @ref sd_ble_gap_adv_set_configure(). + */ +ret_code_t ble_advertising_advdata_update(ble_advertising_t * const p_advertising, + ble_advdata_t const * const p_advdata, + ble_advdata_t const * const p_srdata); + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_ADVERTISING_H__ + +/** @} */ diff --git a/components/ble/ble_db_discovery/ble_db_discovery.c b/components/ble/ble_db_discovery/ble_db_discovery.c new file mode 100644 index 0000000..eb636ea --- /dev/null +++ b/components/ble/ble_db_discovery/ble_db_discovery.c @@ -0,0 +1,1030 @@ +/** + * Copyright (c) 2013 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(BLE_DB_DISCOVERY) +#include "ble_db_discovery.h" +#include +#include "ble_srv_common.h" +#define NRF_LOG_MODULE_NAME ble_db_disc +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define SRV_DISC_START_HANDLE 0x0001 /**< The start handle value used during service discovery. */ +#define DB_DISCOVERY_MAX_USERS BLE_DB_DISCOVERY_MAX_SRV /**< The maximum number of users/registrations allowed by this module. */ +#define MODULE_INITIALIZED (m_initialized == true) /**< Macro designating whether the module has been initialized properly. */ + + +/**@brief Array of structures containing information about the registered application modules. */ +static ble_uuid_t m_registered_handlers[DB_DISCOVERY_MAX_USERS]; +static ble_db_discovery_evt_handler_t m_evt_handler; +static nrf_ble_gq_t * mp_gatt_queue; /**< Pointer to BLE GATT Queue instance. */ + +static uint32_t m_num_of_handlers_reg; /**< The number of handlers registered with the DB Discovery module. */ +static bool m_initialized = false; /**< This variable Indicates if the module is initialized or not. */ + +/**@brief Function for fetching the event handler provided by a registered application module. + * + * @param[in] srv_uuid UUID of the service. + * + * @retval evt_handler Event handler of the module, registered for the given service UUID. + * @retval NULL If no event handler is found. + */ +static ble_db_discovery_evt_handler_t registered_handler_get(ble_uuid_t const * p_srv_uuid) +{ + for (uint32_t i = 0; i < m_num_of_handlers_reg; i++) + { + if (BLE_UUID_EQ(&(m_registered_handlers[i]), p_srv_uuid)) + { + return (m_evt_handler); + } + } + + return NULL; +} + + +/**@brief Function for storing the event handler provided by a registered application module. + * + * @param[in] p_srv_uuid The UUID of the service. + * @param[in] p_evt_handler The event handler provided by the application. + * + * @retval NRF_SUCCESS If the handler was stored or already present in the list. + * @retval NRF_ERROR_NO_MEM If there is no space left to store the handler. + */ +static uint32_t registered_handler_set(ble_uuid_t const * p_srv_uuid, + ble_db_discovery_evt_handler_t p_evt_handler) +{ + if (registered_handler_get(p_srv_uuid) != NULL) + { + return NRF_SUCCESS; + } + + if (m_num_of_handlers_reg < DB_DISCOVERY_MAX_USERS) + { + m_registered_handlers[m_num_of_handlers_reg] = *p_srv_uuid; + m_num_of_handlers_reg++; + + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_NO_MEM; + } +} + + +/**@brief Function for sending all pending discovery events to the corresponding user modules. + */ +static void pending_user_evts_send(ble_db_discovery_t * p_db_discovery) +{ + for (uint32_t i = 0; i < m_num_of_handlers_reg; i++) + { + // Pass the event to the corresponding event handler. + p_db_discovery->pending_usr_evts[i].evt_handler(&(p_db_discovery->pending_usr_evts[i].evt)); + } + + p_db_discovery->pending_usr_evt_index = 0; +} + +/**@brief Function for indicating availability of DB discovery instance. + * + * @details This function triggers an event indicating the finish of a discovery process. + * If the event has happened, then the application can perform the next discovery + * procedure on this DB discovery instance. + * + * @param[in] p_db_discovery Pointer to the DB discovery structure. + * @param[in] conn_handle Connection Handle. + */ +static void discovery_available_evt_trigger(ble_db_discovery_t * const p_db_discovery, + uint16_t const conn_handle) +{ + ble_db_discovery_evt_t evt; + + memset(&evt, 0, sizeof(evt)); + + evt.conn_handle = conn_handle; + evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE; + evt.params.p_db_instance = (void *)p_db_discovery; + + if (m_evt_handler) + { + m_evt_handler(&evt); + } +} + + +/**@brief Function for indicating error to the application. + * + * @details This function will fetch the event handler based on the UUID of the service being + * discovered. (The event handler is registered by the application beforehand). + * The error code is added to the pending events together with the event handler. + * If no event handler was found, then this function will do nothing. + * + * @param[in] p_db_discovery Pointer to the DB discovery structure. + * @param[in] err_code Error code that should be provided to the application. + * @param[in] conn_handle Connection Handle. + * + */ +static void discovery_error_evt_trigger(ble_db_discovery_t * p_db_discovery, + uint32_t err_code, + uint16_t conn_handle) +{ + ble_db_discovery_evt_handler_t p_evt_handler; + ble_gatt_db_srv_t * p_srv_being_discovered; + + p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); + + p_evt_handler = registered_handler_get(&(p_srv_being_discovered->srv_uuid)); + + if (p_evt_handler != NULL) + { + ble_db_discovery_evt_t evt = + { + .conn_handle = conn_handle, + .evt_type = BLE_DB_DISCOVERY_ERROR, + .params.err_code = err_code, + }; + + p_evt_handler(&evt); + } +} + + +/**@brief Function for interception of GATTC and @ref nrf_ble_gq errors. + * + * @param[in] nrf_error Error code. + * @param[in] p_ctx Parameter from the event handler. + * @param[in] conn_handle Connection handle. + */ +static void discovery_error_handler(uint32_t nrf_error, + void * p_ctx, + uint16_t conn_handle) +{ + ble_db_discovery_t * p_db_discovery = (ble_db_discovery_t *)p_ctx; + p_db_discovery->discovery_in_progress = false; + + discovery_error_evt_trigger(p_db_discovery, nrf_error, conn_handle); + discovery_available_evt_trigger(p_db_discovery, conn_handle); +} + + + +/**@brief Function for triggering a Discovery Complete or Service Not Found event to the + * application. + * + * @details This function will fetch the event handler based on the UUID of the service being + * discovered. (The event handler is registered by the application beforehand). + * It then triggers an event indicating the completion of the service discovery. + * If no event handler was found, then this function will do nothing. + * + * @param[in] p_db_discovery Pointer to the DB discovery structure. + * @param[in] is_srv_found Variable to indicate if the service was found at the peer. + * @param[in] conn_handle Connection Handle. + */ +static void discovery_complete_evt_trigger(ble_db_discovery_t * p_db_discovery, + bool is_srv_found, + uint16_t conn_handle) +{ + ble_db_discovery_evt_handler_t p_evt_handler; + ble_gatt_db_srv_t * p_srv_being_discovered; + + p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); + + p_evt_handler = registered_handler_get(&(p_srv_being_discovered->srv_uuid)); + + if (p_evt_handler != NULL) + { + if (p_db_discovery->pending_usr_evt_index < DB_DISCOVERY_MAX_USERS) + { + // Insert an event into the pending event list. + p_db_discovery->pending_usr_evts[p_db_discovery->pending_usr_evt_index].evt.conn_handle = conn_handle; + p_db_discovery->pending_usr_evts[p_db_discovery->pending_usr_evt_index].evt.params.discovered_db = + *p_srv_being_discovered; + + if (is_srv_found) + { + p_db_discovery->pending_usr_evts[p_db_discovery->pending_usr_evt_index].evt.evt_type = + BLE_DB_DISCOVERY_COMPLETE; + } + else + { + p_db_discovery->pending_usr_evts[p_db_discovery->pending_usr_evt_index].evt.evt_type = + BLE_DB_DISCOVERY_SRV_NOT_FOUND; + } + + p_db_discovery->pending_usr_evts[p_db_discovery->pending_usr_evt_index].evt_handler = p_evt_handler; + p_db_discovery->pending_usr_evt_index++; + + if (p_db_discovery->pending_usr_evt_index == m_num_of_handlers_reg) + { + // All registered modules have pending events. Send all pending events to the user + // modules. + pending_user_evts_send(p_db_discovery); + } + else + { + // Too many events pending. Do nothing. (Ideally this should not happen.) + } + } + } +} + + +/**@brief Function for handling service discovery completion. + * + * @details This function will be used to determine if there are more services to be discovered, + * and if so, initiate the discovery of the next service. + * + * @param[in] p_db_discovery Pointer to the DB Discovery Structure. + * @param[in] conn_handle Connection Handle. + */ +static void on_srv_disc_completion(ble_db_discovery_t * p_db_discovery, + uint16_t conn_handle) +{ + nrf_ble_gq_req_t db_srv_disc_req; + + memset(&db_srv_disc_req, 0, sizeof(nrf_ble_gq_req_t)); + + p_db_discovery->discoveries_count++; + + // Check if more services need to be discovered. + if (p_db_discovery->discoveries_count < m_num_of_handlers_reg) + { + // Reset the current characteristic index since a new service discovery is about to start. + p_db_discovery->curr_char_ind = 0; + + // Initiate discovery of the next service. + p_db_discovery->curr_srv_ind++; + + ble_gatt_db_srv_t * p_srv_being_discovered; + + p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); + + p_srv_being_discovered->srv_uuid = m_registered_handlers[p_db_discovery->curr_srv_ind]; + + // Reset the characteristic count in the current service to zero since a new service + // discovery is about to start. + p_srv_being_discovered->char_count = 0; + + NRF_LOG_DEBUG("Starting discovery of service with UUID 0x%x on connection handle 0x%x.", + p_srv_being_discovered->srv_uuid.uuid, conn_handle); + + uint32_t err_code; + + db_srv_disc_req.type = NRF_BLE_GQ_REQ_SRV_DISCOVERY; + db_srv_disc_req.params.gattc_srv_disc.start_handle = SRV_DISC_START_HANDLE; + db_srv_disc_req.params.gattc_srv_disc.srvc_uuid = p_srv_being_discovered->srv_uuid; + db_srv_disc_req.error_handler.p_ctx = p_db_discovery; + db_srv_disc_req.error_handler.cb = discovery_error_handler; + + err_code = nrf_ble_gq_item_add(mp_gatt_queue, &db_srv_disc_req, conn_handle); + + if (err_code != NRF_SUCCESS) + { + discovery_error_handler(err_code, p_db_discovery, conn_handle); + + return; + } + } + else + { + // No more service discovery is needed. + p_db_discovery->discovery_in_progress = false; + + discovery_available_evt_trigger(p_db_discovery, conn_handle); + } +} + + +/**@brief Function for finding out if a characteristic discovery should be performed after the + * last discovered characteristic. + * + * @details This function is used during the time of database discovery to find out if there is + * a need to do more characteristic discoveries. The value handles of the + * last discovered characteristic is compared with the end handle of the service. + * If the service handle is greater than one of the former characteristic handles, + * it means that a characteristic discovery is required. + * + * @param[in] p_db_discovery The pointer to the DB Discovery structure. + * @param[in] p_after_char The pointer to the last discovered characteristic. + * + * @retval True if a characteristic discovery is required. + * @retval False if a characteristic discovery is NOT required. + */ +static bool is_char_discovery_reqd(ble_db_discovery_t * p_db_discovery, + ble_gattc_char_t * p_after_char) +{ + if (p_after_char->handle_value < + p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle) + { + // Handle value of the characteristic being discovered is less than the end handle of + // the service being discovered. There is a possibility of more characteristics being + // present. Hence a characteristic discovery is required. + return true; + } + + return false; +} + + +/**@brief Function to find out if a descriptor discovery is required. + * + * @details This function finds out if there is a possibility of existence of descriptors between + * current characteristic and the next characteristic. If so, this function will compute + * the handle range on which the descriptors may be present and will return it. + * If the current characteristic is the last known characteristic, then this function + * will use the service end handle to find out if the current characteristic can have + * descriptors. + * + * @param[in] p_db_discovery Pointer to the DB Discovery structure. + * @param[in] p_curr_char Pointer to the current characteristic. + * @param[in] p_next_char Pointer to the next characteristic. This should be NULL if the + * caller knows that there is no characteristic after the current + * characteristic at the peer. + * @param[out] p_handle_range Pointer to the handle range in which descriptors may exist at the + * the peer. + * + * @retval True If a descriptor discovery is required. + * @retval False If a descriptor discovery is NOT required. + */ +static bool is_desc_discovery_reqd(ble_db_discovery_t * p_db_discovery, + ble_gatt_db_char_t * p_curr_char, + ble_gatt_db_char_t * p_next_char, + ble_gattc_handle_range_t * p_handle_range) +{ + if (p_next_char == NULL) + { + // Current characteristic is the last characteristic in the service. Check if the value + // handle of the current characteristic is equal to the service end handle. + if ( + p_curr_char->characteristic.handle_value == + p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle + ) + { + // No descriptors can be present for the current characteristic. p_curr_char is the last + // characteristic with no descriptors. + return false; + } + + p_handle_range->start_handle = p_curr_char->characteristic.handle_value + 1; + + // Since the current characteristic is the last characteristic in the service, the end + // handle should be the end handle of the service. + p_handle_range->end_handle = + p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle; + + return true; + } + + // p_next_char != NULL. Check for existence of descriptors between the current and the next + // characteristic. + if ((p_curr_char->characteristic.handle_value + 1) == p_next_char->characteristic.handle_decl) + { + // No descriptors can exist between the two characteristic. + return false; + } + + p_handle_range->start_handle = p_curr_char->characteristic.handle_value + 1; + p_handle_range->end_handle = p_next_char->characteristic.handle_decl - 1; + + return true; +} + + +/**@brief Function for performing characteristic discovery. + * + * @param[in] p_db_discovery Pointer to the DB Discovery structure. + * @param[in] conn_handle Connection Handle. + * + * @return NRF_SUCCESS if the SoftDevice was successfully requested to perform the characteristic + * discovery. Otherwise an error code. This function returns the error code returned + * by the SoftDevice API @ref sd_ble_gattc_characteristics_discover. + */ +static uint32_t characteristics_discover(ble_db_discovery_t * p_db_discovery, + uint16_t conn_handle) +{ + ble_gatt_db_srv_t * p_srv_being_discovered; + ble_gattc_handle_range_t handle_range; + nrf_ble_gq_req_t db_char_disc_req; + + memset(&db_char_disc_req, 0, sizeof(nrf_ble_gq_req_t)); + memset(&handle_range, 0, sizeof(ble_gattc_handle_range_t)); + + p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); + + if (p_db_discovery->curr_char_ind != 0) + { + // This is not the first characteristic being discovered. Hence the 'start handle' to be + // used must be computed using the handle_value of the previous characteristic. + ble_gattc_char_t * p_prev_char; + uint8_t prev_char_ind = p_db_discovery->curr_char_ind - 1; + + p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); + + p_prev_char = &(p_srv_being_discovered->charateristics[prev_char_ind].characteristic); + + handle_range.start_handle = p_prev_char->handle_value + 1; + } + else + { + // This is the first characteristic of this service being discovered. + handle_range.start_handle = p_srv_being_discovered->handle_range.start_handle; + } + + handle_range.end_handle = p_srv_being_discovered->handle_range.end_handle; + + db_char_disc_req.type = NRF_BLE_GQ_REQ_CHAR_DISCOVERY; + db_char_disc_req.params.gattc_char_disc = handle_range; + db_char_disc_req.error_handler.p_ctx = p_db_discovery; + db_char_disc_req.error_handler.cb = discovery_error_handler; + + return nrf_ble_gq_item_add(mp_gatt_queue, &db_char_disc_req, conn_handle); +} + + +/**@brief Function for performing descriptor discovery, if required. + * + * @details This function will check if descriptor discovery is required and then perform it if + * needed. If no more descriptor discovery is required for the service, then the output + * parameter p_raise_discov_complete is set to true, indicating to the caller that a + * discovery complete event can be triggered to the application. + * + * @param[in] p_db_discovery Pointer to the DB Discovery structure. + * @param[out] p_raise_discov_complete The value pointed to by this pointer will be set to true if + * the Discovery Complete event can be triggered to the + * application. + * @param[in] conn_handle Connection Handle. + * + * @return NRF_SUCCESS if the SoftDevice was successfully requested to perform the descriptor + * discovery, or if no more descriptor discovery is required. Otherwise an error code. + * This function returns the error code returned by the SoftDevice API @ref + * sd_ble_gattc_descriptors_discover. + */ +static uint32_t descriptors_discover(ble_db_discovery_t * p_db_discovery, + bool * p_raise_discov_complete, + uint16_t conn_handle) +{ + ble_gattc_handle_range_t handle_range; + ble_gatt_db_char_t * p_curr_char_being_discovered; + ble_gatt_db_srv_t * p_srv_being_discovered; + nrf_ble_gq_req_t db_desc_disc_req; + bool is_discovery_reqd = false; + + memset(&db_desc_disc_req, 0, sizeof(nrf_ble_gq_req_t)); + + p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); + + p_curr_char_being_discovered = + &(p_srv_being_discovered->charateristics[p_db_discovery->curr_char_ind]); + + if ((p_db_discovery->curr_char_ind + 1) == p_srv_being_discovered->char_count) + { + // This is the last characteristic of this service. + is_discovery_reqd = is_desc_discovery_reqd(p_db_discovery, + p_curr_char_being_discovered, + NULL, + &handle_range); + } + else + { + uint8_t i; + ble_gatt_db_char_t * p_next_char; + + for (i = p_db_discovery->curr_char_ind; i < p_srv_being_discovered->char_count; i++) + { + if (i == (p_srv_being_discovered->char_count - 1)) + { + // The current characteristic is the last characteristic in the service. + p_next_char = NULL; + } + else + { + p_next_char = &(p_srv_being_discovered->charateristics[i + 1]); + } + + // Check if it is possible for the current characteristic to have a descriptor. + if (is_desc_discovery_reqd(p_db_discovery, + p_curr_char_being_discovered, + p_next_char, + &handle_range)) + { + is_discovery_reqd = true; + break; + } + else + { + // No descriptors can exist. + p_curr_char_being_discovered = p_next_char; + p_db_discovery->curr_char_ind++; + } + } + } + + if (!is_discovery_reqd) + { + // No more descriptor discovery required. Discovery is complete. + // This informs the caller that a discovery complete event can be triggered. + *p_raise_discov_complete = true; + + return NRF_SUCCESS; + } + + *p_raise_discov_complete = false; + + db_desc_disc_req.type = NRF_BLE_GQ_REQ_DESC_DISCOVERY; + db_desc_disc_req.params.gattc_desc_disc = handle_range; + db_desc_disc_req.error_handler.p_ctx = p_db_discovery; + db_desc_disc_req.error_handler.cb = discovery_error_handler; + + return nrf_ble_gq_item_add(mp_gatt_queue, &db_desc_disc_req, conn_handle); +} + + +/**@brief Function for handling primary service discovery response. + * + * @details This function will handle the primary service discovery response and start the + * discovery of characteristics within that service. + * + * @param[in] p_db_discovery Pointer to the DB Discovery structure. + * @param[in] p_ble_gattc_evt Pointer to the GATT Client event. + */ +static void on_primary_srv_discovery_rsp(ble_db_discovery_t * p_db_discovery, + ble_gattc_evt_t const * p_ble_gattc_evt) +{ + ble_gatt_db_srv_t * p_srv_being_discovered; + + p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); + + if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle) + { + return; + } + + if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS) + { + uint32_t err_code; + ble_gattc_evt_prim_srvc_disc_rsp_t const * p_prim_srvc_disc_rsp_evt; + + NRF_LOG_DEBUG("Found service UUID 0x%x.", p_srv_being_discovered->srv_uuid.uuid); + + p_prim_srvc_disc_rsp_evt = &(p_ble_gattc_evt->params.prim_srvc_disc_rsp); + + p_srv_being_discovered->handle_range = p_prim_srvc_disc_rsp_evt->services[0].handle_range; + + // Number of services, previously discovered. + uint8_t num_srv_previous_disc = p_db_discovery->srv_count; + + // Number of services, currently discovered. + uint8_t current_srv_disc = p_prim_srvc_disc_rsp_evt->count; + + if ((num_srv_previous_disc + current_srv_disc) <= BLE_DB_DISCOVERY_MAX_SRV) + { + p_db_discovery->srv_count += current_srv_disc; + } + else + { + p_db_discovery->srv_count = BLE_DB_DISCOVERY_MAX_SRV; + + NRF_LOG_WARNING("Not enough space for services."); + NRF_LOG_WARNING("Increase BLE_DB_DISCOVERY_MAX_SRV to be able to store more " + "services!"); + } + + err_code = characteristics_discover(p_db_discovery, p_ble_gattc_evt->conn_handle); + + if (err_code != NRF_SUCCESS) + { + discovery_error_handler(err_code, p_db_discovery, p_ble_gattc_evt->conn_handle); + } + } + else + { + NRF_LOG_DEBUG("Service UUID 0x%x not found.", p_srv_being_discovered->srv_uuid.uuid); + // Trigger Service Not Found event to the application. + discovery_complete_evt_trigger(p_db_discovery, false, p_ble_gattc_evt->conn_handle); + on_srv_disc_completion(p_db_discovery, p_ble_gattc_evt->conn_handle); + } +} + + +/**@brief Function for handling characteristic discovery response. + * + * @param[in] p_db_discovery Pointer to the DB Discovery structure. + * @param[in] p_ble_gattc_evt Pointer to the GATT Client event. + */ +static void on_characteristic_discovery_rsp(ble_db_discovery_t * p_db_discovery, + ble_gattc_evt_t const * p_ble_gattc_evt) +{ + uint32_t err_code; + ble_gatt_db_srv_t * p_srv_being_discovered; + bool perform_desc_discov = false; + + if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle) + { + return; + } + + p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); + + if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS) + { + ble_gattc_evt_char_disc_rsp_t const * p_char_disc_rsp_evt; + + p_char_disc_rsp_evt = &(p_ble_gattc_evt->params.char_disc_rsp); + + // Find out the number of characteristics that were previously discovered (in earlier + // characteristic discovery responses, if any). + uint8_t num_chars_prev_disc = p_srv_being_discovered->char_count; + + // Find out the number of characteristics that are currently discovered (in the + // characteristic discovery response being handled). + uint8_t num_chars_curr_disc = p_char_disc_rsp_evt->count; + + // Check if the total number of discovered characteristics are supported by this module. + if ((num_chars_prev_disc + num_chars_curr_disc) <= BLE_GATT_DB_MAX_CHARS) + { + // Update the characteristics count. + p_srv_being_discovered->char_count += num_chars_curr_disc; + } + else + { + // The number of characteristics discovered at the peer is more than the supported + // maximum. This module will store only the characteristics found up to this point. + p_srv_being_discovered->char_count = BLE_GATT_DB_MAX_CHARS; + NRF_LOG_WARNING("Not enough space for characteristics associated with " + "service 0x%04X !", p_srv_being_discovered->srv_uuid.uuid); + NRF_LOG_WARNING("Increase BLE_GATT_DB_MAX_CHARS to be able to store more " + "characteristics for each service!"); + } + + uint32_t i; + uint32_t j; + + for (i = num_chars_prev_disc, j = 0; i < p_srv_being_discovered->char_count; i++, j++) + { + p_srv_being_discovered->charateristics[i].characteristic = + p_char_disc_rsp_evt->chars[j]; + + p_srv_being_discovered->charateristics[i].cccd_handle = BLE_GATT_HANDLE_INVALID; + p_srv_being_discovered->charateristics[i].ext_prop_handle = BLE_GATT_HANDLE_INVALID; + p_srv_being_discovered->charateristics[i].user_desc_handle = BLE_GATT_HANDLE_INVALID; + p_srv_being_discovered->charateristics[i].report_ref_handle = BLE_GATT_HANDLE_INVALID; + } + + ble_gattc_char_t * p_last_known_char; + + p_last_known_char = &(p_srv_being_discovered->charateristics[i - 1].characteristic); + + // If no more characteristic discovery is required, or if the maximum number of supported + // characteristic per service has been reached, descriptor discovery will be performed. + if ( !is_char_discovery_reqd(p_db_discovery, p_last_known_char) + || (p_srv_being_discovered->char_count == BLE_GATT_DB_MAX_CHARS)) + { + perform_desc_discov = true; + } + else + { + // Update the current characteristic index. + p_db_discovery->curr_char_ind = p_srv_being_discovered->char_count; + + // Perform another round of characteristic discovery. + err_code = characteristics_discover(p_db_discovery, p_ble_gattc_evt->conn_handle); + + if (err_code != NRF_SUCCESS) + { + discovery_error_handler(err_code, p_db_discovery, p_ble_gattc_evt->conn_handle); + + return; + } + } + } + else + { + // The previous characteristic discovery resulted in no characteristics. + // descriptor discovery should be performed. + perform_desc_discov = true; + } + + if (perform_desc_discov) + { + bool raise_discov_complete; + + p_db_discovery->curr_char_ind = 0; + + err_code = descriptors_discover(p_db_discovery, + &raise_discov_complete, + p_ble_gattc_evt->conn_handle); + + if (err_code != NRF_SUCCESS) + { + discovery_error_handler(err_code, p_db_discovery, p_ble_gattc_evt->conn_handle); + + return; + } + if (raise_discov_complete) + { + // No more characteristics and descriptors need to be discovered. Discovery is complete. + // Send a discovery complete event to the user application. + NRF_LOG_DEBUG("Discovery of service with UUID 0x%x completed with success" + " on connection handle 0x%x.", + p_srv_being_discovered->srv_uuid.uuid, + p_ble_gattc_evt->conn_handle); + + discovery_complete_evt_trigger(p_db_discovery, true, p_ble_gattc_evt->conn_handle); + on_srv_disc_completion(p_db_discovery, p_ble_gattc_evt->conn_handle); + } + } +} + + +/**@brief Function for handling descriptor discovery response. + * + * @param[in] p_db_discovery Pointer to the DB Discovery structure. + * @param[in] p_ble_gattc_evt Pointer to the GATT Client event. + */ +static void on_descriptor_discovery_rsp(ble_db_discovery_t * const p_db_discovery, + const ble_gattc_evt_t * const p_ble_gattc_evt) +{ + const ble_gattc_evt_desc_disc_rsp_t * p_desc_disc_rsp_evt; + ble_gatt_db_srv_t * p_srv_being_discovered; + + if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle) + { + return; + } + + p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); + + p_desc_disc_rsp_evt = &(p_ble_gattc_evt->params.desc_disc_rsp); + + ble_gatt_db_char_t * p_char_being_discovered = + &(p_srv_being_discovered->charateristics[p_db_discovery->curr_char_ind]); + + if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS) + { + // The descriptor was found at the peer. + // Iterate through and collect CCCD, Extended Properties, + // User Description & Report Reference descriptor handles. + for (uint32_t i = 0; i < p_desc_disc_rsp_evt->count; i++) + { + switch (p_desc_disc_rsp_evt->descs[i].uuid.uuid) + { + case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG: + p_char_being_discovered->cccd_handle = + p_desc_disc_rsp_evt->descs[i].handle; + break; + + case BLE_UUID_DESCRIPTOR_CHAR_EXT_PROP: + p_char_being_discovered->ext_prop_handle = + p_desc_disc_rsp_evt->descs[i].handle; + break; + + case BLE_UUID_DESCRIPTOR_CHAR_USER_DESC: + p_char_being_discovered->user_desc_handle = + p_desc_disc_rsp_evt->descs[i].handle; + break; + + case BLE_UUID_REPORT_REF_DESCR: + p_char_being_discovered->report_ref_handle = + p_desc_disc_rsp_evt->descs[i].handle; + break; + } + + /* Break if we've found all the descriptors we are looking for. */ + if (p_char_being_discovered->cccd_handle != BLE_GATT_HANDLE_INVALID && + p_char_being_discovered->ext_prop_handle != BLE_GATT_HANDLE_INVALID && + p_char_being_discovered->user_desc_handle != BLE_GATT_HANDLE_INVALID && + p_char_being_discovered->report_ref_handle != BLE_GATT_HANDLE_INVALID) + { + break; + } + } + } + + bool raise_discov_complete = false; + + if ((p_db_discovery->curr_char_ind + 1) == p_srv_being_discovered->char_count) + { + // No more characteristics and descriptors need to be discovered. Discovery is complete. + // Send a discovery complete event to the user application. + + raise_discov_complete = true; + } + else + { + // Begin discovery of descriptors for the next characteristic. + uint32_t err_code; + + p_db_discovery->curr_char_ind++; + + err_code = descriptors_discover(p_db_discovery, + &raise_discov_complete, + p_ble_gattc_evt->conn_handle); + + if (err_code != NRF_SUCCESS) + { + discovery_error_handler(err_code, p_db_discovery, p_ble_gattc_evt->conn_handle); + + return; + } + } + + if (raise_discov_complete) + { + NRF_LOG_DEBUG("Discovery of service with UUID 0x%x completed with success" + " on connection handle 0x%x.", + p_srv_being_discovered->srv_uuid.uuid, + p_ble_gattc_evt->conn_handle); + + discovery_complete_evt_trigger(p_db_discovery, true, p_ble_gattc_evt->conn_handle); + on_srv_disc_completion(p_db_discovery, p_ble_gattc_evt->conn_handle); + } +} + + +uint32_t ble_db_discovery_init(ble_db_discovery_init_t * p_db_init) +{ + uint32_t err_code = NRF_SUCCESS; + VERIFY_PARAM_NOT_NULL(p_db_init); + VERIFY_PARAM_NOT_NULL(p_db_init->evt_handler); + VERIFY_PARAM_NOT_NULL(p_db_init->p_gatt_queue); + + m_num_of_handlers_reg = 0; + m_initialized = true; + m_evt_handler = p_db_init->evt_handler; + mp_gatt_queue = p_db_init->p_gatt_queue; + + + return err_code; +} + + +uint32_t ble_db_discovery_close(ble_db_discovery_t * const p_db_discovery) +{ + m_num_of_handlers_reg = 0; + m_initialized = false; + p_db_discovery->pending_usr_evt_index = 0; + + return NRF_SUCCESS; +} + + +uint32_t ble_db_discovery_evt_register(ble_uuid_t const * p_uuid) +{ + VERIFY_PARAM_NOT_NULL(p_uuid); + VERIFY_MODULE_INITIALIZED(); + + return registered_handler_set(p_uuid, m_evt_handler); +} + + +static uint32_t discovery_start(ble_db_discovery_t * const p_db_discovery, uint16_t conn_handle) +{ + ret_code_t err_code; + ble_gatt_db_srv_t * p_srv_being_discovered; + nrf_ble_gq_req_t db_srv_disc_req; + + memset(p_db_discovery, 0x00, sizeof(ble_db_discovery_t)); + memset(&db_srv_disc_req, 0x00, sizeof(nrf_ble_gq_req_t)); + + err_code = nrf_ble_gq_conn_handle_register(mp_gatt_queue, conn_handle); + VERIFY_SUCCESS(err_code); + + p_db_discovery->conn_handle = conn_handle; + + p_db_discovery->pending_usr_evt_index = 0; + + p_db_discovery->discoveries_count = 0; + p_db_discovery->curr_srv_ind = 0; + p_db_discovery->curr_char_ind = 0; + + p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); + p_srv_being_discovered->srv_uuid = m_registered_handlers[p_db_discovery->curr_srv_ind]; + + NRF_LOG_DEBUG("Starting discovery of service with UUID 0x%x on connection handle 0x%x.", + p_srv_being_discovered->srv_uuid.uuid, conn_handle); + + db_srv_disc_req.type = NRF_BLE_GQ_REQ_SRV_DISCOVERY; + db_srv_disc_req.params.gattc_srv_disc.start_handle = SRV_DISC_START_HANDLE; + db_srv_disc_req.params.gattc_srv_disc.srvc_uuid = p_srv_being_discovered->srv_uuid; + db_srv_disc_req.error_handler.p_ctx = p_db_discovery; + db_srv_disc_req.error_handler.cb = discovery_error_handler; + + err_code = nrf_ble_gq_item_add(mp_gatt_queue, &db_srv_disc_req, conn_handle); + + if (err_code == NRF_SUCCESS) + { + p_db_discovery->discovery_in_progress = true; + } + + return err_code; +} + + +uint32_t ble_db_discovery_start(ble_db_discovery_t * const p_db_discovery, uint16_t conn_handle) +{ + VERIFY_PARAM_NOT_NULL(p_db_discovery); + VERIFY_MODULE_INITIALIZED(); + + if (m_num_of_handlers_reg == 0) + { + // No user modules were registered. There are no services to discover. + return NRF_ERROR_INVALID_STATE; + } + + if (p_db_discovery->discovery_in_progress) + { + return NRF_ERROR_BUSY; + } + + return discovery_start(p_db_discovery, conn_handle); +} + + +/**@brief Function for handling disconnected event. + * + * @param[in] p_db_discovery Pointer to the DB Discovery structure. + * @param[in] p_ble_gattc_evt Pointer to the GAP event. + */ +static void on_disconnected(ble_db_discovery_t * p_db_discovery, + ble_gap_evt_t const * p_evt) +{ + if (p_evt->conn_handle == p_db_discovery->conn_handle) + { + p_db_discovery->discovery_in_progress = false; + p_db_discovery->conn_handle = BLE_CONN_HANDLE_INVALID; + } +} + + +void ble_db_discovery_on_ble_evt(ble_evt_t const * p_ble_evt, + void * p_context) +{ + VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt); + VERIFY_PARAM_NOT_NULL_VOID(p_context); + VERIFY_MODULE_INITIALIZED_VOID(); + + ble_db_discovery_t * p_db_discovery = (ble_db_discovery_t *)p_context; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: + on_primary_srv_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt)); + break; + + case BLE_GATTC_EVT_CHAR_DISC_RSP: + on_characteristic_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt)); + break; + + case BLE_GATTC_EVT_DESC_DISC_RSP: + on_descriptor_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt)); + break; + + case BLE_GAP_EVT_DISCONNECTED: + on_disconnected(p_db_discovery, &(p_ble_evt->evt.gap_evt)); + break; + + default: + break; + } +} +#endif // NRF_MODULE_ENABLED(BLE_DB_DISCOVERY) diff --git a/components/ble/ble_db_discovery/ble_db_discovery.h b/components/ble/ble_db_discovery/ble_db_discovery.h new file mode 100644 index 0000000..3f65c0c --- /dev/null +++ b/components/ble/ble_db_discovery/ble_db_discovery.h @@ -0,0 +1,271 @@ +/** + * Copyright (c) 2013 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup ble_db_discovery Database Discovery + * @{ + * @ingroup ble_sdk_lib + * + * @brief Database discovery module. + * + * @details This module contains the APIs and types exposed by the DB Discovery module. These APIs + * and types can be used by the application to perform discovery of a service and its + * characteristics at the peer server. This module can also be used to discover the + * desired services in multiple remote devices. + * + * @warning The maximum number of characteristics per service that can be discovered by this module + * is determined by the number of characteristics in the service structure defined in + * db_disc_config.h. If the peer has more than the supported number of characteristics, then + * the first found will be discovered and any further characteristics will be ignored. Only the + * following descriptors will be searched for at the peer: Client Characteristic Configuration, + * Characteristic Extended Properties, Characteristic User Description, and Report Reference. + * + * @note Presently only one instance of a Primary Service can be discovered by this module. If + * there are multiple instances of the service at the peer, only the first instance + * of it at the peer is fetched and returned to the application. + * + * @note The application must propagate BLE stack events to this module by calling + * ble_db_discovery_on_ble_evt(). + * + */ + +#ifndef BLE_DB_DISCOVERY_H__ +#define BLE_DB_DISCOVERY_H__ + +#include +#include +#include "nrf_error.h" +#include "ble.h" +#include "ble_gattc.h" +#include "ble_gatt_db.h" +#include "nrf_ble_gq.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !(defined(__LINT__)) +/**@brief Macro for defining a ble_db_discovery instance. + * + * @param _name Name of the instance. + * @hideinitializer + */ +#define BLE_DB_DISCOVERY_DEF(_name) \ +static ble_db_discovery_t _name = {.discovery_in_progress = 0, \ + .conn_handle = BLE_CONN_HANDLE_INVALID}; \ +NRF_SDH_BLE_OBSERVER(_name ## _obs, \ + BLE_DB_DISC_BLE_OBSERVER_PRIO, \ + ble_db_discovery_on_ble_evt, &_name) + + +/** @brief Macro for defining multiple ble_db_discovery instances. + * + * @param _name Name of the array of instances. + * @param _cnt Number of instances to define. + */ +#define BLE_DB_DISCOVERY_ARRAY_DEF(_name, _cnt) \ +static ble_db_discovery_t _name[_cnt] = {MACRO_REPEAT(_cnt, DB_INIT)}; \ + \ +NRF_SDH_BLE_OBSERVERS(_name ## _obs, \ + BLE_DB_DISC_BLE_OBSERVER_PRIO, \ + ble_db_discovery_on_ble_evt, &_name, _cnt) + +#if !(defined(DOXYGEN)) +#define DB_INIT() \ +{ \ + .discovery_in_progress = 0, \ + .conn_handle = BLE_CONN_HANDLE_INVALID, \ +}, +#endif + +#else // __LINT__ +/* Swallow semicolons */ +/*lint -save -esym(528, *) -esym(529, *) : Symbol not referenced. */ +#define BLE_DB_DISCOVERY_ARRAY_DEF(A, B) static ble_db_discovery_t A[B] +#define BLE_DB_DISCOVERY_DEF(A) static ble_db_discovery_t A +/*lint -restore */ +#endif //!(defined(__LINT__)) + +#define BLE_DB_DISCOVERY_MAX_SRV 6 /**< Maximum number of services supported by this module. This also indicates the maximum number of users allowed to be registered to this module (one user per service). */ + + +/**@brief DB Discovery event type. */ +typedef enum +{ + BLE_DB_DISCOVERY_COMPLETE, /**< Event indicating that the discovery of one service is complete. */ + BLE_DB_DISCOVERY_ERROR, /**< Event indicating that an internal error has occurred in the DB Discovery module. This could typically be because of the SoftDevice API returning an error code during the DB discover.*/ + BLE_DB_DISCOVERY_SRV_NOT_FOUND, /**< Event indicating that the service was not found at the peer.*/ + BLE_DB_DISCOVERY_AVAILABLE /**< Event indicating that the DB discovery instance is available.*/ +} ble_db_discovery_evt_type_t; + +/**@brief Structure containing the event from the DB discovery module to the application. */ +typedef struct +{ + ble_db_discovery_evt_type_t evt_type; /**< Type of event. */ + uint16_t conn_handle; /**< Handle of the connection for which this event has occurred. */ + union + { + ble_gatt_db_srv_t discovered_db; /**< Structure containing the information about the GATT Database at the server. This will be filled when the event type is @ref BLE_DB_DISCOVERY_COMPLETE. The UUID field of this will be filled when the event type is @ref BLE_DB_DISCOVERY_SRV_NOT_FOUND. */ + void const * p_db_instance; /**< Pointer to DB discovery instance @ref ble_db_discovery_t, indicating availability to the new discovery process. This will be filled when the event type is @ref BLE_DB_DISCOVERY_AVAILABLE. */ + uint32_t err_code; /**< nRF Error code indicating the type of error which occurred in the DB Discovery module. This will be filled when the event type is @ref BLE_DB_DISCOVERY_ERROR. */ + } params; +} ble_db_discovery_evt_t; + +/**@brief DB Discovery event handler type. */ +typedef void (* ble_db_discovery_evt_handler_t)(ble_db_discovery_evt_t * p_evt); + +/**@brief Structure containing the pending event. */ +typedef struct +{ + ble_db_discovery_evt_t evt; /**< Pending event. */ + ble_db_discovery_evt_handler_t evt_handler; /**< Event handler which should be called to raise this event. */ +} ble_db_discovery_user_evt_t; + +/**@brief Structure for holding the information related to the GATT database at the server. + * + * @details This module identifies a remote database. Use one instance of this structure per + * connection. + * + * @warning This structure must be zero-initialized. + */ +typedef struct +{ + ble_gatt_db_srv_t services[BLE_DB_DISCOVERY_MAX_SRV]; /**< Information related to the current service being discovered. This is intended for internal use during service discovery.*/ + uint8_t srv_count; /**< Number of services at the peer's GATT database.*/ + uint8_t curr_char_ind; /**< Index of the current characteristic being discovered. This is intended for internal use during service discovery.*/ + uint8_t curr_srv_ind; /**< Index of the current service being discovered. This is intended for internal use during service discovery.*/ + uint8_t discoveries_count; /**< Number of service discoveries made, both successful and unsuccessful. */ + bool discovery_in_progress; /**< Variable to indicate whether there is a service discovery in progress. */ + uint16_t conn_handle; /**< Connection handle on which the discovery is started. */ + uint32_t pending_usr_evt_index; /**< The index to the pending user event array, pointing to the last added pending user event. */ + ble_db_discovery_user_evt_t pending_usr_evts[BLE_DB_DISCOVERY_MAX_SRV]; /**< Whenever a discovery related event is to be raised to a user module, it is stored in this array first. When all expected services have been discovered, all pending events are sent to the corresponding user modules. */ +} ble_db_discovery_t; + +/**@brief DB discovery module initialization struct. */ +typedef struct +{ + ble_db_discovery_evt_handler_t evt_handler; /**< Event handler to be called by the DB Discovery module. */ + nrf_ble_gq_t * p_gatt_queue; /**< Pointer to BLE GATT Queue instance. */ +} ble_db_discovery_init_t; + + +/**@brief Function for initializing the DB Discovery module. + * + * @param[in] p_db_init Pointer to DB discovery initialization structure. + * + * @retval NRF_SUCCESS On successful initialization. + * @retval NRF_ERROR_NULL If the initialization structure was NULL or + * the structure content is empty. + */ +uint32_t ble_db_discovery_init(ble_db_discovery_init_t * p_db_init); + + +/**@brief Function for closing the DB Discovery module. + * + * @details This function will clear up any internal variables and states maintained by the + * module. To re-use the module after calling this function, the function @ref + * ble_db_discovery_init must be called again. When using more than one DB Discovery + * instance, this function should be called for each instance. + * + * @param[out] p_db_discovery Pointer to the DB discovery structure. + * + * @retval NRF_SUCCESS Operation success. + */ +uint32_t ble_db_discovery_close(ble_db_discovery_t * const p_db_discovery); + + +/**@brief Function for registering with the DB Discovery module. + * + * @details The application can use this function to inform which service it is interested in + * discovering at the server. + * + * @param[in] p_uuid Pointer to the UUID of the service to be discovered at the server. + * + * @note The total number of services that can be discovered by this module is @ref + * BLE_DB_DISCOVERY_MAX_SRV. This effectively means that the maximum number of + * registrations possible is equal to the @ref BLE_DB_DISCOVERY_MAX_SRV. + * + * @retval NRF_SUCCESS Operation success. + * @retval NRF_ERROR_NULL When a NULL pointer is passed as input. + * @retval NRF_ERROR_INVALID_STATE If this function is called without calling the + * @ref ble_db_discovery_init. + * @retval NRF_ERROR_NO_MEM The maximum number of registrations allowed by this module + * has been reached. + */ +uint32_t ble_db_discovery_evt_register(const ble_uuid_t * const p_uuid); + + +/**@brief Function for starting the discovery of the GATT database at the server. + * + * @param[out] p_db_discovery Pointer to the DB Discovery structure. + * @param[in] conn_handle The handle of the connection for which the discovery should be + * started. + * + * @retval NRF_SUCCESS Operation success. + * @retval NRF_ERROR_NULL When a NULL pointer is passed as input. + * @retval NRF_ERROR_INVALID_STATE If this function is called without calling the + * @ref ble_db_discovery_init, or without calling + * @ref ble_db_discovery_evt_register. + * @retval NRF_ERROR_BUSY If a discovery is already in progress using + * @p p_db_discovery. Use a different @ref ble_db_discovery_t + * structure, or wait for a DB Discovery event before retrying. + * @return This API propagates the error code returned by functions: + * @ref nrf_ble_gq_conn_handle_register and @ref nrf_ble_gq_item_add. + */ +uint32_t ble_db_discovery_start(ble_db_discovery_t * p_db_discovery, + uint16_t conn_handle); + + +/**@brief Function for handling the Application's BLE Stack events. + * + * @param[in] p_ble_evt Pointer to the BLE event received. + * @param[in,out] p_context Pointer to the DB Discovery structure. + */ +void ble_db_discovery_on_ble_evt(ble_evt_t const * p_ble_evt, + void * p_context); + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_DB_DISCOVERY_H__ + +/** @} */ diff --git a/components/ble/ble_link_ctx_manager/ble_link_ctx_manager.c b/components/ble/ble_link_ctx_manager/ble_link_ctx_manager.c new file mode 100644 index 0000000..cab5b39 --- /dev/null +++ b/components/ble/ble_link_ctx_manager/ble_link_ctx_manager.c @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "ble_link_ctx_manager.h" +#include "sdk_common.h" + + +ret_code_t blcm_link_ctx_get(blcm_link_ctx_storage_t const * const p_link_ctx_storage, + uint16_t const conn_handle, + void ** const pp_ctx_data) +{ + uint8_t conn_id; + + if (pp_ctx_data == NULL) + { + return NRF_ERROR_NULL; + } + else + { + *pp_ctx_data = NULL; + } + + VERIFY_PARAM_NOT_NULL(p_link_ctx_storage); + VERIFY_PARAM_NOT_NULL(p_link_ctx_storage->p_ctx_data_pool); + VERIFY_TRUE((p_link_ctx_storage->link_ctx_size % BYTES_PER_WORD) == 0, NRF_ERROR_INVALID_PARAM); + + conn_id = ble_conn_state_conn_idx(conn_handle); + + if (conn_id == BLE_CONN_STATE_MAX_CONNECTIONS) + { + return NRF_ERROR_NOT_FOUND; + } + + if (conn_id >= p_link_ctx_storage->max_links_cnt) + { + return NRF_ERROR_NO_MEM; + } + + *pp_ctx_data = (void *) ((uint8_t *) p_link_ctx_storage->p_ctx_data_pool + + conn_id * p_link_ctx_storage->link_ctx_size); + return NRF_SUCCESS; +} + diff --git a/components/ble/ble_link_ctx_manager/ble_link_ctx_manager.h b/components/ble/ble_link_ctx_manager/ble_link_ctx_manager.h new file mode 100644 index 0000000..9798713 --- /dev/null +++ b/components/ble/ble_link_ctx_manager/ble_link_ctx_manager.h @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup ble_link_ctx_manager BLE Link Context Manager + * @{ + * @ingroup ble_sdk_lib + * @brief Storage for link-related data. + * + * @details BLE Link Context Manager can be used as a simple storage for link-related data. + * Each link context data is uniquely identified within the storage by its connection + * handle and can be retrieved from it by using this handle. + * + */ +#ifndef BLE_LINK_CTX_MANAGER_H__ +#define BLE_LINK_CTX_MANAGER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "ble_conn_state.h" +#include "sdk_errors.h" + + +/**@brief Macro for defining a blcm_link_ctx_storage instance. + * + * @param[in] _name Name of the instance. + * @param[in] _max_clients Maximum number of clients connected at a time. + * @param[in] _link_ctx_size Context size in bytes for a single link. + */ +#define BLE_LINK_CTX_MANAGER_DEF(_name, _max_clients, _link_ctx_size) \ + STATIC_ASSERT((_max_clients) <= BLE_CONN_STATE_MAX_CONNECTIONS); \ + static uint32_t CONCAT_2(_name, _ctx_data_pool)[(_max_clients)*BYTES_TO_WORDS(_link_ctx_size)]; \ + static blcm_link_ctx_storage_t _name = \ + { \ + .p_ctx_data_pool = CONCAT_2(_name, _ctx_data_pool), \ + .max_links_cnt = (_max_clients), \ + .link_ctx_size = sizeof(CONCAT_2(_name, _ctx_data_pool))/(_max_clients) \ + } + + +/** + * @brief Type of description that is used for registry of all current connections. + */ +typedef struct +{ + void * const p_ctx_data_pool; /**< Pointer to links context memory pool. */ + uint8_t const max_links_cnt; /**< Maximum number of concurrent links. */ + uint16_t const link_ctx_size; /**< Context size in bytes for a single link (word-aligned). */ +} blcm_link_ctx_storage_t; + + +/** + * @brief Function for getting the link context from the link registry. + * + * This function finds the link context in the registry. The link to find is identified by the + * connection handle within the registry. + * + * The context is preserved for the lifetime of the connection. When a new connection occurs, the + * value of its context is undefined, and should be initialized. + * + * @param[in] p_link_ctx_storage Pointer to the link storage descriptor. + * @param[in] conn_handle Connection whose context to find. + * @param[out] pp_ctx_data Pointer to data with context for the connection. + * + * @retval NRF_ERROR_NULL If \p p_link_ctx_storage is NULL or contains a NULL pointer, or if + * \p pp_ctx_data is NULL. + * @retval NRF_ERROR_INVALID_PARAM If \p p_link_ctx_storage::link_ctx_size is not multiple of word + * size. + * @retval NRF_ERROR_NOT_FOUND If \p conn_handle does not refer to an active or recently + * disconnected link. + * @retval NRF_ERROR_NO_MEM If there is not enough memory to store context for the given + * connection handle. This can happen if the number of links is + * greater than \p p_link_ctx_storage::max_links_cnt. + * @retval NRF_SUCCESS If the operation was successful. + */ +ret_code_t blcm_link_ctx_get(blcm_link_ctx_storage_t const * const p_link_ctx_storage, + uint16_t const conn_handle, + void ** const pp_ctx_data); + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_LINK_CTX_MANAGER_H__ + +/** @} */ diff --git a/components/ble/ble_radio_notification/ble_radio_notification.c b/components/ble/ble_radio_notification/ble_radio_notification.c new file mode 100644 index 0000000..c9187fb --- /dev/null +++ b/components/ble/ble_radio_notification/ble_radio_notification.c @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "ble_radio_notification.h" +#include "nrf_nvic.h" +#include + + +static bool m_radio_active = false; /**< Current radio state. */ +static ble_radio_notification_evt_handler_t m_evt_handler = NULL; /**< Application event handler for handling Radio Notification events. */ + + +void SWI1_IRQHandler(void) +{ + m_radio_active = !m_radio_active; + if (m_evt_handler != NULL) + { + m_evt_handler(m_radio_active); + } +} + + +uint32_t ble_radio_notification_init(uint32_t irq_priority, + uint8_t distance, + ble_radio_notification_evt_handler_t evt_handler) +{ + uint32_t err_code; + + m_evt_handler = evt_handler; + + // Initialize Radio Notification software interrupt + err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = sd_nvic_SetPriority(SWI1_IRQn, irq_priority); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = sd_nvic_EnableIRQ(SWI1_IRQn); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + // Configure the event + return sd_radio_notification_cfg_set(NRF_RADIO_NOTIFICATION_TYPE_INT_ON_BOTH, distance); +} diff --git a/components/ble/ble_radio_notification/ble_radio_notification.h b/components/ble/ble_radio_notification/ble_radio_notification.h new file mode 100644 index 0000000..7d7f0af --- /dev/null +++ b/components/ble/ble_radio_notification/ble_radio_notification.h @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup ble_radio_notification Radio Notification Event Handler + * @{ + * @ingroup ble_sdk_lib + * @brief Module for propagating Radio Notification events to the application. + */ + +#ifndef BLE_RADIO_NOTIFICATION_H__ +#define BLE_RADIO_NOTIFICATION_H__ + +#include +#include +#include "nrf_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Application radio notification event handler type. */ +typedef void (*ble_radio_notification_evt_handler_t) (bool radio_active); + +/**@brief Function for initializing the Radio Notification module. + * + * @param[in] irq_priority Interrupt priority for the Radio Notification interrupt handler. + * @param[in] distance The time from an Active event until the radio is activated. + * @param[in] evt_handler Handler to be executed when a radio notification event has been + * received. + * + * @return NRF_SUCCESS on successful initialization, otherwise an error code. + */ +uint32_t ble_radio_notification_init(uint32_t irq_priority, + uint8_t distance, + ble_radio_notification_evt_handler_t evt_handler); + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_RADIO_NOTIFICATION_H__ + +/** @} */ diff --git a/components/ble/ble_services/ble_dfu/ble_dfu.c b/components/ble/ble_services/ble_dfu/ble_dfu.c new file mode 100644 index 0000000..e7c52a4 --- /dev/null +++ b/components/ble/ble_services/ble_dfu/ble_dfu.c @@ -0,0 +1,323 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* Attention! + * To maintain compliance with Nordic Semiconductor ASA's Bluetooth profile + * qualification listings, this section of source code must not be modified. + */ + +#include "ble_dfu.h" +#include +#include "ble_hci.h" +#include "sdk_macros.h" +#include "ble_srv_common.h" +#include "nrf_nvic.h" +#include "nrf_sdm.h" +#include "nrf_soc.h" +#include "nrf_log.h" +#include "nrf_dfu_ble_svci_bond_sharing.h" +#include "nrf_bootloader_info.h" +#include "nrf_svci_async_function.h" +#include "nrf_pwr_mgmt.h" +#include "peer_manager.h" +#include "gatts_cache_manager.h" +#include "peer_id.h" + +#define MAX_CTRL_POINT_RESP_PARAM_LEN 3 /**< Max length of the responses. */ + +#define BLE_DFU_SERVICE_UUID 0xFE59 /**< The 16-bit UUID of the Secure DFU Service. */ + +static ble_dfu_buttonless_t m_dfu; /**< Structure holding information about the Buttonless Secure DFU Service. */ + +NRF_SDH_BLE_OBSERVER(m_dfus_obs, BLE_DFU_BLE_OBSERVER_PRIO, ble_dfu_buttonless_on_ble_evt, &m_dfu); + + +/**@brief Function that is called if no event handler is provided. + */ +static void dummy_evt_handler(ble_dfu_buttonless_evt_type_t evt) +{ + NRF_LOG_DEBUG("Dummy event handler received event 0x%x", evt); +} + + +/**@brief Function for handling write events to the Buttonless Secure DFU Service Service Control Point characteristic. + * + * @param[in] p_evt_write Write event received from the BLE stack. + */ +static void on_ctrlpt_write(ble_gatts_evt_write_t const * p_evt_write) +{ + uint32_t err_code; + + ble_gatts_rw_authorize_reply_params_t write_authorize_reply; + memset(&write_authorize_reply, 0, sizeof(write_authorize_reply)); + + write_authorize_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; + + uint8_t cccd_val[2]; + ble_gatts_value_t value = {.p_value = cccd_val, .len = 2, .offset = 0}; + err_code = sd_ble_gatts_value_get(m_dfu.conn_handle, m_dfu.control_point_char.cccd_handle, &value); + if (err_code == NRF_SUCCESS && ble_srv_is_indication_enabled(cccd_val)) + { + write_authorize_reply.params.write.update = 1; + write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + } + else + { + write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR; + } + + // Authorize the write request + do { + err_code = sd_ble_gatts_rw_authorize_reply(m_dfu.conn_handle, &write_authorize_reply); + } while (err_code == NRF_ERROR_BUSY); + + + if (write_authorize_reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS) + { + return; + } + + // Forward the write event to the Buttonless DFU module. + ble_dfu_buttonless_on_ctrl_pt_write(p_evt_write); +} + + +/**@brief Write authorization request event handler. + * + * @details The write authorization request event handler is called when writing to the control point. + * + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_rw_authorize_req(ble_evt_t const * p_ble_evt) +{ + if (p_ble_evt->evt.gatts_evt.conn_handle != m_dfu.conn_handle) + { + return; + } + + const ble_gatts_evt_rw_authorize_request_t * p_auth_req = + &p_ble_evt->evt.gatts_evt.params.authorize_request; + + if ( + (p_auth_req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) && + (p_auth_req->request.write.handle == m_dfu.control_point_char.value_handle) && + (p_auth_req->request.write.op != BLE_GATTS_OP_PREP_WRITE_REQ) && + (p_auth_req->request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) && + (p_auth_req->request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL) + ) + { + on_ctrlpt_write(&p_auth_req->request.write); + } +} + + +/**@brief Connect event handler. + * + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_connect(ble_evt_t const * p_ble_evt) +{ + m_dfu.conn_handle = p_ble_evt->evt.gap_evt.conn_handle; +} + + +/**@brief Disconnect event handler. + * + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_disconnect(ble_evt_t const * p_ble_evt) +{ + if (m_dfu.conn_handle != p_ble_evt->evt.gap_evt.conn_handle) + { + return; + } + + m_dfu.conn_handle = BLE_CONN_HANDLE_INVALID; +} + + +/**@brief Function for handling the HVC events. + * + * @details Handles HVC events from the BLE stack. + * + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_hvc(ble_evt_t const * p_ble_evt) +{ + uint32_t err_code; + ble_gatts_evt_hvc_t const * p_hvc = &p_ble_evt->evt.gatts_evt.params.hvc; + + if (p_hvc->handle == m_dfu.control_point_char.value_handle) + { + // Enter bootloader if we were waiting for reset after hvc indication confimation. + if (m_dfu.is_waiting_for_reset) + { + err_code = ble_dfu_buttonless_bootloader_start_prepare(); + if (err_code != NRF_SUCCESS) + { + m_dfu.evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED); + } + } + } +} + + +void ble_dfu_buttonless_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) +{ + VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt); + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + on_connect(p_ble_evt); + break; + + case BLE_GAP_EVT_DISCONNECTED: + on_disconnect(p_ble_evt); + break; + + case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: + on_rw_authorize_req(p_ble_evt); + break; + + case BLE_GATTS_EVT_HVC: + on_hvc(p_ble_evt); + break; + + default: + // no implementation + break; + } +} + + +uint32_t ble_dfu_buttonless_resp_send(ble_dfu_buttonless_op_code_t op_code, ble_dfu_buttonless_rsp_code_t rsp_code) +{ + // Send indication + uint32_t err_code; + const uint16_t len = MAX_CTRL_POINT_RESP_PARAM_LEN; + uint16_t hvx_len; + uint8_t hvx_data[MAX_CTRL_POINT_RESP_PARAM_LEN]; + ble_gatts_hvx_params_t hvx_params; + + memset(&hvx_params, 0, sizeof(hvx_params)); + + hvx_len = len; + hvx_data[0] = DFU_OP_RESPONSE_CODE; + hvx_data[1] = (uint8_t)op_code; + hvx_data[2] = (uint8_t)rsp_code; + + hvx_params.handle = m_dfu.control_point_char.value_handle; + hvx_params.type = BLE_GATT_HVX_INDICATION; + hvx_params.offset = 0; + hvx_params.p_len = &hvx_len; + hvx_params.p_data = hvx_data; + + err_code = sd_ble_gatts_hvx(m_dfu.conn_handle, &hvx_params); + if ((err_code == NRF_SUCCESS) && (hvx_len != len)) + { + err_code = NRF_ERROR_DATA_SIZE; + } + + return err_code; +} + + +uint32_t ble_dfu_buttonless_bootloader_start_finalize(void) +{ + uint32_t err_code; + + NRF_LOG_DEBUG("In ble_dfu_buttonless_bootloader_start_finalize\r\n"); + + err_code = sd_power_gpregret_clr(0, 0xffffffff); + VERIFY_SUCCESS(err_code); + + err_code = sd_power_gpregret_set(0, BOOTLOADER_DFU_START); + VERIFY_SUCCESS(err_code); + + // Indicate that the Secure DFU bootloader will be entered + m_dfu.evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER); + + // Signal that DFU mode is to be enter to the power management module + nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU); + + return NRF_SUCCESS; +} + + +uint32_t ble_dfu_buttonless_init(const ble_dfu_buttonless_init_t * p_dfu_init) +{ + uint32_t err_code; + ble_uuid_t service_uuid; + ble_uuid128_t nordic_base_uuid = BLE_NORDIC_VENDOR_BASE_UUID; + + VERIFY_PARAM_NOT_NULL(p_dfu_init); + + // Initialize the service structure. + m_dfu.conn_handle = BLE_CONN_HANDLE_INVALID; + m_dfu.evt_handler = p_dfu_init->evt_handler; + m_dfu.is_waiting_for_reset = false; + + if (m_dfu.evt_handler == NULL) + { + m_dfu.evt_handler = dummy_evt_handler; + } + + err_code = ble_dfu_buttonless_backend_init(&m_dfu); + VERIFY_SUCCESS(err_code); + + BLE_UUID_BLE_ASSIGN(service_uuid, BLE_DFU_SERVICE_UUID); + + // Add the DFU service declaration. + err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, + &service_uuid, + &(m_dfu.service_handle)); + + VERIFY_SUCCESS(err_code); + + // Add vendor specific base UUID to use with the Buttonless DFU characteristic. + err_code = sd_ble_uuid_vs_add(&nordic_base_uuid, &m_dfu.uuid_type); + VERIFY_SUCCESS(err_code); + + // Add the Buttonless DFU Characteristic (with bonds/without bonds). + err_code = ble_dfu_buttonless_char_add(&m_dfu); + VERIFY_SUCCESS(err_code); + + return NRF_SUCCESS; +} diff --git a/components/ble/ble_services/ble_dfu/ble_dfu.h b/components/ble/ble_services/ble_dfu/ble_dfu.h new file mode 100644 index 0000000..0a8f3d0 --- /dev/null +++ b/components/ble/ble_services/ble_dfu/ble_dfu.h @@ -0,0 +1,249 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup ble_dfu Buttonless DFU Service + * @{ + * @ingroup ble_sdk_srv + * @brief Buttonless DFU Service module. + * + * @details This module implements a proprietary Buttonless Secure DFU Service. The service can + * be configured to support bonds or not. The bond support configuration must correspond to the + * requirement of Secure DFU bootloader. + * + * @note Attention! + * To maintain compliance with Nordic Semiconductor ASA Bluetooth profile + * qualification listings, this section of source code must not be modified. + */ + +#ifndef BLE_DFU_H__ +#define BLE_DFU_H__ + +#include +#include "ble_srv_common.h" +#include "nrf_sdh_ble.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief SoC observer priority. + * @details Priority of this module's SoC event handler. + */ +#define BLE_DFU_SOC_OBSERVER_PRIO 1 + +#define BLE_DFU_BUTTONLESS_CHAR_UUID (0x0003) /**< Value combined with vendor-specific base to create Unbonded Buttonless characteristic UUID. */ +#define BLE_DFU_BUTTONLESS_BONDED_CHAR_UUID (0x0004) /**< Value combined with vendor-specific base to create Bonded Buttonless characteristic UUID. */ + + +/**@brief Nordic vendor-specific base UUID. + */ +#define BLE_NORDIC_VENDOR_BASE_UUID \ +{{ \ + 0x50, 0xEA, 0xDA, 0x30, 0x88, 0x83, 0xB8, 0x9F, \ + 0x60, 0x4F, 0x15, 0xF3, 0x00, 0x00, 0xC9, 0x8E \ +}} + + +/**@brief Nordic Buttonless DFU Service event type . + */ +typedef enum +{ + BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE, /**< Event indicating that the device is preparing to enter bootloader.*/ + BLE_DFU_EVT_BOOTLOADER_ENTER, /**< Event indicating that the bootloader will be entered after return of this event.*/ + BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED, /**< Failure to enter bootloader mode.*/ + BLE_DFU_EVT_RESPONSE_SEND_ERROR, /**< Failure to send response.*/ +} ble_dfu_buttonless_evt_type_t; + + +/**@brief Nordic Buttonless DFU Service event handler type. + */ +typedef void (*ble_dfu_buttonless_evt_handler_t) (ble_dfu_buttonless_evt_type_t p_evt); +/**@brief Enumeration of Bootloader DFU response codes. + */ +typedef enum +{ + DFU_RSP_INVALID = 0x00, /**< Invalid op code. */ + DFU_RSP_SUCCESS = 0x01, /**< Success. */ + DFU_RSP_OP_CODE_NOT_SUPPORTED = 0x02, /**< Op code not supported. */ + DFU_RSP_OPERATION_FAILED = 0x04, /**< Operation failed. */ + DFU_RSP_ADV_NAME_INVALID = 0x05, /**< Requested advertisement name is too short or too long. */ + DFU_RSP_BUSY = 0x06, /**< Ongoing async operation. */ + DFU_RSP_NOT_BONDED = 0x07, /**< Buttonless unavailable due to device not bonded. */ +} ble_dfu_buttonless_rsp_code_t; + + +/**@brief Enumeration of Bootloader DFU Operation codes. + */ +typedef enum +{ + DFU_OP_RESERVED = 0x00, /**< Reserved for future use. */ + DFU_OP_ENTER_BOOTLOADER = 0x01, /**< Enter bootloader. */ + DFU_OP_SET_ADV_NAME = 0x02, /**< Set advertisement name to use in DFU mode. */ + DFU_OP_RESPONSE_CODE = 0x20 /**< Response code. */ +} ble_dfu_buttonless_op_code_t; + + +/**@brief Type holding memory used by Secure DFU Buttonless Service. + */ +typedef struct +{ + uint8_t uuid_type; /**< UUID type for DFU UUID. */ + uint16_t service_handle; /**< Service Handle of DFU (as provided by the SoftDevice). */ + uint16_t conn_handle; /**< Connection handle for the current peer. */ + ble_gatts_char_handles_t control_point_char; /**< Handles related to the DFU Control Point characteristic. */ + uint32_t peers_count; /**< Counter to see how many persistently stored peers must be updated for Service Changed indication. This value will be counted down when comparing write requests. */ + ble_dfu_buttonless_evt_handler_t evt_handler; /**< Event handler that is called upon Buttonless DFU events. See @ref ble_dfu_buttonless_evt_type_t. */ + bool is_waiting_for_reset; /**< Flag indicating that the device will enter bootloader. */ + bool is_waiting_for_svci; /**< Flag indicating that the device is waiting for async SVCI operation */ +} ble_dfu_buttonless_t; + + +/**@brief Type used to initialize the Secure DFU Buttonless Service. + */ +typedef struct +{ + ble_dfu_buttonless_evt_handler_t evt_handler; /**< Bootloader event handler. */ +} ble_dfu_buttonless_init_t; + + +/**@brief Function for initializing the Device Firmware Update module. + * + * @param[in] p_dfu_init Structure containing the values of characteristics needed by the + * service. + * @retval NRF_SUCCESS on successful initialization of the service. + */ +uint32_t ble_dfu_buttonless_init(const ble_dfu_buttonless_init_t * p_dfu_init); + + +/**@brief Function for initializing the async SVCI interface. + * + * @warning Ensure that no interrupts are triggered when calling this functions as + * interrupts and exceptions are forwarded to the bootloader for the period + * of the call and may be lost. + * + * @details This configures the async interface for calling to the + * bootloader through SVCI interface. + * + * @retval NRF_SUCCESS on success, otherwise an error code. + */ +uint32_t ble_dfu_buttonless_async_svci_init(void); + + +/**@brief Function to initialize the backend Secure DFU Buttonless service which is either + * supports bonds or not. + * + * @note Do not call this function directly. It is called internally by @ref ble_dfu_buttonless_init. + * + * @param[in] p_dfu Nordic DFU Service structure. + * + * @return NRF_SUCCESS On sucessfully initializing, otherwise an error code. + */ +uint32_t ble_dfu_buttonless_backend_init(ble_dfu_buttonless_t * p_dfu); + + + +/**@brief Function for adding the buttonless characteristic. + * + * @note This will be implemented differently on bonded/unbonded Buttonless DFU service. + * + * @param[in] p_dfu Nordic DFU Service structure. + * + * @return NRF_SUCCESS on success, otherwise an error code. + */ +uint32_t ble_dfu_buttonless_char_add(ble_dfu_buttonless_t * p_dfu); + + +/**@brief Function for sending a response back to the client. + * + * @param[in] op_code Operation code to send the response for. + * @param[in] rsp_code Response code for the operation. + * + * @retval NRF_SUCCESS on success, otherwise an error code. + */ +uint32_t ble_dfu_buttonless_resp_send(ble_dfu_buttonless_op_code_t op_code, ble_dfu_buttonless_rsp_code_t rsp_code); + + +/**@brief Function for handling the application's BLE stack events. + * + * @details Handles all events from the BLE stack of interest to the DFU buttonless service. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context BLE context structure. + */ +void ble_dfu_buttonless_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); + + +/**@brief Function for handling control point write requests. + * + * @details Handles write requests to the control point in + * DFU with bonds or without bonds. + * + * @param[in] p_evt_write GATTS write event. + */ +void ble_dfu_buttonless_on_ctrl_pt_write(ble_gatts_evt_write_t const * p_evt_write); + + +/**@brief Function for preparing to enter the bootloader. + * + * @warning This function is called directly. (It is called internally). + * + * @retval Any error code from calling @ref sd_ble_gap_disconnect. + */ +uint32_t ble_dfu_buttonless_bootloader_start_prepare(void); + + +/**@brief Function for finalizing entering the bootloader. + * + * @warning This function is not to be called. (It is called internally). + * + * @retval NRF_SUCCESS Finalize was started correctly. + */ +uint32_t ble_dfu_buttonless_bootloader_start_finalize(void); + +#ifdef __cplusplus +} +#endif + +#endif // BLE_DIS_H__ + +/** @} */ diff --git a/components/ble/ble_services/ble_dfu/ble_dfu_bonded.c b/components/ble/ble_services/ble_dfu/ble_dfu_bonded.c new file mode 100644 index 0000000..44d0663 --- /dev/null +++ b/components/ble/ble_services/ble_dfu/ble_dfu_bonded.c @@ -0,0 +1,367 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include "nrf_dfu_ble_svci_bond_sharing.h" +#include "nordic_common.h" +#include "nrf_error.h" +#include "ble_dfu.h" +#include "nrf_log.h" +#include "peer_manager.h" +#include "gatts_cache_manager.h" +#include "peer_id.h" +#include "nrf_sdh_soc.h" +#include "nrf_strerror.h" + +#if (NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS) + + +void ble_dfu_buttonless_on_sys_evt(uint32_t, void * ); +uint32_t nrf_dfu_svci_vector_table_set(void); +uint32_t nrf_dfu_svci_vector_table_unset(void); + +/**@brief Define function for async interface to set peer data. */ +NRF_SVCI_ASYNC_FUNC_DEFINE(NRF_DFU_SVCI_SET_PEER_DATA, nrf_dfu_set_peer_data, nrf_dfu_peer_data_t); + +// Register SoC observer for the Buttonless Secure DFU service +NRF_SDH_SOC_OBSERVER(m_dfu_buttonless_soc_obs, BLE_DFU_SOC_OBSERVER_PRIO, ble_dfu_buttonless_on_sys_evt, NULL); + +ble_dfu_buttonless_t * mp_dfu; +static nrf_dfu_peer_data_t m_peer_data; + + +/**@brief Function for handling Peer Manager events. + * + * @param[in] p_evt Peer Manager event. + */ +static void pm_evt_handler(pm_evt_t const * p_evt) +{ + uint32_t ret; + + if (mp_dfu == NULL) + { + return; + } + + // Only handle this when we are waiting to reset into DFU mode + if (!mp_dfu->is_waiting_for_reset) + { + return; + } + + switch(p_evt->evt_id) + { + case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: + if (p_evt->params.peer_data_update_succeeded.data_id == PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING) + { + mp_dfu->peers_count--; + NRF_LOG_DEBUG("Updating Service Changed indication for peers, %d left", mp_dfu->peers_count); + if (mp_dfu->peers_count == 0) + { + NRF_LOG_DEBUG("Finished updating Service Changed indication for peers"); + // We have updated Service Changed Indication for all devices. + ret = ble_dfu_buttonless_bootloader_start_finalize(); + if (ret != NRF_SUCCESS) + { + mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED); + } + } + } + break; + + case PM_EVT_PEER_DATA_UPDATE_FAILED: + // Failure to update data. Service Changed cannot be sent but DFU mode is still possible + ret = ble_dfu_buttonless_bootloader_start_finalize(); + if (ret != NRF_SUCCESS) + { + mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED); + } + break; + + default: + break; + } +} + + +static uint32_t retrieve_peer_data(void) +{ + ret_code_t ret; + pm_peer_data_bonding_t bonding_data = {0}; + pm_peer_id_t peer_id; + + ret = pm_peer_id_get(mp_dfu->conn_handle, &peer_id); + VERIFY_SUCCESS(ret); + + if (peer_id == PM_PEER_ID_INVALID) + { + return NRF_ERROR_FORBIDDEN; + } + + ret = pm_peer_data_bonding_load(peer_id, &bonding_data); + VERIFY_SUCCESS(ret); + + memcpy(&m_peer_data.ble_id, &bonding_data.peer_ble_id, sizeof(ble_gap_id_key_t)); + memcpy(&m_peer_data.enc_key, &bonding_data.own_ltk, sizeof(ble_gap_enc_key_t)); + + uint16_t len = SYSTEM_SERVICE_ATT_SIZE; + ret = sd_ble_gatts_sys_attr_get(mp_dfu->conn_handle, + m_peer_data.sys_serv_attr, + &len, + BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS); + + NRF_LOG_DEBUG("system attribute table len: %d", len); + + return ret; +} + + +/**@brief Function for entering the bootloader. + * + * @details This starts forwarding peer data to the Secure DFU bootloader. + */ +static uint32_t enter_bootloader(void) +{ + uint32_t ret; + + NRF_LOG_INFO("Writing peer data to the bootloader..."); + + if (mp_dfu->is_waiting_for_svci) + { + return ble_dfu_buttonless_resp_send(DFU_OP_ENTER_BOOTLOADER, DFU_RSP_BUSY); + } + + // If retrieve_peer_data returns NRF_ERROR_FORBIDDEN, then the device was not bonded. + ret = retrieve_peer_data(); + VERIFY_SUCCESS(ret); + + ret = nrf_dfu_set_peer_data(&m_peer_data); + if (ret == NRF_SUCCESS) + { + // The request was accepted. Waiting for sys events to progress. + mp_dfu->is_waiting_for_svci = true; + } + else if (ret == NRF_ERROR_FORBIDDEN) + { + NRF_LOG_ERROR("The bootloader has write protected its settings page. This prohibits setting the peer data. "\ + "The bootloader must be compiled with NRF_BL_SETTINGS_PAGE_PROTECT=0 to allow setting the peer data."); + } + + return ret; +} + + +uint32_t ble_dfu_buttonless_backend_init(ble_dfu_buttonless_t * p_dfu) +{ + VERIFY_PARAM_NOT_NULL(p_dfu); + + // Set the memory used by the backend. + mp_dfu = p_dfu; + + // Initialize the Peer manager handler. + return pm_register(pm_evt_handler); +} + + +uint32_t ble_dfu_buttonless_async_svci_init(void) +{ + uint32_t ret; + + // Set the vector table base address to the bootloader. + ret = nrf_dfu_svci_vector_table_set(); + NRF_LOG_DEBUG("nrf_dfu_svci_vector_table_set() -> %s", + (ret == NRF_SUCCESS) ? "success" : nrf_strerror_get(ret)); + VERIFY_SUCCESS(ret); + + // Initialize the asynchronous SuperVisor interface to set peer data in Secure DFU bootloader. + ret = nrf_dfu_set_peer_data_init(); + NRF_LOG_DEBUG("nrf_dfu_set_peer_data_init() -> %s", + (ret == NRF_SUCCESS) ? "success" : nrf_strerror_get(ret)); + VERIFY_SUCCESS(ret); + + // Set the vector table base address back to main application. + ret = nrf_dfu_svci_vector_table_unset(); + NRF_LOG_DEBUG("nrf_dfu_svci_vector_table_unset() -> %s", + (ret == NRF_SUCCESS) ? "success" : nrf_strerror_get(ret)); + + return ret; +} + + +void ble_dfu_buttonless_on_sys_evt(uint32_t sys_evt, void * p_context) +{ + uint32_t ret; + + if (!nrf_dfu_set_peer_data_is_initialized()) + { + return; + } + + ret = nrf_dfu_set_peer_data_on_sys_evt(sys_evt); + if (ret == NRF_ERROR_INVALID_STATE) + { + // The system event is not from an operation started by buttonless DFU. + // No action is taken, and nothing is reported. + } + else if (ret == NRF_SUCCESS) + { + // Peer data was successfully forwarded to the Secure DFU bootloader. + // Set the flag indicating that we are waiting for indication response + // to activate the reset. + mp_dfu->is_waiting_for_reset = true; + mp_dfu->is_waiting_for_svci = false; + + // Report back the positive response + ret = ble_dfu_buttonless_resp_send(DFU_OP_ENTER_BOOTLOADER, DFU_RSP_SUCCESS); + if (ret != NRF_SUCCESS) + { + mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR); + mp_dfu->is_waiting_for_reset = false; + } + } + else + { + // Failed to set peer data. Report this. + mp_dfu->is_waiting_for_reset = false; + mp_dfu->is_waiting_for_svci = false; + ret = ble_dfu_buttonless_resp_send(DFU_OP_ENTER_BOOTLOADER, DFU_RSP_BUSY); + + // Report the failure to send the response to the client + if (ret != NRF_SUCCESS) + { + mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR); + } + + // Report the failure to enter DFU mode + mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED); + } +} + + +uint32_t ble_dfu_buttonless_char_add(ble_dfu_buttonless_t * p_dfu) +{ + ble_add_char_params_t add_char_params; + + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = BLE_DFU_BUTTONLESS_BONDED_CHAR_UUID; + add_char_params.uuid_type = p_dfu->uuid_type; + add_char_params.char_props.indicate = 1; + add_char_params.char_props.write = 1; + add_char_params.is_defered_write = true; + add_char_params.is_var_len = true; + add_char_params.max_len = BLE_GATT_ATT_MTU_DEFAULT; + + add_char_params.cccd_write_access = SEC_JUST_WORKS; + add_char_params.write_access = SEC_JUST_WORKS; + add_char_params.read_access = SEC_OPEN; + + return characteristic_add(p_dfu->service_handle, &add_char_params, &p_dfu->control_point_char); +} + + +void ble_dfu_buttonless_on_ctrl_pt_write(ble_gatts_evt_write_t const * p_evt_write) +{ + uint32_t ret; + ble_dfu_buttonless_rsp_code_t rsp_code = DFU_RSP_OPERATION_FAILED; + + // Start executing the control point write action + switch (p_evt_write->data[0]) + { + case DFU_OP_ENTER_BOOTLOADER: + ret = enter_bootloader(); + if (ret == NRF_SUCCESS) + { + rsp_code = DFU_RSP_SUCCESS; + } + else if (ret == NRF_ERROR_BUSY) + { + rsp_code = DFU_RSP_BUSY; + } + else if (ret == NRF_ERROR_FORBIDDEN) + { + rsp_code = DFU_RSP_NOT_BONDED; + } + break; + + default: + rsp_code = DFU_RSP_OP_CODE_NOT_SUPPORTED; + break; + } + + // Report back in case of error + if (rsp_code != DFU_RSP_SUCCESS) + { + ret = ble_dfu_buttonless_resp_send((ble_dfu_buttonless_op_code_t)p_evt_write->data[0], + rsp_code); + + if (ret != NRF_SUCCESS) + { + mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR); + } + + // Report the error to the main application + mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED); + } +} + + +uint32_t ble_dfu_buttonless_bootloader_start_prepare(void) +{ + NRF_LOG_DEBUG("In ble_dfu_buttonless_bootloader_start_prepare"); + + // Indicate to main app that DFU mode is starting. + // This event can be used to let the device take down any connection to + // bonded devices. + mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE); + + // Store the number of peers for which Peer Manager is expected to successfully write events. + mp_dfu->peers_count = peer_id_n_ids(); + + // Set local database changed to get Service Changed indication for all bonded peers + // on next bootup (either because of a successful or aborted DFU). + gscm_local_database_has_changed(); + + return NRF_SUCCESS; +} + +#endif // NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS + diff --git a/components/ble/ble_services/ble_dfu/ble_dfu_unbonded.c b/components/ble/ble_services/ble_dfu/ble_dfu_unbonded.c new file mode 100644 index 0000000..273bc23 --- /dev/null +++ b/components/ble/ble_services/ble_dfu/ble_dfu_unbonded.c @@ -0,0 +1,299 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include "nrf_dfu_ble_svci_bond_sharing.h" +#include "nordic_common.h" +#include "nrf_error.h" +#include "ble_dfu.h" +#include "nrf_log.h" +#include "nrf_sdh_soc.h" + +#if (!NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS) + +#define NRF_DFU_ADV_NAME_MAX_LENGTH (20) + + +void ble_dfu_buttonless_on_sys_evt(uint32_t, void * ); +uint32_t nrf_dfu_svci_vector_table_set(void); +uint32_t nrf_dfu_svci_vector_table_unset(void); + +/**@brief Define functions for async interface to set new advertisement name for DFU mode. */ +NRF_SVCI_ASYNC_FUNC_DEFINE(NRF_DFU_SVCI_SET_ADV_NAME, nrf_dfu_set_adv_name, nrf_dfu_adv_name_t); + +// Register SoC observer for the Buttonless Secure DFU service +NRF_SDH_SOC_OBSERVER(m_dfu_buttonless_soc_obs, BLE_DFU_SOC_OBSERVER_PRIO, ble_dfu_buttonless_on_sys_evt, NULL); + +ble_dfu_buttonless_t * mp_dfu = NULL; +static nrf_dfu_adv_name_t m_adv_name; + + +/**@brief Function for setting an advertisement name. + * + * @param[in] adv_name The new advertisement name. + * + * @retval NRF_SUCCESS Advertisement name was successfully set. + * @retval DFU_RSP_BUSY Advertisement name was not set because of an ongoing operation. + * @retval Any other errors from the SVCI interface call. + */ +static uint32_t set_adv_name(nrf_dfu_adv_name_t * p_adv_name) +{ + uint32_t err_code; + + if (mp_dfu->is_waiting_for_svci) + { + return DFU_RSP_BUSY; + } + + err_code = nrf_dfu_set_adv_name(p_adv_name); + if (err_code == NRF_SUCCESS) + { + // The request was accepted. + mp_dfu->is_waiting_for_svci = true; + } + else if (err_code == NRF_ERROR_FORBIDDEN) + { + NRF_LOG_ERROR("The bootloader has write protected its settings page. This prohibits setting the advertising name. "\ + "The bootloader must be compiled with NRF_BL_SETTINGS_PAGE_PROTECT=0 to allow setting the advertising name."); + } + + return err_code; +} + + +/**@brief Function for entering the bootloader. + */ +static uint32_t enter_bootloader() +{ + uint32_t err_code; + + if (mp_dfu->is_waiting_for_svci) + { + // We have an ongoing async operation. Entering bootloader mode is not possible at this time. + err_code = ble_dfu_buttonless_resp_send(DFU_OP_ENTER_BOOTLOADER, DFU_RSP_BUSY); + if (err_code != NRF_SUCCESS) + { + mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR); + } + return NRF_SUCCESS; + } + + // Set the flag indicating that we expect DFU mode. + // This will be handled on acknowledgement of the characteristic indication. + mp_dfu->is_waiting_for_reset = true; + + err_code = ble_dfu_buttonless_resp_send(DFU_OP_ENTER_BOOTLOADER, DFU_RSP_SUCCESS); + if (err_code != NRF_SUCCESS) + { + mp_dfu->is_waiting_for_reset = false; + } + + return err_code; +} + + +uint32_t ble_dfu_buttonless_backend_init(ble_dfu_buttonless_t * p_dfu) +{ + VERIFY_PARAM_NOT_NULL(p_dfu); + + mp_dfu = p_dfu; + + return NRF_SUCCESS; +} + + +uint32_t ble_dfu_buttonless_async_svci_init(void) +{ + uint32_t ret_val; + + ret_val = nrf_dfu_svci_vector_table_set(); + VERIFY_SUCCESS(ret_val); + + ret_val = nrf_dfu_set_adv_name_init(); + VERIFY_SUCCESS(ret_val); + + ret_val = nrf_dfu_svci_vector_table_unset(); + + return ret_val; +} + + +void ble_dfu_buttonless_on_sys_evt(uint32_t sys_evt, void * p_context) +{ + uint32_t err_code; + + if (!nrf_dfu_set_adv_name_is_initialized()) + { + return; + } + + err_code = nrf_dfu_set_adv_name_on_sys_evt(sys_evt); + if (err_code == NRF_ERROR_INVALID_STATE) + { + // The system event is not from an operation started by buttonless DFU. + // No action is taken, and nothing is reported. + } + else if (err_code == NRF_SUCCESS) + { + // The async operation is finished. + // Set the flag indicating that we are waiting for indication response + // to activate the reset. + mp_dfu->is_waiting_for_svci = false; + + // Report back the positive response + err_code = ble_dfu_buttonless_resp_send(DFU_OP_SET_ADV_NAME, DFU_RSP_SUCCESS); + if (err_code != NRF_SUCCESS) + { + mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR); + } + } + else + { + // Invalid error code reported back. + mp_dfu->is_waiting_for_svci = false; + + err_code = ble_dfu_buttonless_resp_send(DFU_OP_SET_ADV_NAME, DFU_RSP_BUSY); + if (err_code != NRF_SUCCESS) + { + mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR); + } + + // Report the failure to enter DFU mode + mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED); + } +} + + +uint32_t ble_dfu_buttonless_char_add(ble_dfu_buttonless_t * p_dfu) +{ + ble_add_char_params_t add_char_params; + + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = BLE_DFU_BUTTONLESS_CHAR_UUID; + add_char_params.uuid_type = p_dfu->uuid_type; + add_char_params.char_props.indicate = 1; + add_char_params.char_props.write = 1; + add_char_params.is_defered_write = true; + add_char_params.is_var_len = true; + add_char_params.max_len = BLE_GATT_ATT_MTU_DEFAULT; + + add_char_params.cccd_write_access = SEC_OPEN; + add_char_params.write_access = SEC_OPEN; + add_char_params.read_access = SEC_OPEN; + + return characteristic_add(p_dfu->service_handle, &add_char_params, &p_dfu->control_point_char); +} + + +void ble_dfu_buttonless_on_ctrl_pt_write(ble_gatts_evt_write_t const * p_evt_write) +{ + uint32_t err_code; + ble_dfu_buttonless_rsp_code_t rsp_code = DFU_RSP_OPERATION_FAILED; + + // Start executing the control point write operation + /*lint -e415 -e416 -save "Out of bounds access"*/ + switch (p_evt_write->data[0]) + { + case DFU_OP_ENTER_BOOTLOADER: + err_code = enter_bootloader(); + if (err_code == NRF_SUCCESS) + { + rsp_code = DFU_RSP_SUCCESS; + } + else if (err_code == NRF_ERROR_BUSY) + { + rsp_code = DFU_RSP_BUSY; + } + break; + + case DFU_OP_SET_ADV_NAME: + if( (p_evt_write->data[1] > NRF_DFU_ADV_NAME_MAX_LENGTH) + || (p_evt_write->data[1] == 0)) + { + // New advertisement name too short or too long. + rsp_code = DFU_RSP_ADV_NAME_INVALID; + } + else + { + memcpy(m_adv_name.name, &p_evt_write->data[2], p_evt_write->data[1]); + m_adv_name.len = p_evt_write->data[1]; + err_code = set_adv_name(&m_adv_name); + if (err_code == NRF_SUCCESS) + { + rsp_code = DFU_RSP_SUCCESS; + } + } + break; + + default: + rsp_code = DFU_RSP_OP_CODE_NOT_SUPPORTED; + break; + } + /*lint -restore*/ + + + // Report back in case of error + if (rsp_code != DFU_RSP_SUCCESS) + { + err_code = ble_dfu_buttonless_resp_send((ble_dfu_buttonless_op_code_t)p_evt_write->data[0], rsp_code); + if (err_code != NRF_SUCCESS) + { + mp_dfu->evt_handler(BLE_DFU_EVT_RESPONSE_SEND_ERROR); + + } + // Report the error to the main application + mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED); + } +} + +uint32_t ble_dfu_buttonless_bootloader_start_prepare(void) +{ + uint32_t err_code; + + // Indicate to main app that DFU mode is starting. + mp_dfu->evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE); + + err_code = ble_dfu_buttonless_bootloader_start_finalize(); + return err_code; +} + +#endif // NRF_DFU_BOTTONLESS_SUPPORT_BOND diff --git a/components/ble/ble_services/ble_nus/ble_nus.c b/components/ble/ble_services/ble_nus/ble_nus.c new file mode 100644 index 0000000..990a4d2 --- /dev/null +++ b/components/ble/ble_services/ble_nus/ble_nus.c @@ -0,0 +1,354 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(BLE_NUS) +#include "ble.h" +#include "ble_nus.h" +#include "ble_srv_common.h" + +#define NRF_LOG_MODULE_NAME ble_nus +#if BLE_NUS_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL BLE_NUS_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR BLE_NUS_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR BLE_NUS_CONFIG_DEBUG_COLOR +#else // BLE_NUS_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif // BLE_NUS_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +#define BLE_UUID_NUS_TX_CHARACTERISTIC 0x0003 /**< The UUID of the TX Characteristic. */ +#define BLE_UUID_NUS_RX_CHARACTERISTIC 0x0002 /**< The UUID of the RX Characteristic. */ + +#define BLE_NUS_MAX_RX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */ +#define BLE_NUS_MAX_TX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */ + +#define NUS_BASE_UUID {{0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}} /**< Used vendor specific UUID. */ + + +/**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the SoftDevice. + * + * @param[in] p_nus Nordic UART Service structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_connect(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + ble_nus_evt_t evt; + ble_gatts_value_t gatts_val; + uint8_t cccd_value[2]; + ble_nus_client_context_t * p_client = NULL; + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, + p_ble_evt->evt.gap_evt.conn_handle, + (void *) &p_client); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", + p_ble_evt->evt.gap_evt.conn_handle); + } + + /* Check the hosts CCCD value to inform of readiness to send data using the RX characteristic */ + memset(&gatts_val, 0, sizeof(ble_gatts_value_t)); + gatts_val.p_value = cccd_value; + gatts_val.len = sizeof(cccd_value); + gatts_val.offset = 0; + + err_code = sd_ble_gatts_value_get(p_ble_evt->evt.gap_evt.conn_handle, + p_nus->tx_handles.cccd_handle, + &gatts_val); + + if ((err_code == NRF_SUCCESS) && + (p_nus->data_handler != NULL) && + ble_srv_is_notification_enabled(gatts_val.p_value)) + { + if (p_client != NULL) + { + p_client->is_notification_enabled = true; + } + + memset(&evt, 0, sizeof(ble_nus_evt_t)); + evt.type = BLE_NUS_EVT_COMM_STARTED; + evt.p_nus = p_nus; + evt.conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + evt.p_link_ctx = p_client; + + p_nus->data_handler(&evt); + } +} + + +/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice. + * + * @param[in] p_nus Nordic UART Service structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_write(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + ble_nus_evt_t evt; + ble_nus_client_context_t * p_client; + ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, + p_ble_evt->evt.gatts_evt.conn_handle, + (void *) &p_client); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", + p_ble_evt->evt.gatts_evt.conn_handle); + } + + memset(&evt, 0, sizeof(ble_nus_evt_t)); + evt.p_nus = p_nus; + evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + evt.p_link_ctx = p_client; + + if ((p_evt_write->handle == p_nus->tx_handles.cccd_handle) && + (p_evt_write->len == 2)) + { + if (p_client != NULL) + { + if (ble_srv_is_notification_enabled(p_evt_write->data)) + { + p_client->is_notification_enabled = true; + evt.type = BLE_NUS_EVT_COMM_STARTED; + } + else + { + p_client->is_notification_enabled = false; + evt.type = BLE_NUS_EVT_COMM_STOPPED; + } + + if (p_nus->data_handler != NULL) + { + p_nus->data_handler(&evt); + } + + } + } + else if ((p_evt_write->handle == p_nus->rx_handles.value_handle) && + (p_nus->data_handler != NULL)) + { + evt.type = BLE_NUS_EVT_RX_DATA; + evt.params.rx_data.p_data = p_evt_write->data; + evt.params.rx_data.length = p_evt_write->len; + + p_nus->data_handler(&evt); + } + else + { + // Do Nothing. This event is not relevant for this service. + } +} + + +/**@brief Function for handling the @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event from the SoftDevice. + * + * @param[in] p_nus Nordic UART Service structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_hvx_tx_complete(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + ble_nus_evt_t evt; + ble_nus_client_context_t * p_client; + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, + p_ble_evt->evt.gatts_evt.conn_handle, + (void *) &p_client); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", + p_ble_evt->evt.gatts_evt.conn_handle); + return; + } + + if ((p_client->is_notification_enabled) && (p_nus->data_handler != NULL)) + { + memset(&evt, 0, sizeof(ble_nus_evt_t)); + evt.type = BLE_NUS_EVT_TX_RDY; + evt.p_nus = p_nus; + evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + evt.p_link_ctx = p_client; + + p_nus->data_handler(&evt); + } +} + + +void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) +{ + if ((p_context == NULL) || (p_ble_evt == NULL)) + { + return; + } + + ble_nus_t * p_nus = (ble_nus_t *)p_context; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + on_connect(p_nus, p_ble_evt); + break; + + case BLE_GATTS_EVT_WRITE: + on_write(p_nus, p_ble_evt); + break; + + case BLE_GATTS_EVT_HVN_TX_COMPLETE: + on_hvx_tx_complete(p_nus, p_ble_evt); + break; + + default: + // No implementation needed. + break; + } +} + + +uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init) +{ + ret_code_t err_code; + ble_uuid_t ble_uuid; + ble_uuid128_t nus_base_uuid = NUS_BASE_UUID; + ble_add_char_params_t add_char_params; + + VERIFY_PARAM_NOT_NULL(p_nus); + VERIFY_PARAM_NOT_NULL(p_nus_init); + + // Initialize the service structure. + p_nus->data_handler = p_nus_init->data_handler; + + /**@snippet [Adding proprietary Service to the SoftDevice] */ + // Add a custom base UUID. + err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type); + VERIFY_SUCCESS(err_code); + + ble_uuid.type = p_nus->uuid_type; + ble_uuid.uuid = BLE_UUID_NUS_SERVICE; + + // Add the service. + err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, + &ble_uuid, + &p_nus->service_handle); + /**@snippet [Adding proprietary Service to the SoftDevice] */ + VERIFY_SUCCESS(err_code); + + // Add the RX Characteristic. + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = BLE_UUID_NUS_RX_CHARACTERISTIC; + add_char_params.uuid_type = p_nus->uuid_type; + add_char_params.max_len = BLE_NUS_MAX_RX_CHAR_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.write = 1; + add_char_params.char_props.write_wo_resp = 1; + + add_char_params.read_access = SEC_OPEN; + add_char_params.write_access = SEC_OPEN; + + err_code = characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->rx_handles); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + // Add the TX Characteristic. + /**@snippet [Adding proprietary characteristic to the SoftDevice] */ + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = BLE_UUID_NUS_TX_CHARACTERISTIC; + add_char_params.uuid_type = p_nus->uuid_type; + add_char_params.max_len = BLE_NUS_MAX_TX_CHAR_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.notify = 1; + + add_char_params.read_access = SEC_OPEN; + add_char_params.write_access = SEC_OPEN; + add_char_params.cccd_write_access = SEC_OPEN; + + return characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->tx_handles); + /**@snippet [Adding proprietary characteristic to the SoftDevice] */ +} + + +uint32_t ble_nus_data_send(ble_nus_t * p_nus, + uint8_t * p_data, + uint16_t * p_length, + uint16_t conn_handle) +{ + ret_code_t err_code; + ble_gatts_hvx_params_t hvx_params; + ble_nus_client_context_t * p_client; + + VERIFY_PARAM_NOT_NULL(p_nus); + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, conn_handle, (void *) &p_client); + VERIFY_SUCCESS(err_code); + + if ((conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL)) + { + return NRF_ERROR_NOT_FOUND; + } + + if (!p_client->is_notification_enabled) + { + return NRF_ERROR_INVALID_STATE; + } + + if (*p_length > BLE_NUS_MAX_DATA_LEN) + { + return NRF_ERROR_INVALID_PARAM; + } + + memset(&hvx_params, 0, sizeof(hvx_params)); + + hvx_params.handle = p_nus->tx_handles.value_handle; + hvx_params.p_data = p_data; + hvx_params.p_len = p_length; + hvx_params.type = BLE_GATT_HVX_NOTIFICATION; + + return sd_ble_gatts_hvx(conn_handle, &hvx_params); +} + + +#endif // NRF_MODULE_ENABLED(BLE_NUS) diff --git a/components/ble/ble_services/ble_nus/ble_nus.h b/components/ble/ble_services/ble_nus/ble_nus.h new file mode 100644 index 0000000..794e178 --- /dev/null +++ b/components/ble/ble_services/ble_nus/ble_nus.h @@ -0,0 +1,244 @@ + /** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup ble_nus Nordic UART Service + * @{ + * @ingroup ble_sdk_srv + * @brief Nordic UART Service implementation. + * + * @details The Nordic UART Service is a simple GATT-based service with TX and RX characteristics. + * Data received from the peer is passed to the application, and the data received + * from the application of this service is sent to the peer as Handle Value + * Notifications. This module demonstrates how to implement a custom GATT-based + * service and characteristics using the SoftDevice. The service + * is used by the application to send and receive ASCII text strings to and from the + * peer. + * + * @note The application must register this module as BLE event observer using the + * NRF_SDH_BLE_OBSERVER macro. Example: + * @code + * ble_nus_t instance; + * NRF_SDH_BLE_OBSERVER(anything, BLE_NUS_BLE_OBSERVER_PRIO, + * ble_nus_on_ble_evt, &instance); + * @endcode + */ +#ifndef BLE_NUS_H__ +#define BLE_NUS_H__ + +#include +#include +#include "sdk_config.h" +#include "ble.h" +#include "ble_srv_common.h" +#include "nrf_sdh_ble.h" +#include "ble_link_ctx_manager.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Macro for defining a ble_nus instance. + * + * @param _name Name of the instance. + * @param[in] _nus_max_clients Maximum number of NUS clients connected at a time. + * @hideinitializer + */ +#define BLE_NUS_DEF(_name, _nus_max_clients) \ + BLE_LINK_CTX_MANAGER_DEF(CONCAT_2(_name, _link_ctx_storage), \ + (_nus_max_clients), \ + sizeof(ble_nus_client_context_t)); \ + static ble_nus_t _name = \ + { \ + .p_link_ctx_storage = &CONCAT_2(_name, _link_ctx_storage) \ + }; \ + NRF_SDH_BLE_OBSERVER(_name ## _obs, \ + BLE_NUS_BLE_OBSERVER_PRIO, \ + ble_nus_on_ble_evt, \ + &_name) + +#define BLE_UUID_NUS_SERVICE 0x0001 /**< The UUID of the Nordic UART Service. */ + +#define OPCODE_LENGTH 1 +#define HANDLE_LENGTH 2 + +/**@brief Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */ +#if defined(NRF_SDH_BLE_GATT_MAX_MTU_SIZE) && (NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 0) + #define BLE_NUS_MAX_DATA_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - OPCODE_LENGTH - HANDLE_LENGTH) +#else + #define BLE_NUS_MAX_DATA_LEN (BLE_GATT_MTU_SIZE_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH) + #warning NRF_SDH_BLE_GATT_MAX_MTU_SIZE is not defined. +#endif + + +/**@brief Nordic UART Service event types. */ +typedef enum +{ + BLE_NUS_EVT_RX_DATA, /**< Data received. */ + BLE_NUS_EVT_TX_RDY, /**< Service is ready to accept new data to be transmitted. */ + BLE_NUS_EVT_COMM_STARTED, /**< Notification has been enabled. */ + BLE_NUS_EVT_COMM_STOPPED, /**< Notification has been disabled. */ +} ble_nus_evt_type_t; + + +/* Forward declaration of the ble_nus_t type. */ +typedef struct ble_nus_s ble_nus_t; + + +/**@brief Nordic UART Service @ref BLE_NUS_EVT_RX_DATA event data. + * + * @details This structure is passed to an event when @ref BLE_NUS_EVT_RX_DATA occurs. + */ +typedef struct +{ + uint8_t const * p_data; /**< A pointer to the buffer with received data. */ + uint16_t length; /**< Length of received data. */ +} ble_nus_evt_rx_data_t; + + +/**@brief Nordic UART Service client context structure. + * + * @details This structure contains state context related to hosts. + */ +typedef struct +{ + bool is_notification_enabled; /**< Variable to indicate if the peer has enabled notification of the RX characteristic.*/ +} ble_nus_client_context_t; + + +/**@brief Nordic UART Service event structure. + * + * @details This structure is passed to an event coming from service. + */ +typedef struct +{ + ble_nus_evt_type_t type; /**< Event type. */ + ble_nus_t * p_nus; /**< A pointer to the instance. */ + uint16_t conn_handle; /**< Connection handle. */ + ble_nus_client_context_t * p_link_ctx; /**< A pointer to the link context. */ + union + { + ble_nus_evt_rx_data_t rx_data; /**< @ref BLE_NUS_EVT_RX_DATA event data. */ + } params; +} ble_nus_evt_t; + + +/**@brief Nordic UART Service event handler type. */ +typedef void (* ble_nus_data_handler_t) (ble_nus_evt_t * p_evt); + + +/**@brief Nordic UART Service initialization structure. + * + * @details This structure contains the initialization information for the service. The application + * must fill this structure and pass it to the service using the @ref ble_nus_init + * function. + */ +typedef struct +{ + ble_nus_data_handler_t data_handler; /**< Event handler to be called for handling received data. */ +} ble_nus_init_t; + + +/**@brief Nordic UART Service structure. + * + * @details This structure contains status information related to the service. + */ +struct ble_nus_s +{ + uint8_t uuid_type; /**< UUID type for Nordic UART Service Base UUID. */ + uint16_t service_handle; /**< Handle of Nordic UART Service (as provided by the SoftDevice). */ + ble_gatts_char_handles_t tx_handles; /**< Handles related to the TX characteristic (as provided by the SoftDevice). */ + ble_gatts_char_handles_t rx_handles; /**< Handles related to the RX characteristic (as provided by the SoftDevice). */ + blcm_link_ctx_storage_t * const p_link_ctx_storage; /**< Pointer to link context storage with handles of all current connections and its context. */ + ble_nus_data_handler_t data_handler; /**< Event handler to be called for handling received data. */ +}; + + +/**@brief Function for initializing the Nordic UART Service. + * + * @param[out] p_nus Nordic UART Service structure. This structure must be supplied + * by the application. It is initialized by this function and will + * later be used to identify this particular service instance. + * @param[in] p_nus_init Information needed to initialize the service. + * + * @retval NRF_SUCCESS If the service was successfully initialized. Otherwise, an error code is returned. + * @retval NRF_ERROR_NULL If either of the pointers p_nus or p_nus_init is NULL. + */ +uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init); + + +/**@brief Function for handling the Nordic UART Service's BLE events. + * + * @details The Nordic UART Service expects the application to call this function each time an + * event is received from the SoftDevice. This function processes the event if it + * is relevant and calls the Nordic UART Service event handler of the + * application if necessary. + * + * @param[in] p_ble_evt Event received from the SoftDevice. + * @param[in] p_context Nordic UART Service structure. + */ +void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); + + +/**@brief Function for sending a data to the peer. + * + * @details This function sends the input string as an RX characteristic notification to the + * peer. + * + * @param[in] p_nus Pointer to the Nordic UART Service structure. + * @param[in] p_data String to be sent. + * @param[in,out] p_length Pointer Length of the string. Amount of sent bytes. + * @param[in] conn_handle Connection Handle of the destination client. + * + * @retval NRF_SUCCESS If the string was sent successfully. Otherwise, an error code is returned. + */ +uint32_t ble_nus_data_send(ble_nus_t * p_nus, + uint8_t * p_data, + uint16_t * p_length, + uint16_t conn_handle); + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_NUS_H__ + +/** @} */ diff --git a/components/ble/common/ble_advdata.c b/components/ble/common/ble_advdata.c new file mode 100644 index 0000000..211d8ef --- /dev/null +++ b/components/ble/common/ble_advdata.c @@ -0,0 +1,838 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "ble_advdata.h" +#include "ble_gap.h" +#include "ble_srv_common.h" +#include "sdk_common.h" + +// NOTE: For now, Security Manager Out of Band Flags (OOB) are omitted from the advertising data. + + +// Types of LE Bluetooth Device Address AD type +#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC 0UL +#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM 1UL + +#define UUID16_SIZE 2 /**< Size of 16 bit UUID. */ +#define UUID32_SIZE 4 /**< Size of 32 bit UUID. */ +#define UUID128_SIZE 16 /**< Size of 128 bit UUID. */ + +#define N_AD_TYPES 2 /**< The number of Advertising data types to search for at a time. */ + + +static ret_code_t ble_device_addr_encode(uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + ret_code_t err_code; + ble_gap_addr_t device_addr; + + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_BLE_DEVICE_ADDR_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Get BLE address. + err_code = sd_ble_gap_addr_get(&device_addr); + VERIFY_SUCCESS(err_code); + + // Encode LE Bluetooth Device Address. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + + AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS; + *p_offset += AD_TYPE_FIELD_SIZE; + memcpy(&p_encoded_data[*p_offset], &device_addr.addr[0], BLE_GAP_ADDR_LEN); + *p_offset += BLE_GAP_ADDR_LEN; + if (BLE_GAP_ADDR_TYPE_PUBLIC == device_addr.addr_type) + { + p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC; + } + else + { + p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM; + } + *p_offset += AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE; + + return NRF_SUCCESS; +} + +static ret_code_t name_encode(const ble_advdata_t * p_advdata, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + ret_code_t err_code; + uint16_t rem_adv_data_len; + uint16_t actual_length; + uint8_t adv_data_format; + + + // Validate parameters + if ((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && (0 == p_advdata->short_name_len)) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Check for buffer overflow. + if ( (((*p_offset) + AD_DATA_OFFSET) > max_size) || + ( (BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && + (((*p_offset) + AD_DATA_OFFSET + p_advdata->short_name_len) > max_size))) + { + return NRF_ERROR_DATA_SIZE; + } + + rem_adv_data_len = max_size - (*p_offset) - AD_DATA_OFFSET; + actual_length = rem_adv_data_len; + + // Get GAP device name and length + err_code = sd_ble_gap_device_name_get(&p_encoded_data[(*p_offset) + AD_DATA_OFFSET], + &actual_length); + VERIFY_SUCCESS(err_code); + + // Check if device intend to use short name and it can fit available data size. + // If the name is shorter than the preferred short name length then it is no longer + // a short name and is in fact the complete name of the device. + if (((p_advdata->name_type == BLE_ADVDATA_FULL_NAME) || + (actual_length <= p_advdata->short_name_len)) && + (actual_length <= rem_adv_data_len)) + { + // Complete device name can fit, setting Complete Name in Adv Data. + adv_data_format = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; + } + else + { + // Else short name needs to be used. Or application has requested use of short name. + adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME; + + // If application has set a preference on the short name size, it needs to be considered, + // else fit what can be fit. + if ((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && + (p_advdata->short_name_len <= rem_adv_data_len)) + { + // Short name fits available size. + actual_length = p_advdata->short_name_len; + } + // Else whatever can fit the data buffer will be packed. + else + { + actual_length = rem_adv_data_len; + } + } + + // There is only 1 byte intended to encode length which is (actual_length + AD_TYPE_FIELD_SIZE) + if (actual_length > (0x00FF - AD_TYPE_FIELD_SIZE)) + { + return NRF_ERROR_DATA_SIZE; + } + + // Complete name field in encoded data. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + actual_length); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = adv_data_format; + *p_offset += AD_TYPE_FIELD_SIZE; + *p_offset += actual_length; + + return NRF_SUCCESS; +} + + +static ret_code_t appearance_encode(uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + ret_code_t err_code; + uint16_t appearance; + + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_APPEARANCE_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Get GAP appearance field. + err_code = sd_ble_gap_appearance_get(&appearance); + VERIFY_SUCCESS(err_code); + + // Encode Length, AD Type and Appearance. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_APPEARANCE_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_APPEARANCE; + *p_offset += AD_TYPE_FIELD_SIZE; + *p_offset += uint16_encode(appearance, &p_encoded_data[*p_offset]); + + return NRF_SUCCESS; +} + +static ret_code_t flags_encode(int8_t flags, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_FLAGS_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode flags. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_FLAGS_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_FLAGS; + *p_offset += AD_TYPE_FIELD_SIZE; + p_encoded_data[*p_offset] = flags; + *p_offset += AD_TYPE_FLAGS_DATA_SIZE; + + return NRF_SUCCESS; +} + +static ret_code_t tx_power_level_encode(int8_t tx_power_level, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_TX_POWER_LEVEL_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode TX Power Level. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + + AD_TYPE_TX_POWER_LEVEL_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL; + *p_offset += AD_TYPE_FIELD_SIZE; + p_encoded_data[*p_offset] = tx_power_level; + *p_offset += AD_TYPE_TX_POWER_LEVEL_DATA_SIZE; + + return NRF_SUCCESS; +} + + +static ret_code_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list, + uint8_t adv_type, + uint8_t uuid_size, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + int i; + bool is_heading_written = false; + uint16_t start_pos = *p_offset; + uint16_t length; + + for (i = 0; i < p_uuid_list->uuid_cnt; i++) + { + ret_code_t err_code; + uint8_t encoded_size; + ble_uuid_t uuid = p_uuid_list->p_uuids[i]; + + // Find encoded uuid size. + err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL); + VERIFY_SUCCESS(err_code); + + // Check size. + if (encoded_size == uuid_size) + { + uint8_t heading_bytes = (is_heading_written) ? 0 : AD_DATA_OFFSET; + + // Check for buffer overflow + if (((*p_offset) + encoded_size + heading_bytes) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + if (!is_heading_written) + { + // Write AD structure heading. + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = adv_type; + *p_offset += AD_TYPE_FIELD_SIZE; + is_heading_written = true; + } + + // Write UUID. + err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_offset]); + VERIFY_SUCCESS(err_code); + *p_offset += encoded_size; + } + } + + if (is_heading_written) + { + // Write length. + length = (*p_offset) - (start_pos + AD_LENGTH_FIELD_SIZE); + // There is only 1 byte intended to encode length + if (length > 0x00FF) + { + return NRF_ERROR_DATA_SIZE; + } + p_encoded_data[start_pos] = (uint8_t)length; + } + + return NRF_SUCCESS; +} + + +static ret_code_t uuid_list_encode(const ble_advdata_uuid_list_t * p_uuid_list, + uint8_t adv_type_16, + uint8_t adv_type_128, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + ret_code_t err_code; + + // Encode 16 bit UUIDs. + err_code = uuid_list_sized_encode(p_uuid_list, + adv_type_16, + sizeof(uint16_le_t), + p_encoded_data, + p_offset, + max_size); + VERIFY_SUCCESS(err_code); + + // Encode 128 bit UUIDs. + err_code = uuid_list_sized_encode(p_uuid_list, + adv_type_128, + sizeof(ble_uuid128_t), + p_encoded_data, + p_offset, + max_size); + VERIFY_SUCCESS(err_code); + + return NRF_SUCCESS; +} + + +static ret_code_t conn_int_check(const ble_advdata_conn_int_t *p_conn_int) +{ + // Check Minimum Connection Interval. + if ((p_conn_int->min_conn_interval < 0x0006) || + ( + (p_conn_int->min_conn_interval > 0x0c80) && + (p_conn_int->min_conn_interval != 0xffff) + ) + ) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Check Maximum Connection Interval. + if ((p_conn_int->max_conn_interval < 0x0006) || + ( + (p_conn_int->max_conn_interval > 0x0c80) && + (p_conn_int->max_conn_interval != 0xffff) + ) + ) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Make sure Minimum Connection Interval is not bigger than Maximum Connection Interval. + if ((p_conn_int->min_conn_interval != 0xffff) && + (p_conn_int->max_conn_interval != 0xffff) && + (p_conn_int->min_conn_interval > p_conn_int->max_conn_interval) + ) + { + return NRF_ERROR_INVALID_PARAM; + } + + return NRF_SUCCESS; +} + + +static ret_code_t conn_int_encode(const ble_advdata_conn_int_t * p_conn_int, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + ret_code_t err_code; + + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_CONN_INT_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Check parameters. + err_code = conn_int_check(p_conn_int); + VERIFY_SUCCESS(err_code); + + // Encode Length and AD Type. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_CONN_INT_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE; + *p_offset += AD_TYPE_FIELD_SIZE; + + // Encode Minimum and Maximum Connection Intervals. + *p_offset += uint16_encode(p_conn_int->min_conn_interval, &p_encoded_data[*p_offset]); + *p_offset += uint16_encode(p_conn_int->max_conn_interval, &p_encoded_data[*p_offset]); + + return NRF_SUCCESS; +} + + +static ret_code_t manuf_specific_data_encode(const ble_advdata_manuf_data_t * p_manuf_sp_data, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint32_t data_size = AD_TYPE_MANUF_SPEC_DATA_ID_SIZE + p_manuf_sp_data->data.size; + + // Check for buffer overflow. + if (((*p_offset) + AD_DATA_OFFSET + data_size) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // There is only 1 byte intended to encode length which is (data_size + AD_TYPE_FIELD_SIZE) + if (data_size > (0x00FF - AD_TYPE_FIELD_SIZE)) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode Length and AD Type. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + data_size); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA; + *p_offset += AD_TYPE_FIELD_SIZE; + + // Encode Company Identifier. + *p_offset += uint16_encode(p_manuf_sp_data->company_identifier, &p_encoded_data[*p_offset]); + + // Encode additional manufacturer specific data. + if (p_manuf_sp_data->data.size > 0) + { + if (p_manuf_sp_data->data.p_data == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + memcpy(&p_encoded_data[*p_offset], p_manuf_sp_data->data.p_data, p_manuf_sp_data->data.size); + *p_offset += p_manuf_sp_data->data.size; + } + + return NRF_SUCCESS; +} + +// Implemented only for 16-bit UUIDs +static ret_code_t service_data_encode(const ble_advdata_t * p_advdata, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint8_t i; + + // Check parameter consistency. + if (p_advdata->p_service_data_array == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + + for (i = 0; i < p_advdata->service_data_count; i++) + { + ble_advdata_service_data_t * p_service_data; + uint32_t data_size; + + p_service_data = &p_advdata->p_service_data_array[i]; + // For now implemented only for 16-bit UUIDs + data_size = AD_TYPE_SERV_DATA_16BIT_UUID_SIZE + p_service_data->data.size; + + // There is only 1 byte intended to encode length which is (data_size + AD_TYPE_FIELD_SIZE) + if (data_size > (0x00FF - AD_TYPE_FIELD_SIZE)) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode Length and AD Type. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + data_size); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SERVICE_DATA; + *p_offset += AD_TYPE_FIELD_SIZE; + + // Encode service 16-bit UUID. + *p_offset += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_offset]); + + // Encode additional service data. + if (p_service_data->data.size > 0) + { + if (p_service_data->data.p_data == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + memcpy(&p_encoded_data[*p_offset], p_service_data->data.p_data, p_service_data->data.size); + *p_offset += p_service_data->data.size; + } + } + + return NRF_SUCCESS; +} + +ret_code_t ble_advdata_encode(ble_advdata_t const * const p_advdata, + uint8_t * const p_encoded_data, + uint16_t * const p_len) +{ + ret_code_t err_code = NRF_SUCCESS; + uint16_t max_size = *p_len; + *p_len = 0; + + // Encode LE Bluetooth Device Address + if (p_advdata->include_ble_device_addr) + { + err_code = ble_device_addr_encode(p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode appearance. + if (p_advdata->include_appearance) + { + err_code = appearance_encode(p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + //Encode Flags + if (p_advdata->flags != 0 ) + { + err_code = flags_encode(p_advdata->flags, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode TX power level. + if (p_advdata->p_tx_power_level != NULL) + { + err_code = tx_power_level_encode(*p_advdata->p_tx_power_level, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode 'more available' uuid list. + if (p_advdata->uuids_more_available.uuid_cnt > 0) + { + err_code = uuid_list_encode(&p_advdata->uuids_more_available, + BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, + BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode 'complete' uuid list. + if (p_advdata->uuids_complete.uuid_cnt > 0) + { + err_code = uuid_list_encode(&p_advdata->uuids_complete, + BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, + BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode 'solicited service' uuid list. + if (p_advdata->uuids_solicited.uuid_cnt > 0) + { + err_code = uuid_list_encode(&p_advdata->uuids_solicited, + BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT, + BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode Slave Connection Interval Range. + if (p_advdata->p_slave_conn_int != NULL) + { + err_code = conn_int_encode(p_advdata->p_slave_conn_int, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode Manufacturer Specific Data. + if (p_advdata->p_manuf_specific_data != NULL) + { + err_code = manuf_specific_data_encode(p_advdata->p_manuf_specific_data, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode Service Data. + if (p_advdata->service_data_count > 0) + { + err_code = service_data_encode(p_advdata, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode name. WARNING: it is encoded last on purpose since too long device name is truncated. + if (p_advdata->name_type != BLE_ADVDATA_NO_NAME) + { + err_code = name_encode(p_advdata, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + return err_code; +} + + +uint16_t ble_advdata_search(uint8_t const * p_encoded_data, + uint16_t data_len, + uint16_t * p_offset, + uint8_t ad_type) +{ + if ((p_encoded_data == NULL) || (p_offset == NULL)) + { + return 0; + } + + uint16_t i = 0; + + while ((i + 1 < data_len) && ((i < *p_offset) || (p_encoded_data[i + 1] != ad_type))) + { + // Jump to next data. + i += (p_encoded_data[i] + 1); + } + + if (i >= data_len) + { + return 0; + } + else + { + uint16_t offset = i + 2; + uint16_t len = p_encoded_data[i] ? (p_encoded_data[i] - 1) : 0; + if (!len || ((offset + len) > data_len)) + { + // Malformed. Zero length or extends beyond provided data. + return 0; + } + *p_offset = offset; + return len; + } +} + + +uint8_t * ble_advdata_parse(uint8_t * p_encoded_data, + uint16_t data_len, + uint8_t ad_type) +{ + uint16_t offset = 0; + uint16_t len = ble_advdata_search(p_encoded_data, data_len, &offset, ad_type); + + if (len == 0) + { + return NULL; + } + else + { + return &p_encoded_data[offset]; + } +} + + +bool ble_advdata_name_find(uint8_t const * p_encoded_data, + uint16_t data_len, + char const * p_target_name) +{ + uint16_t parsed_name_len; + uint8_t const * p_parsed_name; + uint16_t data_offset = 0; + + if (p_target_name == NULL) + { + return false; + } + + + parsed_name_len = ble_advdata_search(p_encoded_data, + data_len, + &data_offset, + BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME); + + p_parsed_name = &p_encoded_data[data_offset]; + + if ( (data_offset != 0) + && (parsed_name_len != 0) + && (strlen(p_target_name) == parsed_name_len) + && (memcmp(p_target_name, p_parsed_name, parsed_name_len) == 0)) + { + return true; + } + + return false; +} + + +bool ble_advdata_short_name_find(uint8_t const * p_encoded_data, + uint16_t data_len, + char const * p_target_name, + uint8_t const short_name_min_len) +{ + uint16_t parsed_name_len; + uint8_t const * p_parsed_name; + uint16_t data_offset = 0; + + if (p_target_name == NULL) + { + return false; + } + + parsed_name_len = ble_advdata_search(p_encoded_data, + data_len, + &data_offset, + BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME); + + p_parsed_name = &p_encoded_data[data_offset]; + + if ( (data_offset != 0) + && (parsed_name_len != 0) + && (parsed_name_len >= short_name_min_len) + && (parsed_name_len < strlen(p_target_name)) + && (memcmp(p_target_name, p_parsed_name, parsed_name_len) == 0)) + { + return true; + } + + return false; +} + + +bool ble_advdata_uuid_find(uint8_t const * p_encoded_data, + uint16_t data_len, + ble_uuid_t const * p_target_uuid) +{ + + ret_code_t err_code; + uint16_t data_offset = 0; + uint8_t raw_uuid_len = UUID128_SIZE; + uint8_t const * p_parsed_uuid; + uint16_t parsed_uuid_len = data_len; + uint8_t raw_uuid[UUID128_SIZE]; + uint8_t ad_types[N_AD_TYPES]; + + err_code = sd_ble_uuid_encode(p_target_uuid, &raw_uuid_len, raw_uuid); + + if ((p_encoded_data == NULL) || (err_code != NRF_SUCCESS)) + { + // Invalid p_encoded_data or p_target_uuid. + return false; + } + + switch (raw_uuid_len) + { + case UUID16_SIZE: + ad_types[0] = BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE; + ad_types[1] = BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE; + break; + + case UUID32_SIZE: + // Not currently supported by sd_ble_uuid_encode(). + ad_types[0] = BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_COMPLETE; + ad_types[1] = BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE; + break; + + case UUID128_SIZE: + ad_types[0] = BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE; + ad_types[1] = BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE; + break; + + default: + return false; + } + + for (uint8_t i = 0; (i < N_AD_TYPES) && (data_offset == 0); i++) + { + parsed_uuid_len = ble_advdata_search(p_encoded_data, data_len, &data_offset, ad_types[i]); + } + + if (data_offset == 0) + { + // Could not find any relevant UUIDs in the encoded data. + return false; + } + + p_parsed_uuid = &p_encoded_data[data_offset]; + + // Verify if any UUID matches the given UUID. + for (uint16_t list_offset = 0; list_offset < parsed_uuid_len; list_offset += raw_uuid_len) + { + if (memcmp(&p_parsed_uuid[list_offset], raw_uuid, raw_uuid_len) == 0) + { + return true; + } + } + + // Could not find the UUID among the encoded data. + return false; +} + + +bool ble_advdata_appearance_find(uint8_t const * p_encoded_data, + uint16_t data_len, + uint16_t const * p_target_appearance) +{ + uint16_t data_offset = 0; + uint8_t appearance_len; + uint16_t decoded_appearance; + + appearance_len = ble_advdata_search(p_encoded_data, data_len, &data_offset, BLE_GAP_AD_TYPE_APPEARANCE); + + if ( (data_offset == 0) + || (p_target_appearance == NULL) + || (appearance_len == 0)) + { + // Could not find any Appearance in the encoded data, or invalid p_target_appearance. + return false; + } + + decoded_appearance = uint16_decode(&p_encoded_data[data_offset]); + + if (decoded_appearance == *p_target_appearance) + { + return true; + } + + // Could not find the appearance among the encoded data. + return false; +} diff --git a/components/ble/common/ble_advdata.h b/components/ble/common/ble_advdata.h new file mode 100644 index 0000000..a254974 --- /dev/null +++ b/components/ble/common/ble_advdata.h @@ -0,0 +1,326 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup ble_sdk_lib_advdata Advertising and Scan Response Data Encoder + * @{ + * @ingroup ble_sdk_lib + * @brief Functions for encoding data in the Advertising and Scan Response Data format, + * and for passing the data to the stack. + */ + +#ifndef BLE_ADVDATA_H__ +#define BLE_ADVDATA_H__ + +#include +#include +#include +#include "ble.h" +#include "sdk_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define AD_LENGTH_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the length. */ +#define AD_TYPE_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the AD type. */ +#define AD_DATA_OFFSET (AD_LENGTH_FIELD_SIZE + AD_TYPE_FIELD_SIZE) /**< Offset for the AD data field of the Advertising Data and Scan Response format. */ + +#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE 1UL /**< Data size (in octets) of the Address type of the LE Bluetooth Device Address AD type. */ +#define AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE (BLE_GAP_ADDR_LEN + \ + AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE) /**< Data size (in octets) of the LE Bluetooth Device Address AD type. */ +#define AD_TYPE_BLE_DEVICE_ADDR_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE) /**< Size (in octets) of the LE Bluetooth Device Address AD type. */ +#define AD_TYPE_APPEARANCE_DATA_SIZE 2UL /**< Data size (in octets) of the Appearance AD type. */ +#define AD_TYPE_APPEARANCE_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_APPEARANCE_DATA_SIZE) /**< Size (in octets) of the Appearance AD type. */ +#define AD_TYPE_FLAGS_DATA_SIZE 1UL /**< Data size (in octets) of the Flags AD type. */ +#define AD_TYPE_FLAGS_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_FLAGS_DATA_SIZE) /**< Size (in octets) of the Flags AD type. */ +#define AD_TYPE_TX_POWER_LEVEL_DATA_SIZE 1UL /**< Data size (in octets) of the TX Power Level AD type. */ +#define AD_TYPE_TX_POWER_LEVEL_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_TX_POWER_LEVEL_DATA_SIZE) /**< Size (in octets) of the TX Power Level AD type. */ +#define AD_TYPE_CONN_INT_DATA_SIZE 4UL /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ +#define AD_TYPE_CONN_INT_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_CONN_INT_DATA_SIZE) /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ +#define AD_TYPE_MANUF_SPEC_DATA_ID_SIZE 2UL /**< Size (in octets) of the Company Identifier Code, which is a part of the Manufacturer Specific Data AD type. */ +#define AD_TYPE_SERV_DATA_16BIT_UUID_SIZE 2UL /**< Size (in octets) of the 16-bit UUID, which is a part of the Service Data AD type. */ + +#define BLE_ADV_DATA_MATCH_FULL_NAME 0xff + + +/**@brief Security Manager TK value. */ +typedef struct +{ + uint8_t tk[BLE_GAP_SEC_KEY_LEN]; /**< Array containing TK value in little-endian format. */ +} ble_advdata_tk_value_t; + +/**@brief Advertising data LE Role types. This enumeration contains the options available for the LE role inside + * the advertising data. */ +typedef enum +{ + BLE_ADVDATA_ROLE_NOT_PRESENT = 0, /**< LE Role AD structure not present. */ + BLE_ADVDATA_ROLE_ONLY_PERIPH, /**< Only Peripheral Role supported. */ + BLE_ADVDATA_ROLE_ONLY_CENTRAL, /**< Only Central Role supported. */ + BLE_ADVDATA_ROLE_BOTH_PERIPH_PREFERRED, /**< Peripheral and Central Role supported. Peripheral Role preferred for connection establishment. */ + BLE_ADVDATA_ROLE_BOTH_CENTRAL_PREFERRED /**< Peripheral and Central Role supported. Central Role preferred for connection establishment */ +} ble_advdata_le_role_t; + +/**@brief Advertising data name type. This enumeration contains the options available for the device name inside + * the advertising data. */ +typedef enum +{ + BLE_ADVDATA_NO_NAME, /**< Include no device name in advertising data. */ + BLE_ADVDATA_SHORT_NAME, /**< Include short device name in advertising data. */ + BLE_ADVDATA_FULL_NAME /**< Include full device name in advertising data. */ +} ble_advdata_name_type_t; + +/**@brief UUID list type. */ +typedef struct +{ + uint16_t uuid_cnt; /**< Number of UUID entries. */ + ble_uuid_t * p_uuids; /**< Pointer to UUID array entries. */ +} ble_advdata_uuid_list_t; + +/**@brief Connection interval range structure. */ +typedef struct +{ + uint16_t min_conn_interval; /**< Minimum connection interval, in units of 1.25 ms, range 6 to 3200 (7.5 ms to 4 s). */ + uint16_t max_conn_interval; /**< Maximum connection interval, in units of 1.25 ms, range 6 to 3200 (7.5 ms to 4 s). The value 0xFFFF indicates no specific maximum. */ +} ble_advdata_conn_int_t; + +/**@brief Manufacturer specific data structure. */ +typedef struct +{ + uint16_t company_identifier; /**< Company identifier code. */ + uint8_array_t data; /**< Additional manufacturer specific data. */ +} ble_advdata_manuf_data_t; + +/**@brief Service data structure. */ +typedef struct +{ + uint16_t service_uuid; /**< Service UUID. */ + uint8_array_t data; /**< Additional service data. */ +} ble_advdata_service_data_t; + +/**@brief Advertising data structure. This structure contains all options and data needed for encoding and + * setting the advertising data. */ +typedef struct +{ + ble_advdata_name_type_t name_type; /**< Type of device name. */ + uint8_t short_name_len; /**< Length of short device name (if short type is specified). */ + bool include_appearance; /**< Determines if Appearance shall be included. */ + uint8_t flags; /**< Advertising data Flags field. */ + int8_t * p_tx_power_level; /**< TX Power Level field. */ + ble_advdata_uuid_list_t uuids_more_available; /**< List of UUIDs in the 'More Available' list. */ + ble_advdata_uuid_list_t uuids_complete; /**< List of UUIDs in the 'Complete' list. */ + ble_advdata_uuid_list_t uuids_solicited; /**< List of solicited UUIDs. */ + ble_advdata_conn_int_t * p_slave_conn_int; /**< Slave Connection Interval Range. */ + ble_advdata_manuf_data_t * p_manuf_specific_data; /**< Manufacturer specific data. */ + ble_advdata_service_data_t * p_service_data_array; /**< Array of Service data structures. */ + uint8_t service_data_count; /**< Number of Service data structures. */ + bool include_ble_device_addr; /**< Determines if LE Bluetooth Device Address shall be included. */ + ble_advdata_le_role_t le_role; /**< LE Role field. Included when different from @ref BLE_ADVDATA_ROLE_NOT_PRESENT. @warning This field can be used only for NFC. For BLE advertising, set it to NULL. */ + ble_advdata_tk_value_t * p_tk_value; /**< Security Manager TK value field. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ + uint8_t * p_sec_mgr_oob_flags; /**< Security Manager Out Of Band Flags field. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ + ble_gap_lesc_oob_data_t * p_lesc_data; /**< LE Secure Connections OOB data. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ +} ble_advdata_t; + +/**@brief Function for encoding data in the Advertising and Scan Response data format (AD structures). + * + * @details This function encodes data into the Advertising and Scan Response data format + * (AD structures) based on the fields in the supplied structures. This function can be + * used to create a payload of Advertising packet or Scan Response packet, or a payload of + * NFC message intended for initiating the Out-of-Band pairing. + * + * @param[in] p_advdata Pointer to the structure for specifying the content of encoded data. + * @param[out] p_encoded_data Pointer to the buffer where encoded data will be returned. + * @param[in,out] p_len \c in: Size of \p p_encoded_data buffer. + * \c out: Length of encoded data. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_PARAM If the operation failed because a wrong parameter was provided in + * \p p_advdata. + * @retval NRF_ERROR_DATA_SIZE If the operation failed because not all the requested data could + * fit into the provided buffer or some encoded AD structure is too + * long and its length cannot be encoded with one octet. + * + * @warning This API may override the application's request to use the long name and use a short name + * instead. This truncation will occur in case the long name does not fit the provided buffer size. + * The application can specify a preferred short name length if truncation is required. + * For example, if the complete device name is ABCD_HRMonitor, the application can specify the short name + * length to be 8, so that the short device name appears as ABCD_HRM instead of ABCD_HRMo or ABCD_HRMoni + * if the available size for the short name is 9 or 12 respectively, to have a more appropriate short name. + * However, it should be noted that this is just a preference that the application can specify, and + * if the preference is too large to fit in the provided buffer, the name can be truncated further. + */ +ret_code_t ble_advdata_encode(ble_advdata_t const * const p_advdata, + uint8_t * const p_encoded_data, + uint16_t * const p_len); + + +/**@brief Function for searching encoded Advertising or Scan Response data for specific data types. + * + * @details This function searches through encoded data e.g. the data produced by + * @ref ble_advdata_encode, or the data found in Advertising reports + * (@ref BLE_GAP_EVT_ADV_REPORT), and gives the offset of the data within the data buffer. + * The data with type \p ad_type can be found at p_encoded_data[*p_offset] after calling + * the function. This function can iterate through multiple instances of data of one + * type by calling it again with the offset provided by the previous call. + * + * Example code for finding multiple instances of one type of data: + * offset = 0; + * ble_advdata_search(&data, len, &offset, AD_TYPE); + * first_instance_of_data = data[offset]; + * ble_advdata_search(&data, len, &offset, AD_TYPE); + * second_instance_of_data = data[offset]; + * + * @param[in] p_encoded_data The data buffer containing the encoded Advertising data. + * @param[in] data_len The length of the data buffer \p p_encoded_data. + * @param[inout] p_offset \c in: The offset to start searching from. + * \c out: The offset the data type can be found at. + * This value is not changed if the call returns 0. + * @param[in] ad_type The type of data to search for. + * + * @return The length of the found data, or 0 if no data was found with the the type \p ad_type, + * or if \p p_encoded_data or \p p_offset were NULL. + */ +uint16_t ble_advdata_search(uint8_t const * p_encoded_data, + uint16_t data_len, + uint16_t * p_offset, + uint8_t ad_type); + +/**@brief Function for getting specific data from encoded Advertising or Scan Response data. + * + * @details This function searches through encoded data e.g. the data produced by + * @ref ble_advdata_encode, or the data found in Advertising reports + * (@ref BLE_GAP_EVT_ADV_REPORT), and returns a pointer directly to the data within the + * data buffer. + * + * Example code: + * ad_type_data = ble_advdata_parse(&data, len, AD_TYPE); + * + * @param[in] p_encoded_data Data buffer containing the encoded Advertising data. + * @param[in] data_len Length of the data buffer \p p_encoded_data. + * @param[in] ad_type Type of data to search for. + * + * @return Pointer to the found data, or NULL if no data was found with the type \p ad_type, + * or if \p p_encoded_data or \p p_data_len were NULL. + */ +uint8_t * ble_advdata_parse(uint8_t * p_encoded_data, + uint16_t data_len, + uint8_t ad_type); + + +/**@brief Function for searching through encoded Advertising data for a complete local name. + * + * @param[in] p_encoded_data Data buffer containing the encoded Advertising data. + * @param[in] data_len Length of the data buffer \p p_encoded_data. + * @param[in] p_target_name Name to search for. + * + * @retval true If \p p_target_name was found among \p p_encoded_data, as a complete local name. + * @retval false If \p p_target_name was not found among \p p_encoded_data, or if \p p_encoded_data + * or \p p_target_name was NULL. + */ +bool ble_advdata_name_find(uint8_t const * p_encoded_data, + uint16_t data_len, + char const * p_target_name); + + +/**@brief Function for searching through encoded Advertising data for a device shortened name. + * + * @param[in] p_encoded_data Data buffer containing the encoded Advertising data. + * @param[in] data_len Length of the data buffer \p p_encoded_data. + * @param[in] p_target_name Name to search for. + * @param[in] short_name_min_len Minimum length of the shortened name. + * For example, if the advertising data has a shortened name 'No' and this parameter is + * set to 4 with a target_name set to Nordic_XXX it will return false, but if + * the shortened name in the advertising data is 'Nord', it will return true. + * @note: If the shortened name in the Advertising data has the same length as the target name, + * this function will return false, since this means that the complete name is actually + * longer, thus different than the target name. + * + * @retval true If \p p_target_name was found among \p p_encoded_data, as short local name. + * @retval false If \p p_target_name was not found among \p p_encoded_data, or if \p p_encoded_data + * or \p p_target_name was NULL. + */ +bool ble_advdata_short_name_find(uint8_t const * p_encoded_data, + uint16_t data_len, + char const * p_target_name, + uint8_t const short_name_min_len); + +/**@brief Function for searching through encoded Advertising data for a UUID (16-bit or 128-bit). + * + * @param[in] p_encoded_data Data buffer containing the encoded Advertising data. + * @param[in] data_len Length of the data buffer \p p_encoded_data. + * @param[in] p_target_uuid UUID to search for. + * + * @retval true If \p p_target_uuid was found among \p p_encoded_data. + * @retval false If \p p_target_uuid was not found among \p p_encoded_data, or if \p p_encoded_data + * or \p p_target_uuid was NULL. + */ +bool ble_advdata_uuid_find(uint8_t const * p_encoded_data, + uint16_t data_len, + ble_uuid_t const * p_target_uuid); + + +/**@brief Function for searching through encoded Advertising data for an appearance. + * + * @param[in] p_encoded_data Data buffer containing the encoded Advertising data. + * @param[in] data_len Length of the data buffer \p p_encoded_data. + * @param[in] p_target_appearance Appearance to search for. + * + * @retval true If \p p_target_appearance was found among \p p_encoded_data. + * @retval false If \p p_target_appearance was not found among \p p_encoded_data, or if \p p_encoded_data + * or \p p_target_appearance was NULL. + */ +bool ble_advdata_appearance_find(uint8_t const * p_encoded_data, + uint16_t data_len, + uint16_t const * p_target_appearance); + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_ADVDATA_H__ + +/** @} */ diff --git a/components/ble/common/ble_conn_params.c b/components/ble/common/ble_conn_params.c new file mode 100644 index 0000000..db61415 --- /dev/null +++ b/components/ble/common/ble_conn_params.c @@ -0,0 +1,575 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_BLE_CONN_PARAMS) +#include +#include "nrf.h" +#include "sdk_errors.h" +#include "ble_hci.h" +#include "ble_err.h" +#include "ble_conn_params.h" +#include "ble_srv_common.h" +#include "ble_conn_state.h" +#include "nrf_sdh_ble.h" +#include "app_timer.h" +#include "app_util.h" + + +#define NRF_BLE_CONN_PARAMS_INSTANCE_COUNT NRF_SDH_BLE_PERIPHERAL_LINK_COUNT //!< The number of @ref ble_conn_params_instance_t instances kept by the conn_params module. + +#if (NRF_BLE_CONN_PARAMS_INSTANCE_COUNT < 1) +#error Invalid NRF_SDH_BLE_PERIPHERAL_LINK_COUNT value. Set it in SDK config (nrf_sdh_ble). +#endif + +/** @brief Each peripheral link has such an instance associated with it. + */ +typedef struct +{ + uint16_t conn_handle; //!< The connection handle of this link. If this is @ref BLE_CONN_HANDLE_INVALID, the instance is free. + app_timer_id_t timer_id; //!< The ID of the timer associated with this link. + uint8_t update_count; //!< The number of times the connection parameters have been attempted negotiated on this link. + uint8_t params_ok; //!< Whether the current connection parameters on this link are acceptable according to the @p preferred_conn_params, and configured maximum deviations. + ble_gap_conn_params_t preferred_conn_params; //!< The desired connection parameters for this link. +} ble_conn_params_instance_t; + +static app_timer_t m_timer_data[NRF_BLE_CONN_PARAMS_INSTANCE_COUNT] = {{{0}}}; //!< Data needed for timers. +static ble_conn_params_instance_t m_conn_params_instances[NRF_BLE_CONN_PARAMS_INSTANCE_COUNT] = {{0}}; //!< Configuration data for each connection. +static ble_conn_params_init_t m_conn_params_config; //!< Configuration as provided by the application during intialization. +static ble_gap_conn_params_t m_preferred_conn_params; //!< The preferred connection parameters as specified during initialization. +//lint -esym(551, m_preferred_conn_params) "Not accessed" + + +/**@brief Function for retrieving the conn_params instance belonging to a conn_handle + * + * @params[in] conn_handle The connection handle to retrieve the instance of. + * + * @return A pointer to the instance, or NULL if no instance was found with that conn_handle. + */ +static ble_conn_params_instance_t * instance_get(uint16_t conn_handle) +{ + //lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_INSTANCE_COUNT is 0 + for (uint32_t i = 0; i < NRF_BLE_CONN_PARAMS_INSTANCE_COUNT; i++) + { + if (m_conn_params_instances[i].conn_handle == conn_handle) + { + return &m_conn_params_instances[i]; + } + } + //lint -restore + return NULL; +} + + +/**@brief Function for initializing an instance, and associating it with a conn_handle. + * + * @params[in] p_instance The instance to initialize and associate. + * @params[in] conn_handle The connection handle to associate with. + */ +static __INLINE void instance_claim(ble_conn_params_instance_t * p_instance, uint16_t conn_handle) +{ + p_instance->conn_handle = conn_handle; + p_instance->update_count = 0; + p_instance->preferred_conn_params = m_preferred_conn_params; +} + + +/**@brief Function for freeing an instance. + * + * @params[in] p_instance The instance to free. + */ +static __INLINE void instance_free(ble_conn_params_instance_t * p_instance) +{ + p_instance->conn_handle = BLE_CONN_HANDLE_INVALID; +} + + +/**@brief Function for validating a set of connection parameters against the preferred parameters. + * + * @param[in] p_preferred_conn_params The desired parameters. + * @param[in] p_actual_conn_params The parameters to validate. + * @param[in] max_slave_latency_err The amount of discrepancy in slave latency, in number of + * connection intervals, that will be accepted. + * @param[in] max_sup_timeout_err The amount of discrepancy in supervision timeout, in tens of + * milliseconds, that will be accepted. + * + * @return Whether the params in @p p_actual_conn_params are acceptable given the other parameters. + */ +static bool is_conn_params_ok(ble_gap_conn_params_t const * p_preferred_conn_params, + ble_gap_conn_params_t const * p_actual_conn_params, + uint16_t max_slave_latency_err, + uint16_t max_sup_timeout_err) +{ + uint32_t max_allowed_sl = p_preferred_conn_params->slave_latency + max_slave_latency_err; + uint32_t min_allowed_sl = p_preferred_conn_params->slave_latency + - MIN(max_slave_latency_err, p_preferred_conn_params->slave_latency); + uint32_t max_allowed_to = p_preferred_conn_params->conn_sup_timeout + max_sup_timeout_err; + uint32_t min_allowed_to = p_preferred_conn_params->conn_sup_timeout + - MIN(max_sup_timeout_err, p_preferred_conn_params->conn_sup_timeout); + + // Check if interval is within the acceptable range. + // NOTE: Using max_conn_interval in the received event data because this contains + // the client's connection interval. + if ((p_actual_conn_params->max_conn_interval < p_preferred_conn_params->min_conn_interval) + || (p_actual_conn_params->max_conn_interval > p_preferred_conn_params->max_conn_interval)) + { + return false; + } + + // Check if slave latency is within the acceptable deviation. + if ((p_actual_conn_params->slave_latency < min_allowed_sl) + || (p_actual_conn_params->slave_latency > max_allowed_sl)) + { + return false; + } + + // Check if supervision timeout is within the acceptable deviation. + if ((p_actual_conn_params->conn_sup_timeout < min_allowed_to) + || (p_actual_conn_params->conn_sup_timeout > max_allowed_to)) + { + return false; + } + + return true; +} + + +static void send_error_evt(ret_code_t err_code) +{ + if (m_conn_params_config.error_handler != NULL) + { + m_conn_params_config.error_handler(err_code); + } +} + + +/**@brief Function for sending a conn_param_update request on-air, and handling errors. + * + * @param[in] conn_handle Connection to send request on. + * @param[in] p_new_conn_params Connection parameters to request. + * + * @return Whether the request was successfully sent. + */ +static bool send_update_request(uint16_t conn_handle, ble_gap_conn_params_t * p_new_conn_params) +{ + ret_code_t err_code; + + err_code = sd_ble_gap_conn_param_update(conn_handle, p_new_conn_params); + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) // NRF_ERROR_BUSY means another conn_param_update request is pending. + { + send_error_evt(err_code); + } + + return (err_code == NRF_SUCCESS); +} + + +/**@brief Function called after conn_params_update_delay has happened. This is triggered by app_timer. + * + * @param[in] p_context Context identifying which connection this is for. + */ +static void update_timeout_handler(void * p_context) +{ + uint32_t conn_handle = (uint32_t)p_context; + ble_conn_params_instance_t * p_instance = instance_get(conn_handle); + + if (p_instance != NULL) + { + // Check if we have reached the maximum number of attempts + if (p_instance->update_count < m_conn_params_config.max_conn_params_update_count) + { + bool update_sent = send_update_request(conn_handle, &p_instance->preferred_conn_params); + if (update_sent) + { + p_instance->update_count++; + } + } + else + { + p_instance->update_count = 0; + + // Negotiation failed, disconnect automatically if this has been configured + if (m_conn_params_config.disconnect_on_fail) + { + ret_code_t err_code; + + err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) // NRF_ERROR_INVALID_STATE means disconnect is already in progress. + { + send_error_evt(err_code); + } + } + + // Notify the application that the procedure has failed + if (m_conn_params_config.evt_handler != NULL) + { + ble_conn_params_evt_t evt; + + evt.evt_type = BLE_CONN_PARAMS_EVT_FAILED; + evt.conn_handle = conn_handle; + m_conn_params_config.evt_handler(&evt); + } + } + } +} + + +ret_code_t ble_conn_params_init(const ble_conn_params_init_t * p_init) +{ + ret_code_t err_code; + + VERIFY_PARAM_NOT_NULL(p_init); + + m_conn_params_config = *p_init; + m_conn_params_config.p_conn_params = &m_preferred_conn_params; + + if (p_init->p_conn_params != NULL) + { + // Set the connection params in stack. + err_code = sd_ble_gap_ppcp_set(p_init->p_conn_params); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + m_preferred_conn_params = *p_init->p_conn_params; + } + else + { + // Get the (default) connection params from stack. + err_code = sd_ble_gap_ppcp_get(&m_preferred_conn_params); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + } + + //lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_INSTANCE_COUNT is 0 + for (uint32_t i = 0; i < NRF_BLE_CONN_PARAMS_INSTANCE_COUNT; i++) + { + ble_conn_params_instance_t * p_instance = &m_conn_params_instances[i]; + + instance_free(p_instance); + p_instance->timer_id = &m_timer_data[i]; + + err_code = app_timer_create(&p_instance->timer_id, + APP_TIMER_MODE_SINGLE_SHOT, + update_timeout_handler); + if (err_code != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + } + //lint -restore + + return NRF_SUCCESS; +} + + +ret_code_t ble_conn_params_stop(void) +{ + ret_code_t err_code; + + //lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_INSTANCE_COUNT is 0 + for (uint32_t i = 0; i < NRF_BLE_CONN_PARAMS_INSTANCE_COUNT; i++) + { + err_code = app_timer_stop(m_conn_params_instances[i].timer_id); + switch (err_code) + { + case NRF_SUCCESS: + /* do nothing */ + break; + + case NRF_ERROR_INVALID_STATE: + /* do nothing */ + break; + + case NRF_ERROR_NO_MEM: + return NRF_ERROR_BUSY; + + case NRF_ERROR_INVALID_PARAM: + /* fallthrough */ + default: + return NRF_ERROR_INTERNAL; + } + } + //lint -restore + return NRF_SUCCESS; +} + + +/**@brief Function for taking appropriate action based on the current state of connection parameters. + * + * @param[in] conn_handle Connection to handle. + * @param[in] p_instance Configuration for the connection. + */ +static void conn_params_negotiation(uint16_t conn_handle, ble_conn_params_instance_t * p_instance) + { + // Start negotiation if the received connection parameters are not acceptable + if (!p_instance->params_ok) + { + ret_code_t err_code; + uint32_t timeout_ticks; + + if (p_instance->update_count == 0) + { + // First connection parameter update + timeout_ticks = m_conn_params_config.first_conn_params_update_delay; + } + else + { + timeout_ticks = m_conn_params_config.next_conn_params_update_delay; + } + + err_code = app_timer_start(p_instance->timer_id, timeout_ticks, (void *)(uint32_t)conn_handle); + if (err_code != NRF_SUCCESS) + { + send_error_evt(err_code); + } + } + else + { + p_instance->update_count = 0; + + // Notify the application that the procedure has succeeded + if (m_conn_params_config.evt_handler != NULL) + { + ble_conn_params_evt_t evt; + + evt.evt_type = BLE_CONN_PARAMS_EVT_SUCCEEDED; + evt.conn_handle = conn_handle; + m_conn_params_config.evt_handler(&evt); + } + } +} + + +/**@brief Function for handling a connection event from the SoftDevice. + * + * @param[in] p_ble_evt Event from the SoftDevice. + */ +static void on_connect(ble_evt_t const * p_ble_evt) +{ + uint8_t role = p_ble_evt->evt.gap_evt.params.connected.role; + uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + + if (role != BLE_GAP_ROLE_PERIPH) + { + return; + } + + ble_conn_params_instance_t * p_instance = instance_get(BLE_CONN_HANDLE_INVALID); + + if (p_instance == NULL) + { + send_error_evt(NRF_ERROR_NO_MEM); + return; + } + + instance_claim(p_instance, conn_handle); + p_instance->params_ok = is_conn_params_ok(&p_instance->preferred_conn_params, + &p_ble_evt->evt.gap_evt.params.connected.conn_params, + NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION, + NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION); + + // Check if we shall handle negotiation on connect + if (m_conn_params_config.start_on_notify_cccd_handle == BLE_GATT_HANDLE_INVALID) + { + conn_params_negotiation(conn_handle, p_instance); + } +} + + +/**@brief Function for handling a disconnection event from the SoftDevice. + * + * @param[in] p_ble_evt Event from the SoftDevice. + */ +static void on_disconnect(ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + ble_conn_params_instance_t * p_instance = instance_get(conn_handle); + + if (p_instance != NULL) + { + // Stop timer if running + err_code = app_timer_stop(p_instance->timer_id); + if (err_code != NRF_SUCCESS) + { + send_error_evt(err_code); + } + + instance_free(p_instance); + } + + + +} + + +/**@brief Function for handling a GATT write event from the SoftDevice. + * + * @details To provide the start_on_notify_cccd_handle functionality. + * + * @param[in] p_ble_evt Event from the SoftDevice. + */ +static void on_write(ble_evt_t const * p_ble_evt) +{ + ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; + + // Check if this is the correct CCCD + if ( + (p_evt_write->handle == m_conn_params_config.start_on_notify_cccd_handle) + && + (p_evt_write->len == 2) + ) + { + uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + ble_conn_params_instance_t * p_instance = instance_get(conn_handle); + + if (p_instance != NULL) + { + // Check if this is a 'start notification' + if (ble_srv_is_notification_enabled(p_evt_write->data)) + { + // Do connection parameter negotiation if necessary + conn_params_negotiation(conn_handle, p_instance); + } + else + { + ret_code_t err_code; + + // Stop timer if running + err_code = app_timer_stop(p_instance->timer_id); + if (err_code != NRF_SUCCESS) + { + send_error_evt(err_code); + } + } + } + } +} + + +/**@brief Function for handling a connection parameter update event from the SoftDevice. + * + * @details This event means the peer central has changed the connection parameters or declined our + * request. + * + * @param[in] p_ble_evt Event from the SoftDevice. + */ +static void on_conn_params_update(ble_evt_t const * p_ble_evt) +{ + uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + ble_conn_params_instance_t * p_instance = instance_get(conn_handle); + + if (p_instance != NULL) + { + p_instance->params_ok = is_conn_params_ok( + &p_instance->preferred_conn_params, + &p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params, + NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION, + NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION); + + conn_params_negotiation(conn_handle, p_instance); + } +} + + +/** + * @brief Function for handling BLE events. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context Context. + */ +static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) +{ + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + on_connect(p_ble_evt); + break; + + case BLE_GAP_EVT_DISCONNECTED: + on_disconnect(p_ble_evt); + break; + + case BLE_GATTS_EVT_WRITE: + on_write(p_ble_evt); + break; + + case BLE_GAP_EVT_CONN_PARAM_UPDATE: + on_conn_params_update(p_ble_evt); + break; + + default: + // No implementation needed. + break; + } +} + + +ret_code_t ble_conn_params_change_conn_params(uint16_t conn_handle, + ble_gap_conn_params_t * p_new_params) +{ + ret_code_t err_code = BLE_ERROR_INVALID_CONN_HANDLE; + ble_conn_params_instance_t * p_instance = instance_get(conn_handle); + + if (p_new_params == NULL) + { + p_new_params = &m_preferred_conn_params; + } + + if (p_instance != NULL) + { + // Send request to central. + err_code = sd_ble_gap_conn_param_update(conn_handle, p_new_params); + if (err_code == NRF_SUCCESS) + { + p_instance->params_ok = false; + p_instance->update_count = 1; + p_instance->preferred_conn_params = *p_new_params; + } + } + + return err_code; +} + +NRF_SDH_BLE_OBSERVER(m_ble_observer, BLE_CONN_PARAMS_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); + +#endif //ENABLED diff --git a/components/ble/common/ble_conn_params.h b/components/ble/common/ble_conn_params.h new file mode 100644 index 0000000..e4049fc --- /dev/null +++ b/components/ble/common/ble_conn_params.h @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup ble_conn_params Connection Parameters Negotiation + * @{ + * @ingroup ble_sdk_lib + * @brief Module for initiating and executing a connection parameters negotiation procedure. + */ + +#ifndef BLE_CONN_PARAMS_H__ +#define BLE_CONN_PARAMS_H__ + +#include +#include "ble.h" +#include "ble_srv_common.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Connection Parameters Module event type. */ +typedef enum +{ + BLE_CONN_PARAMS_EVT_FAILED, //!< Negotiation procedure failed. + BLE_CONN_PARAMS_EVT_SUCCEEDED //!< Negotiation procedure succeeded. +} ble_conn_params_evt_type_t; + +/**@brief Connection Parameters Module event. */ +typedef struct +{ + ble_conn_params_evt_type_t evt_type; //!< Type of event. + uint16_t conn_handle; //!< Connection the event refers to. +} ble_conn_params_evt_t; + +/**@brief Connection Parameters Module event handler type. */ +typedef void (*ble_conn_params_evt_handler_t) (ble_conn_params_evt_t * p_evt); + +/**@brief Connection Parameters Module init structure. This contains all options and data needed for + * initialization of the connection parameters negotiation module. */ +typedef struct +{ + ble_gap_conn_params_t * p_conn_params; //!< Pointer to the connection parameters desired by the application. When calling ble_conn_params_init, if this parameter is set to NULL, the connection parameters will be fetched from host. + uint32_t first_conn_params_update_delay; //!< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (in number of timer ticks). + uint32_t next_conn_params_update_delay; //!< Time between each call to sd_ble_gap_conn_param_update after the first (in number of timer ticks). Recommended value 30 seconds as per BLUETOOTH SPECIFICATION Version 4.0. + uint8_t max_conn_params_update_count; //!< Number of attempts before giving up the negotiation. + uint16_t start_on_notify_cccd_handle; //!< If procedure is to be started when notification is started, set this to the handle of the corresponding CCCD. Set to BLE_GATT_HANDLE_INVALID if procedure is to be started on connect event. + bool disconnect_on_fail; //!< Set to TRUE if a failed connection parameters update shall cause an automatic disconnection, set to FALSE otherwise. + ble_conn_params_evt_handler_t evt_handler; //!< Event handler to be called for handling events in the Connection Parameters. + ble_srv_error_handler_t error_handler; //!< Function to be called in case of an error. +} ble_conn_params_init_t; + + +/**@brief Function for initializing the Connection Parameters module. + * + * @note If the negotiation procedure should be triggered when notification/indication of + * any characteristic is enabled by the peer, then this function must be called after + * having initialized the services. + * + * @param[in] p_init This contains information needed to initialize this module. + * + * @retval NRF_SUCCESS Successful initialization. + * @retval NRF_ERROR_INVALID_ADDR The provided Connection Parameters pointer is invalid. + * @retval NRF_ERROR_INVALID_PARAM The provided Connection Parameters are not valid. + * @retval NRF_ERROR_NULL @p p_init was NULL. + * @retval NRF_ERROR_INTERNAL An unexpected error occurred. + */ +ret_code_t ble_conn_params_init(const ble_conn_params_init_t * p_init); + +/**@brief Function for stopping the Connection Parameters module. + * + * @details This function is intended to be used by the application to clean up the connection + * parameters update module. This will stop the connection parameters update timer if + * running, thereby preventing any impending connection parameters update procedure. This + * function must be called by the application when it needs to clean itself up (for + * example, before disabling the bluetooth SoftDevice) so that an unwanted timer expiry + * event can be avoided. + * + * @retval NRF_SUCCESS Successfully stopped module. + * @retval NRF_ERROR_BUSY Could not complete operation at this time. Try again later. + Note that some timers may have been disabled. + * @retval NRF_ERROR_INTERNAL An unexpected error occurred. + */ +ret_code_t ble_conn_params_stop(void); + +/**@brief Function for changing the current connection parameters to a new set. + * + * @details Use this function to change the connection parameters to a new set of parameter + * (ie different from the ones given at init of the module). + * This function is useful for scenario where most of the time the application + * needs a relatively big connection interval, and just sometimes, for a temporary + * period requires shorter connection interval, for example to transfer a higher + * amount of data. + * If the given parameters does not match the current connection's parameters + * this function initiates a new negotiation. + * + * @param[in] conn_handle The connection to change connection parameters on. + * @param[in] p_new_params This contains the new connections parameters to setup. + * + * @retval NRF_SUCCESS Successfully started Connection Parameter update procedure. + * @retval NRF_ERROR_INVALID_ADDR The provided Connection Parameters pointer is invalid. + * @retval NRF_ERROR_INVALID_PARAM The provided Connection Parameters are not valid. + * @retval BLE_ERROR_INVALID_CONN_HANDLE The provided connection handle is invalid. + * @retval NRF_ERROR_INVALID_STATE The connection is not in a state where this operation can + * performed. + * @retval NRF_ERROR_BUSY Could not start operation at this time. Try again later. + * @retval NRF_ERROR_NO_MEM The SoftDevice lacks the memory to perform the action. + */ +ret_code_t ble_conn_params_change_conn_params(uint16_t conn_handle, + ble_gap_conn_params_t * p_new_params); + +#ifdef __cplusplus +} +#endif + +#endif // BLE_CONN_PARAMS_H__ + +/** @} */ diff --git a/components/ble/common/ble_conn_state.c b/components/ble/common/ble_conn_state.c new file mode 100644 index 0000000..7c285dd --- /dev/null +++ b/components/ble/common/ble_conn_state.c @@ -0,0 +1,497 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "ble_conn_state.h" +#include +#include +#include +#include "ble.h" +#include "nrf_atflags.h" +#include "app_error.h" +#include "nrf_sdh_ble.h" +#include "app_util_platform.h" + + + +#define DEFAULT_FLAG_COLLECTION_COUNT 6 /**< The number of flags kept for each connection, excluding user flags. */ +#define TOTAL_FLAG_COLLECTION_COUNT (DEFAULT_FLAG_COLLECTION_COUNT \ + + BLE_CONN_STATE_USER_FLAG_COUNT) /**< The number of flags kept for each connection, including user flags. */ + +/**@brief Structure containing all the flag collections maintained by the Connection State module. + */ +typedef struct +{ + nrf_atflags_t valid_flags; /**< Flags indicating which connection handles are valid. */ + nrf_atflags_t connected_flags; /**< Flags indicating which connections are connected, since disconnected connection handles will not immediately be invalidated. */ + nrf_atflags_t central_flags; /**< Flags indicating in which connections the local device is the central. */ + nrf_atflags_t encrypted_flags; /**< Flags indicating which connections are encrypted. */ + nrf_atflags_t mitm_protected_flags; /**< Flags indicating which connections have encryption with protection from man-in-the-middle attacks. */ + nrf_atflags_t lesc_flags; /**< Flags indicating which connections have bonded using LE Secure Connections (LESC). */ + nrf_atflags_t user_flags[BLE_CONN_STATE_USER_FLAG_COUNT]; /**< Flags that can be reserved by the user. The flags will be cleared when a connection is invalidated, otherwise, the user is wholly responsible for the flag states. */ +} ble_conn_state_flag_collections_t; + + +ANON_UNIONS_ENABLE; + +/**@brief Structure containing the internal state of the Connection State module. + */ +typedef struct +{ + nrf_atflags_t acquired_flags; /**< Bitmap for keeping track of which user flags have been acquired. */ + union + { + ble_conn_state_flag_collections_t flags; /**< Flag collections kept by the Connection State module. */ + nrf_atflags_t flag_array[TOTAL_FLAG_COLLECTION_COUNT]; /**< Flag collections as array to allow iterating over all flag collections. */ + }; +} ble_conn_state_t; + +ANON_UNIONS_DISABLE; + + +static ble_conn_state_t m_bcs = {0}; /**< Instantiation of the internal state. */ + + +/**@brief Function for resetting all internal memory to the values it had at initialization. + */ +void bcs_internal_state_reset(void) +{ + memset( &m_bcs, 0, sizeof(ble_conn_state_t) ); +} + + +ble_conn_state_conn_handle_list_t conn_handle_list_get(nrf_atflags_t flags) +{ + ble_conn_state_conn_handle_list_t conn_handle_list; + conn_handle_list.len = 0; + + if (flags != 0) + { + for (uint32_t i = 0; i < BLE_CONN_STATE_MAX_CONNECTIONS; i++) + { + if (nrf_atflags_get(&flags, i)) + { + conn_handle_list.conn_handles[conn_handle_list.len++] = i; + } + } + } + + return conn_handle_list; +} + + +uint32_t active_flag_count(nrf_atflags_t flags) +{ + uint32_t set_flag_count = 0; + + for (uint32_t i = 0; i < BLE_CONN_STATE_MAX_CONNECTIONS; i++) + { + if (nrf_atflags_get(&flags, i)) + { + set_flag_count += 1; + } + } + return set_flag_count; +} + + +/**@brief Function for activating a connection record. + * + * @param p_record The record to activate. + * @param conn_handle The connection handle to copy into the record. + * @param role The role of the connection. + * + * @return whether the record was activated successfully. + */ +static bool record_activate(uint16_t conn_handle) +{ + if (conn_handle >= BLE_CONN_STATE_MAX_CONNECTIONS) + { + return false; + } + nrf_atflags_set(&m_bcs.flags.connected_flags, conn_handle); + nrf_atflags_set(&m_bcs.flags.valid_flags, conn_handle); + return true; +} + + +/**@brief Function for marking a connection record as invalid and resetting the values. + * + * @param p_record The record to invalidate. + */ +static void record_invalidate(uint16_t conn_handle) +{ + for (uint32_t i = 0; i < TOTAL_FLAG_COLLECTION_COUNT; i++) + { + nrf_atflags_clear(&m_bcs.flag_array[i], conn_handle); + } +} + + +/**@brief Function for marking a connection as disconnected. See @ref BLE_CONN_STATUS_DISCONNECTED. + * + * @param p_record The record of the connection to set as disconnected. + */ +static void record_set_disconnected(uint16_t conn_handle) +{ + nrf_atflags_clear(&m_bcs.flags.connected_flags, conn_handle); +} + + +/**@brief Function for invalidating records with a @ref BLE_CONN_STATUS_DISCONNECTED + * connection status + */ +static void record_purge_disconnected() +{ + nrf_atflags_t disconnected_flags = ~m_bcs.flags.connected_flags; + ble_conn_state_conn_handle_list_t disconnected_list; + + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&disconnected_flags, m_bcs.flags.valid_flags)); + disconnected_list = conn_handle_list_get(disconnected_flags); + + for (uint32_t i = 0; i < disconnected_list.len; i++) + { + record_invalidate(disconnected_list.conn_handles[i]); + } +} + + +/**@brief Function for checking if a user flag has been acquired. + * + * @param[in] flag_id Which flag to check. + * + * @return Whether the flag has been acquired. + */ +static bool user_flag_is_acquired(ble_conn_state_user_flag_id_t flag_id) +{ + return nrf_atflags_get(&m_bcs.acquired_flags, flag_id); +} + + +void ble_conn_state_init(void) +{ + bcs_internal_state_reset(); +} + +static void flag_toggle(nrf_atflags_t * p_flags, uint16_t conn_handle, bool value) +{ + if (value) + { + nrf_atflags_set(p_flags, conn_handle); + } + else + { + nrf_atflags_clear(p_flags, conn_handle); + } +} + +/** + * @brief Function for handling BLE events. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context Context. + */ +static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) +{ + uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + record_purge_disconnected(); + + if ( !record_activate(conn_handle) ) + { + // No more records available. Should not happen. + APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); + } +#ifdef BLE_GAP_ROLE_CENTRAL + else if ((p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_CENTRAL)) + { + // Central + nrf_atflags_set(&m_bcs.flags.central_flags, conn_handle); + } +#endif // BLE_GAP_ROLE_CENTRAL + else + { + // No implementation required. + } + + break; + + case BLE_GAP_EVT_DISCONNECTED: + record_set_disconnected(conn_handle); + break; + + case BLE_GAP_EVT_CONN_SEC_UPDATE: + { + uint8_t sec_lv = p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv; + // Set/unset flags based on security level. + flag_toggle(&m_bcs.flags.lesc_flags, conn_handle, sec_lv >= 4); + flag_toggle(&m_bcs.flags.mitm_protected_flags, conn_handle, sec_lv >= 3); + flag_toggle(&m_bcs.flags.encrypted_flags, conn_handle, sec_lv >= 2); + break; + } + + case BLE_GAP_EVT_AUTH_STATUS: + if (p_ble_evt->evt.gap_evt.params.auth_status.auth_status == BLE_GAP_SEC_STATUS_SUCCESS) + { + bool lesc = p_ble_evt->evt.gap_evt.params.auth_status.lesc; + flag_toggle(&m_bcs.flags.lesc_flags, conn_handle, lesc); + } + break; + } +} + +NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, BLE_CONN_STATE_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); + + +bool ble_conn_state_valid(uint16_t conn_handle) +{ + if (conn_handle >= BLE_CONN_STATE_MAX_CONNECTIONS) + { + return false; + } + return nrf_atflags_get(&m_bcs.flags.valid_flags, conn_handle); +} + + +uint8_t ble_conn_state_role(uint16_t conn_handle) +{ + uint8_t role = BLE_GAP_ROLE_INVALID; + + if (ble_conn_state_valid(conn_handle)) + { +#if defined (BLE_GAP_ROLE_PERIPH) && defined (BLE_GAP_ROLE_CENTRAL) + bool central = nrf_atflags_get(&m_bcs.flags.central_flags, conn_handle); + role = central ? BLE_GAP_ROLE_CENTRAL : BLE_GAP_ROLE_PERIPH; +#elif defined (BLE_GAP_ROLE_CENTRAL) + role = BLE_GAP_ROLE_CENTRAL; +#else + role = BLE_GAP_ROLE_PERIPH; +#endif // defined (BLE_GAP_ROLE_PERIPH) && defined (BLE_GAP_ROLE_CENTRAL) + } + + return role; +} + + +ble_conn_state_status_t ble_conn_state_status(uint16_t conn_handle) +{ + ble_conn_state_status_t conn_status = BLE_CONN_STATUS_INVALID; + + if (ble_conn_state_valid(conn_handle)) + { + bool connected = nrf_atflags_get(&m_bcs.flags.connected_flags, conn_handle); + conn_status = connected ? BLE_CONN_STATUS_CONNECTED : BLE_CONN_STATUS_DISCONNECTED; + } + + return conn_status; +} + + +bool ble_conn_state_encrypted(uint16_t conn_handle) +{ + if (ble_conn_state_valid(conn_handle)) + { + return nrf_atflags_get(&m_bcs.flags.encrypted_flags, conn_handle); + } + return false; +} + + +bool ble_conn_state_mitm_protected(uint16_t conn_handle) +{ + if (ble_conn_state_valid(conn_handle)) + { + return nrf_atflags_get(&m_bcs.flags.mitm_protected_flags, conn_handle); + } + return false; +} + +bool ble_conn_state_lesc(uint16_t conn_handle) +{ + if (ble_conn_state_valid(conn_handle)) + { + return nrf_atflags_get(&m_bcs.flags.lesc_flags, conn_handle); + } + return false; +} + + +uint32_t ble_conn_state_conn_count(void) +{ + return active_flag_count(m_bcs.flags.connected_flags); +} + + +uint32_t ble_conn_state_central_conn_count(void) +{ + nrf_atflags_t central_conn_flags = m_bcs.flags.central_flags; + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(¢ral_conn_flags, m_bcs.flags.connected_flags)); + + return active_flag_count(central_conn_flags); +} + + +uint32_t ble_conn_state_peripheral_conn_count(void) +{ + nrf_atflags_t peripheral_conn_flags = ~m_bcs.flags.central_flags; + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&peripheral_conn_flags, m_bcs.flags.connected_flags)); + + return active_flag_count(peripheral_conn_flags); +} + + +ble_conn_state_conn_handle_list_t ble_conn_state_conn_handles(void) +{ + return conn_handle_list_get(m_bcs.flags.valid_flags); +} + + +ble_conn_state_conn_handle_list_t ble_conn_state_central_handles(void) +{ + nrf_atflags_t central_conn_flags = m_bcs.flags.central_flags; + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(¢ral_conn_flags, m_bcs.flags.connected_flags)); + + return conn_handle_list_get(central_conn_flags); +} + + +ble_conn_state_conn_handle_list_t ble_conn_state_periph_handles(void) +{ + nrf_atflags_t peripheral_conn_flags = ~m_bcs.flags.central_flags; + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&peripheral_conn_flags, m_bcs.flags.connected_flags)); + + return conn_handle_list_get(peripheral_conn_flags); +} + + +uint16_t ble_conn_state_conn_idx(uint16_t conn_handle) +{ + if (ble_conn_state_valid(conn_handle)) + { + return conn_handle; + } + else + { + return BLE_CONN_STATE_MAX_CONNECTIONS; + } +} + + +ble_conn_state_user_flag_id_t ble_conn_state_user_flag_acquire(void) +{ + uint32_t acquired_flag = nrf_atflags_find_and_set_flag(&m_bcs.acquired_flags, + BLE_CONN_STATE_USER_FLAG_COUNT); + + if (acquired_flag == BLE_CONN_STATE_USER_FLAG_COUNT) + { + return BLE_CONN_STATE_USER_FLAG_INVALID; + } + return (ble_conn_state_user_flag_id_t)acquired_flag; +} + + +bool ble_conn_state_user_flag_get(uint16_t conn_handle, ble_conn_state_user_flag_id_t flag_id) +{ + if (user_flag_is_acquired(flag_id) && ble_conn_state_valid(conn_handle)) + { + return nrf_atflags_get(&m_bcs.flags.user_flags[flag_id], conn_handle); + } + else + { + return false; + } +} + + +void ble_conn_state_user_flag_set(uint16_t conn_handle, + ble_conn_state_user_flag_id_t flag_id, + bool value) +{ + if (user_flag_is_acquired(flag_id) && ble_conn_state_valid(conn_handle)) + { + flag_toggle(&m_bcs.flags.user_flags[flag_id], conn_handle, value); + } +} + + +static uint32_t for_each_set_flag(nrf_atflags_t flags, + ble_conn_state_user_function_t user_function, + void * p_context) +{ + if (user_function == NULL) + { + return 0; + } + + uint32_t call_count = 0; + + if (flags != 0) + { + for (uint32_t i = 0; i < BLE_CONN_STATE_MAX_CONNECTIONS; i++) + { + if (nrf_atflags_get(&flags, i)) + { + user_function(i, p_context); + call_count += 1; + } + } + } + return call_count; +} + + +uint32_t ble_conn_state_for_each_connected(ble_conn_state_user_function_t user_function, + void * p_context) +{ + return for_each_set_flag(m_bcs.flags.connected_flags, user_function, p_context); +} + + +uint32_t ble_conn_state_for_each_set_user_flag(ble_conn_state_user_flag_id_t flag_id, + ble_conn_state_user_function_t user_function, + void * p_context) +{ + if (!user_flag_is_acquired(flag_id)) + { + return 0; + } + + return for_each_set_flag(m_bcs.flags.user_flags[flag_id], user_function, p_context); +} diff --git a/components/ble/common/ble_conn_state.h b/components/ble/common/ble_conn_state.h new file mode 100644 index 0000000..88386e6 --- /dev/null +++ b/components/ble/common/ble_conn_state.h @@ -0,0 +1,361 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * @file + * + * @defgroup ble_conn_state Connection state + * @ingroup ble_sdk_lib + * @{ + * @brief Module for storing data on BLE connections. + * + * @details This module stores certain states for each connection, which can be queried by + * connection handle. The module uses BLE events to keep the states updated. + * + * In addition to the preprogrammed states, this module can also keep track of a number of + * binary user states, or user flags. These are reset to 0 for new connections, but + * otherwise not touched by this module. + * + * This module uses the @ref nrf_atomic module to make the flag operations thread-safe. + * + * @note A connection handle is not immediately invalidated when it is disconnected. Certain states, + * such as the role, can still be queried until the next time a new connection is established + * to any device. + * + */ + +#ifndef BLE_CONN_STATE_H__ +#define BLE_CONN_STATE_H__ + +#include +#include +#include "ble.h" +#include "ble_gap.h" +#include "nrf_atomic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Connection handle statuses. + */ +typedef enum +{ + BLE_CONN_STATUS_INVALID, /**< The connection handle is invalid. */ + BLE_CONN_STATUS_DISCONNECTED, /**< The connection handle refers to a connection that has been disconnected, but not yet invalidated. */ + BLE_CONN_STATUS_CONNECTED, /**< The connection handle refers to an active connection. */ +} ble_conn_state_status_t; + +#define BLE_CONN_STATE_MAX_CONNECTIONS BLE_GAP_ROLE_COUNT_COMBINED_MAX /**< The maximum number of connections supported. */ +#define BLE_CONN_STATE_USER_FLAG_COUNT 24 /**< The number of available user flags. */ + + +/**@brief Type used to present a list of conn_handles. + */ +typedef struct +{ + uint32_t len; /**< The length of the list. */ + uint16_t conn_handles[BLE_CONN_STATE_MAX_CONNECTIONS]; /**< The list of handles. */ +} ble_conn_state_conn_handle_list_t; + +/**@brief One ID for each user flag collection. + * + * @details These IDs are used to identify user flag collections in the API calls. + */ +typedef enum +{ + BLE_CONN_STATE_USER_FLAG0 = 0, + BLE_CONN_STATE_USER_FLAG1, + BLE_CONN_STATE_USER_FLAG2, + BLE_CONN_STATE_USER_FLAG3, + BLE_CONN_STATE_USER_FLAG4, + BLE_CONN_STATE_USER_FLAG5, + BLE_CONN_STATE_USER_FLAG6, + BLE_CONN_STATE_USER_FLAG7, + BLE_CONN_STATE_USER_FLAG8, + BLE_CONN_STATE_USER_FLAG9, + BLE_CONN_STATE_USER_FLAG10, + BLE_CONN_STATE_USER_FLAG11, + BLE_CONN_STATE_USER_FLAG12, + BLE_CONN_STATE_USER_FLAG13, + BLE_CONN_STATE_USER_FLAG14, + BLE_CONN_STATE_USER_FLAG15, + BLE_CONN_STATE_USER_FLAG16, + BLE_CONN_STATE_USER_FLAG17, + BLE_CONN_STATE_USER_FLAG18, + BLE_CONN_STATE_USER_FLAG19, + BLE_CONN_STATE_USER_FLAG20, + BLE_CONN_STATE_USER_FLAG21, + BLE_CONN_STATE_USER_FLAG22, + BLE_CONN_STATE_USER_FLAG23, + BLE_CONN_STATE_USER_FLAG_INVALID, +} ble_conn_state_user_flag_id_t; + + +/**@brief Function to be called when a flag ID is set. See @ref ble_conn_state_for_each_set_user_flag. + * + * @param[in] conn_handle The connection the flag is set for. + * @param[in] p_context Arbitrary pointer provided by the caller of + * @ref ble_conn_state_for_each_set_user_flag. + */ +typedef void (*ble_conn_state_user_function_t)(uint16_t conn_handle, void * p_context); + + +/** + * @defgroup ble_conn_state_functions BLE connection state functions + * @{ + */ + + +/**@brief Function for initializing or resetting the module. + * + * @details This function sets all states to their default, removing all records of connection handles. + */ +void ble_conn_state_init(void); + + +/**@brief Function for querying whether a connection handle represents a valid connection. + * + * @details A connection might be valid and have a BLE_CONN_STATUS_DISCONNECTED status. + * Those connections are invalidated after a new connection occurs. + * + * @param[in] conn_handle Handle of the connection. + * + * @retval true If conn_handle represents a valid connection, thus a connection for which + we have a record. + * @retval false If conn_handle is @ref BLE_GAP_ROLE_INVALID, or if it has never been recorded. + */ +bool ble_conn_state_valid(uint16_t conn_handle); + + +/**@brief Function for querying the role of the local device in a connection. + * + * @param[in] conn_handle Handle of the connection to get the role for. + * + * @return The role of the local device in the connection (see @ref BLE_GAP_ROLES). + * If conn_handle is not valid, the function returns BLE_GAP_ROLE_INVALID. + */ +uint8_t ble_conn_state_role(uint16_t conn_handle); + + +/**@brief Function for querying the status of a connection. + * + * @param[in] conn_handle Handle of the connection. + * + * @return The status of the connection. + * If conn_handle is not valid, the function returns BLE_CONN_STATE_INVALID. + */ +ble_conn_state_status_t ble_conn_state_status(uint16_t conn_handle); + + +/**@brief Function for querying whether a connection is encrypted. + * + * @param[in] conn_handle Handle of connection to get the encryption state for. + * + * @retval true If the connection is encrypted. + * @retval false If the connection is not encrypted or conn_handle is invalid. + */ +bool ble_conn_state_encrypted(uint16_t conn_handle); + + +/**@brief Function for querying whether a connection encryption is protected from Man in the Middle + * attacks. + * + * @param[in] conn_handle Handle of connection to get the MITM state for. + * + * @retval true If the connection is encrypted with MITM protection. + * @retval false If the connection is not encrypted, or encryption is not MITM protected, or + * conn_handle is invalid. + */ +bool ble_conn_state_mitm_protected(uint16_t conn_handle); + + +/**@brief Function for querying whether a connection was bonded using LE Secure Connections (LESC). + * + * The connection must currently be encrypted. + * + * @note This function will report false if bonded, and the LESC bonding was unauthenticated + * ("Just Works") and happened in a previous connection. To detect such cases as well, check + * the stored bonding key, e.g. in Peer Manager, which has a LESC flag associated with it. + * + * @param[in] conn_handle Handle of connection to get the LESC state for. + * + * @retval true If the connection was bonded using LESC. + * @retval false If the connection has not been bonded using LESC, or conn_handle is invalid. + */ +bool ble_conn_state_lesc(uint16_t conn_handle); + + +/**@brief Function for querying the total number of connections. + * + * @return The total number of valid connections for which the module has a record. + */ +uint32_t ble_conn_state_conn_count(void); + + +/**@brief Function for querying the total number of connections in which the role of the local + * device is @ref BLE_GAP_ROLE_CENTRAL. + * + * @return The number of connections in which the role of the local device is + * @ref BLE_GAP_ROLE_CENTRAL. + */ +uint32_t ble_conn_state_central_conn_count(void); + + +/**@brief Function for querying the total number of connections in which the role of the local + * device is @ref BLE_GAP_ROLE_PERIPH. + * + * @return The number of connections in which the role of the local device is + * @ref BLE_GAP_ROLE_PERIPH. + */ +uint32_t ble_conn_state_peripheral_conn_count(void); + + +/**@brief Function for obtaining a list of all connection handles for which the module has a record. + * + * @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED. + * + * @return A list of all valid connection handles for which the module has a record. + */ +ble_conn_state_conn_handle_list_t ble_conn_state_conn_handles(void); + + +/**@brief Function for obtaining a list of connection handles in which the role of the local + * device is @ref BLE_GAP_ROLE_CENTRAL. + * + * @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED. + * + * @return A list of all valid connection handles for which the module has a record and in which + * the role of local device is @ref BLE_GAP_ROLE_CENTRAL. + */ +ble_conn_state_conn_handle_list_t ble_conn_state_central_handles(void); + + +/**@brief Function for obtaining the handle for the connection in which the role of the local device + * is @ref BLE_GAP_ROLE_PERIPH. + * + * @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED. + * + * @return A list of all valid connection handles for which the module has a record and in which + * the role of local device is @ref BLE_GAP_ROLE_PERIPH. + */ +ble_conn_state_conn_handle_list_t ble_conn_state_periph_handles(void); + + +/**@brief Function for translating a connection handle to a value that can be used as an array index. + * + * @details Function for mapping connection handles onto the range <0 - MAX_CONNECTIONS>. + * + * @note The index will be the same as long as a connection is invalid. A subsequent connection with + * the same connection handle might have a different index. + * + * @param[in] conn_handle The connection for which to retrieve an index. + * + * @return An index unique to this connection. Or @ref BLE_CONN_STATE_MAX_CONNECTIONS if + * @p conn_handle refers to an invalid connection. + */ +uint16_t ble_conn_state_conn_idx(uint16_t conn_handle); + + +/**@brief Function for obtaining exclusive access to one of the user flag collections. + * + * @details The acquired collection contains one flag for each connection. These flags can be set + * and read individually for each connection. + * + * The state of user flags will not be modified by the connection state module, except to + * set it to 0 for a connection when that connection is invalidated. + * + * @return The ID of the acquired flag, or BLE_CONN_STATE_USER_FLAG_INVALID if none are available. + */ +ble_conn_state_user_flag_id_t ble_conn_state_user_flag_acquire(void); + + +/**@brief Function for reading the value of a user flag. + * + * @param[in] conn_handle Handle of connection to get the flag state for. + * @param[in] flag_id Which flag to get the state for. + * + * @return The state of the flag. If conn_handle is invalid, the function returns false. + */ +bool ble_conn_state_user_flag_get(uint16_t conn_handle, ble_conn_state_user_flag_id_t flag_id); + + +/**@brief Function for setting the value of a user flag. + * + * @param[in] conn_handle Handle of connection to set the flag state for. + * @param[in] flag_id Which flag to set the state for. + * @param[in] value Value to set the flag state to. + */ +void ble_conn_state_user_flag_set(uint16_t conn_handle, + ble_conn_state_user_flag_id_t flag_id, + bool value); + + +/**@brief Function for running a function for each active connection. + * + * @param[in] user_function The function to run for each connection. + * @param[in] p_context Arbitrary context to be passed to \p user_function. + * + * @return The number of times \p user_function was run. + */ +uint32_t ble_conn_state_for_each_connected(ble_conn_state_user_function_t user_function, + void * p_context); + + +/**@brief Function for running a function for each flag that is set in a user flag collection. + * + * @param[in] flag_id Which flags to check. + * @param[in] user_function The function to run when a flag is set. + * @param[in] p_context Arbitrary context to be passed to \p user_function. + * + * @return The number of times \p user_function was run. + */ +uint32_t ble_conn_state_for_each_set_user_flag(ble_conn_state_user_flag_id_t flag_id, + ble_conn_state_user_function_t user_function, + void * p_context); + +/** @} */ +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif /* BLE_CONN_STATE_H__ */ diff --git a/components/ble/common/ble_date_time.h b/components/ble/common/ble_date_time.h new file mode 100644 index 0000000..5f5c219 --- /dev/null +++ b/components/ble/common/ble_date_time.h @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2011 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* Attention! +* To maintain compliance with Nordic Semiconductor ASAs Bluetooth profile +* qualification listings, this section of source code must not be modified. +*/ + +/** @file + * @brief Contains definition of ble_date_time structure. + */ + +/** @file + * + * @defgroup ble_sdk_srv_date_time BLE Date Time characteristic type + * @{ + * @ingroup ble_sdk_lib + * @brief Definition of ble_date_time_t type. + */ + +#ifndef BLE_DATE_TIME_H__ +#define BLE_DATE_TIME_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Date and Time structure. */ +typedef struct +{ + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hours; + uint8_t minutes; + uint8_t seconds; +} ble_date_time_t; + +static __INLINE uint8_t ble_date_time_encode(const ble_date_time_t * p_date_time, + uint8_t * p_encoded_data) +{ + uint8_t len = uint16_encode(p_date_time->year, p_encoded_data); + + p_encoded_data[len++] = p_date_time->month; + p_encoded_data[len++] = p_date_time->day; + p_encoded_data[len++] = p_date_time->hours; + p_encoded_data[len++] = p_date_time->minutes; + p_encoded_data[len++] = p_date_time->seconds; + + return len; +} + +static __INLINE uint8_t ble_date_time_decode(ble_date_time_t * p_date_time, + const uint8_t * p_encoded_data) +{ + uint8_t len = sizeof(uint16_t); + + p_date_time->year = uint16_decode(p_encoded_data); + p_date_time->month = p_encoded_data[len++]; + p_date_time->day = p_encoded_data[len++]; + p_date_time->hours = p_encoded_data[len++]; + p_date_time->minutes = p_encoded_data[len++]; + p_date_time->seconds = p_encoded_data[len++]; + + return len; +} + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_DATE_TIME_H__ + +/** @} */ diff --git a/components/ble/common/ble_gatt_db.h b/components/ble/common/ble_gatt_db.h new file mode 100644 index 0000000..55c8b0a --- /dev/null +++ b/components/ble/common/ble_gatt_db.h @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup ble_sdk_lib_gatt_db GATT Database Service Structure + * @{ + * @ingroup ble_sdk_lib + */ + +#ifndef BLE_GATT_DB_H__ +#define BLE_GATT_DB_H__ + +#include +#include "ble.h" +#include "ble_gattc.h" +#include "sdk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BLE_GATT_DB_MAX_CHARS +#define BLE_GATT_DB_MAX_CHARS 6 /**< The maximum number of characteristics present in a service record. */ +#endif // BLE_GATT_DB_MAX_CHARS + +/**@brief Structure for holding the characteristic and the handle of its CCCD present on a server. + */ +typedef struct +{ + ble_gattc_char_t characteristic; /**< Structure containing information about the characteristic. */ + uint16_t cccd_handle; /**< CCCD Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if a CCCD is not present at the server. */ + uint16_t ext_prop_handle; /**< Extended Properties Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if an Extended Properties descriptor is not present at the server. */ + uint16_t user_desc_handle; /**< User Description Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if a User Description descriptor is not present at the server. */ + uint16_t report_ref_handle; /**< Report Reference Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if a Report Reference descriptor is not present at the server. */ +} ble_gatt_db_char_t; + +/**@brief Structure for holding information about the service and the characteristics present on a + * server. + */ +typedef struct +{ + ble_uuid_t srv_uuid; /**< UUID of the service. */ + uint8_t char_count; /**< Number of characteristics present in the service. */ + ble_gattc_handle_range_t handle_range; /**< Service Handle Range. */ + ble_gatt_db_char_t charateristics[BLE_GATT_DB_MAX_CHARS]; /**< Array of information related to the characteristics present in the service. This list can extend further than one. */ +} ble_gatt_db_srv_t; + + +#ifdef __cplusplus +} +#endif + +#endif /* BLE_GATT_DB_H__ */ + +/** @} */ diff --git a/components/ble/common/ble_sensor_location.h b/components/ble/common/ble_sensor_location.h new file mode 100644 index 0000000..b4d59ab --- /dev/null +++ b/components/ble/common/ble_sensor_location.h @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* Attention! +* To maintain compliance with Nordic Semiconductor ASAs Bluetooth profile +* qualification listings, this section of source code must not be modified. +*/ + +#ifndef BLE_SENSOR_LOCATION_H__ +#define BLE_SENSOR_LOCATION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + BLE_SENSOR_LOCATION_OTHER = 0 , /**<-- Other */ + BLE_SENSOR_LOCATION_TOP_OF_SHOE = 1 , /**<-- Top of shoe */ + BLE_SENSOR_LOCATION_IN_SHOE = 2 , /**<-- In shoe */ + BLE_SENSOR_LOCATION_HIP = 3 , /**<-- Hip */ + BLE_SENSOR_LOCATION_FRONT_WHEEL = 4 , /**<-- Front Wheel */ + BLE_SENSOR_LOCATION_LEFT_CRANK = 5 , /**<-- Left Crank */ + BLE_SENSOR_LOCATION_RIGHT_CRANK = 6 , /**<-- Right Crank */ + BLE_SENSOR_LOCATION_LEFT_PEDAL = 7 , /**<-- Left Pedal */ + BLE_SENSOR_LOCATION_RIGHT_PEDAL = 8 , /**<-- Right Pedal */ + BLE_SENSOR_LOCATION_FRONT_HUB = 9 , /**<-- Front Hub */ + BLE_SENSOR_LOCATION_REAR_DROPOUT = 10, /**<-- Rear Dropout */ + BLE_SENSOR_LOCATION_CHAINSTAY = 11, /**<-- Chainstay */ + BLE_SENSOR_LOCATION_REAR_WHEEL = 12, /**<-- Rear Wheel */ + BLE_SENSOR_LOCATION_REAR_HUB = 13, /**<-- Rear Hub */ +}ble_sensor_location_t; + +#define BLE_NB_MAX_SENSOR_LOCATIONS 14 + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_SENSOR_LOCATION_H__ diff --git a/components/ble/common/ble_srv_common.c b/components/ble/common/ble_srv_common.c new file mode 100644 index 0000000..038e01d --- /dev/null +++ b/components/ble/common/ble_srv_common.c @@ -0,0 +1,237 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* Attention! + * To maintain compliance with Nordic Semiconductor ASA's Bluetooth profile + * qualification listings, this section of source code must not be modified. + */ + +#include "ble_srv_common.h" +#include +#include "nordic_common.h" +#include "app_error.h" +#include "ble.h" + +bool ble_srv_is_notification_enabled(uint8_t const * p_encoded_data) +{ + uint16_t cccd_value = uint16_decode(p_encoded_data); + return ((cccd_value & BLE_GATT_HVX_NOTIFICATION) != 0); +} + +bool ble_srv_is_indication_enabled(uint8_t const * p_encoded_data) +{ + uint16_t cccd_value = uint16_decode(p_encoded_data); + return ((cccd_value & BLE_GATT_HVX_INDICATION) != 0); +} + +uint8_t ble_srv_report_ref_encode(uint8_t * p_encoded_buffer, + const ble_srv_report_ref_t * p_report_ref) +{ + uint8_t len = 0; + + p_encoded_buffer[len++] = p_report_ref->report_id; + p_encoded_buffer[len++] = p_report_ref->report_type; + + APP_ERROR_CHECK_BOOL(len == BLE_SRV_ENCODED_REPORT_REF_LEN); + return len; +} + + +void ble_srv_ascii_to_utf8(ble_srv_utf8_str_t * p_utf8, char * p_ascii) +{ + p_utf8->length = (uint16_t)strlen(p_ascii); + p_utf8->p_str = (uint8_t *)p_ascii; +} + + +/**@brief Function for setting security requirements of a characteristic. + * + * @param[in] level required security level. + * @param[out] p_perm Characteristic security requirements. + * + * @return encoded security level and security mode. + */ +static inline void set_security_req(security_req_t level, ble_gap_conn_sec_mode_t * p_perm) +{ + + + BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(p_perm); + switch (level) + { + case SEC_NO_ACCESS: + BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(p_perm); + break; + case SEC_OPEN: + BLE_GAP_CONN_SEC_MODE_SET_OPEN(p_perm); + break; + case SEC_JUST_WORKS: + BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(p_perm); + break; + case SEC_MITM: + BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(p_perm); + break; + case SEC_SIGNED: + BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(p_perm); + break; + case SEC_SIGNED_MITM: + BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(p_perm); + break; + } + return; +} + + +uint32_t characteristic_add(uint16_t service_handle, + ble_add_char_params_t * p_char_props, + ble_gatts_char_handles_t * p_char_handle) +{ + ble_gatts_char_md_t char_md; + ble_gatts_attr_t attr_char_value; + ble_uuid_t char_uuid; + ble_gatts_attr_md_t attr_md; + ble_gatts_attr_md_t user_descr_attr_md; + ble_gatts_attr_md_t cccd_md; + + if (p_char_props->uuid_type == 0) + { + char_uuid.type = BLE_UUID_TYPE_BLE; + } + else + { + char_uuid.type = p_char_props->uuid_type; + } + char_uuid.uuid = p_char_props->uuid; + + memset(&attr_md, 0, sizeof(ble_gatts_attr_md_t)); + set_security_req(p_char_props->read_access, &attr_md.read_perm); + set_security_req(p_char_props->write_access, & attr_md.write_perm); + attr_md.rd_auth = (p_char_props->is_defered_read ? 1 : 0); + attr_md.wr_auth = (p_char_props->is_defered_write ? 1 : 0); + attr_md.vlen = (p_char_props->is_var_len ? 1 : 0); + attr_md.vloc = (p_char_props->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); + + + memset(&char_md, 0, sizeof(ble_gatts_char_md_t)); + if ((p_char_props->char_props.notify == 1)||(p_char_props->char_props.indicate == 1)) + { + + memset(&cccd_md, 0, sizeof(cccd_md)); + set_security_req(p_char_props->cccd_write_access, &cccd_md.write_perm); + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); + + cccd_md.vloc = BLE_GATTS_VLOC_STACK; + + char_md.p_cccd_md = &cccd_md; + } + char_md.char_props = p_char_props->char_props; + char_md.char_ext_props = p_char_props->char_ext_props; + + memset(&attr_char_value, 0, sizeof(ble_gatts_attr_t)); + attr_char_value.p_uuid = &char_uuid; + attr_char_value.p_attr_md = &attr_md; + attr_char_value.max_len = p_char_props->max_len; + if (p_char_props->p_init_value != NULL) + { + attr_char_value.init_len = p_char_props->init_len; + attr_char_value.p_value = p_char_props->p_init_value; + } + if (p_char_props->p_user_descr != NULL) + { + memset(&user_descr_attr_md, 0, sizeof(ble_gatts_attr_md_t)); + char_md.char_user_desc_max_size = p_char_props->p_user_descr->max_size; + char_md.char_user_desc_size = p_char_props->p_user_descr->size; + char_md.p_char_user_desc = p_char_props->p_user_descr->p_char_user_desc; + + char_md.p_user_desc_md = &user_descr_attr_md; + + set_security_req(p_char_props->p_user_descr->read_access, &user_descr_attr_md.read_perm); + set_security_req(p_char_props->p_user_descr->write_access, &user_descr_attr_md.write_perm); + + user_descr_attr_md.rd_auth = (p_char_props->p_user_descr->is_defered_read ? 1 : 0); + user_descr_attr_md.wr_auth = (p_char_props->p_user_descr->is_defered_write ? 1 : 0); + user_descr_attr_md.vlen = (p_char_props->p_user_descr->is_var_len ? 1 : 0); + user_descr_attr_md.vloc = (p_char_props->p_user_descr->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); + } + if (p_char_props->p_presentation_format != NULL) + { + char_md.p_char_pf = p_char_props->p_presentation_format; + } + return sd_ble_gatts_characteristic_add(service_handle, + &char_md, + &attr_char_value, + p_char_handle); +} + + +uint32_t descriptor_add(uint16_t char_handle, + ble_add_descr_params_t * p_descr_props, + uint16_t * p_descr_handle) +{ + ble_gatts_attr_t descr_params; + ble_uuid_t desc_uuid; + ble_gatts_attr_md_t attr_md; + + memset(&descr_params, 0, sizeof(descr_params)); + if (p_descr_props->uuid_type == 0) + { + desc_uuid.type = BLE_UUID_TYPE_BLE; + } + else + { + desc_uuid.type = p_descr_props->uuid_type; + } + desc_uuid.uuid = p_descr_props->uuid; + descr_params.p_uuid = &desc_uuid; + + set_security_req(p_descr_props->read_access, &attr_md.read_perm); + set_security_req(p_descr_props->write_access,&attr_md.write_perm); + + attr_md.rd_auth = (p_descr_props->is_defered_read ? 1 : 0); + attr_md.wr_auth = (p_descr_props->is_defered_write ? 1 : 0); + attr_md.vlen = (p_descr_props->is_var_len ? 1 : 0); + attr_md.vloc = (p_descr_props->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); + descr_params.p_attr_md = &attr_md; + + descr_params.init_len = p_descr_props->init_len; + descr_params.init_offs = p_descr_props->init_offs; + descr_params.max_len = p_descr_props->max_len; + descr_params.p_value = p_descr_props->p_value; + + return sd_ble_gatts_descriptor_add(char_handle, &descr_params, p_descr_handle); +} diff --git a/components/ble/common/ble_srv_common.h b/components/ble/common/ble_srv_common.h new file mode 100644 index 0000000..7e9c942 --- /dev/null +++ b/components/ble/common/ble_srv_common.h @@ -0,0 +1,409 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup ble_sdk_srv_common Common service definitions + * @{ + * @ingroup ble_sdk_srv + * @brief Constants, type definitions, and functions that are common to all services. + */ + +#ifndef BLE_SRV_COMMON_H__ +#define BLE_SRV_COMMON_H__ + +#include +#include +#include "ble_types.h" +#include "app_util.h" +#include "ble.h" +#include "ble_gap.h" +#include "ble_gatt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup UUID_SERVICES Service UUID definitions + * @{ */ +#define BLE_UUID_ALERT_NOTIFICATION_SERVICE 0x1811 /**< Alert Notification service UUID. */ +#define BLE_UUID_BATTERY_SERVICE 0x180F /**< Battery service UUID. */ +#define BLE_UUID_BLOOD_PRESSURE_SERVICE 0x1810 /**< Blood Pressure service UUID. */ +#define BLE_UUID_CURRENT_TIME_SERVICE 0x1805 /**< Current Time service UUID. */ +#define BLE_UUID_CYCLING_SPEED_AND_CADENCE 0x1816 /**< Cycling Speed and Cadence service UUID. */ +#define BLE_UUID_LOCATION_AND_NAVIGATION_SERVICE 0x1819 /**< Location and Navigation service UUID. */ +#define BLE_UUID_DEVICE_INFORMATION_SERVICE 0x180A /**< Device Information service UUID. */ +#define BLE_UUID_GLUCOSE_SERVICE 0x1808 /**< Glucose service UUID. */ +#define BLE_UUID_HEALTH_THERMOMETER_SERVICE 0x1809 /**< Health Thermometer service UUID. */ +#define BLE_UUID_HEART_RATE_SERVICE 0x180D /**< Heart Rate service UUID. */ +#define BLE_UUID_HUMAN_INTERFACE_DEVICE_SERVICE 0x1812 /**< Human Interface Device service UUID. */ +#define BLE_UUID_IMMEDIATE_ALERT_SERVICE 0x1802 /**< Immediate Alert service UUID. */ +#define BLE_UUID_LINK_LOSS_SERVICE 0x1803 /**< Link Loss service UUID. */ +#define BLE_UUID_NEXT_DST_CHANGE_SERVICE 0x1807 /**< Next Dst Change service UUID. */ +#define BLE_UUID_PHONE_ALERT_STATUS_SERVICE 0x180E /**< Phone Alert Status service UUID. */ +#define BLE_UUID_REFERENCE_TIME_UPDATE_SERVICE 0x1806 /**< Reference Time Update service UUID. */ +#define BLE_UUID_RUNNING_SPEED_AND_CADENCE 0x1814 /**< Running Speed and Cadence service UUID. */ +#define BLE_UUID_SCAN_PARAMETERS_SERVICE 0x1813 /**< Scan Parameters service UUID. */ +#define BLE_UUID_TX_POWER_SERVICE 0x1804 /**< TX Power service UUID. */ +#define BLE_UUID_IPSP_SERVICE 0x1820 /**< Internet Protocol Support service UUID. */ +#define BLE_UUID_BMS_SERVICE 0x181E /**< BOND MANAGEMENT service UUID*/ +#define BLE_UUID_CGM_SERVICE 0x181F /**< Continuous Glucose Monitoring service UUID*/ +#define BLE_UUID_PLX_SERVICE 0x1822 /**< Pulse Oximeter Service UUID*/ +#define BLE_UUID_OTS_SERVICE 0x1825 /**< Object Transfer Service UUID*/ + +/** @} */ + +/** @defgroup UUID_CHARACTERISTICS Characteristic UUID definitions + * @{ */ +#define BLE_UUID_REMOVABLE_CHAR 0x2A3A /**< Removable characteristic UUID. */ +#define BLE_UUID_SERVICE_REQUIRED_CHAR 0x2A3B /**< Service Required characteristic UUID. */ +#define BLE_UUID_ALERT_CATEGORY_ID_CHAR 0x2A43 /**< Alert Category Id characteristic UUID. */ +#define BLE_UUID_ALERT_CATEGORY_ID_BIT_MASK_CHAR 0x2A42 /**< Alert Category Id Bit Mask characteristic UUID. */ +#define BLE_UUID_ALERT_LEVEL_CHAR 0x2A06 /**< Alert Level characteristic UUID. */ +#define BLE_UUID_ALERT_NOTIFICATION_CONTROL_POINT_CHAR 0x2A44 /**< Alert Notification Control Point characteristic UUID. */ +#define BLE_UUID_ALERT_STATUS_CHAR 0x2A3F /**< Alert Status characteristic UUID. */ +#define BLE_UUID_BATTERY_LEVEL_CHAR 0x2A19 /**< Battery Level characteristic UUID. */ +#define BLE_UUID_BLOOD_PRESSURE_FEATURE_CHAR 0x2A49 /**< Blood Pressure Feature characteristic UUID. */ +#define BLE_UUID_BLOOD_PRESSURE_MEASUREMENT_CHAR 0x2A35 /**< Blood Pressure Measurement characteristic UUID. */ +#define BLE_UUID_BODY_SENSOR_LOCATION_CHAR 0x2A38 /**< Body Sensor Location characteristic UUID. */ +#define BLE_UUID_BOOT_KEYBOARD_INPUT_REPORT_CHAR 0x2A22 /**< Boot Keyboard Input Report characteristic UUID. */ +#define BLE_UUID_BOOT_KEYBOARD_OUTPUT_REPORT_CHAR 0x2A32 /**< Boot Keyboard Output Report characteristic UUID. */ +#define BLE_UUID_BOOT_MOUSE_INPUT_REPORT_CHAR 0x2A33 /**< Boot Mouse Input Report characteristic UUID. */ +#define BLE_UUID_CURRENT_TIME_CHAR 0x2A2B /**< Current Time characteristic UUID. */ +#define BLE_UUID_DATE_TIME_CHAR 0x2A08 /**< Date Time characteristic UUID. */ +#define BLE_UUID_DAY_DATE_TIME_CHAR 0x2A0A /**< Day Date Time characteristic UUID. */ +#define BLE_UUID_DAY_OF_WEEK_CHAR 0x2A09 /**< Day Of Week characteristic UUID. */ +#define BLE_UUID_DST_OFFSET_CHAR 0x2A0D /**< Dst Offset characteristic UUID. */ +#define BLE_UUID_EXACT_TIME_256_CHAR 0x2A0C /**< Exact Time 256 characteristic UUID. */ +#define BLE_UUID_FIRMWARE_REVISION_STRING_CHAR 0x2A26 /**< Firmware Revision String characteristic UUID. */ +#define BLE_UUID_GLUCOSE_FEATURE_CHAR 0x2A51 /**< Glucose Feature characteristic UUID. */ +#define BLE_UUID_GLUCOSE_MEASUREMENT_CHAR 0x2A18 /**< Glucose Measurement characteristic UUID. */ +#define BLE_UUID_GLUCOSE_MEASUREMENT_CONTEXT_CHAR 0x2A34 /**< Glucose Measurement Context characteristic UUID. */ +#define BLE_UUID_HARDWARE_REVISION_STRING_CHAR 0x2A27 /**< Hardware Revision String characteristic UUID. */ +#define BLE_UUID_HEART_RATE_CONTROL_POINT_CHAR 0x2A39 /**< Heart Rate Control Point characteristic UUID. */ +#define BLE_UUID_HEART_RATE_MEASUREMENT_CHAR 0x2A37 /**< Heart Rate Measurement characteristic UUID. */ +#define BLE_UUID_HID_CONTROL_POINT_CHAR 0x2A4C /**< Hid Control Point characteristic UUID. */ +#define BLE_UUID_HID_INFORMATION_CHAR 0x2A4A /**< Hid Information characteristic UUID. */ +#define BLE_UUID_IEEE_REGULATORY_CERTIFICATION_DATA_LIST_CHAR 0x2A2A /**< IEEE Regulatory Certification Data List characteristic UUID. */ +#define BLE_UUID_INTERMEDIATE_CUFF_PRESSURE_CHAR 0x2A36 /**< Intermediate Cuff Pressure characteristic UUID. */ +#define BLE_UUID_INTERMEDIATE_TEMPERATURE_CHAR 0x2A1E /**< Intermediate Temperature characteristic UUID. */ +#define BLE_UUID_LOCAL_TIME_INFORMATION_CHAR 0x2A0F /**< Local Time Information characteristic UUID. */ +#define BLE_UUID_MANUFACTURER_NAME_STRING_CHAR 0x2A29 /**< Manufacturer Name String characteristic UUID. */ +#define BLE_UUID_MEASUREMENT_INTERVAL_CHAR 0x2A21 /**< Measurement Interval characteristic UUID. */ +#define BLE_UUID_MODEL_NUMBER_STRING_CHAR 0x2A24 /**< Model Number String characteristic UUID. */ +#define BLE_UUID_UNREAD_ALERT_CHAR 0x2A45 /**< Unread Alert characteristic UUID. */ +#define BLE_UUID_NEW_ALERT_CHAR 0x2A46 /**< New Alert characteristic UUID. */ +#define BLE_UUID_PNP_ID_CHAR 0x2A50 /**< PNP Id characteristic UUID. */ +#define BLE_UUID_PROTOCOL_MODE_CHAR 0x2A4E /**< Protocol Mode characteristic UUID. */ +#define BLE_UUID_RECORD_ACCESS_CONTROL_POINT_CHAR 0x2A52 /**< Record Access Control Point characteristic UUID. */ +#define BLE_UUID_REFERENCE_TIME_INFORMATION_CHAR 0x2A14 /**< Reference Time Information characteristic UUID. */ +#define BLE_UUID_REPORT_CHAR 0x2A4D /**< Report characteristic UUID. */ +#define BLE_UUID_REPORT_MAP_CHAR 0x2A4B /**< Report Map characteristic UUID. */ +#define BLE_UUID_RINGER_CONTROL_POINT_CHAR 0x2A40 /**< Ringer Control Point characteristic UUID. */ +#define BLE_UUID_RINGER_SETTING_CHAR 0x2A41 /**< Ringer Setting characteristic UUID. */ +#define BLE_UUID_SCAN_INTERVAL_WINDOW_CHAR 0x2A4F /**< Scan Interval Window characteristic UUID. */ +#define BLE_UUID_SCAN_REFRESH_CHAR 0x2A31 /**< Scan Refresh characteristic UUID. */ +#define BLE_UUID_SERIAL_NUMBER_STRING_CHAR 0x2A25 /**< Serial Number String characteristic UUID. */ +#define BLE_UUID_SOFTWARE_REVISION_STRING_CHAR 0x2A28 /**< Software Revision String characteristic UUID. */ +#define BLE_UUID_SUPPORTED_NEW_ALERT_CATEGORY_CHAR 0x2A47 /**< Supported New Alert Category characteristic UUID. */ +#define BLE_UUID_SUPPORTED_UNREAD_ALERT_CATEGORY_CHAR 0x2A48 /**< Supported Unread Alert Category characteristic UUID. */ +#define BLE_UUID_SYSTEM_ID_CHAR 0x2A23 /**< System Id characteristic UUID. */ +#define BLE_UUID_TEMPERATURE_MEASUREMENT_CHAR 0x2A1C /**< Temperature Measurement characteristic UUID. */ +#define BLE_UUID_TEMPERATURE_TYPE_CHAR 0x2A1D /**< Temperature Type characteristic UUID. */ +#define BLE_UUID_TIME_ACCURACY_CHAR 0x2A12 /**< Time Accuracy characteristic UUID. */ +#define BLE_UUID_TIME_SOURCE_CHAR 0x2A13 /**< Time Source characteristic UUID. */ +#define BLE_UUID_TIME_UPDATE_CONTROL_POINT_CHAR 0x2A16 /**< Time Update Control Point characteristic UUID. */ +#define BLE_UUID_TIME_UPDATE_STATE_CHAR 0x2A17 /**< Time Update State characteristic UUID. */ +#define BLE_UUID_TIME_WITH_DST_CHAR 0x2A11 /**< Time With Dst characteristic UUID. */ +#define BLE_UUID_TIME_ZONE_CHAR 0x2A0E /**< Time Zone characteristic UUID. */ +#define BLE_UUID_TX_POWER_LEVEL_CHAR 0x2A07 /**< TX Power Level characteristic UUID. */ +#define BLE_UUID_CSC_FEATURE_CHAR 0x2A5C /**< Cycling Speed and Cadence Feature characteristic UUID. */ +#define BLE_UUID_CSC_MEASUREMENT_CHAR 0x2A5B /**< Cycling Speed and Cadence Measurement characteristic UUID. */ +#define BLE_UUID_RSC_FEATURE_CHAR 0x2A54 /**< Running Speed and Cadence Feature characteristic UUID. */ +#define BLE_UUID_SC_CTRLPT_CHAR 0x2A55 /**< Speed and Cadence Control Point UUID. */ +#define BLE_UUID_RSC_MEASUREMENT_CHAR 0x2A53 /**< Running Speed and Cadence Measurement characteristic UUID. */ +#define BLE_UUID_SENSOR_LOCATION_CHAR 0x2A5D /**< Sensor Location characteristic UUID. */ +#define BLE_UUID_EXTERNAL_REPORT_REF_DESCR 0x2907 /**< External Report Reference descriptor UUID. */ +#define BLE_UUID_REPORT_REF_DESCR 0x2908 /**< Report Reference descriptor UUID. */ +#define BLE_UUID_LN_FEATURE_CHAR 0x2A6A /**< Location Navigation Service, Feature characteristic UUID. */ +#define BLE_UUID_LN_POSITION_QUALITY_CHAR 0x2A69 /**< Location Navigation Service, Position quality UUID. */ +#define BLE_UUID_LN_LOCATION_AND_SPEED_CHAR 0x2A67 /**< Location Navigation Service, Location and Speed characteristic UUID. */ +#define BLE_UUID_LN_NAVIGATION_CHAR 0x2A68 /**< Location Navigation Service, Navigation characteristic UUID. */ +#define BLE_UUID_LN_CONTROL_POINT_CHAR 0x2A6B /**< Location Navigation Service, Control point characteristic UUID. */ +#define BLE_UUID_BMS_CTRLPT 0x2AA4 /**< BMS Control Point characteristic UUID. */ +#define BLE_UUID_BMS_FEATURE 0x2AA5 /**< BMS Feature characteristic UUID. */ +#define BLE_UUID_CGM_MEASUREMENT 0x2AA7 /**< CGM Service, Measurement characteristic UUID*/ +#define BLE_UUID_CGM_FEATURE 0x2AA8 /**< CGM Service, Feature characteristic UUID*/ +#define BLE_UUID_CGM_STATUS 0x2AA9 /**< CGM Service, Status characteristic UUID*/ +#define BLE_UUID_CGM_SESSION_START_TIME 0x2AAA /**< CGM Service, session start time characteristic UUID*/ +#define BLE_UUID_CGM_SESSION_RUN_TIME 0x2AAB /**< CGM Service, session run time characteristic UUID*/ +#define BLE_UUID_CGM_SPECIFIC_OPS_CTRLPT 0x2AAC /**< CGM Service, specific ops ctrlpt characteristic UUID*/ +#define BLE_UUID_PLX_SPOT_CHECK_MEAS 0x2A5E /**< PLX Service, spot check measurement characteristic UUID*/ +#define BLE_UUID_PLX_CONTINUOUS_MEAS 0x2A5F /**< PLX Service, continuous measurement characteristic UUID*/ +#define BLE_UUID_PLX_FEATURES 0x2A60 /**< PLX Service, feature characteristic UUID*/ +#define BLE_UUID_OTS_FEATURES 0x2ABD /**< OTS Service, feature characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_NAME 0x2ABE /**< OTS Service, Object Name characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_TYPE 0x2ABF /**< OTS Service, Object Type characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_SIZE 0x2AC0 /**< OTS Service, Object Size characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_FIRST_CREATED 0x2AC1 /**< OTS Service, Object First Created characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_LAST_MODIFIED 0x2AC2 /**< OTS Service, Object Last Modified characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_ID 0x2AC3 /**< OTS Service, Object ID characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_PROPERTIES 0x2AC4 /**< OTS Service, Object Properties characteristic UUID*/ +#define BLE_UUID_OTS_OACP 0x2AC5 /**< OTS Service, Object Action Control Point characteristic UUID*/ +#define BLE_UUID_OTS_OLCP 0x2AC6 /**< OTS Service, Object List Control Point characteristic UUID*/ +#define BLE_UUID_OTS_LF 0x2AC7 /**< OTS Service, Object List Filter characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_CHANGED 0x2AC8 /**< OTS Service, Object Changed characteristic UUID*/ + + + + +/** @} */ + +/** @defgroup ALERT_LEVEL_VALUES Definitions for the Alert Level characteristic values + * @{ */ +#define BLE_CHAR_ALERT_LEVEL_NO_ALERT 0x00 /**< No Alert. */ +#define BLE_CHAR_ALERT_LEVEL_MILD_ALERT 0x01 /**< Mild Alert. */ +#define BLE_CHAR_ALERT_LEVEL_HIGH_ALERT 0x02 /**< High Alert. */ +/** @} */ + +#define BLE_SRV_ENCODED_REPORT_REF_LEN 2 /**< The length of an encoded Report Reference Descriptor. */ +#define BLE_CCCD_VALUE_LEN 2 /**< The length of a CCCD value. */ + +/**@brief Type definition for error handler function that will be called in case of an error in + * a service or a service library module. */ +typedef void (*ble_srv_error_handler_t) (uint32_t nrf_error); + + + +/**@brief Value of a Report Reference descriptor. + * + * @details This is mapping information that maps the parent characteristic to the Report ID(s) and + * Report Type(s) defined within a Report Map characteristic. + */ +typedef struct +{ + uint8_t report_id; /**< Non-zero value if there is more than one instance of the same Report Type */ + uint8_t report_type; /**< Type of Report characteristic (see @ref BLE_HIDS_REPORT_TYPE) */ +} ble_srv_report_ref_t; + +/**@brief UTF-8 string data type. + * + * @note The type can only hold a pointer to the string data (i.e. not the actual data). + */ +typedef struct +{ + uint16_t length; /**< String length. */ + uint8_t * p_str; /**< String data. */ +} ble_srv_utf8_str_t; + + +/**@brief Security settings structure. + * @details This structure contains the security options needed during initialization of the + * service. + */ +typedef struct +{ + ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */ + ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ +} ble_srv_security_mode_t; + +/**@brief Security settings structure. + * @details This structure contains the security options needed during initialization of the + * service. It can be used when the characteristics contains a CCCD. + */ +typedef struct +{ + ble_gap_conn_sec_mode_t cccd_write_perm; /**< Write permissions for Client Characteristic Configuration Descriptor. */ + ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */ + ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ +} ble_srv_cccd_security_mode_t; + +/**@brief Function for decoding a CCCD value, and then testing if notification is + * enabled. + * + * @param[in] p_encoded_data Buffer where the encoded CCCD is stored. + * + * @retval TRUE If notification is enabled. + * @retval FALSE Otherwise. + */ +bool ble_srv_is_notification_enabled(uint8_t const * p_encoded_data); + + +/**@brief Function for decoding a CCCD value, and then testing if indication is + * enabled. + * + * @param[in] p_encoded_data Buffer where the encoded CCCD is stored. + * + * @retval TRUE If indication is enabled. + * @retval FALSE Otherwise. + */ +bool ble_srv_is_indication_enabled(uint8_t const * p_encoded_data); + + +/**@brief Function for encoding a Report Reference Descriptor. + * + * @param[in] p_encoded_buffer The buffer of the encoded data. + * @param[in] p_report_ref Report Reference value to be encoded. + * + * @return Length of the encoded data. + */ +uint8_t ble_srv_report_ref_encode(uint8_t * p_encoded_buffer, + const ble_srv_report_ref_t * p_report_ref); + +/**@brief Function for making a UTF-8 structure refer to an ASCII string. + * + * @param[out] p_utf8 UTF-8 structure to be set. + * @param[in] p_ascii ASCII string to be referred to. + */ +void ble_srv_ascii_to_utf8(ble_srv_utf8_str_t * p_utf8, char * p_ascii); + + +/**@brief Security Access enumeration. + * @details This enumeration gives the possible requirements for accessing a characteristic value. + */ +typedef enum +{ + SEC_NO_ACCESS = 0, /**< Not possible to access. */ + SEC_OPEN = 1, /**< Access open. */ + SEC_JUST_WORKS = 2, /**< Access possible with 'Just Works' security at least. */ + SEC_MITM = 3, /**< Access possible with 'MITM' security at least. */ + SEC_SIGNED = 4, /**< Access possible with 'signed' security at least. */ + SEC_SIGNED_MITM = 5 /**< Access possible with 'signed and MITM' security at least. */ +}security_req_t; + + +/**@brief Characteristic User Descriptor parameters. + * @details This structure contains the parameters for User Descriptor. + */ +typedef struct +{ + uint16_t max_size; /**< Maximum size of the user descriptor*/ + uint16_t size; /**< Size of the user descriptor*/ + uint8_t *p_char_user_desc; /**< User descriptor content, pointer to a UTF-8 encoded string (non-NULL terminated)*/ + bool is_var_len; /**< Indicates if the user descriptor has variable length.*/ + ble_gatt_char_props_t char_props; /**< user descriptor properties.*/ + bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ + bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ + security_req_t read_access; /**< Security requirement for reading the user descriptor.*/ + security_req_t write_access; /**< Security requirement for writing the user descriptor.*/ + bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ +}ble_add_char_user_desc_t; + + +/**@brief Add characteristic parameters structure. + * @details This structure contains the parameters needed to use the @ref characteristic_add function. + */ +typedef struct +{ + uint16_t uuid; /**< Characteristic UUID (16 bits UUIDs).*/ + uint8_t uuid_type; /**< Base UUID. If 0, the Bluetooth SIG UUID will be used. Otherwise, this should be a value returned by @ref sd_ble_uuid_vs_add when adding the base UUID.*/ + uint16_t max_len; /**< Maximum length of the characteristic value.*/ + uint16_t init_len; /**< Initial length of the characteristic value.*/ + uint8_t * p_init_value; /**< Initial encoded value of the characteristic.*/ + bool is_var_len; /**< Indicates if the characteristic value has variable length.*/ + ble_gatt_char_props_t char_props; /**< Characteristic properties.*/ + ble_gatt_char_ext_props_t char_ext_props; /**< Characteristic extended properties.*/ + bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ + bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ + security_req_t read_access; /**< Security requirement for reading the characteristic value.*/ + security_req_t write_access; /**< Security requirement for writing the characteristic value.*/ + security_req_t cccd_write_access; /**< Security requirement for writing the characteristic's CCCD.*/ + bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ + ble_add_char_user_desc_t *p_user_descr; /**< Pointer to user descriptor if needed*/ + ble_gatts_char_pf_t *p_presentation_format; /**< Pointer to characteristic format if needed*/ +} ble_add_char_params_t; + + +/**@brief Add descriptor parameters structure. + * @details This structure contains the parameters needed to use the @ref descriptor_add function. + */ +typedef struct +{ + uint16_t uuid; /**< descriptor UUID (16 bits UUIDs).*/ + uint8_t uuid_type; /**< Base UUID. If 0, the Bluetooth SIG UUID will be used. Otherwise, this should be a value returned by @ref sd_ble_uuid_vs_add when adding the base UUID.*/ + bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ + bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ + bool is_var_len; /**< Indicates if the descriptor value has variable length.*/ + security_req_t read_access; /**< Security requirement for reading the descriptor value.*/ + security_req_t write_access; /**< Security requirement for writing the descriptor value.*/ + bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ + uint16_t init_len; /**< Initial descriptor value length in bytes. */ + uint16_t init_offs; /**< Initial descriptor value offset in bytes. If different from zero, the first init_offs bytes of the attribute value will be left uninitialized. */ + uint16_t max_len; /**< Maximum descriptor value length in bytes, see @ref BLE_GATTS_ATTR_LENS_MAX for maximum values. */ + uint8_t* p_value; /**< Pointer to the value of the descriptor*/ +} ble_add_descr_params_t; + + +/**@brief Function for adding a characteristic to a given service. + * + * If no pointer is given for the initial value, + * the initial length parameter will be ignored and the initial length will be 0. + * + * @param[in] service_handle Handle of the service to which the characteristic is to be added. + * @param[in] p_char_props Information needed to add the characteristic. + * @param[out] p_char_handle Handle of the added characteristic. + * + * @retval NRF_SUCCESS If the characteristic was added successfully. Otherwise, an error code is returned. + */ +uint32_t characteristic_add(uint16_t service_handle, + ble_add_char_params_t * p_char_props, + ble_gatts_char_handles_t * p_char_handle); + + +/**@brief Function for adding a characteristic's descriptor to a given characteristic. + * + * @param[in] char_handle Handle of the characteristic to which the descriptor is to be added, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially. + * @param[in] p_descr_props Information needed to add the descriptor. + * @param[out] p_descr_handle Handle of the added descriptor. + * + * @retval NRF_SUCCESS If the characteristic was added successfully. Otherwise, an error code is returned. + */ +uint32_t descriptor_add(uint16_t char_handle, + ble_add_descr_params_t * p_descr_props, + uint16_t * p_descr_handle); + + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_SRV_COMMON_H__ + +/** @} */ diff --git a/components/ble/nrf_ble_gatt/nrf_ble_gatt.c b/components/ble/nrf_ble_gatt/nrf_ble_gatt.c new file mode 100644 index 0000000..72d008f --- /dev/null +++ b/components/ble/nrf_ble_gatt/nrf_ble_gatt.c @@ -0,0 +1,555 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_BLE_GATT) + +#include "nrf_ble_gatt.h" + +#define NRF_LOG_MODULE_NAME nrf_ble_gatt +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#include "nrf_strerror.h" + +#define BLE_GAP_DATA_LENGTH_DEFAULT 27 //!< The stack's default data length. +#define BLE_GAP_DATA_LENGTH_MAX 251 //!< Maximum data length. + + +STATIC_ASSERT(NRF_SDH_BLE_GAP_DATA_LENGTH < 252); + + +/**@brief Initialize a link's parameters to defaults. */ +static void link_init(nrf_ble_gatt_link_t * p_link) +{ + p_link->att_mtu_desired = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; + p_link->att_mtu_effective = BLE_GATT_ATT_MTU_DEFAULT; + p_link->att_mtu_exchange_pending = false; + p_link->att_mtu_exchange_requested = false; +#if !defined (S112) && !defined(S312) && !defined (S122) + p_link->data_length_desired = NRF_SDH_BLE_GAP_DATA_LENGTH; + p_link->data_length_effective = BLE_GAP_DATA_LENGTH_DEFAULT; +#endif // !defined (S112) && !defined(S312) && !defined (S122) +} + +/**@brief Start a data length update request procedure on a given connection. */ +#if !defined (S112) && !defined(S312) && !defined(S122) +static ret_code_t data_length_update(uint16_t conn_handle, uint16_t data_length) +{ + NRF_LOG_DEBUG("Updating data length to %u on connection 0x%x.", + data_length, conn_handle); + + ble_gap_data_length_params_t const dlp = + { + .max_rx_octets = data_length, + .max_tx_octets = data_length, + .max_rx_time_us = BLE_GAP_DATA_LENGTH_AUTO, + .max_tx_time_us = BLE_GAP_DATA_LENGTH_AUTO, + }; + + ble_gap_data_length_limitation_t dll = {0}; + + ret_code_t err_code = sd_ble_gap_data_length_update(conn_handle, &dlp, &dll); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_gap_data_length_update() (request) on connection 0x%x returned %s.", + conn_handle, nrf_strerror_get(err_code)); + + if ( (dll.tx_payload_limited_octets != 0) + || (dll.rx_payload_limited_octets != 0)) + { + NRF_LOG_ERROR("The requested TX/RX packet length is too long by %u/%u octets.", + dll.tx_payload_limited_octets, dll.rx_payload_limited_octets); + } + + if (dll.tx_rx_time_limited_us != 0) + { + NRF_LOG_ERROR("The requested combination of TX and RX packet lengths " + "is too long by %u microseconds.", + dll.tx_rx_time_limited_us); + } + } + + return err_code; +} +#endif // !defined (S112) && !defined(S312) && !defined (S122) + + +/**@brief Handle a connected event. + * + * Begins an ATT MTU exchange procedure, followed by a data length update request as necessary. + * + * @param[in] p_gatt GATT structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_connected_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) +{ + uint16_t conn_handle = p_ble_evt->evt.common_evt.conn_handle; + nrf_ble_gatt_link_t * p_link = &p_gatt->links[conn_handle]; + + // Update the link desired settings to reflect the current global settings. +#if !defined (S112) && !defined(S312) && !defined(S122) + p_link->data_length_desired = p_gatt->data_length; +#endif // !defined (S112) && !defined(S312) && !defined (S122) + + switch (p_ble_evt->evt.gap_evt.params.connected.role) + { +#if !defined (S122) + case BLE_GAP_ROLE_PERIPH: + p_link->att_mtu_desired = p_gatt->att_mtu_desired_periph; + break; +#endif // !defined (S122) + +#if !defined (S112) && !defined(S312) && !defined(S113) + case BLE_GAP_ROLE_CENTRAL: + p_link->att_mtu_desired = p_gatt->att_mtu_desired_central; + break; +#endif // !defined (S112) && !defined(S312) && !defined(S113) + + default: + // Ignore. + break; + } + +#if NRF_BLE_GATT_MTU_EXCHANGE_INITIATION_ENABLED + // Begin an ATT MTU exchange if necessary. + if (p_link->att_mtu_desired > p_link->att_mtu_effective) + { + ret_code_t err_code; + + NRF_LOG_DEBUG("Requesting to update ATT MTU to %u bytes on connection 0x%x.", + p_link->att_mtu_desired, conn_handle); + + err_code = sd_ble_gattc_exchange_mtu_request(conn_handle, p_link->att_mtu_desired); + + if (err_code == NRF_SUCCESS) + { + p_link->att_mtu_exchange_requested = true; + } + else if (err_code == NRF_ERROR_BUSY) + { + p_link->att_mtu_exchange_pending = true; + NRF_LOG_DEBUG("sd_ble_gattc_exchange_mtu_request()" + " on connection 0x%x returned busy, will retry.", conn_handle); + } + else + { + NRF_LOG_ERROR("sd_ble_gattc_exchange_mtu_request() returned %s.", + nrf_strerror_get(err_code)); + } + } +#endif // NRF_BLE_GATT_MTU_EXCHANGE_INITIATION_ENABLED + +#if !defined (S112) && !defined(S312) && !defined (S122) + // Send a data length update request if necessary. + if (p_link->data_length_desired > p_link->data_length_effective) + { + (void) data_length_update(conn_handle, p_link->data_length_desired); + } +#endif // !defined (S112) && !defined(S312) && !defined (S122) +} + + +static void on_disconnected_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) +{ + // Reset connection parameters. + link_init(&p_gatt->links[p_ble_evt->evt.gap_evt.conn_handle]); +} + + +/**@brief Handle a BLE_GATTC_EVT_EXCHANGE_MTU_RSP event. + * + * @details The effective ATT MTU is set to the lowest between what we requested and the peer's + * response. This events concludes the ATT MTU exchange. An event is sent to the user + * and a data length update procedure is started if necessary. + * + * @param[in] p_gatt GATT structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_exchange_mtu_rsp_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) +{ + uint16_t conn_handle = p_ble_evt->evt.gattc_evt.conn_handle; + uint16_t server_rx_mtu = p_ble_evt->evt.gattc_evt.params.exchange_mtu_rsp.server_rx_mtu; + + nrf_ble_gatt_link_t * p_link = &p_gatt->links[conn_handle]; + + // Determine the lowest MTU between our own desired MTU and the peer's. + // The MTU may not be less than BLE_GATT_ATT_MTU_DEFAULT. + p_link->att_mtu_effective = MIN(server_rx_mtu, p_link->att_mtu_desired); + p_link->att_mtu_effective = MAX(p_link->att_mtu_effective, BLE_GATT_ATT_MTU_DEFAULT); + + NRF_LOG_DEBUG("ATT MTU updated to %u bytes on connection 0x%x (response).", + p_link->att_mtu_effective, conn_handle); + + // Trigger an event indicating that the ATT MTU size has changed. + // Send an event to the application only if an ATT MTU exchange was requested. + if ((p_gatt->evt_handler != NULL) && (p_link->att_mtu_exchange_requested)) + { + nrf_ble_gatt_evt_t const evt = + { + .evt_id = NRF_BLE_GATT_EVT_ATT_MTU_UPDATED, + .conn_handle = conn_handle, + .params.att_mtu_effective = p_link->att_mtu_effective, + }; + + p_gatt->evt_handler(p_gatt, &evt); + } + + p_link->att_mtu_exchange_requested = false; + p_link->att_mtu_exchange_pending = false; +} + + +/**@brief Handle a BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST event. + * + * @param[in] p_gatt GATT structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_exchange_mtu_request_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + uint16_t conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + uint16_t client_mtu = p_ble_evt->evt.gatts_evt.params.exchange_mtu_request.client_rx_mtu; + + nrf_ble_gatt_link_t * p_link = &p_gatt->links[conn_handle]; + + NRF_LOG_DEBUG("Peer on connection 0x%x requested an ATT MTU of %u bytes.", + conn_handle, client_mtu); + + client_mtu = MAX(client_mtu, BLE_GATT_ATT_MTU_DEFAULT); + p_link->att_mtu_effective = MIN(client_mtu, p_link->att_mtu_desired); + p_link->att_mtu_exchange_pending = false; + + NRF_LOG_DEBUG("Updating ATT MTU to %u bytes (desired: %u) on connection 0x%x.", + p_link->att_mtu_effective, p_link->att_mtu_desired, conn_handle); + + err_code = sd_ble_gatts_exchange_mtu_reply(conn_handle, p_link->att_mtu_desired); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_gatts_exchange_mtu_reply() returned %s.", nrf_strerror_get(err_code)); + } + + // If an ATT_MTU exchange was requested to the peer, defer sending + // the data length update request and the event to the application until + // the response for that request is received. + if (p_link->att_mtu_exchange_requested) + { + return; + } + + // The ATT MTU exchange has finished. Send an event to the application. + if (p_gatt->evt_handler != NULL) + { + nrf_ble_gatt_evt_t const evt = + { + .evt_id = NRF_BLE_GATT_EVT_ATT_MTU_UPDATED, + .conn_handle = conn_handle, + .params.att_mtu_effective = p_link->att_mtu_effective, + }; + + p_gatt->evt_handler(p_gatt, &evt); + } +} + + +/**@brief Handle a BLE_GAP_EVT_DATA_LENGTH_UPDATE event. + * + * @details Update the connection data length and send an event to the user. + * + * @param[in] p_gatt GATT structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +#if !defined (S112) && !defined(S312) && !defined (S122) +static void on_data_length_update_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) +{ + ble_gap_evt_t const gap_evt = p_ble_evt->evt.gap_evt; + uint16_t const conn_handle = gap_evt.conn_handle; + + // Update the connection data length. + // The SoftDevice only supports symmetric RX/TX data length settings. + p_gatt->links[conn_handle].data_length_effective = + gap_evt.params.data_length_update.effective_params.max_tx_octets; + + NRF_LOG_DEBUG("Data length updated to %u on connection 0x%0x.", + p_gatt->links[conn_handle].data_length_effective, + conn_handle); + + NRF_LOG_DEBUG("max_rx_octets: %u", + gap_evt.params.data_length_update.effective_params.max_rx_octets); + NRF_LOG_DEBUG("max_tx_octets: %u", + gap_evt.params.data_length_update.effective_params.max_tx_octets); + NRF_LOG_DEBUG("max_rx_time: %u", + gap_evt.params.data_length_update.effective_params.max_rx_time_us); + NRF_LOG_DEBUG("max_tx_time: %u", + gap_evt.params.data_length_update.effective_params.max_tx_time_us); + + if (p_gatt->evt_handler != NULL) + { + nrf_ble_gatt_evt_t const evt = + { + .evt_id = NRF_BLE_GATT_EVT_DATA_LENGTH_UPDATED, + .conn_handle = conn_handle, + .params.data_length = p_gatt->links[conn_handle].data_length_effective, + }; + + p_gatt->evt_handler(p_gatt, &evt); + } +} + + +/**@brief Handle a BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST event. + * + *@details Reply with a sd_ble_gap_data_length_update() call, using the minimum between the + * link's preferred data length, and what requested by the peer. + * The link preferred data length is set to the global preferred data length + * upon connection and can be overridden by calling nrf_ble_gatt_data_length_set(). + * The default is NRF_SDH_BLE_GAP_DATA_LENGTH. + * + *@note The SoftDevice will not send any BLE_GAP_EVT_DATA_LENGTH_UPDATE events on this side. + * Therefore, the connection data length is updated immediately and an event is sent + * to the user. + * + * @param[in] p_gatt GATT structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_data_length_update_request_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) +{ + ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt; + nrf_ble_gatt_link_t * p_link = &p_gatt->links[p_gap_evt->conn_handle]; + + // The SoftDevice only supports symmetric RX/TX data length settings. + uint8_t const data_length_requested = + p_gap_evt->params.data_length_update_request.peer_params.max_tx_octets; + + NRF_LOG_DEBUG("Peer on connection 0x%x requested a data length of %u bytes.", + p_gap_evt->conn_handle, data_length_requested); + + uint8_t const data_length_effective = MIN(p_link->data_length_desired, data_length_requested); + + (void) data_length_update(p_gap_evt->conn_handle, data_length_effective); +} +#endif // !defined (S112) && !defined(S312) && !defined (S122) + + +ret_code_t nrf_ble_gatt_init(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_handler_t evt_handler) +{ + VERIFY_PARAM_NOT_NULL(p_gatt); + + p_gatt->evt_handler = evt_handler; + p_gatt->att_mtu_desired_periph = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; + p_gatt->att_mtu_desired_central = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; + p_gatt->data_length = NRF_SDH_BLE_GAP_DATA_LENGTH; + + for (uint32_t i = 0; i < NRF_BLE_GATT_LINK_COUNT; i++) + { + link_init(&p_gatt->links[i]); + } + + return NRF_SUCCESS; +} + + +ret_code_t nrf_ble_gatt_att_mtu_periph_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu) +{ + VERIFY_PARAM_NOT_NULL(p_gatt); + + if ((desired_mtu < BLE_GATT_ATT_MTU_DEFAULT) || (desired_mtu > NRF_SDH_BLE_GATT_MAX_MTU_SIZE)) + { + return NRF_ERROR_INVALID_PARAM; + } + + p_gatt->att_mtu_desired_periph = desired_mtu; + return NRF_SUCCESS; +} + + +ret_code_t nrf_ble_gatt_att_mtu_central_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu) +{ + VERIFY_PARAM_NOT_NULL(p_gatt); + + if ((desired_mtu < BLE_GATT_ATT_MTU_DEFAULT) || (desired_mtu > NRF_SDH_BLE_GATT_MAX_MTU_SIZE)) + { + return NRF_ERROR_INVALID_PARAM; + } + + p_gatt->att_mtu_desired_central = desired_mtu; + return NRF_SUCCESS; +} + + +uint16_t nrf_ble_gatt_eff_mtu_get(nrf_ble_gatt_t const * p_gatt, uint16_t conn_handle) +{ + if ((p_gatt == NULL) || (conn_handle >= NRF_BLE_GATT_LINK_COUNT)) + { + return 0; + } + + return p_gatt->links[conn_handle].att_mtu_effective; +} + +#if !defined (S112) && !defined(S312) && !defined (S122) +ret_code_t nrf_ble_gatt_data_length_set(nrf_ble_gatt_t * p_gatt, + uint16_t conn_handle, + uint8_t data_length) +{ + if (p_gatt == NULL) + { + return NRF_ERROR_NULL; + } + + // Check early to avoid requesting an invalid data length for upcoming connections. + if ( (data_length > BLE_GAP_DATA_LENGTH_MAX) + || (data_length < BLE_GAP_DATA_LENGTH_DEFAULT)) + { + return NRF_ERROR_INVALID_PARAM; + } + + if (conn_handle == BLE_CONN_HANDLE_INVALID) + { + // Save value and request upon connection. + p_gatt->data_length = data_length; + return NRF_SUCCESS; + } + + if (conn_handle >= NRF_BLE_GATT_LINK_COUNT) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Request data length on existing link. + p_gatt->links[conn_handle].data_length_desired = data_length; + + return data_length_update(conn_handle, data_length); +} + + +ret_code_t nrf_ble_gatt_data_length_get(nrf_ble_gatt_t const * p_gatt, + uint16_t conn_handle, + uint8_t * p_data_length) +{ + if ((p_gatt == NULL) || (p_data_length == NULL)) + { + return NRF_ERROR_NULL; + } + + if (conn_handle == BLE_CONN_HANDLE_INVALID) + { + *p_data_length = p_gatt->data_length; + return NRF_SUCCESS; + } + + if (conn_handle >= NRF_BLE_GATT_LINK_COUNT) + { + return NRF_ERROR_INVALID_PARAM; + } + + *p_data_length = p_gatt->links[conn_handle].data_length_effective; + return NRF_SUCCESS; +} +#endif // !defined (S112) && !defined(S312) && !defined(S122) + + +void nrf_ble_gatt_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) +{ + nrf_ble_gatt_t * p_gatt = (nrf_ble_gatt_t *)p_context; + uint16_t conn_handle = p_ble_evt->evt.common_evt.conn_handle; + + if (conn_handle >= NRF_BLE_GATT_LINK_COUNT) + { + return; + } + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + on_connected_evt(p_gatt, p_ble_evt); + break; + + case BLE_GAP_EVT_DISCONNECTED: + on_disconnected_evt(p_gatt, p_ble_evt); + break; + + case BLE_GATTC_EVT_EXCHANGE_MTU_RSP: + on_exchange_mtu_rsp_evt(p_gatt, p_ble_evt); + break; + + case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: + on_exchange_mtu_request_evt(p_gatt, p_ble_evt); + break; + +#if !defined (S112) && !defined(S312) && !defined (S122) + case BLE_GAP_EVT_DATA_LENGTH_UPDATE: + on_data_length_update_evt(p_gatt, p_ble_evt); + break; + + case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: + on_data_length_update_request_evt(p_gatt, p_ble_evt); + break; +#endif // !defined (S112) && !defined(S312) && !defined (S122) + + default: + break; + } + + if (p_gatt->links[conn_handle].att_mtu_exchange_pending) + { + ret_code_t err_code; + + err_code = sd_ble_gattc_exchange_mtu_request(conn_handle, + p_gatt->links[conn_handle].att_mtu_desired); + + if (err_code == NRF_SUCCESS) + { + p_gatt->links[conn_handle].att_mtu_exchange_pending = false; + p_gatt->links[conn_handle].att_mtu_exchange_requested = true; + + NRF_LOG_DEBUG("Requesting to update ATT MTU to %u bytes on connection 0x%x (retry).", + p_gatt->links[conn_handle].att_mtu_desired, conn_handle); + } + else if (err_code != NRF_ERROR_BUSY) + { + NRF_LOG_ERROR("sd_ble_gattc_exchange_mtu_request() returned %s.", + nrf_strerror_get(err_code)); + } + } +} + +#endif //NRF_BLE_GATT_ENABLED diff --git a/components/ble/nrf_ble_gatt/nrf_ble_gatt.h b/components/ble/nrf_ble_gatt/nrf_ble_gatt.h new file mode 100644 index 0000000..d50f817 --- /dev/null +++ b/components/ble/nrf_ble_gatt/nrf_ble_gatt.h @@ -0,0 +1,242 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup nrf_ble_gatt GATT module + * @{ + * @ingroup ble_sdk_lib + * @brief Module for negotiating and keeping track of GATT connection parameters and updating the data length. + */ + +#ifndef NRF_BLE_GATT_H__ +#define NRF_BLE_GATT_H__ + +#include +#include +#include +#include "ble.h" +#include "ble_gatt.h" +#include "sdk_config.h" +#include "sdk_errors.h" +#include "app_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Macro for defining a nrf_ble_gatt instance. + * + * @param _name Name of the instance. + * @hideinitializer + */ +#define NRF_BLE_GATT_DEF(_name) \ +static nrf_ble_gatt_t _name; \ +NRF_SDH_BLE_OBSERVER(_name ## _obs, \ + NRF_BLE_GATT_BLE_OBSERVER_PRIO, \ + nrf_ble_gatt_on_ble_evt, &_name) + +/**@brief The maximum number of peripheral and central connections combined. + * This value is based on what is configured in the SoftDevice handler sdk_config. + */ +#define NRF_BLE_GATT_LINK_COUNT (NRF_SDH_BLE_PERIPHERAL_LINK_COUNT + NRF_SDH_BLE_CENTRAL_LINK_COUNT) + + +/**@brief GATT module event types. */ +typedef enum +{ + NRF_BLE_GATT_EVT_ATT_MTU_UPDATED = 0xA77, //!< The ATT_MTU size was updated. + NRF_BLE_GATT_EVT_DATA_LENGTH_UPDATED = 0xDA7A, //!< The data length was updated. +} nrf_ble_gatt_evt_id_t; + +/**@brief GATT module event. */ +typedef struct +{ + nrf_ble_gatt_evt_id_t evt_id; //!< Event ID. + uint16_t conn_handle; //!< Connection handle on which the event happened. + union + { + uint16_t att_mtu_effective; //!< Effective ATT_MTU. +#if !defined (S112) && !defined(S312) + uint8_t data_length; //!< Data length value. +#endif // !defined (S112) && !defined(S312) + } params; +} nrf_ble_gatt_evt_t; + +// Forward declaration of the nrf_ble_gatt_t type. +typedef struct nrf_ble_gatt_s nrf_ble_gatt_t; + +/**@brief GATT module event handler type. + * + * The GATT module calls a function of this type when a parameter value is changed. + */ +typedef void (*nrf_ble_gatt_evt_handler_t) (nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt); + +/**@brief GATT information for each connection. */ +typedef struct +{ + uint16_t att_mtu_desired; //!< Requested ATT_MTU size (in bytes). + uint16_t att_mtu_effective; //!< Effective ATT_MTU size (in bytes). + bool att_mtu_exchange_pending; //!< Indicates that an ATT_MTU exchange request is pending (the call to @ref sd_ble_gattc_exchange_mtu_request returned @ref NRF_ERROR_BUSY). + bool att_mtu_exchange_requested; //!< Indicates that an ATT_MTU exchange request was made. +#if !defined (S112) && !defined(S312) + uint8_t data_length_desired; //!< Desired data length (in bytes). + uint8_t data_length_effective; //!< Requested data length (in bytes). +#endif // !defined (S112) && !defined(S312) +} nrf_ble_gatt_link_t; + + +/**@brief GATT structure that contains status information for the GATT module. */ +struct nrf_ble_gatt_s +{ + uint16_t att_mtu_desired_periph; //!< Requested ATT_MTU size for the next peripheral connection that is established. + uint16_t att_mtu_desired_central; //!< Requested ATT_MTU size for the next central connection that is established. + uint8_t data_length; //!< Data length to use for the next connection that is established. + nrf_ble_gatt_link_t links[NRF_BLE_GATT_LINK_COUNT]; //!< GATT related information for all active connections. + nrf_ble_gatt_evt_handler_t evt_handler; //!< GATT event handler. +}; + + +/**@brief Function for initializing the GATT module. + * + * @param[in] evt_handler Event handler. + * @param[out] p_gatt Pointer to the GATT structure. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If @p p_gatt is NULL. + */ +ret_code_t nrf_ble_gatt_init(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_handler_t evt_handler); + + +/**@brief Function for setting the ATT_MTU size for the next connection that is established as peripheral. + * + * @param[in] p_gatt Pointer to the GATT structure. + * @param[in] desired_mtu Requested ATT_MTU size. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If @p p_gatt is NULL. + * @retval NRF_ERROR_INVALID_PARAM If the size of @p desired_mtu is bigger than + * @ref NRF_SDH_BLE_GATT_MAX_MTU_SIZE or smaller than + * @ref BLE_GATT_ATT_MTU_DEFAULT. + */ +ret_code_t nrf_ble_gatt_att_mtu_periph_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu); + + +/**@brief Function for setting the ATT_MTU size for the next connection that is established as central. + * + * @param[in,out] p_gatt Pointer to the GATT structure. + * @param[in] desired_mtu Requested ATT_MTU size. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If @p p_gatt is NULL. + * @retval NRF_ERROR_INVALID_PARAM If the size of @p desired_mtu is bigger than + * @ref NRF_SDH_BLE_GATT_MAX_MTU_SIZE or smaller + * than @ref BLE_GATT_ATT_MTU_DEFAULT. + */ +ret_code_t nrf_ble_gatt_att_mtu_central_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu); + + +/**@brief Function for setting the data length for a connection. + * + * @details If @p conn_handle is a handle to an existing connection, a data length update + * request is sent on that connection. + * If @p conn_handle is @ref BLE_CONN_HANDLE_INVALID, a data length update request + * is sent on the next connection that is established after the ATT_MTU + * exchange has completed. If no ATT_MTU exchange procedure is carried + * out (for example, if a default ATT_MTU size is used), the data length + * is not changed. + */ +#if !defined (S112) && !defined(S312) +ret_code_t nrf_ble_gatt_data_length_set(nrf_ble_gatt_t * p_gatt, + uint16_t conn_handle, + uint8_t data_length); +#endif // !defined (S112) && !defined(S312) + +/**@brief Function for retrieving the data length of a connection. + * + * @details If @p conn_handle is @ref BLE_CONN_HANDLE_INVALID, the function retrieves the data + * length that will be requested for the next connection. + * If @p conn_handle is a handle to an existing connection, the function retrieves + * the effective data length that was negotiated for that connection. + * + * @param[in,out] p_gatt Pointer to the GATT structure. + * @param[in] conn_handle The connection for which to retrieve the data length, or + * @ref BLE_CONN_HANDLE_INVALID to retrieve the requested data length + * for the next connection. + * @param[out] p_data_length The connection data length. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If @p p_gatt or @p p_data_length is NULL. + * @retval NRF_ERROR_INVALID_PARAM If @p conn_handle is larger than @ref NRF_BLE_GATT_LINK_COUNT. + */ +#if !defined (S112) && !defined(S312) +ret_code_t nrf_ble_gatt_data_length_get(nrf_ble_gatt_t const * p_gatt, + uint16_t conn_handle, + uint8_t * p_data_length); +#endif // !defined (S112) && !defined(S312) + +/**@brief Function for handling BLE stack events. + * + * @details This function handles events from the BLE stack that are of interest to the module. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context Pointer to the GATT structure. + */ +void nrf_ble_gatt_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); + + +/**@brief Function for getting the current ATT_MTU size for a given connection. + * + * @param[in] p_gatt Pointer to the GATT structure. + * @param[in] conn_handle Connection handle of the connection. + * + * @return ATT_MTU size for the given connection. + * @retval 0 If @p p_gatt is NULL or if @p conn_handle is larger than + * the supported maximum number of connections. + */ +uint16_t nrf_ble_gatt_eff_mtu_get(nrf_ble_gatt_t const * p_gatt, uint16_t conn_handle); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_BLE_GATT_H__ + +/** @} */ diff --git a/components/ble/nrf_ble_gq/nrf_ble_gq.c b/components/ble/nrf_ble_gq/nrf_ble_gq.c new file mode 100644 index 0000000..33e46b8 --- /dev/null +++ b/components/ble/nrf_ble_gq/nrf_ble_gq.c @@ -0,0 +1,611 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_BLE_GQ) + +#include "nrf_ble_gq.h" + +#define NRF_LOG_MODULE_NAME nrf_ble_gq +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/**@brief Pointer used to describe memory allocator for GATT request. */ +typedef ret_code_t (* req_data_alloc_t) (nrf_memobj_pool_t const * p_data_pool, + nrf_ble_gq_req_t * const p_req); + + +/**@brief Function allocates memory for data associated with @ref NRF_BLE_GQ_REQ_GATTC_WRITE + * request. + * + * @param[in] p_data_pool Pointer to general memory pool. + * @param[in] p_req Pointer to GATTC write request. + * + * @retval NRF_SUCCESS If the write data was allocated successfully. + * @retval NRF_ERROR_INVALID_LENGTH If data to be written is too long. + * @retval NRF_ERROR_NO_MEM If there was no room either in the data pool for new allocation. + */ +static ret_code_t gattc_write_alloc(nrf_memobj_pool_t const * p_data_pool, + nrf_ble_gq_req_t * const p_req) +{ + nrf_ble_gq_gattc_write_t * p_gattc_write = &p_req->params.gattc_write; + + // Check if the payload data is not too long. + if (p_gattc_write->len > NRF_BLE_GQ_GATTC_WRITE_MAX_DATA_LEN) + { + return NRF_ERROR_INVALID_LENGTH; + } + + // Allocate memory for GATTC write request. + p_req->p_mem_obj = nrf_memobj_alloc(p_data_pool, + p_gattc_write->len); + if (p_req->p_mem_obj == NULL) + { + return NRF_ERROR_NO_MEM; + } + + // Copy relevant data to the pool. + nrf_memobj_write(p_req->p_mem_obj, (void *) p_gattc_write->p_value, p_gattc_write->len, 0); + + NRF_LOG_DEBUG("Pointer to allocated memory block: %p.", p_req->p_mem_obj); + return NRF_SUCCESS; +} + + +/**@brief Function allocates memory for data associated with @ref NRF_BLE_GQ_REQ_GATTS_HVX + * request. + * + * @param[in] p_data_pool Pointer to general memory pool. + * @param[in] p_req Pointer to GATTS hvx request. + * + * @retval NRF_SUCCESS If the notification or indication data was allocated successfully. + * @retval NRF_ERROR_INVALID_LENGTH If data to be written is too long. + * @retval NRF_ERROR_NO_MEM If there was no room either in the data pool for new allocation. + */ +static ret_code_t gatts_hvx_alloc(nrf_memobj_pool_t const * p_data_pool, + nrf_ble_gq_req_t * const p_req) +{ + nrf_ble_gq_gatts_hvx_t * p_gatts_hvx = &p_req->params.gatts_hvx; + + // Check if the payload data is not too long. + if (*p_gatts_hvx->p_len > NRF_BLE_GQ_GATTS_HVX_MAX_DATA_LEN) + { + return NRF_ERROR_INVALID_LENGTH; + } + + // Allocate memory for GATTS notification or indication request. + p_req->p_mem_obj = nrf_memobj_alloc(p_data_pool, + *p_gatts_hvx->p_len + sizeof(uint16_t)); + if (p_req->p_mem_obj == NULL) + { + return NRF_ERROR_NO_MEM; + } + + // Copy relevant data to the pool. + nrf_memobj_write(p_req->p_mem_obj, (void *)p_gatts_hvx->p_len, sizeof(uint16_t), 0); + nrf_memobj_write(p_req->p_mem_obj, + (void *)p_gatts_hvx->p_data, + *p_gatts_hvx->p_len, + sizeof(uint16_t)); + + NRF_LOG_DEBUG("Pointer to allocated memory block: %p.", p_req->p_mem_obj); + return NRF_SUCCESS; +} + + +/**@brief Array of memory allocators for different types of @ref nrf_ble_gq_req_t. */ +static const req_data_alloc_t m_req_data_alloc[NRF_BLE_GQ_REQ_NUM] = +{ + [NRF_BLE_GQ_REQ_GATTC_READ] = NULL, + [NRF_BLE_GQ_REQ_GATTC_WRITE] = gattc_write_alloc, + [NRF_BLE_GQ_REQ_SRV_DISCOVERY] = NULL, + [NRF_BLE_GQ_REQ_CHAR_DISCOVERY] = NULL, + [NRF_BLE_GQ_REQ_DESC_DISCOVERY] = NULL, + [NRF_BLE_GQ_REQ_GATTS_HVX] = gatts_hvx_alloc +}; + + +/**@brief Function handles error codes returned by GATT requests. + * + * @param[in] p_req Pointer to GATT request. + * @param[in] err_code Error code returned by SoftDevice. + * @param[in] conn_handle Connection handle. + */ +__STATIC_INLINE void request_err_code_handle(nrf_ble_gq_req_t const * const p_req, + uint16_t conn_handle, + ret_code_t err_code) +{ + if (err_code == NRF_SUCCESS) + { + NRF_LOG_DEBUG("SD GATT procedure (%d) succeeded on connection handle: %d.", + p_req->type, + conn_handle); + } + else + { + NRF_LOG_ERROR("SD GATT procedure (%d) failed on connection handle %d with error: 0x%08X.", + p_req->type, conn_handle, err_code); + if (p_req->error_handler.cb != NULL) + { + p_req->error_handler.cb(err_code, p_req->error_handler.p_ctx, conn_handle); + } + } +} + + +/**@brief Function processes subsequent requests from the BGQ instance queue. + * + * @param[in] p_queue Pointer to the queue instance. + * @param[in] conn_handle Connection handle. + */ +static void queue_process(nrf_queue_t const * const p_queue, uint16_t conn_handle) +{ + ret_code_t err_code; + nrf_ble_gq_req_t ble_req; + + NRF_LOG_DEBUG("Processing the request queue..."); + + err_code = nrf_queue_peek(p_queue, &ble_req); + if (err_code == NRF_SUCCESS) // Queue is not empty + { + switch (ble_req.type) + { + case NRF_BLE_GQ_REQ_GATTC_READ: + NRF_LOG_DEBUG("GATTC Read Request"); + err_code = sd_ble_gattc_read(conn_handle, + ble_req.params.gattc_read.handle, + ble_req.params.gattc_read.offset); + break; + + case NRF_BLE_GQ_REQ_GATTC_WRITE: + { + uint8_t write_data[NRF_BLE_GQ_GATTC_WRITE_MAX_DATA_LEN]; + + // Retrieve allocated data. + ble_req.params.gattc_write.p_value = write_data; + nrf_memobj_read(ble_req.p_mem_obj, + (void *) ble_req.params.gattc_write.p_value, + ble_req.params.gattc_write.len, 0); + + NRF_LOG_DEBUG("GATTC Write Request"); + err_code = sd_ble_gattc_write(conn_handle, + &ble_req.params.gattc_write); + } break; + + case NRF_BLE_GQ_REQ_SRV_DISCOVERY: + { + NRF_LOG_DEBUG("GATTC Primary Service Discovery Request"); + err_code = sd_ble_gattc_primary_services_discover(conn_handle, + ble_req.params.gattc_srv_disc.start_handle, + &ble_req.params.gattc_srv_disc.srvc_uuid); + } break; + + case NRF_BLE_GQ_REQ_CHAR_DISCOVERY: + { + NRF_LOG_DEBUG("GATTC Characteristic Discovery Request"); + err_code = sd_ble_gattc_characteristics_discover(conn_handle, + &ble_req.params.gattc_char_disc); + } break; + + case NRF_BLE_GQ_REQ_DESC_DISCOVERY: + { + NRF_LOG_DEBUG("GATTC Characteristic Descriptor Discovery Request") + err_code = sd_ble_gattc_descriptors_discover(conn_handle, + &ble_req.params.gattc_desc_disc); + } break; + + case NRF_BLE_GQ_REQ_GATTS_HVX: + { + uint8_t hvx_data[NRF_BLE_GQ_GATTS_HVX_MAX_DATA_LEN]; + uint16_t len; + uint16_t hvx_len; + + // Retrieve allocated data. + ble_req.params.gatts_hvx.p_data = hvx_data; + nrf_memobj_read(ble_req.p_mem_obj, + (void *) &hvx_len, + sizeof(uint16_t), + 0); + ble_req.params.gatts_hvx.p_len = &hvx_len; + nrf_memobj_read(ble_req.p_mem_obj, + (void *) ble_req.params.gatts_hvx.p_data, + *ble_req.params.gatts_hvx.p_len, + sizeof(uint16_t)); + + len = hvx_len; + + NRF_LOG_DEBUG("GATTS HVX"); + err_code = sd_ble_gatts_hvx(conn_handle, + &ble_req.params.gatts_hvx); + + if ((err_code == NRF_SUCCESS) && + (len != hvx_len)) + { + err_code = NRF_ERROR_DATA_SIZE; + } + } break; + + default: + NRF_LOG_WARNING("Unimplemented GATT Request"); + break; + } + + if (err_code == NRF_ERROR_BUSY) // Softdevice is processing another GATT request. + { + NRF_LOG_DEBUG("SD is currently busy. The GATT request procedure will be attempted \ + again later."); + } + else + { + // Remove last request descriptor from the queue and free data associated with it. + if (m_req_data_alloc[ble_req.type] != NULL) + { + nrf_memobj_free(ble_req.p_mem_obj); + NRF_LOG_DEBUG("Pointer to freed memory block: %p.", ble_req.p_mem_obj); + } + UNUSED_RETURN_VALUE(nrf_queue_pop(p_queue, &ble_req)); + + request_err_code_handle(&ble_req, conn_handle, err_code); + } + } +} + + +/**@brief Function purges all requests from BGQ instance queues that are + * no longer used by any connection. + * + * @param[in] p_gatt_queue Pointer to the BGQ instance. + */ +static void queues_purge(nrf_ble_gq_t const * const p_gatt_queue) +{ + ret_code_t err_code; + uint16_t conn_id; + + err_code = nrf_queue_pop(p_gatt_queue->p_purge_queue, &conn_id); + + while (err_code == NRF_SUCCESS) + { + nrf_ble_gq_req_t ble_req; + nrf_queue_t const * p_queue; + + NRF_LOG_DEBUG("Purging request queue with id: %d", conn_id); + + p_queue = &p_gatt_queue->p_req_queue[conn_id]; + err_code = nrf_queue_pop(p_queue, &ble_req); + + while (err_code == NRF_SUCCESS) + { + // Free data associated with this request if there is any. + if (m_req_data_alloc[ble_req.type] != NULL) + { + nrf_memobj_free(ble_req.p_mem_obj); + NRF_LOG_DEBUG("Pointer to freed memory block: %p.", ble_req.p_mem_obj); + } + + err_code = nrf_queue_pop(p_queue, &ble_req); + } + + err_code = nrf_queue_pop(p_gatt_queue->p_purge_queue, &conn_id); + } +} + + +/**@brief Function processes single GATT request without queue. + * + * @param[in] p_req Pointer to GATT request. + * @param[in] conn_handle Connection handle. + * + * @retval true If request is accepted by Softdevice. + * @retval false If Softdevice is busy and the request should be queued. + */ +static bool request_process(nrf_ble_gq_req_t const * const p_req, uint16_t conn_handle) +{ + ret_code_t err_code = NRF_SUCCESS; + + switch (p_req->type) + { + case NRF_BLE_GQ_REQ_GATTC_READ: + NRF_LOG_DEBUG("GATTC Read Request"); + err_code = sd_ble_gattc_read(conn_handle, + p_req->params.gattc_read.handle, + p_req->params.gattc_read.offset); + break; + + case NRF_BLE_GQ_REQ_GATTC_WRITE: + NRF_LOG_DEBUG("GATTC Write Request"); + err_code = sd_ble_gattc_write(conn_handle, + &p_req->params.gattc_write); + break; + + case NRF_BLE_GQ_REQ_SRV_DISCOVERY: + NRF_LOG_DEBUG("GATTC Primary Services Discovery Request"); + err_code = sd_ble_gattc_primary_services_discover(conn_handle, + p_req->params.gattc_srv_disc.start_handle, + &p_req->params.gattc_srv_disc.srvc_uuid); + break; + + case NRF_BLE_GQ_REQ_CHAR_DISCOVERY: + NRF_LOG_DEBUG("GATTC Characteristic Discovery Request"); + err_code = sd_ble_gattc_characteristics_discover(conn_handle, + &p_req->params.gattc_char_disc); + break; + + case NRF_BLE_GQ_REQ_DESC_DISCOVERY: + NRF_LOG_DEBUG("GATTC Characteristic Descriptor Request"); + err_code = sd_ble_gattc_descriptors_discover(conn_handle, + &p_req->params.gattc_desc_disc); + break; + + case NRF_BLE_GQ_REQ_GATTS_HVX: + { + uint16_t len = *p_req->params.gatts_hvx.p_len; + + NRF_LOG_DEBUG("GATTS Notification or Indication"); + + err_code = sd_ble_gatts_hvx(conn_handle, + &p_req->params.gatts_hvx); + + if ((err_code == NRF_SUCCESS) && + (len != *p_req->params.gatts_hvx.p_len)) + { + err_code = NRF_ERROR_DATA_SIZE; + } + + } break; + + default: + NRF_LOG_WARNING("Unimplemented GATT Request"); + break; + } + + if (err_code == NRF_ERROR_BUSY) // Softdevice is processing another GATT request. + { + NRF_LOG_DEBUG("SD is currently busy. The GATT request procedure will be attempted \ + again later."); + return false; + } + else + { + request_err_code_handle(p_req, conn_handle, err_code); + return true; + } +} + + +/**@brief Function finds ID for the provided connection handle within nrf_ble_gq_t instance registry. + * + * @param[in] p_gatt_queue Pointer to the nrf_ble_gq_t instance. + * @param[in] conn_handle Connection handle. + * + * @return Connection ID. + */ +static uint16_t conn_handle_id_find(nrf_ble_gq_t const * const p_gatt_queue, uint16_t conn_handle) +{ + uint16_t id; + + for (id = 0; id < p_gatt_queue->max_conns; id++) + { + if (conn_handle == p_gatt_queue->p_conn_handles[id]) + { + return id; + } + } + return id; +} + + +/**@brief Function registers provided connection handle within nrf_ble_gq_t instance registry. + * + * @param[in] p_gatt_queue Pointer to the nrf_ble_gq_t instance. + * @param[in] conn_handle Connection handle. + * + * @retval NRF_SUCCESS If the registration was successful. + * @retval NRF_ERROR_NO_MEM If there was no space for another connection handle. + */ +static ret_code_t conn_handle_register(nrf_ble_gq_t const * const p_gatt_queue, uint16_t conn_handle) +{ + for (uint16_t id = 0; id < p_gatt_queue->max_conns; id++) + { + if (p_gatt_queue->p_conn_handles[id] == BLE_CONN_HANDLE_INVALID) + { + p_gatt_queue->p_conn_handles[id] = conn_handle; + return NRF_SUCCESS; + } + } + return NRF_ERROR_NO_MEM; +} + + +/**@brief Function checks if any connection handle is registered in nrf_ble_gq_t instance. + * + * @param[in] p_gatt_queue Pointer to the nrf_ble_gq_t instance. + * + * @retval true There is at least one registered connection handle. + * @retval false Connection handle registry is empty. + */ +static bool is_any_conn_handle_registered(nrf_ble_gq_t const * const p_gatt_queue) +{ + for (uint16_t id = 0; id < p_gatt_queue->max_conns; id++) + { + if (p_gatt_queue->p_conn_handles[id] != BLE_CONN_HANDLE_INVALID) + { + return true; + } + } + return false; +} + + +ret_code_t nrf_ble_gq_item_add(nrf_ble_gq_t const * const p_gatt_queue, + nrf_ble_gq_req_t * const p_req, + uint16_t conn_handle) +{ + ret_code_t err_code = NRF_SUCCESS; + uint16_t conn_id; + + NRF_LOG_DEBUG("Adding item to the request queue"); + + VERIFY_PARAM_NOT_NULL(p_gatt_queue); + VERIFY_PARAM_NOT_NULL(p_req); + + // Purge queues that are no longer used by any connection. + queues_purge(p_gatt_queue); + + // Check if connection handle is registered and if GATT request is valid. + conn_id = conn_handle_id_find(p_gatt_queue, conn_handle); + if ((p_req->type >= NRF_BLE_GQ_REQ_NUM) || (conn_id == p_gatt_queue->max_conns)) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Try processing a request without buffering. + if (nrf_queue_is_empty(&p_gatt_queue->p_req_queue[conn_id])) + { + bool req_processed = request_process(p_req, conn_handle); + if (req_processed) + { + return err_code; + } + } + + // Prepare request for buffering and add it to the queue. + if (m_req_data_alloc[p_req->type] != NULL) + { + VERIFY_PARAM_NOT_NULL(p_gatt_queue->p_data_pool); + + err_code = m_req_data_alloc[p_req->type](p_gatt_queue->p_data_pool, p_req); + VERIFY_SUCCESS(err_code); + } + + err_code = nrf_queue_push(&p_gatt_queue->p_req_queue[conn_id], p_req); + if ((err_code != NRF_SUCCESS) && (m_req_data_alloc[p_req->type] != NULL)) + { + nrf_memobj_free(p_req->p_mem_obj); + NRF_LOG_DEBUG("Pointer to freed memory block: %p.", p_req->p_mem_obj); + } + + // Check if Softdevice is still busy. + queue_process(&p_gatt_queue->p_req_queue[conn_id], conn_handle); + return err_code; +} + + +ret_code_t nrf_ble_gq_conn_handle_register(nrf_ble_gq_t * const p_gatt_queue, uint16_t conn_handle) +{ + ret_code_t err_code = NRF_SUCCESS; + uint16_t conn_id; + + VERIFY_PARAM_NOT_NULL(p_gatt_queue); + + // Purge queues that are no longer used by any connection. + queues_purge(p_gatt_queue); + + // Allow instance to claim connection handle only if it has not been claimed already. + conn_id = conn_handle_id_find(p_gatt_queue, conn_handle); + if (conn_id == p_gatt_queue->max_conns) + { + NRF_LOG_DEBUG("Registering connection handle: 0x%04X", conn_handle); + + // Initialize/reset data pool if possible. + if (!is_any_conn_handle_registered(p_gatt_queue)) + { + err_code = nrf_memobj_pool_init(p_gatt_queue->p_data_pool); + } + + err_code = conn_handle_register(p_gatt_queue, conn_handle); + VERIFY_SUCCESS(err_code); + } + return err_code; +} + + +void nrf_ble_gq_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) +{ + nrf_ble_gq_t * p_gatt_queue = (nrf_ble_gq_t *) p_context; + uint16_t conn_handle; + uint16_t conn_id; + + if ((p_ble_evt == NULL) || (p_gatt_queue == NULL)) + { + return; + } + + // Obtain connection handle and filter out the events that do not trigger queue processing. + if (p_ble_evt->header.evt_id == BLE_GAP_EVT_DISCONNECTED) + { + conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + } + else if ((p_ble_evt->header.evt_id >= BLE_GATTC_EVT_BASE) && + (p_ble_evt->header.evt_id <= BLE_GATTC_EVT_LAST)) + { + conn_handle = p_ble_evt->evt.gattc_evt.conn_handle; + } + else if ((p_ble_evt->header.evt_id >= BLE_GATTS_EVT_BASE) && + (p_ble_evt->header.evt_id <= BLE_GATTS_EVT_LAST)) + { + conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + } + else + { + // These events are irrelevant for this module. + return; + } + + // Check if connection handle is registered. + conn_id = conn_handle_id_find(p_gatt_queue, conn_handle); + if (conn_id == p_gatt_queue->max_conns) + { + return; + } + + // Perform operations on the queue. + if (p_ble_evt->header.evt_id == BLE_GAP_EVT_DISCONNECTED) + { + p_gatt_queue->p_conn_handles[conn_id] = BLE_CONN_HANDLE_INVALID; + UNUSED_RETURN_VALUE(nrf_queue_push(p_gatt_queue->p_purge_queue, &conn_id)); + } + else + { + queue_process(&p_gatt_queue->p_req_queue[conn_id], conn_handle); + } +} + + +#endif // NRF_MODULE_ENABLED(NRF_BLE_GQ) diff --git a/components/ble/nrf_ble_gq/nrf_ble_gq.h b/components/ble/nrf_ble_gq/nrf_ble_gq.h new file mode 100644 index 0000000..513d402 --- /dev/null +++ b/components/ble/nrf_ble_gq/nrf_ble_gq.h @@ -0,0 +1,260 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup nrf_ble_gq BLE GATT Queue + * @{ + * @ingroup ble_sdk_lib + * @brief Queue for the BLE GATT requests. + * + * @details The BLE GATT Queue (BGQ) module can be used to queue BLE GATT requests if the SoftDevice is not + * able to handle them at the moment. In this case, processing of queued request is + * postponed. Later on, when corresponding BLE event indicates that the SoftDevice may be + * free, the request is retried. For conceptual documentation of this module, see + * @ref lib_ble_gatt_queue. + * + */ +#ifndef NRF_BLE_GQ_H__ +#define NRF_BLE_GQ_H__ + +#include +#include "sdk_common.h" +#include "nrf_memobj.h" +#include "nrf_queue.h" +#include "nrf_sdh_ble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Macro for defining a nrf_ble_gq_t instance with default parameters. + * + * @param _name Name of the instance. + * @param _max_connections The maximal number of connection handles that can be registered. + * @param _queue_size The maximal number of nrf_ble_gq_req_t instances that queue can hold. + * @hideinitializer + */ +#define NRF_BLE_GQ_DEF(_name, _max_connections, _queue_size) \ + NRF_BLE_GQ_CUSTOM_DEF(_name, \ + _max_connections, \ + _queue_size, \ + NRF_BLE_GQ_DATAPOOL_ELEMENT_SIZE, \ + NRF_BLE_GQ_DATAPOOL_ELEMENT_COUNT) + + +#if !(defined(__LINT__)) +/**@brief Macro for defining a nrf_ble_gq_t instance. + * + * @param _name Name of the instance. + * @param _max_connections The maximal number of connection handles that can be registered. + * @param _queue_size The maximal number of nrf_ble_gq_req_t instances that queue can hold. + * @param _pool_elem_size Size of a single element in the pool of memory objects. + * @param _pool_elem_count Number of elements in the pool of memory objects. + * @hideinitializer + */ +#define NRF_BLE_GQ_CUSTOM_DEF(_name, _max_connections, _queue_size, _pool_elem_size, _pool_elem_count) \ + static uint16_t CONCAT_2(_name, conn_handles_arr)[] = \ + { \ + MACRO_REPEAT(_max_connections, NRF_BLE_GQ_CONN_HANDLE_INIT) \ + }; \ + STATIC_ASSERT(ARRAY_SIZE(CONCAT_2(_name, conn_handles_arr)) == (_max_connections)); \ + NRF_QUEUE_ARRAY_DEF(nrf_ble_gq_req_t, CONCAT_2(_name, req_queue), _queue_size, \ + NRF_QUEUE_MODE_NO_OVERFLOW, _max_connections); \ + NRF_QUEUE_DEF(uint16_t, CONCAT_2(_name, purge_queue), _max_connections, \ + NRF_QUEUE_MODE_NO_OVERFLOW); \ + NRF_MEMOBJ_POOL_DEF(CONCAT_2(_name, pool), _pool_elem_size, _pool_elem_count); \ + static nrf_ble_gq_t _name = \ + { \ + .max_conns = (_max_connections), \ + .p_conn_handles = CONCAT_2(_name, conn_handles_arr), \ + .p_req_queue = CONCAT_2(_name, req_queue), \ + .p_purge_queue = &CONCAT_2(_name, purge_queue), \ + .p_data_pool = &CONCAT_2(_name, pool) \ + }; \ + NRF_SDH_BLE_OBSERVER(_name ## _obs, \ + NRF_BLE_GQ_BLE_OBSERVER_PRIO, \ + nrf_ble_gq_on_ble_evt, &_name) +#else +#define NRF_BLE_GQ_CUSTOM_DEF(_name, _max_connections, _queue_size, _pool_elem_size, _pool_elem_count) \ + static nrf_ble_gq_t _name; +#endif // !(defined(__LINT__)) + +/**@brief Helping macro used to properly initialize connection handle array for nrf_ble_gq_t instance. + * Used in @ref NRF_BLE_GQ_CUSTOM_DEF. + */ +#define NRF_BLE_GQ_CONN_HANDLE_INIT(_arg) BLE_CONN_HANDLE_INVALID, + +/**@brief BLE GATT request types. */ +typedef enum +{ + NRF_BLE_GQ_REQ_GATTC_READ, /**< GATTC Read Request. See @ref nrf_ble_gq_gattc_read_t and @ref sd_ble_gattc_read */ + NRF_BLE_GQ_REQ_GATTC_WRITE, /**< GATTC Write Request. See @ref nrf_ble_gq_gattc_write_t and @ref sd_ble_gattc_write */ + NRF_BLE_GQ_REQ_SRV_DISCOVERY, /**< GATTC Service Discovery Request. See @ref nrf_ble_gq_gattc_write_t and @ref sd_ble_gattc_primary_services_discover. */ + NRF_BLE_GQ_REQ_CHAR_DISCOVERY, /**< GATTC Characteristic Discovery Request. See @ref nrf_ble_gq_gattc_char_disc_t and @ref sd_ble_gattc_characteristics_discover. */ + NRF_BLE_GQ_REQ_DESC_DISCOVERY, /**< GATTC Characteristic Descriptor Discovery Request. See @ref nrf_ble_gq_gattc_desc_disc_t and @ref sd_ble_gattc_descriptors_discover*/ + NRF_BLE_GQ_REQ_GATTS_HVX, /**< GATTS Handle Value Notification or Indication. See @ref nrf_ble_gq_gatts_hvx_t and @ref ble_gatts_hvx_params_t */ + NRF_BLE_GQ_REQ_NUM /**< Total number of different GATT Request types */ +} nrf_ble_gq_req_type_t; + +/**@brief Pointer used to describe error handler for GATTC request. */ +typedef void (* nrf_ble_gq_req_error_cb_t) (uint32_t nrf_error, + void * p_context, + uint16_t conn_handle); + +/**@brief Structure used to describe @ref NRF_BLE_GQ_REQ_GATTC_READ request type. */ +typedef struct +{ + uint16_t handle; /**< Handle of the Attribute to be read. */ + uint16_t offset; /**< Offset into the Attribute Value to be read. */ +} nrf_ble_gq_gattc_read_t; + +/**@brief Structure used to describe @ref NRF_BLE_GQ_REQ_GATTC_WRITE request type. */ +typedef ble_gattc_write_params_t nrf_ble_gq_gattc_write_t; + +/**@brief Structure used to describe @ref NRF_BLE_GQ_REQ_SRV_DISCOVERY request type. */ +typedef struct +{ + uint16_t start_handle; /**< The start handle value used during service discovery. */ + ble_uuid_t srvc_uuid; /**< The service UUID to be found. */ +} nrf_ble_gq_gattc_srv_discovery_t; + +/**@brief Structure used to describe @ref NRF_BLE_GQ_REQ_CHAR_DISCOVERY request type. */ +typedef ble_gattc_handle_range_t nrf_ble_gq_gattc_char_disc_t; + +/**@brief Structure used to describe @ref NRF_BLE_GQ_REQ_DESC_DISCOVERY request type. */ +typedef ble_gattc_handle_range_t nrf_ble_gq_gattc_desc_disc_t; + +/**@brief Structure used to describe @ref NRF_BLE_GQ_REQ_GATTS_HVX request type. */ +typedef ble_gatts_hvx_params_t nrf_ble_gq_gatts_hvx_t; + +/**@brief Structure used to handle SoftDevice error. */ +typedef struct +{ + nrf_ble_gq_req_error_cb_t cb; /**< Error handler to be called in case of an error from SoftDevice. */ + void * p_ctx; /**< Parameter to the error handler. */ +} nrf_ble_gq_req_error_handler_t; + + +/**@brief Structure used to describe BLE GATT request. */ +typedef struct +{ + nrf_ble_gq_req_type_t type; /**< Type of request. */ + nrf_memobj_t * p_mem_obj; /**< Memory object for data that cannot be contained in request descriptor. */ + nrf_ble_gq_req_error_handler_t error_handler; /**< Error handler structure. */ + union + { + nrf_ble_gq_gattc_read_t gattc_read; /**< GATTC read parameters. Filled when nrf_ble_gq_req_t::type is @ref NRF_BLE_GQ_REQ_GATTC_READ. */ + nrf_ble_gq_gattc_write_t gattc_write; /**< GATTC write parameters. Filled when nrf_ble_gq_req_t::type is @ref NRF_BLE_GQ_REQ_GATTC_WRITE. */ + nrf_ble_gq_gattc_srv_discovery_t gattc_srv_disc; /**< GATTC Service discovery parameters. Filled when nrf_ble_gq_req_t::type is @ref NRF_BLE_GQ_REQ_SRV_DISCOVERY. */ + nrf_ble_gq_gattc_char_disc_t gattc_char_disc; /**< GATTC characteristic discovery parameters. Filled when nrf_ble_gq_req_t::type is @ref NRF_BLE_GQ_REQ_CHAR_DISCOVERY. */ + nrf_ble_gq_gattc_desc_disc_t gattc_desc_disc; /**< GATTC characteristic descriptor discovery parameters. Filled when nrf_ble_gq_req_t::type is NRF_BLE_GQ_REQ_DESC_DISCOVERY. */ + nrf_ble_gq_gatts_hvx_t gatts_hvx; /**< GATTS Handle Value Notification or Indication Parameters. Filled when nrf_ble_gq_req_t::type is @ref NRF_BLE_GQ_REQ_GATTS_HVX. */ + } params; +} nrf_ble_gq_req_t; + +/**@brief Descriptor for the BLE GATT Queue instance. */ +typedef struct +{ + uint16_t const max_conns; /**< Maximal number of connection handles that can be registered. */ + uint16_t * p_conn_handles; /**< Pointer to array with registered connection handles.*/ + nrf_queue_t const * const p_req_queue; /**< Pointer to array of queue instances used to hold nrf_ble_gq_req_t instances.*/ + nrf_queue_t const * const p_purge_queue; /**< Pointer to the queue instance used to hold indexes of queues to purge.*/ + nrf_memobj_pool_t const * p_data_pool; /**< Memory pool used to obtain nrf_memobj_t instances.*/ +} nrf_ble_gq_t; + + +/**@brief Function for adding a GATT request to the BGQ instance. + * + * @details This function adds a request to the BGQ instance and allocates necessary memory + * for data that can be held within the request descriptor. If the SoftDevice is free, + * this request will be processed immediately. Otherwise, the request remains in + * in the queue and is processed later. + * + * @param[in] p_gatt_queue Pointer to the BGQ instance. + * @param[in] p_req Pointer to the request. + * @param[in] conn_handle Connection handle associated with the request. + * + * @retval NRF_SUCCESS If the request was added successfully. + * @retval NRF_ERROR_NULL Any parameter was NULL. + * @retval NRF_ERROR_NO_MEM There was no room in the queue or in the data pool. + * @retval NRF_ERROR_INVALID_PARAM If \p conn_handle is not registered or type of request - + * \p p_req is not valid. + * @retval err_code Other request specific error codes may be returned. + */ +ret_code_t nrf_ble_gq_item_add(nrf_ble_gq_t const * const p_gatt_queue, + nrf_ble_gq_req_t * const p_req, + uint16_t conn_handle); + + +/**@brief Function for registering connection handle in the BGQ instance. + * + * @details This function is used for registering connection handle in the BGQ instance. From this + * point, the BGQ instance can handle GATT requests associated with the handle until connection + * is no longer valid (disconnect event occurs). + * + * @param[in] p_gatt_queue Pointer to the BGQ instance. + * @param[in] conn_handle Connection handle. + * + * @retval NRF_SUCCESS If the registration was successful. + * @retval NRF_ERROR_NULL If \p p_gatt_queue was NULL. + * @retval NRF_ERROR_NO_MEM If there was no space for another connection handle. + */ +ret_code_t nrf_ble_gq_conn_handle_register(nrf_ble_gq_t * const p_gatt_queue, uint16_t conn_handle); + + +/**@brief Function for handling BLE events from the SoftDevice. + * + * @details This function handles the BLE events received from the SoftDevice. If a BLE + * event is relevant to the BGQ module, it is used to update internal variables, + * process queued GATT requests and, if necessary, send errors to the application. + * + * @param[in] p_ble_evt Pointer to the BLE event. + * @param[in] p_context Pointer to the BGQ instance. + */ +void nrf_ble_gq_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_BLE_GQ_H__ + +/** @} */ diff --git a/components/ble/nrf_ble_qwr/nrf_ble_qwr.c b/components/ble/nrf_ble_qwr/nrf_ble_qwr.c new file mode 100644 index 0000000..4575bf4 --- /dev/null +++ b/components/ble/nrf_ble_qwr/nrf_ble_qwr.c @@ -0,0 +1,488 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_BLE_QWR) +#include +#include "nrf_ble_qwr.h" +#include "ble.h" +#include "ble_srv_common.h" + + +#define NRF_BLE_QWR_INITIALIZED 0xDE // Non-zero value used to make sure the given structure has been initialized by the module. +#define MODULE_INITIALIZED (p_qwr->initialized == NRF_BLE_QWR_INITIALIZED) +#include "sdk_macros.h" + +ret_code_t nrf_ble_qwr_init(nrf_ble_qwr_t * p_qwr, + nrf_ble_qwr_init_t const * p_qwr_init) +{ + VERIFY_PARAM_NOT_NULL(p_qwr); + VERIFY_PARAM_NOT_NULL(p_qwr_init); + if (MODULE_INITIALIZED) + { + return NRF_ERROR_INVALID_STATE; + } + + p_qwr->error_handler = p_qwr_init->error_handler; + p_qwr->initialized = NRF_BLE_QWR_INITIALIZED; + p_qwr->conn_handle = BLE_CONN_HANDLE_INVALID; +#if (NRF_BLE_QWR_MAX_ATTR > 0) + memset(p_qwr->attr_handles, 0, sizeof(p_qwr->attr_handles)); + p_qwr->nb_registered_attr = 0; + p_qwr->is_user_mem_reply_pending = false; + p_qwr->mem_buffer = p_qwr_init->mem_buffer; + p_qwr->callback = p_qwr_init->callback; + p_qwr->nb_written_handles = 0; +#endif + return NRF_SUCCESS; +} + + +#if (NRF_BLE_QWR_MAX_ATTR > 0) +ret_code_t nrf_ble_qwr_attr_register(nrf_ble_qwr_t * p_qwr, uint16_t attr_handle) +{ + VERIFY_PARAM_NOT_NULL(p_qwr); + VERIFY_MODULE_INITIALIZED(); + + if ((p_qwr->nb_registered_attr == NRF_BLE_QWR_MAX_ATTR) + || (p_qwr->mem_buffer.p_mem == NULL) + || (p_qwr->mem_buffer.len == 0)) + { + return (NRF_ERROR_NO_MEM); + } + + if (attr_handle == BLE_GATT_HANDLE_INVALID) + { + return NRF_ERROR_INVALID_PARAM; + } + + p_qwr->attr_handles[p_qwr->nb_registered_attr] = attr_handle; + p_qwr->nb_registered_attr++; + + return NRF_SUCCESS; +} + + +ret_code_t nrf_ble_qwr_value_get(nrf_ble_qwr_t * p_qwr, + uint16_t attr_handle, + uint8_t * p_mem, + uint16_t * p_len) +{ + VERIFY_PARAM_NOT_NULL(p_qwr); + VERIFY_PARAM_NOT_NULL(p_mem); + VERIFY_PARAM_NOT_NULL(p_len); + VERIFY_MODULE_INITIALIZED(); + + uint16_t i = 0; + uint16_t handle = BLE_GATT_HANDLE_INVALID; + uint16_t val_len = 0; + uint16_t val_offset = 0; + uint32_t cur_len = 0; + + do + { + handle = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); + + if (handle == BLE_GATT_HANDLE_INVALID) + { + break; + } + + i += sizeof(uint16_t); + val_offset = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); + i += sizeof(uint16_t); + val_len = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); + i += sizeof(uint16_t); + + if (handle == attr_handle) + { + cur_len = val_offset + val_len; + if (cur_len <= *p_len) + { + memcpy((p_mem + val_offset), &(p_qwr->mem_buffer.p_mem[i]), val_len); + } + else + { + return NRF_ERROR_NO_MEM; + } + } + + i += val_len; + } + while (i < p_qwr->mem_buffer.len); + + *p_len = cur_len; + return NRF_SUCCESS; +} +#endif + + +ret_code_t nrf_ble_qwr_conn_handle_assign(nrf_ble_qwr_t * p_qwr, + uint16_t conn_handle) +{ + VERIFY_PARAM_NOT_NULL(p_qwr); + VERIFY_MODULE_INITIALIZED(); + p_qwr->conn_handle = conn_handle; + return NRF_SUCCESS; +} + + +/**@brief checks if a user_mem_reply is pending, if so attempts to send it. + * + * @param[in] p_qwr QWR structure. + */ +static void user_mem_reply(nrf_ble_qwr_t * p_qwr) +{ + if (p_qwr->is_user_mem_reply_pending) + { + ret_code_t err_code; +#if (NRF_BLE_QWR_MAX_ATTR == 0) + err_code = sd_ble_user_mem_reply(p_qwr->conn_handle, NULL); +#else + err_code = sd_ble_user_mem_reply(p_qwr->conn_handle, &p_qwr->mem_buffer); +#endif + if (err_code == NRF_SUCCESS) + { + p_qwr->is_user_mem_reply_pending = false; + } + else if (err_code == NRF_ERROR_BUSY) + { + p_qwr->is_user_mem_reply_pending = true; + } + else + { + p_qwr->error_handler(err_code); + } + } +} + + +/**@brief Handle a user memory request event. + * + * @param[in] p_qwr QWR structure. + * @param[in] p_common_evt User_mem_request event to be handled. + */ +static void on_user_mem_request(nrf_ble_qwr_t * p_qwr, + ble_common_evt_t const * p_common_evt) +{ + if ((p_common_evt->params.user_mem_request.type == BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES) && + (p_common_evt->conn_handle == p_qwr->conn_handle)) + { + p_qwr->is_user_mem_reply_pending = true; + user_mem_reply(p_qwr); + } +} + + +/**@brief Handle a user memory release event. + * + * @param[in] p_qwr QWR structure. + * @param[in] p_common_evt User_mem_release event to be handled. + */ +static void on_user_mem_release(nrf_ble_qwr_t * p_qwr, + ble_common_evt_t const * p_common_evt) +{ +#if (NRF_BLE_QWR_MAX_ATTR > 0) + if ((p_common_evt->params.user_mem_release.type == BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES) && + (p_common_evt->conn_handle == p_qwr->conn_handle)) + { + // Cancel the current operation. + p_qwr->nb_written_handles = 0; + } +#endif +} + + +#if (NRF_BLE_QWR_MAX_ATTR > 0) +/**@brief Handle a prepare write event. + * + * @param[in] p_qwr QWR structure. + * @param[in] p_evt_write WRITE event to be handled. + */ +static void on_prepare_write(nrf_ble_qwr_t * p_qwr, + ble_gatts_evt_write_t const * p_evt_write) +{ + uint32_t err_code; + ble_gatts_rw_authorize_reply_params_t auth_reply; + memset(&auth_reply, 0, sizeof(auth_reply)); + + auth_reply.params.write.gatt_status = NRF_BLE_QWR_REJ_REQUEST_ERR_CODE; + auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; + + uint32_t i; + + for (i = 0; i < p_qwr->nb_written_handles; i++) + { + if (p_qwr->written_attr_handles[i] == p_evt_write->handle) + { + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + break; + } + } + + if (auth_reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS) + { + for (i = 0; i < p_qwr->nb_registered_attr; i++) + { + if (p_qwr->attr_handles[i] == p_evt_write->handle) + { + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + p_qwr->written_attr_handles[p_qwr->nb_written_handles++] = p_evt_write->handle; + break; + } + } + } + + err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); + if (err_code != NRF_SUCCESS) + { + // Cancel the current operation. + p_qwr->nb_written_handles = 0; + + // Report error to application. + p_qwr->error_handler(err_code); + } + +} + + +/**@brief Handle an execute write event. + * + * @param[in] p_qwr QWR structure. + * @param[in] p_evt_write EXEC WRITE event to be handled. + */ +static void on_execute_write(nrf_ble_qwr_t * p_qwr, + ble_gatts_evt_write_t const * p_evt_write) +{ + uint32_t err_code; + ble_gatts_rw_authorize_reply_params_t auth_reply; + memset(&auth_reply, 0, sizeof(auth_reply)); + + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; + + if (p_qwr->nb_written_handles == 0) + { + auth_reply.params.write.gatt_status = NRF_BLE_QWR_REJ_REQUEST_ERR_CODE; + err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); + if (err_code != NRF_SUCCESS) + { + // Report error to application. + p_qwr->error_handler(err_code); + } + return; + } + + for (uint16_t i = 0; i < p_qwr->nb_written_handles; i++) + { + nrf_ble_qwr_evt_t evt; + uint16_t ret_val; + + evt.evt_type = NRF_BLE_QWR_EVT_AUTH_REQUEST; + evt.attr_handle = p_qwr->written_attr_handles[i]; + ret_val = p_qwr->callback(p_qwr, &evt); + if (ret_val != BLE_GATT_STATUS_SUCCESS) + { + auth_reply.params.write.gatt_status = ret_val; + } + } + + err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); + if (err_code != NRF_SUCCESS) + { + // Report error to application. + p_qwr->error_handler(err_code); + } + + // If the execute has not been rejected by any of the registered applications, propagate execute write event to all written handles. */ + if (auth_reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) + { + for (uint16_t i = 0; i < p_qwr->nb_written_handles; i++) + { + nrf_ble_qwr_evt_t evt; + evt.evt_type = NRF_BLE_QWR_EVT_EXECUTE_WRITE; + evt.attr_handle = p_qwr->written_attr_handles[i]; + /*lint -e534 -save "Ignoring return value of function" */ + p_qwr->callback(p_qwr, &evt); + /*lint -restore*/ + + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + } + } + p_qwr->nb_written_handles = 0; +} + + +/**@brief Handle a cancel write event. + * + * @param[in] p_qwr QWR structure. + * @param[in] p_evt_write EXEC WRITE event to be handled. + */ +static void on_cancel_write(nrf_ble_qwr_t * p_qwr, + ble_gatts_evt_write_t const * p_evt_write) +{ + uint32_t err_code; + ble_gatts_rw_authorize_reply_params_t auth_reply; + memset(&auth_reply, 0, sizeof(auth_reply)); + + auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + + err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); + if (err_code != NRF_SUCCESS) + { + // Report error to application. + p_qwr->error_handler(err_code); + } + p_qwr->nb_written_handles = 0; +} +#endif + +/**@brief Handle a rw_authorize_request event. + * + * @param[in] p_qwr QWR structure. + * @param[in] p_gatts_evt RW_authorize_request event to be handled. + */ +static void on_rw_authorize_request(nrf_ble_qwr_t * p_qwr, + ble_gatts_evt_t const * p_gatts_evt) +{ + if (p_gatts_evt->conn_handle != p_qwr->conn_handle) + { + return; + } + + ble_gatts_evt_rw_authorize_request_t const * p_auth_req = &p_gatts_evt->params.authorize_request; + + if (p_auth_req->type != BLE_GATTS_AUTHORIZE_TYPE_WRITE) + { + return; + } + +#if (NRF_BLE_QWR_MAX_ATTR == 0) + // Handle only queued write related operations. + if ((p_auth_req->request.write.op != BLE_GATTS_OP_PREP_WRITE_REQ) && + (p_auth_req->request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) && + (p_auth_req->request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) + { + return; + } + + // Prepare the response. + ble_gatts_rw_authorize_reply_params_t auth_reply = {0}; + + auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; + auth_reply.params.write.gatt_status = NRF_BLE_QWR_REJ_REQUEST_ERR_CODE; + if (p_auth_req->request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL) + { + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + } + + ret_code_t err_code = sd_ble_gatts_rw_authorize_reply(p_gatts_evt->conn_handle, &auth_reply); + if (err_code != NRF_SUCCESS) + { + // Report error to application. + p_qwr->error_handler(err_code); + } +#else + switch (p_auth_req->request.write.op) + { + case BLE_GATTS_OP_PREP_WRITE_REQ: + on_prepare_write(p_qwr, &p_auth_req->request.write); + break; // BLE_GATTS_OP_PREP_WRITE_REQ + + case BLE_GATTS_OP_EXEC_WRITE_REQ_NOW: + on_execute_write(p_qwr, &p_auth_req->request.write); + break; // BLE_GATTS_OP_EXEC_WRITE_REQ_NOW + + case BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL: + on_cancel_write(p_qwr, &p_auth_req->request.write); + break; // BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL + + default: + // No implementation needed. + break; + } +#endif +} + + +void nrf_ble_qwr_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) +{ + VERIFY_PARAM_NOT_NULL_VOID(p_context); + VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt); + + nrf_ble_qwr_t * p_qwr = (nrf_ble_qwr_t *)p_context; + + VERIFY_MODULE_INITIALIZED_VOID(); + + if (p_ble_evt->evt.common_evt.conn_handle == p_qwr->conn_handle) + { + user_mem_reply(p_qwr); + } + + switch (p_ble_evt->header.evt_id) + { + case BLE_EVT_USER_MEM_REQUEST: + on_user_mem_request(p_qwr, &p_ble_evt->evt.common_evt); + break; // BLE_EVT_USER_MEM_REQUEST + + case BLE_EVT_USER_MEM_RELEASE: + on_user_mem_release(p_qwr, &p_ble_evt->evt.common_evt); + break; // BLE_EVT_USER_MEM_REQUEST + + case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: + on_rw_authorize_request(p_qwr, &p_ble_evt->evt.gatts_evt); + break; // BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST + + case BLE_GAP_EVT_DISCONNECTED: + if (p_ble_evt->evt.gap_evt.conn_handle == p_qwr->conn_handle) + { + p_qwr->conn_handle = BLE_CONN_HANDLE_INVALID; +#if (NRF_BLE_QWR_MAX_ATTR > 0) + p_qwr->nb_written_handles = 0; +#endif + } + break; // BLE_GAP_EVT_DISCONNECTED + + default: + break; + } + +} +#endif // NRF_MODULE_ENABLED(NRF_BLE_QWR) diff --git a/components/ble/nrf_ble_qwr/nrf_ble_qwr.h b/components/ble/nrf_ble_qwr/nrf_ble_qwr.h new file mode 100644 index 0000000..a345fc3 --- /dev/null +++ b/components/ble/nrf_ble_qwr/nrf_ble_qwr.h @@ -0,0 +1,246 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup nrf_ble_qwr Queued Writes module + * @{ + * @ingroup ble_sdk_lib + * @brief Module for handling Queued Write operations. + * + * @details This module handles prepare write, execute write, and cancel write + * commands. It also manages memory requests related to these operations. + * + * @note The application must propagate BLE stack events to this module by calling + * @ref nrf_ble_qwr_on_ble_evt(). + */ + +#ifndef NRF_BLE_QUEUED_WRITES_H__ +#define NRF_BLE_QUEUED_WRITES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "nordic_common.h" +#include "sdk_common.h" +#include "ble.h" +#include "ble_srv_common.h" + +/**@brief Macro for defining a nrf_ble_qwr instance. + * + * @param _name Name of the instance. + * @hideinitializer + */ +#define NRF_BLE_QWR_DEF(_name) \ + static nrf_ble_qwr_t _name; \ + NRF_SDH_BLE_OBSERVER(_name ## _obs, \ + NRF_BLE_QWR_BLE_OBSERVER_PRIO, \ + nrf_ble_qwr_on_ble_evt, \ + &_name) + +/**@brief Macro for defining an array of nrf_ble_qwr instance. + * + * @param _name Name of the array. + * @param _cnt Size of the array. + * @hideinitializer + */ +#define NRF_BLE_QWRS_DEF(_name, _cnt) \ + static nrf_ble_qwr_t _name[_cnt]; \ + NRF_SDH_BLE_OBSERVERS(_name ## _obs, \ + NRF_BLE_QWR_BLE_OBSERVER_PRIO, \ + nrf_ble_qwr_on_ble_evt, \ + &_name, \ + _cnt) + + +#define NRF_BLE_QWR_REJ_REQUEST_ERR_CODE BLE_GATT_STATUS_ATTERR_APP_BEGIN + 0 //!< Error code used by the module to reject prepare write requests on non-registered attributes. + + +/**@brief Queued Writes module event types. */ +typedef enum +{ + NRF_BLE_QWR_EVT_EXECUTE_WRITE, //!< Event that indicates that an execute write command was received for a registered handle and that the received data was actually written and is now ready. + NRF_BLE_QWR_EVT_AUTH_REQUEST, //!< Event that indicates that an execute write command was received for a registered handle and that the write request must now be accepted or rejected. +} nrf_ble_qwr_evt_type_t; + +/**@brief Queued Writes module events. */ +typedef struct +{ + nrf_ble_qwr_evt_type_t evt_type; //!< Type of the event. + uint16_t attr_handle; //!< Handle of the attribute to which the event relates. +} nrf_ble_qwr_evt_t; + +// Forward declaration of the nrf_ble_qwr_t type. +struct nrf_ble_qwr_t; + +/**@brief Queued Writes module event handler type. + * + * If the provided event is of type @ref NRF_BLE_QWR_EVT_AUTH_REQUEST, + * this function must accept or reject the execute write request by returning + * one of the @ref BLE_GATT_STATUS_CODES.*/ +typedef uint16_t (* nrf_ble_qwr_evt_handler_t) (struct nrf_ble_qwr_t * p_qwr, + nrf_ble_qwr_evt_t * p_evt); + +/**@brief Queued Writes structure. + * @details This structure contains status information for the Queued Writes module. */ +typedef struct nrf_ble_qwr_t +{ + uint8_t initialized; //!< Flag that indicates whether the module has been initialized. + uint16_t conn_handle; //!< Connection handle. + ble_srv_error_handler_t error_handler; //!< Error handler. + bool is_user_mem_reply_pending; //!< Flag that indicates whether a mem_reply is pending (because a previous attempt returned busy). +#if (NRF_BLE_QWR_MAX_ATTR > 0) + uint16_t attr_handles[NRF_BLE_QWR_MAX_ATTR]; //!< List of handles for registered attributes, for which the module accepts and handles prepare write operations. + uint8_t nb_registered_attr; //!< Number of registered attributes. + uint16_t written_attr_handles[NRF_BLE_QWR_MAX_ATTR]; //!< List of attribute handles that have been written to during the current prepare write or execute write operation. + uint8_t nb_written_handles; //!< Number of attributes that have been written to during the current prepare write or execute write operation. + ble_user_mem_block_t mem_buffer; //!< Memory buffer that is provided to the SoftDevice on an ON_USER_MEM_REQUEST event. + nrf_ble_qwr_evt_handler_t callback; //!< Event handler function that is called for events concerning the handles of all registered attributes. +#endif +} nrf_ble_qwr_t; + +/**@brief Queued Writes init structure. + * @details This structure contains all information + * that is needed to initialize the Queued Writes module. */ +typedef struct +{ + ble_srv_error_handler_t error_handler; //!< Error handler. +#if (NRF_BLE_QWR_MAX_ATTR > 0) + ble_user_mem_block_t mem_buffer; //!< Memory buffer that is provided to the SoftDevice on an ON_USER_MEM_REQUEST event. + nrf_ble_qwr_evt_handler_t callback; //!< Event handler function that is called for events concerning the handles of all registered attributes. +#endif +} nrf_ble_qwr_init_t; + + +/**@brief Function for initializing the Queued Writes module. + * + * @details Call this function in the main entry of your application to + * initialize the Queued Writes module. It must be called only once with a + * given Queued Writes structure. + * + * @param[out] p_qwr Queued Writes structure. This structure must be + * supplied by the application. It is initialized by this function + * and is later used to identify the particular Queued Writes instance. + * @param[in] p_qwr_init Initialization structure. + * + * @retval NRF_SUCCESS If the Queued Writes module was initialized successfully. + * @retval NRF_ERROR_NULL If any of the given pointers is NULL. + * @retval NRF_ERROR_INVALID_STATE If the given context has already been initialized. + */ +ret_code_t nrf_ble_qwr_init(nrf_ble_qwr_t * p_qwr, + nrf_ble_qwr_init_t const * p_qwr_init); + + +/**@brief Function for assigning a connection handle to a given instance of the Queued Writes module. + * + * @details Call this function when a link with a peer has been established to + * associate this link to the instance of the module. This makes it + * possible to handle several links and associate each link to a particular + * instance of this module. + * + * @param[in] p_qwr Queued Writes structure. + * @param[in] conn_handle Connection handle to be associated with the given Queued Writes instance. + * + * @retval NRF_SUCCESS If the assignment was successful. + * @retval NRF_ERROR_NULL If any of the given pointers is NULL. + * @retval NRF_ERROR_INVALID_STATE If the given context has not been initialized. + */ +ret_code_t nrf_ble_qwr_conn_handle_assign(nrf_ble_qwr_t * p_qwr, + uint16_t conn_handle); + + +/**@brief Function for handling BLE stack events. + * + * @details Handles all events from the BLE stack that are of interest to the Queued Writes module. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context Queued Writes structure. + */ +void nrf_ble_qwr_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); + + +#if (NRF_BLE_QWR_MAX_ATTR > 0) +/**@brief Function for registering an attribute with the Queued Writes module. + * + * @details Call this function for each attribute that you want to enable for + * Queued Writes (thus a series of prepare write and execute write operations). + * + * @param[in] p_qwr Queued Writes structure. + * @param[in] attr_handle Handle of the attribute to register. + * + * @retval NRF_SUCCESS If the registration was successful. + * @retval NRF_ERROR_NO_MEM If no more memory is available to add this registration. + * @retval NRF_ERROR_NULL If any of the given pointers is NULL. + * @retval NRF_ERROR_INVALID_STATE If the given context has not been initialized. + */ +ret_code_t nrf_ble_qwr_attr_register(nrf_ble_qwr_t * p_qwr, uint16_t attr_handle); + + +/**@brief Function for retrieving the received data for a given attribute. + * + * @details Call this function after receiving an @ref NRF_BLE_QWR_EVT_AUTH_REQUEST + * event to retrieve a linear copy of the data that was received for the given attribute. + * + * @param[in] p_qwr Queued Writes structure. + * @param[in] attr_handle Handle of the attribute. + * @param[out] p_mem Pointer to the application buffer where the received data will be copied. + * @param[in,out] p_len Input: length of the input buffer. Output: length of the received data. + * + * + * @retval NRF_SUCCESS If the data was retrieved and stored successfully. + * @retval NRF_ERROR_NO_MEM If the provided buffer was smaller than the received data. + * @retval NRF_ERROR_NULL If any of the given pointers is NULL. + * @retval NRF_ERROR_INVALID_STATE If the given context has not been initialized. + */ +ret_code_t nrf_ble_qwr_value_get(nrf_ble_qwr_t * p_qwr, + uint16_t attr_handle, + uint8_t * p_mem, + uint16_t * p_len); +#endif // (NRF_BLE_QWR_MAX_ATTR > 0) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_BLE_QUEUED_WRITES_H__ + +/** @} */ diff --git a/components/ble/nrf_ble_scan/nrf_ble_scan.c b/components/ble/nrf_ble_scan/nrf_ble_scan.c new file mode 100644 index 0000000..6d9f8c1 --- /dev/null +++ b/components/ble/nrf_ble_scan/nrf_ble_scan.c @@ -0,0 +1,1224 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_BLE_SCAN) + +#include "sdk_config.h" +#include + +#include "nrf_ble_scan.h" + +#include +#include "app_error.h" +#include "nrf_assert.h" +#include "sdk_macros.h" +#include "ble_advdata.h" + +#define NRF_LOG_MODULE_NAME ble_scan +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +/**@brief Function for establishing the connection with a device. + * + * @details Connection is established if @ref NRF_BLE_SCAN_EVT_FILTER_MATCH + * or @ref NRF_BLE_SCAN_EVT_WHITELIST_ADV_REPORT occurs and the module was + * initialized in the automatic connection mode. This function can generate an event + * to the main application when @ref sd_ble_gap_connect is used inside the function and it returns value + * that is different than @ref NRF_SUCCESS. + * + * @param[in] p_scan_ctx Pointer to the Scanning Module instance. + * @param[in] p_adv_report Advertising data. + */ +static void nrf_ble_scan_connect_with_target(nrf_ble_scan_t const * const p_scan_ctx, + ble_gap_evt_adv_report_t const * const p_adv_report) +{ + ret_code_t err_code; + scan_evt_t scan_evt; + + // For readability. + ble_gap_addr_t const * p_addr = &p_adv_report->peer_addr; + ble_gap_scan_params_t const * p_scan_params = &p_scan_ctx->scan_params; + ble_gap_conn_params_t const * p_conn_params = &p_scan_ctx->conn_params; + uint8_t con_cfg_tag = p_scan_ctx->conn_cfg_tag; + + // Return if the automatic connection is disabled. + if (!p_scan_ctx->connect_if_match) + { + return; + } + + // Stop scanning. + nrf_ble_scan_stop(); + + memset(&scan_evt, 0, sizeof(scan_evt)); + + // Establish connection. + err_code = sd_ble_gap_connect(p_addr, + p_scan_params, + p_conn_params, + con_cfg_tag); + + NRF_LOG_DEBUG("Connecting"); + + scan_evt.scan_evt_id = NRF_BLE_SCAN_EVT_CONNECTING_ERROR; + scan_evt.params.connecting_err.err_code = err_code; + + NRF_LOG_DEBUG("Connection status: %d", err_code); + + // If an error occurred, send an event to the event handler. + if ((err_code != NRF_SUCCESS) && (p_scan_ctx->evt_handler != NULL)) + { + p_scan_ctx->evt_handler(&scan_evt); + } + +} + + +#if (NRF_BLE_SCAN_FILTER_ENABLE == 1) +#if (NRF_BLE_SCAN_ADDRESS_CNT > 0) + +/**@brief Function for searching for the provided address in the advertisement packets. + * + * @details Use this function to parse the received advertising data for the provided address. + * + * + * @param[in] p_adv_report Advertising data to parse. + * @param[in] p_addr Address to search for. The address length must correspond to @ref BLE_GAP_ADDR_LEN. + * + * @return True if the provided address was found, false otherwise. + */ +static bool find_peer_addr(ble_gap_evt_adv_report_t const * const p_adv_report, + ble_gap_addr_t const * p_addr) +{ + // Compare addresses. + if (memcmp(p_addr->addr, + p_adv_report->peer_addr.addr, + sizeof(p_adv_report->peer_addr.addr)) == 0) + { + return true; + } + + return false; +} + + +/** @brief Function for comparing the provided address with the addresses of the advertising devices. + * + * @param[in] p_adv_report Advertising data to parse. + * @param[in] p_scan_ctx Pointer to the Scanning Module instance. + * + * @retval True when the address matches with the addresses of the advertising devices. False otherwise. + */ +static bool adv_addr_compare(ble_gap_evt_adv_report_t const * const p_adv_report, + nrf_ble_scan_t const * const p_scan_ctx) +{ + ble_gap_addr_t const * p_addr = p_scan_ctx->scan_filters.addr_filter.target_addr; + uint8_t counter = p_scan_ctx->scan_filters.addr_filter.addr_cnt; + + for (uint8_t index = 0; index < counter; index++) + { + // Search for address. + if (find_peer_addr(p_adv_report, &p_addr[index])) + { + return true; + } + } + + return false; +} + + +/**@brief Function for adding target address to the scanning filter. + * + * @param[in] p_addr Target address in the format required by the SoftDevice. If you need to convert the address, use @ref nrf_ble_scan_copy_addr_to_sd_gap_addr. The address length must correspond to @ref BLE_GAP_ADDR_LEN. + * @param[in,out] p_scan_ctx Pointer to the Scanning Module instance. + * + * @retval NRF_SUCCESS If the filter is added successfully or if you try to add a filter that was already added before. + * @retval NRF_ERROR_NO_MEMORY If the number of available filters is exceeded. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If the BLE address type is invalid. + */ +static ret_code_t nrf_ble_scan_addr_filter_add(nrf_ble_scan_t * const p_scan_ctx, + uint8_t const * p_addr) +{ + ble_gap_addr_t * p_addr_filter = p_scan_ctx->scan_filters.addr_filter.target_addr; + uint8_t * p_counter = &p_scan_ctx->scan_filters.addr_filter.addr_cnt; + uint8_t index; + + // If no memory for filter. + if (*p_counter >= NRF_BLE_SCAN_ADDRESS_CNT) + { + return NRF_ERROR_NO_MEM; + } + + // Check for duplicated filter. + for (index = 0; index < NRF_BLE_SCAN_ADDRESS_CNT; index++) + { + if (!memcmp(p_addr_filter[index].addr, p_addr, BLE_GAP_ADDR_LEN)) + { + return NRF_SUCCESS; + } + } + + for (uint8_t i = 0; i < BLE_GAP_ADDR_LEN; i++) + { + p_addr_filter[*p_counter].addr[i] = p_addr[i]; + } + + // Address type is not used so set it to 0. + p_addr_filter[*p_counter].addr_type = 0; + + NRF_LOG_DEBUG("Filter set on address 0x"); + NRF_LOG_HEXDUMP_DEBUG(p_addr_filter[*p_counter].addr, BLE_GAP_ADDR_LEN); + + // Increase the address filter counter. + *p_counter += 1; + + return NRF_SUCCESS; +} + + +#endif // NRF_BLE_SCAN_ADDRESS_CNT + + +#if (NRF_BLE_SCAN_NAME_CNT > 0) +/** @brief Function for comparing the provided name with the advertised name. + * + * @param[in] p_adv_report Advertising data to parse. + * @param[in] p_scan_ctx Pointer to the Scanning Module instance. + * + * @retval True when the names match. False otherwise. + */ +static bool adv_name_compare(ble_gap_evt_adv_report_t const * p_adv_report, + nrf_ble_scan_t const * const p_scan_ctx) +{ + nrf_ble_scan_name_filter_t const * p_name_filter = &p_scan_ctx->scan_filters.name_filter; + uint8_t counter = + p_scan_ctx->scan_filters.name_filter.name_cnt; + uint8_t index; + uint16_t data_len; + + data_len = p_adv_report->data.len; + + // Compare the name found with the name filter. + for (index = 0; index < counter; index++) + { + if (ble_advdata_name_find(p_adv_report->data.p_data, + data_len, + p_name_filter->target_name[index])) + { + return true; + } + } + + return false; +} + + +/**@brief Function for adding name of the peripheral to the scanning filter. + * + * @param[in] p_name Peripheral name. + * @param[in,out] p_scan_ctx Pointer to the Scanning Module instance. + * + * @retval NRF_SUCCESS If the filter is added successfully or if you try to add a filter that was already added before. + * @retval NRF_ERROR_NULL If a NULL pointer is passed as input. + * @retval NRF_ERROR_DATA_SIZE If the name filter length is too long. The maximum filter name length corresponds to @ref NRF_BLE_SCAN_NAME_MAX_LEN. + * @retval NRF_ERROR_NO_MEMORY If the number of available filters is exceeded. + */ +static ret_code_t nrf_ble_scan_name_filter_add(nrf_ble_scan_t * const p_scan_ctx, + char const * p_name) +{ + uint8_t index; + uint8_t * counter = &p_scan_ctx->scan_filters.name_filter.name_cnt; + uint8_t name_len = strlen(p_name); + + // Check the name length. + if ((name_len == 0) || (name_len > NRF_BLE_SCAN_NAME_MAX_LEN)) + { + return NRF_ERROR_DATA_SIZE; + } + + // If no memory for filter. + if (*counter >= NRF_BLE_SCAN_NAME_CNT) + { + return NRF_ERROR_NO_MEM; + } + + // Check for duplicated filter. + for (index = 0; index < NRF_BLE_SCAN_NAME_CNT; index++) + { + if (!strcmp(p_scan_ctx->scan_filters.name_filter.target_name[index], p_name)) + { + return NRF_SUCCESS; + } + } + + // Add name to filter. + memcpy(p_scan_ctx->scan_filters.name_filter.target_name[(*counter)++], + p_name, + strlen(p_name)); + + NRF_LOG_DEBUG("Adding filter on %s name", p_name); + + return NRF_SUCCESS; +} + + +#endif // NRF_BLE_SCAN_NAME_CNT + + +#if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0) +/** @brief Function for comparing the provided short name with the advertised short name. + * + * @param[in] p_adv_report Advertising data to parse. + * @param[in] p_scan_ctx Pointer to the Scanning Module instance. + * + * @retval True when the names match. False otherwise. + */ +static bool adv_short_name_compare(ble_gap_evt_adv_report_t const * const p_adv_report, + nrf_ble_scan_t const * const p_scan_ctx) +{ + nrf_ble_scan_short_name_filter_t const * p_name_filter = + &p_scan_ctx->scan_filters.short_name_filter; + uint8_t counter = p_scan_ctx->scan_filters.short_name_filter.name_cnt; + uint8_t index; + uint16_t data_len; + + data_len = p_adv_report->data.len; + + // Compare the name found with the name filters. + for (index = 0; index < counter; index++) + { + if (ble_advdata_short_name_find(p_adv_report->data.p_data, + data_len, + p_name_filter->short_name[index].short_target_name, + p_name_filter->short_name[index].short_name_min_len)) + { + return true; + } + } + + return false; +} + + +/**@brief Function for adding the short name of the peripheral to the scanning filter. + * + * @param[in] p_short_name Short name of the peripheral. + * @param[in,out] p_scan_ctx Pointer to the Scanning Module instance. + * + * @retval NRF_SUCCESS If the filter is added successfully or if you try to add a filter that was already added before. + * @retval NRF_ERROR_NULL If a NULL pointer is passed as input. + * @retval NRF_ERROR_DATA_SIZE If the name filter length is too long. The maximum filter name length corresponds to @ref NRF_BLE_SCAN_SHORT_NAME_MAX_LEN. + * @retval NRF_ERROR_NO_MEMORY If the number of available filters is exceeded. + */ +static ret_code_t nrf_ble_scan_short_name_filter_add(nrf_ble_scan_t * const p_scan_ctx, + nrf_ble_scan_short_name_t const * p_short_name) +{ + uint8_t index; + uint8_t * p_counter = + &p_scan_ctx->scan_filters.short_name_filter.name_cnt; + nrf_ble_scan_short_name_filter_t * p_short_name_filter = + &p_scan_ctx->scan_filters.short_name_filter; + uint8_t name_len = strlen(p_short_name->p_short_name); + + // Check the name length. + if ((name_len == 0) || (name_len > NRF_BLE_SCAN_SHORT_NAME_MAX_LEN)) + { + return NRF_ERROR_DATA_SIZE; + } + + // If no memory for filter. + if (*p_counter >= NRF_BLE_SCAN_SHORT_NAME_CNT) + { + return NRF_ERROR_NO_MEM; + } + + // Check for duplicated filter. + for (index = 0; index < NRF_BLE_SCAN_SHORT_NAME_CNT; index++) + { + if (!strcmp(p_short_name_filter->short_name[index].short_target_name, + p_short_name->p_short_name)) + { + return NRF_SUCCESS; + } + } + + // Add name to the filter. + p_short_name_filter->short_name[(*p_counter)].short_name_min_len = + p_short_name->short_name_min_len; + memcpy(p_short_name_filter->short_name[(*p_counter)++].short_target_name, + p_short_name->p_short_name, + strlen(p_short_name->p_short_name)); + + NRF_LOG_DEBUG("Adding filter on %s name", p_short_name->p_short_name); + + return NRF_SUCCESS; +} + + +#endif + + +#if (NRF_BLE_SCAN_UUID_CNT > 0) +/**@brief Function for comparing the provided UUID with the UUID in the advertisement packets. + * + * @param[in] p_adv_report Advertising data to parse. + * @param[in] p_scan_ctx Pointer to the Scanning Module instance. + * + * @return True if the UUIDs match. False otherwise. + */ +static bool adv_uuid_compare(ble_gap_evt_adv_report_t const * const p_adv_report, + nrf_ble_scan_t const * const p_scan_ctx) +{ + nrf_ble_scan_uuid_filter_t const * p_uuid_filter = &p_scan_ctx->scan_filters.uuid_filter; + bool const all_filters_mode = p_scan_ctx->scan_filters.all_filters_mode; + uint8_t const counter = + p_scan_ctx->scan_filters.uuid_filter.uuid_cnt; + uint8_t index; + uint16_t data_len; + uint8_t uuid_match_cnt = 0; + + data_len = p_adv_report->data.len; + + for (index = 0; index < counter; index++) + { + + if (ble_advdata_uuid_find(p_adv_report->data.p_data, + data_len, + &p_uuid_filter->uuid[index])) + { + uuid_match_cnt++; + + // In the normal filter mode, only one UUID is needed to match. + if (!all_filters_mode) + { + break; + } + } + else if (all_filters_mode) + { + break; + } + else + { + // Do nothing. + } + } + + // In the multifilter mode, all UUIDs must be found in the advertisement packets. + if ((all_filters_mode && (uuid_match_cnt == counter)) || + ((!all_filters_mode) && (uuid_match_cnt > 0))) + { + return true; + } + + return false; +} + + +/**@brief Function for adding UUID to the scanning filter. + * + * @param[in] uuid UUID, 16-bit size. + * @param[in,out] p_scan_ctx Pointer to the Scanning Module instance. + * + * @retval NRF_SUCCESS If the scanning started. Otherwise, an error code is returned, also if you tried to add a filter that was already added before. + * @retval NRF_ERROR_NO_MEMORY If the number of available filters is exceeded. + */ +static ret_code_t nrf_ble_scan_uuid_filter_add(nrf_ble_scan_t * const p_scan_ctx, + ble_uuid_t const * p_uuid) +{ + ble_uuid_t * p_uuid_filter = p_scan_ctx->scan_filters.uuid_filter.uuid; + uint8_t * p_counter = &p_scan_ctx->scan_filters.uuid_filter.uuid_cnt; + uint8_t index; + + // If no memory. + if (*p_counter >= NRF_BLE_SCAN_UUID_CNT) + { + return NRF_ERROR_NO_MEM; + } + + // Check for duplicated filter. + for (index = 0; index < NRF_BLE_SCAN_UUID_CNT; index++) + { + if (p_uuid_filter[index].uuid == p_uuid->uuid) + { + return NRF_SUCCESS; + } + } + + // Add UUID to the filter. + p_uuid_filter[(*p_counter)++] = *p_uuid; + NRF_LOG_DEBUG("Added filter on UUID %x", p_uuid->uuid); + + return NRF_SUCCESS; +} + + +#endif // NRF_BLE_SCAN_UUID_CNT + + +#if (NRF_BLE_SCAN_APPEARANCE_CNT) +/**@brief Function for comparing the provided appearance with the appearance in the advertisement packets. + * + * @param[in] p_adv_report Advertising data to parse. + * @param[in,out] p_scan_ctx Pointer to the Scanning Module instance. + * + * @return True if the appearances match. False otherwise. + */ +static bool adv_appearance_compare(ble_gap_evt_adv_report_t const * const p_adv_report, + nrf_ble_scan_t const * const p_scan_ctx) +{ + nrf_ble_scan_appearance_filter_t const * p_appearance_filter = + &p_scan_ctx->scan_filters.appearance_filter; + uint8_t const counter = + p_scan_ctx->scan_filters.appearance_filter.appearance_cnt; + uint8_t index; + uint16_t data_len; + + data_len = p_adv_report->data.len; + + // Verify if the advertised appearance matches the provided appearance. + for (index = 0; index < counter; index++) + { + if (ble_advdata_appearance_find(p_adv_report->data.p_data, + data_len, + &p_appearance_filter->appearance[index])) + { + return true; + } + } + return false; +} + + +/**@brief Function for adding appearance to the scanning filter. + * + * @param[in] appearance Appearance to be added. + * @param[in,out] p_scan_ctx Pointer to the Scanning Module instance. + * + * @retval NRF_SUCCESS If the filter is added successfully or if you try to add a filter that was already added before. + * @retval NRF_ERROR_NULL If a NULL pointer is passed as input. + * @retval NRF_ERROR_NO_MEMORY If the number of available filters is exceeded. + */ +static ret_code_t nrf_ble_scan_appearance_filter_add(nrf_ble_scan_t * const p_scan_ctx, + uint16_t appearance) +{ + uint16_t * p_appearance_filter = p_scan_ctx->scan_filters.appearance_filter.appearance; + uint8_t * p_counter = &p_scan_ctx->scan_filters.appearance_filter.appearance_cnt; + uint8_t index; + + // If no memory. + if (*p_counter >= NRF_BLE_SCAN_APPEARANCE_CNT) + { + return NRF_ERROR_NO_MEM; + } + + // Check for duplicated filter. + for ( index = 0; index < NRF_BLE_SCAN_APPEARANCE_CNT; index++) + { + if (p_appearance_filter[index] == appearance) + { + return NRF_SUCCESS; + } + } + + // Add appearance to the filter. + p_appearance_filter[(*p_counter)++] = appearance; + NRF_LOG_DEBUG("Added filter on appearance %x", appearance); + return NRF_SUCCESS; +} + + +#endif // NRF_BLE_SCAN_APPEARANCE_CNT + + +ret_code_t nrf_ble_scan_filter_set(nrf_ble_scan_t * const p_scan_ctx, + nrf_ble_scan_filter_type_t type, + void const * p_data) +{ + VERIFY_PARAM_NOT_NULL(p_scan_ctx); + VERIFY_PARAM_NOT_NULL(p_data); + + switch (type) + { +#if (NRF_BLE_SCAN_NAME_CNT > 0) + case SCAN_NAME_FILTER: + { + char * p_name = (char *)p_data; + return nrf_ble_scan_name_filter_add(p_scan_ctx, p_name); + } +#endif + +#if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0) + case SCAN_SHORT_NAME_FILTER: + { + nrf_ble_scan_short_name_t * p_short_name = (nrf_ble_scan_short_name_t *)p_data; + return nrf_ble_scan_short_name_filter_add(p_scan_ctx, p_short_name); + } +#endif + +#if (NRF_BLE_SCAN_ADDRESS_CNT > 0) + case SCAN_ADDR_FILTER: + { + uint8_t * p_addr = (uint8_t *)p_data; + return nrf_ble_scan_addr_filter_add(p_scan_ctx, p_addr); + } +#endif + +#if (NRF_BLE_SCAN_UUID_CNT > 0) + case SCAN_UUID_FILTER: + { + ble_uuid_t * p_uuid = (ble_uuid_t *)p_data; + return nrf_ble_scan_uuid_filter_add(p_scan_ctx, p_uuid); + } +#endif + +#if (NRF_BLE_SCAN_APPEARANCE_CNT > 0) + case SCAN_APPEARANCE_FILTER: + { + uint16_t appearance = *((uint16_t *)p_data); + return nrf_ble_scan_appearance_filter_add(p_scan_ctx, appearance); + } +#endif + + default: + return NRF_ERROR_INVALID_PARAM; + } +} + + +ret_code_t nrf_ble_scan_all_filter_remove(nrf_ble_scan_t * const p_scan_ctx) +{ +#if (NRF_BLE_SCAN_NAME_CNT > 0) + nrf_ble_scan_name_filter_t * p_name_filter = &p_scan_ctx->scan_filters.name_filter; + memset(p_name_filter->target_name, 0, sizeof(p_name_filter->target_name)); + p_name_filter->name_cnt = 0; +#endif + +#if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0) + nrf_ble_scan_short_name_filter_t * p_short_name_filter = + &p_scan_ctx->scan_filters.short_name_filter; + memset(p_short_name_filter->short_name, 0, sizeof(p_short_name_filter->short_name)); + p_short_name_filter->name_cnt = 0; +#endif + +#if (NRF_BLE_SCAN_ADDRESS_CNT > 0) + nrf_ble_scan_addr_filter_t * p_addr_filter = &p_scan_ctx->scan_filters.addr_filter; + memset(p_addr_filter->target_addr, 0, sizeof(p_addr_filter->target_addr)); + p_addr_filter->addr_cnt = 0; +#endif + +#if (NRF_BLE_SCAN_UUID_CNT > 0) + nrf_ble_scan_uuid_filter_t * p_uuid_filter = &p_scan_ctx->scan_filters.uuid_filter; + memset(p_uuid_filter->uuid, 0, sizeof(p_uuid_filter->uuid)); + p_uuid_filter->uuid_cnt = 0; +#endif + +#if (NRF_BLE_SCAN_APPEARANCE_CNT > 0) + nrf_ble_scan_appearance_filter_t * p_appearance_filter = + &p_scan_ctx->scan_filters.appearance_filter; + memset(p_appearance_filter->appearance, 0, sizeof(p_appearance_filter->appearance)); + p_appearance_filter->appearance_cnt = 0; +#endif + + return NRF_SUCCESS; +} + + +ret_code_t nrf_ble_scan_filters_enable(nrf_ble_scan_t * const p_scan_ctx, + uint8_t mode, + bool match_all) +{ + VERIFY_PARAM_NOT_NULL(p_scan_ctx); + + // Check if the mode is correct. + if ((!(mode & NRF_BLE_SCAN_ADDR_FILTER)) && + (!(mode & NRF_BLE_SCAN_NAME_FILTER)) && + (!(mode & NRF_BLE_SCAN_UUID_FILTER)) && + (!(mode & NRF_BLE_SCAN_SHORT_NAME_FILTER)) && + (!(mode & NRF_BLE_SCAN_APPEARANCE_FILTER))) + { + return NRF_ERROR_INVALID_PARAM; + } + + ret_code_t err_code; + + // Disable filters. + err_code = nrf_ble_scan_filters_disable(p_scan_ctx); + ASSERT(err_code == NRF_SUCCESS); + + nrf_ble_scan_filters_t * p_filters = &p_scan_ctx->scan_filters; + + // Turn on the filters of your choice. +#if (NRF_BLE_SCAN_ADDRESS_CNT > 0) + if (mode & NRF_BLE_SCAN_ADDR_FILTER) + { + p_filters->addr_filter.addr_filter_enabled = true; + } +#endif + +#if (NRF_BLE_SCAN_NAME_CNT > 0) + if (mode & NRF_BLE_SCAN_NAME_FILTER) + { + p_filters->name_filter.name_filter_enabled = true; + } +#endif + +#if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0) + if (mode & NRF_BLE_SCAN_SHORT_NAME_FILTER) + { + p_filters->short_name_filter.short_name_filter_enabled = true; + } +#endif + +#if (NRF_BLE_SCAN_UUID_CNT > 0) + if (mode & NRF_BLE_SCAN_UUID_FILTER) + { + p_filters->uuid_filter.uuid_filter_enabled = true; + } +#endif + +#if (NRF_BLE_SCAN_APPEARANCE_CNT > 0) + if (mode & NRF_BLE_SCAN_APPEARANCE_FILTER) + { + p_filters->appearance_filter.appearance_filter_enabled = true; + } +#endif + + // Select the filter mode. + p_filters->all_filters_mode = match_all; + + return NRF_SUCCESS; +} + + +ret_code_t nrf_ble_scan_filters_disable(nrf_ble_scan_t * const p_scan_ctx) +{ + VERIFY_PARAM_NOT_NULL(p_scan_ctx); + + // Disable all filters. +#if (NRF_BLE_SCAN_NAME_CNT > 0) + bool * p_name_filter_enabled = &p_scan_ctx->scan_filters.name_filter.name_filter_enabled; + *p_name_filter_enabled = false; +#endif + +#if (NRF_BLE_SCAN_ADDRESS_CNT > 0) + bool * p_addr_filter_enabled = &p_scan_ctx->scan_filters.addr_filter.addr_filter_enabled; + *p_addr_filter_enabled = false; +#endif + +#if (NRF_BLE_SCAN_UUID_CNT > 0) + bool * p_uuid_filter_enabled = &p_scan_ctx->scan_filters.uuid_filter.uuid_filter_enabled; + *p_uuid_filter_enabled = false; +#endif + +#if (NRF_BLE_SCAN_APPEARANCE_CNT > 0) + bool * p_appearance_filter_enabled = + &p_scan_ctx->scan_filters.appearance_filter.appearance_filter_enabled; + *p_appearance_filter_enabled = false; +#endif + + return NRF_SUCCESS; +} + + +ret_code_t nrf_ble_scan_filter_get(nrf_ble_scan_t * const p_scan_ctx, + nrf_ble_scan_filters_t * p_status) +{ + VERIFY_PARAM_NOT_NULL(p_scan_ctx); + VERIFY_PARAM_NOT_NULL(p_status); + + *p_status = p_scan_ctx->scan_filters; + + return NRF_SUCCESS; +} + + +#endif // NRF_BLE_SCAN_FILTER_ENABLE + +/**@brief Function for calling the BLE_GAP_EVT_ADV_REPORT event to check whether the received + * scanning data matches the scan configuration. + * + * @param[in] p_scan_ctx Pointer to the Scanning Module instance. + * @param[in] p_adv_report Advertising report. + */ +static void nrf_ble_scan_on_adv_report(nrf_ble_scan_t const * const p_scan_ctx, + ble_gap_evt_adv_report_t const * const p_adv_report) +{ + scan_evt_t scan_evt; + +#if (NRF_BLE_SCAN_FILTER_ENABLE == 1) + uint8_t filter_cnt = 0; + uint8_t filter_match_cnt = 0; +#endif + + memset(&scan_evt, 0, sizeof(scan_evt)); + + scan_evt.p_scan_params = &p_scan_ctx->scan_params; + + // If the whitelist is used, do not check the filters and return. + if (is_whitelist_used(p_scan_ctx)) + { + scan_evt.scan_evt_id = NRF_BLE_SCAN_EVT_WHITELIST_ADV_REPORT; + scan_evt.params.p_not_found = p_adv_report; + p_scan_ctx->evt_handler(&scan_evt); + + UNUSED_RETURN_VALUE(sd_ble_gap_scan_start(NULL, &p_scan_ctx->scan_buffer)); + nrf_ble_scan_connect_with_target(p_scan_ctx, p_adv_report); + + return; + } + +#if (NRF_BLE_SCAN_FILTER_ENABLE == 1) + bool const all_filter_mode = p_scan_ctx->scan_filters.all_filters_mode; + bool is_filter_matched = false; + +#if (NRF_BLE_SCAN_ADDRESS_CNT > 0) + bool const addr_filter_enabled = p_scan_ctx->scan_filters.addr_filter.addr_filter_enabled; +#endif + +#if (NRF_BLE_SCAN_NAME_CNT > 0) + bool const name_filter_enabled = p_scan_ctx->scan_filters.name_filter.name_filter_enabled; +#endif + +#if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0) + bool const short_name_filter_enabled = + p_scan_ctx->scan_filters.short_name_filter.short_name_filter_enabled; +#endif + +#if (NRF_BLE_SCAN_UUID_CNT > 0) + bool const uuid_filter_enabled = p_scan_ctx->scan_filters.uuid_filter.uuid_filter_enabled; +#endif + +#if (NRF_BLE_SCAN_APPEARANCE_CNT > 0) + bool const appearance_filter_enabled = + p_scan_ctx->scan_filters.appearance_filter.appearance_filter_enabled; +#endif + + +#if (NRF_BLE_SCAN_ADDRESS_CNT > 0) + // Check the address filter. + if (addr_filter_enabled) + { + // Number of active filters. + filter_cnt++; + if (adv_addr_compare(p_adv_report, p_scan_ctx)) + { + // Number of filters matched. + filter_match_cnt++; + // Information about the filters matched. + scan_evt.params.filter_match.filter_match.address_filter_match = true; + is_filter_matched = true; + } + } +#endif + +#if (NRF_BLE_SCAN_NAME_CNT > 0) + // Check the name filter. + if (name_filter_enabled) + { + filter_cnt++; + if (adv_name_compare(p_adv_report, p_scan_ctx)) + { + filter_match_cnt++; + + // Information about the filters matched. + scan_evt.params.filter_match.filter_match.name_filter_match = true; + is_filter_matched = true; + } + } +#endif + +#if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0) + if (short_name_filter_enabled) + { + filter_cnt++; + if (adv_short_name_compare(p_adv_report, p_scan_ctx)) + { + filter_match_cnt++; + + // Information about the filters matched. + scan_evt.params.filter_match.filter_match.short_name_filter_match = true; + is_filter_matched = true; + } + } +#endif + +#if (NRF_BLE_SCAN_UUID_CNT > 0) + // Check the UUID filter. + if (uuid_filter_enabled) + { + filter_cnt++; + if (adv_uuid_compare(p_adv_report, p_scan_ctx)) + { + filter_match_cnt++; + // Information about the filters matched. + scan_evt.params.filter_match.filter_match.uuid_filter_match = true; + is_filter_matched = true; + } + } +#endif + +#if (NRF_BLE_SCAN_APPEARANCE_CNT > 0) + // Check the appearance filter. + if (appearance_filter_enabled) + { + filter_cnt++; + if (adv_appearance_compare(p_adv_report, p_scan_ctx)) + { + filter_match_cnt++; + // Information about the filters matched. + scan_evt.params.filter_match.filter_match.appearance_filter_match = true; + is_filter_matched = true; + } + } + + scan_evt.scan_evt_id = NRF_BLE_SCAN_EVT_NOT_FOUND; +#endif + + scan_evt.params.filter_match.p_adv_report = p_adv_report; + + // In the multifilter mode, the number of the active filters must equal the number of the filters matched to generate the notification. + if (all_filter_mode && (filter_match_cnt == filter_cnt)) + { + scan_evt.scan_evt_id = NRF_BLE_SCAN_EVT_FILTER_MATCH; + nrf_ble_scan_connect_with_target(p_scan_ctx, p_adv_report); + } + // In the normal filter mode, only one filter match is needed to generate the notification to the main application. + else if ((!all_filter_mode) && is_filter_matched) + { + scan_evt.scan_evt_id = NRF_BLE_SCAN_EVT_FILTER_MATCH; + nrf_ble_scan_connect_with_target(p_scan_ctx, p_adv_report); + } + else + { + scan_evt.scan_evt_id = NRF_BLE_SCAN_EVT_NOT_FOUND; + scan_evt.params.p_not_found = p_adv_report; + + } + + // If the event handler is not NULL, notify the main application. + if (p_scan_ctx->evt_handler != NULL) + { + p_scan_ctx->evt_handler(&scan_evt); + } + +#endif // NRF_BLE_SCAN_FILTER_ENABLE + + // Resume the scanning. + UNUSED_RETURN_VALUE(sd_ble_gap_scan_start(NULL, &p_scan_ctx->scan_buffer)); +} + + +/**@brief Function for checking whether the whitelist is used. + * + * @param[in] p_scan_ctx Scanning Module instance. + */ +bool is_whitelist_used(nrf_ble_scan_t const * const p_scan_ctx) +{ + if (p_scan_ctx->scan_params.filter_policy == BLE_GAP_SCAN_FP_WHITELIST || + p_scan_ctx->scan_params.filter_policy == BLE_GAP_SCAN_FP_WHITELIST_NOT_RESOLVED_DIRECTED) + { + return true; + } + + return false; +} + + +/**@brief Function for restoring the default scanning parameters. + * + * @param[out] p_scan_ctx Pointer to the Scanning Module instance. + */ +static void nrf_ble_scan_default_param_set(nrf_ble_scan_t * const p_scan_ctx) +{ + // Set the default parameters. + p_scan_ctx->scan_params.active = 1; +#if (NRF_SD_BLE_API_VERSION > 7) + p_scan_ctx->scan_params.interval_us = NRF_BLE_SCAN_SCAN_INTERVAL * UNIT_0_625_MS; + p_scan_ctx->scan_params.window_us = NRF_BLE_SCAN_SCAN_WINDOW * UNIT_0_625_MS; +#else + p_scan_ctx->scan_params.interval = NRF_BLE_SCAN_SCAN_INTERVAL; + p_scan_ctx->scan_params.window = NRF_BLE_SCAN_SCAN_WINDOW; +#endif // #if (NRF_SD_BLE_API_VERSION > 7) + p_scan_ctx->scan_params.timeout = NRF_BLE_SCAN_SCAN_DURATION; + p_scan_ctx->scan_params.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL; + p_scan_ctx->scan_params.scan_phys = BLE_GAP_PHY_1MBPS; +} + + +/**@brief Function for setting the default connection parameters. + * + * @param[out] p_scan_ctx Pointer to the Scanning Module instance. + */ +static void nrf_ble_scan_default_conn_param_set(nrf_ble_scan_t * const p_scan_ctx) +{ + p_scan_ctx->conn_params.conn_sup_timeout = + (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_SUPERVISION_TIMEOUT, UNIT_10_MS); + p_scan_ctx->conn_params.min_conn_interval = + (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL, UNIT_1_25_MS); + p_scan_ctx->conn_params.max_conn_interval = + (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL, UNIT_1_25_MS); + p_scan_ctx->conn_params.slave_latency = + (uint16_t)NRF_BLE_SCAN_SLAVE_LATENCY; +} + + +/**@brief Function for calling the BLE_GAP_EVT_TIMEOUT event. + * + * @param[in] p_scan_ctx Pointer to the Scanning Module instance. + * @param[in] p_gap GAP event structure. + */ +static void nrf_ble_scan_on_timeout(nrf_ble_scan_t const * const p_scan_ctx, + ble_gap_evt_t const * const p_gap) +{ + ble_gap_evt_timeout_t const * p_timeout = &p_gap->params.timeout; + scan_evt_t scan_evt; + + memset(&scan_evt, 0, sizeof(scan_evt)); + + if (p_timeout->src == BLE_GAP_TIMEOUT_SRC_SCAN) + { + NRF_LOG_DEBUG("BLE_GAP_SCAN_TIMEOUT"); + if (p_scan_ctx->evt_handler != NULL) + { + scan_evt.scan_evt_id = NRF_BLE_SCAN_EVT_SCAN_TIMEOUT; + scan_evt.p_scan_params = &p_scan_ctx->scan_params; + scan_evt.params.timeout.src = p_timeout->src; + + p_scan_ctx->evt_handler(&scan_evt); + } + } +} + + +/**@brief Function for stopping the scanning. + */ +void nrf_ble_scan_stop(void) +{ + // It is ok to ignore the function return value here, because this function can return NRF_SUCCESS or + // NRF_ERROR_INVALID_STATE, when app is not in the scanning state. + UNUSED_RETURN_VALUE(sd_ble_gap_scan_stop()); +} + + +ret_code_t nrf_ble_scan_init(nrf_ble_scan_t * const p_scan_ctx, + nrf_ble_scan_init_t const * const p_init, + nrf_ble_scan_evt_handler_t evt_handler) +{ + VERIFY_PARAM_NOT_NULL(p_scan_ctx); + + p_scan_ctx->evt_handler = evt_handler; + +#if (NRF_BLE_SCAN_FILTER_ENABLE == 1) + // Disable all scanning filters. + memset(&p_scan_ctx->scan_filters, 0, sizeof(p_scan_ctx->scan_filters)); +#endif + + // If the pointer to the initialization structure exist, use it to scan the configuration. + if (p_init != NULL) + { + p_scan_ctx->connect_if_match = p_init->connect_if_match; + p_scan_ctx->conn_cfg_tag = p_init->conn_cfg_tag; + + if (p_init->p_scan_param != NULL) + { + p_scan_ctx->scan_params = *p_init->p_scan_param; + } + else + { + // Use the default static configuration. + nrf_ble_scan_default_param_set(p_scan_ctx); + } + + if (p_init->p_conn_param != NULL) + { + p_scan_ctx->conn_params = *p_init->p_conn_param; + } + else + { + // Use the default static configuration. + nrf_ble_scan_default_conn_param_set(p_scan_ctx); + } + } + // If pointer is NULL, use the static default configuration. + else + { + nrf_ble_scan_default_param_set(p_scan_ctx); + nrf_ble_scan_default_conn_param_set(p_scan_ctx); + + p_scan_ctx->connect_if_match = false; + } + + // Assign a buffer where the advertising reports are to be stored by the SoftDevice. + p_scan_ctx->scan_buffer.p_data = p_scan_ctx->scan_buffer_data; + p_scan_ctx->scan_buffer.len = NRF_BLE_SCAN_BUFFER; + + return NRF_SUCCESS; +} + + +ret_code_t nrf_ble_scan_start(nrf_ble_scan_t const * const p_scan_ctx) +{ + VERIFY_PARAM_NOT_NULL(p_scan_ctx); + + ret_code_t err_code; + scan_evt_t scan_evt; + + memset(&scan_evt, 0, sizeof(scan_evt)); + + nrf_ble_scan_stop(); + + // If the whitelist is used and the event handler is not NULL, send the whitelist request to the main application. + if (is_whitelist_used(p_scan_ctx)) + { + if (p_scan_ctx->evt_handler != NULL) + { + scan_evt.scan_evt_id = NRF_BLE_SCAN_EVT_WHITELIST_REQUEST; + p_scan_ctx->evt_handler(&scan_evt); + } + } + + // Start the scanning. + err_code = sd_ble_gap_scan_start(&p_scan_ctx->scan_params, &p_scan_ctx->scan_buffer); + + // It is okay to ignore this error, because the scan stopped earlier. + if ((err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_SUCCESS)) + { + NRF_LOG_ERROR("sd_ble_gap_scan_start returned 0x%x", err_code); + return (err_code); + } + NRF_LOG_DEBUG("Scanning"); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_ble_scan_params_set(nrf_ble_scan_t * const p_scan_ctx, + ble_gap_scan_params_t const * const p_scan_param) +{ + VERIFY_PARAM_NOT_NULL(p_scan_ctx); + + nrf_ble_scan_stop(); + + if (p_scan_param != NULL) + { + // Assign new scanning parameters. + p_scan_ctx->scan_params = *p_scan_param; + } + else + { + // If NULL, use the default static configuration. + nrf_ble_scan_default_param_set(p_scan_ctx); + } + + NRF_LOG_DEBUG("Scanning parameters have been changed successfully"); + + return NRF_SUCCESS; +} + + +/**@brief Function for calling the BLE_GAP_EVT_CONNECTED event. + * + * @param[in] p_scan_ctx Pointer to the Scanning Module instance. + * @param[in] p_gap_evt GAP event structure. + */ +static void nrf_ble_scan_on_connected_evt(nrf_ble_scan_t const * const p_scan_ctx, + ble_gap_evt_t const * const p_gap_evt) +{ + scan_evt_t scan_evt; + + memset(&scan_evt, 0, sizeof(scan_evt)); + scan_evt.scan_evt_id = NRF_BLE_SCAN_EVT_CONNECTED; + scan_evt.params.connected.p_connected = &p_gap_evt->params.connected; + scan_evt.params.connected.conn_handle = p_gap_evt->conn_handle; + scan_evt.p_scan_params = &p_scan_ctx->scan_params; + + if (p_scan_ctx->evt_handler != NULL) + { + p_scan_ctx->evt_handler(&scan_evt); + } +} + + +ret_code_t nrf_ble_scan_copy_addr_to_sd_gap_addr(ble_gap_addr_t * p_gap_addr, + const uint8_t addr[BLE_GAP_ADDR_LEN]) +{ + VERIFY_PARAM_NOT_NULL(p_gap_addr); + + for (uint8_t i = 0; i < BLE_GAP_ADDR_LEN; ++i) + { + p_gap_addr->addr[i] = addr[BLE_GAP_ADDR_LEN - (i + 1)]; + } + + return NRF_SUCCESS; +} + + +void nrf_ble_scan_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_contex) +{ + nrf_ble_scan_t * p_scan_data = (nrf_ble_scan_t *)p_contex; + ble_gap_evt_adv_report_t const * p_adv_report = &p_ble_evt->evt.gap_evt.params.adv_report; + ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_ADV_REPORT: + nrf_ble_scan_on_adv_report(p_scan_data, p_adv_report); + break; + + case BLE_GAP_EVT_TIMEOUT: + nrf_ble_scan_on_timeout(p_scan_data, p_gap_evt); + break; + + case BLE_GAP_EVT_CONNECTED: + nrf_ble_scan_on_connected_evt(p_scan_data, p_gap_evt); + break; + + default: + break; + } +} + + +#endif // NRF_BLE_SCAN_ENABLED + diff --git a/components/ble/nrf_ble_scan/nrf_ble_scan.h b/components/ble/nrf_ble_scan/nrf_ble_scan.h new file mode 100644 index 0000000..88dcd7b --- /dev/null +++ b/components/ble/nrf_ble_scan/nrf_ble_scan.h @@ -0,0 +1,500 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** @file + * + * @defgroup nrf_ble_scan Scanning Module + * @{ + * @ingroup ble_sdk_lib + * @brief Module for handling the BLE scanning. + * + * @details The Scanning Module handles the BLE scanning for your application. + * The module offers several criteria for filtering the devices available for connection, + * and it can also work in the simple mode without using the filtering. + * If an event handler is provided, your main application can react to a filter match or to the need of setting the whitelist. + * The module can also be configured to automatically + * connect after it matches a filter or a device from the whitelist. + * + * @note The Scanning Module also supports applications with a multicentral link. + */ + +#ifndef NRF_BLE_SCAN_H__ +#define NRF_BLE_SCAN_H__ + +#include +#include +#include +#include "ble.h" +#include "ble_gap.h" +#include "app_util.h" +#include "sdk_errors.h" +#include "sdk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@defgroup NRF_BLE_SCAN_FILTER_MODE Filter modes + * @{ */ +#define NRF_BLE_SCAN_NAME_FILTER (0x01) /**< Filters the device name. */ +#define NRF_BLE_SCAN_ADDR_FILTER (0x02) /**< Filters the device address. */ +#define NRF_BLE_SCAN_UUID_FILTER (0x04) /**< Filters the UUID. */ +#define NRF_BLE_SCAN_APPEARANCE_FILTER (0x08) /**< Filters the appearance. */ +#define NRF_BLE_SCAN_SHORT_NAME_FILTER (0x10) /**< Filters the device short name. */ +#define NRF_BLE_SCAN_ALL_FILTER (0x1F) /**< Uses the combination of all filters. */ +/* @} */ + +/**@brief Macro for defining a nrf_ble_scan instance. + * + * @param _name Name of the instance. + * @hideinitializer + */ +#define NRF_BLE_SCAN_DEF(_name) \ + static nrf_ble_scan_t _name; \ + NRF_SDH_BLE_OBSERVER(_name ## _ble_obs, \ + NRF_BLE_SCAN_OBSERVER_PRIO, \ + nrf_ble_scan_on_ble_evt, &_name); \ + + +/**@brief Enumeration for scanning events. + * + * @details These events are propagated to the main application if a handler is provided during + * the initialization of the Scanning Module. @ref NRF_BLE_SCAN_EVT_WHITELIST_REQUEST cannot be + * ignored if whitelist is used. + */ +typedef enum +{ + NRF_BLE_SCAN_EVT_FILTER_MATCH, /**< A filter is matched or all filters are matched in the multifilter mode. */ + NRF_BLE_SCAN_EVT_WHITELIST_REQUEST, /**< Request the whitelist from the main application. For whitelist scanning to work, the whitelist must be set when this event occurs. */ + NRF_BLE_SCAN_EVT_WHITELIST_ADV_REPORT, /**< Send notification to the main application when a device from the whitelist is found. */ + NRF_BLE_SCAN_EVT_NOT_FOUND, /**< The filter was not matched for the scan data. */ + NRF_BLE_SCAN_EVT_SCAN_TIMEOUT, /**< Scan timeout. */ + NRF_BLE_SCAN_EVT_CONNECTING_ERROR, /**< Error occurred when establishing the connection. In this event, an error is passed from the function call @ref sd_ble_gap_connect. */ + NRF_BLE_SCAN_EVT_CONNECTED /**< Connected to device. */ +} nrf_ble_scan_evt_t; + + +/**@brief Types of filters. + */ +typedef enum +{ + SCAN_NAME_FILTER, /**< Filter for names. */ + SCAN_SHORT_NAME_FILTER, /**< Filter for short names. */ + SCAN_ADDR_FILTER, /**< Filter for addresses. */ + SCAN_UUID_FILTER, /**< Filter for UUIDs. */ + SCAN_APPEARANCE_FILTER, /**< Filter for appearances. */ +} nrf_ble_scan_filter_type_t; + + +typedef struct +{ + char const * p_short_name; /**< Pointer to the short name. */ + uint8_t short_name_min_len; /**< Minimum length of the short name. */ +} nrf_ble_scan_short_name_t; + +/**@brief Structure for Scanning Module initialization. + */ +typedef struct +{ + ble_gap_scan_params_t const * p_scan_param; /**< BLE GAP scan parameters required to initialize the module. Can be initialized as NULL. If NULL, the parameters required to initialize the module are loaded from the static configuration. */ + bool connect_if_match; /**< If set to true, the module automatically connects after a filter match or successful identification of a device from the whitelist. */ + ble_gap_conn_params_t const * p_conn_param; /**< Connection parameters. Can be initialized as NULL. If NULL, the default static configuration is used. */ + uint8_t conn_cfg_tag; /**< Variable to keep track of what connection settings will be used if a filer match or a whitelist match results in a connection. */ +} nrf_ble_scan_init_t; + + +/**@brief Structure for setting the filter status. + * + * @details This structure is used for sending filter status to the main application. + */ +typedef struct +{ + uint8_t name_filter_match : 1; /**< Set to 1 if name filter is matched. */ + uint8_t address_filter_match : 1; /**< Set to 1 if address filter is matched. */ + uint8_t uuid_filter_match : 1; /**< Set to 1 if uuid filter is matched. */ + uint8_t appearance_filter_match : 1; /**< Set to 1 if appearance filter is matched. */ + uint8_t short_name_filter_match : 1; /**< Set to 1 if short name filter is matched. */ +} nrf_ble_scan_filter_match; + + +/**@brief Event structure for @ref NRF_BLE_SCAN_EVT_FILTER_MATCH. + */ +typedef struct +{ + ble_gap_evt_adv_report_t const * p_adv_report; /**< Event structure for @ref BLE_GAP_EVT_ADV_REPORT. This data allows the main application to establish connection. */ + nrf_ble_scan_filter_match filter_match; /**< Matching filters. Information about matched filters. */ +} nrf_ble_scan_evt_filter_match_t; + + +/**@brief Event structure for @ref NRF_BLE_SCAN_EVT_CONNECTING_ERROR. + */ +typedef struct +{ + ret_code_t err_code; /**< Indicates success or failure of an API procedure. In case of failure, a comprehensive error code indicating the cause or reason for failure is provided. */ +} nrf_ble_scan_evt_connecting_err_t; + + +/**@brief Event structure for @ref NRF_BLE_SCAN_EVT_CONNECTED. + */ +typedef struct +{ + ble_gap_evt_connected_t const * p_connected; /**< Connected event parameters. */ + uint16_t conn_handle; /**< Connection handle of the device on which the event occurred. */ +} nrf_ble_scan_evt_connected_t; + + +/**@brief Structure for Scanning Module event data. + * + * @details This structure is used to send module event data to the main application when an event occurs. + */ +typedef struct +{ + nrf_ble_scan_evt_t scan_evt_id; /**< Type of event propagated to the main application. */ + union + { + nrf_ble_scan_evt_filter_match_t filter_match; /**< Scan filter match. */ + ble_gap_evt_timeout_t timeout; /**< Timeout event parameters. */ + ble_gap_evt_adv_report_t const * p_whitelist_adv_report; /**< Advertising report event parameters for whitelist. */ + ble_gap_evt_adv_report_t const * p_not_found; /**< Advertising report event parameters when filter is not found. */ + nrf_ble_scan_evt_connected_t connected; /**< Connected event parameters. */ + nrf_ble_scan_evt_connecting_err_t connecting_err; /**< Error event when connecting. Propagates the error code returned by the SoftDevice API @ref sd_ble_gap_scan_start. */ + } params; + ble_gap_scan_params_t const * p_scan_params; /**< GAP scanning parameters. These parameters are needed to establish connection. */ +} scan_evt_t; + + +/**@brief BLE scanning event handler type. + */ +typedef void (*nrf_ble_scan_evt_handler_t)(scan_evt_t const * p_scan_evt); + + +#if (NRF_BLE_SCAN_FILTER_ENABLE == 1) + +#if (NRF_BLE_SCAN_NAME_CNT > 0) +typedef struct +{ + char target_name[NRF_BLE_SCAN_NAME_CNT][NRF_BLE_SCAN_NAME_MAX_LEN]; /**< Names that the main application will scan for, and that will be advertised by the peripherals. */ + uint8_t name_cnt; /**< Name filter counter. */ + bool name_filter_enabled; /**< Flag to inform about enabling or disabling this filter. */ +} nrf_ble_scan_name_filter_t; +#endif + +#if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0) +typedef struct +{ + struct + { + char short_target_name[NRF_BLE_SCAN_SHORT_NAME_MAX_LEN]; /**< Short names that the main application will scan for, and that will be advertised by the peripherals. */ + uint8_t short_name_min_len; /**< Minimum length of the short name. */ + } short_name[NRF_BLE_SCAN_SHORT_NAME_CNT]; + uint8_t name_cnt; /**< Short name filter counter. */ + bool short_name_filter_enabled; /**< Flag to inform about enabling or disabling this filter. */ +} nrf_ble_scan_short_name_filter_t; +#endif + +#if (NRF_BLE_SCAN_ADDRESS_CNT > 0) +typedef struct +{ + ble_gap_addr_t target_addr[NRF_BLE_SCAN_ADDRESS_CNT]; /**< Addresses in the same format as the format used by the SoftDevice that the main application will scan for, and that will be advertised by the peripherals. */ + uint8_t addr_cnt; /**< Address filter counter. */ + bool addr_filter_enabled; /**< Flag to inform about enabling or disabling this filter. */ +} nrf_ble_scan_addr_filter_t; +#endif + +#if (NRF_BLE_SCAN_UUID_CNT > 0) +typedef struct +{ + ble_uuid_t uuid[NRF_BLE_SCAN_UUID_CNT]; /**< UUIDs that the main application will scan for, and that will be advertised by the peripherals. */ + uint8_t uuid_cnt; /**< UUID filter counter. */ + bool uuid_filter_enabled; /**< Flag to inform about enabling or disabling this filter. */ +} nrf_ble_scan_uuid_filter_t; +#endif + +#if (NRF_BLE_SCAN_APPEARANCE_CNT > 0) +typedef struct +{ + uint16_t appearance[NRF_BLE_SCAN_APPEARANCE_CNT]; /**< Apperances that the main application will scan for, and that will be advertised by the peripherals. */ + uint8_t appearance_cnt; /**< Appearance filter counter. */ + bool appearance_filter_enabled; /**< Flag to inform about enabling or disabling this filter. */ +} nrf_ble_scan_appearance_filter_t; +#endif + +/**@brief Filters data. + * + * @details This structure contains all filter data and the information about enabling and disabling any type of filters. + * Flag all_filter_mode informs about the filter mode. If this flag is set, then all types of enabled + * filters must be matched for the module to send a notification to the main application. Otherwise, it is enough to match + * one of filters to send notification. + */ +typedef struct +{ +#if (NRF_BLE_SCAN_NAME_CNT > 0) + nrf_ble_scan_name_filter_t name_filter; /**< Name filter data. */ +#endif +#if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0) + nrf_ble_scan_short_name_filter_t short_name_filter; /**< Short name filter data. */ +#endif +#if (NRF_BLE_SCAN_ADDRESS_CNT > 0) + nrf_ble_scan_addr_filter_t addr_filter; /**< Address filter data. */ +#endif +#if (NRF_BLE_SCAN_UUID_CNT > 0) + nrf_ble_scan_uuid_filter_t uuid_filter; /**< UUID filter data. */ +#endif +#if (NRF_BLE_SCAN_APPEARANCE_CNT > 0) + nrf_ble_scan_appearance_filter_t appearance_filter; /**< Appearance filter data. */ +#endif + bool all_filters_mode; /**< Filter mode. If true, all set filters must be matched to generate an event.*/ +} nrf_ble_scan_filters_t; + +#endif // NRF_BLE_SCAN_FILTER_ENABLE + +/**@brief Scan module instance. Options for the different scanning modes. + * + * @details This structure stores all module settings. It is used to enable or disable scanning modes + * and to configure filters. + */ +typedef struct +{ +#if (NRF_BLE_SCAN_FILTER_ENABLE == 1) + nrf_ble_scan_filters_t scan_filters; /**< Filter data. */ +#endif + bool connect_if_match; /**< If set to true, the module automatically connects after a filter match or successful identification of a device from the whitelist. */ + ble_gap_conn_params_t conn_params; /**< Connection parameters. */ + uint8_t conn_cfg_tag; /**< Variable to keep track of what connection settings will be used if a filer match or a whitelist match results in a connection. */ + ble_gap_scan_params_t scan_params; /**< GAP scanning parameters. */ + nrf_ble_scan_evt_handler_t evt_handler; /**< Handler for the scanning events. Can be initialized as NULL if no handling is implemented in the main application. */ + uint8_t scan_buffer_data[NRF_BLE_SCAN_BUFFER]; /**< Buffer where advertising reports will be stored by the SoftDevice. */ + ble_data_t scan_buffer; /**< Structure-stored pointer to the buffer where advertising reports will be stored by the SoftDevice. */ +} nrf_ble_scan_t; + + +/**@brief Function for indicating that the Scanning Module is using the whitelist. + * + * @param[in] p_scan_ctx Pointer to the Scanning Module instance. + * + * @return Whether the whitelist is used. + */ +bool is_whitelist_used(nrf_ble_scan_t const * const p_scan_ctx); + + +/**@brief Function for initializing the Scanning Module. + * + * @param[out] p_scan_ctx Pointer to the Scanning Module instance. This structure must be supplied by + * the application. It is initialized by this function and is later used + * to identify this particular module instance. + * + * @param[in] p_init Can be initialized as NULL. If NULL, the parameters required to initialize + * the module are loaded from static configuration. + * If module is to establish the connection automatically, this must be initialized + * with the relevant data. + * @param[in] evt_handler Handler for the scanning events. + * Can be initialized as NULL if no handling is implemented in the main application. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_NULL When the NULL pointer is passed as input. + */ +ret_code_t nrf_ble_scan_init(nrf_ble_scan_t * const p_scan_ctx, + nrf_ble_scan_init_t const * const p_init, + nrf_ble_scan_evt_handler_t evt_handler); + + +/**@brief Function for starting scanning. + * + * @details This function starts the scanning according to the configuration set during the initialization. + * + * @param[in] p_scan_ctx Pointer to the Scanning Module instance. + * + * @retval NRF_SUCCESS If scanning started. Otherwise, an error code is returned. + * @retval NRF_ERROR_NULL If NULL pointer is passed as input. + * + * @return This API propagates the error code returned by the + * SoftDevice API @ref sd_ble_gap_scan_start. + */ +ret_code_t nrf_ble_scan_start(nrf_ble_scan_t const * const p_scan_ctx); + + +/**@brief Function for stopping scanning. + */ +void nrf_ble_scan_stop(void); + + +#if (NRF_BLE_SCAN_FILTER_ENABLE == 1) + +/**@brief Function for enabling filtering. + * + * @details The filters can be combined with each other. For example, you can enable one filter or several filters. + * For example, (NRF_BLE_SCAN_NAME_FILTER | NRF_BLE_SCAN_UUID_FILTER) enables UUID and name filters. + * + * @param[in] mode Filter mode: @ref NRF_BLE_SCAN_FILTER_MODE. + * @param[in] match_all If this flag is set, all types of enabled filters must be matched + * before generating @ref NRF_BLE_SCAN_EVT_FILTER_MATCH to the main application. Otherwise, it is enough to match + * one filter to trigger the filter match event. + * @param[in] p_scan_ctx Pointer to the Scanning Module instance. + * + * @retval NRF_SUCCESS If the filters are enabled successfully. + * @retval NRF_ERROR_INVALID_PARAM If the filter mode is incorrect. Available filter modes: @ref NRF_BLE_SCAN_FILTER_MODE. + * @retval NRF_ERROR_NULL If a NULL pointer is passed as input. + */ +ret_code_t nrf_ble_scan_filters_enable(nrf_ble_scan_t * const p_scan_ctx, + uint8_t mode, + bool match_all); + + +/**@brief Function for disabling filtering. + * + * @details This function disables all filters. + * Even if the automatic connection establishing is enabled, + * the connection will not be established with the first + device found after this function is called. + * + * @param[in] p_scan_ctx Pointer to the Scanning Module instance. + * + * @retval NRF_SUCCESS If filters are disabled successfully. + * @retval NRF_ERROR_NULL If a NULL pointer is passed as input. + */ +ret_code_t nrf_ble_scan_filters_disable(nrf_ble_scan_t * const p_scan_ctx); + + +/**@brief Function for getting filter status. + * + * @details This function returns the filter setting and whether it is enabled or disabled. + + * @param[out] p_status Filter status. + * @param[in] p_scan_ctx Pointer to the Scanning Module instance. + * + * @retval NRF_SUCCESS If filter status is returned. + * @retval NRF_ERROR_NULL If a NULL pointer is passed as input. + */ +ret_code_t nrf_ble_scan_filter_get(nrf_ble_scan_t * const p_scan_ctx, + nrf_ble_scan_filters_t * p_status); + + +/**@brief Function for adding any type of filter to the scanning. + * + * @details This function adds a new filter by type @ref nrf_ble_scan_filter_type_t. + * The filter will be added if the number of filters of a given type does not exceed @ref NRF_BLE_SCAN_UUID_CNT, + * @ref NRF_BLE_SCAN_NAME_CNT, @ref NRF_BLE_SCAN_ADDRESS_CNT, or @ref NRF_BLE_SCAN_APPEARANCE_CNT, depending on the filter type, + * and if the same filter has not already been set. + * + * @param[in,out] p_scan_ctx Pointer to the Scanning Module instance. + * @param[in] type Filter type. + * @param[in] p_data The filter data to add. + * + * @retval NRF_SUCCESS If the filter is added successfully. + * @retval NRF_ERROR_NULL If a NULL pointer is passed as input. + * @retval NRF_ERROR_DATA_SIZE If the name filter length is too long. Maximum name filter length corresponds to @ref NRF_BLE_SCAN_NAME_MAX_LEN. + * @retval NRF_ERROR_NO_MEMORY If the number of available filters is exceeded. + * @retval NRF_ERROR_INVALID_PARAM If the filter type is incorrect. Available filter types: @ref nrf_ble_scan_filter_type_t. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If the BLE address type is invalid. + */ +ret_code_t nrf_ble_scan_filter_set(nrf_ble_scan_t * const p_scan_ctx, + nrf_ble_scan_filter_type_t type, + void const * p_data); + + +/**@brief Function for removing all set filters. + * + * @details The function removes all previously set filters. + * + * @note After using this function the filters are still enabled. + * + * @param[in,out] p_scan_ctx Pointer to the Scanning Module instance. + * + * @retval NRF_SUCCESS If all filters are removed successfully. + */ +ret_code_t nrf_ble_scan_all_filter_remove(nrf_ble_scan_t * const p_scan_ctx); + + +#endif // NRF_BLE_SCAN_FILTER_ENABLE + + +/**@brief Function for changing the scanning parameters. + * + **@details Use this function to change scanning parameters. During the parameter change + * the scan is stopped. To resume scanning, use @ref nrf_ble_scan_start. + * Scanning parameters can be set to NULL. If so, the default static configuration + * is used. For example, use this function when the @ref NRF_BLE_SCAN_EVT_WHITELIST_ADV_REPORT event is generated. + * The generation of this event means that there is a risk that the whitelist is empty. In such case, this function can change + * the scanning parameters, so that the whitelist is not used, and you avoid the error caused by scanning with the whitelist + * when there are no devices on the whitelist. + * + * @param[in,out] p_scan_ctx Pointer to the Scanning Module instance. + * @param[in] p_scan_param GAP scanning parameters. Can be initialized as NULL. + * + * @retval NRF_SUCCESS If parameters are changed successfully. + * @retval NRF_ERROR_NULL If a NULL pointer is passed as input. + */ +ret_code_t nrf_ble_scan_params_set(nrf_ble_scan_t * const p_scan_ctx, + ble_gap_scan_params_t const * p_scan_param); + + +/**@brief Function for handling the BLE stack events of the application. + * + * @param[in] p_ble_evt Pointer to the BLE event received. + * @param[in,out] p_scan Pointer to the Scanning Module instance. + */ +void nrf_ble_scan_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_scan); + + +/**@brief Function for converting the raw address to the SoftDevice GAP address. + * + * @details This function inverts the byte order in the address. If you enter the address as it is displayed + * (for example, on a phone screen from left to right), you must use this function to + * convert the address to the SoftDevice address type. + * + * @note This function does not decode an address type. + * + * @param[out] p_gap_addr The Bluetooth Low Energy address. + * @param[in] addr Address to be converted to the SoftDevice address. + * + * @retval NRF_ERROR_NULL If a NULL pointer is passed as input. + * @retval NRF_SUCCESS If the address is copied and converted successfully. + */ +ret_code_t nrf_ble_scan_copy_addr_to_sd_gap_addr(ble_gap_addr_t * p_gap_addr, + uint8_t const addr[BLE_GAP_ADDR_LEN]); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_BLE_SCAN_H__ + +/** @} */ diff --git a/components/ble/peer_manager/auth_status_tracker.c b/components/ble/peer_manager/auth_status_tracker.c new file mode 100644 index 0000000..884bd3a --- /dev/null +++ b/components/ble/peer_manager/auth_status_tracker.c @@ -0,0 +1,340 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(PEER_MANAGER) && NRF_MODULE_ENABLED(PM_RA_PROTECTION) +#include "auth_status_tracker.h" + +#include "app_timer.h" +#include "id_manager.h" + +#define NRF_LOG_MODULE_NAME peer_manager_ast +#if PM_LOG_ENABLED + #define NRF_LOG_LEVEL PM_LOG_LEVEL + #define NRF_LOG_INFO_COLOR PM_LOG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR PM_LOG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // PM_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); +#include "nrf_strerror.h" + +// Assume that waiting interval doubles with each failed authentication. +//lint --emacro((647),PENALITY_LVL_TO_PENALITY_MS) +#define PAIR_REWARD_TICKS APP_TIMER_TICKS(PM_RA_PROTECTION_REWARD_PERIOD) +#define PENALITY_LVL_TO_PENALITY_MS(_lvl) (PM_RA_PROTECTION_MIN_WAIT_INTERVAL * (1 << _lvl)) +#define PENALITY_LVL_TO_PENALITY_TICKS(_lvl) APP_TIMER_TICKS(PENALITY_LVL_TO_PENALITY_MS(_lvl)) +#define PENALITY_LVL_NEXT_SET(_lvl) \ + _lvl = (PENALITY_LVL_TO_PENALITY_MS(_lvl) >= (PM_RA_PROTECTION_MAX_WAIT_INTERVAL)) ? \ + (_lvl) : (_lvl + 1) + + +/**@brief Tracked peer state. */ +typedef struct +{ + ble_gap_addr_t peer_addr; /**< BLE address, used to identify peer. */ + uint32_t reward_ticks; /**< Accumulated reward ticks, used to decrease penality level + after achieving certain threshold. */ + uint32_t penality_ticks; /**< Accumulated penality ticks, used to determine remaining time + in which pairing attempts should be rejected. */ + uint8_t penality_lvl; /**< Accumulated penality level, used to determine waiting interval + after failed authorization attempt. */ + bool is_active; /**< Flag indicating that the waiting interval for this peer has not + passed yet. */ + bool is_valid; /**< Flag indicating that this entry is valid in the peer blacklist. */ +} blacklisted_peer_t; + +APP_TIMER_DEF(m_pairing_attempt_timer); +static blacklisted_peer_t m_blacklisted_peers[PM_RA_PROTECTION_TRACKED_PEERS_NUM]; +static uint32_t m_ticks_cnt; + + +/**@brief Function for updating the state of blacklisted peers after timer has been stopped or + * timed out. + * + * @param[in] ticks_passed The number of ticks since the timer has started. + */ +static uint32_t blacklisted_peers_state_update(uint32_t ticks_passed) +{ + uint32_t minimal_ticks = UINT32_MAX; + + for (uint32_t id = 0; id < ARRAY_SIZE(m_blacklisted_peers); id++) + { + blacklisted_peer_t * p_bl_peer = &m_blacklisted_peers[id]; + + if (p_bl_peer->is_valid) + { + if (p_bl_peer->is_active) + { + if (p_bl_peer->penality_ticks > ticks_passed) + { + p_bl_peer->penality_ticks -= ticks_passed; + minimal_ticks = MIN(minimal_ticks, p_bl_peer->penality_ticks); + } + else + { + p_bl_peer->is_active = false; + + if (p_bl_peer->penality_lvl == 0) + { + p_bl_peer->is_valid = false; + NRF_LOG_DEBUG("Peer has been removed from the blacklist, its address:"); + NRF_LOG_HEXDUMP_DEBUG(p_bl_peer->peer_addr.addr, + sizeof(p_bl_peer->peer_addr.addr)); + } + else + { + minimal_ticks = MIN(minimal_ticks, PAIR_REWARD_TICKS); + } + + NRF_LOG_DEBUG("Pairing waiting interval has expired for:"); + NRF_LOG_HEXDUMP_DEBUG(p_bl_peer->peer_addr.addr, + sizeof(p_bl_peer->peer_addr.addr)); + } + } + else + { + if (p_bl_peer->penality_lvl == 0) + { + p_bl_peer->is_valid = false; + NRF_LOG_DEBUG("Peer has been removed from the blacklist, its address:"); + NRF_LOG_HEXDUMP_DEBUG(p_bl_peer->peer_addr.addr, + sizeof(p_bl_peer->peer_addr.addr)); + } + else + { + p_bl_peer->reward_ticks += ticks_passed; + if (p_bl_peer->reward_ticks >= PAIR_REWARD_TICKS) + { + p_bl_peer->penality_lvl--; + p_bl_peer->reward_ticks -= PAIR_REWARD_TICKS; + NRF_LOG_DEBUG("Peer penality level has decreased to %d for device:", + p_bl_peer->penality_lvl); + NRF_LOG_HEXDUMP_DEBUG(p_bl_peer->peer_addr.addr, + sizeof(p_bl_peer->peer_addr.addr)); + } + + minimal_ticks = MIN(minimal_ticks, + (PAIR_REWARD_TICKS - p_bl_peer->reward_ticks)); + } + } + } + } + + return minimal_ticks; +} + + +/**@brief Function for handling state transition of blacklisted peers. + * + * @param[in] context Context containing the number of ticks since the timer has started. + */ +static void blacklisted_peers_state_transition_handle(void * context) +{ + ret_code_t err_code; + uint32_t minimal_ticks; + uint32_t ticks_passed = (uint32_t) context; + + minimal_ticks = blacklisted_peers_state_update(ticks_passed); + m_ticks_cnt = app_timer_cnt_get(); + + if (minimal_ticks != UINT32_MAX) + { + err_code = app_timer_start(m_pairing_attempt_timer, + minimal_ticks, + (void *) minimal_ticks); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_WARNING("app_timer_start() returned %s", nrf_strerror_get(err_code)); + } + NRF_LOG_DEBUG("Restarting the timer"); + } +} + + +ret_code_t ast_init(void) +{ + ret_code_t err_code = app_timer_create(&m_pairing_attempt_timer, + APP_TIMER_MODE_SINGLE_SHOT, + blacklisted_peers_state_transition_handle); + + return err_code; +} + + +void ast_auth_error_notify(uint16_t conn_handle) +{ + ret_code_t err_code; + ble_gap_addr_t peer_addr; + uint32_t new_timeout; + uint32_t free_id = ARRAY_SIZE(m_blacklisted_peers); + bool new_bl_entry = true; + + // Get the peer address associated with connection handle. + err_code = im_ble_addr_get(conn_handle, &peer_addr); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_WARNING("im_ble_addr_get() returned %s. conn_handle: %d. " + "Link was likely disconnected.", + nrf_strerror_get(err_code), + conn_handle); + return; + } + + // Stop the timer and update the state of all blacklisted peers. + err_code = app_timer_stop(m_pairing_attempt_timer); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_WARNING("app_timer_stop() returned %s", nrf_strerror_get(err_code)); + return; + } + + new_timeout = blacklisted_peers_state_update(app_timer_cnt_diff_compute(app_timer_cnt_get(), + m_ticks_cnt)); + m_ticks_cnt = app_timer_cnt_get(); + + // Check if authorization has failed for already blacklisted peer. + for (uint32_t id = 0; id < ARRAY_SIZE(m_blacklisted_peers); id++) + { + blacklisted_peer_t * p_bl_peer = &m_blacklisted_peers[id]; + + if (p_bl_peer->is_valid) + { + if (memcmp(peer_addr.addr, p_bl_peer->peer_addr.addr, BLE_GAP_ADDR_LEN) == 0) + { + uint8_t lvl = p_bl_peer->penality_lvl; + + PENALITY_LVL_NEXT_SET(lvl); + p_bl_peer->penality_lvl = lvl; + p_bl_peer->reward_ticks = 0; + p_bl_peer->penality_ticks = PENALITY_LVL_TO_PENALITY_TICKS(lvl); + + new_timeout = MIN(new_timeout, p_bl_peer->penality_ticks); + + p_bl_peer->is_active = true; + new_bl_entry = false; + + NRF_LOG_DEBUG("Pairing waiting interval has been renewed. " + "Penality level: %d for device:", + lvl); + NRF_LOG_HEXDUMP_DEBUG(p_bl_peer->peer_addr.addr, + sizeof(p_bl_peer->peer_addr.addr)); + } + } + else + { + free_id = id; + } + } + + // Add a new peer to the blacklist. + if (new_bl_entry) + { + if (free_id < ARRAY_SIZE(m_blacklisted_peers)) + { + blacklisted_peer_t * p_bl_peer = &m_blacklisted_peers[free_id]; + + memcpy(&p_bl_peer->peer_addr, &peer_addr, sizeof(peer_addr)); + + p_bl_peer->penality_lvl = 0; + p_bl_peer->reward_ticks = 0; + p_bl_peer->penality_ticks = PENALITY_LVL_TO_PENALITY_TICKS(p_bl_peer->penality_lvl); + + new_timeout = MIN(new_timeout, p_bl_peer->penality_ticks); + + p_bl_peer->is_active = true; + p_bl_peer->is_valid = true; + NRF_LOG_DEBUG("New peer has been added to the blacklist:"); + NRF_LOG_HEXDUMP_DEBUG(p_bl_peer->peer_addr.addr, sizeof(p_bl_peer->peer_addr.addr)); + } + else + { + NRF_LOG_WARNING("No space to blacklist another peer ID"); + } + } + + // Restart the timer. + if (new_timeout != UINT32_MAX) + { + err_code = app_timer_start(m_pairing_attempt_timer, + new_timeout, + (void *) new_timeout); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_WARNING("app_timer_start() returned %s", nrf_strerror_get(err_code)); + } + } +} + + +bool ast_peer_blacklisted(uint16_t conn_handle) +{ + ret_code_t err_code; + ble_gap_addr_t peer_addr; + + err_code = im_ble_addr_get(conn_handle, &peer_addr); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_WARNING("im_ble_addr_get() returned %s. conn_handle: %d. " + "Link was likely disconnected.", + nrf_strerror_get(err_code), + conn_handle); + return true; + } + + for (uint32_t id = 0; id < ARRAY_SIZE(m_blacklisted_peers); id++) + { + blacklisted_peer_t * p_bl_peer = &m_blacklisted_peers[id]; + + if (p_bl_peer->is_valid) + { + if ((memcmp(peer_addr.addr, p_bl_peer->peer_addr.addr, BLE_GAP_ADDR_LEN) == 0) && + (p_bl_peer->is_active)) + { + return true; + } + } + } + + return false; +} + + +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) && NRF_MODULE_ENABLED(PM_RA_PROTECTION) diff --git a/components/ble/peer_manager/auth_status_tracker.h b/components/ble/peer_manager/auth_status_tracker.h new file mode 100644 index 0000000..4496105 --- /dev/null +++ b/components/ble/peer_manager/auth_status_tracker.h @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef AUTH_STATUS_TRACKER_H__ +#define AUTH_STATUS_TRACKER_H__ + +#include +#include "sdk_errors.h" +#include "ble_gap.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @defgroup auth_status_tracker Authorization Status Tracker + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. A module for tracking peers with failed + * authorization attempts. It uses tracking policy, which is described in Bluetooth + * Core Specification v5.0, Vol 3, Part H, Section 2.3.6. + */ + + +/**@brief Function for initializing the Authorization Status Tracker module. + * + * @retval NRF_SUCCESS Initialization was successful. + * @retval Other Other error codes might be returned by the @ref app_timer_create function. + */ +ret_code_t ast_init(void); + + +/**@brief Function for notifying about failed authorization attempts. + * + * @param[in] conn_handle Connection handle on which authorization attempt has failed. + */ +void ast_auth_error_notify(uint16_t conn_handle); + + +/**@brief Function for checking if pairing request must be rejected. + * + * @param[in] conn_handle Connection handle on which this check must be performed. + * + * @retval true If the connected peer is blacklisted. + * @retval false If the connected peer is not blacklisted. + */ +bool ast_peer_blacklisted(uint16_t conn_handle); + + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* AUTH_STATUS_TRACKER_H__ */ diff --git a/components/ble/peer_manager/gatt_cache_manager.c b/components/ble/peer_manager/gatt_cache_manager.c new file mode 100644 index 0000000..0f51935 --- /dev/null +++ b/components/ble/peer_manager/gatt_cache_manager.c @@ -0,0 +1,842 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(PEER_MANAGER) +#include "gatt_cache_manager.h" + +#include "ble_gap.h" +#include "ble_err.h" +#include "ble_conn_state.h" +#include "peer_manager_types.h" +#include "peer_manager_internal.h" +#include "id_manager.h" +#include "gatts_cache_manager.h" +#include "peer_data_storage.h" +#include "peer_database.h" +#include "nrf_mtx.h" + +#define NRF_LOG_MODULE_NAME peer_manager_gcm +#if PM_LOG_ENABLED + #define NRF_LOG_LEVEL PM_LOG_LEVEL + #define NRF_LOG_INFO_COLOR PM_LOG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR PM_LOG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // PM_LOG_ENABLED +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +NRF_LOG_MODULE_REGISTER(); +#include "nrf_strerror.h" + +// The number of registered event handlers. +#define GCM_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) + +// GATT Cache Manager event handler in Peer Manager. +extern void pm_gcm_evt_handler(pm_evt_t * p_gcm_evt); + +// GATT Cache Manager events' handlers. +// The number of elements in this array is GCM_EVENT_HANDLERS_CNT. +static pm_evt_handler_internal_t m_evt_handlers[] = +{ + pm_gcm_evt_handler +}; + +static bool m_module_initialized; +static nrf_mtx_t m_db_update_in_progress_mutex; /**< Mutex indicating whether a local DB write operation is ongoing. */ +static ble_conn_state_user_flag_id_t m_flag_local_db_update_pending; /**< Flag ID for flag collection to keep track of which connections need a local DB update procedure. */ +static ble_conn_state_user_flag_id_t m_flag_local_db_apply_pending; /**< Flag ID for flag collection to keep track of which connections need a local DB apply procedure. */ +static ble_conn_state_user_flag_id_t m_flag_service_changed_pending; /**< Flag ID for flag collection to keep track of which connections need to be sent a service changed indication. */ +static ble_conn_state_user_flag_id_t m_flag_service_changed_sent; /**< Flag ID for flag collection to keep track of which connections have been sent a service changed indication and are waiting for a handle value confirmation. */ +static ble_conn_state_user_flag_id_t m_flag_car_update_pending; /**< Flag ID for flag collection to keep track of which connections need to have their Central Address Resolution value stored. */ +static ble_conn_state_user_flag_id_t m_flag_car_handle_queried; /**< Flag ID for flag collection to keep track of which connections are pending Central Address Resolution handle reply. */ +static ble_conn_state_user_flag_id_t m_flag_car_value_queried; /**< Flag ID for flag collection to keep track of which connections are pending Central Address Resolution value reply. */ + +#ifdef PM_SERVICE_CHANGED_ENABLED + STATIC_ASSERT(PM_SERVICE_CHANGED_ENABLED || !NRF_SDH_BLE_SERVICE_CHANGED, + "PM_SERVICE_CHANGED_ENABLED should be enabled if NRF_SDH_BLE_SERVICE_CHANGED is enabled."); +#else + #define PM_SERVICE_CHANGED_ENABLED 1 +#endif + +/**@brief Function for resetting the module variable(s) of the GSCM module. + * + * @param[out] The instance to reset. + */ +static void internal_state_reset() +{ + m_module_initialized = false; +} + + +static void evt_send(pm_evt_t * p_gcm_evt) +{ + p_gcm_evt->peer_id = im_peer_id_get_by_conn_handle(p_gcm_evt->conn_handle); + + for (uint32_t i = 0; i < GCM_EVENT_HANDLERS_CNT; i++) + { + m_evt_handlers[i](p_gcm_evt); + } +} + + +/**@brief Function for checking a write event for whether a CCCD was written during the write + * operation. + * + * @param[in] p_write_evt The parameters of the write event. + * + * @return Whether the write was on a CCCD. + */ +static bool cccd_written(ble_gatts_evt_write_t const * p_write_evt) +{ + return ( (p_write_evt->op == BLE_GATTS_OP_WRITE_REQ) + && (p_write_evt->uuid.type == BLE_UUID_TYPE_BLE) + && (p_write_evt->uuid.uuid == BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG) + ); +} + + +/**@brief Function for sending an PM_EVT_ERROR_UNEXPECTED event. + * + * @param[in] conn_handle The connection handle the event pertains to. + * @param[in] err_code The unexpected error that occurred. + */ +static void send_unexpected_error(uint16_t conn_handle, ret_code_t err_code) +{ + pm_evt_t error_evt = + { + .evt_id = PM_EVT_ERROR_UNEXPECTED, + .conn_handle = conn_handle, + .params = + { + .error_unexpected = + { + .error = err_code + } + } + }; + evt_send(&error_evt); +} + + +/**@brief Function for performing the local DB update procedure in an event context, where no return + * code can be given. + * + * @details This function will do the procedure, and check the result, set a flag if needed, and + * send an event if needed. + * + * @param[in] conn_handle The connection to perform the procedure on. + */ +static void local_db_apply_in_evt(uint16_t conn_handle) +{ + bool set_procedure_as_pending = false; + ret_code_t err_code; + pm_evt_t event = + { + .conn_handle = conn_handle, + }; + + if (conn_handle == BLE_CONN_HANDLE_INVALID) + { + return; + } + + err_code = gscm_local_db_cache_apply(conn_handle); + + switch (err_code) + { + case NRF_SUCCESS: + event.evt_id = PM_EVT_LOCAL_DB_CACHE_APPLIED; + + evt_send(&event); + break; + + case NRF_ERROR_BUSY: + set_procedure_as_pending = true; + break; + + case NRF_ERROR_INVALID_DATA: + event.evt_id = PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED; + + NRF_LOG_WARNING("The local database has changed, so some subscriptions to notifications "\ + "and indications could not be restored for conn_handle %d", + conn_handle); + evt_send(&event); + break; + + case BLE_ERROR_INVALID_CONN_HANDLE: + /* Do nothing */ + break; + + default: + NRF_LOG_ERROR("gscm_local_db_cache_apply() returned %s which should not happen. "\ + "conn_handle: %d", + nrf_strerror_get(err_code), + conn_handle); + send_unexpected_error(conn_handle, err_code); + break; + } + + ble_conn_state_user_flag_set(conn_handle, m_flag_local_db_apply_pending, set_procedure_as_pending); +} + + +/**@brief Function for asynchronously starting a DB update procedure. + * + * @note This procedure can only be started asynchronously. + * + * @param[in] conn_handle The connection to perform the procedure on. + * @param[in] update Whether to perform the procedure. + */ +static __INLINE void local_db_update(uint16_t conn_handle, bool update) +{ + ble_conn_state_user_flag_set(conn_handle, m_flag_local_db_update_pending, update); +} + + +/**@brief Function for performing the local DB update procedure in an event context, where no return + * code can be given. + * + * @details This function will do the procedure, and check the result, set a flag if needed, and + * send an event if needed. + * + * @param[in] conn_handle The connection to perform the procedure on. + */ +static bool local_db_update_in_evt(uint16_t conn_handle) +{ + bool set_procedure_as_pending = false; + bool success = false; + ret_code_t err_code = gscm_local_db_cache_update(conn_handle); + + switch (err_code) + { + case NRF_SUCCESS: + success = true; + break; + + case NRF_ERROR_INVALID_DATA: + /* Fallthrough */ + case BLE_ERROR_INVALID_CONN_HANDLE: + /* Do nothing */ + break; + + case NRF_ERROR_BUSY: + set_procedure_as_pending = true; + break; + + case NRF_ERROR_STORAGE_FULL: + { + pm_evt_t event = + { + .evt_id = PM_EVT_STORAGE_FULL, + .conn_handle = conn_handle, + }; + + NRF_LOG_WARNING("Flash full. Could not store data for conn_handle: %d", conn_handle); + evt_send(&event); + break; + } + + default: + NRF_LOG_ERROR("gscm_local_db_cache_update() returned %s for conn_handle: %d", + nrf_strerror_get(err_code), + conn_handle); + send_unexpected_error(conn_handle, err_code); + break; + } + + local_db_update(conn_handle, set_procedure_as_pending); + + return success; +} + +#if PM_SERVICE_CHANGED_ENABLED + +/**@brief Function for getting the value of the CCCD for the service changed characteristic. + * + * @details This function will search all system handles consecutively. + * + * @param[in] conn_handle The connection to check. + * @param[out] p_cccd The CCCD value of the service changed characteristic for this link. + * + * @return Any error from @ref sd_ble_gatts_value_get or @ref sd_ble_gatts_attr_get. + */ +static ret_code_t service_changed_cccd(uint16_t conn_handle, uint16_t * p_cccd) +{ + bool sc_found = false; + uint16_t end_handle; + + ret_code_t err_code = sd_ble_gatts_initial_user_handle_get(&end_handle); + ASSERT(err_code == NRF_SUCCESS); + + for (uint16_t handle = 1; handle < end_handle; handle++) + { + ble_uuid_t uuid; + ble_gatts_value_t value = {.p_value = (uint8_t *)&uuid.uuid, .len = 2, .offset = 0}; + + err_code = sd_ble_gatts_attr_get(handle, &uuid, NULL); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + else if (!sc_found && (uuid.uuid == BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED)) + { + sc_found = true; + } + else if (sc_found && (uuid.uuid == BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG)) + { + value.p_value = (uint8_t *)p_cccd; + return sd_ble_gatts_value_get(conn_handle, handle, &value); + } + } + return NRF_ERROR_NOT_FOUND; +} + +/**@brief Function for sending a service changed indication in an event context, where no return + * code can be given. + * + * @details This function will do the procedure, and check the result, set a flag if needed, and + * send an event if needed. + * + * @param[in] conn_handle The connection to perform the procedure on. + */ +static void service_changed_send_in_evt(uint16_t conn_handle) +{ + bool sc_pending_state = true; + bool sc_sent_state = false; + ret_code_t err_code = gscm_service_changed_ind_send(conn_handle); + + switch (err_code) + { + case NRF_SUCCESS: + { + pm_evt_t event = + { + .evt_id = PM_EVT_SERVICE_CHANGED_IND_SENT, + .conn_handle = conn_handle, + }; + + sc_sent_state = true; + + evt_send(&event); + break; + } + + case NRF_ERROR_BUSY: + // Do nothing. + break; + + case NRF_ERROR_INVALID_STATE: + { + uint16_t cccd; + err_code = service_changed_cccd(conn_handle, &cccd); + if ((err_code == NRF_SUCCESS) && cccd) + { + // Possible ATT_MTU exchange ongoing. + // Do nothing, treat as busy. + break; + } + else + { + if (err_code != NRF_SUCCESS) + { + NRF_LOG_DEBUG("Unexpected error when looking for service changed CCCD: %s", + nrf_strerror_get(err_code)); + } + // CCCDs not enabled or an error happened. Drop indication. + // Fallthrough. + } + } + // Sometimes fallthrough. + case NRF_ERROR_NOT_SUPPORTED: + // Service changed not supported. Drop indication. + sc_pending_state = false; + gscm_db_change_notification_done(im_peer_id_get_by_conn_handle(conn_handle)); + break; + + case BLE_ERROR_GATTS_SYS_ATTR_MISSING: + local_db_apply_in_evt(conn_handle); + break; + + case BLE_ERROR_INVALID_CONN_HANDLE: + // Do nothing. + break; + + default: + NRF_LOG_ERROR("gscm_service_changed_ind_send() returned %s for conn_handle: %d", + nrf_strerror_get(err_code), + conn_handle); + send_unexpected_error(conn_handle, err_code); + break; + } + + ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_pending, sc_pending_state); + ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_sent, sc_sent_state); +} +#endif + +static void apply_pending_handle(uint16_t conn_handle, void * p_context) +{ + UNUSED_PARAMETER(p_context); + local_db_apply_in_evt(conn_handle); +} + + +static __INLINE void apply_pending_flags_check(void) +{ + UNUSED_RETURN_VALUE(ble_conn_state_for_each_set_user_flag(m_flag_local_db_apply_pending, + apply_pending_handle, + NULL)); +} + + +static void db_update_pending_handle(uint16_t conn_handle, void * p_context) +{ + UNUSED_PARAMETER(p_context); + if (nrf_mtx_trylock(&m_db_update_in_progress_mutex)) + { + if (local_db_update_in_evt(conn_handle)) + { + // Successfully started writing to flash. + return; + } + else + { + nrf_mtx_unlock(&m_db_update_in_progress_mutex); + } + } +} + + +#if PM_SERVICE_CHANGED_ENABLED +static void sc_send_pending_handle(uint16_t conn_handle, void * p_context) +{ + UNUSED_PARAMETER(p_context); + if (!ble_conn_state_user_flag_get(conn_handle, m_flag_service_changed_sent)) + { + service_changed_send_in_evt(conn_handle); + } +} + + +static __INLINE void service_changed_pending_flags_check(void) +{ + UNUSED_RETURN_VALUE(ble_conn_state_for_each_set_user_flag(m_flag_service_changed_pending, + sc_send_pending_handle, + NULL)); +} + + +static void service_changed_needed(uint16_t conn_handle) +{ + if (gscm_service_changed_ind_needed(conn_handle)) + { + ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_pending, true); + } +} +#endif + + +static void car_update_pending_handle(uint16_t conn_handle, void * p_context) +{ + UNUSED_PARAMETER(p_context); + + ble_uuid_t car_uuid; + memset(&car_uuid, 0, sizeof(ble_uuid_t)); + car_uuid.uuid = BLE_UUID_GAP_CHARACTERISTIC_CAR; + car_uuid.type = BLE_UUID_TYPE_BLE; + + ble_gattc_handle_range_t const car_handle_range = {1, 0xFFFF}; + + ret_code_t err_code = sd_ble_gattc_char_value_by_uuid_read(conn_handle, &car_uuid, &car_handle_range); + if (err_code == NRF_SUCCESS) + { + ble_conn_state_user_flag_set(conn_handle, m_flag_car_handle_queried, true); + } +} + + +static void car_update_needed(uint16_t conn_handle) +{ + pm_peer_data_t peer_data; + if (pds_peer_data_read(im_peer_id_get_by_conn_handle(conn_handle), + PM_PEER_DATA_ID_CENTRAL_ADDR_RES, + &peer_data, + NULL) == NRF_ERROR_NOT_FOUND) + { + ble_conn_state_user_flag_set(conn_handle, m_flag_car_update_pending, true); + } +} + + +static __INLINE void update_pending_flags_check(void) +{ + uint32_t count = ble_conn_state_for_each_set_user_flag(m_flag_local_db_update_pending, + db_update_pending_handle, + NULL); + if (count == 0) + { + count = ble_conn_state_for_each_set_user_flag(m_flag_car_update_pending, + car_update_pending_handle, + NULL); + UNUSED_RETURN_VALUE(count); + } +} + + +/**@brief Callback function for events from the ID Manager module. + * This function is registered in the ID Manager module. + * + * @param[in] p_event The event from the ID Manager module. + */ +void gcm_im_evt_handler(pm_evt_t * p_event) +{ + switch (p_event->evt_id) + { + case PM_EVT_BONDED_PEER_CONNECTED: + local_db_apply_in_evt(p_event->conn_handle); +#if (PM_SERVICE_CHANGED_ENABLED == 1) + service_changed_needed(p_event->conn_handle); +#endif + car_update_needed(p_event->conn_handle); + update_pending_flags_check(); + break; + default: + break; + } +} + + +/**@brief Callback function for events from the Peer Database module. + * This handler is extern in Peer Database. + * + * @param[in] p_event The event from the Security Dispatcher module. + */ +void gcm_pdb_evt_handler(pm_evt_t * p_event) +{ + if ( p_event->evt_id == PM_EVT_PEER_DATA_UPDATE_SUCCEEDED + && p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) + { + switch (p_event->params.peer_data_update_succeeded.data_id) + { + case PM_PEER_DATA_ID_BONDING: + { + uint16_t conn_handle = im_conn_handle_get(p_event->peer_id); + + if (conn_handle != BLE_CONN_HANDLE_INVALID) + { + local_db_update(conn_handle, true); + car_update_needed(conn_handle); + } + break; + } + +#if PM_SERVICE_CHANGED_ENABLED + case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING: + { + ret_code_t err_code; + pm_peer_data_flash_t peer_data; + + err_code = pdb_peer_data_ptr_get(p_event->peer_id, + PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, + &peer_data); + + if (err_code == NRF_SUCCESS) + { + if (*peer_data.p_service_changed_pending) + { + uint16_t conn_handle = im_conn_handle_get(p_event->peer_id); + if (conn_handle != BLE_CONN_HANDLE_INVALID) + { + ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_pending, true); + service_changed_pending_flags_check(); + } + } + } + break; + } +#endif + + case PM_PEER_DATA_ID_GATT_LOCAL: + if (m_db_update_in_progress_mutex == NRF_MTX_LOCKED) + { + nrf_mtx_unlock(&m_db_update_in_progress_mutex); + } + + // Expecting a call to update_pending_flags_check() immediately. + break; + + default: + /* No action */ + break; + } + } + + update_pending_flags_check(); +} + + +ret_code_t gcm_init() +{ + NRF_PM_DEBUG_CHECK(!m_module_initialized); + + internal_state_reset(); + + m_flag_local_db_update_pending = ble_conn_state_user_flag_acquire(); + m_flag_local_db_apply_pending = ble_conn_state_user_flag_acquire(); + m_flag_service_changed_pending = ble_conn_state_user_flag_acquire(); + m_flag_service_changed_sent = ble_conn_state_user_flag_acquire(); + m_flag_car_update_pending = ble_conn_state_user_flag_acquire(); + m_flag_car_handle_queried = ble_conn_state_user_flag_acquire(); + m_flag_car_value_queried = ble_conn_state_user_flag_acquire(); + + if ((m_flag_local_db_update_pending == BLE_CONN_STATE_USER_FLAG_INVALID) + || (m_flag_local_db_apply_pending == BLE_CONN_STATE_USER_FLAG_INVALID) + || (m_flag_service_changed_pending == BLE_CONN_STATE_USER_FLAG_INVALID) + || (m_flag_service_changed_sent == BLE_CONN_STATE_USER_FLAG_INVALID) + || (m_flag_car_update_pending == BLE_CONN_STATE_USER_FLAG_INVALID) + || (m_flag_car_handle_queried == BLE_CONN_STATE_USER_FLAG_INVALID) + || (m_flag_car_value_queried == BLE_CONN_STATE_USER_FLAG_INVALID) + ) + { + NRF_LOG_ERROR("Could not acquire conn_state user flags. Increase "\ + "BLE_CONN_STATE_USER_FLAG_COUNT in the ble_conn_state module."); + return NRF_ERROR_INTERNAL; + } + + nrf_mtx_init(&m_db_update_in_progress_mutex); + + m_module_initialized = true; + + return NRF_SUCCESS; +} + + +void store_car_value(uint16_t conn_handle, bool car_value) +{ + // Use a uint32_t to enforce 4-byte alignment. + static const uint32_t car_value_true = true; + static const uint32_t car_value_false = false; + + pm_peer_data_const_t peer_data = + { + .data_id = PM_PEER_DATA_ID_CENTRAL_ADDR_RES, + .length_words = 1, + }; + + ble_conn_state_user_flag_set(conn_handle, m_flag_car_update_pending, false); + peer_data.p_central_addr_res = car_value ? &car_value_true : &car_value_false; + ret_code_t err_code = pds_peer_data_store(im_peer_id_get_by_conn_handle(conn_handle), &peer_data, NULL); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_WARNING("CAR char value couldn't be stored (error: %s). Reattempt will happen on the next connection.", nrf_strerror_get(err_code)); + } +} + + +/**@brief Callback function for BLE events from the SoftDevice. + * + * @param[in] p_ble_evt The BLE event from the SoftDevice. + */ +void gcm_ble_evt_handler(ble_evt_t const * p_ble_evt) +{ + uint16_t conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GATTS_EVT_SYS_ATTR_MISSING: + local_db_apply_in_evt(conn_handle); + break; + +#if PM_SERVICE_CHANGED_ENABLED + case BLE_GATTS_EVT_SC_CONFIRM: + { + pm_evt_t event = + { + .evt_id = PM_EVT_SERVICE_CHANGED_IND_CONFIRMED, + .peer_id = im_peer_id_get_by_conn_handle(conn_handle), + .conn_handle = conn_handle, + }; + + gscm_db_change_notification_done(event.peer_id); + + ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_sent, false); + ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_pending, false); + evt_send(&event); + break; + } +#endif + + case BLE_GATTS_EVT_WRITE: + if (cccd_written(&p_ble_evt->evt.gatts_evt.params.write)) + { + local_db_update(conn_handle, true); + update_pending_flags_check(); + } + break; + + case BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP: + { + bool handle_found = false; + conn_handle = p_ble_evt->evt.gattc_evt.conn_handle; + const ble_gattc_evt_char_val_by_uuid_read_rsp_t * p_val = &p_ble_evt->evt.gattc_evt.params.char_val_by_uuid_read_rsp; + + if (!ble_conn_state_user_flag_get(conn_handle, m_flag_car_handle_queried)) + { + break; + } + + ble_conn_state_user_flag_set(conn_handle, m_flag_car_handle_queried, false); + + if (p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND) + { + // Store 0. + } + else if (p_ble_evt->evt.gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) + { + NRF_LOG_WARNING("Unexpected GATT status while getting CAR char value: 0x%x", + p_ble_evt->evt.gattc_evt.gatt_status); + // Store 0. + } + else + { + if (p_val->count != 1) + { + NRF_LOG_WARNING("Multiple (%d) CAR characteristics found, using the first.", + p_val->count); + } + + if (p_val->value_len != 1) + { + NRF_LOG_WARNING("Unexpected CAR characteristic value length (%d), store 0.", + p_val->value_len); + // Store 0. + } + else + { + ret_code_t err_code = sd_ble_gattc_read(conn_handle, *(uint16_t*)p_val->handle_value, 0); + if (err_code == NRF_SUCCESS) + { + handle_found = true; + ble_conn_state_user_flag_set(conn_handle, m_flag_car_value_queried, true); + } + } + } + + if (!handle_found) + { + store_car_value(conn_handle, false); + } + break; + } + + case BLE_GATTC_EVT_READ_RSP: + { + bool car_value = false; + conn_handle = p_ble_evt->evt.gattc_evt.conn_handle; + const ble_gattc_evt_read_rsp_t * p_val = &p_ble_evt->evt.gattc_evt.params.read_rsp; + + if (!ble_conn_state_user_flag_get(conn_handle, m_flag_car_value_queried)) + { + break; + } + + ble_conn_state_user_flag_set(conn_handle, m_flag_car_value_queried, false); + + if (p_ble_evt->evt.gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) + { + NRF_LOG_WARNING("Unexpected GATT status while getting CAR char value: 0x%x", + p_ble_evt->evt.gattc_evt.gatt_status); + // Store 0. + } + else + { + if (p_val->len != 1) + { + NRF_LOG_WARNING("Unexpected CAR characteristic value length (%d), store 0.", + p_val->len); + // Store 0. + } + else + { + car_value = *p_val->data; + } + } + + store_car_value(conn_handle, car_value); + } + } + + apply_pending_flags_check(); +#if PM_SERVICE_CHANGED_ENABLED + service_changed_pending_flags_check(); +#endif +} + + +ret_code_t gcm_local_db_cache_update(uint16_t conn_handle) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + local_db_update(conn_handle, true); + update_pending_flags_check(); + + return NRF_SUCCESS; +} + + +#if PM_SERVICE_CHANGED_ENABLED +void gcm_local_database_has_changed(void) +{ + gscm_local_database_has_changed(); + + ble_conn_state_conn_handle_list_t conn_handles = ble_conn_state_conn_handles(); + + for (uint16_t i = 0; i < conn_handles.len; i++) + { + if (im_peer_id_get_by_conn_handle(conn_handles.conn_handles[i]) == PM_PEER_ID_INVALID) + { + ble_conn_state_user_flag_set(conn_handles.conn_handles[i], m_flag_service_changed_pending, true); + } + } + + service_changed_pending_flags_check(); +} +#endif +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/components/ble/peer_manager/gatt_cache_manager.h b/components/ble/peer_manager/gatt_cache_manager.h new file mode 100644 index 0000000..fec8334 --- /dev/null +++ b/components/ble/peer_manager/gatt_cache_manager.h @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef GATT_CACHE_MANAGER_H__ +#define GATT_CACHE_MANAGER_H__ + +#include +#include "sdk_errors.h" +#include "ble.h" +#include "ble_gap.h" +#include "peer_manager_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +/** + * @cond NO_DOXYGEN + * @defgroup gatt_cache_manager GATT Cache Manager + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. A module for managing persistent storing of GATT + * attributes. + */ + + +/**@brief Function for initializing the GATT Cache Manager module. + * + * @retval NRF_SUCCESS Initialization was successful. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t gcm_init(void); + + +/**@brief Function for dispatching SoftDevice events to the GATT Cache Manager module. + * + * @param[in] p_ble_evt The SoftDevice event. + */ +void gcm_ble_evt_handler(ble_evt_t const * p_ble_evt); + + +/**@brief Function for triggering local GATT database data to be stored persistently. + * + * @details Values are retrieved from SoftDevice and written to persistent storage. + * + * @note This operation happens asynchronously, so any errors are reported as events. + * + * @note This function is only needed when you want to override the regular functionality of the + * module, e.g. to immediately store to flash instead of waiting for the native logic to + * perform the update. + * + * @param[in] conn_handle Connection handle to perform update on. + * + * @retval NRF_SUCCESS Store operation started. + */ +ret_code_t gcm_local_db_cache_update(uint16_t conn_handle); + + +/**@brief Function for manually informing that the local database has changed. + * + * @details This causes a service changed notification to be sent to all bonded peers that + * subscribe to it. + */ +void gcm_local_database_has_changed(void); + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* GATT_CACHE_MANAGER_H__ */ diff --git a/components/ble/peer_manager/gatts_cache_manager.c b/components/ble/peer_manager/gatts_cache_manager.c new file mode 100644 index 0000000..9718a2d --- /dev/null +++ b/components/ble/peer_manager/gatts_cache_manager.c @@ -0,0 +1,457 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(PEER_MANAGER) +#include "gatts_cache_manager.h" + +#include +#include "ble_gap.h" +#include "ble_err.h" +#include "peer_manager_types.h" +#include "peer_manager_internal.h" +#include "peer_database.h" +#include "peer_data_storage.h" +#include "id_manager.h" + +#define NRF_LOG_MODULE_NAME peer_manager_gscm +#if PM_LOG_ENABLED + #define NRF_LOG_LEVEL PM_LOG_LEVEL + #define NRF_LOG_INFO_COLOR PM_LOG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR PM_LOG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // PM_LOG_ENABLED +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +NRF_LOG_MODULE_REGISTER(); +#include "nrf_strerror.h" + + +#if !defined(PM_SERVICE_CHANGED_ENABLED) || (PM_SERVICE_CHANGED_ENABLED == 1) +// The number of registered event handlers. +#define GSCM_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) + +// GATTS Cache Manager event handler in Peer Manager. +extern void pm_gscm_evt_handler(pm_evt_t * p_gcm_evt); + +// GATTS Cache Manager events' handlers. +// The number of elements in this array is GSCM_EVENT_HANDLERS_CNT. +static pm_evt_handler_internal_t m_evt_handlers[] = +{ + pm_gscm_evt_handler +}; +#endif + +// Syntactic sugar, two spoons. +#define SYS_ATTR_SYS (BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS) +#define SYS_ATTR_USR (BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS) +#define SYS_ATTR_BOTH (SYS_ATTR_SYS | SYS_ATTR_USR) + +static bool m_module_initialized; +static pm_peer_id_t m_current_sc_store_peer_id; + + +/**@brief Function for resetting the module variable(s) of the GSCM module. + */ +static void internal_state_reset() +{ + m_module_initialized = false; + m_current_sc_store_peer_id = PM_PEER_ID_INVALID; + + // If PM_SERVICE_CHANGED_ENABLED is 0, this variable is unused. + UNUSED_VARIABLE(m_current_sc_store_peer_id); +} + + +#if !defined(PM_SERVICE_CHANGED_ENABLED) || (PM_SERVICE_CHANGED_ENABLED == 1) +static void evt_send(pm_evt_t * p_gscm_evt) +{ + p_gscm_evt->conn_handle = im_conn_handle_get(p_gscm_evt->peer_id); + + for (uint32_t i = 0; i < GSCM_EVENT_HANDLERS_CNT; i++) + { + m_evt_handlers[i](p_gscm_evt); + } +} + + +//lint -save -e550 +/**@brief Function for storing service_changed_pending = true to flash for all peers, in sequence. + * + * This function aborts if it gets @ref NRF_ERROR_BUSY when trying to store. A subsequent call will + * continue where the last call was aborted. + */ +static void service_changed_pending_set(void) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + ret_code_t err_code; + // Use a uint32_t to enforce 4-byte alignment. + static const uint32_t service_changed_pending = true; + + //lint -save -e65 -e64 + pm_peer_data_const_t peer_data = + { + .data_id = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, + .length_words = PM_SC_STATE_N_WORDS(), + .p_service_changed_pending = (bool*)&service_changed_pending, + }; + //lint -restore + + while (m_current_sc_store_peer_id != PM_PEER_ID_INVALID) + { + err_code = pds_peer_data_store(m_current_sc_store_peer_id, &peer_data, NULL); + if (err_code != NRF_SUCCESS) + { + pm_evt_t evt = {.peer_id = m_current_sc_store_peer_id}; + if (err_code == NRF_ERROR_BUSY) + { + // Do nothing. + } + else if (err_code == NRF_ERROR_STORAGE_FULL) + { + evt.evt_id = PM_EVT_STORAGE_FULL; + evt_send(&evt); + } + else + { + NRF_LOG_ERROR("pds_peer_data_store() returned %s while storing service changed"\ + "state for peer id %d.", + nrf_strerror_get(err_code), + m_current_sc_store_peer_id); + evt.evt_id = PM_EVT_ERROR_UNEXPECTED; + evt.params.error_unexpected.error = err_code; + evt_send(&evt); + } + break; + } + + m_current_sc_store_peer_id = pds_next_peer_id_get(m_current_sc_store_peer_id); + } +} +//lint -restore + + + +/**@brief Event handler for events from the Peer Database module. + * This function is extern in Peer Database. + * + * @param[in] p_event The event that has happened with peer id and flags. + */ +void gscm_pdb_evt_handler(pm_evt_t * p_event) +{ + if (m_current_sc_store_peer_id != PM_PEER_ID_INVALID) + { + service_changed_pending_set(); + } +} +#endif + + +ret_code_t gscm_init() +{ + NRF_PM_DEBUG_CHECK(!m_module_initialized); + + internal_state_reset(); + m_module_initialized = true; + + return NRF_SUCCESS; +} + + +ret_code_t gscm_local_db_cache_update(uint16_t conn_handle) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); + ret_code_t err_code; + + if (peer_id == PM_PEER_ID_INVALID) + { + return BLE_ERROR_INVALID_CONN_HANDLE; + } + else + { + pm_peer_data_t peer_data; + uint16_t n_bufs = 1; + bool retry_with_bigger_buffer = false; + + do + { + retry_with_bigger_buffer = false; + + err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, n_bufs++, &peer_data); + if (err_code == NRF_SUCCESS) + { + pm_peer_data_local_gatt_db_t * p_local_gatt_db = peer_data.p_local_gatt_db; + + p_local_gatt_db->flags = SYS_ATTR_BOTH; + + err_code = sd_ble_gatts_sys_attr_get(conn_handle, &p_local_gatt_db->data[0], &p_local_gatt_db->len, p_local_gatt_db->flags); + + if (err_code == NRF_SUCCESS) + { + pm_peer_data_flash_t curr_peer_data; + + err_code = pdb_peer_data_ptr_get(peer_id, + PM_PEER_DATA_ID_GATT_LOCAL, + &curr_peer_data); + + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_NOT_FOUND)) + { + NRF_LOG_ERROR("pdb_peer_data_ptr_get() returned %s for conn_handle: %d", + nrf_strerror_get(err_code), + conn_handle); + return NRF_ERROR_INTERNAL; + } + + if((err_code == NRF_ERROR_NOT_FOUND) + || (p_local_gatt_db->len != curr_peer_data.p_local_gatt_db->len) + || (memcmp(p_local_gatt_db->data, curr_peer_data.p_local_gatt_db->data, + p_local_gatt_db->len) != 0)) + { + err_code = pdb_write_buf_store(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, peer_id); + } + else + { + NRF_LOG_DEBUG("Local db is already up to date, skipping write."); + ret_code_t err_code_release = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_GATT_LOCAL); + if (err_code_release == NRF_SUCCESS) + { + err_code = NRF_ERROR_INVALID_DATA; + } + else + { + NRF_LOG_ERROR("Did another thread manipulate PM_PEER_DATA_ID_GATT_LOCAL for "\ + "peer_id %d at the same time? pdb_write_buf_release() returned %s.", + peer_id, + nrf_strerror_get(err_code_release)); + err_code = NRF_ERROR_INTERNAL; + } + } + } + else + { + if (err_code == NRF_ERROR_DATA_SIZE) + { + // The sys attributes are bigger than the requested write buffer. + retry_with_bigger_buffer = true; + } + else if (err_code == NRF_ERROR_NOT_FOUND) + { + // There are no sys attributes in the GATT db, so nothing needs to be stored. + err_code = NRF_SUCCESS; + } + + ret_code_t err_code_release = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_GATT_LOCAL); + if (err_code_release != NRF_SUCCESS) + { + NRF_LOG_ERROR("Did another thread manipulate PM_PEER_DATA_ID_GATT_LOCAL for "\ + "peer_id %d at the same time? pdb_write_buf_release() returned %s.", + peer_id, + nrf_strerror_get(err_code_release)); + err_code = NRF_ERROR_INTERNAL; + } + } + } + else if (err_code == NRF_ERROR_INVALID_PARAM) + { + // The sys attributes are bigger than the entire write buffer. + err_code = NRF_ERROR_DATA_SIZE; + } + } while (retry_with_bigger_buffer); + } + + return err_code; +} + + +ret_code_t gscm_local_db_cache_apply(uint16_t conn_handle) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); + ret_code_t err_code; + pm_peer_data_flash_t peer_data; + uint8_t const * p_sys_attr_data = NULL; + uint16_t sys_attr_len = 0; + uint32_t sys_attr_flags = (SYS_ATTR_BOTH); + bool all_attributes_applied = true; + + if (peer_id != PM_PEER_ID_INVALID) + { + err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, &peer_data); + if (err_code == NRF_SUCCESS) + { + pm_peer_data_local_gatt_db_t const * p_local_gatt_db; + + p_local_gatt_db = peer_data.p_local_gatt_db; + p_sys_attr_data = p_local_gatt_db->data; + sys_attr_len = p_local_gatt_db->len; + sys_attr_flags = p_local_gatt_db->flags; + } + } + + do + { + err_code = sd_ble_gatts_sys_attr_set(conn_handle, p_sys_attr_data, sys_attr_len, sys_attr_flags); + + if (err_code == NRF_ERROR_NO_MEM) + { + err_code = NRF_ERROR_BUSY; + } + else if (err_code == NRF_ERROR_INVALID_STATE) + { + err_code = NRF_SUCCESS; + } + else if (err_code == NRF_ERROR_INVALID_DATA) + { + all_attributes_applied = false; + + if (sys_attr_flags & SYS_ATTR_USR) + { + // Try setting only system attributes. + sys_attr_flags = SYS_ATTR_SYS; + } + else if (p_sys_attr_data || sys_attr_len) + { + // Try reporting that none exist. + p_sys_attr_data = NULL; + sys_attr_len = 0; + sys_attr_flags = SYS_ATTR_BOTH; + } + else + { + NRF_LOG_ERROR("sd_ble_gatts_sys_attr_set() returned NRF_ERROR_INVALID_DATA for NULL "\ + "pointer which should never happen. conn_handle: %d", + conn_handle); + err_code = NRF_ERROR_INTERNAL; + } + } + } while (err_code == NRF_ERROR_INVALID_DATA); + + if (!all_attributes_applied) + { + err_code = NRF_ERROR_INVALID_DATA; + } + + return err_code; +} + +#if !defined(PM_SERVICE_CHANGED_ENABLED) || (PM_SERVICE_CHANGED_ENABLED == 1) +void gscm_local_database_has_changed(void) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + m_current_sc_store_peer_id = pds_next_peer_id_get(PM_PEER_ID_INVALID); + service_changed_pending_set(); +} + + +bool gscm_service_changed_ind_needed(uint16_t conn_handle) +{ + ret_code_t err_code; + bool service_changed_state; + pm_peer_data_flash_t peer_data; + + peer_data.p_service_changed_pending = &service_changed_state; + pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); + + err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, &peer_data); + + if (err_code != NRF_SUCCESS) + { + return false; + } + + return *peer_data.p_service_changed_pending; +} + + +ret_code_t gscm_service_changed_ind_send(uint16_t conn_handle) +{ + static uint16_t start_handle; + const uint16_t end_handle = 0xFFFF; + ret_code_t err_code; + + err_code = sd_ble_gatts_initial_user_handle_get(&start_handle); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_gatts_initial_user_handle_get() returned %s which should not happen.", + nrf_strerror_get(err_code)); + return NRF_ERROR_INTERNAL; + } + + do + { + err_code = sd_ble_gatts_service_changed(conn_handle, start_handle, end_handle); + if (err_code == BLE_ERROR_INVALID_ATTR_HANDLE) + { + start_handle += 1; + } + } while (err_code == BLE_ERROR_INVALID_ATTR_HANDLE); + + return err_code; +} + + +void gscm_db_change_notification_done(pm_peer_id_t peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + // Use a uint32_t to enforce 4-byte alignment. + static const uint32_t service_changed_pending = false; + + //lint -save -e65 -e64 + pm_peer_data_const_t peer_data = + { + .data_id = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, + .length_words = PM_SC_STATE_N_WORDS(), + .p_service_changed_pending = (bool*)&service_changed_pending, + }; + //lint -restore + + // Don't need to check return code, because all error conditions can be ignored. + //lint -save -e550 + (void) pds_peer_data_store(peer_id, &peer_data, NULL); + //lint -restore +} +#endif +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/components/ble/peer_manager/gatts_cache_manager.h b/components/ble/peer_manager/gatts_cache_manager.h new file mode 100644 index 0000000..42171f3 --- /dev/null +++ b/components/ble/peer_manager/gatts_cache_manager.h @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef GATTS_CACHE_MANAGER_H__ +#define GATTS_CACHE_MANAGER_H__ + +#include +#include "sdk_errors.h" +#include "ble.h" +#include "ble_gap.h" +#include "peer_manager_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +/** + * @cond NO_DOXYGEN + * @defgroup gatts_cache_manager GATT Server Cache Manager + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. A module for managing persistent storing of GATT + * attributes pertaining to the GATT server role of the local device. + */ + + +/**@brief Function for initializing the GATT Server Cache Manager module. + * + * @retval NRF_SUCCESS Initialization was successful. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t gscm_init(void); + + +/**@brief Function for triggering local GATT database data to be stored persistently. Values are + * retrieved from the SoftDevice and written to persistent storage. + * + * @param[in] conn_handle Connection handle to perform update on. + * + * @retval NRF_SUCCESS Store operation started. + * @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection with a + * bonded peer. + * @retval NRF_ERROR_INVALID_DATA Refused to update because the GATT database is already up + * to date. + * @retval NRF_ERROR_BUSY Unable to perform operation at this time. Reattempt later. + * @retval NRF_ERROR_DATA_SIZE Write buffer not large enough. Call will never work with + * this GATT database. + * @retval NRF_ERROR_STORAGE_FULL No room in persistent_storage. Free up space; the + * operation will be automatically reattempted after the + * next FDS garbage collection procedure. + */ +ret_code_t gscm_local_db_cache_update(uint16_t conn_handle); + + +/**@brief Function for applying stored local GATT database data to the SoftDevice. Values are + * retrieved from persistent storage and given to the SoftDevice. + * + * @param[in] conn_handle Connection handle to apply values to. + * + * @retval NRF_SUCCESS Store operation started. + * @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection with a + * bonded peer. + * @retval NRF_ERROR_INVALID_DATA The stored data was rejected by the SoftDevice, which + * probably means that the local database has changed. The + * system part of the sys_attributes was attempted applied, + * so service changed indications can be sent to subscribers. + * @retval NRF_ERROR_BUSY Unable to perform operation at this time. Reattempt later. + * @retval NRF_ERROR_INTERNAL An unexpected error happened. + */ +ret_code_t gscm_local_db_cache_apply(uint16_t conn_handle); + + +/**@brief Function for storing the fact that the local database has changed, for all currently + * bonded peers. + * + * @note This will cause a later call to @ref gscm_service_changed_ind_needed to return true for + * a connection with a currently bonded peer. + */ +void gscm_local_database_has_changed(void); + + +/**@brief Function for checking if a service changed indication should be sent. + * + * @param[in] conn_handle The connection to check. + * + * @return true if a service changed indication should be sent, false if not. + */ +bool gscm_service_changed_ind_needed(uint16_t conn_handle); + + +/**@brief Function for sending a service changed indication to a connected peer. + * + * @param[in] conn_handle The connection to send the indication on. + * + * @retval NRF_SUCCESS Indication sent or not needed. + * @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection. + * @retval NRF_ERROR_BUSY Unable to send indication at this time. Reattempt later. + * @retval BLE_ERROR_GATTS_SYS_ATTR_MISSING Information missing. Apply local cache, then reattempt. + * @retval NRF_ERROR_INVALID_PARAM From @ref sd_ble_gatts_service_changed. Unexpected. + * @retval NRF_ERROR_NOT_SUPPORTED Service changed characteristic is not present. + * @retval NRF_ERROR_INVALID_STATE Service changed cannot be indicated to this peer + * because the peer has not subscribed to it. + * @retval NRF_ERROR_INTERNAL An unexpected error happened. + */ +ret_code_t gscm_service_changed_ind_send(uint16_t conn_handle); + + +/**@brief Function for specifying that a peer has been made aware of the latest local database + * change. + * + * @note After calling this, a later call to @ref gscm_service_changed_ind_needed will to return + * false for this peer unless @ref gscm_local_database_has_changed is called again. + * + * @param[in] peer_id The connection to send the indication on. + */ +void gscm_db_change_notification_done(pm_peer_id_t peer_id); + +/** @} + * @endcond +*/ + + +#ifdef __cplusplus +} +#endif + +#endif /* GATTS_CACHE_MANAGER_H__ */ diff --git a/components/ble/peer_manager/id_manager.c b/components/ble/peer_manager/id_manager.c new file mode 100644 index 0000000..b6f6ebe --- /dev/null +++ b/components/ble/peer_manager/id_manager.c @@ -0,0 +1,758 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(PEER_MANAGER) +#include "id_manager.h" + +#include +#include "ble.h" +#include "ble_gap.h" +#include "ble_err.h" +#include "peer_manager_types.h" +#include "peer_database.h" +#include "peer_data_storage.h" +#include "nrf_soc.h" +#include "ble_conn_state.h" + +#define NRF_LOG_MODULE_NAME peer_manager_im +#if PM_LOG_ENABLED + #define NRF_LOG_LEVEL PM_LOG_LEVEL + #define NRF_LOG_INFO_COLOR PM_LOG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR PM_LOG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // PM_LOG_ENABLED +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +NRF_LOG_MODULE_REGISTER(); + +#define IM_MAX_CONN_HANDLES (20) +#define IM_NO_INVALID_CONN_HANDLES (0xFF) +#define IM_ADDR_CLEARTEXT_LENGTH (3) +#define IM_ADDR_CIPHERTEXT_LENGTH (3) + +// The number of registered event handlers. +#define IM_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) + + +// Identity Manager event handlers in Peer Manager and GATT Cache Manager. +extern void pm_im_evt_handler(pm_evt_t * p_event); +extern void gcm_im_evt_handler(pm_evt_t * p_event); + +// Identity Manager events' handlers. +// The number of elements in this array is IM_EVENT_HANDLERS_CNT. +static pm_evt_handler_internal_t const m_evt_handlers[] = +{ + pm_im_evt_handler, + gcm_im_evt_handler +}; + +typedef struct +{ + pm_peer_id_t peer_id; + ble_gap_addr_t peer_address; +} im_connection_t; + +static im_connection_t m_connections[IM_MAX_CONN_HANDLES]; +static uint8_t m_wlisted_peer_cnt; +static pm_peer_id_t m_wlisted_peers[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + + +/**@brief Function for sending an event to all registered event handlers. + * + * @param[in] p_event The event to distribute. + */ +static void evt_send(pm_evt_t * p_event) +{ + for (uint32_t i = 0; i < IM_EVENT_HANDLERS_CNT; i++) + { + m_evt_handlers[i](p_event); + } +} + + +/**@brief Function checking the validity of an IRK + * + * @detail An all-zero IRK is not valid. This function will check if a given IRK is valid. + * + * @param[in] p_irk The IRK for which the validity is going to be checked. + * + * @retval true The IRK is valid. + * @retval false The IRK is invalid. + */ +bool is_valid_irk(ble_gap_irk_t const * p_irk) +{ + NRF_PM_DEBUG_CHECK(p_irk != NULL); + + for (uint32_t i = 0; i < BLE_GAP_SEC_KEY_LEN; i++) + { + if (p_irk->irk[i] != 0) + { + return true; + } + } + return false; +} + + +/**@brief Function for comparing two addresses to determine if they are identical + * + * @note The address type need to be identical, as well as every bit in the address itself. + * + * @param[in] p_addr1 The first address to be compared. + * @param[in] p_addr2 The second address to be compared. + * + * @retval true The addresses are identical. + * @retval false The addresses are not identical. + */ +bool addr_compare(ble_gap_addr_t const * p_addr1, ble_gap_addr_t const * p_addr2) +{ + // @note emdi: use NRF_PM_DEBUG_CHECK ? + if ((p_addr1 == NULL) || (p_addr2 == NULL)) + { + return false; + } + + // Check that the addr type is identical, return false if it is not + if (p_addr1->addr_type != p_addr2->addr_type) + { + return false; + } + + // Check if the addr bytes are is identical + return (memcmp(p_addr1->addr, p_addr2->addr, BLE_GAP_ADDR_LEN) == 0); +} + + +void im_ble_evt_handler(ble_evt_t const * ble_evt) +{ + ble_gap_evt_t gap_evt; + pm_peer_id_t bonded_matching_peer_id; + + if (ble_evt->header.evt_id != BLE_GAP_EVT_CONNECTED) + { + // Nothing to do. + return; + } + + gap_evt = ble_evt->evt.gap_evt; + bonded_matching_peer_id = PM_PEER_ID_INVALID; + + if ( gap_evt.params.connected.peer_addr.addr_type + != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) + { + /* Search the database for bonding data matching the one that triggered the event. + * Public and static addresses can be matched on address alone, while resolvable + * random addresses can be resolved agains known IRKs. Non-resolvable random addresses + * are never matching because they are not longterm form of identification. + */ + + pm_peer_id_t peer_id; + pm_peer_data_flash_t peer_data; + + pds_peer_data_iterate_prepare(); + + switch (gap_evt.params.connected.peer_addr.addr_type) + { + case BLE_GAP_ADDR_TYPE_PUBLIC: + case BLE_GAP_ADDR_TYPE_RANDOM_STATIC: + { + while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) + { + if (addr_compare(&gap_evt.params.connected.peer_addr, + &peer_data.p_bonding_data->peer_ble_id.id_addr_info)) + { + bonded_matching_peer_id = peer_id; + break; + } + } + } + break; + + case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE: + { + while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) + { + if (im_address_resolve(&gap_evt.params.connected.peer_addr, + &peer_data.p_bonding_data->peer_ble_id.id_info)) + { + bonded_matching_peer_id = peer_id; + break; + } + } + } + break; + + default: + NRF_PM_DEBUG_CHECK(false); + break; + } + } + + m_connections[gap_evt.conn_handle].peer_id = bonded_matching_peer_id; + m_connections[gap_evt.conn_handle].peer_address = gap_evt.params.connected.peer_addr; + + if (bonded_matching_peer_id != PM_PEER_ID_INVALID) + { + // Send a bonded peer event + pm_evt_t im_evt; + im_evt.conn_handle = gap_evt.conn_handle; + im_evt.peer_id = bonded_matching_peer_id; + im_evt.evt_id = PM_EVT_BONDED_PEER_CONNECTED; + evt_send(&im_evt); + } +} + + +/**@brief Function to compare two sets of bonding data to check if they belong to the same device. + * @note Invalid irks will never match even though they are identical. + * + * @param[in] p_bonding_data1 First bonding data for comparison + * @param[in] p_bonding_data2 Second bonding data for comparison + * + * @return True if the input matches, false if it does not. + */ +bool im_is_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data1, + pm_peer_data_bonding_t const * p_bonding_data2) +{ + NRF_PM_DEBUG_CHECK(p_bonding_data1 != NULL); + NRF_PM_DEBUG_CHECK(p_bonding_data2 != NULL); + + ble_gap_addr_t const * p_addr1 = &p_bonding_data1->peer_ble_id.id_addr_info; + ble_gap_addr_t const * p_addr2 = &p_bonding_data2->peer_ble_id.id_addr_info; + + bool duplicate_irk = ((memcmp(p_bonding_data1->peer_ble_id.id_info.irk, + p_bonding_data2->peer_ble_id.id_info.irk, + BLE_GAP_SEC_KEY_LEN) == 0) + && is_valid_irk(&p_bonding_data1->peer_ble_id.id_info) + && is_valid_irk(&p_bonding_data2->peer_ble_id.id_info)); + + bool duplicate_addr = addr_compare(p_addr1, p_addr2); + + bool id_addrs = ((p_addr1->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) + && (p_addr1->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) + && (p_addr2->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) + && (p_addr2->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)); + + return (duplicate_addr && id_addrs) || (duplicate_irk && !id_addrs); +} + + +pm_peer_id_t im_find_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data, + pm_peer_id_t peer_id_skip) +{ + pm_peer_id_t peer_id; + pm_peer_data_flash_t peer_data_duplicate; + + NRF_PM_DEBUG_CHECK(p_bonding_data != NULL); + + pds_peer_data_iterate_prepare(); + + while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data_duplicate)) + { + if ( (peer_id != peer_id_skip) + && im_is_duplicate_bonding_data(p_bonding_data, + peer_data_duplicate.p_bonding_data)) + { + return peer_id; + } + } + return PM_PEER_ID_INVALID; +} + + +pm_peer_id_t im_peer_id_get_by_conn_handle(uint16_t conn_handle) +{ + if ((conn_handle >= IM_MAX_CONN_HANDLES) || !ble_conn_state_valid(conn_handle)) + { + return PM_PEER_ID_INVALID; + } + + return m_connections[conn_handle].peer_id; +} + + +ret_code_t im_ble_addr_get(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr) +{ + NRF_PM_DEBUG_CHECK(p_ble_addr != NULL); + + if ((conn_handle >= IM_MAX_CONN_HANDLES) || !ble_conn_state_valid(conn_handle)) + { + return BLE_ERROR_INVALID_CONN_HANDLE; + } + + *p_ble_addr = m_connections[conn_handle].peer_address; + return NRF_SUCCESS; +} + + +bool im_master_ids_compare(ble_gap_master_id_t const * p_master_id1, + ble_gap_master_id_t const * p_master_id2) +{ + NRF_PM_DEBUG_CHECK(p_master_id1 != NULL); + NRF_PM_DEBUG_CHECK(p_master_id2 != NULL); + + if (!im_master_id_is_valid(p_master_id1)) + { + return false; + } + + if (p_master_id1->ediv != p_master_id2->ediv) + { + return false; + } + + return (memcmp(p_master_id1->rand, p_master_id2->rand, BLE_GAP_SEC_RAND_LEN) == 0); +} + + +pm_peer_id_t im_peer_id_get_by_master_id(ble_gap_master_id_t const * p_master_id) +{ + pm_peer_id_t peer_id; + pm_peer_data_flash_t peer_data; + + NRF_PM_DEBUG_CHECK(p_master_id != NULL); + + pds_peer_data_iterate_prepare(); + + // For each stored peer, check if the master_id matches p_master_id + while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) + { + if (im_master_ids_compare(p_master_id, &peer_data.p_bonding_data->own_ltk.master_id) || + im_master_ids_compare(p_master_id, &peer_data.p_bonding_data->peer_ltk.master_id)) + { + // If a matching master ID is found then return the peer ID. + return peer_id; + } + } + + // If no matching master ID is found return PM_PEER_ID_INVALID. + return PM_PEER_ID_INVALID; +} + + +uint16_t im_conn_handle_get(pm_peer_id_t peer_id) +{ + if (peer_id == PM_PEER_ID_INVALID) + { + return BLE_CONN_HANDLE_INVALID; + } + + for (uint16_t conn_handle = 0; conn_handle < IM_MAX_CONN_HANDLES; conn_handle++) + { + if ((m_connections[conn_handle].peer_id == peer_id) && ble_conn_state_valid(conn_handle)) + { + return conn_handle; + } + } + return BLE_CONN_HANDLE_INVALID; +} + + +bool im_master_id_is_valid(ble_gap_master_id_t const * p_master_id) +{ + if (p_master_id->ediv != 0) + { + return true; + } + + for (uint32_t i = 0; i < BLE_GAP_SEC_RAND_LEN; i++) + { + if (p_master_id->rand[i] != 0) + { + return true; + } + } + return false; +} + + +void im_new_peer_id(uint16_t conn_handle, pm_peer_id_t peer_id) +{ + if (conn_handle < IM_MAX_CONN_HANDLES) + { + m_connections[conn_handle].peer_id = peer_id; + } +} + + +ret_code_t im_peer_free(pm_peer_id_t peer_id) +{ + uint16_t conn_handle; + ret_code_t ret; + + conn_handle = im_conn_handle_get(peer_id); + ret = pdb_peer_free(peer_id); + + if (ret == NRF_SUCCESS && (conn_handle < IM_MAX_CONN_HANDLES)) + { + m_connections[conn_handle].peer_id = PM_PEER_ID_INVALID; + } + return ret; +} + + +/**@brief Given a list of peers, loads their GAP address and IRK into the provided buffers. + */ +static ret_code_t peers_id_keys_get(pm_peer_id_t const * p_peers, + uint32_t peer_cnt, + ble_gap_addr_t * p_gap_addrs, + uint32_t * p_addr_cnt, + ble_gap_irk_t * p_gap_irks, + uint32_t * p_irk_cnt) +{ + ret_code_t ret; + + pm_peer_data_bonding_t bond_data; + pm_peer_data_t peer_data; + + uint32_t const buf_size = sizeof(bond_data); + + bool copy_addrs = false; + bool copy_irks = false; + + NRF_PM_DEBUG_CHECK(p_peers != NULL); + + // One of these two has to be provided. + NRF_PM_DEBUG_CHECK((p_gap_addrs != NULL) || (p_gap_irks != NULL)); + + if ((p_gap_addrs != NULL) && (p_addr_cnt != NULL)) + { + NRF_PM_DEBUG_CHECK((*p_addr_cnt) >= peer_cnt); + + copy_addrs = true; + *p_addr_cnt = 0; + } + + if ((p_gap_irks != NULL) && (p_irk_cnt != NULL)) + { + NRF_PM_DEBUG_CHECK((*p_irk_cnt) >= peer_cnt); + + copy_irks = true; + *p_irk_cnt = 0; + } + + memset(&peer_data, 0x00, sizeof(peer_data)); + peer_data.p_bonding_data = &bond_data; + + // Read through flash memory and look for peers ID keys. + + for (uint32_t i = 0; i < peer_cnt; i++) + { + memset(&bond_data, 0x00, sizeof(bond_data)); + + // Read peer data from flash. + ret = pds_peer_data_read(p_peers[i], PM_PEER_DATA_ID_BONDING, + &peer_data, &buf_size); + + if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) + { + // Peer data coulnd't be found in flash or peer ID is not valid. + return NRF_ERROR_NOT_FOUND; + } + + uint8_t const addr_type = bond_data.peer_ble_id.id_addr_info.addr_type; + + if ((addr_type != BLE_GAP_ADDR_TYPE_PUBLIC) && + (addr_type != BLE_GAP_ADDR_TYPE_RANDOM_STATIC)) + { + // The address shared by the peer during bonding can't be used for whitelisting. + return BLE_ERROR_GAP_INVALID_BLE_ADDR; + } + + // Copy the GAP address. + if (copy_addrs) + { + memcpy(&p_gap_addrs[i], &bond_data.peer_ble_id.id_addr_info, sizeof(ble_gap_addr_t)); + (*p_addr_cnt)++; + } + + // Copy the IRK. + if (copy_irks) + { + memcpy(&p_gap_irks[i], bond_data.peer_ble_id.id_info.irk, BLE_GAP_SEC_KEY_LEN); + (*p_irk_cnt)++; + } + } + + return NRF_SUCCESS; +} + + +ret_code_t im_device_identities_list_set(pm_peer_id_t const * p_peers, + uint32_t peer_cnt) +{ + ret_code_t ret; + pm_peer_data_t peer_data; + pm_peer_data_bonding_t bond_data; + + ble_gap_id_key_t keys[BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT]; + ble_gap_id_key_t const * key_ptrs[BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT]; + + if (peer_cnt > BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT) + { + return NRF_ERROR_INVALID_PARAM; + } + + if ((p_peers == NULL) || (peer_cnt == 0)) + { + // Clear the device identities list. + return sd_ble_gap_device_identities_set(NULL, NULL, 0); + } + + peer_data.p_bonding_data = &bond_data; + uint32_t const buf_size = sizeof(bond_data); + + memset(keys, 0x00, sizeof(keys)); + for (uint32_t i = 0; i < BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT; i++) + { + key_ptrs[i] = &keys[i]; + } + + for (uint32_t i = 0; i < peer_cnt; i++) + { + memset(&bond_data, 0x00, sizeof(bond_data)); + + // Read peer data from flash. + ret = pds_peer_data_read(p_peers[i], PM_PEER_DATA_ID_BONDING, + &peer_data, &buf_size); + + if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) + { + NRF_LOG_WARNING("peer id %d: Peer data could not be found in flash. Remove the peer ID " + "from the peer list and try again.", + p_peers[i]); + return NRF_ERROR_NOT_FOUND; + } + + uint8_t const addr_type = bond_data.peer_ble_id.id_addr_info.addr_type; + + if ((addr_type != BLE_GAP_ADDR_TYPE_PUBLIC) && + (addr_type != BLE_GAP_ADDR_TYPE_RANDOM_STATIC)) + { + NRF_LOG_WARNING("peer id %d: The address shared by the peer during bonding cannot be " + "whitelisted. Remove the peer ID from the peer list and try again.", + p_peers[i]); + return BLE_ERROR_GAP_INVALID_BLE_ADDR; + } + + // Copy data to the buffer. + memcpy(&keys[i], &bond_data.peer_ble_id, sizeof(ble_gap_id_key_t)); + } + + return sd_ble_gap_device_identities_set(key_ptrs, NULL, peer_cnt); +} + + +ret_code_t im_id_addr_set(ble_gap_addr_t const * p_addr) +{ + return sd_ble_gap_addr_set(p_addr); +} + + +ret_code_t im_id_addr_get(ble_gap_addr_t * p_addr) +{ + NRF_PM_DEBUG_CHECK(p_addr != NULL); + + return sd_ble_gap_addr_get(p_addr); +} + + +ret_code_t im_privacy_set(pm_privacy_params_t const * p_privacy_params) +{ + return sd_ble_gap_privacy_set(p_privacy_params); +} + + +ret_code_t im_privacy_get(pm_privacy_params_t * p_privacy_params) +{ + return sd_ble_gap_privacy_get(p_privacy_params); +} + + +/* Create a whitelist for the user using the cached list of peers. + * This whitelist is meant to be provided by the application to the Advertising module. + */ +ret_code_t im_whitelist_get(ble_gap_addr_t * p_addrs, + uint32_t * p_addr_cnt, + ble_gap_irk_t * p_irks, + uint32_t * p_irk_cnt) +{ + // One of the two buffers has to be provided. + NRF_PM_DEBUG_CHECK((p_addrs != NULL) || (p_irks != NULL)); + NRF_PM_DEBUG_CHECK((p_addr_cnt != NULL) || (p_irk_cnt != NULL)); + + if (((p_addr_cnt != NULL) && (m_wlisted_peer_cnt > *p_addr_cnt)) || + ((p_irk_cnt != NULL) && (m_wlisted_peer_cnt > *p_irk_cnt))) + { + // The size of the cached list of peers is larger than the provided buffers. + return NRF_ERROR_NO_MEM; + } + + // NRF_SUCCESS or + // NRF_ERROR_NOT_FOUND, if a peer or its data were not found. + // BLE_ERROR_GAP_INVALID_BLE_ADDR, if a peer address can not be used for whitelisting. + return peers_id_keys_get(m_wlisted_peers, m_wlisted_peer_cnt, + p_addrs, p_addr_cnt, + p_irks, p_irk_cnt); +} + + +/* Copies the peers to whitelist into a local cache. + * The cached list will be used by im_whitelist_get() to retrieve the active whitelist. + * For SoftDevices 3x, also loads the peers' GAP addresses and whitelists them using + * sd_ble_gap_whitelist_set(). + */ +ret_code_t im_whitelist_set(pm_peer_id_t const * p_peers, + uint32_t peer_cnt) +{ + // Clear the cache of whitelisted peers. + memset(m_wlisted_peers, 0x00, sizeof(m_wlisted_peers)); + + if ((p_peers == NULL) || (peer_cnt == 0)) + { + // Clear the current whitelist. + m_wlisted_peer_cnt = 0; + + // NRF_SUCCESS, or + // BLE_GAP_ERROR_WHITELIST_IN_USE + return sd_ble_gap_whitelist_set(NULL, 0); + } + + // Copy the new whitelisted peers. + m_wlisted_peer_cnt = peer_cnt; + memcpy(m_wlisted_peers, p_peers, sizeof(pm_peer_id_t) * peer_cnt); + + ret_code_t ret; + uint32_t wlist_addr_cnt = 0; + + ble_gap_addr_t const * addr_ptrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + ble_gap_addr_t addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + + memset(addrs, 0x00, sizeof(addrs)); + + // Fetch GAP addresses for these peers, but don't fetch IRKs. + ret = peers_id_keys_get(p_peers, peer_cnt, addrs, &wlist_addr_cnt, NULL, NULL); + + if (ret != NRF_SUCCESS) + { + // NRF_ERROR_NOT_FOUND, if a peer or its data were not found. + // BLE_ERROR_GAP_INVALID_BLE_ADDR, if a peer address can not be used for whitelisting. + return ret; + } + + for (uint32_t i = 0; i < BLE_GAP_WHITELIST_ADDR_MAX_COUNT; i++) + { + addr_ptrs[i] = &addrs[i]; + } + + // NRF_ERROR_DATA_SIZE, if peer_cnt > BLE_GAP_WHITELIST_ADDR_MAX_COUNT. + // BLE_ERROR_GAP_WHITELIST_IN_USE, if a whitelist is in use. + return sd_ble_gap_whitelist_set(addr_ptrs, peer_cnt); +} + + +/**@brief Function for calculating the ah() hash function described in Bluetooth core specification + * 4.2 section 3.H.2.2.2. + * + * @detail BLE uses a hash function to calculate the first half of a resolvable address + * from the second half of the address and an irk. This function will use the ECB + * periferal to hash these data acording to the Bluetooth core specification. + * + * @note The ECB expect little endian input and output. + * This function expect big endian and will reverse the data as necessary. + * + * @param[in] p_k The key used in the hash function. + * For address resolution this is should be the irk. + * The array must have a length of 16. + * @param[in] p_r The rand used in the hash function. For generating a new address + * this would be a random number. For resolving a resolvable address + * this would be the last half of the address being resolved. + * The array must have a length of 3. + * @param[out] p_local_hash The result of the hash operation. For address resolution this + * will match the first half of the address being resolved if and only + * if the irk used in the hash function is the same one used to generate + * the address. + * The array must have a length of 16. + */ +void ah(uint8_t const * p_k, uint8_t const * p_r, uint8_t * p_local_hash) +{ + nrf_ecb_hal_data_t ecb_hal_data; + + for (uint32_t i = 0; i < SOC_ECB_KEY_LENGTH; i++) + { + ecb_hal_data.key[i] = p_k[SOC_ECB_KEY_LENGTH - 1 - i]; + } + + memset(ecb_hal_data.cleartext, 0, SOC_ECB_KEY_LENGTH - IM_ADDR_CLEARTEXT_LENGTH); + + for (uint32_t i = 0; i < IM_ADDR_CLEARTEXT_LENGTH; i++) + { + ecb_hal_data.cleartext[SOC_ECB_KEY_LENGTH - 1 - i] = p_r[i]; + } + + // Can only return NRF_SUCCESS. + (void) sd_ecb_block_encrypt(&ecb_hal_data); + + for (uint32_t i = 0; i < IM_ADDR_CIPHERTEXT_LENGTH; i++) + { + p_local_hash[i] = ecb_hal_data.ciphertext[SOC_ECB_KEY_LENGTH - 1 - i]; + } +} + + +bool im_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) +{ + uint8_t hash[IM_ADDR_CIPHERTEXT_LENGTH]; + uint8_t local_hash[IM_ADDR_CIPHERTEXT_LENGTH]; + uint8_t prand[IM_ADDR_CLEARTEXT_LENGTH]; + + if (p_addr->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) + { + return false; + } + + memcpy(hash, p_addr->addr, IM_ADDR_CIPHERTEXT_LENGTH); + memcpy(prand, &p_addr->addr[IM_ADDR_CIPHERTEXT_LENGTH], IM_ADDR_CLEARTEXT_LENGTH); + ah(p_irk->irk, prand, local_hash); + + return (memcmp(hash, local_hash, IM_ADDR_CIPHERTEXT_LENGTH) == 0); +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/components/ble/peer_manager/id_manager.h b/components/ble/peer_manager/id_manager.h new file mode 100644 index 0000000..c3e8c7d --- /dev/null +++ b/components/ble/peer_manager/id_manager.h @@ -0,0 +1,318 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef PEER_ID_MANAGER_H__ +#define PEER_ID_MANAGER_H__ + +#include +#include "sdk_errors.h" +#include "ble.h" +#include "ble_gap.h" +#include "peer_manager_types.h" +#include "peer_manager_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @defgroup id_manager ID Manager + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. A module for keeping track of peer identities + * (IRK and peer address). + */ + + +/**@brief Function for dispatching SoftDevice events to the ID Manager module. + * + * @param[in] p_ble_evt The SoftDevice event. + */ +void im_ble_evt_handler(ble_evt_t const * p_ble_evt); + + +/**@brief Function for getting the corresponding peer ID from a connection handle. + * + * @param[in] conn_handle The connection handle. + * + * @return The corresponding peer ID, or @ref PM_PEER_ID_INVALID if none could be resolved. + */ +pm_peer_id_t im_peer_id_get_by_conn_handle(uint16_t conn_handle); + + +/**@brief Function for getting the corresponding peer ID from a master ID (EDIV and rand). + * + * @param[in] p_master_id The master ID. + * + * @return The corresponding peer ID, or @ref PM_PEER_ID_INVALID if none could be resolved. + */ +pm_peer_id_t im_peer_id_get_by_master_id(ble_gap_master_id_t const * p_master_id); + + +/**@brief Function for getting the corresponding connection handle from a peer ID. + * + * @param[in] peer_id The peer ID. + * + * @return The corresponding connection handle, or @ref BLE_CONN_HANDLE_INVALID if none could be + * resolved. The conn_handle can refer to a recently disconnected connection. + */ +uint16_t im_conn_handle_get(pm_peer_id_t peer_id); + + +/**@brief Function for comparing two master ids + * @note Two invalid master IDs will not match. + * + * @param[in] p_master_id1 First master id for comparison + * @param[in] p_master_id2 Second master id for comparison + * + * @return True if the input matches, false if it does not. + */ +bool im_master_ids_compare(ble_gap_master_id_t const * p_master_id1, + ble_gap_master_id_t const * p_master_id2); + + +/**@brief Function for getting the BLE address used by the peer when connecting. + * + * @param[in] conn_handle The connection handle. + * @param[out] p_ble_addr The BLE address used by the peer when the connection specified by + * conn_handle was established. Cannot be NULL. + * + * @retval NRF_SUCCESS The address was found and copied. + * @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection. + */ +ret_code_t im_ble_addr_get(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr); + + +/**@brief Function for checking if a master ID is valid or invalid + * + * @param[in] p_master_id The master ID. + * + * @retval true The master id is valid. + * @retval false The master id is invalid (i.e. all zeros). + */ +bool im_master_id_is_valid(ble_gap_master_id_t const * p_master_id); + + +/**@brief Function for checking if two pieces of bonding data correspond to the same peer. + * + * @param[in] p_bonding_data1 The first piece of bonding data to check. + * @param[in] p_bonding_data2 The second piece of bonding data to check. + * + * @retval true The bonding data correspond to the same peer. + * @retval false The bonding data do not correspond to the same peer. + */ +bool im_is_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data1, + pm_peer_data_bonding_t const * p_bonding_data2); + + +/**@brief Function for finding if we are already bonded to a peer. + * + * @param[in] p_bonding_data The bonding data to check. + * @param[in] peer_id_skip Optional peer to ignore when searching for duplicates. + * + * @return An existing peer ID for the peer, or PM_PEER_ID_INVALID if none was found. + */ +pm_peer_id_t im_find_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data, + pm_peer_id_t peer_id_skip); + + +/**@brief Function for reporting that a new peer ID has been allocated for a specified connection. + * + * @param[in] conn_handle The connection. + * @param[in] peer_id The new peer ID. + */ +void im_new_peer_id(uint16_t conn_handle, pm_peer_id_t peer_id); + + +/**@brief Function for deleting all of a peer's data from flash and disassociating it from any + * connection handles it is associated with. + * + * @param[in] peer_id The peer to free. + * + * @return Any error code returned by @ref pdb_peer_free. + */ +ret_code_t im_peer_free(pm_peer_id_t peer_id); + + +/**@brief Function to set the local Bluetooth identity address. + * + * @details The local Bluetooth identity address is the address that identifies this device to other + * peers. The address type must be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref + * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. The identity address cannot be changed while roles are + * running. + * + * @note This address will be distributed to the peer during bonding. + * If the address changes, the address stored in the peer device will not be valid and the + * ability to reconnect using the old address will be lost. + * + * @note By default the SoftDevice will set an address of type @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC + * upon being enabled. The address is a random number populated during the IC manufacturing + * process and remains unchanged for the lifetime of each IC. + * + * @param[in] p_addr Pointer to address structure. + * + * @retval NRF_SUCCESS Address successfully set. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If the GAP address is invalid. + * @retval NRF_ERROR_BUSY Could not process at this time. Process SoftDevice events + * and retry. + * @retval NRF_ERROR_INVALID_STATE The identity address cannot be changed while advertising, + * scanning, or while in a connection. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t im_id_addr_set(ble_gap_addr_t const * p_addr); + + +/**@brief Function to get the local Bluetooth identity address. + * + * @note This will always return the identity address irrespective of the privacy settings, + * i.e. the address type will always be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref + * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. + * + * @param[out] p_addr Pointer to address structure to be filled in. + * + * @retval NRF_SUCCESS If the address was successfully retrieved. + */ +ret_code_t im_id_addr_get(ble_gap_addr_t * p_addr); + + +/**@brief Function to set privacy settings. + * + * @details Privacy settings cannot be set while advertising, scanning, or while in a connection. + * + * @param[in] p_privacy_params Privacy settings. + * + * @retval NRF_SUCCESS If privacy options were set successfully. + * @retval NRF_ERROR_NULL If @p p_privacy_params is NULL. + * @retval NRF_ERROR_INVALID_PARAM If the address type is not valid. + * @retval NRF_ERROR_BUSY If the request could not be processed at this time. + * Process SoftDevice events and retry. + * @retval NRF_ERROR_INVALID_STATE Privacy settings cannot be changed while BLE roles using + * privacy are enabled. + */ +ret_code_t im_privacy_set(pm_privacy_params_t const * p_privacy_params); + + +/**@brief Function to retrieve the current privacy settings. + * + * @details The privacy settings returned include the current device irk as well. + * + * @param[in] p_privacy_params Privacy settings. + * + * @retval NRF_SUCCESS Successfully retrieved privacy settings. + * @retval NRF_ERROR_NULL @c p_privacy_params is NULL. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t im_privacy_get(pm_privacy_params_t * p_privacy_params); + + +/**@brief Function for resolving a resolvable address with an identity resolution key (IRK). + * + * @details This function will use the ECB peripheral to resolve a resolvable address. + * This can be used to resolve the identity of a device distributing a random + * resolvable address based on any IRKs you have received earlier. If an address is + * resolved by an IRK, the device distributing the address must also know the IRK. + * + * @param[in] p_addr A random resolvable address. + * @param[in] p_irk An identity resolution key (IRK). + * + * @retval true The irk used matched the one used to create the address. + * @retval false The irk used did not match the one used to create the address, or an argument was + * NULL. + */ +bool im_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk); + + +/**@brief Function for setting / clearing the whitelist. + * + * @param p_peers The peers to whitelist. Pass NULL to clear the whitelist. + * @param peer_cnt The number of peers to whitelist. Pass zero to clear the whitelist. + * + * @retval NRF_SUCCESS If the whitelist was successfully set or cleared. + * @retval BLE_GAP_ERROR_WHITELIST_IN_USE If a whitelist is in use. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If any peer has an address which can not be used + * for whitelisting. + * @retval NRF_ERROR_NOT_FOUND If any peer or its data could not be found. + * @retval NRF_ERROR_DATA_SIZE If @p peer_cnt is greater than + * @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. + */ +ret_code_t im_whitelist_set(pm_peer_id_t const * p_peers, + uint32_t const peer_cnt); + + +/**@brief Retrieves the current whitelist, set by a previous call to @ref im_whitelist_set. + * + * @param[out] A buffer where to copy the GAP addresses. + * @param[inout] In: the size of the @p p_addrs buffer. + * Out: the number of address copied into the buffer. + * @param[out] A buffer where to copy the IRKs. + * @param[inout] In: the size of the @p p_irks buffer. + * Out: the number of IRKs copied into the buffer. + * + * @retval NRF_SUCCESS If the whitelist was successfully retrieved. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If any peer has an address which can not be used for + * whitelisting. + * @retval NRF_ERROR_NOT_FOUND If the data for any of the cached whitelisted peers + * can not be found anymore. It might have been deleted in + * the meanwhile. + * @retval NRF_ERROR_NO_MEM If the provided buffers are too small. + */ +ret_code_t im_whitelist_get(ble_gap_addr_t * p_addrs, + uint32_t * p_addr_cnt, + ble_gap_irk_t * p_irks, + uint32_t * p_irk_cnt); + + +/**@brief Set the device identities list. + */ +ret_code_t im_device_identities_list_set(pm_peer_id_t const * p_peers, + uint32_t peer_cnt); + + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* PEER_ID_MANAGER_H__ */ diff --git a/components/ble/peer_manager/nrf_ble_lesc.c b/components/ble/peer_manager/nrf_ble_lesc.c new file mode 100644 index 0000000..1aab48d --- /dev/null +++ b/components/ble/peer_manager/nrf_ble_lesc.c @@ -0,0 +1,519 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_BLE_LESC) + +#include "nrf_ble_lesc.h" +#include "nrf_crypto.h" + +#define NRF_LOG_MODULE_NAME nrf_ble_lesc +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/**@brief Descriptor of the peer public key. */ +typedef struct +{ + nrf_crypto_ecc_public_key_t value; /**< Peer public key. */ + bool is_requested; /**< Flag indicating that the public key has been requested to compute DH key. */ + bool is_valid; /**< Flag indicating that the public key is valid. */ + bool passkey_requested; /**< Flag indicating that the passkey key has been requested. */ + bool passkey_displayed; /**< Flag indicating that the passkey display event has been received. */ +} nrf_ble_lesc_peer_pub_key_t; + +/**@brief The maximum number of peripheral and central connections combined. + * This value is based on what is configured in the SoftDevice handler sdk_config. + */ +#define NRF_BLE_LESC_LINK_COUNT (NRF_SDH_BLE_PERIPHERAL_LINK_COUNT + NRF_SDH_BLE_CENTRAL_LINK_COUNT) + +__ALIGN(4) static ble_gap_lesc_p256_pk_t m_lesc_public_key; /**< LESC ECC Public Key. */ +__ALIGN(4) static ble_gap_lesc_dhkey_t m_lesc_dh_key; /**< LESC ECC DH Key. */ + +static nrf_crypto_ecdh_context_t m_ecdh_context; /**< Context to do the LESC ECDH calculation */ + +static bool m_ble_lesc_internal_error; /**< Flag indicating that the module encountered an internal error. */ +static bool m_keypair_generated; /**< Flag indicating that the local ECDH key pair was generated. */ +static nrf_crypto_ecc_key_pair_generate_context_t m_keygen_context; /**< Context to generate private/public key pair. */ +static nrf_crypto_ecc_private_key_t m_private_key; /**< Allocated private key type to use for LESC DH generation. */ +static nrf_crypto_ecc_public_key_t m_public_key; /**< Allocated public key type to use for LESC DH generation. */ +static nrf_ble_lesc_peer_pub_key_t m_peer_keys[NRF_BLE_LESC_LINK_COUNT]; /**< Array of pointers to peer public keys, used for LESC DH generation. */ + +static bool m_lesc_oobd_own_generated; +static ble_gap_lesc_oob_data_t m_ble_lesc_oobd_own; /**< LESC OOB data used in LESC OOB pairing mode. */ +static nrf_ble_lesc_peer_oob_data_handler m_lesc_oobd_peer_handler; + +ret_code_t nrf_ble_lesc_init(void) +{ + ret_code_t err_code; + + memset((void *) m_peer_keys, 0, sizeof(m_peer_keys)); + +#if NRF_CRYPTO_ALLOCATOR == NRF_CRYPTO_ALLOCATOR_NRF_MALLOC + // Initialize mem_manager if used by nrf_crypto. + err_code = nrf_mem_init(); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_mem_init() returned error 0x%x.", err_code); + return err_code; + } +#endif + + // Ensure that nrf_crypto has been initialized. + err_code = nrf_crypto_init(); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_crypto_init() returned error 0x%x.", err_code); + return err_code; + } + NRF_LOG_DEBUG("Initialized nrf_crypto."); + +#if defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 1) + // Do nothing. RNG is initialized with nrf_crypto_init call. +#elif defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 0) + // Initialize the RNG. + err_code = nrf_crypto_rng_init(NULL, NULL); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_crypto_rng_init() returned error 0x%x.", err_code); + return err_code; + } +#else + #error Invalid sdk_config.h (does not contain NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) +#endif // defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 1) + NRF_LOG_DEBUG("Initialized nrf_ble_lesc."); + + // Reset module state. + m_ble_lesc_internal_error = false; + m_keypair_generated = false; + + // Generate ECC key pair. Only one key pair is automatically generated by this module. + err_code = nrf_ble_lesc_keypair_generate(); + return err_code; +} + + +ret_code_t nrf_ble_lesc_keypair_generate(void) +{ + ret_code_t err_code; + size_t public_len = NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE; + + // Check if any DH computation is pending + for (uint32_t i = 0; i < ARRAY_SIZE(m_peer_keys); i++) + { + if (m_peer_keys[i].is_valid) + { + return NRF_ERROR_BUSY; + } + } + + // Update flag to indicate that there is no valid private key. + m_keypair_generated = false; + m_lesc_oobd_own_generated = false; + + NRF_LOG_DEBUG("Generating ECC key pair"); + err_code = nrf_crypto_ecc_key_pair_generate(&m_keygen_context, + &g_nrf_crypto_ecc_secp256r1_curve_info, + &m_private_key, + &m_public_key); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_crypto_ecc_key_pair_generate() returned error 0x%x.", err_code); + return err_code; + } + + // Convert to a raw type. + err_code = nrf_crypto_ecc_public_key_to_raw(&m_public_key, + m_lesc_public_key.pk, + &public_len); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_crypto_ecc_public_key_to_raw() returned error 0x%x.", err_code); + return err_code; + } + + // Invert the raw type to little-endian (required for BLE). + err_code = nrf_crypto_ecc_byte_order_invert(&g_nrf_crypto_ecc_secp256r1_curve_info, + m_lesc_public_key.pk, + m_lesc_public_key.pk, + NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_crypto_ecc_byte_order_invert() returned error 0x%x.", err_code); + } + else + { + // Set the flag to indicate that there is a valid ECDH key pair generated. + m_keypair_generated = true; + } + + return err_code; +} + + +ret_code_t nrf_ble_lesc_own_oob_data_generate(void) +{ + ret_code_t err_code = NRF_ERROR_INVALID_STATE; + + m_lesc_oobd_own_generated = false; + + if (m_keypair_generated) + { + err_code = sd_ble_gap_lesc_oob_data_get(BLE_CONN_HANDLE_INVALID, + &m_lesc_public_key, + &m_ble_lesc_oobd_own); + if (err_code == NRF_SUCCESS) + { + m_lesc_oobd_own_generated = true; + } + } + + return err_code; +} + + +ble_gap_lesc_p256_pk_t * nrf_ble_lesc_public_key_get(void) +{ + ble_gap_lesc_p256_pk_t * p_lesc_pk = NULL; + + if (m_keypair_generated) + { + p_lesc_pk = &m_lesc_public_key; + } + else + { + NRF_LOG_ERROR("Trying to access LESC public key that has not been generated yet."); + } + + return p_lesc_pk; +} + + +ble_gap_lesc_oob_data_t * nrf_ble_lesc_own_oob_data_get(void) +{ + ble_gap_lesc_oob_data_t * p_lesc_oobd_own = NULL; + + if (m_lesc_oobd_own_generated) + { + p_lesc_oobd_own = &m_ble_lesc_oobd_own; + } + else + { + NRF_LOG_ERROR("Trying to access LESC OOB data that have not been generated yet."); + } + + return p_lesc_oobd_own; +} + + +void nrf_ble_lesc_peer_oob_data_handler_set(nrf_ble_lesc_peer_oob_data_handler handler) +{ + m_lesc_oobd_peer_handler = handler; +} + + +/**@brief Function for calculating a DH key and responding to the DH key request on a given + * connection handle. + * + * @param[in] p_peer_public_key ECC peer public key, used to compute shared secret. + * @param[in] conn_handle Connection handle. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval Other Other error codes might be returned by the @ref nrf_crypto_ecdh_compute, @ref + * nrf_crypto_ecc_byte_order_invert, and @ref sd_ble_gap_lesc_dhkey_reply functions. + */ +static ret_code_t compute_and_give_dhkey(nrf_ble_lesc_peer_pub_key_t * p_peer_public_key, + uint16_t conn_handle) +{ + ret_code_t err_code = NRF_ERROR_INTERNAL; + size_t shared_secret_size = BLE_GAP_LESC_DHKEY_LEN; + uint8_t * p_shared_secret = m_lesc_dh_key.key; + + // Check if there is a valid generated and set a local ECDH public key. + if (!m_keypair_generated) + { + return NRF_ERROR_INTERNAL; + } + + // Check if the public_key is valid + if (p_peer_public_key->is_valid) + { + err_code = nrf_crypto_ecdh_compute(&m_ecdh_context, + &m_private_key, + &p_peer_public_key->value, + p_shared_secret, + &shared_secret_size); + } + + if (err_code == NRF_SUCCESS) + { + // Invert the shared secret for little endian format. + err_code = nrf_crypto_ecc_byte_order_invert(&g_nrf_crypto_ecc_secp256r1_curve_info, + p_shared_secret, + p_shared_secret, + BLE_GAP_LESC_DHKEY_LEN); + VERIFY_SUCCESS(err_code); + } + else + { + NRF_LOG_WARNING("Creating invalid shared secret to make LESC fail."); + err_code = nrf_crypto_rng_vector_generate(p_shared_secret, BLE_GAP_LESC_DHKEY_LEN); + VERIFY_SUCCESS(err_code); + } + + NRF_LOG_INFO("Calling sd_ble_gap_lesc_dhkey_reply on conn_handle: %d", conn_handle); + err_code = sd_ble_gap_lesc_dhkey_reply(conn_handle, &m_lesc_dh_key); + + return err_code; +} + + +ret_code_t nrf_ble_lesc_request_handler(void) +{ + ret_code_t err_code = NRF_SUCCESS; + + // If the LESC module is in an invalid state, a restart is required. + if (m_ble_lesc_internal_error) + { + return NRF_ERROR_INTERNAL; + } + + for (uint16_t i = 0; i < NRF_BLE_LESC_LINK_COUNT; i++) + { + if (m_peer_keys[i].is_requested) + { + err_code = compute_and_give_dhkey(&m_peer_keys[i], i); + m_peer_keys[i].is_requested = false; + m_peer_keys[i].is_valid = false; + m_peer_keys[i].passkey_requested = false; + m_peer_keys[i].passkey_displayed = false; + + VERIFY_SUCCESS(err_code); + + } + } + + return err_code; +} + + +/**@brief Function for handling a DH key request event. + * + * @param[in] conn_handle Connection handle. + * @param[in] p_dhkey_request DH key request descriptor. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval Other Other error codes might be returned by the @ref nrf_crypto_ecc_byte_order_invert + * and @ref nrf_crypto_ecc_public_key_from_raw functions. + */ +static ret_code_t on_dhkey_request(uint16_t conn_handle, + ble_gap_evt_lesc_dhkey_request_t const * p_dhkey_request) +{ + ret_code_t err_code = NRF_SUCCESS; + uint8_t public_raw[BLE_GAP_LESC_P256_PK_LEN]; + uint8_t * p_public_raw; + size_t public_raw_len; + + p_public_raw = p_dhkey_request->p_pk_peer->pk; + public_raw_len = BLE_GAP_LESC_P256_PK_LEN; + + // Don't allow to pair with remote peer which uses the same public key. + // Compare only X cordinate of the public key, bytes from 0 to 31. + if (memcmp(m_lesc_public_key.pk, p_public_raw, BLE_GAP_LESC_P256_PK_LEN / 2) == 0) + { + NRF_LOG_WARNING("Remote peer is using identical public key."); + m_peer_keys[conn_handle].is_valid = false; + + // In case when we have gotten passkey requested then we will respond to it with the + // "NONE" key type to prevent us from going through Authentication Stage 1. + if (m_peer_keys[conn_handle].passkey_requested) + { + m_peer_keys[conn_handle].passkey_requested = false; + + err_code = sd_ble_gap_auth_key_reply(conn_handle, BLE_GAP_AUTH_KEY_TYPE_NONE, NULL); + + return err_code; + + } + // In case we have gotten passkey display event then we need to disconnect a link + // to prevent us from going through Authentication Stage 1. + else if (m_peer_keys[conn_handle].passkey_displayed) + { + m_peer_keys[conn_handle].passkey_displayed = false; + + err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE) + { + return err_code; + } + + return NRF_SUCCESS; + } + else + { + // Do nothing + } + } else { + // Convert the received public key from little endian to big-endian. + err_code = nrf_crypto_ecc_byte_order_invert(&g_nrf_crypto_ecc_secp256r1_curve_info, + p_public_raw, + public_raw, + public_raw_len); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_crypto_ecc_byte_order_invert() returned error 0x%x.", err_code); + return err_code; + } + + // Copy peer public key to the allocated context. The dhkey calculation will be performed in + // @ref nrf_ble_lesc_request_handler, so it does not block normal operation. + err_code = nrf_crypto_ecc_public_key_from_raw(&g_nrf_crypto_ecc_secp256r1_curve_info, + &m_peer_keys[conn_handle].value, + public_raw, + public_raw_len); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_crypto_ecc_public_key_from_raw() returned error 0x%x.", err_code); + m_peer_keys[conn_handle].is_valid = false; + } + else + { + m_peer_keys[conn_handle].is_valid = true; + } + } + + m_peer_keys[conn_handle].is_requested = true; + + return NRF_SUCCESS; +} + + +/**@brief Function for setting LESC OOB data. + * + * @param[in] conn_handle Connection handle. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval Other Other error codes might be returned by the @ref sd_ble_gap_lesc_oob_data_set. + */ +static ret_code_t lesc_oob_data_set(uint16_t conn_handle) +{ + ret_code_t err_code; + ble_gap_lesc_oob_data_t * p_lesc_oobd_own; + ble_gap_lesc_oob_data_t * p_lesc_oobd_peer; + + p_lesc_oobd_own = (m_lesc_oobd_own_generated) ? &m_ble_lesc_oobd_own : NULL; + p_lesc_oobd_peer = (m_lesc_oobd_peer_handler != NULL) ? + m_lesc_oobd_peer_handler(conn_handle) : NULL; + + err_code = sd_ble_gap_lesc_oob_data_set(conn_handle, + p_lesc_oobd_own, + p_lesc_oobd_peer); + return err_code; +} + + +void nrf_ble_lesc_on_ble_evt(ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code = NRF_SUCCESS; + uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_DISCONNECTED: + m_peer_keys[conn_handle].is_valid = false; + m_peer_keys[conn_handle].is_requested = false; + m_peer_keys[conn_handle].passkey_requested = false; + m_peer_keys[conn_handle].passkey_displayed = false; + + break; + + case BLE_GAP_EVT_AUTH_KEY_REQUEST: + if (p_ble_evt->evt.gap_evt.params.auth_key_request.key_type == + BLE_GAP_AUTH_KEY_TYPE_PASSKEY) + { + m_peer_keys[conn_handle].passkey_requested = true; + } + + break; + + case BLE_GAP_EVT_PASSKEY_DISPLAY: + m_peer_keys[conn_handle].passkey_displayed = true; + + break; + + case BLE_GAP_EVT_LESC_DHKEY_REQUEST: + NRF_LOG_DEBUG("BLE_GAP_EVT_LESC_DHKEY_REQUEST"); + + if (p_ble_evt->evt.gap_evt.params.lesc_dhkey_request.oobd_req) + { + err_code = lesc_oob_data_set(conn_handle); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_gap_lesc_oob_data_set() returned error 0x%x.", err_code); + m_ble_lesc_internal_error = true; + } + } + + err_code = on_dhkey_request(conn_handle, + &p_ble_evt->evt.gap_evt.params.lesc_dhkey_request); + if (err_code != NRF_SUCCESS) + { + m_ble_lesc_internal_error = true; + } + break; + +#if NRF_BLE_LESC_GENERATE_NEW_KEYS + case BLE_GAP_EVT_AUTH_STATUS: + // Generate new pairing keys. + err_code = nrf_ble_lesc_keypair_generate(); + if (err_code != NRF_SUCCESS) + { + m_ble_lesc_internal_error = true; + } + + break; +#endif // NRF_BLE_LESC_GENERATE_NEW_KEYS + + default: + break; + } +} + + +#endif // NRF_BLE_LESC_ENABLED diff --git a/components/ble/peer_manager/nrf_ble_lesc.h b/components/ble/peer_manager/nrf_ble_lesc.h new file mode 100644 index 0000000..c9a3600 --- /dev/null +++ b/components/ble/peer_manager/nrf_ble_lesc.h @@ -0,0 +1,164 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup nrf_ble_lesc LESC module + * @{ + * @ingroup peer_manager + * @brief Module for handling LESC related events. + */ + +#ifndef NRF_BLE_LESC_H__ +#define NRF_BLE_LESC_H__ + +#include +#include +#include "ble.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Peer OOB Data handler prototype. */ +typedef ble_gap_lesc_oob_data_t * (* nrf_ble_lesc_peer_oob_data_handler)(uint16_t conn_handle); + +/**@brief Function for initializing the LESC module. + * + * @details This function initializes the nrf_crypto for ECC and ECDH calculations, which are + * required to handle LESC authentication procedures. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval Other Other error codes might be returned by the @ref nrf_crypto_init or + * @ref nrf_ble_lesc_keypair_generate functions. + */ +ret_code_t nrf_ble_lesc_init(void); + + +/**@brief Function for generating ECC keypair used for the LESC procedure. + * + * @details This function generates an ECC key pair, which consists of a private and public key. Keys are + * generated using ECC and are used to create LESC DH key during authentication procedures. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_BUSY If any pending request needs to be processed by @ref nrf_ble_lesc_request_handler. + * @retval Other Other error codes might be returned by the @ref nrf_crypto_ecc_key_pair_generate, + * @ref nrf_crypto_ecc_public_key_to_raw and @ref nrf_crypto_ecc_byte_order_invert + * functions. + */ +ret_code_t nrf_ble_lesc_keypair_generate(void); + + +/**@brief Function for generating LESC OOB data. + * + * @details This function generates LESC OOB data, which can be transmitted Out-Of-Band to the peer + * device and used during LESC procedure. It is required to generate ECC keypair with @ref + * nrf_ble_lesc_keypair_generate before calling this function. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_STATE If the ECC keypair hasn't been generated or is currently + * being generated. + */ +ret_code_t nrf_ble_lesc_own_oob_data_generate(void); + + +/**@brief Function for accessing the ECC public key used for LESC DH key generation. + * + * @details This function can be used to access the ECC public key, which is required to generate a LESC DH key + * at the peer side. + * + * @return Pointer to the generated public key or NULL if the key has not been generated yet. + */ +ble_gap_lesc_p256_pk_t * nrf_ble_lesc_public_key_get(void); + + +/**@brief Function for accessing LESC OOB data. + * + * @details This function can be used to access LESC OOB data that is associated with this device. + * It is required to regenerate LESC OOB data with @ref nrf_ble_lesc_own_oob_data_generate, + * after each change of ECC keypair with @ref nrf_ble_lesc_keypair_generate. + * + * @return Pointer to the LESC OOB data or NULL if the data has not been generated yet or is no + * no longer valid. + */ +ble_gap_lesc_oob_data_t * nrf_ble_lesc_own_oob_data_get(void); + + +/**@brief Function for setting the handler used to retrieve peer OOB data. + * + * @param[in] handler Function to retrieve peer OOB data. + */ +void nrf_ble_lesc_peer_oob_data_handler_set(nrf_ble_lesc_peer_oob_data_handler handler); + + +/**@brief Function for responding to a DH key requests. + * + * @details This function calculates DH keys and supplies them to the SoftDevice if there are any + * pending requests for keys. + * + * @note This function should be called systematically (e.g. in the main application loop) to handle + * any pending DH key requests. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INTERNAL If the LESC module encountered an internal error. The only way to recover from + * this type of error is to reset the application. + * @retval Other Other error codes might be returned by the @ref nrf_crypto_ecdh_compute, + * @ref nrf_crypto_ecc_byte_order_invert, and @ref sd_ble_gap_lesc_dhkey_reply + * functions. + */ +ret_code_t nrf_ble_lesc_request_handler(void); + + +/**@brief Function for handling BLE stack events. + * + * @details This function handles events from the BLE stack that are of interest to the module. + * + * @param[in] p_ble_evt Event received from the BLE stack. + */ +void nrf_ble_lesc_on_ble_evt(ble_evt_t const * p_ble_evt); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_BLE_LESC_H__ + +/** @} */ diff --git a/components/ble/peer_manager/peer_data_storage.c b/components/ble/peer_manager/peer_data_storage.c new file mode 100644 index 0000000..918619a --- /dev/null +++ b/components/ble/peer_manager/peer_data_storage.c @@ -0,0 +1,657 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(PEER_MANAGER) +#include "peer_data_storage.h" + +#include +#include +#include "sdk_errors.h" +#include "peer_manager_types.h" +#include "peer_manager_internal.h" +#include "peer_id.h" +#include "fds.h" + +#define NRF_LOG_MODULE_NAME peer_manager_pds +#if PM_LOG_ENABLED + #define NRF_LOG_LEVEL PM_LOG_LEVEL + #define NRF_LOG_INFO_COLOR PM_LOG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR PM_LOG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // PM_LOG_ENABLED +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +NRF_LOG_MODULE_REGISTER(); + +// Macro for verifying that the peer id is within a valid range. +#define VERIFY_PEER_ID_IN_RANGE(id) VERIFY_FALSE((id >= PM_PEER_ID_N_AVAILABLE_IDS), \ + NRF_ERROR_INVALID_PARAM) + +// Macro for verifying that the peer data id is withing a valid range. +#define VERIFY_PEER_DATA_ID_IN_RANGE(id) VERIFY_TRUE(peer_data_id_is_valid(id), \ + NRF_ERROR_INVALID_PARAM) + +// The number of registered event handlers. +#define PDS_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) + + +// Peer Data Storage event handler in Peer Database. +extern void pdb_pds_evt_handler(pm_evt_t *); + +// Peer Data Storage events' handlers. +// The number of elements in this array is PDS_EVENT_HANDLERS_CNT. +static pm_evt_handler_internal_t const m_evt_handlers[] = +{ + pdb_pds_evt_handler, +}; + +static bool m_module_initialized = false; +static volatile bool m_peer_delete_deferred = false; + +// A token used for Flash Data Storage searches. +static fds_find_token_t m_fds_ftok; + + +// Function for dispatching events to all registered event handlers. +static void pds_evt_send(pm_evt_t * p_event) +{ + p_event->conn_handle = BLE_CONN_HANDLE_INVALID; + + for (uint32_t i = 0; i < PDS_EVENT_HANDLERS_CNT; i++) + { + m_evt_handlers[i](p_event); + } +} + + +// Function to convert peer IDs to file IDs. +static uint16_t peer_id_to_file_id(pm_peer_id_t peer_id) +{ + return (uint16_t)(peer_id + PEER_ID_TO_FILE_ID); +} + + +// Function to convert peer data id to type id. +static pm_peer_id_t file_id_to_peer_id(uint16_t file_id) +{ + return (pm_peer_id_t)(file_id + FILE_ID_TO_PEER_ID); +} + + +// Function to convert peer data IDs to record keys. +static uint16_t peer_data_id_to_record_key(pm_peer_data_id_t peer_data_id) +{ + return (uint16_t)(peer_data_id + DATA_ID_TO_RECORD_KEY); +} + + +// Function to convert record keys to peer data IDs. +static pm_peer_data_id_t record_key_to_peer_data_id(uint16_t record_key) +{ + return (pm_peer_data_id_t)(record_key + RECORD_KEY_TO_DATA_ID); +} + + +// Function for checking whether a file ID is relevant for the Peer Manager. +static bool file_id_within_pm_range(uint16_t file_id) +{ + return ((PDS_FIRST_RESERVED_FILE_ID <= file_id) + && (file_id <= PDS_LAST_RESERVED_FILE_ID)); +} + + +// Function for checking whether a record key is relevant for the Peer Manager. +static bool record_key_within_pm_range(uint16_t record_key) +{ + return ((PDS_FIRST_RESERVED_RECORD_KEY <= record_key) + && (record_key <= PDS_LAST_RESERVED_RECORD_KEY)); +} + + +static bool peer_data_id_is_valid(pm_peer_data_id_t data_id) +{ + return ((data_id == PM_PEER_DATA_ID_BONDING) || + (data_id == PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING) || + (data_id == PM_PEER_DATA_ID_GATT_LOCAL) || + (data_id == PM_PEER_DATA_ID_GATT_REMOTE) || + (data_id == PM_PEER_DATA_ID_PEER_RANK) || + (data_id == PM_PEER_DATA_ID_CENTRAL_ADDR_RES) || + (data_id == PM_PEER_DATA_ID_APPLICATION)); +} + + +/**@brief Function for sending a PM_EVT_ERROR_UNEXPECTED event. + * + * @param[in] peer_id The peer the event pertains to. + * @param[in] err_code The unexpected error that occurred. + */ +static void send_unexpected_error(pm_peer_id_t peer_id, ret_code_t err_code) +{ + pm_evt_t error_evt = + { + .evt_id = PM_EVT_ERROR_UNEXPECTED, + .peer_id = peer_id, + .params = + { + .error_unexpected = + { + .error = err_code, + } + } + }; + pds_evt_send(&error_evt); +} + + +// Function for deleting all data beloning to a peer. +// These operations will be sent to FDS one at a time. +static void peer_data_delete_process() +{ + ret_code_t ret; + pm_peer_id_t peer_id; + uint16_t file_id; + fds_record_desc_t desc; + fds_find_token_t ftok; + + m_peer_delete_deferred = false; + + memset(&ftok, 0x00, sizeof(fds_find_token_t)); + peer_id = peer_id_get_next_deleted(PM_PEER_ID_INVALID); + + while ( (peer_id != PM_PEER_ID_INVALID) + && (fds_record_find_in_file(peer_id_to_file_id(peer_id), &desc, &ftok) + == FDS_ERR_NOT_FOUND)) + { + peer_id_free(peer_id); + peer_id = peer_id_get_next_deleted(peer_id); + } + + if (peer_id != PM_PEER_ID_INVALID) + { + file_id = peer_id_to_file_id(peer_id); + ret = fds_file_delete(file_id); + + if (ret == FDS_ERR_NO_SPACE_IN_QUEUES) + { + m_peer_delete_deferred = true; + } + else if (ret != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not delete peer data. fds_file_delete() returned 0x%x for peer_id: %d", + ret, + peer_id); + send_unexpected_error(peer_id, ret); + } + } +} + + +static ret_code_t peer_data_find(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + fds_record_desc_t * const p_desc) +{ + ret_code_t ret; + fds_find_token_t ftok; + + NRF_PM_DEBUG_CHECK(peer_id < PM_PEER_ID_N_AVAILABLE_IDS); + NRF_PM_DEBUG_CHECK(peer_data_id_is_valid(data_id)); + NRF_PM_DEBUG_CHECK(p_desc != NULL); + + memset(&ftok, 0x00, sizeof(fds_find_token_t)); + + uint16_t file_id = peer_id_to_file_id(peer_id); + uint16_t record_key = peer_data_id_to_record_key(data_id); + + ret = fds_record_find(file_id, record_key, p_desc, &ftok); + + if (ret != NRF_SUCCESS) + { + return NRF_ERROR_NOT_FOUND; + } + + return NRF_SUCCESS; +} + + +static void peer_ids_load() +{ + fds_record_desc_t record_desc; + fds_flash_record_t record; + fds_find_token_t ftok; + + memset(&ftok, 0x00, sizeof(fds_find_token_t)); + + uint16_t const record_key = peer_data_id_to_record_key(PM_PEER_DATA_ID_BONDING); + + while (fds_record_find_by_key(record_key, &record_desc, &ftok) == NRF_SUCCESS) + { + pm_peer_id_t peer_id; + + // It is safe to ignore the return value since the descriptor was + // just obtained and also 'record' is different from NULL. + (void)fds_record_open(&record_desc, &record); + peer_id = file_id_to_peer_id(record.p_header->file_id); + (void)fds_record_close(&record_desc); + + (void)peer_id_allocate(peer_id); + } +} + + +static void fds_evt_handler(fds_evt_t const * const p_fds_evt) +{ + pm_evt_t pds_evt = + { + .peer_id = file_id_to_peer_id(p_fds_evt->write.file_id) + }; + + switch (p_fds_evt->id) + { + case FDS_EVT_WRITE: + case FDS_EVT_UPDATE: + case FDS_EVT_DEL_RECORD: + if ( file_id_within_pm_range(p_fds_evt->write.file_id) + || record_key_within_pm_range(p_fds_evt->write.record_key)) + { + pds_evt.params.peer_data_update_succeeded.data_id + = record_key_to_peer_data_id(p_fds_evt->write.record_key); + pds_evt.params.peer_data_update_succeeded.action + = (p_fds_evt->id == FDS_EVT_DEL_RECORD) ? PM_PEER_DATA_OP_DELETE + : PM_PEER_DATA_OP_UPDATE; + pds_evt.params.peer_data_update_succeeded.token = p_fds_evt->write.record_id; + + if (p_fds_evt->result == NRF_SUCCESS) + { + pds_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_SUCCEEDED; + pds_evt.params.peer_data_update_succeeded.flash_changed = true; + } + else + { + pds_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_FAILED; + pds_evt.params.peer_data_update_failed.error = p_fds_evt->result; + } + + pds_evt_send(&pds_evt); + } + break; + + case FDS_EVT_DEL_FILE: + if ( file_id_within_pm_range(p_fds_evt->del.file_id) + && (p_fds_evt->del.record_key == FDS_RECORD_KEY_DIRTY)) + { + if (p_fds_evt->result == NRF_SUCCESS) + { + pds_evt.evt_id = PM_EVT_PEER_DELETE_SUCCEEDED; + peer_id_free(pds_evt.peer_id); + } + else + { + pds_evt.evt_id = PM_EVT_PEER_DELETE_FAILED; + pds_evt.params.peer_delete_failed.error = p_fds_evt->result; + } + + m_peer_delete_deferred = true; // Trigger remaining deletes. + + pds_evt_send(&pds_evt); + } + break; + + case FDS_EVT_GC: + if (p_fds_evt->result == NRF_SUCCESS) + { + pds_evt.evt_id = PM_EVT_FLASH_GARBAGE_COLLECTED; + } + else + { + pds_evt.evt_id = PM_EVT_FLASH_GARBAGE_COLLECTION_FAILED; + pds_evt.params.garbage_collection_failed.error = p_fds_evt->result; + } + pds_evt.peer_id = PM_PEER_ID_INVALID; + pds_evt_send(&pds_evt); + break; + + default: + // No action. + break; + } + + if (m_peer_delete_deferred) + { + peer_data_delete_process(); + } +} + + +ret_code_t pds_init() +{ + ret_code_t ret; + + // Check for re-initialization if debugging. + NRF_PM_DEBUG_CHECK(!m_module_initialized); + + ret = fds_register(fds_evt_handler); + if (ret != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not initialize flash storage. fds_register() returned 0x%x.", ret); + return NRF_ERROR_INTERNAL; + } + + ret = fds_init(); + if (ret != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not initialize flash storage. fds_init() returned 0x%x.", ret); + return NRF_ERROR_STORAGE_FULL; + } + + peer_id_init(); + peer_ids_load(); + + m_module_initialized = true; + + return NRF_SUCCESS; +} + + +ret_code_t pds_peer_data_read(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + pm_peer_data_t * const p_data, + uint32_t const * const p_buf_len) +{ + ret_code_t ret; + fds_record_desc_t rec_desc; + fds_flash_record_t rec_flash; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_data != NULL); + + VERIFY_PEER_ID_IN_RANGE(peer_id); + VERIFY_PEER_DATA_ID_IN_RANGE(data_id); + + ret = peer_data_find(peer_id, data_id, &rec_desc); + + if (ret != NRF_SUCCESS) + { + return NRF_ERROR_NOT_FOUND; + } + + // Shouldn't fail, unless the record was deleted in the meanwhile or the CRC check has failed. + ret = fds_record_open(&rec_desc, &rec_flash); + + if (ret != NRF_SUCCESS) + { + return NRF_ERROR_NOT_FOUND; + } + + p_data->data_id = data_id; + p_data->length_words = rec_flash.p_header->length_words; + + // If p_buf_len is NULL, provide a pointer to data in flash, otherwise, + // check that the buffer is large enough and copy the data in flash into the buffer. + if (p_buf_len == NULL) + { + // The cast is necessary because if no buffer is provided, we just copy the pointer, + // but in that case it should be considered a pointer to const data by the caller, + // since it is a pointer to data in flash. + p_data->p_all_data = (void*)rec_flash.p_data; + } + else + { + uint32_t const data_len_bytes = (p_data->length_words * sizeof(uint32_t)); + uint32_t const copy_len_bytes = MIN((*p_buf_len), (p_data->length_words * sizeof(uint32_t))); + + memcpy(p_data->p_all_data, rec_flash.p_data, copy_len_bytes); + + if (copy_len_bytes < data_len_bytes) + { + return NRF_ERROR_DATA_SIZE; + } + } + + // Shouldn't fail unless the record was already closed, in which case it can be ignored. + (void)fds_record_close(&rec_desc); + + return NRF_SUCCESS; +} + + +void pds_peer_data_iterate_prepare(void) +{ + memset(&m_fds_ftok, 0x00, sizeof(fds_find_token_t)); +} + + +bool pds_peer_data_iterate(pm_peer_data_id_t data_id, + pm_peer_id_t * const p_peer_id, + pm_peer_data_flash_t * const p_data) +{ + ret_code_t ret; + uint16_t rec_key; + fds_record_desc_t rec_desc; + fds_flash_record_t rec_flash; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_peer_id != NULL); + NRF_PM_DEBUG_CHECK(p_data != NULL); + + VERIFY_PEER_DATA_ID_IN_RANGE(data_id); + + rec_key = peer_data_id_to_record_key(data_id); + + if (fds_record_find_by_key(rec_key, &rec_desc, &m_fds_ftok) != NRF_SUCCESS) + { + return false; + } + + ret = fds_record_open(&rec_desc, &rec_flash); + + if (ret != NRF_SUCCESS) + { + // It can only happen if the record was deleted after the call to fds_record_find_by_key(), + // before we could open it, or if CRC support was enabled in Flash Data Storage at compile + // time and the CRC check failed. + return false; + } + + p_data->data_id = data_id; + p_data->length_words = rec_flash.p_header->length_words; + p_data->p_all_data = rec_flash.p_data; + + *p_peer_id = file_id_to_peer_id(rec_flash.p_header->file_id); + + (void)fds_record_close(&rec_desc); + + return true; +} + + +ret_code_t pds_peer_data_store(pm_peer_id_t peer_id, + pm_peer_data_const_t const * p_peer_data, + pm_store_token_t * p_store_token) +{ + ret_code_t ret; + fds_record_t rec; + fds_record_desc_t rec_desc; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_peer_data != NULL); + + VERIFY_PEER_ID_IN_RANGE(peer_id); + VERIFY_PEER_DATA_ID_IN_RANGE(p_peer_data->data_id); + + // Prepare the record to be stored in flash. + rec.file_id = peer_id_to_file_id(peer_id); + rec.key = peer_data_id_to_record_key(p_peer_data->data_id); + rec.data.p_data = (void*)p_peer_data->p_all_data; + rec.data.length_words = p_peer_data->length_words; + + ret = peer_data_find(peer_id, p_peer_data->data_id, &rec_desc); + + if (ret == NRF_ERROR_NOT_FOUND) + { + ret = fds_record_write(&rec_desc, &rec); + } + else // NRF_SUCCESS + { + // Update existing record. + ret = fds_record_update(&rec_desc, &rec); + } + + switch (ret) + { + case NRF_SUCCESS: + if (p_store_token != NULL) + { + // Update the store token. + (void)fds_record_id_from_desc(&rec_desc, (uint32_t*)p_store_token); + } + return NRF_SUCCESS; + + case FDS_ERR_BUSY: + case FDS_ERR_NO_SPACE_IN_QUEUES: + return NRF_ERROR_BUSY; + + case FDS_ERR_NO_SPACE_IN_FLASH: + return NRF_ERROR_STORAGE_FULL; + + case FDS_ERR_UNALIGNED_ADDR: + return NRF_ERROR_INVALID_ADDR; + + default: + NRF_LOG_ERROR("Could not write data to flash. fds_record_{write|update}() returned 0x%x. "\ + "peer_id: %d", + ret, + peer_id); + return NRF_ERROR_INTERNAL; + } +} + + +ret_code_t pds_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) +{ + ret_code_t ret; + fds_record_desc_t record_desc; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + + VERIFY_PEER_ID_IN_RANGE(peer_id); + VERIFY_PEER_DATA_ID_IN_RANGE(data_id); + + ret = peer_data_find(peer_id, data_id, &record_desc); + + if (ret != NRF_SUCCESS) + { + return NRF_ERROR_NOT_FOUND; + } + + ret = fds_record_delete(&record_desc); + + switch (ret) + { + case NRF_SUCCESS: + return NRF_SUCCESS; + + case FDS_ERR_NO_SPACE_IN_QUEUES: + return NRF_ERROR_BUSY; + + default: + NRF_LOG_ERROR("Could not delete peer. fds_record_delete() returned 0x%x. peer_id: %d, "\ + "data_id: %d.", + ret, + peer_id, + data_id); + return NRF_ERROR_INTERNAL; + } +} + + +pm_peer_id_t pds_peer_id_allocate(void) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return peer_id_allocate(PM_PEER_ID_INVALID); +} + + +ret_code_t pds_peer_id_free(pm_peer_id_t peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + VERIFY_PEER_ID_IN_RANGE(peer_id); + + (void)peer_id_delete(peer_id); + peer_data_delete_process(); + + return NRF_SUCCESS; +} + + +bool pds_peer_id_is_allocated(pm_peer_id_t peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return peer_id_is_allocated(peer_id); +} + + +bool pds_peer_id_is_deleted(pm_peer_id_t peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return peer_id_is_deleted(peer_id); +} + + +pm_peer_id_t pds_next_peer_id_get(pm_peer_id_t prev_peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return peer_id_get_next_used(prev_peer_id); +} + + +pm_peer_id_t pds_next_deleted_peer_id_get(pm_peer_id_t prev_peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return peer_id_get_next_deleted(prev_peer_id); +} + + +uint32_t pds_peer_count_get(void) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return peer_id_n_ids(); +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/components/ble/peer_manager/peer_data_storage.h b/components/ble/peer_manager/peer_data_storage.h new file mode 100644 index 0000000..b8071e2 --- /dev/null +++ b/components/ble/peer_manager/peer_data_storage.h @@ -0,0 +1,251 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef PEER_DATA_STORAGE_H__ +#define PEER_DATA_STORAGE_H__ + + +#include +#include "sdk_errors.h" +#include "ble_gap.h" +#include "peer_manager_types.h" +#include "peer_manager_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @defgroup peer_data_storage Peer Data Storage + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. This module provides a Peer Manager-specific API + * to the persistent storage. + * + * @details This module uses Flash Data Storage (FDS) to interface with persistent storage. + */ + +#define PDS_FIRST_RESERVED_FILE_ID (0xC000) /**< The beginning of the range of file IDs reserved for Peer Manager. */ +#define PDS_LAST_RESERVED_FILE_ID (0xFFFE) /**< The end of the range of file IDs reserved for Peer Manager. */ +#define PDS_FIRST_RESERVED_RECORD_KEY (0xC000) /**< The beginning of the range of record keys reserved for Peer Manager. */ +#define PDS_LAST_RESERVED_RECORD_KEY (0xFFFE) /**< The end of the range of record keys reserved for Peer Manager. */ + +#define PEER_ID_TO_FILE_ID ( PDS_FIRST_RESERVED_FILE_ID) //!< Macro for converting a @ref pm_peer_id_t to an FDS file ID. +#define FILE_ID_TO_PEER_ID (-PDS_FIRST_RESERVED_FILE_ID) //!< Macro for converting an FDS file ID to a @ref pm_peer_id_t. +#define DATA_ID_TO_RECORD_KEY ( PDS_FIRST_RESERVED_RECORD_KEY) //!< Macro for converting a @ref pm_peer_data_id_t to an FDS record ID. +#define RECORD_KEY_TO_DATA_ID (-PDS_FIRST_RESERVED_RECORD_KEY) //!< Macro for converting an FDS record ID to a @ref pm_peer_data_id_t. + + +/**@brief Function for initializing the module. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_STORAGE_FULL If no flash pages were available for use. + * @retval NRF_ERROR_INTERNAL If the module couldn't register with the flash filesystem. + */ +ret_code_t pds_init(void); + + +/**@brief Function for reading peer data in flash. + * + * @param[in] peer_id The peer the data belongs to. + * @param[in] data_id The data to retrieve. + * @param[out] p_data The peer data. May not be @c NULL. p_data.length_words and p_data.data_id + * are ignored. p_data.p_all_data is ignored if @p p_buf_len is @c NULL. + * @param[in] p_buf_len Length of the provided buffer, in bytes. Pass @c NULL to only copy + * a pointer to the data in flash. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or @p data_id are invalid. + * @retval NRF_ERROR_NOT_FOUND If the data was not found in flash. + * @retval NRF_ERROR_DATA_SIZE If the provided buffer is too small. The data is still copied, + * filling the provided buffer. + */ +ret_code_t pds_peer_data_read(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + pm_peer_data_t * const p_data, + uint32_t const * const p_buf_len); + + +/**@brief Function to prepare iterating over peer data in flash using @ref pds_peer_data_iterate. + * Call this function once each time before iterating using @ref pds_peer_data_iterate. + */ +void pds_peer_data_iterate_prepare(void); + + +/**@brief Function for iterating peers' data in flash. + * Always call @ref pds_peer_data_iterate_prepare before starting iterating. + * + * @param[in] data_id The peer data to iterate over. + * @param[out] p_peer_id The peer the data belongs to. + * @param[out] p_data The peer data in flash. + * + * @retval true If the operation was successful. + * @retval false If the data was not found in flash, or another error occurred. + */ +bool pds_peer_data_iterate(pm_peer_data_id_t data_id, + pm_peer_id_t * const p_peer_id, + pm_peer_data_flash_t * const p_data); + + +/**@brief Function for storing peer data in flash. If the same piece of data already exists for the + * given peer, it will be updated. This operation is asynchronous. + * Expect a @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED or @ref PM_EVT_PEER_DATA_UPDATE_FAILED + * event. + * + * @param[in] peer_id The peer the data belongs to. + * @param[in] p_peer_data The peer data. May not be @c NULL. + * @param[out] p_store_token A token identifying this particular store operation. The token can be + * used to identify events pertaining to this operation. Pass @p NULL + * if not used. + * + * @retval NRF_SUCCESS If the operation was initiated successfully. + * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or the data ID in @p_peer_data are invalid. + * @retval NRF_ERROR_INVALID_ADDR If @p p_peer_data is not word-aligned. + * @retval NRF_ERROR_STORAGE_FULL If no space is available in flash. + * @retval NRF_ERROR_BUSY If the flash filesystem was busy. + * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. + */ +ret_code_t pds_peer_data_store(pm_peer_id_t peer_id, + pm_peer_data_const_t const * p_peer_data, + pm_store_token_t * p_store_token); + + +/**@brief Function for deleting peer data in flash. This operation is asynchronous. + * Expect a @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED or @ref PM_EVT_PEER_DATA_UPDATE_FAILED + * event. + * + * @param[in] peer_id The peer the data belongs to + * @param[in] data_id The data to delete. + * + * @retval NRF_SUCCESS If the operation was initiated successfully. + * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or @p data_id are invalid. + * @retval NRF_ERROR_NOT_FOUND If data was not found in flash. + * @retval NRF_ERROR_BUSY If the flash filesystem was busy. + * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. + */ +ret_code_t pds_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); + + +/**@brief Function for claiming an unused peer ID. + * + * @retval PM_PEER_ID_INVALID If no peer ID was available. + */ +pm_peer_id_t pds_peer_id_allocate(void); + + +/**@brief Function for freeing a peer ID and deleting all data associated with it in flash. + * + * @param[in] peer_id The ID of the peer to free. + * + * @retval NRF_SUCCESS The operation was initiated successfully. + * @retval NRF_ERROR_INVALID_PARAM If @p peer_id is invalid. + */ +ret_code_t pds_peer_id_free(pm_peer_id_t peer_id); + + +/**@brief Function for finding out whether a peer ID is in use. + * + * @param[in] peer_id The peer ID to inquire about. + * + * @retval true @p peer_id is in use. + * @retval false @p peer_id is free. + */ +bool pds_peer_id_is_allocated(pm_peer_id_t peer_id); + + +/**@brief Function for finding out whether a peer ID is marked for deletion. + * + * @param[in] peer_id The peer ID to inquire about. + * + * @retval true @p peer_id is marked for deletion. + * @retval false @p peer_id is not marked for deletion. + */ +bool pds_peer_id_is_deleted(pm_peer_id_t peer_id); + +/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. Can be + * used to loop through all used peer IDs. + * + * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary + * peer ID. + * + * @param[in] prev_peer_id The previous peer ID. + * + * @return The first ordinary peer ID If @p prev_peer_id is @ref PM_PEER_ID_INVALID. + * @retval PM_PEER_ID_INVALID If @p prev_peer_id is the last ordinary peer ID or the module + * is not initialized. + */ +pm_peer_id_t pds_next_peer_id_get(pm_peer_id_t prev_peer_id); + + +/**@brief Function for getting the next peer ID in the sequence of all peer IDs pending deletion. + * Can be used to loop through all used peer IDs. + * + * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary + * peer ID. + * + * @param[in] prev_peer_id The previous peer ID. + * + * @return The next peer ID pending deletion. + * @return The first ordinary peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. + * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module + * is not initialized. + */ +pm_peer_id_t pds_next_deleted_peer_id_get(pm_peer_id_t prev_peer_id); + + +/**@brief Function for querying the number of valid peer IDs available. I.E the number of peers + * in persistent storage. + * + * @return The number of valid peer IDs. + */ +uint32_t pds_peer_count_get(void); + + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* PEER_DATA_STORAGE_H__ */ diff --git a/components/ble/peer_manager/peer_database.c b/components/ble/peer_manager/peer_database.c new file mode 100644 index 0000000..fd46a27 --- /dev/null +++ b/components/ble/peer_manager/peer_database.c @@ -0,0 +1,726 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(PEER_MANAGER) +#include "peer_database.h" + +#include +#include "peer_manager_types.h" +#include "peer_manager_internal.h" +#include "peer_data_storage.h" +#include "pm_buffer.h" + +#define NRF_LOG_MODULE_NAME peer_manager_pdb +#if PM_LOG_ENABLED + #define NRF_LOG_LEVEL PM_LOG_LEVEL + #define NRF_LOG_INFO_COLOR PM_LOG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR PM_LOG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // PM_LOG_ENABLED +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +NRF_LOG_MODULE_REGISTER(); +#include "nrf_strerror.h" + +/**@brief Macro for verifying that the data ID is among the values eligible for using the write buffer. + * + * @param[in] data_id The data ID to verify. + */ +// @note emdi: could this maybe be a function? +#define VERIFY_DATA_ID_WRITE_BUF(data_id) \ +do \ +{ \ + if (((data_id) != PM_PEER_DATA_ID_BONDING) && ((data_id) != PM_PEER_DATA_ID_GATT_LOCAL)) \ + { \ + return NRF_ERROR_INVALID_PARAM; \ + } \ +} while (0) + + +// The number of registered event handlers. +#define PDB_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) + + +// Peer Database event handlers in other Peer Manager submodules. +extern void pm_pdb_evt_handler(pm_evt_t * p_event); +extern void sm_pdb_evt_handler(pm_evt_t * p_event); +#if !defined(PM_SERVICE_CHANGED_ENABLED) || (PM_SERVICE_CHANGED_ENABLED == 1) +extern void gscm_pdb_evt_handler(pm_evt_t * p_event); +#endif +extern void gcm_pdb_evt_handler(pm_evt_t * p_event); + +// Peer Database events' handlers. +// The number of elements in this array is PDB_EVENT_HANDLERS_CNT. +static pm_evt_handler_internal_t const m_evt_handlers[] = +{ + pm_pdb_evt_handler, + sm_pdb_evt_handler, +#if !defined(PM_SERVICE_CHANGED_ENABLED) || (PM_SERVICE_CHANGED_ENABLED == 1) + gscm_pdb_evt_handler, +#endif + gcm_pdb_evt_handler, +}; + + +/**@brief Struct for keeping track of one write buffer, from allocation, until it is fully written + * or cancelled. + */ +typedef struct +{ + pm_peer_id_t peer_id; /**< The peer ID this buffer belongs to. */ + pm_peer_data_id_t data_id; /**< The data ID this buffer belongs to. */ + pm_store_token_t store_token; /**< Token given by Peer Data Storage when a flash write has been successfully requested. This is used as the check for whether such an operation has been successfully requested. */ + uint8_t n_bufs; /**< The number of buffer blocks containing peer data. */ + uint8_t buffer_block_id; /**< The index of the first (or only) buffer block containing peer data. */ + uint8_t store_flash_full : 1; /**< Flag indicating that the buffer was attempted written to flash, but a flash full error was returned and the operation should be retried after room has been made. */ + uint8_t store_busy : 1; /**< Flag indicating that the buffer was attempted written to flash, but a busy error was returned and the operation should be retried. */ +} pdb_buffer_record_t; + + +static bool m_module_initialized; +static pm_buffer_t m_write_buffer; /**< The internal states of the write buffer. */ +static pdb_buffer_record_t m_write_buffer_records[PM_FLASH_BUFFERS]; /**< The available write buffer records. */ +static bool m_pending_store = false; /**< Whether there are any pending (Not yet successfully requested in Peer Data Storage) store operations. This flag is for convenience only. The real bookkeeping is in the records (@ref m_write_buffer_records). */ + + + +/**@brief Function for invalidating a record of a write buffer allocation. + * + * @param[in] p_record The record to invalidate. + */ +static void write_buffer_record_invalidate(pdb_buffer_record_t * p_record) +{ + p_record->peer_id = PM_PEER_ID_INVALID; + p_record->data_id = PM_PEER_DATA_ID_INVALID; + p_record->buffer_block_id = PM_BUFFER_INVALID_ID; + p_record->store_busy = false; + p_record->store_flash_full = false; + p_record->n_bufs = 0; + p_record->store_token = PM_STORE_TOKEN_INVALID; +} + + +/**@brief Function for finding a record of a write buffer allocation. + * + * @param[in] peer_id The peer ID in the record. + * @param[inout] p_index In: The starting index, out: The index of the record + * + * @return A pointer to the matching record, or NULL if none was found. + */ +static pdb_buffer_record_t * write_buffer_record_find_next(pm_peer_id_t peer_id, uint32_t * p_index) +{ + for (uint32_t i = *p_index; i < PM_FLASH_BUFFERS; i++) + { + if ((m_write_buffer_records[i].peer_id == peer_id)) + { + *p_index = i; + return &m_write_buffer_records[i]; + } + } + return NULL; +} + + +/**@brief Function for finding a record of a write buffer allocation. + * + * @param[in] peer_id The peer ID in the record. + * @param[in] data_id The data ID in the record. + * + * @return A pointer to the matching record, or NULL if none was found. + */ +static pdb_buffer_record_t * write_buffer_record_find(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id) +{ + uint32_t index = 0; + pdb_buffer_record_t * p_record = write_buffer_record_find_next(peer_id, &index); + + while ((p_record != NULL) && ( (p_record->data_id != data_id) + || (p_record->store_busy) + || (p_record->store_flash_full) + || (p_record->store_token != PM_STORE_TOKEN_INVALID))) + { + index++; + p_record = write_buffer_record_find_next(peer_id, &index); + } + + return p_record; +} + + +/**@brief Function for finding a record of a write buffer allocation that has been sent to be stored. + * + * @param[in] store_token The store token received when store was called for the record. + * + * @return A pointer to the matching record, or NULL if none was found. + */ +static pdb_buffer_record_t * write_buffer_record_find_stored(pm_store_token_t store_token) +{ + for (int i = 0; i < PM_FLASH_BUFFERS; i++) + { + if (m_write_buffer_records[i].store_token == store_token) + { + return &m_write_buffer_records[i]; + } + } + return NULL; +} + + +/**@brief Function for finding an available record for write buffer allocation. + * + * @return A pointer to the available record, or NULL if none was found. + */ +static pdb_buffer_record_t * write_buffer_record_find_unused(void) +{ + return write_buffer_record_find(PM_PEER_ID_INVALID, PM_PEER_DATA_ID_INVALID); +} + + +/**@brief Function for gracefully deactivating a write buffer record. + * + * @details This function will first release any buffers, then invalidate the record. + * + * @param[inout] p_write_buffer_record The record to release. + * + * @return A pointer to the matching record, or NULL if none was found. + */ +static void write_buffer_record_release(pdb_buffer_record_t * p_write_buffer_record) +{ + for (uint32_t i = 0; i < p_write_buffer_record->n_bufs; i++) + { + pm_buffer_release(&m_write_buffer, p_write_buffer_record->buffer_block_id + i); + } + + write_buffer_record_invalidate(p_write_buffer_record); +} + + +/**@brief Function for claiming and activating a write buffer record. + * + * @param[out] pp_write_buffer_record The claimed record. + * @param[in] peer_id The peer ID this record should have. + * @param[in] data_id The data ID this record should have. + */ +static void write_buffer_record_acquire(pdb_buffer_record_t ** pp_write_buffer_record, + pm_peer_id_t peer_id, + pm_peer_data_id_t data_id) +{ + if (pp_write_buffer_record == NULL) + { + return; + } + *pp_write_buffer_record = write_buffer_record_find_unused(); + if (*pp_write_buffer_record == NULL) + { + // This also means the buffer is full. + return; + } + (*pp_write_buffer_record)->peer_id = peer_id; + (*pp_write_buffer_record)->data_id = data_id; +} + + +/**@brief Function for dispatching outbound events to all registered event handlers. + * + * @param[in] p_event The event to dispatch. + */ +static void pdb_evt_send(pm_evt_t * p_event) +{ + for (uint32_t i = 0; i < PDB_EVENT_HANDLERS_CNT; i++) + { + m_evt_handlers[i](p_event); + } +} + + +/**@brief Function for resetting the internal state of the Peer Database module. + * + * @param[out] p_event The event to dispatch. + */ +static void internal_state_reset() +{ + for (uint32_t i = 0; i < PM_FLASH_BUFFERS; i++) + { + write_buffer_record_invalidate(&m_write_buffer_records[i]); + } +} + + +static void peer_data_point_to_buffer(pm_peer_data_t * p_peer_data, pm_peer_data_id_t data_id, uint8_t * p_buffer_memory, uint16_t n_bufs) +{ + uint16_t n_bytes = n_bufs * PDB_WRITE_BUF_SIZE; + p_peer_data->data_id = data_id; + + p_peer_data->p_all_data = (pm_peer_data_bonding_t *)p_buffer_memory; + p_peer_data->length_words = BYTES_TO_WORDS(n_bytes); +} + + +static void peer_data_const_point_to_buffer(pm_peer_data_const_t * p_peer_data, pm_peer_data_id_t data_id, uint8_t * p_buffer_memory, uint32_t n_bufs) +{ + peer_data_point_to_buffer((pm_peer_data_t*)p_peer_data, data_id, p_buffer_memory, n_bufs); +} + + +static void write_buf_length_words_set(pm_peer_data_const_t * p_peer_data) +{ + switch (p_peer_data->data_id) + { + case PM_PEER_DATA_ID_BONDING: + p_peer_data->length_words = PM_BONDING_DATA_N_WORDS(); + break; + case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING: + p_peer_data->length_words = PM_SC_STATE_N_WORDS(); + break; + case PM_PEER_DATA_ID_PEER_RANK: + p_peer_data->length_words = PM_USAGE_INDEX_N_WORDS(); + break; + case PM_PEER_DATA_ID_GATT_LOCAL: + p_peer_data->length_words = PM_LOCAL_DB_N_WORDS(p_peer_data->p_local_gatt_db->len); + break; + default: + // No action needed. + break; + } +} + + +/**@brief Function for writing data into persistent storage. Writing happens asynchronously. + * + * @note This will unlock the data after it has been written. + * + * @param[in] p_write_buffer_record The write buffer record to write into persistent storage. + * + * @retval NRF_SUCCESS Data storing was successfully started. + * @retval NRF_ERROR_STORAGE_FULL No space available in persistent storage. Please clear some + * space, the operation will be reattempted after the next compress + * procedure. + * @retval NRF_ERROR_INVALID_PARAM Data ID was invalid. + * @retval NRF_ERROR_INVALID_STATE Module is not initialized. + * @retval NRF_ERROR_INTERNAL Unexpected internal error. + */ +ret_code_t write_buf_store(pdb_buffer_record_t * p_write_buffer_record) +{ + ret_code_t err_code = NRF_SUCCESS; + pm_peer_data_const_t peer_data = {.data_id = p_write_buffer_record->data_id}; + uint8_t * p_buffer_memory; + + p_buffer_memory = pm_buffer_ptr_get(&m_write_buffer, p_write_buffer_record->buffer_block_id); + if (p_buffer_memory == NULL) + { + NRF_LOG_ERROR("pm_buffer_ptr_get() could not retrieve RAM buffer. block_id: %d", + p_write_buffer_record->buffer_block_id); + return NRF_ERROR_INTERNAL; + } + + peer_data_const_point_to_buffer(&peer_data, + p_write_buffer_record->data_id, + p_buffer_memory, + p_write_buffer_record->n_bufs); + write_buf_length_words_set(&peer_data); + + err_code = pds_peer_data_store(p_write_buffer_record->peer_id, + &peer_data, + &p_write_buffer_record->store_token); + + + switch (err_code) + { + case NRF_SUCCESS: + p_write_buffer_record->store_busy = false; + p_write_buffer_record->store_flash_full = false; + break; + + case NRF_ERROR_BUSY: + p_write_buffer_record->store_busy = true; + p_write_buffer_record->store_flash_full = false; + m_pending_store = true; + + err_code = NRF_SUCCESS; + break; + + case NRF_ERROR_STORAGE_FULL: + p_write_buffer_record->store_busy = false; + p_write_buffer_record->store_flash_full = true; + m_pending_store = true; + break; + + case NRF_ERROR_INVALID_PARAM: + // No action. + break; + + default: + NRF_LOG_ERROR("pds_peer_data_store() returned %s. peer_id: %d", + nrf_strerror_get(err_code), + p_write_buffer_record->peer_id); + err_code = NRF_ERROR_INTERNAL; + break; + } + + return err_code; +} + + +/**@brief This calls @ref write_buf_store and sends events based on the return value. + * + * See @ref write_buf_store for more info. + * + * @return Whether or not the store operation succeeded. + */ +static bool write_buf_store_in_event(pdb_buffer_record_t * p_write_buffer_record) +{ + ret_code_t err_code; + pm_evt_t event; + + err_code = write_buf_store(p_write_buffer_record); + if (err_code != NRF_SUCCESS) + { + event.conn_handle = BLE_CONN_HANDLE_INVALID; + event.peer_id = p_write_buffer_record->peer_id; + + if (err_code == NRF_ERROR_STORAGE_FULL) + { + event.evt_id = PM_EVT_STORAGE_FULL; + } + else + { + event.evt_id = PM_EVT_ERROR_UNEXPECTED; + event.params.error_unexpected.error = err_code; + + NRF_LOG_ERROR("Some peer data was not properly written to flash. write_buf_store() "\ + "returned %s for peer_id: %d", + nrf_strerror_get(err_code), + p_write_buffer_record->peer_id); + } + + pdb_evt_send(&event); + + return false; + } + + return true; +} + + +/**@brief This reattempts store operations on write buffers, that previously failed because of @ref + * NRF_ERROR_BUSY or @ref NRF_ERROR_STORAGE_FULL errors. + * + * param[in] retry_flash_full Whether to retry operations that failed because of an + * @ref NRF_ERROR_STORAGE_FULL error. + */ +static void reattempt_previous_operations(bool retry_flash_full) +{ + if (!m_pending_store) + { + return; + } + + m_pending_store = false; + + for (uint32_t i = 0; i < PM_FLASH_BUFFERS; i++) + { + if ((m_write_buffer_records[i].store_busy) + || (m_write_buffer_records[i].store_flash_full)) + { + m_pending_store = true; + + if (m_write_buffer_records[i].store_busy || retry_flash_full) + { + if (!write_buf_store_in_event(&m_write_buffer_records[i])) + { + return; + } + } + } + } +} + + +/**@brief Function for handling events from the Peer Data Storage module. + * This function is extern in Peer Data Storage. + * + * @param[in] p_event The event to handle. + */ +void pdb_pds_evt_handler(pm_evt_t * p_event) +{ + pdb_buffer_record_t * p_write_buffer_record; + bool evt_send = true; + bool retry_flash_full = false; + + p_write_buffer_record = write_buffer_record_find_stored(p_event->params.peer_data_update_succeeded.token); + + switch (p_event->evt_id) + { + case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: + if ( (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) + && (p_write_buffer_record != NULL)) + { + // The write came from PDB. + write_buffer_record_release(p_write_buffer_record); + } + break; + + case PM_EVT_PEER_DATA_UPDATE_FAILED: + if ( (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) + && (p_write_buffer_record != NULL)) + { + // The write came from PDB, retry. + p_write_buffer_record->store_token = PM_STORE_TOKEN_INVALID; + p_write_buffer_record->store_busy = true; + m_pending_store = true; + evt_send = false; + } + break; + + case PM_EVT_FLASH_GARBAGE_COLLECTED: + retry_flash_full = true; + break; + + default: + break; + } + + if (evt_send) + { + // Forward the event to all registered Peer Database event handlers. + pdb_evt_send(p_event); + } + + reattempt_previous_operations(retry_flash_full); +} + + +ret_code_t pdb_init() +{ + ret_code_t err_code; + + NRF_PM_DEBUG_CHECK(!m_module_initialized); + + internal_state_reset(); + + PM_BUFFER_INIT(&m_write_buffer, PM_FLASH_BUFFERS, PDB_WRITE_BUF_SIZE, err_code); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("PM_BUFFER_INIT() returned %s.", nrf_strerror_get(err_code)); + return NRF_ERROR_INTERNAL; + } + + m_module_initialized = true; + + return NRF_SUCCESS; +} + + +ret_code_t pdb_peer_free(pm_peer_id_t peer_id) +{ + ret_code_t err_code; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + + uint32_t index = 0; + pdb_buffer_record_t * p_record = write_buffer_record_find_next(peer_id, &index); + + while (p_record != NULL) + { + err_code = pdb_write_buf_release(peer_id, p_record->data_id); + UNUSED_VARIABLE(err_code); // All return values are acceptable. + + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_NOT_FOUND)) + { + NRF_LOG_ERROR("pdb_write_buf_release() returned %s which should not happen. peer_id: %d, "\ + "data_id: %d", + nrf_strerror_get(err_code), + peer_id, + p_record->data_id); + return NRF_ERROR_INTERNAL; + } + + index++; + p_record = write_buffer_record_find_next(peer_id, &index); + } + + err_code = pds_peer_id_free(peer_id); + + if ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_INVALID_PARAM)) + { + return err_code; + } + else + { + NRF_LOG_ERROR("Peer ID %d was not properly released. pds_peer_id_free() returned %s. "\ + "peer_id: %d", + peer_id, + nrf_strerror_get(err_code)); + return NRF_ERROR_INTERNAL; + } +} + + +ret_code_t pdb_peer_data_ptr_get(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + pm_peer_data_flash_t * const p_peer_data) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_peer_data != NULL); + + // Pass NULL to only retrieve a pointer. + return pds_peer_data_read(peer_id, data_id, (pm_peer_data_t*)p_peer_data, NULL); +} + + + +ret_code_t pdb_write_buf_get(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + uint32_t n_bufs, + pm_peer_data_t * p_peer_data) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + VERIFY_PARAM_NOT_NULL(p_peer_data); + VERIFY_DATA_ID_WRITE_BUF(data_id); + + if ((n_bufs == 0) || (n_bufs > PM_FLASH_BUFFERS)) + { + return NRF_ERROR_INVALID_PARAM; + } + + pdb_buffer_record_t * p_write_buffer_record; + uint8_t * p_buffer_memory; + bool new_record = false; + + p_write_buffer_record = write_buffer_record_find(peer_id, data_id); + + if (p_write_buffer_record == NULL) + { + // No buffer exists. + write_buffer_record_acquire(&p_write_buffer_record, peer_id, data_id); + if (p_write_buffer_record == NULL) + { + return NRF_ERROR_BUSY; + } + } + else if (p_write_buffer_record->n_bufs != n_bufs) + { + // Buffer exists with a different n_bufs from what was requested. + return NRF_ERROR_FORBIDDEN; + } + + if (p_write_buffer_record->buffer_block_id == PM_BUFFER_INVALID_ID) + { + p_write_buffer_record->buffer_block_id = pm_buffer_block_acquire(&m_write_buffer, n_bufs); + + if (p_write_buffer_record->buffer_block_id == PM_BUFFER_INVALID_ID) + { + write_buffer_record_invalidate(p_write_buffer_record); + return NRF_ERROR_BUSY; + } + + new_record = true; + } + + p_write_buffer_record->n_bufs = n_bufs; + + p_buffer_memory = pm_buffer_ptr_get(&m_write_buffer, p_write_buffer_record->buffer_block_id); + + if (p_buffer_memory == NULL) + { + NRF_LOG_ERROR("Cannot store data to flash because pm_buffer_ptr_get() could not retrieve "\ + "RAM buffer. Is block_id %d not allocated?", + p_write_buffer_record->buffer_block_id); + return NRF_ERROR_INTERNAL; + } + + peer_data_point_to_buffer(p_peer_data, data_id, p_buffer_memory, n_bufs); + if (new_record && (data_id == PM_PEER_DATA_ID_GATT_LOCAL)) + { + p_peer_data->p_local_gatt_db->len = PM_LOCAL_DB_LEN(p_peer_data->length_words); + } + + return NRF_SUCCESS; +} + + +ret_code_t pdb_write_buf_release(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + pdb_buffer_record_t * p_write_buffer_record; + p_write_buffer_record = write_buffer_record_find(peer_id, data_id); + + if (p_write_buffer_record == NULL) + { + return NRF_ERROR_NOT_FOUND; + } + + write_buffer_record_release(p_write_buffer_record); + + return NRF_SUCCESS; +} + + +ret_code_t pdb_write_buf_store(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + pm_peer_id_t new_peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + VERIFY_DATA_ID_WRITE_BUF(data_id); + + if (!pds_peer_id_is_allocated(new_peer_id)) + { + return NRF_ERROR_INVALID_PARAM; + } + + pdb_buffer_record_t * p_write_buffer_record = write_buffer_record_find(peer_id, data_id); + + if (p_write_buffer_record == NULL) + { + return NRF_ERROR_NOT_FOUND; + } + + p_write_buffer_record->peer_id = new_peer_id; + p_write_buffer_record->data_id = data_id; + return write_buf_store(p_write_buffer_record); +} + + +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/components/ble/peer_manager/peer_database.h b/components/ble/peer_manager/peer_database.h new file mode 100644 index 0000000..5660d11 --- /dev/null +++ b/components/ble/peer_manager/peer_database.h @@ -0,0 +1,194 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef PEER_DATABASE_H__ +#define PEER_DATABASE_H__ + +#include +#include "peer_manager_types.h" +#include "peer_manager_internal.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @cond NO_DOXYGEN + * @defgroup peer_database Peer Database + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. A module for simple management of reading and + * writing of peer data into persistent storage. + * + */ + +#define PDB_WRITE_BUF_SIZE (sizeof(pm_peer_data_bonding_t)) //!< The size (in bytes) of each block in the internal buffer accessible via @ref pdb_write_buf_get. + +/**@brief Macro for creating a peer ID value from a connection handle. + * + * Use this macro with pdb_write_buf_get() or pdb_write_buf_store(). It allows to create a write buffer + * even if you do not yet know the proper peer ID the data will be stored for. + * + * @return @p conn_handle + @ref PM_PEER_ID_N_AVAILABLE_IDS. + */ +#define PDB_TEMP_PEER_ID(conn_handle) (PM_PEER_ID_N_AVAILABLE_IDS + conn_handle) + + +/**@brief Function for initializing the module. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INTERNAL An unexpected error happened. + */ +ret_code_t pdb_init(void); + +/**@brief Function for freeing a peer's persistent bond storage. + * + * @note This function will call @ref pdb_write_buf_release on the data for this peer. + * + * @param[in] peer_id ID to be freed. + * + * @retval NRF_SUCCESS Peer ID was released and clear operation was initiated successfully. + * @retval NRF_ERROR_INVALID_PARAM Peer ID was invalid. + */ +ret_code_t pdb_peer_free(pm_peer_id_t peer_id); + +/**@brief Function for retrieving a pointer to peer data in flash (read-only). + * + * @note Dereferencing this pointer is not the safest thing to do if interrupts are enabled, + * because Flash Data Storage garbage collection might move the data around. Either disable + * interrupts while using the data, or use @ref pdb_peer_data_load. + * + * @param[in] peer_id The peer the data belongs to. + * @param[in] data_id The data to read. + * @param[out] p_peer_data The peer data, read-only. + * + * @retval NRF_SUCCESS If the pointer to the data was retrieved successfully. + * @retval NRF_ERROR_INVALID_PARAM If either @p peer_id or @p data_id are invalid. + * @retval NRF_ERROR_NOT_FOUND If data was not found in flash. + */ +ret_code_t pdb_peer_data_ptr_get(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + pm_peer_data_flash_t * const p_peer_data); + +/**@brief Function for retrieving pointers to a write buffer for peer data. + * + * @details This function will provide pointers to a buffer of the data. The data buffer will not be + * written to persistent storage until @ref pdb_write_buf_store is called. The buffer is + * released by calling either @ref pdb_write_buf_release, @ref pdb_write_buf_store, or + * @ref pdb_peer_free. + * + * When the data_id refers to a variable length data type, the available size is written + * to the data, both the top-level, and any internal length fields. + * + * @note Calling this function on a peer_id/data_id pair that already has a buffer created will + * give the same buffer, not create a new one. If n_bufs was increased since last time, the + * buffer might be relocated to be able to provide additional room. In this case, the data + * will be copied. If n_bufs was increased since last time, this function might return @ref + * NRF_ERROR_BUSY. In that case, the buffer is automatically released. + * + * @param[in] peer_id ID of the peer to get a write buffer for. If @p peer_id is larger than + * @ref PM_PEER_ID_N_AVAILABLE_IDS, it is interpreted as pertaining to + * the connection with connection handle peer_id - PM_PEER_ID_N_AVAILABLE_IDS. + * See @ref PDB_TEMP_PEER_ID. + * @param[in] data_id The piece of data to get. + * @param[in] n_bufs Number of contiguous buffers needed. + * @param[out] p_peer_data Pointers to mutable peer data. + * + * @retval NRF_SUCCESS Data retrieved successfully. + * @retval NRF_ERROR_INVALID_PARAM @p data_id was invalid, or @p n_bufs was 0 or more than the total + * available buffers. + * @retval NRF_ERROR_FORBIDDEN n_bufs was higher or lower than the existing buffer. If needed, + * release the existing buffer with @ref pdb_write_buf_release, and + * call this function again. + * @retval NRF_ERROR_NULL p_peer_data was NULL. + * @retval NRF_ERROR_BUSY Not enough buffer(s) available. + * @retval NRF_ERROR_INTERNAL Unexpected internal error. + */ +ret_code_t pdb_write_buf_get(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + uint32_t n_bufs, + pm_peer_data_t * p_peer_data); + +/**@brief Function for freeing a write buffer allocated with @ref pdb_write_buf_get. + * + * @note This function will not write peer data to persistent memory. Data in released buffer will + * be lost. + * + * @param[in] peer_id ID of peer to release buffer for. + * @param[in] data_id Which piece of data to release buffer for. + * + * @retval NRF_SUCCESS Successfully released buffer. + * @retval NRF_ERROR_NOT_FOUND No buffer was allocated for this peer ID/data ID pair. + */ +ret_code_t pdb_write_buf_release(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); + +/**@brief Function for writing data into persistent storage. Writing happens asynchronously. + * + * @note This will unlock the data after it has been written. + * + * @param[in] peer_id The ID used to address the write buffer. + * @param[in] data_id The piece of data to store. + * @param[in] new_peer_id The ID to put in flash. This is usually the same as peer_id, but + * must be valid, i.e. allocated (and smaller than @ref PM_PEER_ID_N_AVAILABLE_IDS). + * + * @retval NRF_SUCCESS Data storing was successfully started. + * @retval NRF_ERROR_STORAGE_FULL No space available in persistent storage. Please clear some + * space, the operation will be reattempted after the next compress + * procedure. + * @retval NRF_ERROR_INVALID_PARAM @p data_id or @p new_peer_id was invalid. + * @retval NRF_ERROR_NOT_FOUND No buffer has been allocated for this peer ID/data ID pair. + * @retval NRF_ERROR_INTERNAL Unexpected internal error. + */ +ret_code_t pdb_write_buf_store(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + pm_peer_id_t new_peer_id); + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* PEER_DATABASE_H__ */ + + diff --git a/components/ble/peer_manager/peer_id.c b/components/ble/peer_manager/peer_id.c new file mode 100644 index 0000000..7a041a9 --- /dev/null +++ b/components/ble/peer_manager/peer_id.c @@ -0,0 +1,200 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(PEER_MANAGER) +#include "peer_id.h" + +#include +#include +#include "sdk_errors.h" +#include "peer_manager_types.h" +#include "nrf_atflags.h" + + +typedef struct +{ + NRF_ATFLAGS_DEF_MEMBER(used_peer_ids, PM_PEER_ID_N_AVAILABLE_IDS); /**< Bitmap designating which peer IDs are in use. */ + NRF_ATFLAGS_DEF_MEMBER(deleted_peer_ids, PM_PEER_ID_N_AVAILABLE_IDS); /**< Bitmap designating which peer IDs are marked for deletion. */ +} pi_t; + + +static pi_t m_pi = {{0}, {0}}; + + +static void internal_state_reset(pi_t * p_pi) +{ + memset(p_pi, 0, sizeof(pi_t)); +} + + +void peer_id_init(void) +{ + internal_state_reset(&m_pi); +} + + +static pm_peer_id_t claim(pm_peer_id_t peer_id, nrf_atflags_t * p_peer_id_flags) +{ + pm_peer_id_t allocated_peer_id = PM_PEER_ID_INVALID; + if (peer_id == PM_PEER_ID_INVALID) + { + allocated_peer_id = nrf_atflags_find_and_set_flag(p_peer_id_flags, PM_PEER_ID_N_AVAILABLE_IDS); + if (allocated_peer_id == PM_PEER_ID_N_AVAILABLE_IDS) + { + allocated_peer_id = PM_PEER_ID_INVALID; + } + } + else if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) + { + bool lock_success = !nrf_atflags_fetch_set(p_peer_id_flags, peer_id); + allocated_peer_id = lock_success ? peer_id : PM_PEER_ID_INVALID; + } + return allocated_peer_id; +} + + +static void release(pm_peer_id_t peer_id, nrf_atflags_t * p_peer_id_flags) +{ + if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) + { + nrf_atflags_clear(p_peer_id_flags, peer_id); + } +} + + +pm_peer_id_t peer_id_allocate(pm_peer_id_t peer_id) +{ + return claim(peer_id, m_pi.used_peer_ids); +} + + +bool peer_id_delete(pm_peer_id_t peer_id) +{ + pm_peer_id_t deleted_peer_id; + + if (peer_id == PM_PEER_ID_INVALID) + { + return false; + } + + deleted_peer_id = claim(peer_id, m_pi.deleted_peer_ids); + + return (deleted_peer_id == peer_id); +} + + +void peer_id_free(pm_peer_id_t peer_id) +{ + release(peer_id, m_pi.used_peer_ids); + release(peer_id, m_pi.deleted_peer_ids); +} + + +bool peer_id_is_allocated(pm_peer_id_t peer_id) +{ + if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) + { + return nrf_atflags_get(m_pi.used_peer_ids, peer_id); + } + return false; +} + + +bool peer_id_is_deleted(pm_peer_id_t peer_id) +{ + if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) + { + return nrf_atflags_get(m_pi.deleted_peer_ids, peer_id); + } + return false; +} + + +pm_peer_id_t next_id_get(pm_peer_id_t prev_peer_id, nrf_atflags_t * p_peer_id_flags) +{ + pm_peer_id_t i = (prev_peer_id == PM_PEER_ID_INVALID) ? 0 : (prev_peer_id + 1); + for (; i < PM_PEER_ID_N_AVAILABLE_IDS; i++) + { + if (nrf_atflags_get(p_peer_id_flags, i)) + { + return i; + } + } + + return PM_PEER_ID_INVALID; +} + + +pm_peer_id_t peer_id_get_next_used(pm_peer_id_t peer_id) +{ + peer_id = next_id_get(peer_id, m_pi.used_peer_ids); + + while (peer_id != PM_PEER_ID_INVALID) + { + if (!peer_id_is_deleted(peer_id)) + { + return peer_id; + } + + peer_id = next_id_get(peer_id, m_pi.used_peer_ids); + } + + return peer_id; +} + + +pm_peer_id_t peer_id_get_next_deleted(pm_peer_id_t prev_peer_id) +{ + return next_id_get(prev_peer_id, m_pi.deleted_peer_ids); +} + + +uint32_t peer_id_n_ids(void) +{ + uint32_t n_ids = 0; + + for (pm_peer_id_t i = 0; i < PM_PEER_ID_N_AVAILABLE_IDS; i++) + { + n_ids += nrf_atflags_get(m_pi.used_peer_ids, i); + } + + return n_ids; +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/components/ble/peer_manager/peer_id.h b/components/ble/peer_manager/peer_id.h new file mode 100644 index 0000000..565ac45 --- /dev/null +++ b/components/ble/peer_manager/peer_id.h @@ -0,0 +1,167 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef PEER_ID_H__ +#define PEER_ID_H__ + + +#include +#include "sdk_errors.h" +#include "ble_gap.h" +#include "peer_manager_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @defgroup peer_id Peer IDs + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. This module keeps track of which peer IDs are in + * use and which are free. + */ + + +/**@brief Function for initializing the module. + */ +void peer_id_init(void); + + +/**@brief Function for claiming an unused peer ID. + * + * @param peer_id The peer ID to allocate. If this is @ref PM_PEER_ID_INVALID, the first available + * will be allocated. + * + * @return The allocated peer ID. + * @retval PM_PEER_ID_INVALID If no peer ID could be allocated or module is not initialized. + */ +pm_peer_id_t peer_id_allocate(pm_peer_id_t peer_id); + + +/**@brief Function for marking a peer ID for deletion. + * + * @param peer_id The peer ID to delete. + * + * @retval true Deletion was successful. + * @retval false Peer ID already marked for deletion, peer_id was PM_PEER_ID_INVALID, or module is + * not initialized. + */ +bool peer_id_delete(pm_peer_id_t peer_id); + + +/**@brief Function for freeing a peer ID and clearing all data associated with it in persistent + * storage. + * + * @param[in] peer_id Peer ID to free. + */ +void peer_id_free(pm_peer_id_t peer_id); + + +/**@brief Function for finding out whether a peer ID is marked for deletion. + * + * @param[in] peer_id The peer ID to inquire about. + * + * @retval true peer_id is in marked for deletion. + * @retval false peer_id is not marked for deletion, or the module is not initialized. + */ +bool peer_id_is_deleted(pm_peer_id_t peer_id); + + +/**@brief Function for finding out whether a peer ID is in use. + * + * @param[in] peer_id The peer ID to inquire about. + * + * @retval true peer_id is in use. + * @retval false peer_id is free, or the module is not initialized. + */ +bool peer_id_is_allocated(pm_peer_id_t peer_id); + + +/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. Can be + * used to loop through all used peer IDs. + * + * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary + * peer ID. + * + * @param[in] prev_peer_id The previous peer ID. + * + * @return The next peer ID. + * @return The first used peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. + * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module is + * not initialized. + */ +pm_peer_id_t peer_id_get_next_used(pm_peer_id_t prev_peer_id); + + +/**@brief Function for getting the next peer ID in the sequence of all peer IDs marked for deletion. + * Can be used to loop through all peer IDs marked for deletion. + * + * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary + * peer ID. + * + * @param[in] prev_peer_id The previous peer ID. + * + * @return The next peer ID. + * @return The first used peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. + * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module is + * not initialized. + */ +pm_peer_id_t peer_id_get_next_deleted(pm_peer_id_t prev_peer_id); + + +/**@brief Function for querying the number of valid peer IDs available. I.E the number of peers + * in persistent storage. + * + * @return The number of valid peer IDs, or 0 if module is not initialized. + */ +uint32_t peer_id_n_ids(void); + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* PEER_ID_H__ */ diff --git a/components/ble/peer_manager/peer_manager.c b/components/ble/peer_manager/peer_manager.c new file mode 100644 index 0000000..c832e62 --- /dev/null +++ b/components/ble/peer_manager/peer_manager.c @@ -0,0 +1,1243 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(PEER_MANAGER) +#include "ble_err.h" +#include "peer_manager.h" +#include +#include "security_manager.h" +#include "security_dispatcher.h" +#include "gatt_cache_manager.h" +#include "gatts_cache_manager.h" +#include "peer_database.h" +#include "peer_data_storage.h" +#include "id_manager.h" +#include "ble_conn_state.h" +#include "peer_manager_internal.h" +#include "nrf_sdh_ble.h" + +#define NRF_LOG_MODULE_NAME peer_manager +#if PM_LOG_ENABLED + #define NRF_LOG_LEVEL PM_LOG_LEVEL + #define NRF_LOG_INFO_COLOR PM_LOG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR PM_LOG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // PM_LOG_ENABLED +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +NRF_LOG_MODULE_REGISTER(); +#include "nrf_strerror.h" + + +#ifndef PM_PEER_RANKS_ENABLED + #define PM_PEER_RANKS_ENABLED 1 +#endif + +#define MODULE_INITIALIZED (m_module_initialized) /**< Macro indicating whether the module has been initialized properly. */ + + +static bool m_module_initialized; /**< Whether or not @ref pm_init has been called successfully. */ +static bool m_peer_rank_initialized; /**< Whether or not @ref rank_init has been called successfully. */ +static bool m_deleting_all; /**< True from when @ref pm_peers_delete is called until all peers have been deleted. */ +static pm_store_token_t m_peer_rank_token; /**< The store token of an ongoing peer rank update via a call to @ref pm_peer_rank_highest. If @ref PM_STORE_TOKEN_INVALID, there is no ongoing update. */ +static uint32_t m_current_highest_peer_rank; /**< The current highest peer rank. Used by @ref pm_peer_rank_highest. */ +static pm_peer_id_t m_highest_ranked_peer; /**< The peer with the highest peer rank. Used by @ref pm_peer_rank_highest. */ +static pm_evt_handler_t m_evt_handlers[PM_MAX_REGISTRANTS];/**< The subscribers to Peer Manager events, as registered through @ref pm_register. */ +static uint8_t m_n_registrants; /**< The number of event handlers registered through @ref pm_register. */ + +static ble_conn_state_user_flag_id_t m_flag_conn_excluded = BLE_CONN_STATE_USER_FLAG_INVALID; /**< User flag indicating whether a connection is excluded from being handled by the Peer Manager. */ + +/**@brief Function for sending a Peer Manager event to all subscribers. + * + * @param[in] p_pm_evt The event to send. + */ +static void evt_send(pm_evt_t const * p_pm_evt) +{ + for (int i = 0; i < m_n_registrants; i++) + { + m_evt_handlers[i](p_pm_evt); + } +} + + +#if PM_PEER_RANKS_ENABLED == 1 +/**@brief Function for initializing peer rank static variables. + */ +static void rank_vars_update(void) +{ + ret_code_t err_code = pm_peer_ranks_get(&m_highest_ranked_peer, + &m_current_highest_peer_rank, + NULL, + NULL); + + if (err_code == NRF_ERROR_NOT_FOUND) + { + m_highest_ranked_peer = PM_PEER_ID_INVALID; + m_current_highest_peer_rank = 0; + } + + m_peer_rank_initialized = ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NOT_FOUND)); +} +#endif + + +/**@brief Event handler for events from the Peer Database module. + * This handler is extern in the Peer Database module. + * + * @param[in] p_pdb_evt The incoming Peer Database event. + */ +void pm_pdb_evt_handler(pm_evt_t * p_pdb_evt) +{ + bool send_evt = true; + + p_pdb_evt->conn_handle = im_conn_handle_get(p_pdb_evt->peer_id); + + switch (p_pdb_evt->evt_id) + { +#if PM_PEER_RANKS_ENABLED == 1 + case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: + if (p_pdb_evt->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) + { + if ( (m_peer_rank_token != PM_STORE_TOKEN_INVALID) + && (m_peer_rank_token == p_pdb_evt->params.peer_data_update_succeeded.token)) + { + m_peer_rank_token = PM_STORE_TOKEN_INVALID; + m_highest_ranked_peer = p_pdb_evt->peer_id; + + p_pdb_evt->params.peer_data_update_succeeded.token = PM_STORE_TOKEN_INVALID; + } + else if ( m_peer_rank_initialized + && (p_pdb_evt->peer_id == m_highest_ranked_peer) + && (p_pdb_evt->params.peer_data_update_succeeded.data_id + == PM_PEER_DATA_ID_PEER_RANK)) + { + // Update peer rank variable if highest ranked peer has changed its rank. + rank_vars_update(); + } + } + else if (p_pdb_evt->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_DELETE) + { + if ( m_peer_rank_initialized + && (p_pdb_evt->peer_id == m_highest_ranked_peer) + && (p_pdb_evt->params.peer_data_update_succeeded.data_id == PM_PEER_DATA_ID_PEER_RANK)) + { + // Update peer rank variable if highest ranked peer has deleted its rank. + rank_vars_update(); + } + } + break; + + case PM_EVT_PEER_DATA_UPDATE_FAILED: + if (p_pdb_evt->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) + { + if ( (m_peer_rank_token != PM_STORE_TOKEN_INVALID) + && (m_peer_rank_token == p_pdb_evt->params.peer_data_update_failed.token)) + { + m_peer_rank_token = PM_STORE_TOKEN_INVALID; + m_current_highest_peer_rank -= 1; + + p_pdb_evt->params.peer_data_update_succeeded.token = PM_STORE_TOKEN_INVALID; + } + } + break; +#endif + + case PM_EVT_PEER_DELETE_SUCCEEDED: + // Check that no peers marked for deletion are left. + if (m_deleting_all + && (pds_next_peer_id_get(PM_PEER_ID_INVALID) == PM_PEER_ID_INVALID) + && (pds_next_deleted_peer_id_get(PM_PEER_ID_INVALID) == PM_PEER_ID_INVALID)) + { + // pm_peers_delete() has been called and this is the last peer to be deleted. + m_deleting_all = false; + + pm_evt_t pm_delete_all_evt; + memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t)); + pm_delete_all_evt.evt_id = PM_EVT_PEERS_DELETE_SUCCEEDED; + pm_delete_all_evt.peer_id = PM_PEER_ID_INVALID; + pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID; + + send_evt = false; + + // Forward the event to all registered Peer Manager event handlers. + evt_send(p_pdb_evt); // Ensure that PEER_DELETE_SUCCEEDED arrives before PEERS_DELETE_SUCCEEDED. + evt_send(&pm_delete_all_evt); + } + +#if PM_PEER_RANKS_ENABLED == 1 + if (m_peer_rank_initialized && (p_pdb_evt->peer_id == m_highest_ranked_peer)) + { + // Update peer rank variable if highest ranked peer has been deleted. + rank_vars_update(); + } +#endif + break; + + case PM_EVT_PEER_DELETE_FAILED: + if (m_deleting_all) + { + // pm_peers_delete() was called and has thus failed. + + m_deleting_all = false; + + pm_evt_t pm_delete_all_evt; + memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t)); + pm_delete_all_evt.evt_id = PM_EVT_PEERS_DELETE_FAILED; + pm_delete_all_evt.peer_id = PM_PEER_ID_INVALID; + pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID; + pm_delete_all_evt.params.peers_delete_failed_evt.error + = p_pdb_evt->params.peer_delete_failed.error; + + send_evt = false; + + // Forward the event to all registered Peer Manager event handlers. + evt_send(p_pdb_evt); // Ensure that PEER_DELETE_FAILED arrives before PEERS_DELETE_FAILED. + evt_send(&pm_delete_all_evt); + } + break; + + default: + // Do nothing. + break; + } + + if (send_evt) + { + // Forward the event to all registered Peer Manager event handlers. + evt_send(p_pdb_evt); + } +} + + +/**@brief Event handler for events from the Security Manager module. + * This handler is extern in the Security Manager module. + * + * @param[in] p_sm_evt The incoming Security Manager event. + */ +void pm_sm_evt_handler(pm_evt_t * p_sm_evt) +{ + VERIFY_PARAM_NOT_NULL_VOID(p_sm_evt); + + // Forward the event to all registered Peer Manager event handlers. + evt_send(p_sm_evt); +} + + +/**@brief Event handler for events from the GATT Cache Manager module. + * This handler is extern in GATT Cache Manager. + * + * @param[in] p_gcm_evt The incoming GATT Cache Manager event. + */ +void pm_gcm_evt_handler(pm_evt_t * p_gcm_evt) +{ + // Forward the event to all registered Peer Manager event handlers. + evt_send(p_gcm_evt); +} + + +/**@brief Event handler for events from the GATTS Cache Manager module. + * This handler is extern in GATTS Cache Manager. + * + * @param[in] p_gscm_evt The incoming GATTS Cache Manager event. + */ +void pm_gscm_evt_handler(pm_evt_t * p_gscm_evt) +{ + // Forward the event to all registered Peer Manager event handlers. + evt_send(p_gscm_evt); +} + + +/**@brief Event handler for events from the ID Manager module. + * This function is registered in the ID Manager. + * + * @param[in] p_im_evt The incoming ID Manager event. + */ +void pm_im_evt_handler(pm_evt_t * p_im_evt) +{ + // Forward the event to all registered Peer Manager event handlers. + evt_send(p_im_evt); +} + + + +static bool is_conn_handle_excluded(ble_evt_t const * p_ble_evt) +{ + uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + { + pm_evt_t pm_conn_config_req_evt; + bool is_excluded = false; + + memset(&pm_conn_config_req_evt, 0, sizeof(pm_evt_t)); + pm_conn_config_req_evt.evt_id = PM_EVT_CONN_CONFIG_REQ; + pm_conn_config_req_evt.peer_id = PM_PEER_ID_INVALID; + pm_conn_config_req_evt.conn_handle = conn_handle; + + pm_conn_config_req_evt.params.conn_config_req.p_peer_params = + &p_ble_evt->evt.gap_evt.params.connected; + pm_conn_config_req_evt.params.conn_config_req.p_context = &is_excluded; + + evt_send(&pm_conn_config_req_evt); + ble_conn_state_user_flag_set(conn_handle, + m_flag_conn_excluded, + is_excluded); + + return is_excluded; + } + + default: + return ble_conn_state_user_flag_get(conn_handle, m_flag_conn_excluded); + } +} + +/** + * @brief Function for handling BLE events. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context Context. + */ +static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) +{ + VERIFY_MODULE_INITIALIZED_VOID(); + + if (is_conn_handle_excluded(p_ble_evt)) + { + NRF_LOG_DEBUG("Filtering BLE event with ID: 0x%04X targeting 0x%04X connection handle", + p_ble_evt->header.evt_id, p_ble_evt->evt.gap_evt.conn_handle); + return; + } + + im_ble_evt_handler(p_ble_evt); + sm_ble_evt_handler(p_ble_evt); + gcm_ble_evt_handler(p_ble_evt); +} + +NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, PM_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); + + +/**@brief Function for resetting the internal state of this module. + */ +static void internal_state_reset() +{ + m_highest_ranked_peer = PM_PEER_ID_INVALID; + m_peer_rank_token = PM_STORE_TOKEN_INVALID; +} + + +ret_code_t pm_init(void) +{ + ret_code_t err_code; + + err_code = pds_init(); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("%s failed because pds_init() returned %s.", __func__, nrf_strerror_get(err_code)); + return NRF_ERROR_INTERNAL; + } + + err_code = pdb_init(); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("%s failed because pdb_init() returned %s.", __func__, nrf_strerror_get(err_code)); + return NRF_ERROR_INTERNAL; + } + + err_code = sm_init(); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("%s failed because sm_init() returned %s.", __func__, nrf_strerror_get(err_code)); + return NRF_ERROR_INTERNAL; + } + + err_code = smd_init(); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("%s failed because smd_init() returned %s.", __func__, nrf_strerror_get(err_code)); + return NRF_ERROR_INTERNAL; + } + + err_code = gcm_init(); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("%s failed because gcm_init() returned %s.", __func__, nrf_strerror_get(err_code)); + return NRF_ERROR_INTERNAL; + } + + err_code = gscm_init(); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("%s failed because gscm_init() returned %s.", __func__, nrf_strerror_get(err_code)); + return NRF_ERROR_INTERNAL; + } + + internal_state_reset(); + + m_peer_rank_initialized = false; + m_module_initialized = true; + + m_flag_conn_excluded = ble_conn_state_user_flag_acquire(); + + // If PM_PEER_RANKS_ENABLED is 0, these variables are unused. + UNUSED_VARIABLE(m_peer_rank_initialized); + UNUSED_VARIABLE(m_peer_rank_token); + UNUSED_VARIABLE(m_current_highest_peer_rank); + UNUSED_VARIABLE(m_highest_ranked_peer); + + return NRF_SUCCESS; +} + + +ret_code_t pm_register(pm_evt_handler_t event_handler) +{ + VERIFY_MODULE_INITIALIZED(); + + if (m_n_registrants >= PM_MAX_REGISTRANTS) + { + return NRF_ERROR_NO_MEM; + } + + m_evt_handlers[m_n_registrants] = event_handler; + m_n_registrants += 1; + + return NRF_SUCCESS; +} + + +ret_code_t pm_sec_params_set(ble_gap_sec_params_t * p_sec_params) +{ + VERIFY_MODULE_INITIALIZED(); + + ret_code_t err_code; + + err_code = sm_sec_params_set(p_sec_params); + + // NRF_ERROR_INVALID_PARAM if parameters are invalid, + // NRF_SUCCESS otherwise. + return err_code; +} + + +ret_code_t pm_conn_secure(uint16_t conn_handle, bool force_repairing) +{ + VERIFY_MODULE_INITIALIZED(); + + ret_code_t err_code; + + err_code = sm_link_secure(conn_handle, force_repairing); + + if (err_code == NRF_ERROR_INVALID_STATE) + { + err_code = NRF_ERROR_BUSY; + } + + return err_code; +} + + +ret_code_t pm_conn_exclude(uint16_t conn_handle, void const * p_context) +{ + VERIFY_PARAM_NOT_NULL(p_context); + + bool * p_is_conn_excluded = (bool *) p_context; + + *p_is_conn_excluded = true; + + return NRF_SUCCESS; +} + + +void pm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config) +{ + if (p_conn_sec_config != NULL) + { + sm_conn_sec_config_reply(conn_handle, p_conn_sec_config); + } +} + + +ret_code_t pm_conn_sec_params_reply(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + void const * p_context) +{ + VERIFY_MODULE_INITIALIZED(); + + return sm_sec_params_reply(conn_handle, p_sec_params, p_context); +} + + +void pm_local_database_has_changed(void) +{ +#if !defined(PM_SERVICE_CHANGED_ENABLED) || (PM_SERVICE_CHANGED_ENABLED == 1) + VERIFY_MODULE_INITIALIZED_VOID(); + + gcm_local_database_has_changed(); +#endif +} + + +ret_code_t pm_id_addr_set(ble_gap_addr_t const * p_addr) +{ + VERIFY_MODULE_INITIALIZED(); + return im_id_addr_set(p_addr); +} + + +ret_code_t pm_id_addr_get(ble_gap_addr_t * p_addr) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_addr); + return im_id_addr_get(p_addr); +} + + +ret_code_t pm_privacy_set(pm_privacy_params_t const * p_privacy_params) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_privacy_params); + return im_privacy_set(p_privacy_params); +} + + +ret_code_t pm_privacy_get(pm_privacy_params_t * p_privacy_params) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_privacy_params); + VERIFY_PARAM_NOT_NULL(p_privacy_params->p_device_irk); + return im_privacy_get(p_privacy_params); +} + + +bool pm_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) +{ + VERIFY_MODULE_INITIALIZED(); + + if ((p_addr == NULL) || (p_irk == NULL)) + { + return false; + } + else + { + return im_address_resolve(p_addr, p_irk); + } +} + + +ret_code_t pm_whitelist_set(pm_peer_id_t const * p_peers, + uint32_t peer_cnt) +{ + VERIFY_MODULE_INITIALIZED(); + return im_whitelist_set(p_peers, peer_cnt); +} + + +ret_code_t pm_whitelist_get(ble_gap_addr_t * p_addrs, + uint32_t * p_addr_cnt, + ble_gap_irk_t * p_irks, + uint32_t * p_irk_cnt) +{ + VERIFY_MODULE_INITIALIZED(); + + if (((p_addrs == NULL) && (p_irks == NULL)) || + ((p_addrs != NULL) && (p_addr_cnt == NULL)) || + ((p_irks != NULL) && (p_irk_cnt == NULL))) + { + // The buffers can't be both NULL, and if a buffer is provided its size must be specified. + return NRF_ERROR_NULL; + } + + return im_whitelist_get(p_addrs, p_addr_cnt, p_irks, p_irk_cnt); +} + + +ret_code_t pm_device_identities_list_set(pm_peer_id_t const * p_peers, + uint32_t peer_cnt) +{ + VERIFY_MODULE_INITIALIZED(); + return im_device_identities_list_set(p_peers, peer_cnt); +} + + +ret_code_t pm_conn_sec_status_get(uint16_t conn_handle, pm_conn_sec_status_t * p_conn_sec_status) +{ + VERIFY_MODULE_INITIALIZED(); + return sm_conn_sec_status_get(conn_handle, p_conn_sec_status); +} + + +bool pm_sec_is_sufficient(uint16_t conn_handle, pm_conn_sec_status_t * p_sec_status_req) +{ + VERIFY_MODULE_INITIALIZED_BOOL(); + return sm_sec_is_sufficient(conn_handle, p_sec_status_req); +} + + +ret_code_t pm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key) +{ + VERIFY_MODULE_INITIALIZED(); + return sm_lesc_public_key_set(p_public_key); +} + + +ret_code_t pm_conn_handle_get(pm_peer_id_t peer_id, uint16_t * p_conn_handle) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_conn_handle); + *p_conn_handle = im_conn_handle_get(peer_id); + return NRF_SUCCESS; +} + + +ret_code_t pm_peer_id_get(uint16_t conn_handle, pm_peer_id_t * p_peer_id) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_peer_id); + *p_peer_id = im_peer_id_get_by_conn_handle(conn_handle); + return NRF_SUCCESS; +} + + +uint32_t pm_peer_count(void) +{ + if (!MODULE_INITIALIZED) + { + return 0; + } + return pds_peer_count_get(); +} + + +pm_peer_id_t pm_next_peer_id_get(pm_peer_id_t prev_peer_id) +{ + pm_peer_id_t next_peer_id = prev_peer_id; + + if (!MODULE_INITIALIZED) + { + return PM_PEER_ID_INVALID; + } + + do + { + next_peer_id = pds_next_peer_id_get(next_peer_id); + } while (pds_peer_id_is_deleted(next_peer_id)); + + return next_peer_id; +} + + +/**@brief Function for checking if the peer has a valid Identity Resolving Key. + * + * @param[in] p_irk Pointer to the Identity Resolving Key. + */ +static bool peer_is_irk(ble_gap_irk_t const * const p_irk) +{ + for (uint32_t i = 0; i < ARRAY_SIZE(p_irk->irk); i++) + { + if (p_irk->irk[i] != 0) + { + return true; + } + } + + return false; +} + + +ret_code_t pm_peer_id_list(pm_peer_id_t * p_peer_list, + uint32_t * const p_list_size, + pm_peer_id_t first_peer_id, + pm_peer_id_list_skip_t skip_id) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_list_size); + VERIFY_PARAM_NOT_NULL(p_peer_list); + + ret_code_t err_code; + uint32_t size = *p_list_size; + uint32_t current_size = 0; + pm_peer_data_t pm_car_data; + pm_peer_data_t pm_bond_data; + pm_peer_id_t current_peer_id = first_peer_id; + ble_gap_addr_t const * p_gap_addr; + bool skip_no_addr = skip_id & PM_PEER_ID_LIST_SKIP_NO_ID_ADDR; + bool skip_no_irk = skip_id & PM_PEER_ID_LIST_SKIP_NO_IRK; + bool skip_no_car = skip_id & PM_PEER_ID_LIST_SKIP_NO_CAR; + + //lint -save -e685 + if ((*p_list_size < 1) || + (skip_id > (PM_PEER_ID_LIST_SKIP_NO_ID_ADDR | PM_PEER_ID_LIST_SKIP_ALL))) + { + return NRF_ERROR_INVALID_PARAM; + } + //lint -restore + + *p_list_size = 0; + + if (current_peer_id == PM_PEER_ID_INVALID) + { + current_peer_id = pm_next_peer_id_get(current_peer_id); + + if (current_peer_id == PM_PEER_ID_INVALID) + { + return NRF_SUCCESS; + } + } + + memset(&pm_car_data, 0, sizeof(pm_peer_data_t)); + memset(&pm_bond_data, 0, sizeof(pm_peer_data_t)); + + while (current_peer_id != PM_PEER_ID_INVALID) + { + bool skip = false; + + if (skip_no_addr || skip_no_irk) + { + // Get data + pm_bond_data.p_bonding_data = NULL; + + err_code = pds_peer_data_read(current_peer_id, + PM_PEER_DATA_ID_BONDING, + &pm_bond_data, + NULL); + + if (err_code == NRF_ERROR_NOT_FOUND) + { + skip = true; + } + else + { + VERIFY_SUCCESS(err_code); + } + + // Check data + if (skip_no_addr) + { + p_gap_addr = &pm_bond_data.p_bonding_data->peer_ble_id.id_addr_info; + + if ((p_gap_addr->addr_type != BLE_GAP_ADDR_TYPE_PUBLIC) && + (p_gap_addr->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_STATIC)) + { + skip = true; + } + } + if (skip_no_irk) + { + if (!peer_is_irk(&pm_bond_data.p_bonding_data->peer_ble_id.id_info)) + { + skip = true; + } + } + } + + if (skip_no_car) + { + // Get data + pm_car_data.p_central_addr_res = NULL; + + err_code = pds_peer_data_read(current_peer_id, + PM_PEER_DATA_ID_CENTRAL_ADDR_RES, + &pm_car_data, + NULL); + + if (err_code == NRF_ERROR_NOT_FOUND) + { + skip = true; + } + else + { + VERIFY_SUCCESS(err_code); + } + + // Check data + if (*pm_car_data.p_central_addr_res == 0) + { + skip = true; + } + } + + if (!skip) + { + p_peer_list[current_size++] = current_peer_id; + + if (current_size >= size) + { + break; + } + } + + current_peer_id = pm_next_peer_id_get(current_peer_id); + } + + *p_list_size = current_size; + + return NRF_SUCCESS; +} + + +ret_code_t pm_peer_data_load(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + void * p_data, + uint32_t * p_length) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_data); + VERIFY_PARAM_NOT_NULL(p_length); + + pm_peer_data_t peer_data; + memset(&peer_data, 0, sizeof(peer_data)); + peer_data.p_all_data = p_data; + + return pds_peer_data_read(peer_id, data_id, &peer_data, p_length); +} + + +ret_code_t pm_peer_data_bonding_load(pm_peer_id_t peer_id, + pm_peer_data_bonding_t * p_data) +{ + uint32_t length = sizeof(pm_peer_data_bonding_t); + return pm_peer_data_load(peer_id, + PM_PEER_DATA_ID_BONDING, + p_data, + &length); +} + + +ret_code_t pm_peer_data_remote_db_load(pm_peer_id_t peer_id, + ble_gatt_db_srv_t * p_data, + uint32_t * p_length) +{ + return pm_peer_data_load(peer_id, + PM_PEER_DATA_ID_GATT_REMOTE, + p_data, + p_length); +} + + +ret_code_t pm_peer_data_app_data_load(pm_peer_id_t peer_id, + void * p_data, + uint32_t * p_length) +{ + return pm_peer_data_load(peer_id, + PM_PEER_DATA_ID_APPLICATION, + p_data, + p_length); +} + + +ret_code_t pm_peer_data_store(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + void const * p_data, + uint32_t length, + pm_store_token_t * p_token) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_data); + if (ALIGN_NUM(4, length) != length) + { + return NRF_ERROR_INVALID_PARAM; + } + + if (data_id == PM_PEER_DATA_ID_BONDING) + { + pm_peer_id_t dupl_peer_id; + dupl_peer_id = im_find_duplicate_bonding_data((pm_peer_data_bonding_t *) p_data, peer_id); + + if (dupl_peer_id != PM_PEER_ID_INVALID) + { + return NRF_ERROR_FORBIDDEN; + } + } + + pm_peer_data_flash_t peer_data; + memset(&peer_data, 0, sizeof(peer_data)); + peer_data.length_words = BYTES_TO_WORDS(length); + peer_data.data_id = data_id; + peer_data.p_all_data = p_data; + + return pds_peer_data_store(peer_id, &peer_data, p_token); +} + + +ret_code_t pm_peer_data_bonding_store(pm_peer_id_t peer_id, + pm_peer_data_bonding_t const * p_data, + pm_store_token_t * p_token) +{ + return pm_peer_data_store(peer_id, + PM_PEER_DATA_ID_BONDING, + p_data, + ALIGN_NUM(4, sizeof(pm_peer_data_bonding_t)), + p_token); +} + + +ret_code_t pm_peer_data_remote_db_store(pm_peer_id_t peer_id, + ble_gatt_db_srv_t const * p_data, + uint32_t length, + pm_store_token_t * p_token) +{ + return pm_peer_data_store(peer_id, + PM_PEER_DATA_ID_GATT_REMOTE, + p_data, + length, + p_token); +} + + +ret_code_t pm_peer_data_app_data_store(pm_peer_id_t peer_id, + void const * p_data, + uint32_t length, + pm_store_token_t * p_token) +{ + return pm_peer_data_store(peer_id, + PM_PEER_DATA_ID_APPLICATION, + p_data, + length, + p_token); +} + + +ret_code_t pm_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) +{ + VERIFY_MODULE_INITIALIZED(); + + if (data_id == PM_PEER_DATA_ID_BONDING) + { + return NRF_ERROR_INVALID_PARAM; + } + + return pds_peer_data_delete(peer_id, data_id); +} + + +ret_code_t pm_peer_new(pm_peer_id_t * p_new_peer_id, + pm_peer_data_bonding_t * p_bonding_data, + pm_store_token_t * p_token) +{ + ret_code_t err_code; + pm_peer_id_t peer_id; + pm_peer_data_flash_t peer_data; + + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_bonding_data); + VERIFY_PARAM_NOT_NULL(p_new_peer_id); + + memset(&peer_data, 0, sizeof(pm_peer_data_flash_t)); + + // Search through existing bonds to look for a duplicate. + pds_peer_data_iterate_prepare(); + + // @note This check is not thread safe since data is not copied while iterating. + while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) + { + if (im_is_duplicate_bonding_data(p_bonding_data, peer_data.p_bonding_data)) + { + *p_new_peer_id = peer_id; + return NRF_SUCCESS; + } + } + + // If no duplicate data is found, prepare to write a new bond to flash. + + *p_new_peer_id = pds_peer_id_allocate(); + + if (*p_new_peer_id == PM_PEER_ID_INVALID) + { + return NRF_ERROR_NO_MEM; + } + + memset(&peer_data, 0, sizeof(pm_peer_data_flash_t)); + + peer_data.data_id = PM_PEER_DATA_ID_BONDING; + peer_data.p_bonding_data = p_bonding_data; + peer_data.length_words = BYTES_TO_WORDS(sizeof(pm_peer_data_bonding_t)); + + err_code = pds_peer_data_store(*p_new_peer_id, &peer_data, p_token); + + if (err_code != NRF_SUCCESS) + { + ret_code_t err_code_free = im_peer_free(*p_new_peer_id); + if (err_code_free != NRF_SUCCESS) + { + NRF_LOG_ERROR("Fatal error during cleanup of a failed call to %s. im_peer_free() "\ + "returned %s. peer_id: %d", + __func__, + nrf_strerror_get(err_code_free), + *p_new_peer_id); + return NRF_ERROR_INTERNAL; + } + + // NRF_ERROR_STORAGE_FULL, if no space in flash. + // NRF_ERROR_BUSY, if flash filesystem was busy. + // NRF_ERROR_INVALID_ADDR, if bonding data is unaligned. + // NRF_ERROR_INTENRAL, on internal error. + return err_code; + } + + return NRF_SUCCESS; +} + + +ret_code_t pm_peer_delete(pm_peer_id_t peer_id) +{ + VERIFY_MODULE_INITIALIZED(); + + return im_peer_free(peer_id); +} + + +ret_code_t pm_peers_delete(void) +{ + VERIFY_MODULE_INITIALIZED(); + + m_deleting_all = true; + + pm_peer_id_t current_peer_id = pds_next_peer_id_get(PM_PEER_ID_INVALID); + + if (current_peer_id == PM_PEER_ID_INVALID) + { + // No peers bonded. + m_deleting_all = false; + + pm_evt_t pm_delete_all_evt; + memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t)); + pm_delete_all_evt.evt_id = PM_EVT_PEERS_DELETE_SUCCEEDED; + pm_delete_all_evt.peer_id = PM_PEER_ID_INVALID; + pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID; + + evt_send(&pm_delete_all_evt); + } + + while (current_peer_id != PM_PEER_ID_INVALID) + { + ret_code_t err_code = pm_peer_delete(current_peer_id); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("%s() failed because a call to pm_peer_delete() returned %s. peer_id: %d", + __func__, + nrf_strerror_get(err_code), + current_peer_id); + return NRF_ERROR_INTERNAL; + } + + current_peer_id = pds_next_peer_id_get(current_peer_id); + } + + return NRF_SUCCESS; +} + + +ret_code_t pm_peer_ranks_get(pm_peer_id_t * p_highest_ranked_peer, + uint32_t * p_highest_rank, + pm_peer_id_t * p_lowest_ranked_peer, + uint32_t * p_lowest_rank) +{ +#if PM_PEER_RANKS_ENABLED == 0 + return NRF_ERROR_NOT_SUPPORTED; +#else + VERIFY_MODULE_INITIALIZED(); + + pm_peer_id_t peer_id = pds_next_peer_id_get(PM_PEER_ID_INVALID); + uint32_t peer_rank = 0; + //lint -save -e65 -e64 + uint32_t length = sizeof(peer_rank); + pm_peer_data_t peer_data = {.p_peer_rank = &peer_rank}; + //lint -restore + ret_code_t err_code = pds_peer_data_read(peer_id, + PM_PEER_DATA_ID_PEER_RANK, + &peer_data, + &length); + uint32_t highest_rank = 0; + uint32_t lowest_rank = 0xFFFFFFFF; + pm_peer_id_t highest_ranked_peer = PM_PEER_ID_INVALID; + pm_peer_id_t lowest_ranked_peer = PM_PEER_ID_INVALID; + + if (err_code == NRF_ERROR_INVALID_PARAM) + { + // No peer IDs exist. + return NRF_ERROR_NOT_FOUND; + } + + while ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NOT_FOUND)) + { + if (err_code == NRF_SUCCESS) + { + if (peer_rank >= highest_rank) + { + highest_rank = peer_rank; + highest_ranked_peer = peer_id; + } + if (peer_rank < lowest_rank) + { + lowest_rank = peer_rank; + lowest_ranked_peer = peer_id; + } + } + peer_id = pds_next_peer_id_get(peer_id); + err_code = pds_peer_data_read(peer_id, PM_PEER_DATA_ID_PEER_RANK, &peer_data, &length); + } + if (peer_id == PM_PEER_ID_INVALID) + { + if ((highest_ranked_peer == PM_PEER_ID_INVALID) || (lowest_ranked_peer == PM_PEER_ID_INVALID)) + { + err_code = NRF_ERROR_NOT_FOUND; + } + else + { + err_code = NRF_SUCCESS; + } + + if (p_highest_ranked_peer != NULL) + { + *p_highest_ranked_peer = highest_ranked_peer; + } + if (p_highest_rank != NULL) + { + *p_highest_rank = highest_rank; + } + if (p_lowest_ranked_peer != NULL) + { + *p_lowest_ranked_peer = lowest_ranked_peer; + } + if (p_lowest_rank != NULL) + { + *p_lowest_rank = lowest_rank; + } + } + else + { + NRF_LOG_ERROR("Could not retreive ranks. pdb_peer_data_load() returned %s. peer_id: %d", + nrf_strerror_get(err_code), + peer_id); + err_code = NRF_ERROR_INTERNAL; + } + return err_code; +#endif +} + + +#if PM_PEER_RANKS_ENABLED == 1 +/**@brief Function for initializing peer rank functionality. + */ +static void rank_init(void) +{ + rank_vars_update(); +} +#endif + + +ret_code_t pm_peer_rank_highest(pm_peer_id_t peer_id) +{ +#if PM_PEER_RANKS_ENABLED == 0 + return NRF_ERROR_NOT_SUPPORTED; +#else + VERIFY_MODULE_INITIALIZED(); + + ret_code_t err_code; + //lint -save -e65 -e64 + pm_peer_data_flash_t peer_data = {.length_words = BYTES_TO_WORDS(sizeof(m_current_highest_peer_rank)), + .data_id = PM_PEER_DATA_ID_PEER_RANK, + .p_peer_rank = &m_current_highest_peer_rank}; + //lint -restore + + + if (!m_peer_rank_initialized) + { + rank_init(); + } + + if (!m_peer_rank_initialized || (m_peer_rank_token != PM_STORE_TOKEN_INVALID)) + { + err_code = NRF_ERROR_BUSY; + } + else + { + if ((peer_id == m_highest_ranked_peer) && (m_current_highest_peer_rank > 0)) + { + pm_evt_t pm_evt; + + // The reported peer is already regarded as highest (provided it has an index at all) + err_code = NRF_SUCCESS; + + memset(&pm_evt, 0, sizeof(pm_evt)); + pm_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_SUCCEEDED; + pm_evt.conn_handle = im_conn_handle_get(peer_id); + pm_evt.peer_id = peer_id; + pm_evt.params.peer_data_update_succeeded.data_id = PM_PEER_DATA_ID_PEER_RANK; + pm_evt.params.peer_data_update_succeeded.action = PM_PEER_DATA_OP_UPDATE; + pm_evt.params.peer_data_update_succeeded.token = PM_STORE_TOKEN_INVALID; + pm_evt.params.peer_data_update_succeeded.flash_changed = false; + + evt_send(&pm_evt); + } + else + { + if (m_current_highest_peer_rank == UINT32_MAX) + { + err_code = NRF_ERROR_RESOURCES; + } + else + { + m_current_highest_peer_rank += 1; + err_code = pds_peer_data_store(peer_id, &peer_data, &m_peer_rank_token); + if (err_code != NRF_SUCCESS) + { + m_peer_rank_token = PM_STORE_TOKEN_INVALID; + m_current_highest_peer_rank -= 1; + if ((err_code != NRF_ERROR_BUSY) && + (err_code != NRF_ERROR_STORAGE_FULL) && + (err_code != NRF_ERROR_INVALID_PARAM)) // Assume INVALID_PARAM refers to peer_id, not data_id. + { + NRF_LOG_ERROR("Could not update rank. pdb_raw_store() returned %s. "\ + "peer_id: %d", + nrf_strerror_get(err_code), + peer_id); + err_code = NRF_ERROR_INTERNAL; + } + } + } + } + } + return err_code; +#endif +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/components/ble/peer_manager/peer_manager.h b/components/ble/peer_manager/peer_manager.h new file mode 100644 index 0000000..3576828 --- /dev/null +++ b/components/ble/peer_manager/peer_manager.h @@ -0,0 +1,856 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * @file peer_manager.h + * + * @defgroup peer_manager Peer Manager + * @ingroup ble_sdk_lib + * @{ + * @brief Module for managing BLE bonding, which includes controlling encryption and pairing + * procedures as well as persistently storing different pieces of data that must be stored + * when bonded. + * + * @details The API consists of functions for configuring the pairing and encryption behavior of the + * device and functions for manipulating the stored data. + * + * This module uses Flash Data Storage (FDS) to interface with persistent storage. The + * Peer Manager needs exclusive use of certain FDS file IDs and record keys. See + * @ref lib_fds_functionality_keys for more information. + */ + + +#ifndef PEER_MANAGER_H__ +#define PEER_MANAGER_H__ + +#include +#include +#include "sdk_common.h" +#include "ble.h" +#include "ble_gap.h" +#include "peer_manager_types.h" +#include "peer_database.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Peer list filtrations. They determine which peer ID will be added to list. + */ +typedef enum +{ + PM_PEER_ID_LIST_ALL_ID, /**< Add all peers. */ + PM_PEER_ID_LIST_SKIP_NO_ID_ADDR = BIT_0, /**< Add only peers with an ID address (static address). */ + PM_PEER_ID_LIST_SKIP_NO_IRK = BIT_1, /**< Add only peers with a valid IRK. This implies @ref PM_PEER_ID_LIST_SKIP_NO_ID_ADDR, since all peers with IRKs have ID addresses. */ + PM_PEER_ID_LIST_SKIP_NO_CAR = BIT_2, /**< Add only peers with Central Address Resolution characteristic set to 0. */ + PM_PEER_ID_LIST_SKIP_ALL = PM_PEER_ID_LIST_SKIP_NO_IRK | /**< All above filters applied. */ + PM_PEER_ID_LIST_SKIP_NO_CAR +} pm_peer_id_list_skip_t; + +/**@brief Function for initializing the Peer Manager. + * + * @details You must initialize the Peer Manager before you can call any other Peer Manager + * functions. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_init(void); + + +/**@brief Function for registering an event handler with the Peer Manager. + * + * @param[in] event_handler Callback for events from the @ref peer_manager module. @p event_handler + * is called for every event that the Peer Manager sends after this + * function is called. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_NULL If @p event_handler was NULL. + * @retval NRF_ERROR_NO_MEM If no more registrations can happen. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_register(pm_evt_handler_t event_handler); + + +/**@brief Function for providing pairing and bonding parameters to use for pairing procedures. + * + * @details Until this function is called, all bonding procedures that are initiated by the + * peer are rejected. + * + * This function can be called multiple times with different parameters, even with NULL as + * @p p_sec_params, in which case the Peer Manager starts rejecting all procedures again. + * + * @param[in] p_sec_params Security parameters to be used for subsequent security procedures. + * + * @retval NRF_SUCCESS If the parameters were set successfully. + * @retval NRF_ERROR_INVALID_PARAM If the combination of parameters is invalid. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_sec_params_set(ble_gap_sec_params_t * p_sec_params); + + +/**@brief Function for establishing encryption on a connection, and optionally establishing a bond. + * + * @details This function attempts to secure the link that is specified by @p conn_handle. It uses + * the parameters that were previously provided in a call to @ref pm_sec_params_set. + * + * If the connection is a master connection, calling this function starts a security + * procedure on the link. If we have keys from a previous bonding procedure with this peer + * and the keys meet the security requirements in the currently active security parameters, + * the function attempts to establish encryption with the existing keys. If no key exists, + * the function attempts to perform pairing and bonding according to the currently active + * security parameters. + * + * If the function completes successfully, a @ref PM_EVT_CONN_SEC_START event is sent. + * The procedure might be queued, in which case the @ref PM_EVT_CONN_SEC_START event is + * delayed until the procedure is initiated in the SoftDevice. + * + * If the connection is a slave connection, the function sends a security request to + * the peer (master). It is up to the peer then to initiate pairing or encryption. + * If the peer ignores the request, a @ref BLE_GAP_EVT_AUTH_STATUS event occurs + * with the status @ref BLE_GAP_SEC_STATUS_TIMEOUT. Otherwise, the peer initiates + * security, in which case things happen as if the peer had initiated security itself. + * See @ref PM_EVT_CONN_SEC_START for information about peer-initiated security. + * + * @param[in] conn_handle Connection handle of the link as provided by the SoftDevice. + * @param[in] force_repairing Whether to force a pairing procedure even if there is an existing + * encryption key. This argument is relevant only for + * the central role. Recommended value: false. + * + * @retval NRF_SUCCESS If the operation completed successfully. + * @retval NRF_ERROR_BUSY If a security procedure is already in progress on the link, + * or if the link is disconnecting or disconnected. + * @retval NRF_ERROR_TIMEOUT If there was an SMP time-out, so that no more security + * operations can be performed on this link. + * @retval BLE_ERROR_INVALID_CONN_HANDLE If the connection handle is invalid. + * @retval NRF_ERROR_NOT_FOUND If the security parameters have not been set, either by + * @ref pm_sec_params_set or by @ref pm_conn_sec_params_reply. + * @retval NRF_ERROR_INVALID_DATA If the peer is bonded, but no LTK was found in the stored + * bonding data. Repairing was not requested. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_conn_secure(uint16_t conn_handle, bool force_repairing); + + +/**@brief Function for excluding a connection from the BLE event flow that is handled inside + * the Peer Manager. + * + * @details This function is optional, and must be called in reply to a @ref PM_EVT_CONN_CONFIG_REQ + * event, before the Peer Manager event handler returns. If it is not called in time, + * BLE events for a connection handle passed in the @ref PM_EVT_CONN_CONFIG_REQ event will + * be normally handled by the Peer Manager. + * + * @param[in] conn_handle The connection to be excluded. + * @param[in] p_context The context found in the request event that this function replies to. + * + * @retval NRF_SUCCESS Successful reply. + * @retval NRF_ERROR_NULL p_context was null. + */ +ret_code_t pm_conn_exclude(uint16_t conn_handle, void const * p_context); + + +/**@brief Function for providing security configuration for a link. + * + * @details This function is optional, and must be called in reply to a @ref + * PM_EVT_CONN_SEC_CONFIG_REQ event, before the Peer Manager event handler returns. If it + * is not called in time, a default configuration is used. See @ref pm_conn_sec_config_t + * for the value of the default. + * + * @param[in] conn_handle The connection to set the configuration for. + * @param[in] p_conn_sec_config The configuration. + */ +void pm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config); + + +/**@brief Function for providing security parameters for a link. + * + * @details This function is optional, and must be called in reply to a @ref + * PM_EVT_CONN_SEC_PARAMS_REQ event, before the Peer Manager event handler returns. If it + * is not called in time, the parameters given in @ref pm_sec_params_set are used. + * + * @param[in] conn_handle The connection to set the parameters for. + * @param[in] p_sec_params The parameters. If NULL, the security procedure is rejected. + * @param[in] p_context The context found in the request event that this function replies to. + * + * @retval NRF_SUCCESS Successful reply. + * @retval NRF_ERROR_NULL p_sec_params or p_context was null. + * @retval NRF_ERROR_INVALID_PARAM Value of p_sec_params was invalid. + * @retval NRF_ERROR_INVALID_STATE This module is not initialized. + */ +ret_code_t pm_conn_sec_params_reply(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + void const * p_context); + + +/**@brief Function for manually informing that the local database has changed. + * + * @details This function sends a service changed indication to all bonded and/or connected peers + * that subscribe to this indication. If a bonded peer is not connected, the indication is + * sent when it reconnects. Every time an indication is sent, a @ref + * PM_EVT_SERVICE_CHANGED_IND_SENT event occurs, followed by a @ref + * PM_EVT_SERVICE_CHANGED_IND_CONFIRMED when the peer sends its confirmation. Peers that + * are not subscribed to the service changed indication when this function is called do not + * receive an indication, and no events are sent to the user. Likewise, if the service + * changed characteristic is not present in the local database, or if the @ref + * PM_SERVICE_CHANGED_ENABLED is set to 0, no indications are sent peers, and no events are + * sent to the user. + */ +void pm_local_database_has_changed(void); + + +/**@brief Function for getting the security status of a connection. + * + * @param[in] conn_handle Connection handle of the link as provided by the SoftDevice. + * @param[out] p_conn_sec_status Security status of the link. + * + * @retval NRF_SUCCESS If pairing was initiated successfully. + * @retval BLE_ERROR_INVALID_CONN_HANDLE If the connection handle is invalid. + * @retval NRF_ERROR_NULL If @p p_conn_sec_status was NULL. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_conn_sec_status_get(uint16_t conn_handle, pm_conn_sec_status_t * p_conn_sec_status); + + +/**@brief Function for comparing the security status of a connection against a baseline. + * + * @param[in] conn_handle Connection handle of the link as provided by the SoftDevice. + * @param[out] p_sec_status_req Target baseline security status to compare against. + * + * @retval true If the security status of the connection matches or exceeds the baseline on all + * points. + * @retval false If the security status of the connection does not fulfil the baseline, or could + * not be retrieved. + */ +bool pm_sec_is_sufficient(uint16_t conn_handle, pm_conn_sec_status_t * p_sec_status_req); + + +/**@brief Experimental function for specifying the public key to use for LESC operations. + * + * @details This function can be called multiple times. The specified public key will be used for + * all subsequent LESC (LE Secure Connections) operations until the next time this function + * is called. + * + * @note The key must continue to reside in application memory as it is not copied by Peer Manager. + * + * @note This function is deprecated. LESC keys are now handled internally if @ref PM_LESC_ENABLED + * is true. If @ref PM_LESC_ENABLED is false, this function works as before. + * + * @param[in] p_public_key The public key to use for all subsequent LESC operations. + * + * @retval NRF_SUCCESS If pairing was initiated successfully. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_FORBIDDEN If LESC module support is enabled (see @ref PM_LESC_ENABLED). + */ +ret_code_t pm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key); + + +/**@brief Function for setting or clearing the whitelist. + * + * When using the S13x SoftDevice v3.x, this function sets or clears the whitelist. + * When using the S13x SoftDevice v2.x, this function caches a list of + * peers that can be retrieved later by @ref pm_whitelist_get to pass to the @ref lib_ble_advertising. + * + * To clear the current whitelist, pass either NULL as @p p_peers or zero as @p peer_cnt. + * + * @param[in] p_peers The peers to add to the whitelist. Pass NULL to clear the current whitelist. + * @param[in] peer_cnt The number of peers to add to the whitelist. The number must not be greater than + * @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. Pass zero to clear the current + * whitelist. + * + * @retval NRF_SUCCESS If the whitelist was successfully set or cleared. + * @retval BLE_GAP_ERROR_WHITELIST_IN_USE If a whitelist is already in use and cannot be set. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If a peer in @p p_peers has an address that cannot + * be used for whitelisting. + * @retval NRF_ERROR_NOT_FOUND If any of the peers in @p p_peers cannot be found. + * @retval NRF_ERROR_DATA_SIZE If @p peer_cnt is greater than + * @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_whitelist_set(pm_peer_id_t const * p_peers, + uint32_t peer_cnt); + + +/**@brief Function for retrieving the previously set whitelist. + * + * The function retrieves the whitelist of GAP addresses and IRKs that was + * previously set by @ref pm_whitelist_set. + * + * To retrieve only GAP addresses or only IRKs, provide only one of the + * buffers. If a buffer is provided, its size must be specified. + * + * @param[out] p_addrs The buffer where to store GAP addresses. Pass NULL to retrieve + * only IRKs (in that case, @p p_irks must not be NULL). + * @param[in,out] p_addr_cnt In: The size of the @p p_addrs buffer. + * May be NULL if and only if @p p_addrs is NULL. + * Out: The number of GAP addresses copied into the buffer. + * If @p p_addrs is NULL, this parameter remains unchanged. + * @param[out] p_irks The buffer where to store IRKs. Pass NULL to retrieve + * only GAP addresses (in that case, @p p_addrs must not NULL). + * @param[in,out] p_irk_cnt In: The size of the @p p_irks buffer. + * May be NULL if and only if @p p_irks is NULL. + * Out: The number of IRKs copied into the buffer. + * If @p p_irks is NULL, this paramater remains unchanged. + * + * @retval NRF_SUCCESS If the whitelist was successfully retrieved. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If a peer has an address that cannot be used for + * whitelisting (this error can occur only + * when using the S13x SoftDevice v2.x). + * @retval NRF_ERROR_NULL If a required parameter is NULL. + * @retval NRF_ERROR_NO_MEM If the provided buffers are too small. + * @retval NRF_ERROR_NOT_FOUND If the data for any of the cached whitelisted peers + * cannot be found. It might have been deleted. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_whitelist_get(ble_gap_addr_t * p_addrs, + uint32_t * p_addr_cnt, + ble_gap_irk_t * p_irks, + uint32_t * p_irk_cnt); + + +/**@brief Function for setting and clearing the device identities list. + * + * @note When entering directed advertising, make sure the active identities list does not contain + * peers that have no Central Address Resolution. See @ref pm_peer_id_list with skip_id + * @ref PM_PEER_ID_LIST_SKIP_NO_CAR. + * + * @param[in] p_peers The peers to add to the device identities list. Pass NULL to clear + * the device identities list. + * @param[in] peer_cnt The number of peers. Pass zero to clear the device identities list. + * + * @retval NRF_SUCCESS If the device identities list was successfully + * set or cleared. + * @retval NRF_ERROR_NOT_FOUND If a peer is invalid or its data could not + * be found in flash. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If a peer has an address that cannot be + * used for whitelisting. + * @retval BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE If the device identities list is in use and + * cannot be set. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_NOT_SUPPORTED If using a SoftDevice that does not support + * device identities, e.g. S130 v2.0. + */ +ret_code_t pm_device_identities_list_set(pm_peer_id_t const * p_peers, + uint32_t peer_cnt); + + +/**@brief Function for setting the local Bluetooth identity address. + * + * @details The local Bluetooth identity address is the address that identifies the device + * to other peers. The address type must be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref + * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. The identity address cannot be changed while roles are running. + * + * The SoftDevice sets a default address of type @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC when it is + * enabled. This default address is a random number that is populated during the IC manufacturing + * process. It remains unchanged for the lifetime of each IC, but the application can use this + * function to assign a different identity address. + * + * The identity address is distributed to the peer during bonding. Changing the identity address + * means bonded devices might not recognize us. + * + * @note The SoftDevice functions @ref sd_ble_gap_addr_set and @ref sd_ble_gap_privacy_set must not + * be called when using the Peer Manager. Use the Peer Manager equivalents instead. + * + * @param[in] p_addr The GAP address to be set. + * + * @retval NRF_SUCCESS If the identity address was set successfully. + * @retval NRF_ERROR_NULL If @p p_addr is NULL. + * @retval NRF_ERROR_INVALID_ADDR If the @p p_addr pointer is invalid. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If the BLE address is invalid. + * @retval NRF_ERROR_BUSY If the SoftDevice was busy. Process SoftDevice events + * and retry. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized or if this function + * was called while advertising, scanning, or while connected. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_id_addr_set(ble_gap_addr_t const * p_addr); + + +/**@brief Function for retrieving the local Bluetooth identity address. + * + * This function always returns the identity address, irrespective of the privacy settings. + * This means that the address type will always be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref + * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. + * + * @param[out] p_addr Pointer to the address structure to be filled in. + * + * @retval NRF_SUCCESS If the address was retrieved successfully. + * @retval NRF_ERROR_NULL If @p p_addr is NULL. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_id_addr_get(ble_gap_addr_t * p_addr); + + +/**@brief Function for configuring privacy settings. + * + * The privacy settings cannot be configured while advertising, scanning, or while in a connection. + * + * @note The SoftDevice functions @ref sd_ble_gap_addr_set + * and @ref sd_ble_gap_privacy_set must not be called when using the Peer Manager. + * Use this function instead. + * + * @param[in] p_privacy_params Privacy settings. + * + * @retval NRF_SUCCESS If the privacy settings were configured successfully. + * @retval NRF_ERROR_NULL If @p p_privacy_params is NULL. + * @retval NRF_ERROR_BUSY If the operation could not be performed at this time. + * Process SoftDevice events and retry. + * @retval NRF_ERROR_INVALID_PARAM If the address type is invalid. + * @retval NRF_ERROR_INVALID_STATE If this function is called while BLE roles using + * privacy are enabled. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_privacy_set(pm_privacy_params_t const * p_privacy_params); + + +/**@brief Function for retrieving privacy settings. + * + * The privacy settings that are returned include the current IRK as well. + * + * @param[out] p_privacy_params Privacy settings. + * + * @retval NRF_SUCCESS If the privacy settings were retrieved successfully. + * @retval NRF_ERROR_NULL If @p p_privacy_params or @p p_privacy_params->p_device_irk is + * NULL. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_privacy_get(pm_privacy_params_t * p_privacy_params); + + +/**@brief Function for resolving a resolvable address with an identity resolution key (IRK). + * + * @param[in] p_addr A private random resolvable address. + * @param[in] p_irk An identity resolution key (IRK). + * + * @retval true The IRK used matched the one used to create the address. + * @retval false The IRK used did not match the one used to create the address, or an argument was + * NULL or invalid. + */ +bool pm_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk); + + +/**@brief Function for getting the connection handle of the connection with a bonded peer. + * + * @param[in] peer_id The peer ID of the bonded peer. + * @param[out] p_conn_handle Connection handle, or @ref BLE_CONN_HANDLE_INVALID if none could be + * resolved. The conn_handle can refer to a recently disconnected connection. + * + * @retval NRF_SUCCESS If the connection handle was retrieved successfully. + * @retval NRF_ERROR_NULL If @p p_conn_handle was NULL. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_conn_handle_get(pm_peer_id_t peer_id, uint16_t * p_conn_handle); + + +/**@brief Function for retrieving the ID of a peer, given its connection handle. + * + * @param[in] conn_handle The connection handle of the peer. + * @param[out] p_peer_id The peer ID, or @ref PM_PEER_ID_INVALID if the peer is not bonded or + * @p conn_handle does not refer to a valid connection. + * + * @retval NRF_SUCCESS If the peer ID was retrieved successfully. + * @retval NRF_ERROR_NULL If @p p_peer_id was NULL. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_peer_id_get(uint16_t conn_handle, pm_peer_id_t * p_peer_id); + + +/**@brief Function for retrieving a filtered list of peer IDs. + * + * @details This function starts searching from @p first_peer_id. IDs ordering + * is the same as for @ref pm_next_peer_id_get(). If the first_peer_id + * is @ref PM_PEER_ID_INVALID, the function starts searching from the first ID. + * The function looks for the ID's number specified by @p p_list_size. Only those IDs that + * match @p skip_id are added to the list. The number of returned elements is determined + * by @p p_list_size. + * + * @warning The size of the @p p_peer_list buffer must be equal or greater than @p p_list_size. + * + * @param[out] p_peer_list Pointer to peer IDs list buffer. + * @param[in,out] p_list_size The amount of IDs to return / The number of returned IDs. + * @param[in] first_peer_id The first ID from which the search begins. IDs ordering + * is the same as for @ref pm_next_peer_id_get() + * @param[in] skip_id It determines which peer ID will be added to list. + * + * @retval NRF_SUCCESS If the ID list has been filled out. + * @retval NRF_ERROR_INVALID_PARAM If @p skip_id was invalid. + * @retval NRF_ERROR_NULL If peer_list or list_size was NULL. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_peer_id_list(pm_peer_id_t * p_peer_list, + uint32_t * const p_list_size, + pm_peer_id_t first_peer_id, + pm_peer_id_list_skip_t skip_id); + + +/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. + * + * @details This function can be used to loop through all used peer IDs. The order in which + * peer IDs are returned should be considered unpredictable. @ref PM_PEER_ID_INVALID + * is considered to be before the first and after the last used peer ID. + * + * @details To loop through all peer IDs exactly once, use the following constuct: + * @code{c} + * pm_peer_id_t current_peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); + * while (current_peer_id != PM_PEER_ID_INVALID) + * { + * // Do something with current_peer_id. + * current_peer_id = pm_next_peer_id_get(current_peer_id) + * } + * @endcode + * + * @note This function does not report peer IDs that are pending deletion. + * + * @param[in] prev_peer_id The previous peer ID. + * + * @return The next peer ID. If @p prev_peer_id was @ref PM_PEER_ID_INVALID, the + * next peer ID is the first used peer ID. If @p prev_peer_id was the last + * used peer ID, the function returns @ref PM_PEER_ID_INVALID. + */ +pm_peer_id_t pm_next_peer_id_get(pm_peer_id_t prev_peer_id); + + +/**@brief Function for querying the number of valid peer IDs that are available. + * + * @details This function returns the number of peers for which there is data in persistent storage. + * + * @return The number of valid peer IDs. + */ +uint32_t pm_peer_count(void); + + + + +/**@anchor PM_PEER_DATA_FUNCTIONS + * @name Functions (Peer Data) + * Functions for manipulating peer data. + * @{ + */ + +/** + * @{ + */ + +/**@brief Function for retrieving stored data of a peer. + * + * @note The length of the provided buffer must be a multiple of 4. + * + * @param[in] peer_id Peer ID to get data for. + * @param[in] data_id Which type of data to read. + * @param[out] p_data Where to put the retrieved data. The documentation for + * @ref pm_peer_data_id_t specifies what data type each data ID is stored as. + * @param[in,out] p_len In: The length in bytes of @p p_data. + * Out: The length in bytes of the read data, if the read was successful. + * + * @retval NRF_SUCCESS If the data was read successfully. + * @retval NRF_ERROR_INVALID_PARAM If the data type or the peer ID was invalid or unallocated. + * @retval NRF_ERROR_NULL If a pointer parameter was NULL. + * @retval NRF_ERROR_NOT_FOUND If no stored data was found for this peer ID/data ID combination. + * @retval NRF_ERROR_DATA_SIZE If the provided buffer was not large enough. The data is still + * copied, filling the provided buffer. Note that this error can + * occur even if loading the same size as was stored, because the + * underlying layers round the length up to the nearest word (4 bytes) + * when storing. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_peer_data_load(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + void * p_data, + uint32_t * p_len); + +/**@brief Function for reading a peer's bonding data (@ref PM_PEER_DATA_ID_BONDING). + * @details See @ref pm_peer_data_load for parameters and return values. */ +ret_code_t pm_peer_data_bonding_load(pm_peer_id_t peer_id, + pm_peer_data_bonding_t * p_data); + +/**@brief Function for reading a peer's remote DB values. (@ref PM_PEER_DATA_ID_GATT_REMOTE). + * @details See @ref pm_peer_data_load for parameters and return values. */ +ret_code_t pm_peer_data_remote_db_load(pm_peer_id_t peer_id, + ble_gatt_db_srv_t * p_data, + uint32_t * p_len); + +/**@brief Function for reading a peer's application data. (@ref PM_PEER_DATA_ID_APPLICATION). + * @details See @ref pm_peer_data_load for parameters and return values. */ +ret_code_t pm_peer_data_app_data_load(pm_peer_id_t peer_id, + void * p_data, + uint32_t * p_len); +/** @}*/ + + +/** + * @{ + */ + +/**@brief Function for setting or updating stored data of a peer. + * + * @note Writing the data to persistent storage happens asynchronously. Therefore, the buffer + * that contains the data must be kept alive until the operation has completed. + * + * @note The data written using this function might later be overwritten as a result of internal + * operations in the Peer Manager. A Peer Manager event is sent each time data is updated, + * regardless of whether the operation originated internally or from action by the user. + * Data with @p data_id @ref PM_PEER_DATA_ID_GATT_REMOTE @ref PM_PEER_DATA_ID_APPLICATION is + * never (over)written internally. + * + * @param[in] peer_id Peer ID to set data for. + * @param[in] data_id Which type of data to set. + * @param[in] p_data New value to set. The documentation for @ref pm_peer_data_id_t specifies + * what data type each data ID should be stored as. + * @param[in] len The length in bytes of @p p_data. + * @param[out] p_token A token that identifies this particular store operation. The token can be + * used to identify events that pertain to this operation. This parameter can + * be NULL. + * + * @retval NRF_SUCCESS If the data is scheduled to be written to persistent storage. + * @retval NRF_ERROR_NULL If @p p_data is NULL. + * @retval NRF_ERROR_NOT_FOUND If no peer was found for the peer ID. + * @retval NRF_ERROR_INVALID_ADDR If @p p_data is not word-aligned (4 bytes). + * @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash + * operations. Try again after receiving a Peer Manager event. + * @retval NRF_ERROR_STORAGE_FULL If there is not enough space in persistent storage. + * @retval NRF_ERROR_FORBIDDEN If data ID is @ref PM_PEER_DATA_ID_BONDING and the new bonding + * data also corresponds to another bonded peer. No data is written + * so duplicate entries are avoided. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_peer_data_store(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + void const * p_data, + uint32_t len, + pm_store_token_t * p_token); + +/**@brief Function for setting or updating a peer's bonding data (@ref PM_PEER_DATA_ID_BONDING). + * @details See @ref pm_peer_data_store for parameters and return values. */ +ret_code_t pm_peer_data_bonding_store(pm_peer_id_t peer_id, + pm_peer_data_bonding_t const * p_data, + pm_store_token_t * p_token); + +/**@brief Function for setting or updating a peer's remote DB values. (@ref PM_PEER_DATA_ID_GATT_REMOTE). + * @details See @ref pm_peer_data_store for parameters and return values. */ +ret_code_t pm_peer_data_remote_db_store(pm_peer_id_t peer_id, + ble_gatt_db_srv_t const * p_data, + uint32_t len, + pm_store_token_t * p_token); + +/**@brief Function for setting or updating a peer's application data. (@ref PM_PEER_DATA_ID_APPLICATION). + * @details See @ref pm_peer_data_store for parameters and return values. */ +ret_code_t pm_peer_data_app_data_store(pm_peer_id_t peer_id, + void const * p_data, + uint32_t len, + pm_store_token_t * p_token); +/** @}*/ + + +/** + * @{ + */ + +/**@brief Function for deleting a peer's stored pieces of data. + * + * @details This function deletes specific data that is stored for a peer. Note that bonding data + * cannot be cleared separately. + * + * To delete all data for a peer (including bonding data), use @ref pm_peer_delete. + * + * @note Clearing data in persistent storage happens asynchronously. + * + * @param[in] peer_id Peer ID to clear data for. + * @param[in] data_id Which data to clear. + * + * @retval NRF_SUCCESS If the clear procedure was initiated successfully. + * @retval NRF_ERROR_INVALID_PARAM If @p data_id was PM_PEER_DATA_ID_BONDING or invalid, or + * @p peer_id was invalid. + * @retval NRF_ERROR_NOT_FOUND If there was no data to clear for this peer ID/data ID combination. + * @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash + * operations. Try again after receiving a Peer Manager event. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); + + +/**@brief Function for manually adding a peer to the persistent storage. + * + * @details This function allocates a new peer ID and stores bonding data for the new peer. The + * bonding data is necessary to prevent ambiguity/inconsistency in peer data. + * + * @param[in] p_bonding_data The bonding data of the new peer (must contain a public/static + * address or a non-zero IRK). + * @param[out] p_new_peer_id Peer ID for the new peer, or an existing peer if a match was found. + * @param[out] p_token A token that identifies this particular store operation (storing the + * bonding data). The token can be used to identify events that pertain + * to this operation. This parameter can be NULL. + * + * @retval NRF_SUCCESS If the store operation for bonding data was initiated successfully. + * @retval NRF_ERROR_NULL If @p p_bonding_data or @p p_new_peer_id is NULL. + * @retval NRF_ERROR_INVALID_ADDR If @p p_bonding_data is not word-aligned (4 bytes). + * @retval NRF_ERROR_STORAGE_FULL If there is not enough space in persistent storage. + * @retval NRF_ERROR_NO_MEM If there are no more available peer IDs. + * @retval NRF_ERROR_BUSY If the underlying flash filesystem is busy with other flash + * operations. Try again after receiving a Peer Manager event. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_peer_new(pm_peer_id_t * p_new_peer_id, + pm_peer_data_bonding_t * p_bonding_data, + pm_store_token_t * p_token); + + +/**@brief Function for freeing persistent storage for a peer. + * + * @details This function deletes every piece of data that is associated with the specified peer and + * frees the peer ID to be used for another peer. The deletion happens asynchronously, and + * the peer ID is not freed until the data is deleted. When the operation finishes, a @ref + * PM_EVT_PEER_DELETE_SUCCEEDED or @ref PM_EVT_PEER_DELETE_FAILED event is sent. + * + * @warning Use this function only when not connected to or connectable for the peer that is being + * deleted. If the peer is or becomes connected or data is manually written in flash during + * this procedure (until the success or failure event happens), the behavior is undefined. + * + * @param[in] peer_id Peer ID to be freed and have all associated data deleted. + * + * @retval NRF_SUCCESS If the operation was initiated successfully. + * @retval NRF_ERROR_INVALID_PARAM If the peer ID was not valid. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_peer_delete(pm_peer_id_t peer_id); + + +/**@brief Function for deleting all data stored for all peers. + * + * @details This function sends either a @ref PM_EVT_PEERS_DELETE_SUCCEEDED or a @ref + * PM_EVT_PEERS_DELETE_FAILED event. In addition, a @ref PM_EVT_PEER_DELETE_SUCCEEDED or + * @ref PM_EVT_PEER_DELETE_FAILED event is sent for each deleted peer. + * + * @note When there is no peer data in flash the @ref PM_EVT_PEER_DELETE_SUCCEEDED event is sent synchronously. + * + * @warning Use this function only when not connected or connectable. If a peer is or becomes + * connected or a @ref PM_PEER_DATA_FUNCTIONS function is used during this procedure (until + * the success or failure event happens), the behavior is undefined. + * + * @retval NRF_SUCCESS If the deletion process was initiated successfully. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_peers_delete(void); +/** @}*/ + + +/** + * @{ + */ + + +/**@brief Function for finding the highest and lowest ranked peers. + * + * @details The rank is saved in persistent storage under the data ID @ref PM_PEER_DATA_ID_PEER_RANK. + * + * @details The interpretation of rank is up to the user, because the rank is only updated by + * calling @ref pm_peer_rank_highest or by manipulating the value using a @ref + * PM_PEER_DATA_FUNCTIONS function. + * + * @note Peers with no stored rank are not considered. + * @note Any argument that is NULL is ignored. + * + * @param[out] p_highest_ranked_peer The peer ID with the highest rank of all peers, for example, + * the most recently used peer. + * @param[out] p_highest_rank The highest rank. + * @param[out] p_lowest_ranked_peer The peer ID with the lowest rank of all peers, for example, + * the least recently used peer. + * @param[out] p_lowest_rank The lowest rank. + * + * @retval NRF_SUCCESS If the operation completed successfully. + * @retval NRF_ERROR_NOT_FOUND If no peer with stored peer rank was found. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + * @retval NRF_ERROR_NOT_SUPPORTED If peer rank functionality has been disabled via the @ref + * PM_PEER_RANKS_ENABLED configuration option. + */ +ret_code_t pm_peer_ranks_get(pm_peer_id_t * p_highest_ranked_peer, + uint32_t * p_highest_rank, + pm_peer_id_t * p_lowest_ranked_peer, + uint32_t * p_lowest_rank); + + +/**@brief Function for updating the rank of a peer to be highest among all stored peers. + * + * @details If this function returns @ref NRF_SUCCESS, either a @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED or a + * @ref PM_EVT_PEER_DATA_UPDATE_FAILED event is sent with a @ref + * PM_STORE_TOKEN_INVALID store token when the operation is complete. Until the operation + * is complete, this function returns @ref NRF_ERROR_BUSY. + * + * When the operation is complete, the peer is the highest ranked peer as reported by + * @ref pm_peer_ranks_get. + * + * @note The @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event can arrive before the function returns if the peer + * is already ranked highest. In this case, the @ref pm_peer_data_update_succeeded_evt_t::flash_changed flag + * in the event will be false. + * + * @param[in] peer_id The peer to rank highest. + * + * @retval NRF_SUCCESS If the peer's rank is, or will be updated to be highest. + * @retval NRF_ERROR_INVALID_PARAM If @p peer_id is invalid, or doesn't exist in flash. + * @retval NRF_ERROR_STORAGE_FULL If there is not enough space in persistent storage. + * @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash + * operations, or if a previous call to this function has not + * completed. Try again after receiving a Peer Manager event. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_RESOURCES If the highest rank is UINT32_MAX, so the new rank would wrap + * around to 0. To fix this, manually update all ranks to smaller + * values, while still keeping their order. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + * @retval NRF_ERROR_NOT_SUPPORTED If peer rank functionality has been disabled via the @ref + * PM_PEER_RANKS_ENABLED configuration option. + */ +ret_code_t pm_peer_rank_highest(pm_peer_id_t peer_id); + +/** @}*/ + +/** @} */ + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif // PEER_MANAGER_H__ diff --git a/components/ble/peer_manager/peer_manager_handler.c b/components/ble/peer_manager/peer_manager_handler.c new file mode 100644 index 0000000..849e6a0 --- /dev/null +++ b/components/ble/peer_manager/peer_manager_handler.c @@ -0,0 +1,691 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "peer_manager_handler.h" +#include +#include +#include "sdk_errors.h" +#include "app_error.h" +#include "peer_manager.h" +#include "ble_gap.h" +#include "ble_gattc.h" +#include "ble_conn_state.h" +#include "fds.h" +#include "nrf_strerror.h" +#include "sdk_config.h" + +#if PM_HANDLER_SEC_DELAY_MS > 0 +#include "app_timer.h" +#endif + +#define NRF_LOG_MODULE_NAME peer_manager_handler +#if PM_LOG_ENABLED + #define NRF_LOG_LEVEL PM_LOG_LEVEL + #define NRF_LOG_INFO_COLOR PM_LOG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR PM_LOG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // PM_LOG_ENABLED +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +NRF_LOG_MODULE_REGISTER(); +#include "nrf_strerror.h" + +static const char * m_roles_str[] = +{ + "Invalid Role", + "Peripheral", + "Central", +}; + +static const char * m_sec_procedure_str[] = +{ + "Encryption", + "Bonding", + "Pairing", +}; + +#define PM_EVT_STR(_name) [_name] = STRINGIFY(_name) + +static const char * m_event_str[] = +{ + PM_EVT_STR(PM_EVT_BONDED_PEER_CONNECTED), + PM_EVT_STR(PM_EVT_CONN_CONFIG_REQ), + PM_EVT_STR(PM_EVT_CONN_SEC_START), + PM_EVT_STR(PM_EVT_CONN_SEC_SUCCEEDED), + PM_EVT_STR(PM_EVT_CONN_SEC_FAILED), + PM_EVT_STR(PM_EVT_CONN_SEC_CONFIG_REQ), + PM_EVT_STR(PM_EVT_CONN_SEC_PARAMS_REQ), + PM_EVT_STR(PM_EVT_STORAGE_FULL), + PM_EVT_STR(PM_EVT_ERROR_UNEXPECTED), + PM_EVT_STR(PM_EVT_PEER_DATA_UPDATE_SUCCEEDED), + PM_EVT_STR(PM_EVT_PEER_DATA_UPDATE_FAILED), + PM_EVT_STR(PM_EVT_PEER_DELETE_SUCCEEDED), + PM_EVT_STR(PM_EVT_PEER_DELETE_FAILED), + PM_EVT_STR(PM_EVT_PEERS_DELETE_SUCCEEDED), + PM_EVT_STR(PM_EVT_PEERS_DELETE_FAILED), + PM_EVT_STR(PM_EVT_LOCAL_DB_CACHE_APPLIED), + PM_EVT_STR(PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED), + PM_EVT_STR(PM_EVT_SERVICE_CHANGED_IND_SENT), + PM_EVT_STR(PM_EVT_SERVICE_CHANGED_IND_CONFIRMED), + PM_EVT_STR(PM_EVT_SLAVE_SECURITY_REQ), + PM_EVT_STR(PM_EVT_FLASH_GARBAGE_COLLECTED), + PM_EVT_STR(PM_EVT_FLASH_GARBAGE_COLLECTION_FAILED), +}; + +static const char * m_data_id_str[] = +{ + "Outdated (0)", + "Service changed pending flag", + "Outdated (2)", + "Outdated (3)", + "Application data", + "Remote database", + "Peer rank", + "Bonding data", + "Local database", + "Central address resolution", +}; + +static const char * m_data_action_str[] = +{ + "Update", + "Delete" +}; + +#define PM_SEC_ERR_STR(_name) {.error = _name, .error_str = #_name} + +typedef struct +{ + pm_sec_error_code_t error; + const char * error_str; +} sec_err_str_t; + +static const sec_err_str_t m_pm_sec_error_str[] = +{ + PM_SEC_ERR_STR(PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING), + PM_SEC_ERR_STR(PM_CONN_SEC_ERROR_MIC_FAILURE), + PM_SEC_ERR_STR(PM_CONN_SEC_ERROR_DISCONNECT), + PM_SEC_ERR_STR(PM_CONN_SEC_ERROR_SMP_TIMEOUT), +}; + +static const char * sec_err_string_get(pm_sec_error_code_t error) +{ + static char errstr[30]; + + for (uint32_t i = 0; i < (sizeof(m_pm_sec_error_str)/sizeof(sec_err_str_t)); i++) + { + if (m_pm_sec_error_str[i].error == error) + { + return m_pm_sec_error_str[i].error_str; + } + } + + int len = snprintf(errstr, sizeof(errstr), "%s 0x%hx", (error < PM_CONN_SEC_ERROR_BASE) + ? "BLE_GAP_SEC_STATUS" + :"PM_CONN_SEC_ERROR", error); + UNUSED_VARIABLE(len); + return errstr; +} + + +static void _conn_secure(uint16_t conn_handle, bool force) +{ + ret_code_t err_code; + + if (!force) + { + pm_conn_sec_status_t status; + err_code = pm_conn_sec_status_get(conn_handle, &status); + if (err_code != BLE_ERROR_INVALID_CONN_HANDLE) + { + APP_ERROR_CHECK(err_code); + } + + // If the link is already secured, don't initiate security procedure. + if (status.encrypted) + { + NRF_LOG_DEBUG("Already encrypted, skipping security."); + return; + } + } + + err_code = pm_conn_secure(conn_handle, false); + + if ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_BUSY)) + { + // Success. + } + else if (err_code == NRF_ERROR_TIMEOUT) + { + NRF_LOG_WARNING("pm_conn_secure() failed because an SMP timeout is preventing security on "\ + "the link. Disconnecting conn_handle %d.", + conn_handle); + + err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_WARNING("sd_ble_gap_disconnect() returned %s on conn_handle %d.", + nrf_strerror_get(err_code), + conn_handle); + } + } + else if (err_code == NRF_ERROR_INVALID_DATA) + { + NRF_LOG_WARNING("pm_conn_secure() failed because the stored data for conn_handle %d does "\ + "not have a valid key.", + conn_handle); + } + else if (err_code == BLE_ERROR_INVALID_CONN_HANDLE) + { + NRF_LOG_WARNING("pm_conn_secure() failed because conn_handle %d is not a valid connection.", + conn_handle); + } + else + { + NRF_LOG_ERROR("Asserting. pm_conn_secure() returned %s on conn_handle %d.", + nrf_strerror_get(err_code), + conn_handle); + APP_ERROR_CHECK(err_code); + } +} + +#if PM_HANDLER_SEC_DELAY_MS > 0 +APP_TIMER_DEF(secure_delay_timer); + +typedef union +{ + struct + { + uint16_t conn_handle; + bool force; + } values; + void * p_void; +} conn_secure_context_t; + +STATIC_ASSERT(sizeof(conn_secure_context_t) <= sizeof(void *), "conn_secure_context_t is too large."); + +static void _conn_secure(uint16_t conn_handle, bool force); + +static void delayed_conn_secure(void * context) +{ + conn_secure_context_t sec_context = {.p_void = context}; + _conn_secure(sec_context.values.conn_handle, sec_context.values.force); +} + +static void conn_secure(uint16_t conn_handle, bool force) +{ + ret_code_t err_code; + static bool created = false; + if (!created) + { + err_code = app_timer_create(&secure_delay_timer, + APP_TIMER_MODE_SINGLE_SHOT, + delayed_conn_secure); + APP_ERROR_CHECK(err_code); + created = true; + } + + conn_secure_context_t sec_context = {0}; + sec_context.values.conn_handle = conn_handle; + sec_context.values.force = force; + + err_code = app_timer_start(secure_delay_timer, + APP_TIMER_TICKS(PM_HANDLER_SEC_DELAY_MS), + sec_context.p_void); + APP_ERROR_CHECK(err_code); +} + + +#else +static void conn_secure(uint16_t conn_handle, bool force) +{ + _conn_secure(conn_handle, force); +} +#endif + + +void pm_handler_on_pm_evt(pm_evt_t const * p_pm_evt) +{ + pm_handler_pm_evt_log(p_pm_evt); + + if (p_pm_evt->evt_id == PM_EVT_BONDED_PEER_CONNECTED) + { + conn_secure(p_pm_evt->conn_handle, false); + } + else if (p_pm_evt->evt_id == PM_EVT_ERROR_UNEXPECTED) + { + NRF_LOG_ERROR("Asserting."); + APP_ERROR_CHECK(p_pm_evt->params.error_unexpected.error); + } +} + + +void pm_handler_flash_clean_on_return(void) +{ + // Trigger the mechanism to make more room in flash. + pm_evt_t storage_full_evt = {.evt_id = PM_EVT_STORAGE_FULL}; + pm_handler_flash_clean(&storage_full_evt); +} + + +static void rank_highest(pm_peer_id_t peer_id) +{ + // Trigger a pm_peer_rank_highest() with internal bookkeeping. + pm_evt_t connected_evt = {.evt_id = PM_EVT_BONDED_PEER_CONNECTED, .peer_id = peer_id}; + pm_handler_flash_clean(&connected_evt); +} + + +void pm_handler_flash_clean(pm_evt_t const * p_pm_evt) +{ + ret_code_t err_code; + static bool flash_cleaning = false; // Indicates whether garbage collection is currently being run. + static bool flash_write_after_gc = true; // Indicates whether a successful write happened after the last garbage + // collection. If this is false when flash is full, it means just a + // garbage collection won't work, so some data should be deleted. + #define RANK_QUEUE_SIZE 8 // Size of rank_queue. + #define RANK_QUEUE_INIT() PM_PEER_ID_INVALID, // Initial value of rank_queue. + + //lint -save -e40 -e26 -esym(628,MACRO_REPEAT_8) + static pm_peer_id_t rank_queue[8] = {MACRO_REPEAT(RANK_QUEUE_SIZE, RANK_QUEUE_INIT)}; // Queue of rank_highest calls that + // failed because of full flash. + //lint -restore + static int rank_queue_wr = 0; // Write pointer for rank_queue. + + switch (p_pm_evt->evt_id) + { + case PM_EVT_BONDED_PEER_CONNECTED: + err_code = pm_peer_rank_highest(p_pm_evt->peer_id); + if ((err_code == NRF_ERROR_STORAGE_FULL) || + (err_code == NRF_ERROR_BUSY)) + { + // Queue pm_peer_rank_highest() call and attempt to clean flash. + rank_queue[rank_queue_wr] = p_pm_evt->peer_id; + rank_queue_wr = (rank_queue_wr + 1) % RANK_QUEUE_SIZE; + pm_handler_flash_clean_on_return(); + } + else if ((err_code != NRF_ERROR_NOT_SUPPORTED) && + (err_code != NRF_ERROR_INVALID_PARAM) && + (err_code != NRF_ERROR_RESOURCES)) + { + APP_ERROR_CHECK(err_code); + } + else + { + NRF_LOG_DEBUG("pm_peer_rank_highest() returned %s for peer id %d", + nrf_strerror_get(err_code), + p_pm_evt->peer_id); + } + break; + + case PM_EVT_CONN_SEC_START: + break; + + case PM_EVT_CONN_SEC_SUCCEEDED: + if ( (p_pm_evt->params.conn_sec_succeeded.procedure == PM_CONN_SEC_PROCEDURE_BONDING) + || (p_pm_evt->params.conn_sec_succeeded.procedure == PM_CONN_SEC_PROCEDURE_ENCRYPTION)) + // PM_CONN_SEC_PROCEDURE_ENCRYPTION in case peer was not recognized at connection time. + { + rank_highest(p_pm_evt->peer_id); + } + break; + + case PM_EVT_CONN_SEC_FAILED: + case PM_EVT_CONN_SEC_CONFIG_REQ: + case PM_EVT_CONN_SEC_PARAMS_REQ: + break; + + case PM_EVT_STORAGE_FULL: + if (!flash_cleaning) + { + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Attempting to clean flash."); + if (!flash_write_after_gc) + { + // Check whether another user of FDS has deleted a record that can be GCed. + fds_stat_t fds_stats; + err_code = fds_stat(&fds_stats); + APP_ERROR_CHECK(err_code); + flash_write_after_gc = (fds_stats.dirty_records > 0); + } + if (!flash_write_after_gc) + { + pm_peer_id_t peer_id_to_delete; + err_code = pm_peer_ranks_get(NULL, NULL, &peer_id_to_delete, NULL); + if (err_code == NRF_SUCCESS) + { + NRF_LOG_INFO("Deleting lowest ranked peer (peer_id: %d)", peer_id_to_delete); + err_code = pm_peer_delete(peer_id_to_delete); + APP_ERROR_CHECK(err_code); + flash_write_after_gc = true; + } + if (err_code == NRF_ERROR_NOT_FOUND) + { + NRF_LOG_ERROR("There are no peers to delete."); + } + else if (err_code == NRF_ERROR_NOT_SUPPORTED) + { + NRF_LOG_WARNING("Peer ranks functionality is disabled, so no peers are deleted."); + } + else + { + APP_ERROR_CHECK(err_code); + } + } + if (err_code == NRF_SUCCESS) + { + err_code = fds_gc(); + if (err_code == NRF_SUCCESS) + { + NRF_LOG_DEBUG("Running flash garbage collection."); + flash_cleaning = true; + } + else if (err_code != FDS_ERR_NO_SPACE_IN_QUEUES) + { + APP_ERROR_CHECK(err_code); + } + } + } + break; + + case PM_EVT_ERROR_UNEXPECTED: + break; + + case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: + flash_write_after_gc = true; + break; + + case PM_EVT_PEER_DATA_UPDATE_FAILED: + break; + + case PM_EVT_PEER_DELETE_SUCCEEDED: + flash_write_after_gc = true; + break; + + case PM_EVT_PEER_DELETE_FAILED: + case PM_EVT_PEERS_DELETE_SUCCEEDED: + case PM_EVT_PEERS_DELETE_FAILED: + case PM_EVT_LOCAL_DB_CACHE_APPLIED: + case PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED: + case PM_EVT_SERVICE_CHANGED_IND_SENT: + case PM_EVT_SERVICE_CHANGED_IND_CONFIRMED: + case PM_EVT_SLAVE_SECURITY_REQ: + break; + + case PM_EVT_FLASH_GARBAGE_COLLECTED: + flash_cleaning = false; + flash_write_after_gc = false; + { + // Reattempt queued pm_peer_rank_highest() calls. + int rank_queue_rd = rank_queue_wr; + for (int i = 0; i < RANK_QUEUE_SIZE; i++) + { + pm_peer_id_t peer_id = rank_queue[(i + rank_queue_rd) % RANK_QUEUE_SIZE]; + if (peer_id != PM_PEER_ID_INVALID) + { + rank_queue[(i + rank_queue_rd) % RANK_QUEUE_SIZE] = PM_PEER_ID_INVALID; + rank_highest(peer_id); + } + } + } + break; + + case PM_EVT_FLASH_GARBAGE_COLLECTION_FAILED: + flash_cleaning = false; + + if (p_pm_evt->params.garbage_collection_failed.error == FDS_ERR_BUSY + || p_pm_evt->params.garbage_collection_failed.error == FDS_ERR_OPERATION_TIMEOUT) + { + // Retry immediately if error is transient. + pm_handler_flash_clean_on_return(); + } + break; + + default: + break; + } +} + + +void pm_handler_pm_evt_log(pm_evt_t const * p_pm_evt) +{ + NRF_LOG_DEBUG("Event %s", m_event_str[p_pm_evt->evt_id]); + + switch (p_pm_evt->evt_id) + { + case PM_EVT_BONDED_PEER_CONNECTED: + NRF_LOG_DEBUG("Previously bonded peer connected: role: %s, conn_handle: %d, peer_id: %d", + m_roles_str[ble_conn_state_role(p_pm_evt->conn_handle)], + p_pm_evt->conn_handle, + p_pm_evt->peer_id); + break; + + case PM_EVT_CONN_CONFIG_REQ: + NRF_LOG_DEBUG("Connection configuration request"); + break; + + case PM_EVT_CONN_SEC_START: + NRF_LOG_DEBUG("Connection security procedure started: role: %s, conn_handle: %d, procedure: %s", + m_roles_str[ble_conn_state_role(p_pm_evt->conn_handle)], + p_pm_evt->conn_handle, + m_sec_procedure_str[p_pm_evt->params.conn_sec_start.procedure]); + break; + + case PM_EVT_CONN_SEC_SUCCEEDED: + NRF_LOG_INFO("Connection secured: role: %s, conn_handle: %d, procedure: %s", + m_roles_str[ble_conn_state_role(p_pm_evt->conn_handle)], + p_pm_evt->conn_handle, + m_sec_procedure_str[p_pm_evt->params.conn_sec_start.procedure]); + break; + + case PM_EVT_CONN_SEC_FAILED: + NRF_LOG_INFO("Connection security failed: role: %s, conn_handle: 0x%x, procedure: %s, error: %d", + m_roles_str[ble_conn_state_role(p_pm_evt->conn_handle)], + p_pm_evt->conn_handle, + m_sec_procedure_str[p_pm_evt->params.conn_sec_start.procedure], + p_pm_evt->params.conn_sec_failed.error); + NRF_LOG_DEBUG("Error (decoded): %s", + sec_err_string_get(p_pm_evt->params.conn_sec_failed.error)); + break; + + case PM_EVT_CONN_SEC_CONFIG_REQ: + NRF_LOG_DEBUG("Security configuration request"); + break; + + case PM_EVT_CONN_SEC_PARAMS_REQ: + NRF_LOG_DEBUG("Security parameter request"); + break; + + case PM_EVT_STORAGE_FULL: + NRF_LOG_WARNING("Flash storage is full"); + break; + + case PM_EVT_ERROR_UNEXPECTED: + NRF_LOG_ERROR("Unexpected fatal error occurred: error: %s", + nrf_strerror_get(p_pm_evt->params.error_unexpected.error)); + break; + + case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: + NRF_LOG_INFO("Peer data updated in flash: peer_id: %d, data_id: %s, action: %s%s", + p_pm_evt->peer_id, + m_data_id_str[p_pm_evt->params.peer_data_update_succeeded.data_id], + m_data_action_str[p_pm_evt->params.peer_data_update_succeeded.action], + p_pm_evt->params.peer_data_update_succeeded.flash_changed ? "" : ", no change"); + break; + + case PM_EVT_PEER_DATA_UPDATE_FAILED: + // This can happen if the SoftDevice is too busy with BLE operations. + NRF_LOG_WARNING("Peer data updated failed: peer_id: %d, data_id: %s, action: %s, error: %s", + p_pm_evt->peer_id, + m_data_id_str[p_pm_evt->params.peer_data_update_failed.data_id], + m_data_action_str[p_pm_evt->params.peer_data_update_succeeded.action], + nrf_strerror_get(p_pm_evt->params.peer_data_update_failed.error)); + break; + + case PM_EVT_PEER_DELETE_SUCCEEDED: + NRF_LOG_ERROR("Peer deleted successfully: peer_id: %d", p_pm_evt->peer_id); + break; + + case PM_EVT_PEER_DELETE_FAILED: + NRF_LOG_ERROR("Peer deletion failed: peer_id: %d, error: %s", + p_pm_evt->peer_id, + nrf_strerror_get(p_pm_evt->params.peer_delete_failed.error)); + break; + + case PM_EVT_PEERS_DELETE_SUCCEEDED: + NRF_LOG_INFO("All peers deleted."); + break; + + case PM_EVT_PEERS_DELETE_FAILED: + NRF_LOG_ERROR("All peer deletion failed: error: %s", + nrf_strerror_get(p_pm_evt->params.peers_delete_failed_evt.error)); + break; + + case PM_EVT_LOCAL_DB_CACHE_APPLIED: + NRF_LOG_DEBUG("Previously stored local DB applied: conn_handle: %d, peer_id: %d", + p_pm_evt->conn_handle, + p_pm_evt->peer_id); + break; + + case PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED: + // This can happen when the local DB has changed. + NRF_LOG_WARNING("Local DB could not be applied: conn_handle: %d, peer_id: %d", + p_pm_evt->conn_handle, + p_pm_evt->peer_id); + break; + + case PM_EVT_SERVICE_CHANGED_IND_SENT: + NRF_LOG_DEBUG("Sending Service Changed indication."); + break; + + case PM_EVT_SERVICE_CHANGED_IND_CONFIRMED: + NRF_LOG_DEBUG("Service Changed indication confirmed."); + break; + + case PM_EVT_SLAVE_SECURITY_REQ: + NRF_LOG_DEBUG("Security Request received from peer."); + break; + + case PM_EVT_FLASH_GARBAGE_COLLECTED: + NRF_LOG_DEBUG("Flash garbage collection complete."); + break; + + case PM_EVT_FLASH_GARBAGE_COLLECTION_FAILED: + NRF_LOG_WARNING("Flash garbage collection failed with error %s.", + nrf_strerror_get(p_pm_evt->params.garbage_collection_failed.error)); + break; + + default: + NRF_LOG_WARNING("Unexpected PM event ID: 0x%x.", p_pm_evt->evt_id); + break; + } +} + + +void pm_handler_disconnect_on_sec_failure(pm_evt_t const * p_pm_evt) +{ + ret_code_t err_code; + + if (p_pm_evt->evt_id == PM_EVT_CONN_SEC_FAILED) + { + NRF_LOG_WARNING("Disconnecting conn_handle %d.", p_pm_evt->conn_handle); + err_code = sd_ble_gap_disconnect(p_pm_evt->conn_handle, + BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + if ((err_code != NRF_ERROR_INVALID_STATE) && (err_code != BLE_ERROR_INVALID_CONN_HANDLE)) + { + APP_ERROR_CHECK(err_code); + } + } +} + + +void pm_handler_disconnect_on_insufficient_sec(pm_evt_t const * p_pm_evt, + pm_conn_sec_status_t * p_min_conn_sec) +{ + if (p_pm_evt->evt_id == PM_EVT_CONN_SEC_SUCCEEDED) + { + if (!pm_sec_is_sufficient(p_pm_evt->conn_handle, p_min_conn_sec)) + { + NRF_LOG_WARNING("Connection security is insufficient, disconnecting."); + ret_code_t err_code = sd_ble_gap_disconnect(p_pm_evt->conn_handle, + BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + APP_ERROR_CHECK(err_code); + } + } +} + + +void pm_handler_secure_on_connection(ble_evt_t const * p_ble_evt) +{ + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + NRF_LOG_DEBUG("Connected, securing connection. conn_handle: %d", p_ble_evt->evt.gap_evt.conn_handle); + conn_secure(p_ble_evt->evt.gap_evt.conn_handle, false); + break; + +#if PM_HANDLER_SEC_DELAY_MS > 0 + case BLE_GAP_EVT_DISCONNECTED: + { + ret_code_t err_code = app_timer_stop(secure_delay_timer); + APP_ERROR_CHECK(err_code); + } break; +#endif + + default: + break; + } +} + + +void pm_handler_secure_on_error(ble_evt_t const * p_ble_evt) +{ + if ((p_ble_evt->header.evt_id >= BLE_GATTC_EVT_BASE) && (p_ble_evt->header.evt_id <= BLE_GATTC_EVT_LAST)) + { + if ((p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_INSUF_ENCRYPTION) || + (p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_INSUF_AUTHENTICATION)) + { + NRF_LOG_INFO("GATTC procedure (evt id 0x%x) failed because it needs encryption. Bonding: conn_handle=%d", + p_ble_evt->header.evt_id, + p_ble_evt->evt.gattc_evt.conn_handle); + conn_secure(p_ble_evt->evt.gattc_evt.conn_handle, true); + } + } +} diff --git a/components/ble/peer_manager/peer_manager_handler.h b/components/ble/peer_manager/peer_manager_handler.h new file mode 100644 index 0000000..4354e2a --- /dev/null +++ b/components/ble/peer_manager/peer_manager_handler.h @@ -0,0 +1,166 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * @file peer_manager_handler.h + * + * @defgroup pm_handler Peer Manager Standard Event Handlers + * @ingroup peer_manager + * @{ + * @brief Standard event handlers implementing some best practices for BLE security. + */ + + +#ifndef PEER_MANAGER_HANDLER_H__ +#define PEER_MANAGER_HANDLER_H__ + +#include "ble.h" +#include "peer_manager.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Standard function for making Peer Manager calls based on Peer Manager events. + * + * This function does the following: + * - Logs all PM events using @ref nrf_log, at different severity levels. + * - Starts encryption if connected to an already bonded peer. This is affected by @ref + * PM_HANDLER_SEC_DELAY_MS. + * - Calls @ref app_error on fatal errors. + * + * @note In normal circumstances, this function should be called for every Peer Manager event. + * + * @param[in] p_pm_evt Peer Manager event to handle. + */ +void pm_handler_on_pm_evt(pm_evt_t const * p_pm_evt); + +/**@brief Auxiliary standard function for logging Peer Manager events. + * + * This function logs all PM events using @ref nrf_log, at different severity levels. The + * @ref PM_LOG_ENABLED and other @c PM_LOG_* configs control these log messages. + * + * @note This function is called internally by @ref pm_handler_on_pm_evt. + * + * @param[in] p_pm_evt Peer Manager event to log. + */ +void pm_handler_pm_evt_log(pm_evt_t const * p_pm_evt); + +/**@brief Auxiliary standard function for maintaining room in flash based on Peer Manager events. + * + * This function does the following: + * - Ranks peers by when they last connected. + * - Garbage collects the flash when needed. + * - Deletes the lowest ranked peer(s) when garbage collection is insufficient. + * + * @note See also @ref pm_handler_flash_clean_on_return. + * @note In normal circumstances, this function should be called for every Peer Manager event. + * @note This function is a supplement to @ref pm_handler_on_pm_evt, not its replacement. + * + * @param[in] p_pm_evt Peer Manager event to handle. + */ +void pm_handler_flash_clean(pm_evt_t const * p_pm_evt); + +/**@brief Function to call when a Peer Manager function returns @ref NRF_ERROR_STORAGE_FULL. + * + * @note This should only be used if @ref pm_handler_flash_clean is also used. + */ +void pm_handler_flash_clean_on_return(void); + +/**@brief Auxiliary standard function for disconnecting when the connection could not be secured. + * + * This function disconnects whenever connection security fails, i.e. whenever it receives a + * @ref PM_EVT_CONN_SEC_FAILED. + * + * @note In normal circumstances, this function should be called for every Peer Manager event. + * @note This function is a supplement to @ref pm_handler_on_pm_evt, not its replacement. + * + * @param[in] p_pm_evt Peer Manager event to handle. + */ +void pm_handler_disconnect_on_sec_failure(pm_evt_t const * p_pm_evt); + +/**@brief Auxiliary standard function for disconnecting on insufficient connection security. + * + * This function disconnects whenever the connection security succeeds, that is whenever it + * receives a @ref PM_EVT_CONN_SEC_SUCCEEDED, but the established security does not fulfill the + * provided criteria. + * + * @note In normal circumstances, this function should be called for every Peer Manager event. + * @note This function is a supplement to @ref pm_handler_on_pm_evt, not its replacement. + * + * @param[in] p_pm_evt Peer Manager event to handle. + * @param[in] p_min_conn_sec Minumum security status below which to disconnect the link. + */ +void pm_handler_disconnect_on_insufficient_sec(pm_evt_t const * p_pm_evt, + pm_conn_sec_status_t * p_min_conn_sec); + +/**@brief Function for securing a connection when it is established. + * + * This function starts security when receiving a @ref BLE_GAP_EVT_CONNECTED event. This is + * affected by @ref PM_HANDLER_SEC_DELAY_MS. + * + * @note In normal circumstances, this function should be called for every BLE event. + * + * @param[in] p_ble_evt BLE event to handle. + */ +void pm_handler_secure_on_connection(ble_evt_t const * p_ble_evt); + +/**@brief Function for securing a connection if a GATT read or write operation lacks security. + * + * This function starts pairing if a GATTC procedure fails with insufficient encryption + * or insufficient authentication. This is meant to delay performing pairing/bonding until + * it is actually needed to access resources. This is affected by @ref PM_HANDLER_SEC_DELAY_MS. + * + * @note When using this handler, the failed GATTC operation must be retried by the user. + * @note This does not work when using Write Without Response (@ref BLE_GATT_OP_WRITE_CMD) because + * the server does not send any response, even on error. Instead, the write will be + * silently dropped by the server. + * @note In normal circumstances, this function should be called for every BLE event. + * + * @param[in] p_ble_evt BLE event to handle. + */ +void pm_handler_secure_on_error(ble_evt_t const * p_ble_evt); + +#ifdef __cplusplus +} +#endif + +/** @}*/ + +#endif // PEER_MANAGER_HANDLER_H__ diff --git a/components/ble/peer_manager/peer_manager_internal.h b/components/ble/peer_manager/peer_manager_internal.h new file mode 100644 index 0000000..8fde049 --- /dev/null +++ b/components/ble/peer_manager/peer_manager_internal.h @@ -0,0 +1,209 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef PEER_MANAGER_INTERNAL_H__ +#define PEER_MANAGER_INTERNAL_H__ + +#include +#include "sdk_errors.h" +#include "ble.h" +#include "ble_gap.h" +#include "peer_manager_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @file peer_manager_types.h + * + * @addtogroup peer_manager + * @brief File containing definitions used solely inside the Peer Manager's modules. + * @{ + */ + +ANON_UNIONS_ENABLE; + +/**@brief One piece of data associated with a peer, together with its type. + * + * @note This type is deprecated. + */ +typedef struct +{ + uint16_t length_words; /**< @brief The length of the data in words. */ + pm_peer_data_id_t data_id; /**< @brief ID that specifies the type of data (defines which member of the union is used). */ + union + { + pm_peer_data_bonding_t * p_bonding_data; /**< @brief The exchanged bond information in addition to metadata of the bonding. */ + uint32_t * p_peer_rank; /**< @brief A value locally assigned to this peer. Its interpretation is up to the user. The rank is not set automatically by the Peer Manager, but it is assigned by the user using either @ref pm_peer_rank_highest or a @ref PM_PEER_DATA_FUNCTIONS function. */ + uint32_t * p_central_addr_res; /**< @brief Value of peer's Central Address Resolution characteristic. */ + bool * p_service_changed_pending; /**< @brief Whether a service changed indication should be sent to the peer. */ + pm_peer_data_local_gatt_db_t * p_local_gatt_db; /**< @brief Persistent information pertaining to a peer GATT client. */ + ble_gatt_db_srv_t * p_remote_gatt_db; /**< @brief Persistent information pertaining to a peer GATT server. */ + uint8_t * p_application_data; /**< @brief Arbitrary data to associate with the peer. This data can be freely used by the application. */ + void * p_all_data; /**< @brief Generic access pointer to the data. It is used only to handle the data without regard to type. */ + }; /**< @brief The data. */ +} pm_peer_data_t; + + +/**@brief Immutable version of @ref pm_peer_data_t. + * + * @note This type is deprecated. + */ +typedef struct +{ + uint16_t length_words; /**< @brief The length of the data in words. */ + pm_peer_data_id_t data_id; /**< @brief ID that specifies the type of data (defines which member of the union is used). */ + union + { + pm_peer_data_bonding_t const * p_bonding_data; /**< @brief Immutable @ref pm_peer_data_t::p_bonding_data. */ + uint32_t const * p_peer_rank; /**< @brief Immutable @ref pm_peer_data_t::p_peer_rank. */ + uint32_t const * p_central_addr_res; /**< @brief Immutable @ref pm_peer_data_t::p_central_addr_res. */ + bool const * p_service_changed_pending; /**< @brief Immutable @ref pm_peer_data_t::p_service_changed_pending. */ + pm_peer_data_local_gatt_db_t const * p_local_gatt_db; /**< @brief Immutable @ref pm_peer_data_t::p_local_gatt_db. */ + ble_gatt_db_srv_t const * p_remote_gatt_db; /**< @brief Immutable @ref pm_peer_data_t::p_remote_gatt_db. */ + uint8_t const * p_application_data; /**< @brief Immutable @ref pm_peer_data_t::p_application_data. */ + void const * p_all_data; /**< @brief Immutable @ref pm_peer_data_t::p_all_data. */ + }; /**< @brief The data. */ +} pm_peer_data_const_t; + +ANON_UNIONS_DISABLE; + + +/**@brief Version of @ref pm_peer_data_t that reflects the structure of peer data in flash. + * + * @note This type is deprecated. + */ +typedef pm_peer_data_const_t pm_peer_data_flash_t; + + +/**@brief Event handler for events from the @ref peer_manager module. + * + * @sa pm_register + * + * @param[in] p_event The event that has occurred. + */ +typedef void (*pm_evt_handler_internal_t)(pm_evt_t * p_event); + + +/**@brief Macro for calculating the flash size of bonding data. + * + * @return The number of words that the data takes in flash. + */ +#define PM_BONDING_DATA_N_WORDS() BYTES_TO_WORDS(sizeof(pm_peer_data_bonding_t)) + + +/**@brief Macro for calculating the flash size of service changed pending state. + * + * @return The number of words that the data takes in flash. + */ +#define PM_SC_STATE_N_WORDS() BYTES_TO_WORDS(sizeof(bool)) + + +/**@brief Macro for calculating the flash size of local GATT database data. + * + * @param[in] local_db_len The length, in bytes, of the database as reported by the SoftDevice. + * + * @return The number of words that the data takes in flash. + */ +#define PM_LOCAL_DB_N_WORDS(local_db_len) \ + BYTES_TO_WORDS((local_db_len) + PM_LOCAL_DB_LEN_OVERHEAD_BYTES) + + +/**@brief Macro for calculating the length of a local GATT database attribute array. + * + * @param[in] n_words The number of words that the data takes in flash. + * + * @return The length of the database attribute array. + */ +#define PM_LOCAL_DB_LEN(n_words) (((n_words) * BYTES_PER_WORD) - PM_LOCAL_DB_LEN_OVERHEAD_BYTES) + + +/**@brief Macro for calculating the flash size of remote GATT database data. + * + * @param[in] service_count The number of services in the service array. + * + * @return The number of words that the data takes in flash. + */ +#define PM_REMOTE_DB_N_WORDS(service_count) BYTES_TO_WORDS(sizeof(ble_gatt_db_srv_t) * (service_count)) + + +/**@brief Macro for calculating the flash size of remote GATT database data. + * + * @param[in] n_words The length in number of words. + * + * @return The number of words that the data takes in flash. + */ +#define PM_REMOTE_DB_N_SERVICES(n_words) (((n_words) * BYTES_PER_WORD) / sizeof(ble_gatt_db_srv_t)) + + +/**@brief Function for calculating the flash size of the usage index. + * + * @return The number of words that the data takes in flash. + */ +#define PM_USAGE_INDEX_N_WORDS() BYTES_TO_WORDS(sizeof(uint32_t)) + +/** @} + * @endcond + */ + + +#ifdef NRF_PM_DEBUG + + #define NRF_PM_DEBUG_CHECK(condition) \ + if (!(condition)) \ + { \ + __asm("bkpt #0"); \ + } + +#else + + // Prevent "variable set but never used" compiler warnings. + #define NRF_PM_DEBUG_CHECK(condition) (void)(condition) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* PEER_MANAGER_INTERNAL_H__ */ diff --git a/components/ble/peer_manager/peer_manager_types.h b/components/ble/peer_manager/peer_manager_types.h new file mode 100644 index 0000000..88fae2b --- /dev/null +++ b/components/ble/peer_manager/peer_manager_types.h @@ -0,0 +1,369 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * @file peer_manager_types.h + * + * @addtogroup peer_manager + * @{ + */ + +#ifndef PEER_MANAGER_TYPES_H__ +#define PEER_MANAGER_TYPES_H__ + +#include +#include +#include +#include "nrf.h" +#include "ble_gap.h" +#include "ble_hci.h" +#include "ble_gatt_db.h" +#include "app_util.h" +#include "app_util_platform.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Handle to uniquely identify a peer for which we have persistently stored data. + */ +typedef uint16_t pm_peer_id_t; + +/**@brief Type that is used to hold a reference to a stored item in flash. + */ +typedef uint32_t pm_store_token_t; + +/**@brief Errors from security procedures in Peer Manager. + * + * @details Possible values are defined in @ref PM_SEC_ERRORS and @ref BLE_GAP_SEC_STATUS. + */ +typedef uint16_t pm_sec_error_code_t; + + +//lint -emacro(516,PM_LOCAL_DB_LEN_OVERHEAD_BYTES) + +#define PM_PEER_ID_INVALID 0xFFFF /**< @brief Invalid value for @ref pm_peer_id_t. */ +#define PM_STORE_TOKEN_INVALID 0 /**< @brief Invalid value for store token. */ +#define PM_PEER_ID_N_AVAILABLE_IDS 256 /**< @brief The number of available peer IDs. */ +#define PM_LOCAL_DB_LEN_OVERHEAD_BYTES offsetof(pm_peer_data_local_gatt_db_t, data) /**< @brief The static-length part of the local GATT data struct. */ + + +#define PM_CONN_SEC_ERROR_BASE 0x1000 /**< @brief The base for Peer Manager defined errors. See @ref PM_SEC_ERRORS and @ref pm_sec_error_code_t. */ + + +/**@defgroup PM_SEC_ERRORS Peer Manager defined security errors + * + * @details The first 256 numbers, from PM_CONN_SEC_ERROR_BASE to (PM_CONN_SEC_ERROR_BASE + 0xFF), + * correspond to the status codes in @ref BLE_HCI_STATUS_CODES. + * @{ */ +#define PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING (PM_CONN_SEC_ERROR_BASE + 0x06) /**< @brief Encryption failed because the peripheral has lost the LTK for this bond. See also @ref BLE_HCI_STATUS_CODE_PIN_OR_KEY_MISSING and Table 3.7 ("Pairing Failed Reason Codes") in the Bluetooth Core Specification 4.2, section 3.H.3.5.5 (@linkBLEcore). */ +#define PM_CONN_SEC_ERROR_MIC_FAILURE (PM_CONN_SEC_ERROR_BASE + 0x3D) /**< @brief Encryption ended with disconnection because of mismatching keys or a stray packet during a procedure. See the SoftDevice GAP Message Sequence Charts on encryption (@linkBLEMSCgap), the Bluetooth Core Specification 4.2, sections 6.B.5.1.3.1 and 3.H.3.5.5 (@linkBLEcore), and @ref BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE. */ +#define PM_CONN_SEC_ERROR_DISCONNECT (PM_CONN_SEC_ERROR_BASE + 0x100) /**< @brief Pairing or encryption did not finish before the link disconnected for an unrelated reason. */ +#define PM_CONN_SEC_ERROR_SMP_TIMEOUT (PM_CONN_SEC_ERROR_BASE + 0x101) /**< @brief Pairing/bonding could not start because an SMP time-out has already happened on this link. This means that no more pairing or bonding can happen on this link. To be able to pair or bond, the link must be disconnected and then reconnected. See Bluetooth Core Specification 4.2 section 3.H.3.4 (@linkBLEcore). */ + /** @} */ + + + +/**@defgroup PM_PEER_ID_VERSIONS All versions of Peer IDs. + * @brief The data ID for each iteration of the data formats in flash. + * @details Each time the format (in flash) of a piece of peer data changes, the data ID will also + * be updated. This list of defines is a record of each data ID that has ever existed, and + * code that caters to legacy formats can find the relevant IDs here. + * @{ */ +#define PM_PEER_DATA_ID_FIRST_VX 0 /**< @brief The smallest data ID. */ +#define PM_PEER_DATA_ID_BONDING_V1 0 /**< @brief The data ID of the first version of bonding data. */ +#define PM_PEER_DATA_ID_BONDING_V2 7 /**< @brief The data ID of the second version of bonding data. */ +#define PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING_V1 1 /**< @brief The data ID of the first version of the service changed pending flag. */ +#define PM_PEER_DATA_ID_GATT_LOCAL_V1 2 /**< @brief The data ID of the first version of local GATT data. */ +#define PM_PEER_DATA_ID_GATT_LOCAL_V2 8 /**< @brief The data ID of the second version of local GATT data. */ +#define PM_PEER_DATA_ID_GATT_REMOTE_V1 3 /**< @brief The data ID of the first version of remote GATT data. */ +#define PM_PEER_DATA_ID_APPLICATION_V1 4 /**< @brief The data ID of the first version of application data. */ +#define PM_PEER_DATA_ID_GATT_REMOTE_V2 5 /**< @brief The data ID of the second version of remote GATT data. */ +#define PM_PEER_DATA_ID_PEER_RANK_V1 6 /**< @brief The data ID of the first version of the rank. */ +#define PM_PEER_DATA_ID_CENTRAL_ADDR_RES_V1 9 /**< @brief The data ID of the first version of central address resolution. */ +#define PM_PEER_DATA_ID_LAST_VX 10 /**< @brief The data ID after the last valid one. */ +#define PM_PEER_DATA_ID_INVALID_VX 0xFF /**< @brief A data ID guaranteed to be invalid. */ +/**@}*/ + + +/**@brief The different types of data associated with a peer. + */ +typedef enum +{ + PM_PEER_DATA_ID_FIRST = PM_PEER_DATA_ID_FIRST_VX, /**< @brief The smallest data ID. */ + PM_PEER_DATA_ID_BONDING = PM_PEER_DATA_ID_BONDING_V2, /**< @brief The data ID for bonding data. Type: @ref pm_peer_data_bonding_t. */ + PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING_V1, /**< @brief The data ID for service changed state. Type: bool. */ + PM_PEER_DATA_ID_GATT_LOCAL = PM_PEER_DATA_ID_GATT_LOCAL_V2, /**< @brief The data ID for local GATT data (sys attributes). Type: @ref pm_peer_data_local_gatt_db_t. */ + PM_PEER_DATA_ID_GATT_REMOTE = PM_PEER_DATA_ID_GATT_REMOTE_V2, /**< @brief The data ID for remote GATT data. Type: uint8_t array. */ + PM_PEER_DATA_ID_PEER_RANK = PM_PEER_DATA_ID_PEER_RANK_V1, /**< @brief The data ID for peer rank. See @ref pm_peer_rank_highest. Type: uint32_t. */ + PM_PEER_DATA_ID_CENTRAL_ADDR_RES = PM_PEER_DATA_ID_CENTRAL_ADDR_RES_V1, /**< @brief The data ID for central address resolution. See @ref pm_peer_id_list. Type: uint32_t. */ + PM_PEER_DATA_ID_APPLICATION = PM_PEER_DATA_ID_APPLICATION_V1, /**< @brief The data ID for application data. Type: uint8_t array. */ + PM_PEER_DATA_ID_LAST = PM_PEER_DATA_ID_LAST_VX, /**< @brief One more than the highest data ID. */ + PM_PEER_DATA_ID_INVALID = PM_PEER_DATA_ID_INVALID_VX, /**< @brief A data ID guaranteed to be invalid. */ +} pm_peer_data_id_t; + + +/**@brief Different procedures that can lead to an encrypted link. + */ +typedef enum +{ + PM_CONN_SEC_PROCEDURE_ENCRYPTION, /**< @brief Using an LTK that was shared during a previous bonding procedure to encrypt the link. */ + PM_CONN_SEC_PROCEDURE_BONDING, /**< @brief A pairing procedure, followed by a bonding procedure. */ + PM_CONN_SEC_PROCEDURE_PAIRING, /**< @brief A pairing procedure with no bonding. */ +} pm_conn_sec_procedure_t; + + +/**@brief Configuration of a security procedure. + */ +typedef struct +{ + bool allow_repairing; /** @brief Whether to allow the peer to pair if it wants to, but is already bonded. If this is false, the procedure is rejected, and no more events are sent. Default: false. */ +} pm_conn_sec_config_t; + + +/**@brief Data associated with a bond to a peer. + */ +typedef struct +{ + uint8_t own_role; /**< @brief The BLE role of the local device during bonding. See @ref BLE_GAP_ROLES. */ + ble_gap_id_key_t peer_ble_id; /**< @brief The peer's Bluetooth address and identity resolution key (IRK). */ + ble_gap_enc_key_t peer_ltk; /**< @brief The peer's long-term encryption key (LTK) and master ID. */ + ble_gap_enc_key_t own_ltk; /**< @brief Locally generated long-term encryption key (LTK) and master ID, distributed to the peer. */ +} pm_peer_data_bonding_t; + + +/**@brief Data on a local GATT database. + */ +typedef struct +{ + uint32_t flags; /**< @brief Flags that describe the database attributes. */ + uint16_t len; /**< @brief Size of the attribute array. */ + uint8_t data[1]; /**< @brief Array to hold the database attributes. */ +} pm_peer_data_local_gatt_db_t; + + +/**@brief Device Privacy. + * + * The privacy feature provides a way for the device to avoid being tracked over a period of + * time. The privacy feature, when enabled, hides the local device identity and replaces it + * with a private address that is automatically refreshed at a specified interval. + * + * If a device still wants to be recognized by other peers, it needs to share it's Identity + * Resolving Key (IRK). With this key, a device can generate a random private address that + * can only be recognized by peers in possession of that key, and devices can establish + * connections without revealing their real identities. + * + * @note If the device IRK is updated, the new IRK becomes the one to be distributed in all + * bonding procedures performed after @ref sd_ble_gap_privacy_set returns. + * The IRK distributed during bonding procedure is the device IRK that is active when @ref + * sd_ble_gap_sec_params_reply is called. + */ +typedef ble_gap_privacy_params_t pm_privacy_params_t; + + +/**@brief Security status of a connection. + */ +typedef struct +{ + uint8_t connected : 1; /**< @brief The connection is active (not disconnected). */ + uint8_t encrypted : 1; /**< @brief The communication on this link is encrypted. */ + uint8_t mitm_protected : 1; /**< @brief The encrypted communication is also protected against man-in-the-middle attacks. */ + uint8_t bonded : 1; /**< @brief The peer is bonded. */ + uint8_t lesc : 1; /**< @brief The peer is paired using LESC. */ + uint8_t reserved : 3; /**< @brief Reserved for future use. */ +} pm_conn_sec_status_t; + + +/**@brief Types of events that can come from the @ref peer_manager module. + */ +typedef enum +{ + PM_EVT_BONDED_PEER_CONNECTED, /**< @brief A connected peer has been identified as one with which we have a bond. When performing bonding with a peer for the first time, this event will not be sent until a new connection is established with the peer. When we are central, this event is always sent when the Peer Manager receives the @ref BLE_GAP_EVT_CONNECTED event. When we are peripheral, this event might in rare cases arrive later. */ + PM_EVT_CONN_CONFIG_REQ, /**< @brief A new connection has been established. This event is a wrapper for @ref BLE_GAP_EVT_CONNECTED event and contains its parameters. Reply with @ref pm_conn_exclude before the event handler returns to exclude BLE events targeting this connection from being handled by the Peer Manager */ + PM_EVT_CONN_SEC_START, /**< @brief A security procedure has started on a link, initiated either locally or remotely. The security procedure is using the last parameters provided via @ref pm_sec_params_set. This event is always followed by either a @ref PM_EVT_CONN_SEC_SUCCEEDED or a @ref PM_EVT_CONN_SEC_FAILED event. This is an informational event; no action is needed for the procedure to proceed. */ + PM_EVT_CONN_SEC_SUCCEEDED, /**< @brief A link has been encrypted, either as a result of a call to @ref pm_conn_secure or a result of an action by the peer. The event structure contains more information about the circumstances. This event might contain a peer ID with the value @ref PM_PEER_ID_INVALID, which means that the peer (central) used an address that could not be identified, but it used an encryption key (LTK) that is present in the database. */ + PM_EVT_CONN_SEC_FAILED, /**< @brief A pairing or encryption procedure has failed. In some cases, this means that security is not possible on this link (temporarily or permanently). How to handle this error depends on the application. */ + PM_EVT_CONN_SEC_CONFIG_REQ, /**< @brief The peer (central) has requested pairing, but a bond already exists with that peer. Reply by calling @ref pm_conn_sec_config_reply before the event handler returns. If no reply is sent, a default is used. */ + PM_EVT_CONN_SEC_PARAMS_REQ, /**< @brief Security parameters (@ref ble_gap_sec_params_t) are needed for an ongoing security procedure. Reply with @ref pm_conn_sec_params_reply before the event handler returns. If no reply is sent, the parameters given in @ref pm_sec_params_set are used. If a peripheral connection, the central's sec_params will be available in the event. */ + PM_EVT_STORAGE_FULL, /**< @brief There is no more room for peer data in flash storage. To solve this problem, delete data that is not needed anymore and run a garbage collection procedure in FDS. */ + PM_EVT_ERROR_UNEXPECTED, /**< @brief An unrecoverable error happened inside Peer Manager. An operation failed with the provided error. */ + PM_EVT_PEER_DATA_UPDATE_SUCCEEDED, /**< @brief A piece of peer data was stored, updated, or cleared in flash storage. This event is sent for all successful changes to peer data, also those initiated internally in Peer Manager. To identify an operation, compare the store token in the event with the store token received during the initiating function call. Events from internally initiated changes might have invalid store tokens. */ + PM_EVT_PEER_DATA_UPDATE_FAILED, /**< @brief A piece of peer data could not be stored, updated, or cleared in flash storage. This event is sent instead of @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED for the failed operation. */ + PM_EVT_PEER_DELETE_SUCCEEDED, /**< @brief A peer was cleared from flash storage, for example because a call to @ref pm_peer_delete succeeded. This event can also be sent as part of a call to @ref pm_peers_delete or internal cleanup. */ + PM_EVT_PEER_DELETE_FAILED, /**< @brief A peer could not be cleared from flash storage. This event is sent instead of @ref PM_EVT_PEER_DELETE_SUCCEEDED for the failed operation. */ + PM_EVT_PEERS_DELETE_SUCCEEDED, /**< @brief A call to @ref pm_peers_delete has completed successfully. Flash storage now contains no peer data. */ + PM_EVT_PEERS_DELETE_FAILED, /**< @brief A call to @ref pm_peers_delete has failed, which means that at least one of the peers could not be deleted. Other peers might have been deleted, or might still be queued to be deleted. No more @ref PM_EVT_PEERS_DELETE_SUCCEEDED or @ref PM_EVT_PEERS_DELETE_FAILED events are sent until the next time @ref pm_peers_delete is called. */ + PM_EVT_LOCAL_DB_CACHE_APPLIED, /**< @brief Local database values for a peer (taken from flash storage) have been provided to the SoftDevice. */ + PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED, /**< @brief Local database values for a peer (taken from flash storage) were rejected by the SoftDevice, which means that either the database has changed or the user has manually set the local database to an invalid value (using @ref pm_peer_data_store). */ + PM_EVT_SERVICE_CHANGED_IND_SENT, /**< @brief A service changed indication has been sent to a peer, as a result of a call to @ref pm_local_database_has_changed. This event will be followed by a @ref PM_EVT_SERVICE_CHANGED_IND_CONFIRMED event if the peer acknowledges the indication. */ + PM_EVT_SERVICE_CHANGED_IND_CONFIRMED, /**< @brief A service changed indication that was sent has been confirmed by a peer. The peer can now be considered aware that the local database has changed. */ + PM_EVT_SLAVE_SECURITY_REQ, /**< @brief The peer (peripheral) has requested link encryption, which has been enabled. */ + PM_EVT_FLASH_GARBAGE_COLLECTED, /**< @brief The flash has been garbage collected (By FDS), possibly freeing up space. */ + PM_EVT_FLASH_GARBAGE_COLLECTION_FAILED, /**< @brief Garbage collection was attempted but failed. */ +} pm_evt_id_t; + + +/**@brief Parameters specific to the @ref PM_EVT_CONN_CONFIG_REQ event. + */ +typedef struct +{ + ble_gap_evt_connected_t const * p_peer_params; /**< @brief Connected Event parameters. */ + void const * p_context; /**< @brief This pointer must be provided in the reply if the reply function takes a p_context argument. */ +} pm_conn_config_req_evt_t; + + +/**@brief Events parameters specific to the @ref PM_EVT_CONN_SEC_START event. + */ +typedef struct +{ + pm_conn_sec_procedure_t procedure; /**< @brief The procedure that has started. */ +} pm_conn_sec_start_evt_t; + + +/**@brief Parameters specific to the @ref PM_EVT_CONN_SEC_SUCCEEDED event. + */ +typedef struct +{ + pm_conn_sec_procedure_t procedure; /**< @brief The procedure that led to securing the link. */ + bool data_stored; /**< @brief Whether bonding data was successfully requested to be stored. This is false if: No bonding happened, or an internal error occurred when trying to store the data, or if the data was rejected via @ref pm_conn_sec_config_reply. */ +} pm_conn_secured_evt_t; + + +/**@brief Parameters specific to the @ref PM_EVT_CONN_SEC_FAILED event. + */ +typedef struct +{ + pm_conn_sec_procedure_t procedure; /**< @brief The procedure that failed. */ + pm_sec_error_code_t error; /**< @brief An error code that describes the failure. */ + uint8_t error_src; /**< @brief The party that raised the error, see @ref BLE_GAP_SEC_STATUS_SOURCES. */ +} pm_conn_secure_failed_evt_t; + + +/**@brief Parameters specific to the @ref PM_EVT_CONN_SEC_PARAMS_REQ event. + */ +typedef struct +{ + ble_gap_sec_params_t const * p_peer_params; /**< @brief Peer security parameters, if role is peripheral. Otherwise, this is NULL. */ + void const * p_context; /**< @brief This pointer must be provided in the reply if the reply function takes a p_context argument. */ +} pm_conn_sec_params_req_evt_t; + + +/**@brief Actions that can be performed to peer data in persistent storage. + */ +typedef enum +{ + PM_PEER_DATA_OP_UPDATE, /**< @brief Writing or overwriting the data. */ + PM_PEER_DATA_OP_DELETE, /**< @brief Removing the data. */ +} pm_peer_data_op_t; + + +/**@brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event. + */ +typedef struct +{ + pm_peer_data_id_t data_id; /**< @brief The type of the data that was changed. */ + pm_peer_data_op_t action; /**< @brief What happened to the data. */ + pm_store_token_t token; /**< @brief Token that identifies the operation. For @ref PM_PEER_DATA_OP_DELETE actions, this token can be disregarded. For @ref PM_PEER_DATA_OP_UPDATE actions, compare this token with the token that is received from a call to a @ref PM_PEER_DATA_FUNCTIONS function. */ + uint8_t flash_changed : 1; /**< @brief If this is false, no operation was done in flash, because the value was already what it should be. Please note that in certain scenarios, this flag will be true even if the new value is the same as the old. */ +} pm_peer_data_update_succeeded_evt_t; + + +/**@brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_FAILED event. + */ +typedef struct +{ + pm_peer_data_id_t data_id; /**< @brief The type of the data that was supposed to be changed. */ + pm_peer_data_op_t action; /**< @brief The action that failed. */ + pm_store_token_t token; /**< @brief Token that identifies the operation. For @ref PM_PEER_DATA_OP_DELETE actions, this token can be disregarded. For @ref PM_PEER_DATA_OP_UPDATE actions, compare this token with the token that is received from a call to a @ref PM_PEER_DATA_FUNCTIONS function. */ + ret_code_t error; /**< @brief An error code that describes the failure. */ +} pm_peer_data_update_failed_t; + + +/**@brief Standard parameters for failure events. + */ +typedef struct +{ + ret_code_t error; /**< @brief The error that occurred. */ +} pm_failure_evt_t; + + +/**@brief An event from the @ref peer_manager module. + * + * @details The structure contains both standard parameters and parameters that are specific to some events. + */ +typedef struct +{ + pm_evt_id_t evt_id; /**< @brief The type of the event. */ + uint16_t conn_handle; /**< @brief The connection that this event pertains to, or @ref BLE_CONN_HANDLE_INVALID. */ + pm_peer_id_t peer_id; /**< @brief The bonded peer that this event pertains to, or @ref PM_PEER_ID_INVALID. */ + union + { + pm_conn_config_req_evt_t conn_config_req; /**< @brief Parameters specific to the @ref PM_EVT_CONN_CONFIG_REQ event. */ + pm_conn_sec_start_evt_t conn_sec_start; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_START event. */ + pm_conn_secured_evt_t conn_sec_succeeded; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_SUCCEEDED event. */ + pm_conn_secure_failed_evt_t conn_sec_failed; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_FAILED event. */ + pm_conn_sec_params_req_evt_t conn_sec_params_req; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_PARAMS_REQ event. */ + pm_peer_data_update_succeeded_evt_t peer_data_update_succeeded; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event. */ + pm_peer_data_update_failed_t peer_data_update_failed; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_FAILED event. */ + pm_failure_evt_t peer_delete_failed; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DELETE_FAILED event. */ + pm_failure_evt_t peers_delete_failed_evt; /**< @brief Parameters specific to the @ref PM_EVT_PEERS_DELETE_FAILED event. */ + pm_failure_evt_t error_unexpected; /**< @brief Parameters specific to the @ref PM_EVT_ERROR_UNEXPECTED event. */ + ble_gap_evt_sec_request_t slave_security_req; /**< @brief Parameters specific to the @ref PM_EVT_SLAVE_SECURITY_REQ event. */ + pm_failure_evt_t garbage_collection_failed; /**< @brief Parameters specific to the @ref PM_EVT_FLASH_GARBAGE_COLLECTION_FAILED event. */ + } params; +} pm_evt_t; + + +/**@brief Event handler for events from the @ref peer_manager module. + * + * @sa pm_register + * + * @param[in] p_event The event that has occurred. + */ +typedef void (*pm_evt_handler_t)(pm_evt_t const * p_event); + +#ifdef __cplusplus +} +#endif + +#endif /* PEER_MANAGER_TYPES_H__ */ + +/** @} */ diff --git a/components/ble/peer_manager/pm_buffer.c b/components/ble/peer_manager/pm_buffer.c new file mode 100644 index 0000000..08fd264 --- /dev/null +++ b/components/ble/peer_manager/pm_buffer.c @@ -0,0 +1,170 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(PEER_MANAGER) +#include "pm_buffer.h" + +#include +#include +#include "nrf_error.h" +#include "nrf_atflags.h" + + +#define BUFFER_IS_VALID(p_buffer) ((p_buffer != NULL) \ + && (p_buffer->p_memory != NULL) \ + && (p_buffer->p_mutex != NULL)) + + + +static bool mutex_lock(nrf_atflags_t * p_mutex, uint32_t mutex_id) +{ + bool locked = !nrf_atflags_fetch_set(p_mutex, mutex_id); + __DMB(); + return locked; +} + + +static void mutex_unlock(nrf_atflags_t * p_mutex, uint32_t mutex_id) +{ + __DMB(); + nrf_atflags_clear(p_mutex, mutex_id); +} + + +static bool mutex_lock_status_get(nrf_atflags_t * p_mutex, uint32_t mutex_id) +{ + __DMB(); + return nrf_atflags_get(p_mutex, mutex_id); +} + + +ret_code_t pm_buffer_init(pm_buffer_t * p_buffer, + uint8_t * p_buffer_memory, + uint32_t buffer_memory_size, + nrf_atflags_t * p_mutex_memory, + uint32_t n_blocks, + uint32_t block_size) +{ + if ( (p_buffer != NULL) + && (p_buffer_memory != NULL) + && (p_mutex_memory != NULL) + && (buffer_memory_size >= (n_blocks * block_size)) + && (n_blocks != 0) + && (block_size != 0)) + { + p_buffer->p_memory = p_buffer_memory; + p_buffer->p_mutex = p_mutex_memory; + p_buffer->n_blocks = n_blocks; + p_buffer->block_size = block_size; + + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_INVALID_PARAM; + } +} + + +uint8_t pm_buffer_block_acquire(pm_buffer_t * p_buffer, uint32_t n_blocks) +{ + if (!BUFFER_IS_VALID(p_buffer)) + { + return ( PM_BUFFER_INVALID_ID ); + } + + uint8_t first_locked_mutex = PM_BUFFER_INVALID_ID; + + for (uint8_t i = 0; i < p_buffer->n_blocks; i++) + { + if (mutex_lock(p_buffer->p_mutex, i)) + { + if (first_locked_mutex == PM_BUFFER_INVALID_ID) + { + first_locked_mutex = i; + } + if ((i - first_locked_mutex + 1U) == n_blocks) + { + return first_locked_mutex; + } + } + else if (first_locked_mutex != PM_BUFFER_INVALID_ID) + { + for (uint8_t j = first_locked_mutex; j < i; j++) + { + pm_buffer_release(p_buffer, j); + } + first_locked_mutex = PM_BUFFER_INVALID_ID; + } + } + + return ( PM_BUFFER_INVALID_ID ); +} + + +uint8_t * pm_buffer_ptr_get(pm_buffer_t * p_buffer, uint8_t id) +{ + if (!BUFFER_IS_VALID(p_buffer)) + { + return ( NULL ); + } + + if ( (id != PM_BUFFER_INVALID_ID) + && mutex_lock_status_get(p_buffer->p_mutex, id) ) + { + return ( &p_buffer->p_memory[id * p_buffer->block_size] ); + } + else + { + return ( NULL ); + } +} + + +void pm_buffer_release(pm_buffer_t * p_buffer, uint8_t id) +{ + if ( BUFFER_IS_VALID(p_buffer) + && (id != PM_BUFFER_INVALID_ID) + && mutex_lock_status_get(p_buffer->p_mutex, id)) + { + mutex_unlock(p_buffer->p_mutex, id); + } +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/components/ble/peer_manager/pm_buffer.h b/components/ble/peer_manager/pm_buffer.h new file mode 100644 index 0000000..2747641 --- /dev/null +++ b/components/ble/peer_manager/pm_buffer.h @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef BUFFER_H__ +#define BUFFER_H__ + +#include +#include "compiler_abstraction.h" +#include "sdk_errors.h" +#include "nrf_atflags.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @defgroup pm_buffer Buffer + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. This module provides a simple buffer. + */ + + +#define PM_BUFFER_INVALID_ID 0xFF //!< Invalid buffer block ID. + + +/**@brief Convenience macro for declaring memory and initializing a buffer instance. + * + * @param[out] p_buffer The buffer instance to initialize. + * @param[in] n_blocks The desired number of blocks in the buffer. + * @param[in] block_size The desired block size of the buffer. + * @param[out] err_code The return code from @ref pm_buffer_init. + */ +#define PM_BUFFER_INIT(p_buffer, n_blocks, block_size, err_code) \ +do \ +{ \ + __ALIGN(4) static uint8_t buffer_memory[(n_blocks) * (block_size)]; \ + static NRF_ATFLAGS_DEF(mutex_memory, n_blocks); \ + err_code = pm_buffer_init((p_buffer), \ + buffer_memory, \ + (n_blocks) * (block_size), \ + mutex_memory, \ + (n_blocks), \ + (block_size)); \ +} while (0) + + +typedef struct +{ + uint8_t * p_memory; /**< The storage for all buffer entries. The size of the buffer must be n_blocks*block_size. */ + nrf_atflags_t * p_mutex; /**< A mutex group with one mutex for each buffer entry. */ + uint32_t n_blocks; /**< The number of allocatable blocks in the buffer. */ + uint32_t block_size; /**< The size of each block in the buffer. */ +} pm_buffer_t; + +/**@brief Function for initializing a buffer instance. + * + * @param[out] p_buffer The buffer instance to initialize. + * @param[in] p_buffer_memory The memory this buffer will use. + * @param[in] buffer_memory_size The size of p_buffer_memory. This must be at least + * n_blocks*block_size. + * @param[in] p_mutex_memory The memory for the mutexes. This must be at least + * @ref NRF_ATFLAGS_ARRAY_LEN(n_blocks). + * @param[in] n_blocks The number of blocks in the buffer. + * @param[in] block_size The size of each block. + * + * @retval NRF_SUCCESS Successfully initialized buffer instance. + * @retval NRF_ERROR_INVALID_PARAM A parameter was 0 or NULL or a size was too small. + */ +ret_code_t pm_buffer_init(pm_buffer_t * p_buffer, + uint8_t * p_buffer_memory, + uint32_t buffer_memory_size, + nrf_atflags_t * p_mutex_memory, + uint32_t n_blocks, + uint32_t block_size); + + +/**@brief Function for acquiring a buffer block in a buffer. + * + * @param[in] p_buffer The buffer instance acquire from. + * @param[in] n_blocks The number of contiguous blocks to acquire. + * + * @return The id of the acquired block, if successful. + * @retval PM_BUFFER_INVALID_ID If unsuccessful. + */ +uint8_t pm_buffer_block_acquire(pm_buffer_t * p_buffer, uint32_t n_blocks); + + +/**@brief Function for getting a pointer to a specific buffer block. + * + * @param[in] p_buffer The buffer instance get from. + * @param[in] id The id of the buffer to get the pointer for. + * + * @return A pointer to the buffer for the specified id, if the id is valid. + * @retval NULL If the id is invalid. + */ +uint8_t * pm_buffer_ptr_get(pm_buffer_t * p_buffer, uint8_t id); + + +/**@brief Function for releasing a buffer block. + * + * @param[in] p_buffer The buffer instance containing the block to release. + * @param[in] id The id of the block to release. + */ +void pm_buffer_release(pm_buffer_t * p_buffer, uint8_t id); + + + +#ifdef __cplusplus +} +#endif + +#endif // BUFFER_H__ + +/** + * @} + * @endcond + */ diff --git a/components/ble/peer_manager/security_dispatcher.c b/components/ble/peer_manager/security_dispatcher.c new file mode 100644 index 0000000..b7c8b4d --- /dev/null +++ b/components/ble/peer_manager/security_dispatcher.c @@ -0,0 +1,1097 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(PEER_MANAGER) +#include "security_dispatcher.h" + +#include +#include "ble.h" +#include "ble_gap.h" +#include "ble_err.h" +#include "ble_conn_state.h" +#include "peer_manager_types.h" +#include "peer_data_storage.h" +#include "peer_database.h" +#include "id_manager.h" +#if PM_RA_PROTECTION_ENABLED +#include "auth_status_tracker.h" +#endif // PM_RA_PROTECTION_ENABLED + +#define NRF_LOG_MODULE_NAME peer_manager_smd +#if PM_LOG_ENABLED + #define NRF_LOG_LEVEL PM_LOG_LEVEL + #define NRF_LOG_INFO_COLOR PM_LOG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR PM_LOG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // PM_LOG_ENABLED +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +NRF_LOG_MODULE_REGISTER(); +#include "nrf_strerror.h" + +#ifndef PM_CENTRAL_ENABLED + #define PM_CENTRAL_ENABLED 1 +#endif + +// The number of registered event handlers. +#define SMD_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) + +STATIC_ASSERT((NRF_SDH_BLE_CENTRAL_LINK_COUNT == 0) || PM_CENTRAL_ENABLED, + "Peer Manager Central operation must be enabled when using central links."); + +// Security Dispacher event handlers in Security Manager and GATT Cache Manager. +extern void sm_smd_evt_handler(pm_evt_t * p_event); + +// Security Dispatcher events' handlers. +// The number of elements in this array is SMD_EVENT_HANDLERS_CNT. +static pm_evt_handler_internal_t const m_evt_handlers[] = +{ + sm_smd_evt_handler +}; + +static bool m_module_initialized; + +static ble_conn_state_user_flag_id_t m_flag_sec_proc = BLE_CONN_STATE_USER_FLAG_INVALID; +static ble_conn_state_user_flag_id_t m_flag_sec_proc_pairing = BLE_CONN_STATE_USER_FLAG_INVALID; +static ble_conn_state_user_flag_id_t m_flag_sec_proc_bonding = BLE_CONN_STATE_USER_FLAG_INVALID; +static ble_conn_state_user_flag_id_t m_flag_allow_repairing = BLE_CONN_STATE_USER_FLAG_INVALID; + +static ble_gap_lesc_p256_pk_t m_peer_pk; + + +static __INLINE bool sec_procedure(uint16_t conn_handle) +{ + return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc); +} + +static __INLINE bool pairing(uint16_t conn_handle) +{ + return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc_pairing); +} + +static __INLINE bool bonding(uint16_t conn_handle) +{ + return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc_bonding); +} + +static __INLINE bool allow_repairing(uint16_t conn_handle) +{ + return ble_conn_state_user_flag_get(conn_handle, m_flag_allow_repairing); +} + + +/**@brief Function for sending an SMD event to all event handlers. + * + * @param[in] p_event The event to pass to all event handlers. + */ +static void evt_send(pm_evt_t * p_event) +{ + p_event->peer_id = im_peer_id_get_by_conn_handle(p_event->conn_handle); + + for (uint32_t i = 0; i < SMD_EVENT_HANDLERS_CNT; i++) + { + m_evt_handlers[i](p_event); + } +} + + +/**@brief Function for sending a PM_EVT_CONN_SEC_START event. + * + * @param[in] conn_handle The connection handle the event pertains to. + * @param[in] procedure The procedure that has started on the connection. + */ +static void sec_start_send(uint16_t conn_handle, + pm_conn_sec_procedure_t procedure) +{ + pm_evt_t evt = + { + .evt_id = PM_EVT_CONN_SEC_START, + .conn_handle = conn_handle, + .params = {.conn_sec_start = {.procedure = procedure}} + }; + evt_send(&evt); +} + + +/**@brief Function for sending a PM_EVT_ERROR_UNEXPECTED event. + * + * @param[in] conn_handle The connection handle the event pertains to. + * @param[in] err_code The unexpected error that occurred. + */ +static void send_unexpected_error(uint16_t conn_handle, ret_code_t err_code) +{ + pm_evt_t error_evt = + { + .evt_id = PM_EVT_ERROR_UNEXPECTED, + .conn_handle = conn_handle, + .params = + { + .error_unexpected = + { + .error = err_code, + } + } + }; + evt_send(&error_evt); +} + + +/**@brief Function for sending a PM_EVT_STORAGE_FULL event. + * + * @param[in] conn_handle The connection handle the event pertains to. + */ +static void send_storage_full_evt(uint16_t conn_handle) +{ + pm_evt_t evt = + { + .evt_id = PM_EVT_STORAGE_FULL, + .conn_handle = conn_handle + }; + evt_send(&evt); +} + + +/**@brief Function for cleaning up after a failed security procedure. + * + * @param[in] conn_handle The handle of the connection the security procedure happens on. + * @param[in] procedure The procedure that failed. + * @param[in] error The error the procedure failed with. + * @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES. + */ +static void conn_sec_failure(uint16_t conn_handle, + pm_conn_sec_procedure_t procedure, + pm_sec_error_code_t error, + uint8_t error_src) +{ + pm_evt_t evt = + { + .evt_id = PM_EVT_CONN_SEC_FAILED, + .conn_handle = conn_handle, + .params = + { + .conn_sec_failed = + { + .procedure = procedure, + .error = error, + .error_src = error_src, + } + } + }; + + ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc, false); + + evt_send(&evt); + return; +} + + +/**@brief Function for cleaning up after a failed pairing procedure. + * + * @param[in] conn_handle The handle of the connection the pairing procedure happens on. + * @param[in] error The error the procedure failed with. + * @param[in] error_src The source of the error (local or remote). See @ref + * BLE_GAP_SEC_STATUS_SOURCES. + */ +static void pairing_failure(uint16_t conn_handle, + pm_sec_error_code_t error, + uint8_t error_src) +{ + ret_code_t err_code = NRF_SUCCESS; + pm_conn_sec_procedure_t procedure = bonding(conn_handle) ? PM_CONN_SEC_PROCEDURE_BONDING + : PM_CONN_SEC_PROCEDURE_PAIRING; + + err_code = pdb_write_buf_release(PDB_TEMP_PEER_ID(conn_handle), PM_PEER_DATA_ID_BONDING); + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_NOT_FOUND /* No buffer was allocated */)) + { + NRF_LOG_ERROR("Could not clean up after failed bonding procedure. "\ + "pdb_write_buf_release() returned %s. conn_handle: %d.", + nrf_strerror_get(err_code), + conn_handle); + send_unexpected_error(conn_handle, err_code); + } + + conn_sec_failure(conn_handle, procedure, error, error_src); + + return; +} + + +/**@brief Function for cleaning up after a failed encryption procedure. + * + * @param[in] conn_handle The handle of the connection the encryption procedure happens on. + * @param[in] error The error the procedure failed with. + * @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES. + */ +static __INLINE void encryption_failure(uint16_t conn_handle, + pm_sec_error_code_t error, + uint8_t error_src) +{ + conn_sec_failure(conn_handle, PM_CONN_SEC_PROCEDURE_ENCRYPTION, error, error_src); + + return; +} + + +/**@brief Function for possibly cleaning up after a failed pairing or encryption procedure. + * + * @param[in] conn_handle The handle of the connection the pairing procedure happens on. + * @param[in] error The error the procedure failed with. + * @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES. + */ +static void link_secure_failure(uint16_t conn_handle, + pm_sec_error_code_t error, + uint8_t error_src) +{ + if (sec_procedure(conn_handle)) + { + if (pairing(conn_handle)) + { + pairing_failure(conn_handle, error, error_src); + } + else + { + encryption_failure(conn_handle, error, error_src); + } + } +} + + +/**@brief Function for administrative actions to be taken when a security process has started. + * + * @param[in] conn_handle The connection the security process was attempted on. + * @param[in] success Whether the procedure was started successfully. + * @param[in] procedure The procedure that was started. + */ +static void sec_proc_start(uint16_t conn_handle, + bool success, + pm_conn_sec_procedure_t procedure) +{ + ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc, success); + if (success) + { + ble_conn_state_user_flag_set(conn_handle, + m_flag_sec_proc_pairing, + (procedure != PM_CONN_SEC_PROCEDURE_ENCRYPTION)); + ble_conn_state_user_flag_set(conn_handle, + m_flag_sec_proc_bonding, + (procedure == PM_CONN_SEC_PROCEDURE_BONDING)); + sec_start_send(conn_handle, procedure); + } +} + + +#ifdef BLE_GAP_ROLE_PERIPH +/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_INFO_REQUEST event from the SoftDevice. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void sec_info_request_process(ble_gap_evt_t const * p_gap_evt) +{ + ret_code_t err_code; + ble_gap_enc_info_t const * p_enc_info = NULL; + pm_peer_data_flash_t peer_data; + pm_peer_id_t peer_id = im_peer_id_get_by_master_id( + &p_gap_evt->params.sec_info_request.master_id); + + if (peer_id == PM_PEER_ID_INVALID) + { + peer_id = im_peer_id_get_by_conn_handle(p_gap_evt->conn_handle); + } + else + { + // The peer might have been unrecognized until now (since connecting). E.g. if using a + // random non-resolvable advertising address. Report the discovered peer ID just in case. + im_new_peer_id(p_gap_evt->conn_handle, peer_id); + } + + sec_proc_start(p_gap_evt->conn_handle, true, PM_CONN_SEC_PROCEDURE_ENCRYPTION); + + if (peer_id != PM_PEER_ID_INVALID) + { + err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_BONDING, &peer_data); + + if (err_code == NRF_SUCCESS) + { + // There is stored bonding data for this peer. + ble_gap_enc_key_t const * p_existing_key = &peer_data.p_bonding_data->own_ltk; + + if (p_gap_evt->params.sec_info_request.enc_info + && (p_existing_key->enc_info.lesc + || im_master_ids_compare(&p_existing_key->master_id, + &p_gap_evt->params.sec_info_request.master_id))) + { + p_enc_info = &p_existing_key->enc_info; + } + } + } + + err_code = sd_ble_gap_sec_info_reply(p_gap_evt->conn_handle, p_enc_info, NULL, NULL); + + if (err_code == NRF_ERROR_INVALID_STATE) + { + // Do nothing. If disconnecting, it will be caught later by the handling of the DISCONNECTED + // event. If there is no SEC_INFO_REQ pending, there is either a logic error, or the user + // is also calling sd_ble_gap_sec_info_reply(), but there is no way for the present code to + // detect which one is the case. + NRF_LOG_WARNING("sd_ble_gap_sec_info_reply() returned NRF_EROR_INVALID_STATE, which is an"\ + "error unless the link is disconnecting."); + } + else if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not complete encryption procedure. sd_ble_gap_sec_info_reply() "\ + "returned %s. conn_handle: %d, peer_id: %d.", + nrf_strerror_get(err_code), + p_gap_evt->conn_handle, + peer_id); + send_unexpected_error(p_gap_evt->conn_handle, err_code); + } + else if (p_gap_evt->params.sec_info_request.enc_info && (p_enc_info == NULL)) + { + encryption_failure(p_gap_evt->conn_handle, + PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING, + BLE_GAP_SEC_STATUS_SOURCE_LOCAL); + } + + return; +} +#endif // BLE_GAP_ROLE_PERIPH + + +/**@brief Function for sending a CONFIG_REQ event. + * + * @param[in] conn_handle The connection the sec parameters are needed for. + */ +static void send_config_req(uint16_t conn_handle) +{ + pm_evt_t evt; + memset(&evt, 0, sizeof(evt)); + + evt.evt_id = PM_EVT_CONN_SEC_CONFIG_REQ; + evt.conn_handle = conn_handle; + + evt_send(&evt); +} + + +void smd_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_conn_sec_config != NULL); + + ble_conn_state_user_flag_set(conn_handle, + m_flag_allow_repairing, + p_conn_sec_config->allow_repairing); +} + + +/**@brief Function for processing the @ref BLE_GAP_EVT_DISCONNECT event from the SoftDevice. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void disconnect_process(ble_gap_evt_t const * p_gap_evt) +{ + pm_sec_error_code_t error = (p_gap_evt->params.disconnected.reason + == BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE) + ? PM_CONN_SEC_ERROR_MIC_FAILURE : PM_CONN_SEC_ERROR_DISCONNECT; + + link_secure_failure(p_gap_evt->conn_handle, error, BLE_GAP_SEC_STATUS_SOURCE_LOCAL); +} + + +/**@brief Function for sending a PARAMS_REQ event. + * + * @param[in] conn_handle The connection the security parameters are needed for. + * @param[in] p_peer_params The security parameters from the peer. Can be NULL if the peer's parameters + * are not yet available. + */ +static void send_params_req(uint16_t conn_handle, ble_gap_sec_params_t const * p_peer_params) +{ + pm_evt_t evt = + { + .evt_id = PM_EVT_CONN_SEC_PARAMS_REQ, + .conn_handle = conn_handle, + .params = + { + .conn_sec_params_req = + { + .p_peer_params = p_peer_params + }, + }, + }; + + evt_send(&evt); +} + + +/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST event from the SoftDevice. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void sec_params_request_process(ble_gap_evt_t const * p_gap_evt) +{ +#ifdef BLE_GAP_ROLE_PERIPH + if (ble_conn_state_role(p_gap_evt->conn_handle) == BLE_GAP_ROLE_PERIPH) + { + sec_proc_start(p_gap_evt->conn_handle, + true, + p_gap_evt->params.sec_params_request.peer_params.bond + ? PM_CONN_SEC_PROCEDURE_BONDING + : PM_CONN_SEC_PROCEDURE_PAIRING); + } +#endif // BLE_GAP_ROLE_PERIPH + + send_params_req(p_gap_evt->conn_handle, &p_gap_evt->params.sec_params_request.peer_params); + return; +} + + +/**@brief Function for sending a Peer Manager event indicating that pairing has succeeded. + * + * @param[in] p_gap_evt The AUTH_STATUS event from the SoftDevice that triggered this. + * @param[in] data_stored Whether bonding data was stored. + */ +static void pairing_success_evt_send(ble_gap_evt_t const * p_gap_evt, bool data_stored) +{ + pm_evt_t pairing_success_evt; + + pairing_success_evt.evt_id = PM_EVT_CONN_SEC_SUCCEEDED; + pairing_success_evt.conn_handle = p_gap_evt->conn_handle; + pairing_success_evt.params.conn_sec_succeeded.procedure = p_gap_evt->params.auth_status.bonded + ? PM_CONN_SEC_PROCEDURE_BONDING + : PM_CONN_SEC_PROCEDURE_PAIRING; + pairing_success_evt.params.conn_sec_succeeded.data_stored = data_stored; + + evt_send(&pairing_success_evt); +} + + +/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice, when + * the auth_status is success. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void auth_status_success_process(ble_gap_evt_t const * p_gap_evt) +{ + ret_code_t err_code; + uint16_t conn_handle = p_gap_evt->conn_handle; + pm_peer_id_t peer_id; + pm_peer_data_t peer_data; + bool new_peer_id = false; + + ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc, false); + + if (!p_gap_evt->params.auth_status.bonded) + { + pairing_success_evt_send(p_gap_evt, false); + return; + } + + err_code = pdb_write_buf_get(PDB_TEMP_PEER_ID(conn_handle), PM_PEER_DATA_ID_BONDING, 1, &peer_data); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("RAM buffer for new bond was unavailable. pdb_write_buf_get() returned %s. conn_handle: %d.", + nrf_strerror_get(err_code), + conn_handle); + send_unexpected_error(conn_handle, err_code); + pairing_success_evt_send(p_gap_evt, false); + return; + } + + peer_id = im_peer_id_get_by_conn_handle(conn_handle); + + if (peer_id == PM_PEER_ID_INVALID) + { + peer_id = im_find_duplicate_bonding_data(peer_data.p_bonding_data, PM_PEER_ID_INVALID); + + if (peer_id != PM_PEER_ID_INVALID) + { + // The peer has been identified as someone we have already bonded with. + im_new_peer_id(conn_handle, peer_id); + + // If the flag is true, the configuration has been requested before. + if (!allow_repairing(conn_handle)) + { + send_config_req(conn_handle); + if (!allow_repairing(conn_handle)) + { + pairing_success_evt_send(p_gap_evt, false); + return; + } + } + } + } + + if (peer_id == PM_PEER_ID_INVALID) + { + peer_id = pds_peer_id_allocate(); + if (peer_id == PM_PEER_ID_INVALID) + { + NRF_LOG_ERROR("Could not allocate new peer_id for incoming bond."); + send_unexpected_error(conn_handle, NRF_ERROR_NO_MEM); + pairing_success_evt_send(p_gap_evt, false); + return; + } + im_new_peer_id(conn_handle, peer_id); + new_peer_id = true; + } + + err_code = pdb_write_buf_store(PDB_TEMP_PEER_ID(conn_handle), PM_PEER_DATA_ID_BONDING, peer_id); + + if (err_code == NRF_SUCCESS) + { + pairing_success_evt_send(p_gap_evt, true); + } + else if (err_code == NRF_ERROR_STORAGE_FULL) + { + send_storage_full_evt(conn_handle); + pairing_success_evt_send(p_gap_evt, true); + } + else + { + /* Unexpected error */ + NRF_LOG_ERROR("Could not store bond. pdb_write_buf_store() returned %s. "\ + "conn_handle: %d, peer_id: %d", + nrf_strerror_get(err_code), + conn_handle, + peer_id); + send_unexpected_error(conn_handle, err_code); + pairing_success_evt_send(p_gap_evt, false); + if (new_peer_id) + { + UNUSED_RETURN_VALUE(im_peer_free(peer_id)); // We are already in a bad state. + } + } + + return; +} + + +/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice, when + * the auth_status is failure. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void auth_status_failure_process(ble_gap_evt_t const * p_gap_evt) +{ + link_secure_failure(p_gap_evt->conn_handle, + p_gap_evt->params.auth_status.auth_status, + p_gap_evt->params.auth_status.error_src); +} + + +/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void auth_status_process(ble_gap_evt_t const * p_gap_evt) +{ + switch (p_gap_evt->params.auth_status.auth_status) + { + case BLE_GAP_SEC_STATUS_SUCCESS: + auth_status_success_process(p_gap_evt); + break; + + default: + auth_status_failure_process(p_gap_evt); +#if PM_RA_PROTECTION_ENABLED + ast_auth_error_notify(p_gap_evt->conn_handle); +#endif // PM_RA_PROTECTION_ENABLED + break; + } +} + + +/**@brief Function for processing the @ref BLE_GAP_EVT_CONN_SEC_UPDATE event from the SoftDevice. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void conn_sec_update_process(ble_gap_evt_t const * p_gap_evt) +{ + if (!pairing(p_gap_evt->conn_handle)) + { + // This is an encryption procedure (not pairing), so this event marks the end of the procedure. + + if (!ble_conn_state_encrypted(p_gap_evt->conn_handle)) + { + encryption_failure(p_gap_evt->conn_handle, + PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING, + BLE_GAP_SEC_STATUS_SOURCE_REMOTE); + } + else + { + ble_conn_state_user_flag_set(p_gap_evt->conn_handle, m_flag_sec_proc, false); + + pm_evt_t evt; + + evt.evt_id = PM_EVT_CONN_SEC_SUCCEEDED; + evt.conn_handle = p_gap_evt->conn_handle; + evt.params.conn_sec_succeeded.procedure = PM_CONN_SEC_PROCEDURE_ENCRYPTION; + evt.params.conn_sec_succeeded.data_stored = false; + + evt_send(&evt); + } + } +} + + +/**@brief Funtion for initializing a BLE Connection State user flag. + * + * @param[out] flag_id The flag to initialize. + */ +static void flag_id_init(ble_conn_state_user_flag_id_t * p_flag_id) +{ + if (*p_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID) + { + *p_flag_id = ble_conn_state_user_flag_acquire(); + } +} + + +ret_code_t smd_init(void) +{ + NRF_PM_DEBUG_CHECK(!m_module_initialized); + + flag_id_init(&m_flag_sec_proc); + flag_id_init(&m_flag_sec_proc_pairing); + flag_id_init(&m_flag_sec_proc_bonding); + flag_id_init(&m_flag_allow_repairing); + + if ((m_flag_sec_proc == BLE_CONN_STATE_USER_FLAG_INVALID) || + (m_flag_sec_proc_pairing == BLE_CONN_STATE_USER_FLAG_INVALID) || + (m_flag_sec_proc_bonding == BLE_CONN_STATE_USER_FLAG_INVALID) || + (m_flag_allow_repairing == BLE_CONN_STATE_USER_FLAG_INVALID)) + { + NRF_LOG_ERROR("Could not acquire conn_state user flags. Increase "\ + "BLE_CONN_STATE_USER_FLAG_COUNT in the ble_conn_state module."); + return NRF_ERROR_INTERNAL; + } + +#if PM_RA_PROTECTION_ENABLED + ret_code_t err_code = ast_init(); + if (err_code != NRF_SUCCESS) + { + return err_code; + } +#endif // PM_RA_PROTECTION_ENABLED + + m_module_initialized = true; + + return NRF_SUCCESS; +} + + +/**@brief Function for putting retrieving a buffer and putting pointers into a @ref ble_gap_sec_keyset_t. + * + * @param[in] conn_handle The connection the security procedure is happening on. + * @param[in] role Our role in the connection. + * @param[in] p_public_key Pointer to a buffer holding the public key, or NULL. + * @param[out] p_sec_keyset Pointer to the keyset to be filled. + * + * @retval NRF_SUCCESS Success. + * @retval NRF_ERROR_BUSY Could not process request at this time. Reattempt later. + * @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated. + * @retval NRF_ERROR_INVALID_STATE The link is disconnected. + * @retval NRF_ERROR_INTERNAL Fatal error. + */ +static ret_code_t sec_keyset_fill(uint16_t conn_handle, + uint8_t role, + ble_gap_lesc_p256_pk_t * p_public_key, + ble_gap_sec_keyset_t * p_sec_keyset) +{ + ret_code_t err_code; + pm_peer_data_t peer_data; + + if (p_sec_keyset == NULL) + { + NRF_LOG_ERROR("Internal error: %s received NULL for p_sec_keyset.", __func__); + return NRF_ERROR_INTERNAL; + } + + // Acquire a memory buffer to receive bonding data into. + err_code = pdb_write_buf_get(PDB_TEMP_PEER_ID(conn_handle), PM_PEER_DATA_ID_BONDING, 1, &peer_data); + + if (err_code == NRF_ERROR_BUSY) + { + // No action. + } + else if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not retrieve RAM buffer for incoming bond. pdb_write_buf_get() "\ + "returned %s. conn_handle: %d", + nrf_strerror_get(err_code), + conn_handle); + err_code = NRF_ERROR_INTERNAL; + } + else /* if (err_code == NRF_SUCCESS) */ + { + memset(peer_data.p_bonding_data, 0, sizeof(pm_peer_data_bonding_t)); + + peer_data.p_bonding_data->own_role = role; + + p_sec_keyset->keys_own.p_enc_key = &peer_data.p_bonding_data->own_ltk; + p_sec_keyset->keys_own.p_pk = p_public_key; + p_sec_keyset->keys_peer.p_enc_key = &peer_data.p_bonding_data->peer_ltk; + p_sec_keyset->keys_peer.p_id_key = &peer_data.p_bonding_data->peer_ble_id; + p_sec_keyset->keys_peer.p_pk = &m_peer_pk; + + // Retrieve the address the peer used during connection establishment. + // This address will be overwritten if ID is shared. Should not fail. + err_code = im_ble_addr_get(conn_handle, &peer_data.p_bonding_data->peer_ble_id.id_addr_info); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_WARNING("im_ble_addr_get() returned %s. conn_handle: %d. Link was likely disconnected.", + nrf_strerror_get(err_code), + conn_handle); + return NRF_ERROR_INVALID_STATE; + } + } + + return err_code; +} + + +ret_code_t smd_params_reply(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + ble_gap_lesc_p256_pk_t * p_public_key) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + uint8_t role = ble_conn_state_role(conn_handle); + ret_code_t err_code = NRF_SUCCESS; + uint8_t sec_status = BLE_GAP_SEC_STATUS_SUCCESS; + ble_gap_sec_keyset_t sec_keyset; + + memset(&sec_keyset, 0, sizeof(ble_gap_sec_keyset_t)); +#ifdef BLE_GAP_ROLE_PERIPH + if (role == BLE_GAP_ROLE_PERIPH) + { + // Set the default value for allowing repairing at the start of the sec proc. (for peripheral) + ble_conn_state_user_flag_set(conn_handle, m_flag_allow_repairing, false); + } +#endif // BLE_GAP_ROLE_PERIPH + + if (role == BLE_GAP_ROLE_INVALID) + { + return BLE_ERROR_INVALID_CONN_HANDLE; + } + +#if PM_RA_PROTECTION_ENABLED + if (ast_peer_blacklisted(conn_handle)) //Check for repeated attempts here. + { + sec_status = BLE_GAP_SEC_STATUS_REPEATED_ATTEMPTS; + } + else +#endif // PM_RA_PROTECTION_ENABLED + if (p_sec_params == NULL) + { + // NULL params means reject pairing. + sec_status = BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP; + } + else + { +#ifdef BLE_GAP_ROLE_PERIPH + if ((im_peer_id_get_by_conn_handle(conn_handle) != PM_PEER_ID_INVALID) && + (role == BLE_GAP_ROLE_PERIPH) && + !allow_repairing(conn_handle)) + { + // Bond already exists. Reject the pairing request if the user doesn't intervene. + send_config_req(conn_handle); + if (!allow_repairing(conn_handle)) + { + // Reject pairing. + sec_status = BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP; + } + } +#endif // BLE_GAP_ROLE_PERIPH + + if (!p_sec_params->bond) + { + // Pairing, no bonding. + sec_keyset.keys_own.p_pk = p_public_key; + sec_keyset.keys_peer.p_pk = &m_peer_pk; + } + else if (sec_status != BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP) + { + // Bonding is to be performed, prepare to receive bonding data. + err_code = sec_keyset_fill(conn_handle, role, p_public_key, &sec_keyset); + } + } + + if (err_code == NRF_SUCCESS) + { + // Everything OK, reply to SoftDevice. If an error happened, the user is given an + // opportunity to change the parameters and retry the call. + + ble_gap_sec_params_t * p_aux_sec_params = NULL; +#ifdef BLE_GAP_ROLE_PERIPH + p_aux_sec_params = (role == BLE_GAP_ROLE_PERIPH) ? p_sec_params : NULL; +#endif // BLE_GAP_ROLE_PERIPH + + err_code = sd_ble_gap_sec_params_reply(conn_handle, sec_status, p_aux_sec_params, &sec_keyset); + } + + return err_code; +} + + +/**@brief Function for initiating pairing as a central, or all security as a periheral. + * + * See @ref smd_link_secure and @ref sd_ble_gap_authenticate for more information. + */ +static ret_code_t link_secure_authenticate(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params) +{ + ret_code_t err_code = sd_ble_gap_authenticate(conn_handle, p_sec_params); + + if (err_code == NRF_ERROR_NO_MEM) + { + // sd_ble_gap_authenticate() returned NRF_ERROR_NO_MEM. Too many other sec procedures running. + err_code = NRF_ERROR_BUSY; + } + + return err_code; +} + + +#if PM_CENTRAL_ENABLED +/**@brief Function for initiating encryption as a central. See @ref smd_link_secure for more info. + */ +static ret_code_t link_secure_central_encryption(uint16_t conn_handle, + pm_peer_id_t peer_id) +{ + pm_peer_data_flash_t peer_data; + ret_code_t err_code; + ble_gap_enc_key_t const * p_existing_key = NULL; + bool lesc = false; + + err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_BONDING, &peer_data); + + if (err_code == NRF_SUCCESS) + { + // Use peer's key since they are peripheral. + p_existing_key = &(peer_data.p_bonding_data->peer_ltk); + + lesc = peer_data.p_bonding_data->own_ltk.enc_info.lesc; + if (lesc) // LESC was used during bonding. + { + // For LESC, always use own key. + p_existing_key = &(peer_data.p_bonding_data->own_ltk); + } + } + + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_NOT_FOUND)) + { + if (err_code != NRF_ERROR_BUSY) + { + NRF_LOG_ERROR("Could not retrieve stored bond. pdb_peer_data_ptr_get() returned %s. "\ + "peer_id: %d", + nrf_strerror_get(err_code), + peer_id); + err_code = NRF_ERROR_INTERNAL; + } + } + else if (p_existing_key == NULL) /* There is no bonding data stored. This means that a bonding + procedure is in ongoing, or that the records in flash are + in a bad state. */ + { + err_code = NRF_ERROR_BUSY; + } + else if (!lesc && !im_master_id_is_valid(&(p_existing_key->master_id))) /* There is no valid LTK stored. */ + { + // No LTK to encrypt with. + err_code = NRF_ERROR_INVALID_DATA; + } + else + { + // Encrypt with existing LTK. + err_code = sd_ble_gap_encrypt(conn_handle, + &(p_existing_key->master_id), + &(p_existing_key->enc_info)); + } + + sec_proc_start(conn_handle, err_code == NRF_SUCCESS, PM_CONN_SEC_PROCEDURE_ENCRYPTION); + + return err_code; +} + + +/**@brief Function for intiating security as a central. See @ref smd_link_secure for more info. + */ +static ret_code_t link_secure_central(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + bool force_repairing) +{ + ret_code_t err_code; + pm_peer_id_t peer_id; + + if (p_sec_params == NULL) + { + return link_secure_authenticate(conn_handle, NULL); + } + + // Set the default value for allowing repairing at the start of the sec proc. (for central) + ble_conn_state_user_flag_set(conn_handle, m_flag_allow_repairing, force_repairing); + + peer_id = im_peer_id_get_by_conn_handle(conn_handle); + + if ((peer_id != PM_PEER_ID_INVALID) && !force_repairing) + { + // There is already data in flash for this peer, and repairing has not been requested, so + // the link will be encrypted with the existing keys. + err_code = link_secure_central_encryption(conn_handle, peer_id); + } + else + { + // There are no existing keys, or repairing has been explicitly requested, so pairing + // (possibly including bonding) will be performed to encrypt the link. + err_code = link_secure_authenticate(conn_handle, p_sec_params); + pm_conn_sec_procedure_t procedure = (p_sec_params && p_sec_params->bond) ? + PM_CONN_SEC_PROCEDURE_BONDING : + PM_CONN_SEC_PROCEDURE_PAIRING; + sec_proc_start(conn_handle, err_code == NRF_SUCCESS, procedure); + } + + return err_code; +} + +/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_REQUEST event from the SoftDevice. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void sec_request_process(ble_gap_evt_t const * p_gap_evt) +{ + if (sec_procedure(p_gap_evt->conn_handle)) + { + // Ignore request as per spec. + return; + } + + pm_evt_t evt = + { + .evt_id = PM_EVT_SLAVE_SECURITY_REQ, + .conn_handle = p_gap_evt->conn_handle + }; + memcpy(&evt.params.slave_security_req, &p_gap_evt->params.sec_request, sizeof(ble_gap_evt_sec_request_t)); + + evt_send(&evt); + return; +} +#endif // PM_CENTRAL_ENABLED + + +#ifdef BLE_GAP_ROLE_PERIPH +/**@brief Function for asking the central to secure the link. See @ref smd_link_secure for more info. + */ +static ret_code_t link_secure_peripheral(uint16_t conn_handle, ble_gap_sec_params_t * p_sec_params) +{ + ret_code_t err_code = NRF_SUCCESS; + + if (p_sec_params != NULL) + { + err_code = link_secure_authenticate(conn_handle, p_sec_params); + } + + return err_code; +} +#endif + + +ret_code_t smd_link_secure(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + bool force_repairing) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + uint8_t role = ble_conn_state_role(conn_handle); + + switch (role) + { +#if PM_CENTRAL_ENABLED + case BLE_GAP_ROLE_CENTRAL: + return link_secure_central(conn_handle, p_sec_params, force_repairing); +#endif + +#ifdef BLE_GAP_ROLE_PERIPH + case BLE_GAP_ROLE_PERIPH: + return link_secure_peripheral(conn_handle, p_sec_params); +#endif // BLE_GAP_ROLE_PERIPH + + default: + return BLE_ERROR_INVALID_CONN_HANDLE; + } +} + + +void smd_ble_evt_handler(ble_evt_t const * p_ble_evt) +{ + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_DISCONNECTED: + disconnect_process(&(p_ble_evt->evt.gap_evt)); + break; + + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: + sec_params_request_process(&(p_ble_evt->evt.gap_evt)); + break; + +#ifdef BLE_GAP_ROLE_PERIPH + case BLE_GAP_EVT_SEC_INFO_REQUEST: + sec_info_request_process(&(p_ble_evt->evt.gap_evt)); + break; +#endif // BLE_GAP_ROLE_PERIPH + +#if PM_CENTRAL_ENABLED + case BLE_GAP_EVT_SEC_REQUEST: + sec_request_process(&(p_ble_evt->evt.gap_evt)); + //printf("rebonds"); not affect this setting.2024.03.02 + break; +#endif + + case BLE_GAP_EVT_AUTH_STATUS: + auth_status_process(&(p_ble_evt->evt.gap_evt)); + break; + + case BLE_GAP_EVT_CONN_SEC_UPDATE: + conn_sec_update_process(&(p_ble_evt->evt.gap_evt)); + break; + }; +} +#endif //NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/components/ble/peer_manager/security_dispatcher.h b/components/ble/peer_manager/security_dispatcher.h new file mode 100644 index 0000000..4aab6d4 --- /dev/null +++ b/components/ble/peer_manager/security_dispatcher.h @@ -0,0 +1,162 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef SECURITY_DISPATCHER_H__ +#define SECURITY_DISPATCHER_H__ + +#include +#include "sdk_errors.h" +#include "ble.h" +#include "ble_gap.h" +#include "peer_manager_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @defgroup security_dispatcher Security Dispatcher + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. A module for streamlining pairing, bonding, and + * encryption, including flash storage of shared data. + * + */ + + +/**@brief Function for initializing the Security Dispatcher module. + * + * @retval NRF_SUCCESS Initialization was successful. + * @retval NRF_ERROR_INTERNAL An unexpected fatal error occurred. + */ +ret_code_t smd_init(void); + + +/**@brief Function for dispatching SoftDevice events to the Security Dispatcher module. + * + * @param[in] ble_evt The SoftDevice event. + */ +void smd_ble_evt_handler(ble_evt_t const * ble_evt); + + +/**@brief Function for providing security configuration for a link. + * + * @details This function is optional, and must be called in reply to a @ref + * PM_EVT_CONN_SEC_CONFIG_REQ event, before the Peer Manager event handler returns. If it + * is not called in time, a default configuration is used. See @ref pm_conn_sec_config_t + * for the value of the default. + * + * @param[in] conn_handle The connection to set the configuration for. + * @param[in] p_conn_sec_config The configuration. + */ +void smd_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config); + + +/**@brief Function for providing pairing and bonding parameters to use for the current pairing + * procedure on a connection. + * + * @note If this function returns an @ref NRF_ERROR_NULL, @ref NRF_ERROR_INVALID_PARAM, @ref + * BLE_ERROR_INVALID_CONN_HANDLE, or @ref NRF_ERROR_STORAGE_FULL, this function can be called + * again after corrective action. + * + * @note To reject a request, call this function with NULL p_sec_params. + * + * @param[in] conn_handle The connection handle of the connection the pairing is happening on. + * @param[in] p_sec_params The security parameters to use for this link. + * @param[in] p_public_key A pointer to the public key to use if using LESC, or NULL. + * + * @retval NRF_SUCCESS Success. + * @retval NRF_ERROR_INVALID_STATE No parameters have been requested on that conn_handle, or + * the link is disconnecting. + * @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters (not including conn_handle). + * @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations + * can be performed on this link. + * @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle. + * @retval NRF_ERROR_BUSY No write buffer. Reattempt later. + * @retval NRF_ERROR_INTERNAL A fatal error occurred. + */ +ret_code_t smd_params_reply(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + ble_gap_lesc_p256_pk_t * p_public_key); + + +/**@brief Function for initiating security on the link, with the specified parameters. + * + * @note If the connection is a peripheral connection, this will send a security request to the + * master, but the master is not obligated to initiate pairing or encryption in response. + * @note If the connection is a central connection and a key is available, the parameters will be + * used to determine whether to re-pair or to encrypt using the existing key. If no key is + * available, pairing will be started. + * + * @param[in] conn_handle Handle of the connection to initiate pairing on. + * @param[in] p_sec_params The security parameters to use for this link. As a central, this can + * be NULL to reject a slave security request. + * @param[in] force_repairing Whether to force a pairing procedure to happen regardless of whether + * an encryption key already exists. This argument is only relevant for + * the central role. Recommended value: false + * + * @retval NRF_SUCCESS Success. + * @retval NRF_ERROR_NULL p_sec_params was NULL (peripheral only). + * @retval NRF_ERROR_INVALID_STATE A security procedure is already in progress on the link, + * or the link is disconnecting. + * @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters (not including conn_handle). + * @retval NRF_ERROR_INVALID_DATA Peer is bonded, but no LTK was found, and repairing was + * not requested. + * @retval NRF_ERROR_BUSY Unable to initiate procedure at this time. + * @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations + * can be performed on this link. + * @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle. + * @retval NRF_ERROR_INTERNAL No more available peer IDs. + */ +ret_code_t smd_link_secure(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + bool force_repairing); + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* SECURITY_DISPATCHER_H__ */ diff --git a/components/ble/peer_manager/security_manager.c b/components/ble/peer_manager/security_manager.c new file mode 100644 index 0000000..beac731 --- /dev/null +++ b/components/ble/peer_manager/security_manager.c @@ -0,0 +1,769 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(PEER_MANAGER) +#include "security_manager.h" + +#include +#include "ble_err.h" +#include "security_dispatcher.h" +#include "peer_database.h" +#include "ble_conn_state.h" +#include "id_manager.h" +#include "sdk_common.h" + +#if PM_LESC_ENABLED +#include "nrf_ble_lesc.h" +#endif +#define NRF_LOG_MODULE_NAME peer_manager_sm +#if PM_LOG_ENABLED + #define NRF_LOG_LEVEL PM_LOG_LEVEL + #define NRF_LOG_INFO_COLOR PM_LOG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR PM_LOG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // PM_LOG_ENABLED +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +NRF_LOG_MODULE_REGISTER(); +#include "nrf_strerror.h" + + +// The number of registered event handlers. +#define SM_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) + + +// Security Manager event handler in Peer Manager. +extern void pm_sm_evt_handler(pm_evt_t * p_sm_evt); + +// Security Manager events' handlers. +// The number of elements in this array is SM_EVENT_HANDLERS_CNT. +static pm_evt_handler_internal_t const m_evt_handlers[] = +{ + pm_sm_evt_handler +}; + + +// The context type that is used in PM_EVT_CONN_SEC_PARAMS_REQ events and in calls to sm_sec_params_reply(). +typedef struct +{ + ble_gap_sec_params_t * p_sec_params; //!< The security parameters to use in the call to the security_dispatcher + ble_gap_sec_params_t sec_params_mem; //!< The buffer for holding the security parameters. + bool params_reply_called; //!< Whether @ref sm_sec_params_reply has been called for this context instance. +} sec_params_reply_context_t; + +static bool m_module_initialized; //!< Whether the Security Manager module has been initialized. + +static ble_gap_sec_params_t m_sec_params; //!< The buffer for the default security parameters set by @ref sm_sec_params_set. +static ble_gap_sec_params_t * mp_sec_params = NULL; //!< The default security parameters set by @ref sm_sec_params_set. +static bool m_sec_params_set = false; //!< Whether @ref sm_sec_params_set has been called. + +#if PM_LESC_ENABLED == 0 +static ble_gap_lesc_p256_pk_t * m_p_public_key; //!< Pointer, provided by the user, to the public key to use for LESC procedures. +#endif + +static ble_conn_state_user_flag_id_t m_flag_link_secure_pending_busy = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a connection has a pending call to @ref sm_link_secure because it returned @ref NRF_ERROR_BUSY. +static ble_conn_state_user_flag_id_t m_flag_link_secure_force_repairing = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a pending call to @ref sm_link_secure should be called with true for the force_repairing parameter. +static ble_conn_state_user_flag_id_t m_flag_link_secure_null_params = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a pending call to @ref sm_link_secure should be called with NULL security parameters. +static ble_conn_state_user_flag_id_t m_flag_params_reply_pending_busy = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a connection has a pending call to @ref sm_sec_params_reply because it returned @ref NRF_ERROR_BUSY. + + +/**@brief Function for sending an SM event to all registered event handlers. + * + * @param[in] p_event The event to send. + */ +static void evt_send(pm_evt_t * p_event) +{ + for (uint32_t i = 0; i < SM_EVENT_HANDLERS_CNT; i++) + { + m_evt_handlers[i](p_event); + } +} + + +/**@brief Function for setting or clearing user flags based on error codes returned from @ref + * smd_link_secure or @ref smd_params_reply. + * + * @param[in] conn_handle The connection the call pertained to. + * @param[in] err_code The error code returned from @ref smd_link_secure or + * @ref smd_params_reply. + * @param[in] params_reply Whether the call was to @ref smd_params_reply. + */ +static void flags_set_from_err_code(uint16_t conn_handle, ret_code_t err_code, bool params_reply) +{ + bool flag_value_busy = false; + + if (err_code == NRF_ERROR_BUSY) + { + flag_value_busy = true; + } + else + { + flag_value_busy = false; + } + + if (params_reply) + { + ble_conn_state_user_flag_set(conn_handle, + m_flag_params_reply_pending_busy, + flag_value_busy); + ble_conn_state_user_flag_set(conn_handle, + m_flag_link_secure_pending_busy, + false); + } + else + { + ble_conn_state_user_flag_set(conn_handle, + m_flag_link_secure_pending_busy, + flag_value_busy); + } +} + + +static inline pm_evt_t new_evt(pm_evt_id_t evt_id, uint16_t conn_handle) +{ + pm_evt_t evt = + { + .evt_id = evt_id, + .conn_handle = conn_handle, + .peer_id = im_peer_id_get_by_conn_handle(conn_handle) + }; + return evt; +} + + +/**@brief Function for sending a PM_EVT_ERROR_UNEXPECTED event. + * + * @param[in] conn_handle The connection handle the event pertains to. + * @param[in] err_code The unexpected error that occurred. + */ +static void send_unexpected_error(uint16_t conn_handle, ret_code_t err_code) +{ + pm_evt_t error_evt = new_evt(PM_EVT_ERROR_UNEXPECTED, conn_handle); + error_evt.params.error_unexpected.error = err_code; + evt_send(&error_evt); +} + + +/**@brief Returns whether the LTK came from LESC bonding. + * + * @param[in] peer_id The peer to check. + * + * @return Whether the key is LESC or not. + */ +static bool key_is_lesc(pm_peer_id_t peer_id) +{ + pm_peer_data_flash_t peer_data; + ret_code_t err_code; + + err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_BONDING, &peer_data); + + return (err_code == NRF_SUCCESS) && (peer_data.p_bonding_data->own_ltk.enc_info.lesc); +} + + +/**@brief Function for sending an event based on error codes returned from @ref smd_link_secure or + * @ref smd_params_reply. + * + * @param[in] conn_handle The connection the event pertains to. + * @param[in] err_code The error code returned from @ref smd_link_secure or + * @ref smd_params_reply. + * @param[in] p_sec_params The security parameters attempted to pass in the call to + * @ref smd_link_secure or @ref smd_params_reply. + */ +static void events_send_from_err_code(uint16_t conn_handle, + ret_code_t err_code, + ble_gap_sec_params_t * p_sec_params) +{ + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY) && (err_code != NRF_ERROR_INVALID_STATE)) + { + if (err_code == NRF_ERROR_TIMEOUT) + { + NRF_LOG_WARNING("Cannot secure link because a previous security procedure ended in timeout. "\ + "Disconnect and retry. smd_params_reply() or smd_link_secure() returned "\ + "NRF_ERROR_TIMEOUT. conn_handle: %d", + conn_handle); + + pm_evt_t evt = new_evt(PM_EVT_CONN_SEC_FAILED, conn_handle); + evt.params.conn_sec_failed.procedure = ((p_sec_params != NULL) && p_sec_params->bond) + ? PM_CONN_SEC_PROCEDURE_BONDING + : PM_CONN_SEC_PROCEDURE_PAIRING; + evt.params.conn_sec_failed.error_src = BLE_GAP_SEC_STATUS_SOURCE_LOCAL; + evt.params.conn_sec_failed.error = PM_CONN_SEC_ERROR_SMP_TIMEOUT; + evt_send(&evt); + } + else + { + NRF_LOG_ERROR("Could not perform security procedure. smd_params_reply() or "\ + "smd_link_secure() returned %s. conn_handle: %d", + nrf_strerror_get(err_code), + conn_handle); + send_unexpected_error(conn_handle, err_code); + } + } +} + + +/**@brief Function for sending an PM_EVT_CONN_SEC_PARAMS_REQ event. + * + * @param[in] conn_handle The connection the event pertains to. + * @param[in] p_peer_params The peer's security parameters to include in the event. Can be NULL. + * @param[in] p_context Pointer to a context that the user must include in the call to @ref + * sm_sec_params_reply(). + */ +static void params_req_send(uint16_t conn_handle, + ble_gap_sec_params_t const * p_peer_params, + sec_params_reply_context_t * p_context) +{ + pm_evt_t evt = new_evt(PM_EVT_CONN_SEC_PARAMS_REQ, conn_handle); + evt.params.conn_sec_params_req.p_peer_params = p_peer_params; + evt.params.conn_sec_params_req.p_context = p_context; + + evt_send(&evt); +} + + +/**@brief Function for creating a new @ref sec_params_reply_context_t with the correct initial values. + * + * @return The new context. + */ +static sec_params_reply_context_t new_context_get(void) +{ + sec_params_reply_context_t new_context = + { + .p_sec_params = mp_sec_params, + .params_reply_called = false + }; + return new_context; +} + + +/**@brief Internal function corresponding to @ref sm_link_secure. + * + * @param[in] conn_handle The connection to secure. + * @param[in] null_params Whether to pass NULL security parameters to the security_dispatcher. + * @param[in] force_repairing Whether to force rebonding if peer exists. + * @param[in] send_events Whether to send events based on the result of @ref smd_link_secure. + * + * @return Same return codes as @ref sm_link_secure. + */ +static ret_code_t link_secure(uint16_t conn_handle, + bool null_params, + bool force_repairing, + bool send_events) +{ + ret_code_t err_code; + ret_code_t return_err_code; + ble_gap_sec_params_t * p_sec_params; + + if (null_params) + { + p_sec_params = NULL; + } + else + { + sec_params_reply_context_t context = new_context_get(); + params_req_send(conn_handle, NULL, &context); + p_sec_params = context.p_sec_params; + + if (!m_sec_params_set && !context.params_reply_called) + { + // Security parameters have not been set. + return NRF_ERROR_NOT_FOUND; + } + } + + + err_code = smd_link_secure(conn_handle, p_sec_params, force_repairing); + + flags_set_from_err_code(conn_handle, err_code, false); + + switch (err_code) + { + case NRF_ERROR_BUSY: + ble_conn_state_user_flag_set(conn_handle, m_flag_link_secure_null_params, null_params); + ble_conn_state_user_flag_set(conn_handle, m_flag_link_secure_force_repairing, force_repairing); + return_err_code = NRF_SUCCESS; + break; + case NRF_SUCCESS: + case NRF_ERROR_TIMEOUT: + case BLE_ERROR_INVALID_CONN_HANDLE: + case NRF_ERROR_INVALID_STATE: + case NRF_ERROR_INVALID_DATA: + return_err_code = err_code; + break; + default: + NRF_LOG_ERROR("Could not perform security procedure. smd_link_secure() returned %s. "\ + "conn_handle: %d", + nrf_strerror_get(err_code), + conn_handle); + return_err_code = NRF_ERROR_INTERNAL; + break; + } + + if (send_events) + { + events_send_from_err_code(conn_handle, err_code, p_sec_params); + } + + return return_err_code; +} + + +/**@brief Function for requesting security parameters from the user and passing them to the security_dispatcher. + * + * @param[in] conn_handle The connection that needs security parameters. + * @param[in] p_peer_params The peer's security parameters if present. Otherwise NULL. + */ +static void smd_params_reply_perform(uint16_t conn_handle, ble_gap_sec_params_t const * p_peer_params) +{ + ret_code_t err_code; + ble_gap_lesc_p256_pk_t * p_public_key; + sec_params_reply_context_t context = new_context_get(); + + params_req_send(conn_handle, p_peer_params, &context); + +#if PM_LESC_ENABLED + p_public_key = nrf_ble_lesc_public_key_get(); +#else + p_public_key = m_p_public_key; +#endif // PM_LESC_ENABLED + err_code = smd_params_reply(conn_handle, context.p_sec_params, p_public_key); + + flags_set_from_err_code(conn_handle, err_code, true); + events_send_from_err_code(conn_handle, err_code, context.p_sec_params); +} + + +/**@brief Function for handling @ref PM_EVT_CONN_SEC_PARAMS_REQ events. + * + * @param[in] p_event The @ref PM_EVT_CONN_SEC_PARAMS_REQ event. + */ +static __INLINE void params_req_process(pm_evt_t const * p_event) +{ + smd_params_reply_perform(p_event->conn_handle, p_event->params.conn_sec_params_req.p_peer_params); +} + + +ret_code_t sm_conn_sec_status_get(uint16_t conn_handle, pm_conn_sec_status_t * p_conn_sec_status) +{ + VERIFY_PARAM_NOT_NULL(p_conn_sec_status); + + ble_conn_state_status_t status = ble_conn_state_status(conn_handle); + + if (status == BLE_CONN_STATUS_INVALID) + { + return BLE_ERROR_INVALID_CONN_HANDLE; + } + + pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); + + p_conn_sec_status->connected = (status == BLE_CONN_STATUS_CONNECTED); + p_conn_sec_status->bonded = (peer_id != PM_PEER_ID_INVALID); + p_conn_sec_status->encrypted = ble_conn_state_encrypted(conn_handle); + p_conn_sec_status->mitm_protected = ble_conn_state_mitm_protected(conn_handle); + p_conn_sec_status->lesc = ble_conn_state_lesc(conn_handle) + || (ble_conn_state_encrypted(conn_handle) + && key_is_lesc(peer_id)); + return NRF_SUCCESS; +} + + +bool sm_sec_is_sufficient(uint16_t conn_handle, pm_conn_sec_status_t * p_sec_status_req) +{ + pm_conn_sec_status_t sec_status = {.reserved = ~0}; // Set all bits in reserved to 1 so they are + // ignored in subsequent logic. + ret_code_t err_code = sm_conn_sec_status_get(conn_handle, &sec_status); + + STATIC_ASSERT(sizeof(pm_conn_sec_status_t) == sizeof(uint8_t)); + + uint8_t unmet_reqs = (~(*((uint8_t *) &sec_status)) & *((uint8_t *) p_sec_status_req)); + + return (err_code == NRF_SUCCESS) && !unmet_reqs; +} + + +/**@brief Function for handling @ref PM_EVT_SLAVE_SECURITY_REQ events. + * + * @param[in] p_event The @ref PM_EVT_SLAVE_SECURITY_REQ event. + */ +static void sec_req_process(pm_evt_t const * p_event) +{ + ret_code_t err_code; + bool null_params = false; + bool force_repairing = false; + + if (mp_sec_params == NULL) + { + null_params = true; + } + else if (ble_conn_state_encrypted(p_event->conn_handle)) + { + pm_conn_sec_status_t sec_status_req = + { + .bonded = p_event->params.slave_security_req.bond, + .mitm_protected = p_event->params.slave_security_req.mitm, + .lesc = p_event->params.slave_security_req.lesc, + }; + + force_repairing = !sm_sec_is_sufficient(p_event->conn_handle, &sec_status_req); + } + + err_code = link_secure(p_event->conn_handle, null_params, force_repairing, true); + UNUSED_VARIABLE(err_code); // The error code has been properly handled inside link_secure(). +} + + +/**@brief Function for translating an SMD event to an SM event and passing it on to SM event handlers. + * + * @param[in] p_event The event to forward. + */ +static void evt_forward(pm_evt_t * p_event) +{ + evt_send(p_event); +} + + +/**@brief Event handler for events from the Security Dispatcher module. + * This handler is extern in Security Dispatcher. + * + * @param[in] p_event The event that has happened. + */ +void sm_smd_evt_handler(pm_evt_t * p_event) +{ + switch (p_event->evt_id) + { + case PM_EVT_CONN_SEC_PARAMS_REQ: + params_req_process(p_event); + break; + case PM_EVT_SLAVE_SECURITY_REQ: + sec_req_process(p_event); + /* fallthrough */ + default: + // Forward the event to all registered Security Manager event handlers. + evt_forward(p_event); + break; + } +} + + +/**@brief Function handling a pending params_reply. See @ref ble_conn_state_user_function_t. + */ +static void params_reply_pending_handle(uint16_t conn_handle, void * p_context) +{ + UNUSED_PARAMETER(p_context); + smd_params_reply_perform(conn_handle, NULL); +} + + +/**@brief Function handling a pending link_secure. See @ref ble_conn_state_user_function_t. + */ +static void link_secure_pending_handle(uint16_t conn_handle, void * p_context) +{ + UNUSED_PARAMETER(p_context); + + bool force_repairing = ble_conn_state_user_flag_get(conn_handle, m_flag_link_secure_force_repairing); + bool null_params = ble_conn_state_user_flag_get(conn_handle, m_flag_link_secure_null_params); + + // If this fails, it will be automatically retried. + ret_code_t err_code = link_secure(conn_handle, null_params, force_repairing, true); + UNUSED_VARIABLE(err_code); +} + + +/**@brief Event handler for events from the Peer Database module. + * This handler is extern in Peer Database. + * + * @param[in] p_event The event that has happened. + */ +void sm_pdb_evt_handler(pm_evt_t * p_event) +{ + switch (p_event->evt_id) + { + case PM_EVT_FLASH_GARBAGE_COLLECTED: + case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: + case PM_EVT_PEER_DATA_UPDATE_FAILED: + case PM_EVT_PEER_DELETE_SUCCEEDED: + case PM_EVT_PEER_DELETE_FAILED: + (void) ble_conn_state_for_each_set_user_flag(m_flag_params_reply_pending_busy, + params_reply_pending_handle, + NULL); + (void) ble_conn_state_for_each_set_user_flag(m_flag_link_secure_pending_busy, + link_secure_pending_handle, + NULL); + break; + default: + // Do nothing. + break; + } +} + + +/**@brief Funtion for initializing a BLE Connection State user flag. + * + * @param[out] flag_id The flag to initialize. + */ +static void flag_id_init(ble_conn_state_user_flag_id_t * p_flag_id) +{ + if (*p_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID) + { + *p_flag_id = ble_conn_state_user_flag_acquire(); + } +} + + +ret_code_t sm_init(void) +{ + NRF_PM_DEBUG_CHECK(!m_module_initialized); + +#if PM_LESC_ENABLED + ret_code_t err_code = nrf_ble_lesc_init(); + if (err_code != NRF_SUCCESS) + { + return err_code; + } +#endif + + flag_id_init(&m_flag_link_secure_pending_busy); + flag_id_init(&m_flag_link_secure_force_repairing); + flag_id_init(&m_flag_link_secure_null_params); + flag_id_init(&m_flag_params_reply_pending_busy); + + if (m_flag_params_reply_pending_busy == BLE_CONN_STATE_USER_FLAG_INVALID) + { + NRF_LOG_ERROR("Could not acquire conn_state user flags. Increase "\ + "BLE_CONN_STATE_USER_FLAG_COUNT in the ble_conn_state module."); + return NRF_ERROR_INTERNAL; + } + + m_module_initialized = true; + + return NRF_SUCCESS; +} + + +void sm_ble_evt_handler(ble_evt_t const * p_ble_evt) +{ + NRF_PM_DEBUG_CHECK(p_ble_evt != NULL); + + smd_ble_evt_handler(p_ble_evt); +#if PM_LESC_ENABLED + nrf_ble_lesc_on_ble_evt(p_ble_evt); +#endif + (void) ble_conn_state_for_each_set_user_flag(m_flag_params_reply_pending_busy, + params_reply_pending_handle, + NULL); + (void) ble_conn_state_for_each_set_user_flag(m_flag_link_secure_pending_busy, + link_secure_pending_handle, + NULL); +} + + +/**@brief Funtion for checking whether security parameters are valid. + * + * @param[out] p_sec_params The security parameters to verify. + * + * @return Whether the security parameters are valid. + */ +static bool sec_params_verify(ble_gap_sec_params_t * p_sec_params) +{ + // NULL check. + if (p_sec_params == NULL) + { + return false; + } + + // OOB not allowed unless MITM. + if (!p_sec_params->mitm && p_sec_params->oob) + { + return false; + } + + // IO Capabilities must be one of the valid values from @ref BLE_GAP_IO_CAPS. + if (p_sec_params->io_caps > BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY) + { + return false; + } + + // Must have either IO capabilities or OOB if MITM. + if (p_sec_params->mitm && (p_sec_params->io_caps == BLE_GAP_IO_CAPS_NONE) && !p_sec_params->oob) + { + return false; + } + + // Minimum key size cannot be larger than maximum key size. + if (p_sec_params->min_key_size > p_sec_params->max_key_size) + { + return false; + } + + // Key size cannot be below 7 bytes. + if (p_sec_params->min_key_size < 7) + { + return false; + } + + // Key size cannot be above 16 bytes. + if (p_sec_params->max_key_size > 16) + { + return false; + } + + // Signing is not supported. + if (p_sec_params->kdist_own.sign || p_sec_params->kdist_peer.sign) + { + return false; + } + + // link bit must be 0. + if (p_sec_params->kdist_own.link || p_sec_params->kdist_peer.link) + { + return false; + } + + // If bonding is not enabled, no keys can be distributed. + if (!p_sec_params->bond && ( p_sec_params->kdist_own.enc + || p_sec_params->kdist_own.id + || p_sec_params->kdist_peer.enc + || p_sec_params->kdist_peer.id)) + { + return false; + } + + // If bonding is enabled, one or more keys must be distributed. + if ( p_sec_params->bond + && !p_sec_params->kdist_own.enc + && !p_sec_params->kdist_own.id + && !p_sec_params->kdist_peer.enc + && !p_sec_params->kdist_peer.id) + { + return false; + } + + return true; +} + + +ret_code_t sm_sec_params_set(ble_gap_sec_params_t * p_sec_params) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + if (p_sec_params == NULL) + { + mp_sec_params = NULL; + m_sec_params_set = true; + return NRF_SUCCESS; + } + else if (sec_params_verify(p_sec_params)) + { + m_sec_params = *p_sec_params; + mp_sec_params = &m_sec_params; + m_sec_params_set = true; + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_INVALID_PARAM; + } +} + + +void sm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_conn_sec_config != NULL); + + smd_conn_sec_config_reply(conn_handle, p_conn_sec_config); +} + + +ret_code_t sm_sec_params_reply(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + void const * p_context) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + VERIFY_PARAM_NOT_NULL(p_context); + + sec_params_reply_context_t * p_sec_params_reply_context = (sec_params_reply_context_t *)p_context; + if (p_sec_params == NULL) + { + // Set the store pointer to NULL, so that NULL is passed to the SoftDevice. + p_sec_params_reply_context->p_sec_params = NULL; + } + else if (sec_params_verify(p_sec_params)) + { + // Copy the provided sec_params into the store. + p_sec_params_reply_context->sec_params_mem = *p_sec_params; + p_sec_params_reply_context->p_sec_params = &p_sec_params_reply_context->sec_params_mem; + } + else + { + return NRF_ERROR_INVALID_PARAM; + } + p_sec_params_reply_context->params_reply_called = true; + + return NRF_SUCCESS; +} + + +ret_code_t sm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + +#if PM_LESC_ENABLED + return NRF_ERROR_FORBIDDEN; +#else + m_p_public_key = p_public_key; + + return NRF_SUCCESS; +#endif // PM_LESC_ENABLED +} + + +ret_code_t sm_link_secure(uint16_t conn_handle, bool force_repairing) +{ + ret_code_t ret; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + + ret = link_secure(conn_handle, false, force_repairing, false); + return ret; +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/components/ble/peer_manager/security_manager.h b/components/ble/peer_manager/security_manager.h new file mode 100644 index 0000000..270c4c3 --- /dev/null +++ b/components/ble/peer_manager/security_manager.h @@ -0,0 +1,205 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef SECURITY_MANAGER_H__ +#define SECURITY_MANAGER_H__ + +#include +#include "sdk_errors.h" +#include "ble.h" +#include "ble_gap.h" +#include "peer_manager_types.h" +#include "security_dispatcher.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @defgroup security_manager Security Manager + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. A module for streamlining pairing, bonding, and + * encryption, including flash storage of shared data. + */ + + +/**@brief Function for initializing the Security Manager module. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. + */ +ret_code_t sm_init(void); + + +/**@brief Function for dispatching SoftDevice events to the Security Manager module. + * + * @param[in] ble_evt The SoftDevice event. + */ +void sm_ble_evt_handler(ble_evt_t const * ble_evt); + + +/**@brief Function for providing pairing and bonding parameters to use for pairing procedures. + * + * @details Until this is called, all bonding procedures initiated by the peer will be rejected. + * This function can be called multiple times, even with NULL p_sec_params, in which case + * it will go back to rejecting all procedures. + * + * @param[in] p_sec_params The security parameters to use for this link. Can be NULL to reject + * all pairing procedures. + * + * @retval NRF_SUCCESS Success. + * @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters. + */ +ret_code_t sm_sec_params_set(ble_gap_sec_params_t * p_sec_params); + + +/**@brief Function for providing security configuration for a link. + * + * @details This function is optional, and must be called in reply to a @ref + * PM_EVT_CONN_SEC_CONFIG_REQ event, before the Peer Manager event handler returns. If it + * is not called in time, a default configuration is used. See @ref pm_conn_sec_config_t + * for the value of the default. + * + * @param[in] conn_handle The connection to set the configuration for. + * @param[in] p_conn_sec_config The configuration. + */ +void sm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config); + + +/**@brief Function for providing security parameters for a link. + * + * @details This function is optional, and must be called in reply to a @ref + * PM_EVT_CONN_SEC_PARAMS_REQ event, before the Security Manager event handler returns. If + * it is not called in time, the parameters given in @ref sm_sec_params_set are used. See + * @ref pm_conn_sec_config_t for the value of the default. + * + * @param[in] conn_handle The connection to set the parameters for. + * @param[in] p_sec_params The parameters. If NULL, the security procedure is rejected. + * @param[in] p_context The context found in the request event that this function replies to. + * + * @retval NRF_SUCCESS Successful reply. + * @retval NRF_ERROR_NULL p_context was null. + * @retval NRF_ERROR_INVALID_PARAM Value of p_sec_params was invalid. + * @retval NRF_ERROR_INVALID_STATE This module is not initialized. + */ +ret_code_t sm_sec_params_reply(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + void const * p_context); + + +/**@brief Experimental function for specifying the public key to use for LESC operations. + * + * @details This function can be called multiple times. The specified public key will be used for + * all subsequent LESC (LE Secure Connections) operations until the next time this function + * is called. + * + * @note The key must continue to reside in application memory as it is not copied by Peer Manager. + * + * @param[in] p_public_key The public key to use for all subsequent LESC operations. + * + * @retval NRF_SUCCESS Pairing initiated successfully. + * @retval NRF_ERROR_INVALID_STATE This module is not initialized. + */ +ret_code_t sm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key); + + +/**@brief Function for getting the security status of a connection. + * + * @param[in] conn_handle Connection handle of the link as provided by the SoftDevice. + * @param[out] p_conn_sec_status Security status of the link. + * + * @retval NRF_SUCCESS If pairing was initiated successfully. + * @retval BLE_ERROR_INVALID_CONN_HANDLE If the connection handle is invalid. + * @retval NRF_ERROR_NULL If @p p_conn_sec_status was NULL. + */ +ret_code_t sm_conn_sec_status_get(uint16_t conn_handle, pm_conn_sec_status_t * p_conn_sec_status); + + +/**@brief Function for comparing the security status of a connection against a baseline. + * + * @param[in] conn_handle Connection handle of the link as provided by the SoftDevice. + * @param[out] p_sec_status_req Target baseline security status to compare against. + * + * @retval true If the security status of the connection matches or exceeds the baseline on all + * points. + * @retval false If the security status of the connection does not fulfill the baseline, or could + * not be retrieved. + */ +bool sm_sec_is_sufficient(uint16_t conn_handle, pm_conn_sec_status_t * p_sec_status_req); + + +/**@brief Function for initiating security on the link, with the specified parameters. + * + * @note If the connection is a peripheral connection, this will send a security request to the + * master, but the master is not obligated to initiate pairing or encryption in response. + * @note If the connection is a central connection and a key is available, the parameters will be + * used to determine whether to re-pair or to encrypt using the existing key. If no key is + * available, pairing will be started. + * + * @param[in] conn_handle Handle of the connection to initiate pairing on. + * @param[in] force_repairing Whether to force a pairing procedure to happen regardless of whether + * an encryption key already exists. This argument is only relevant for + * the central role. Recommended value: false + * + * @retval NRF_SUCCESS Success. + * @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations + * can be performed on this link. + * @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle. + * @retval NRF_ERROR_INVALID_DATA Peer is bonded, but no LTK was found, and repairing was + * not requested. + * @retval NRF_ERROR_NOT_FOUND Security parameters have not been set. + * @retval NRF_ERROR_INVALID_STATE A security procedure is already in progress on the link, + * or the link is disconnecting. + * @retval NRF_ERROR_INTERNAL An unexpected error occurred. + */ +ret_code_t sm_link_secure(uint16_t conn_handle, bool force_repairing); + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* SECURITY_MANAGER_H__ */ diff --git a/components/boards/boards.c b/components/boards/boards.c new file mode 100644 index 0000000..4fd51f0 --- /dev/null +++ b/components/boards/boards.c @@ -0,0 +1,228 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "boards.h" +#if defined(BOARDS_WITH_USB_DFU_TRIGGER) && defined(BOARD_PCA10059) +#include "nrf_dfu_trigger_usb.h" +#endif +#include +#include + +#if LEDS_NUMBER > 0 +static const uint8_t m_board_led_list[LEDS_NUMBER] = LEDS_LIST; +#endif + +#if BUTTONS_NUMBER > 0 +static const uint8_t m_board_btn_list[BUTTONS_NUMBER] = BUTTONS_LIST; +#endif + +#if LEDS_NUMBER > 0 +bool bsp_board_led_state_get(uint32_t led_idx) +{ + ASSERT(led_idx < LEDS_NUMBER); + bool pin_set = nrf_gpio_pin_out_read(m_board_led_list[led_idx]) ? true : false; + return (pin_set == (LEDS_ACTIVE_STATE ? true : false)); +} + +void bsp_board_led_on(uint32_t led_idx) +{ + ASSERT(led_idx < LEDS_NUMBER); + nrf_gpio_pin_write(m_board_led_list[led_idx], LEDS_ACTIVE_STATE ? 1 : 0); +} + +void bsp_board_led_off(uint32_t led_idx) +{ + ASSERT(led_idx < LEDS_NUMBER); + nrf_gpio_pin_write(m_board_led_list[led_idx], LEDS_ACTIVE_STATE ? 0 : 1); +} + +void bsp_board_leds_off(void) +{ + uint32_t i; + for (i = 0; i < LEDS_NUMBER; ++i) + { + bsp_board_led_off(i); + } +} + +void bsp_board_leds_on(void) +{ + uint32_t i; + for (i = 0; i < LEDS_NUMBER; ++i) + { + bsp_board_led_on(i); + } +} + +void bsp_board_led_invert(uint32_t led_idx) +{ + ASSERT(led_idx < LEDS_NUMBER); + nrf_gpio_pin_toggle(m_board_led_list[led_idx]); +} + +#if defined(BOARD_PCA10059) +/** + * Function for configuring UICR_REGOUT0 register + * to set GPIO output voltage to 3.0V. + */ +static void gpio_output_voltage_setup(void) +{ + // Configure UICR_REGOUT0 register only if it is set to default value. + if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) == + (UICR_REGOUT0_VOUT_DEFAULT << UICR_REGOUT0_VOUT_Pos)) + { + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} + + NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~((uint32_t)UICR_REGOUT0_VOUT_Msk)) | + (UICR_REGOUT0_VOUT_3V0 << UICR_REGOUT0_VOUT_Pos); + + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} + + // System reset is needed to update UICR registers. + NVIC_SystemReset(); + } +} +#endif + +static void bsp_board_leds_init(void) +{ + #if defined(BOARD_PCA10059) + // If nRF52 USB Dongle is powered from USB (high voltage mode), + // GPIO output voltage is set to 1.8 V by default, which is not + // enough to turn on green and blue LEDs. Therefore, GPIO voltage + // needs to be increased to 3.0 V by configuring the UICR register. + if (NRF_POWER->MAINREGSTATUS & + (POWER_MAINREGSTATUS_MAINREGSTATUS_High << POWER_MAINREGSTATUS_MAINREGSTATUS_Pos)) + { + gpio_output_voltage_setup(); + } + #endif + + uint32_t i; + for (i = 0; i < LEDS_NUMBER; ++i) + { + nrf_gpio_cfg_output(m_board_led_list[i]); + } + bsp_board_leds_off(); +} + +uint32_t bsp_board_led_idx_to_pin(uint32_t led_idx) +{ + ASSERT(led_idx < LEDS_NUMBER); + return m_board_led_list[led_idx]; +} + +uint32_t bsp_board_pin_to_led_idx(uint32_t pin_number) +{ + uint32_t ret = 0xFFFFFFFF; + uint32_t i; + for (i = 0; i < LEDS_NUMBER; ++i) + { + if (m_board_led_list[i] == pin_number) + { + ret = i; + break; + } + } + return ret; +} +#endif //LEDS_NUMBER > 0 + +#if BUTTONS_NUMBER > 0 +bool bsp_board_button_state_get(uint32_t button_idx) +{ + ASSERT(button_idx < BUTTONS_NUMBER); + bool pin_set = nrf_gpio_pin_read(m_board_btn_list[button_idx]) ? true : false; + return (pin_set == (BUTTONS_ACTIVE_STATE ? true : false)); +} + +static void bsp_board_buttons_init(void) +{ + uint32_t i; + for (i = 0; i < BUTTONS_NUMBER; ++i) + { + nrf_gpio_cfg_input(m_board_btn_list[i], BUTTON_PULL); + } +} + +uint32_t bsp_board_pin_to_button_idx(uint32_t pin_number) +{ + uint32_t i; + uint32_t ret = 0xFFFFFFFF; + for (i = 0; i < BUTTONS_NUMBER; ++i) + { + if (m_board_btn_list[i] == pin_number) + { + ret = i; + break; + } + } + return ret; +} + +uint32_t bsp_board_button_idx_to_pin(uint32_t button_idx) +{ + ASSERT(button_idx < BUTTONS_NUMBER); + return m_board_btn_list[button_idx]; +} +#endif //BUTTONS_NUMBER > 0 + + +void bsp_board_init(uint32_t init_flags) +{ + #if defined(BOARDS_WITH_USB_DFU_TRIGGER) && defined(BOARD_PCA10059) + (void) nrf_dfu_trigger_usb_init(); + #endif + + #if LEDS_NUMBER > 0 + if (init_flags & BSP_INIT_LEDS) + { + bsp_board_leds_init(); + } + #endif //LEDS_NUMBER > 0 + + #if BUTTONS_NUMBER > 0 + if (init_flags & BSP_INIT_BUTTONS) + { + bsp_board_buttons_init(); + } + #endif //BUTTONS_NUMBER > 0 +} diff --git a/components/boards/boards.h b/components/boards/boards.h new file mode 100644 index 0000000..365b90e --- /dev/null +++ b/components/boards/boards.h @@ -0,0 +1,368 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef BOARDS_H +#define BOARDS_H + +#include "nrf_gpio.h" +#include "nordic_common.h" + +#if defined(BOARD_NRF6310) + #include "nrf6310.h" +#elif defined(BOARD_PCA10000) + #include "pca10000.h" +#elif defined(BOARD_PCA10001) + #include "pca10001.h" +#elif defined(BOARD_PCA10002) + #include "pca10000.h" +#elif defined(BOARD_PCA10003) + #include "pca10003.h" +#elif defined(BOARD_PCA20006) + #include "pca20006.h" +#elif defined(BOARD_PCA10028) + #include "pca10028.h" +#elif defined(BOARD_PCA10031) + #include "pca10031.h" +#elif defined(BOARD_PCA10036) + #include "pca10036.h" +#elif defined(BOARD_PCA10040) + #include "pca10040.h" +#elif defined(BOARD_PCA10056) + #include "pca10056.h" +#elif defined(BOARD_PCA10100) + #include "pca10100.h" +#elif defined(BOARD_PCA10112) + #include "pca10112.h" +#elif defined(BOARD_PCA20020) + #include "pca20020.h" +#elif defined(BOARD_PCA10059) + #include "pca10059.h" +#elif defined(BOARD_WT51822) + #include "wt51822.h" +#elif defined(BOARD_N5DK1) + #include "n5_starterkit.h" +#elif defined (BOARD_D52DK1) + #include "d52_starterkit.h" +#elif defined (BOARD_ARDUINO_PRIMO) + #include "arduino_primo.h" +#elif defined (CUSTOM_BOARD_INC) + #include STRINGIFY(CUSTOM_BOARD_INC.h) +#elif defined(BOARD_CUSTOM) + #include "custom_board.h" +#else +#error "Board is not defined" + +#endif + +#if defined (SHIELD_BSP_INC) + #include STRINGIFY(SHIELD_BSP_INC.h) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/**@defgroup BSP_BOARD_INIT_FLAGS Board initialization flags. + * @{ */ +#define BSP_INIT_NONE 0 /**< No initialization of LEDs or buttons (@ref bsp_board_init).*/ +#define BSP_INIT_LEDS (1 << 0) /**< Enable LEDs during initialization (@ref bsp_board_init).*/ +#define BSP_INIT_BUTTONS (1 << 1) /**< Enable buttons during initialization (@ref bsp_board_init).*/ +/**@} */ + +/** + * Function for returning the state of an LED. + * + * @param led_idx LED index (starting from 0), as defined in the board-specific header. + * + * @return True if the LED is turned on. + */ +bool bsp_board_led_state_get(uint32_t led_idx); + +/** + * Function for turning on an LED. + * + * @param led_idx LED index (starting from 0), as defined in the board-specific header. + */ +void bsp_board_led_on(uint32_t led_idx); + +/** + * Function for turning off an LED. + * + * @param led_idx LED index (starting from 0), as defined in the board-specific header. + */ +void bsp_board_led_off(uint32_t led_idx); + +/** + * Function for inverting the state of an LED. + * + * @param led_idx LED index (starting from 0), as defined in the board-specific header. + */ +void bsp_board_led_invert(uint32_t led_idx); +/** + * Function for turning off all LEDs. + */ +void bsp_board_leds_off(void); + +/** + * Function for turning on all LEDs. + */ +void bsp_board_leds_on(void); + +/** + * Function for initializing the BSP handling for the board. + * + * @note This also initializes the USB DFU trigger library if @ref BOARDS_WITH_USB_DFU_TRIGGER is 1. + * + * @param[in] init_flags Flags specifying what to initialize (LEDs/buttons). + * See @ref BSP_BOARD_INIT_FLAGS. + */ +void bsp_board_init(uint32_t init_flags); + +/** + * Function for converting pin number to LED index. + * + * @param pin_number Pin number. + * + * @return LED index of the given pin or 0xFFFFFFFF if invalid pin provided. + */ +uint32_t bsp_board_pin_to_led_idx(uint32_t pin_number); + +/** + * Function for converting LED index to pin number. + * + * @param led_idx LED index. + * + * @return Pin number. + */ +uint32_t bsp_board_led_idx_to_pin(uint32_t led_idx); + +/** + * Function for returning the state of a button. + * + * @param button_idx Button index (starting from 0), as defined in the board-specific header. + * + * @return True if the button is pressed. + */ +bool bsp_board_button_state_get(uint32_t button_idx); + +/** + * Function for converting pin number to button index. + * + * @param pin_number Pin number. + * + * @return Button index of the given pin or 0xFFFFFFFF if invalid pin provided. + */ +uint32_t bsp_board_pin_to_button_idx(uint32_t pin_number); + + +/** + * Function for converting button index to pin number. + * + * @param button_idx Button index. + * + * @return Pin number. + */ +uint32_t bsp_board_button_idx_to_pin(uint32_t button_idx); + +#define BSP_BOARD_LED_0 0 +#define BSP_BOARD_LED_1 1 +#define BSP_BOARD_LED_2 2 +#define BSP_BOARD_LED_3 3 +#define BSP_BOARD_LED_4 4 +#define BSP_BOARD_LED_5 5 +#define BSP_BOARD_LED_6 6 +#define BSP_BOARD_LED_7 7 + +#define PIN_MASK(_pin) /*lint -save -e504 */ \ + (1u << (uint32_t)((_pin) & (~P0_PIN_NUM))) \ + /*lint -restore */ + +#define PIN_PORT(_pin) (((_pin) >= P0_PIN_NUM) ? NRF_P1 : NRF_GPIO) + +#ifdef BSP_LED_0 +#define BSP_LED_0_MASK PIN_MASK(BSP_LED_0) +#define BSP_LED_0_PORT PIN_PORT(BSP_LED_0) +#else +#define BSP_LED_0_MASK 0 +#define BSP_LED_0_PORT 0 +#endif +#ifdef BSP_LED_1 +#define BSP_LED_1_MASK PIN_MASK(BSP_LED_1) +#define BSP_LED_1_PORT PIN_PORT(BSP_LED_1) +#else +#define BSP_LED_1_MASK 0 +#define BSP_LED_1_PORT 0 +#endif +#ifdef BSP_LED_2 +#define BSP_LED_2_MASK PIN_MASK(BSP_LED_2) +#define BSP_LED_2_PORT PIN_PORT(BSP_LED_2) +#else +#define BSP_LED_2_MASK 0 +#define BSP_LED_2_PORT 0 +#endif +#ifdef BSP_LED_3 +#define BSP_LED_3_MASK PIN_MASK(BSP_LED_3) +#define BSP_LED_3_PORT PIN_PORT(BSP_LED_3) +#else +#define BSP_LED_3_MASK 0 +#define BSP_LED_3_PORT 0 +#endif +#ifdef BSP_LED_4 +#define BSP_LED_4_MASK PIN_MASK(BSP_LED_4) +#define BSP_LED_4_PORT PIN_PORT(BSP_LED_4) +#else +#define BSP_LED_4_MASK 0 +#define BSP_LED_4_PORT 0 +#endif +#ifdef BSP_LED_5 +#define BSP_LED_5_MASK PIN_MASK(BSP_LED_5) +#define BSP_LED_5_PORT PIN_PORT(BSP_LED_5) +#else +#define BSP_LED_5_MASK 0 +#define BSP_LED_5_PORT 0 +#endif +#ifdef BSP_LED_6 +#define BSP_LED_6_MASK PIN_MASK(BSP_LED_6) +#define BSP_LED_6_PORT PIN_PORT(BSP_LED_6) +#else +#define BSP_LED_6_MASK 0 +#define BSP_LED_6_PORT 0 +#endif +#ifdef BSP_LED_7 +#define BSP_LED_7_MASK PIN_MASK(BSP_LED_7) +#define BSP_LED_7_PORT PIN_PORT(BSP_LED_7) +#else +#define BSP_LED_7_MASK 0 +#define BSP_LED_7_PORT 0 +#endif + + +#define LEDS_MASK (BSP_LED_0_MASK | BSP_LED_1_MASK | \ + BSP_LED_2_MASK | BSP_LED_3_MASK | \ + BSP_LED_4_MASK | BSP_LED_5_MASK | \ + BSP_LED_6_MASK | BSP_LED_7_MASK) + +#define BSP_BOARD_BUTTON_0 0 +#define BSP_BOARD_BUTTON_1 1 +#define BSP_BOARD_BUTTON_2 2 +#define BSP_BOARD_BUTTON_3 3 +#define BSP_BOARD_BUTTON_4 4 +#define BSP_BOARD_BUTTON_5 5 +#define BSP_BOARD_BUTTON_6 6 +#define BSP_BOARD_BUTTON_7 7 + + +#ifdef BSP_BUTTON_0 +#define BSP_BUTTON_0_MASK (1<OUTSET = (leds_mask) & (LEDS_MASK & LEDS_INV_MASK); \ + NRF_GPIO->OUTCLR = (leds_mask) & (LEDS_MASK & ~LEDS_INV_MASK); } while (0) + +/* This macro is supporting only P0 and should not be used if LEDs are on other ports. */ +#define LEDS_ON(leds_mask) do { ASSERT(sizeof(leds_mask) == 4); \ + NRF_GPIO->OUTCLR = (leds_mask) & (LEDS_MASK & LEDS_INV_MASK); \ + NRF_GPIO->OUTSET = (leds_mask) & (LEDS_MASK & ~LEDS_INV_MASK); } while (0) + +/* This macro is supporting only P0 and should not be used if LEDs are on other ports. */ +#define LED_IS_ON(leds_mask) ((leds_mask) & (NRF_GPIO->OUT ^ LEDS_INV_MASK) ) + +/* This macro is supporting only P0 and should not be used if LEDs are on other ports. */ +#define LEDS_INVERT(leds_mask) do { uint32_t gpio_state = NRF_GPIO->OUT; \ + ASSERT(sizeof(leds_mask) == 4); \ + NRF_GPIO->OUTSET = ((leds_mask) & ~gpio_state); \ + NRF_GPIO->OUTCLR = ((leds_mask) & gpio_state); } while (0) + +/* This macro is supporting only P0 and should not be used if LEDs are on other ports. */ +#define LEDS_CONFIGURE(leds_mask) do { uint32_t pin; \ + ASSERT(sizeof(leds_mask) == 4); \ + for (pin = 0; pin < 32; pin++) \ + if ( (leds_mask) & (1 << pin) ) \ + nrf_gpio_cfg_output(pin); } while (0) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/boards/pca10056.h b/components/boards/pca10056.h new file mode 100644 index 0000000..730e1d9 --- /dev/null +++ b/components/boards/pca10056.h @@ -0,0 +1,151 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef PCA10056_H +#define PCA10056_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_gpio.h" + +// LEDs definitions for PCA10056 +#define LEDS_NUMBER 1 + +#define LED_GR NRF_GPIO_PIN_MAP(0,12) //Green LED for Advertise +#define LED_YL_TEST NRF_GPIO_PIN_MAP(0,29) // Yello LED for Function 260311 + +#define LEDS_ACTIVE_STATE 0 +#define LEDS_LIST { LED_GR } +#define LEDS_INV_MASK LEDS_MASK +#define BSP_LED_0 LED_GR + +#define BUTTONS_NUMBER 3 + +#define BUTTON_1 19 //24 change for eeprom 2025.03.24 //Dummy Pin +#define BUTTON_2 23 //Bonds Erase & Reset 2025.05.06 18-->19 use rest pin as trigger signal +#define BUTTON_3 NRF_GPIO_PIN_MAP(1,8) //Power Button +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +#define BUTTONS_ACTIVE_STATE 0 + +#define BUTTONS_LIST { BUTTON_1, BUTTON_2, BUTTON_3 } + +#define BSP_BUTTON_0 BUTTON_1 +#define BSP_BUTTON_1 BUTTON_2 +#define BSP_BUTTON_2 BUTTON_3 + +#define RX_PIN_NUMBER 7 +#define TX_PIN_NUMBER 6 +#define CTS_PIN_NUMBER 21 //24 change for eeprom 2025.03.24 +#define RTS_PIN_NUMBER 27 +#define HWFC true + +#define BSP_QSPI_SCK_PIN 19 +#define BSP_QSPI_CSN_PIN 17 +#define BSP_QSPI_IO0_PIN 20 +#define BSP_QSPI_IO1_PIN 21 +#define BSP_QSPI_IO2_PIN 22 +#define BSP_QSPI_IO3_PIN 23 + + +// serialization APPLICATION board - temp. setup for running serialized MEMU tests +#define SER_APP_RX_PIN NRF_GPIO_PIN_MAP(1,13) // UART RX pin number. +#define SER_APP_TX_PIN NRF_GPIO_PIN_MAP(1,14) // UART TX pin number. +#define SER_APP_CTS_PIN NRF_GPIO_PIN_MAP(0,2) // UART Clear To Send pin number. +#define SER_APP_RTS_PIN NRF_GPIO_PIN_MAP(1,15) // UART Request To Send pin number. + +#define SER_APP_SPIM0_SCK_PIN NRF_GPIO_PIN_MAP(0,27) // SPI clock GPIO pin number. +#define SER_APP_SPIM0_MOSI_PIN NRF_GPIO_PIN_MAP(0,2) // SPI Master Out Slave In GPIO pin number +#define SER_APP_SPIM0_MISO_PIN NRF_GPIO_PIN_MAP(0,26) // SPI Master In Slave Out GPIO pin number +#define SER_APP_SPIM0_SS_PIN NRF_GPIO_PIN_MAP(1,13) // SPI Slave Select GPIO pin number +#define SER_APP_SPIM0_RDY_PIN NRF_GPIO_PIN_MAP(1,15) // SPI READY GPIO pin number +#define SER_APP_SPIM0_REQ_PIN NRF_GPIO_PIN_MAP(1,14) // SPI REQUEST GPIO pin number + +// serialization CONNECTIVITY board +#define SER_CON_RX_PIN NRF_GPIO_PIN_MAP(1,14) // UART RX pin number. +#define SER_CON_TX_PIN NRF_GPIO_PIN_MAP(1,13) // UART TX pin number. +#define SER_CON_CTS_PIN NRF_GPIO_PIN_MAP(1,15) // UART Clear To Send pin number. Not used if HWFC is set to false. +#define SER_CON_RTS_PIN NRF_GPIO_PIN_MAP(0,2) // UART Request To Send pin number. Not used if HWFC is set to false. + + +#define SER_CON_SPIS_SCK_PIN NRF_GPIO_PIN_MAP(0,27) // SPI SCK signal. +#define SER_CON_SPIS_MOSI_PIN NRF_GPIO_PIN_MAP(0,2) // SPI MOSI signal. +#define SER_CON_SPIS_MISO_PIN NRF_GPIO_PIN_MAP(0,26) // SPI MISO signal. +#define SER_CON_SPIS_CSN_PIN NRF_GPIO_PIN_MAP(1,13) // SPI CSN signal. +#define SER_CON_SPIS_RDY_PIN NRF_GPIO_PIN_MAP(1,15) // SPI READY GPIO pin number. +#define SER_CON_SPIS_REQ_PIN NRF_GPIO_PIN_MAP(1,14) // SPI REQUEST GPIO pin number. + +#define SER_CONN_CHIP_RESET_PIN NRF_GPIO_PIN_MAP(1,1) // Pin used to reset connectivity chip + +// Arduino board mappings +#define ARDUINO_SCL_PIN 27 // SCL signal pin +#define ARDUINO_SDA_PIN 26 // SDA signal pin +#define ARDUINO_AREF_PIN 2 // Aref pin + +#define ARDUINO_13_PIN NRF_GPIO_PIN_MAP(1, 15) // Digital pin 13 +#define ARDUINO_12_PIN NRF_GPIO_PIN_MAP(1, 14) // Digital pin 12 +#define ARDUINO_11_PIN NRF_GPIO_PIN_MAP(1, 13) // Digital pin 11 +#define ARDUINO_10_PIN NRF_GPIO_PIN_MAP(1, 12) // Digital pin 10 +#define ARDUINO_9_PIN NRF_GPIO_PIN_MAP(1, 11) // Digital pin 9 +#define ARDUINO_8_PIN NRF_GPIO_PIN_MAP(1, 10) // Digital pin 8 + +#define ARDUINO_7_PIN NRF_GPIO_PIN_MAP(1, 8) // Digital pin 7 +#define ARDUINO_6_PIN NRF_GPIO_PIN_MAP(1, 7) // Digital pin 6 +#define ARDUINO_5_PIN NRF_GPIO_PIN_MAP(1, 6) // Digital pin 5 +#define ARDUINO_4_PIN NRF_GPIO_PIN_MAP(1, 5) // Digital pin 4 +#define ARDUINO_3_PIN NRF_GPIO_PIN_MAP(1, 4) // Digital pin 3 +#define ARDUINO_2_PIN NRF_GPIO_PIN_MAP(1, 3) // Digital pin 2 +#define ARDUINO_1_PIN NRF_GPIO_PIN_MAP(1, 2) // Digital pin 1 +#define ARDUINO_0_PIN NRF_GPIO_PIN_MAP(1, 1) // Digital pin 0 + +#define ARDUINO_A0_PIN 3 // Analog channel 0 +#define ARDUINO_A1_PIN 4 // Analog channel 1 +#define ARDUINO_A2_PIN 28 // Analog channel 2 +#define ARDUINO_A3_PIN 29 // Analog channel 3 +#define ARDUINO_A4_PIN 30 // Analog channel 4 +#define ARDUINO_A5_PIN 31 // Analog channel 5 + + +#ifdef __cplusplus +} +#endif + +#endif // PCA10056_H diff --git a/components/libraries/atomic/nrf_atomic.c b/components/libraries/atomic/nrf_atomic.c new file mode 100644 index 0000000..911b20b --- /dev/null +++ b/components/libraries/atomic/nrf_atomic.c @@ -0,0 +1,449 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_atomic.h" + +#ifndef NRF_ATOMIC_USE_BUILD_IN +#if (defined(__GNUC__) && defined(WIN32)) + #define NRF_ATOMIC_USE_BUILD_IN 1 +#else + #define NRF_ATOMIC_USE_BUILD_IN 0 +#endif +#endif // NRF_ATOMIC_USE_BUILD_IN + +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) +#define STREX_LDREX_PRESENT +#else +#include "app_util_platform.h" +#endif + + +#if (NRF_ATOMIC_USE_BUILD_IN == 0) && defined(STREX_LDREX_PRESENT) +#include "nrf_atomic_internal.h" +#endif + +uint32_t nrf_atomic_u32_fetch_store(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_exchange_n(p_data, value, __ATOMIC_SEQ_CST); + +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value); + + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data = value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_store(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + __atomic_store_n(p_data, value, __ATOMIC_SEQ_CST); + return value; +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value); + + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data = value; + CRITICAL_REGION_EXIT(); + return value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_or(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_or(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data |= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_or(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_or_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data |= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_and(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_and(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(and, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data &= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_and(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_and_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(and, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data &= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_xor(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_xor(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data ^= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_xor(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_xor_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data ^= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_add(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_add(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(add, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data += value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_add(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_add_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(add, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data += value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_fetch_sub(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_sub(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data -= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_sub(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_sub_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data -= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +bool nrf_atomic_u32_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t desired) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_compare_exchange(p_data, + p_expected, + &desired, + 1, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + return nrf_atomic_internal_cmp_exch(p_data, p_expected, desired); +#else + bool ret; + CRITICAL_REGION_ENTER(); + if (*p_data == *p_expected) + { + *p_data = desired; + ret = true; + } + else + { + *p_expected = *p_data; + ret = false; + } + CRITICAL_REGION_EXIT(); + return ret; +#endif +} + +uint32_t nrf_atomic_u32_fetch_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + uint32_t expected = *p_data; + uint32_t new_val; + bool success; + + do + { + if (expected >= value) + { + new_val = expected - value; + } + else + { + new_val = expected; + } + success = __atomic_compare_exchange(p_data, + &expected, + &new_val, + 1, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST); + } while(!success); + return expected; +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub_hs, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data -= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_u32_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + uint32_t expected = *p_data; + uint32_t new_val; + bool success; + + do + { + if (expected >= value) + { + new_val = expected - value; + } + else + { + new_val = expected; + } + success = __atomic_compare_exchange(p_data, + &expected, + &new_val, + 1, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST); + } while(!success); + return new_val; +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub_hs, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data -= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +uint32_t nrf_atomic_flag_set_fetch(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_fetch_or(p_data, 1); +} + +uint32_t nrf_atomic_flag_set(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_or(p_data, 1); +} + +uint32_t nrf_atomic_flag_clear_fetch(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_fetch_and(p_data, 0); +} + +uint32_t nrf_atomic_flag_clear(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_and(p_data, 0); +} + diff --git a/components/libraries/atomic/nrf_atomic.h b/components/libraries/atomic/nrf_atomic.h new file mode 100644 index 0000000..63add0b --- /dev/null +++ b/components/libraries/atomic/nrf_atomic.h @@ -0,0 +1,274 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_atomic Atomic operations API + * @ingroup app_common + * @{ + * + * @brief @tagAPI52 This module implements C11 stdatomic.h simplified API. + At this point only Cortex-M3/M4 cores are supported (LDREX/STREX instructions). + * Atomic types are limited to @ref nrf_atomic_u32_t and @ref nrf_atomic_flag_t. + */ + +#ifndef NRF_ATOMIC_H__ +#define NRF_ATOMIC_H__ + +#include "sdk_common.h" + +/** + * @brief Atomic 32 bit unsigned type + * */ +typedef volatile uint32_t nrf_atomic_u32_t; + +/** + * @brief Atomic 1 bit flag type (technically 32 bit) + * */ +typedef volatile uint32_t nrf_atomic_flag_t; + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Stores value to an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value to store + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_store(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Stores value to an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value to store + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_store(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical OR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand OR operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_or(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical OR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand OR operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_or(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical AND operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand AND operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_and(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical AND operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand AND operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_and(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical XOR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand XOR operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_xor(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Logical XOR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand XOR operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_xor(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic ADD operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand ADD operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_add(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic ADD operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand ADD operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_add(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic SUB operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_sub(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic SUB operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_sub(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief If value at pointer is equal to expected value, changes value at pointer to desired + * + * Atomically compares the value pointed to by p_data with the value pointed to by p_expected, + * and if those are equal, replaces the former with desired. Otherwise, loads the actual value + * pointed to by p_data into *p_expected. + * + * @param p_data Atomic memory pointer to test and modify. + * @param p_expected Pointer to test value. + * @param desired Value to be stored to atomic memory. + * + * @retval true *p_data was equal to *p_expected + * @retval false *p_data was not equal to *p_expected + */ +bool nrf_atomic_u32_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t desired); + +/** + * @brief Arithmetic SUB operation on an atomic object performed if object >= value. + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return Old value stored into atomic object + * */ +uint32_t nrf_atomic_u32_fetch_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value); + +/** + * @brief Arithmetic SUB operation on an atomic object performed if object >= value. + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return New value stored into atomic object + * */ +uint32_t nrf_atomic_u32_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value); + +/**************************************************************************************************/ + +/** + * @brief Logic one bit flag set operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return Old flag value + * */ +uint32_t nrf_atomic_flag_set_fetch(nrf_atomic_flag_t * p_data); + +/** + * @brief Logic one bit flag set operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return New flag value + * */ +uint32_t nrf_atomic_flag_set(nrf_atomic_flag_t * p_data); + +/** + * @brief Logic one bit flag clear operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return Old flag value + * */ +uint32_t nrf_atomic_flag_clear_fetch(nrf_atomic_flag_t * p_data); + +/** + * @brief Logic one bit flag clear operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return New flag value + * */ +uint32_t nrf_atomic_flag_clear(nrf_atomic_flag_t * p_data); + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_H__ */ + +/** @} */ diff --git a/components/libraries/atomic/nrf_atomic_internal.h b/components/libraries/atomic/nrf_atomic_internal.h new file mode 100644 index 0000000..dbc6cfc --- /dev/null +++ b/components/libraries/atomic/nrf_atomic_internal.h @@ -0,0 +1,343 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_ATOMIC_INTERNAL_H__ +#define NRF_ATOMIC_INTERNAL_H__ + +#include "sdk_common.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * + * @defgroup nrf_atomic_internal Atomic operations internals + * @ingroup nrf_atomic + * @{ + * + */ + +/* Only Cortex M cores > 3 support LDREX/STREX instructions*/ +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0 +#error "Unsupported core version" +#endif + +#if defined ( __CC_ARM ) +static __asm uint32_t nrf_atomic_internal_mov(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + /* The base standard provides for passing arguments in core registers (r0-r3) and on the stack. + * Registers r4 and r5 have to be saved on stack. Note that only even number of register push are + * allowed. This is a requirement of the Procedure Call Standard for the ARM Architecture [AAPCS]. + * */ + push {r4, r5} + mov r4, r0 + +loop_mov + ldrex r0, [r4] + mov r5, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_mov + + str r5, [r2] + pop {r4, r5} + bx lr +} + + +static __asm uint32_t nrf_atomic_internal_orr(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_orr + ldrex r0, [r4] + orr r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_orr + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_and(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_and + ldrex r0, [r4] + and r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_and + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_eor(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_eor + ldrex r0, [r4] + eor r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_eor + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_add(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_add + ldrex r0, [r4] + add r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_add + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_sub(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_sub + ldrex r0, [r4] + sub r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_sub + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm bool nrf_atomic_internal_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t value) +{ +#define RET_REG r0 +#define P_EXPC r1 +#define VALUE r2 +#define STR_RES r3 +#define P_DATA r4 +#define EXPC_VAL r5 +#define ACT_VAL r6 + + push {r4-r6} + mov P_DATA, r0 + mov RET_REG, #0 + +loop_cmp_exch + ldrex ACT_VAL, [P_DATA] + ldr EXPC_VAL, [P_EXPC] + cmp ACT_VAL, EXPC_VAL + ittee eq + strexeq STR_RES, VALUE, [P_DATA] + moveq RET_REG, #1 + strexne STR_RES, ACT_VAL, [P_DATA] + strne ACT_VAL, [P_EXPC] + cmp STR_RES, #0 + itt ne + movne RET_REG, #0 + bne loop_cmp_exch + + pop {r4-r6} + bx lr + +#undef RET_REG +#undef P_EXPC +#undef VALUE +#undef STR_RES +#undef P_DATA +#undef EXPC_VAL +#undef ACT_VAL +} + +static __asm uint32_t nrf_atomic_internal_sub_hs(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_sub_ge + ldrex r0, [r4] + cmp r0, r1 + ite hs + subhs r5, r0, r1 + movlo r5, r0 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_sub_ge + + str r5, [r2] + pop {r4, r5} + bx lr +} + + +#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \ + old_val = nrf_atomic_internal_##asm_op(ptr, value, &new_val) + +#elif defined ( __ICCARM__ ) || defined ( __GNUC__ ) + +/** + * @brief Atomic operation generic macro + * @param[in] asm_op operation: mov, orr, and, eor, add, sub + * @param[out] old_val atomic object output (uint32_t), value before operation + * @param[out] new_val atomic object output (uint32_t), value after operation + * @param[in] value atomic operation operand + * */ +#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \ +{ \ + uint32_t str_res; \ + __ASM volatile( \ + "1: ldrex %["#old_val"], [%["#ptr"]]\n" \ + NRF_ATOMIC_OP_##asm_op(new_val, old_val, value) \ + " strex %[str_res], %["#new_val"], [%["#ptr"]]\n" \ + " teq %[str_res], #0\n" \ + " bne.n 1b" \ + : \ + [old_val]"=&r" (old_val), \ + [new_val]"=&r" (new_val), \ + [str_res]"=&r" (str_res) \ + : \ + [ptr]"r" (ptr), \ + [value]"r" (value) \ + : "cc"); \ + UNUSED_PARAMETER(str_res); \ +} + +#define NRF_ATOMIC_OP_mov(new_val, old_val, value) "mov %["#new_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_orr(new_val, old_val, value) "orr %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_and(new_val, old_val, value) "and %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_eor(new_val, old_val, value) "eor %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_add(new_val, old_val, value) "add %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_sub(new_val, old_val, value) "sub %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_sub_hs(new_val, old_val, value) \ + "cmp %["#old_val"], %["#value"]\n " \ + "ite hs\n" \ + "subhs %["#new_val"], %["#old_val"], %["#value"]\n" \ + "movlo %["#new_val"], %["#old_val"]\n" + +static inline bool nrf_atomic_internal_cmp_exch(nrf_atomic_u32_t * p_data, + uint32_t * p_expected, + uint32_t value) +{ + bool res = false; + uint32_t str_res = 0; + uint32_t act_val = 0; + uint32_t exp_val = 0; + UNUSED_VARIABLE(str_res); + UNUSED_VARIABLE(act_val); + UNUSED_VARIABLE(exp_val); + __ASM volatile( + "1: ldrex %[act_val], [%[ptr]]\n" + " ldr %[exp_val], [%[expc]]\n" + " cmp %[act_val], %[exp_val]\n" + " ittee eq\n" + " strexeq %[str_res], %[value], [%[ptr]]\n" + " moveq %[res], #1\n" + " strexne %[str_res], %[act_val], [%[ptr]]\n" + " strne %[act_val], [%[expc]]\n" + " cmp %[str_res], #0\n" + " itt ne\n" + " movne %[res], #0\n" + " bne.n 1b" + : + [res] "=&r" (res), + [exp_val] "=&r" (exp_val), + [act_val] "=&r" (act_val), + [str_res] "=&r" (str_res) + : + "0" (res), + "1" (exp_val), + "2" (act_val), + [expc] "r" (p_expected), + [ptr] "r" (p_data), + [value] "r" (value) + : "cc"); + return res; +} + +#else +#error "Unsupported compiler" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_INTERNAL_H__ */ + +/** @} */ diff --git a/components/libraries/atomic/nrf_atomic_sanity_check.h b/components/libraries/atomic/nrf_atomic_sanity_check.h new file mode 100644 index 0000000..215f7e6 --- /dev/null +++ b/components/libraries/atomic/nrf_atomic_sanity_check.h @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_ATOMIC_SANITY_CHECK_H__ +#define NRF_ATOMIC_SANITY_CHECK_H__ + +#include "nrf_atomic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Quick sanity check of nrf_atomic API + * */ +static inline void nrf_atomic_sanity_check(void) +{ +#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER) + nrf_atomic_u32_t val; + nrf_atomic_u32_t flag; + + /*Fetch version tests*/ + val = 0; + ASSERT(nrf_atomic_u32_store_fetch(&val, 10) == 0); + ASSERT(nrf_atomic_u32_store_fetch(&val, 0) == 10); + + val = 0; + ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 16) == 0); + ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 5) == ((1 << 16))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 5) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 0xFFFFFFFF) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 0xFFFFFFFF) == (0xFFFFFFFF)); + + val = 0xFFFFFFFF; + ASSERT(nrf_atomic_u32_and_fetch(&val, ~(1 << 16)) == 0xFFFFFFFF); + ASSERT(nrf_atomic_u32_and_fetch(&val, ~(1 << 5)) == (0xFFFFFFFF & ~((1 << 16)))); + ASSERT(nrf_atomic_u32_and_fetch(&val, 0) == (0xFFFFFFFF & ~(((1 << 16) | (1 << 5))))); + ASSERT(nrf_atomic_u32_and_fetch(&val, 0xFFFFFFFF) == (0)); + + val = 0; + ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 16)) == 0); + ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 5)) == ((1 << 16))); + ASSERT(nrf_atomic_u32_xor_fetch(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 16) | (1 << 5)) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor_fetch(&val, 0) == (0)); + + val = 0; + ASSERT(nrf_atomic_u32_add_fetch(&val, 100) == 0); + ASSERT(nrf_atomic_u32_add_fetch(&val, 100) == 100); + ASSERT(nrf_atomic_u32_add_fetch(&val, 1 << 24) == 200); + ASSERT(nrf_atomic_u32_add_fetch(&val, 0) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add_fetch(&val, 0xFFFFFFFF) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add_fetch(&val, 0) == (200 - 1 + (1 << 24))); + + val = 1000; + ASSERT(nrf_atomic_u32_sub_fetch(&val, 100) == 1000); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 100) == 900); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 0) == 800); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 0xFFFFFFFF) == 800); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 0) == 801); + + flag = 0; + ASSERT(nrf_atomic_flag_set_fetch(&flag) == 0); + ASSERT(nrf_atomic_flag_set_fetch(&flag) == 1); + ASSERT(nrf_atomic_flag_clear_fetch(&flag) == 1); + ASSERT(nrf_atomic_flag_clear_fetch(&flag) == 0); + + /*No fetch version tests*/ + val = 0; + ASSERT(nrf_atomic_u32_store(&val, 10) == 10); + ASSERT(nrf_atomic_u32_store(&val, 0) == 0); + + val = 0; + ASSERT(nrf_atomic_u32_or(&val, 1 << 16) == 1 << 16); + ASSERT(nrf_atomic_u32_or(&val, 1 << 5) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or(&val, 1 << 5) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or(&val, 0xFFFFFFFF) == 0xFFFFFFFF); + + val = 0xFFFFFFFF; + ASSERT(nrf_atomic_u32_and(&val, ~(1 << 16)) == (0xFFFFFFFF & ~((1 << 16)))); + ASSERT(nrf_atomic_u32_and(&val, ~(1 << 5)) == (0xFFFFFFFF & ~(((1 << 16) | (1 << 5))))); + ASSERT(nrf_atomic_u32_and(&val, 0) == 0); + + val = 0; + ASSERT(nrf_atomic_u32_xor(&val, (1 << 16)) == ((1 << 16))); + ASSERT(nrf_atomic_u32_xor(&val, (1 << 5)) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor(&val, (1 << 16) | (1 << 5)) == 0); + + val = 0; + ASSERT(nrf_atomic_u32_add(&val, 100) == 100); + ASSERT(nrf_atomic_u32_add(&val, 100) == 200); + ASSERT(nrf_atomic_u32_add(&val, 1 << 24) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add(&val, 0) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add(&val, 0xFFFFFFFF) == (200 - 1 + (1 << 24))); + + val = 1000; + ASSERT(nrf_atomic_u32_sub(&val, 100) == 900); + ASSERT(nrf_atomic_u32_sub(&val, 100) == 800); + ASSERT(nrf_atomic_u32_sub(&val, 0) == 800); + ASSERT(nrf_atomic_u32_sub(&val, 0xFFFFFFFF) == 801); + + flag = 0; + ASSERT(nrf_atomic_flag_set(&flag) == 1); + ASSERT(nrf_atomic_flag_set(&flag) == 1); + ASSERT(nrf_atomic_flag_clear(&flag) == 0); + ASSERT(nrf_atomic_flag_clear(&flag) == 0); +#endif +} + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_SANITY_CHECK_H__ */ diff --git a/components/libraries/atomic_fifo/nrf_atfifo.c b/components/libraries/atomic_fifo/nrf_atfifo.c new file mode 100644 index 0000000..3705b72 --- /dev/null +++ b/components/libraries/atomic_fifo/nrf_atfifo.c @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2011 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include "app_util.h" +#include "nrf_atfifo.h" +#include "nrf_atfifo_internal.h" + +#if NRF_ATFIFO_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_ATFIFO_CONFIG_LOG_LEVEL + #define NRF_LOG_INIT_FILTER_LEVEL NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL + #define NRF_LOG_INFO_COLOR NRF_ATFIFO_CONFIG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_ATFIFO_CONFIG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_ATFIFO_CONFIG_LOG_ENABLED +#include "nrf_log.h" + +/* Unions testing */ +STATIC_ASSERT(sizeof(nrf_atfifo_postag_t) == sizeof(uint32_t)); + + +ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size) +{ + if (NULL == p_buf) + { + NRF_LOG_INST_ERROR(p_fifo->p_log, "Initialization failed. p_buf == NULL"); + return NRF_ERROR_NULL; + } + if (0 != (buf_size % item_size)) + { + NRF_LOG_INST_ERROR(p_fifo->p_log, "Initialization failed. Buf_size not multiple of item_size"); + return NRF_ERROR_INVALID_LENGTH; + } + + p_fifo->p_buf = p_buf; + p_fifo->tail.tag = 0; + p_fifo->head.tag = 0; + p_fifo->buf_size = buf_size; + p_fifo->item_size = item_size; + + NRF_LOG_INST_INFO(p_fifo->p_log, "Initialized."); + return NRF_SUCCESS; +} + + +ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo) +{ + bool released = nrf_atfifo_space_clear(p_fifo); + NRF_LOG_INST_INFO(p_fifo->p_log, "Cleared result:%s", released ? "success" : "busy"); + return released ? NRF_SUCCESS : NRF_ERROR_BUSY; +} + + +ret_code_t nrf_atfifo_alloc_put(nrf_atfifo_t * const p_fifo, void const * p_var, size_t size, bool * const p_visible) +{ + nrf_atfifo_item_put_t context; + bool visible; + void * p_data = nrf_atfifo_item_alloc(p_fifo, &context); + if (NULL == p_data) + { + NRF_LOG_INST_WARNING(p_fifo->p_log, "Copying in element (0x%08X) failed - no space.", p_var); + return NRF_ERROR_NO_MEM; + } + + memcpy(p_data, p_var, size); + + visible = nrf_atfifo_item_put(p_fifo, &context); + if (NULL != p_visible) + { + *p_visible = visible; + } + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Element (0x%08X) copied in.", p_var); + return NRF_SUCCESS; +} + + +void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context) +{ + if (nrf_atfifo_wspace_req(p_fifo, &(p_context->last_tail))) + { + void * p_item = ((uint8_t*)(p_fifo->p_buf)) + p_context->last_tail.pos.wr; + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Allocated element (0x%08X).", p_item); + return p_item; + } + NRF_LOG_INST_WARNING(p_fifo->p_log, "Allocation failed - no space."); + return NULL; +} + + +bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context) +{ + if ((p_context->last_tail.pos.wr) == (p_context->last_tail.pos.rd)) + { + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Put (uninterrupted)"); + nrf_atfifo_wspace_close(p_fifo); + return true; + } + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Put (interrupted!)"); + return false; +} + + +ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released) +{ + nrf_atfifo_item_get_t context; + bool released; + void const * p_s = nrf_atfifo_item_get(p_fifo, &context); + if (NULL == p_s) + { + NRF_LOG_INST_WARNING(p_fifo->p_log, "Copying out failed - no item in the FIFO."); + return NRF_ERROR_NOT_FOUND; + } + + memcpy(p_var, p_s, size); + + released = nrf_atfifo_item_free(p_fifo, &context); + if (NULL != p_released) + { + *p_released = released; + } + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Element (0x%08X) copied out.", p_var); + return NRF_SUCCESS; +} + + +void * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context) +{ + if (nrf_atfifo_rspace_req(p_fifo, &(p_context->last_head))) + { + void * p_item = ((uint8_t*)(p_fifo->p_buf)) + p_context->last_head.pos.rd; + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Get element: 0x%08X", p_item); + return p_item; + } + NRF_LOG_INST_WARNING(p_fifo->p_log, "Get failed - no item in the FIFO."); + return NULL; +} + + +bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context) +{ + if ((p_context->last_head.pos.wr) == (p_context->last_head.pos.rd)) + { + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Free (uninterrupted)"); + nrf_atfifo_rspace_close(p_fifo); + return true; + } + NRF_LOG_INST_DEBUG(p_fifo->p_log, "Free (interrupted)"); + return false; +} diff --git a/components/libraries/atomic_fifo/nrf_atfifo.h b/components/libraries/atomic_fifo/nrf_atfifo.h new file mode 100644 index 0000000..4c03d86 --- /dev/null +++ b/components/libraries/atomic_fifo/nrf_atfifo.h @@ -0,0 +1,424 @@ +/** + * Copyright (c) 2011 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_ATFIFO_H__ +#define NRF_ATFIFO_H__ + +#include +#include +#include "sdk_config.h" +#include "nordic_common.h" +#include "nrf_assert.h" +#include "sdk_errors.h" +#include "nrf_log_instance.h" +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_atfifo Atomic FIFO + * @ingroup app_common + * + * @brief @tagAPI52 FIFO implementation that allows for making atomic transactions without + * locking interrupts. + * + * @details There are two types of functions to prepare the FIFO writing: + * - Single function for simple access: + * @code + * if (NRF_SUCCESS != nrf_atfifo_simple_put(my_fifo, &data, NULL)) + * { + * // Error handling + * } + * @endcode + * - Function pair to limit data copying: + * @code + * struct point3d + * { + * int x, y, z; + * }point3d_t; + * nrf_atfifo_context_t context; + * point3d_t * point; + * + * if (NULL != (point = nrf_atfifo_item_alloc(my_fifo, &context))) + * { + * point->x = a; + * point->y = b; + * point->z = c; + * if (nrf_atfifo_item_put(my_fifo, &context)) + * { + * // Send information to the rest of the system + * // that there is new data in the FIFO available for reading. + * } + * } + * else + * { + * // Error handling + * } + * + * @endcode + * @note + * This atomic FIFO implementation requires that the operation that is + * opened last is finished (committed/flushed) first. + * This is typical for operations performed from the interrupt runtime + * when the other operation is performed from the main thread. + * + * This implementation does not support typical multithreading operating system + * access where operations can be started and finished in totally unrelated order. + * + * @{ + */ + +/** + * @brief Read and write position structure. + * + * A structure that holds the read and write position used by the FIFO head and tail. + */ +typedef struct nrf_atfifo_postag_pos_s +{ + uint16_t wr; //!< First free space to write the data + uint16_t rd; //!< A place after the last data to read +}nrf_atfifo_postag_pos_t; + +/** + * @brief End data index tag. + * + * A tag used to mark the end of data. + * To properly realize atomic data committing, the whole variable has to be + * accessed atomically. + */ +typedef union nrf_atfifo_postag_u +{ + uint32_t tag; //!< Whole tag, used for atomic, 32-bit access + nrf_atfifo_postag_pos_t pos; //!< Structure that holds reading and writing position separately +}nrf_atfifo_postag_t; + +/** + * @brief The FIFO instance. + * + * The instance of atomic FIFO. + * Used with all FIFO functions. + */ +typedef struct nrf_atfifo_s +{ + void * p_buf; //!< Pointer to the data buffer + nrf_atfifo_postag_t tail; //!< Read and write tail position tag + nrf_atfifo_postag_t head; //!< Read and write head position tag + uint16_t buf_size; //!< FIFO size in number of bytes (has to be divisible by @c item_size) + uint16_t item_size; //!< Size of a single FIFO item + NRF_LOG_INSTANCE_PTR_DECLARE(p_log) //!< Pointer to instance of the logger object (Conditionally compiled). +}nrf_atfifo_t; + +/** + * @brief FIFO write operation item context. + * + * Context structure used to mark an allocated space in FIFO that is ready for put. + * All the data required to properly put allocated and written data. + */ +typedef struct nrf_atfifo_item_put_s +{ + nrf_atfifo_postag_t last_tail; //!< Tail tag value that was here when opening the FIFO to write +}nrf_atfifo_item_put_t; + + +/** + * @brief FIFO read operation item context. + * + * Context structure used to mark an opened get operation to properly free an item after reading. + */ +typedef struct nrf_atfifo_rcontext_s +{ + nrf_atfifo_postag_t last_head; //!< Head tag value that was here when opening the FIFO to read +}nrf_atfifo_item_get_t; + + +/** @brief Name of the module used for logger messaging. + */ +#define NRF_ATFIFO_LOG_NAME atfifo + +/** + * @defgroup nrf_atfifo_instmacros FIFO instance macros + * + * A group of macros helpful for FIFO instance creation and initialization. + * They may be used to create and initialize instances for most use cases. + * + * FIFO may also be created and initialized directly using + * @ref nrf_atfifo_init function. + * @{ + */ + /** + * @brief Macro for generating the name for a data buffer. + * + * The name of the data buffer that would be created by + * @ref NRF_ATFIFO_DEF macro. + * + * @param[in] fifo_id Identifier of the FIFO object. + * + * @return Name of the buffer variable. + * + * @note This is auxiliary internal macro and in normal usage + * it should not be called. + */ + #define NRF_ATFIFO_BUF_NAME(fifo_id) CONCAT_2(fifo_id, _data) + + /** + * @brief Macro for generating the name for a FIFO instance. + * + * The name of the instance variable that will be created by the + * @ref NRF_ATFIFO_DEF macro. + * + * @param[in] fifo_id Identifier of the FIFO object. + * + * @return Name of the instance variable. + * + * @note This is auxiliary internal macro and in normal usage + * it should not be called. + */ + #define NRF_ATFIFO_INST_NAME(fifo_id) CONCAT_2(fifo_id, _inst) + + /** + * @brief Macro for creating an instance. + * + * Creates the FIFO object variable itself. + * + * Usage example: + * @code + * NRF_ATFIFO_DEF(my_fifo, uint16_t, 12); + * NRF_ATFIFO_INIT(my_fifo); + * + * uint16_t some_val = 45; + * nrf_atfifo_item_put(my_fifo, &some_val, sizeof(some_val), NULL); + * nrf_atfifo_item_get(my_fifo, &some_val, sizeof(some_val), NULL); + * @endcode + * + * @param[in] fifo_id Identifier of a FIFO object. + * This identifier will be a pointer to the instance. + * It makes it possible to use this directly for the functions + * that operate on the FIFO. + * Because it is a static const object, it should be optimized by the compiler. + * @param[in] storage_type Type of data that will be stored in the FIFO. + * @param[in] item_cnt Capacity of the created FIFO in maximum number of items that may be stored. + * The phisical size of the buffer will be 1 element bigger. + */ + #define NRF_ATFIFO_DEF(fifo_id, storage_type, item_cnt) \ + static storage_type NRF_ATFIFO_BUF_NAME(fifo_id)[(item_cnt)+1]; \ + NRF_LOG_INSTANCE_REGISTER(NRF_ATFIFO_LOG_NAME, fifo_id, \ + NRF_ATFIFO_CONFIG_INFO_COLOR, \ + NRF_ATFIFO_CONFIG_DEBUG_COLOR, \ + NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL, \ + NRF_ATFIFO_CONFIG_LOG_ENABLED ? \ + NRF_ATFIFO_CONFIG_LOG_LEVEL : NRF_LOG_SEVERITY_NONE); \ + static nrf_atfifo_t NRF_ATFIFO_INST_NAME(fifo_id) = { \ + .p_buf = NULL, \ + NRF_LOG_INSTANCE_PTR_INIT(p_log, NRF_ATFIFO_LOG_NAME, fifo_id) \ + }; \ + static nrf_atfifo_t * const fifo_id = &NRF_ATFIFO_INST_NAME(fifo_id) + + /** + * @brief Macro for initializing the FIFO that was previously declared by the macro. + * + * Use this macro to simplify FIFO initialization. + * + * @note + * This macro can be only used on a FIFO object defined by @ref NRF_ATFIFO_DEF macro. + * + * @param[in] fifo_id Identifier of the FIFO object. + * + * @return Value from the @ref nrf_atfifo_init function. + */ + #define NRF_ATFIFO_INIT(fifo_id) \ + nrf_atfifo_init( \ + fifo_id, \ + NRF_ATFIFO_BUF_NAME(fifo_id), \ + sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)), \ + sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)[0]) \ + ) + +/** @} */ + +/** + * @brief Function for initializing the FIFO. + * + * Preparing the FIFO instance to work. + * + * @param[out] p_fifo FIFO object to initialize. + * @param[in,out] p_buf FIFO buffer for storing data. + * @param[in] buf_size Total buffer size (has to be divisible by @c item_size). + * @param[in] item_size Size of a single item held inside the FIFO. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_NULL If a NULL pointer is provided as the buffer. + * @retval NRF_ERROR_INVALID_LENGTH If size of the buffer provided is not divisible by @c item_size. + * + * @note + * Buffer size must be able to hold one element more than the designed FIFO capacity. + * This one, empty element is used for overflow checking. + */ +ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size); + +/** + * @brief Function for clearing the FIFO. + * + * Function for clearing the FIFO. + * + * If this function is called during an opened and uncommitted write operation, + * the FIFO is cleared up to the currently ongoing commit. + * There is no possibility to cancel an ongoing commit. + * + * If this function is called during an opened and unflushed read operation, + * the read position in the head is set, but copying it into the write head position + * is left to read closing operation. + * + * This way, there is no more data to read, but the memory is released + * in the moment when it is safe. + * + * @param[in,out] p_fifo FIFO object. + * + * @retval NRF_SUCCESS FIFO totally cleared. + * @retval NRF_ERROR_BUSY Function called in the middle of writing or reading operation. + * If it is called in the middle of writing operation, + * FIFO was cleared up to the already started and uncommitted write. + * If it is called in the middle of reading operation, + * write head was only moved. It will be copied into read tail when the reading operation + * is flushed. + */ +ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo); + +/** + * @brief Function for atomically putting data into the FIFO. + * + * It uses memcpy function inside and in most situations, it is more suitable to + * use @ref nrf_atfifo_item_alloc, write the data, and @ref nrf_atfifo_item_put to store a new value + * in a FIFO. + * + * @param[in,out] p_fifo FIFO object. + * @param[in] p_var Variable to copy. + * @param[in] size Size of the variable to copy. + * Can be smaller or equal to the FIFO item size. + * @param[out] p_visible See value returned by @ref nrf_atfifo_item_put. + * It may be NULL if the caller does not require the current operation status. + * + * @retval NRF_SUCCESS If an element has been successfully added to the FIFO. + * @retval NRF_ERROR_NO_MEM If the FIFO is full. + * + * @note + * To avoid data copying, you can use the @ref nrf_atfifo_item_alloc and @ref nrf_atfifo_item_put + * functions pair. + */ +ret_code_t nrf_atfifo_alloc_put(nrf_atfifo_t * const p_fifo, void const * const p_var, size_t size, bool * const p_visible); + +/** + * @brief Function for opening the FIFO for writing. + * + * Function called to start the FIFO write operation and access the given FIFO buffer directly. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] p_context Operation context, required by @ref nrf_atfifo_item_put. + * + * @return Pointer to the space where variable data can be stored. + * NULL if there is no space in the buffer. + */ +void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context); + +/** + * @brief Function for closing the writing operation. + * + * Puts a previously allocated context into FIFO. + * This function must be called to commit an opened write operation. + * It sets all the buffers and marks the data, so that it is visible to read. + * + * @param[in,out] p_fifo FIFO object. + * @param[in] p_context Operation context, filled by the @ref nrf_atfifo_item_alloc function. + * + * @retval true Data is currently ready and will be visible to read. + * @retval false The internal commit was marked, but the writing operation interrupted another writing operation. + * The data will be available to read when the interrupted operation is committed. + */ +bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context); + +/** + * @brief Function for getting a single value from the FIFO. + * + * This function gets the value from the top of the FIFO. + * The value is removed from the FIFO memory. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] p_var Pointer to the variable to store the data. + * @param[in] size Size of the data to be loaded. + * @param[out] p_released See the values returned by @ref nrf_atfifo_item_free. + * + * @retval NRF_SUCCESS Element was successfully copied from the FIFO memory. + * @retval NRF_ERROR_NOT_FOUND No data in the FIFO. + */ +ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released); + +/** + * @brief Function for opening the FIFO for reading. + * + * Function called to start the FIFO read operation and access the given FIFO buffer directly. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] p_context The operation context, required by @ref nrf_atfifo_item_free + * + * @return Pointer to data buffer or NULL if there is no data in the FIFO. + */ +void * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context); + +/** + * @brief Function for closing the reading operation. + * + * Function used to finish the reading operation. + * If this reading operation does not interrupt another reading operation, the head write buffer is moved. + * If this reading operation is placed in the middle of another reading, only the new read pointer is written. + * + * @param[in,out] p_fifo FIFO object. + * @param[in] p_context Context of the reading operation to be closed. + * + * @retval true This operation is not generated in the middle of another read operation and the write head will be updated to the read head (space is released). + * @retval false This operation was performed in the middle of another read operation and the write buffer head was not moved (no space is released). + */ +bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context); + + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATFIFO_H__ */ diff --git a/components/libraries/atomic_fifo/nrf_atfifo_internal.h b/components/libraries/atomic_fifo/nrf_atfifo_internal.h new file mode 100644 index 0000000..3fb0677 --- /dev/null +++ b/components/libraries/atomic_fifo/nrf_atfifo_internal.h @@ -0,0 +1,577 @@ +/** + * Copyright (c) 2011 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * @brief Atomic FIFO internal file + * + * This file should be included only by nrf_atfifo internally. + * Needs nrf_atfifo.h included first. + */ +#ifndef NRF_ATFIFO_H__ +#error This is internal file. Do not include this file in your program. +#endif + +#ifndef NRF_ATFIFO_INTERNAL_H__ +#define NRF_ATFIFO_INTERNAL_H__ +#include +#include "nrf.h" +#include "app_util.h" +#include "nordic_common.h" + +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0 +#error Unsupported core version +#endif + +/* + * Make sure that rd and wr pos in a tag are aligned like expected + * Changing this would require changes inside assembly code! + */ +STATIC_ASSERT(offsetof(nrf_atfifo_postag_pos_t, wr) == 0); +STATIC_ASSERT(offsetof(nrf_atfifo_postag_pos_t, rd) == 2); + +/** + * @brief Atomically reserve space for a new write. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] old_tail Tail position tag before new space is reserved. + * + * @retval true Space available. + * @retval false Memory full. + * + * @sa nrf_atfifo_wspace_close + */ +static bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail); + +/** + * @brief Atomically mark all written data available. + * + * This function marks all data available for reading. + * This marking is done by copying tail.pos.wr into tail.pos.rd. + * + * It must be called only when closing the first write. + * It cannot be called if any write access was interrupted. + * See the code below: + * @code + * if (old_tail.pos.wr == old_tail.pos.rd) + * { + * nrf_atfifo_wspace_close(my_fifo); + * return true; + * } + * return false; + * @endcode + * + * @param[in,out] p_fifo FIFO object. + * + * @sa nrf_atfifo_wspace_req + */ +static void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo); + +/** + * @brief Atomically get a part of a buffer to read data. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] old_head Head position tag before the data buffer is read. + * + * @retval true Data available for reading. + * @retval false No data in the buffer. + * + * @sa nrf_atfifo_rspace_close + */ +static bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head); + +/** + * @brief Atomically release all read data. + * + * This function marks all data that was read as free space, + * which is available for writing. + * This marking is done by copying head.pos.rd into head.pos.wr. + * + * It must be called only when closing the first read. + * It cannot be called when the current read access interrupted any other read access. + * See code below: + * @code + * if (old_head.pos.wr == old_head.pos.rd) + * { + * nrf_atfifo_rspace_close(my_fifo); + * return true; + * } + * return false; + * @endcode + * + * @param[in,out] p_fifo FIFO object. + * + * @sa nrf_atfifo_rspace_req + */ +static void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo); + +/** + * @brief Safely clear the FIFO, internal function. + * + * This function realizes the functionality required by @ref nrf_atfifo_clear. + * + * @param[in,out] p_fifo FIFO object. + * + * @retval true All the data was released. + * @retval false All the data available for releasing was released, but there is some pending transfer. + */ +static bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo); + + +/* --------------------------------------------------------------------------- + * Implementation starts here + */ + +#if defined ( __CC_ARM ) + + +__ASM bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - p_old_tail + * R2 - internal variable old_tail (saved by caller) + * R3 - internal variable new_tail (saved by caller) + * R4 - internal temporary register (saved by this function) + * R5 - not used stored to keep the stack aligned to 8 bytes + * Returned value: + * R0 (bool - 32 bits) + */ + push {r4, r5} +nrf_atfifo_wspace_req_repeat + /* Load tail tag and set memory monitor !!! R2 - old tail !!! */ + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + /* Extract write position !!! R3 !!! */ + uxth r3, r2 + /* Increment address with overload support !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, item_size))] + add r3, r4 + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, buf_size))] + cmp r3, r4 + it hs + subhs r3, r3, r4 + + /* Check if FIFO would overload after making this increment !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, head) + offsetof(nrf_atfifo_postag_pos_t, wr))] + cmp r3, r4 + ittt eq + clrexeq + moveq r0, #__cpp(false) + beq nrf_atfifo_wspace_req_exit + + /* Pack everything back !!! R3 - new tail !!! */ + /* Copy lower byte from new_tail, and higher byte is a value from the top of old_tail */ + pkhbt r3, r3, r2 + + /* Store new value clearing memory monitor !!! R4 used temporary !!! */ + strex r4, r3, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + cmp r4, #0 + bne nrf_atfifo_wspace_req_repeat + + /* Return true */ + mov r0, #__cpp(true) +nrf_atfifo_wspace_req_exit + /* Save old tail */ + str r2, [r1] + pop {r4, r5} + bx lr +} + + +__ASM void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - internal temporary register + * R2 - new_tail + */ +nrf_atfifo_wspace_close_repeat + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + /* Copy from lower byte to higher */ + pkhbt r2, r2, r2, lsl #16 + + strex r1, r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + cmp r1, #0 + bne nrf_atfifo_wspace_close_repeat + bx lr +} + + +__ASM bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - p_old_head + * R2 - internal variable old_head (saved by caller) + * R3 - internal variable new_head (saved by caller) + * R4 - internal temporary register (saved by this function) + * R5 - not used stored to keep the stack aligned to 8 bytes + * Returned value: + * R0 (bool - 32 bits) + */ + push {r4, r5} +nrf_atfifo_rspace_req_repeat + /* Load tail tag and set memory monitor !!! R2 - old tail !!! */ + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + /* Extract read position !!! R3 !!! */ + uxth r3, r2, ror #16 + + /* Check if we have any data !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd))] + cmp r3, r4 + ittt eq + clrexeq + moveq r0, #__cpp(false) + beq nrf_atfifo_rspace_req_exit + + /* Increment address with overload support !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, item_size))] + add r3, r4 + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, buf_size))] + cmp r3, r4 + it hs + subhs r3, r3, r4 + + /* Pack everything back !!! R3 - new tail !!! */ + /* Copy lower byte from old_head, and higher byte is a value from write_pos */ + pkhbt r3, r2, r3, lsl #16 + + /* Store new value clearing memory monitor !!! R4 used temporary !!! */ + strex r4, r3, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + cmp r4, #0 + bne nrf_atfifo_rspace_req_repeat + + /* Return true */ + mov r0, #__cpp(true) +nrf_atfifo_rspace_req_exit + /* Save old head */ + str r2, [r1] + pop {r4, r5} + bx lr +} + + +__ASM void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - internal temporary register + * R2 - new_tail + */ +nrf_atfifo_rspace_close_repeat + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + /* Copy from higher byte to lower */ + pkhtb r2, r2, r2, asr #16 + + strex r1, r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + cmp r1, #0 + bne nrf_atfifo_rspace_close_repeat + bx lr +} + + +__ASM bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo) +{ + /* Registry usage: + * R0 - p_fifo as input, bool output after + * R1 - tail, rd pointer, new_head + * R2 - head_old, destroyed when creating new_head + * R3 - p_fifo - copy + */ + mov r3, r0 +nrf_atfifo_space_clear_repeat + /* Load old head in !!! R2 register !!! and read pointer of tail in !!! R1 register !!! */ + ldrex r2, [r3, #__cpp(offsetof(nrf_atfifo_t, head))] + ldrh r1, [r3, #__cpp(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd))] + cmp r2, r2, ror #16 + /* Return false as default */ + mov r0, #__cpp(false) + /* Create new head in !!! R1 register !!! Data in !!! R2 register broken !!! */ + itett ne + uxthne r2, r2 + orreq r1, r1, r1, lsl #16 + orrne r1, r2, r1, lsl #16 + + /* Skip header test */ + bne nrf_atfifo_space_clear_head_test_skip + + /* Load whole tail and test it !!! R2 used !!! */ + ldr r2, [r3, #__cpp(offsetof(nrf_atfifo_t, tail))] + cmp r2, r2, ror #16 + /* Return true if equal */ + it eq + moveq r0, #__cpp(true) + +nrf_atfifo_space_clear_head_test_skip + /* Store and test if success !!! R2 used temporary !!! */ + strex r2, r1, [r3, #__cpp(offsetof(nrf_atfifo_t, head))] + cmp r2, #0 + bne nrf_atfifo_space_clear_repeat + bx lr +} + +#elif defined ( __ICCARM__ ) || defined ( __GNUC__ ) + +bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail) +{ + volatile bool ret; + volatile uint32_t old_tail; + uint32_t new_tail; + uint32_t temp; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[old_tail], [%[p_fifo], %[offset_tail]] \n" + " uxth %[new_tail], %[old_tail] \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_item_size]] \n" + " add %[new_tail], %[temp] \n" + " ldrh %[temp], [%[p_fifo], %[offset_buf_size]] \n" + " cmp %[new_tail], %[temp] \n" + " it hs \n" + " subhs %[new_tail], %[new_tail], %[temp] \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_head_wr]] \n" + " cmp %[new_tail], %[temp] \n" + " ittt eq \n" + " clrexeq \n" + " moveq %[ret], %[false_val] \n" + " beq.n 2f \n" + " \n" + " pkhbt %[new_tail], %[new_tail], %[old_tail] \n" + " \n" + " strex %[temp], %[new_tail], [%[p_fifo], %[offset_tail]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + " \n" + " mov %[ret], %[true_val] \n" + "2: \n" + : /* Output operands */ + [ret] "=r"(ret), + [temp] "=&r"(temp), + [old_tail]"=&r"(old_tail), + [new_tail]"=&r"(new_tail) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)), + [offset_head_wr] "J"(offsetof(nrf_atfifo_t, head) + offsetof(nrf_atfifo_postag_pos_t, wr)), + [offset_item_size]"J"(offsetof(nrf_atfifo_t, item_size)), + [offset_buf_size] "J"(offsetof(nrf_atfifo_t, buf_size)), + [true_val] "I"(true), + [false_val] "I"(false) + : /* Clobbers */ + "cc"); + + p_old_tail->tag = old_tail; + UNUSED_VARIABLE(new_tail); + UNUSED_VARIABLE(temp); + return ret; +} + + +void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo) +{ + uint32_t temp; + uint32_t new_tail; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[new_tail], [%[p_fifo], %[offset_tail]] \n" + " pkhbt %[new_tail],%[new_tail], %[new_tail], lsl #16 \n" + " \n" + " strex %[temp], %[new_tail], [%[p_fifo], %[offset_tail]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + : /* Output operands */ + [temp] "=&r"(temp), + [new_tail] "=&r"(new_tail) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)) + : /* Clobbers */ + "cc"); + + UNUSED_VARIABLE(temp); + UNUSED_VARIABLE(new_tail); +} + + +bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head) +{ + volatile bool ret; + volatile uint32_t old_head; + uint32_t new_head; + uint32_t temp; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[old_head], [%[p_fifo], %[offset_head]] \n" + " uxth %[new_head], %[old_head], ror #16 \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_tail_rd]] \n" + " cmp %[new_head], %[temp] \n" + " ittt eq \n" + " clrexeq \n" + " moveq %[ret], %[false_val] \n" + " beq.n 2f \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_item_size]] \n" + " add %[new_head], %[temp] \n" + " ldrh %[temp], [%[p_fifo], %[offset_buf_size]] \n" + " cmp %[new_head], %[temp] \n" + " it hs \n" + " subhs %[new_head], %[new_head], %[temp] \n" + " \n" + " pkhbt %[new_head], %[old_head], %[new_head], lsl #16 \n" + " \n" + " strex %[temp], %[new_head], [%[p_fifo], %[offset_head]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + " \n" + " mov %[ret], %[true_val] \n" + "2: \n" + : /* Output operands */ + [ret] "=r"(ret), + [temp] "=&r"(temp), + [old_head]"=&r"(old_head), + [new_head]"=&r"(new_head) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_head] "J"(offsetof(nrf_atfifo_t, head)), + [offset_tail_rd] "J"(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd)), + [offset_item_size]"J"(offsetof(nrf_atfifo_t, item_size)), + [offset_buf_size] "J"(offsetof(nrf_atfifo_t, buf_size)), + [true_val] "I"(true), + [false_val] "I"(false) + : /* Clobbers */ + "cc"); + + p_old_head->tag = old_head; + UNUSED_VARIABLE(new_head); + UNUSED_VARIABLE(temp); + return ret; +} + + +void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo) +{ + uint32_t temp; + uint32_t new_head; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[new_head], [%[p_fifo], %[offset_head]] \n" + " pkhtb %[new_head],%[new_head], %[new_head], asr #16 \n" + " \n" + " strex %[temp], %[new_head], [%[p_fifo], %[offset_head]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + : /* Output operands */ + [temp] "=&r"(temp), + [new_head] "=&r"(new_head) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_head] "J"(offsetof(nrf_atfifo_t, head)) + : /* Clobbers */ + "cc"); + + UNUSED_VARIABLE(temp); + UNUSED_VARIABLE(new_head); +} + + +bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo) +{ + volatile bool ret; + uint32_t old_head; /* This variable is left broken after assembly code finishes */ + uint32_t new_head; + + __ASM volatile( + "1: \n" + " ldrex %[old_head], [%[p_fifo], %[offset_head]] \n" + " ldrh %[new_head], [%[p_fifo], %[offset_tail_rd]] \n" + " cmp %[old_head], %[old_head], ror #16 \n" + " \n" + " mov %[ret], %[false_val] \n" + " \n" + " itett ne \n" + " uxthne %[old_head], %[old_head] \n" + " orreq %[new_head], %[new_head], %[new_head], lsl #16 \n" + " orrne %[new_head], %[old_head], %[new_head], lsl #16 \n" + " \n" + " bne.n 2f \n" + " \n" + " ldr %[old_head], [%[p_fifo], %[offset_tail]] \n" + " cmp %[old_head], %[old_head], ror #16 \n" + " it eq \n" + " moveq %[ret], %[true_val] \n" + " \n" + "2: \n" + " strex %[old_head], %[new_head], [%[p_fifo], %[offset_head]] \n" + " cmp %[old_head], #0 \n" + " bne.n 1b \n" + : /* Output operands */ + [ret] "=&r"(ret), + [old_head] "=&r"(old_head), + [new_head] "=&r"(new_head) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_head] "J"(offsetof(nrf_atfifo_t, head)), + [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)), + [offset_tail_rd] "J"(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd)), + [true_val] "I"(true), + [false_val] "I"(false) + : /* Clobbers */ + "cc"); + + UNUSED_VARIABLE(old_head); + UNUSED_VARIABLE(new_head); + return ret; +} + +#else +#error Unsupported compiler +#endif + +#endif /* NRF_ATFIFO_INTERNAL_H__ */ diff --git a/components/libraries/atomic_flags/nrf_atflags.c b/components/libraries/atomic_flags/nrf_atflags.c new file mode 100644 index 0000000..6388ee7 --- /dev/null +++ b/components/libraries/atomic_flags/nrf_atflags.c @@ -0,0 +1,160 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf.h" +#include "nrf_atomic.h" +#include "nrf_atflags.h" +#include "sdk_common.h" + + + +/**@brief Macro for getting the index inside the flag array where a flag can be found. + * + * @param flag_index Index of the flag. + * + * @return Index of the @ref nrf_atflags_t the flag can be found in. + */ +#define FLAG_BASE(flag_index) ((flag_index) / NRF_ATFLAGS_FLAGS_PER_ELEMENT) + +/**@brief Macro for getting the mask representing the flag within the flag array member. + * + * @param flag_index ID of the flag. + * + * @return Mask representing the flag within a single @ref nrf_atflags_t. + */ +#define FLAG_MASK(flag_index) (1UL << ((flag_index) % NRF_ATFLAGS_FLAGS_PER_ELEMENT)) + + +void nrf_atflags_set(nrf_atflags_t * p_flags, uint32_t flag_index) +{ + uint32_t new_value = nrf_atomic_u32_or(&p_flags[FLAG_BASE(flag_index)], FLAG_MASK(flag_index)); + UNUSED_RETURN_VALUE(new_value); +} + + +bool nrf_atflags_fetch_set(nrf_atflags_t * p_flags, uint32_t flag_index) +{ + return (nrf_atomic_u32_fetch_or(&p_flags[FLAG_BASE(flag_index)], FLAG_MASK(flag_index)) + & FLAG_MASK(flag_index)) != 0; +} + + +void nrf_atflags_clear(nrf_atflags_t * p_flags, uint32_t flag_index) +{ + uint32_t new_value = nrf_atomic_u32_and(&p_flags[FLAG_BASE(flag_index)], ~FLAG_MASK(flag_index)); + UNUSED_RETURN_VALUE(new_value); +} + + +bool nrf_atflags_fetch_clear(nrf_atflags_t * p_flags, uint32_t flag_index) +{ + return (nrf_atomic_u32_fetch_and(&p_flags[FLAG_BASE(flag_index)], ~FLAG_MASK(flag_index)) + & FLAG_MASK(flag_index)) != 0; +} + + +bool nrf_atflags_get(nrf_atflags_t const * p_flags, uint32_t flag_index) +{ + return (p_flags[FLAG_BASE(flag_index)] & FLAG_MASK(flag_index)) != 0; +} + + +uint32_t nrf_atflags_init(nrf_atflags_t * p_flags, uint32_t flags_array_len, uint32_t flag_count) +{ + uint32_t required_flags_array_len = NRF_ATFLAGS_ARRAY_LEN(flag_count); + + if (required_flags_array_len <= flags_array_len) + { + for (uint32_t i = 0; i < required_flags_array_len; i++) + { + p_flags[i] = 0; + } + return required_flags_array_len; + } + return 0; +} + +uint32_t nrf_atflags_find_and_set_flag(nrf_atflags_t * p_flags, uint32_t flag_count) +{ + for (uint32_t i = 0; i < NRF_ATFLAGS_ARRAY_LEN(flag_count); i++) + { + // Using __RBIT to make the order of flags more traditional. + uint32_t first_zero = __CLZ(__RBIT(~p_flags[i])); + while (first_zero < 32) + { + uint32_t first_zero_global = first_zero + (i * 32); + if (first_zero_global >= flag_count) + { + break; + } + if (!nrf_atflags_fetch_set(p_flags, first_zero_global)) + { + return first_zero_global; + } + first_zero = __CLZ(__RBIT(~p_flags[i])); + } + } + + return flag_count; +} + +uint32_t nrf_atflags_find_and_clear_flag(nrf_atflags_t * p_flags, uint32_t flag_count) +{ + for (uint32_t i = 0; i < NRF_ATFLAGS_ARRAY_LEN(flag_count); i++) + { + // Using __RBIT to make the order of flags more traditional. + uint32_t first_one = __CLZ(__RBIT(p_flags[i])); + while (first_one < 32) + { + uint32_t first_one_global = first_one + (i * 32); + if (first_one_global >= flag_count) + { + break; + } + if (nrf_atflags_fetch_clear(p_flags, first_one_global)) + { + return first_one_global; + } + first_one = __CLZ(__RBIT(p_flags[i])); + } + } + + return flag_count; +} diff --git a/components/libraries/atomic_flags/nrf_atflags.h b/components/libraries/atomic_flags/nrf_atflags.h new file mode 100644 index 0000000..5c8c894 --- /dev/null +++ b/components/libraries/atomic_flags/nrf_atflags.h @@ -0,0 +1,184 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_atflags Atomic flags (bitmaps) + * @ingroup app_common + * @{ + * + * @brief @tagAPI52 This module implements atomic flags as bitmaps. + * + * Operations on the individual flags are atomic, meaning that you are always sure that the flag is + * set to the desired value, and you always know what value was there before. You also know that no + * other flags were affected by the operation. + * + * Operations on the entire flag collection are NOT atomic. This essentially means that you can't + * know the order in which operations on different flags happened, and you can't know the state of + * the entire flag collection at any instant. These limitations can be overcome by protecting + * operations with a mutex. + */ + +#ifndef NRF_ATFLAGS_H__ +#define NRF_ATFLAGS_H__ + +#include +#include + +/** + * @brief Array of atomic flags. + * */ +typedef volatile uint32_t nrf_atflags_t; + + +/** + * @brief Number of flags per @ref nrf_atflags_t. + * */ +#define NRF_ATFLAGS_FLAGS_PER_ELEMENT (sizeof(nrf_atflags_t) * 8) + +/**@brief Macro for the length of an array of @ref nrf_atflags_t needed to keep \p flag_count flags. + * + * @param flag_count Number of flags to keep in a flag array. + * + * @return Length of the array needed to house flag_count flags. + */ +#define NRF_ATFLAGS_ARRAY_LEN(flag_count) ((flag_count - 1) / NRF_ATFLAGS_FLAGS_PER_ELEMENT) + 1 + +/**@brief Macro for declaring a flag array with the right size and initial value. + * + * @note When using this macro, no call to @ref nrf_atflags_init is necessary for this array. + * + * @param _name Name to be given to the array. + * @param flag_count Number of flags to be kept in the flag array. + * + * @return Flag array definition. + */ +#define NRF_ATFLAGS_DEF(_name, flag_count) \ + nrf_atflags_t _name[NRF_ATFLAGS_ARRAY_LEN((flag_count))] = {0} + +/**@brief Macro for defining a flag array inside a struct. + * + * @note When using this macro, make sure to set the array to 0 or use @ref nrf_atflags_init + * + * @param _name Name to be given to the array. + * @param flag_count Number of flags to be kept in the flag array. + * + * @return The flag array definition. + */ +#define NRF_ATFLAGS_DEF_MEMBER(_name, flag_count) \ + nrf_atflags_t _name[NRF_ATFLAGS_ARRAY_LEN((flag_count))] + +/**@brief Function for safely initializing a flag array to 0. + * + * @param p_flags Flag array to initialize. + * @param flags_array_len Length of \p p_flags. + * @param flag_count Number of flags to be kept in the flag array. + * + * @retval 0 if the given length is not sufficient to house \p flag_count flags in the array. + * @return If successful: The actual length required. + */ +uint32_t nrf_atflags_init(nrf_atflags_t * p_flags, uint32_t flags_array_len, uint32_t flag_count); + +/**@brief Function for atomically setting a flag to 1. + * + * @param[in] p_flags Atomic flag array. + * @param[in] flag_index Index of the flag in the array. + */ +void nrf_atflags_set(nrf_atflags_t * p_flags, uint32_t flag_index); + +/**@brief Function for atomically setting a flag to 1, returning the previous value of the flag. + * + * @param[in] p_flags Atomic flag array. + * @param[in] flag_index Index of the flag in the array. + * + * @return Old flag value. + */ +bool nrf_atflags_fetch_set(nrf_atflags_t * p_flags, uint32_t flag_index); + +/**@brief Function for atomically setting a flag to 0. + * + * @param[in] p_flags Atomic flag array. + * @param[in] flag_index Index of the flag in the array. + */ +void nrf_atflags_clear(nrf_atflags_t * p_flags, uint32_t flag_index); + +/**@brief Function for atomically setting a flag to 0, returning the previous value of the flag. + * + * @param[in] p_flags Atomic flag array. + * @param[in] flag_index Index of the flag in the array. + * + * @return Old flag value. + */ +bool nrf_atflags_fetch_clear(nrf_atflags_t * p_flags, uint32_t flag_index); + +/**@brief Function for getting the value of a flag in a flag array. + * + * @param[in] p_flags Atomic flag array. + * @param[in] flag_index Index of the flag in the array. + * + * @return Flag value. + */ +bool nrf_atflags_get(nrf_atflags_t const * p_flags, uint32_t flag_index); + +/**@brief Function for finding a flag with value 0, and atomically setting it to one. + * + * @param[in] p_flags Atomic flag array. + * @param[in] flag_count Number of flags in the array. + * + * @return Index of the cleared flag that has been set. + */ +uint32_t nrf_atflags_find_and_set_flag(nrf_atflags_t * p_flags, uint32_t flag_count); + +/**@brief Function for finding a flag with value 1, and atomically clearing it to 0. + * + * @param[in] p_flags Atomic flag array. + * @param[in] flag_count The number of flags in the array. + * + * @return The index of the set flag that has been cleared. + */ +uint32_t nrf_atflags_find_and_clear_flag(nrf_atflags_t * p_flags, uint32_t flag_count); + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATFLAGS_H__ */ + +/** @} */ diff --git a/components/libraries/balloc/nrf_balloc.c b/components/libraries/balloc/nrf_balloc.c new file mode 100644 index 0000000..882c248 --- /dev/null +++ b/components/libraries/balloc/nrf_balloc.c @@ -0,0 +1,399 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" + #if NRF_MODULE_ENABLED(NRF_BALLOC) + +#include "nrf_section.h" +#include "nrf_balloc.h" +#include "app_util_platform.h" + + +#if NRF_BALLOC_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_BALLOC_CONFIG_LOG_LEVEL + #define NRF_LOG_INITIAL_LEVEL NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL + #define NRF_LOG_INFO_COLOR NRF_BALLOC_CONFIG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_BALLOC_CONFIG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_BALLOC_CONFIG_LOG_ENABLED +#include "nrf_log.h" + +#define HEAD_GUARD_FILL 0xBAADF00D /**< Magic number used to mark head guard.*/ +#define TAIL_GUARD_FILL 0xBAADCAFE /**< Magic number used to mark tail guard.*/ +#define FREE_MEM_FILL 0xBAADBAAD /**< Magic number used to mark free memory.*/ + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED +#define POOL_ID(_p_pool) _p_pool->p_name +#define POOL_MARKER "%s" +#else +#define POOL_ID(_p_pool) _p_pool +#define POOL_MARKER "0x%08X" +#endif + +NRF_SECTION_DEF(nrf_balloc, nrf_balloc_t); + +#if NRF_BALLOC_CLI_CMDS && NRF_CLI_ENABLED +#include "nrf_cli.h" + +static void nrf_balloc_status(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + UNUSED_PARAMETER(argv); + + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + + if (argc > 1) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Bad argument count"); + return; + } + + uint32_t num_of_instances = NRF_SECTION_ITEM_COUNT(nrf_balloc, nrf_balloc_t); + uint32_t i; + + for (i = 0; i < num_of_instances; i++) + { + const nrf_balloc_t * p_instance = NRF_SECTION_ITEM_GET(nrf_balloc, nrf_balloc_t, i); + + uint32_t element_size = NRF_BALLOC_ELEMENT_SIZE(p_instance); + uint32_t dbg_addon = p_instance->block_size - element_size; + uint32_t pool_size = p_instance->p_stack_limit - p_instance->p_stack_base; + uint32_t max_util = nrf_balloc_max_utilization_get(p_instance); + uint32_t util = nrf_balloc_utilization_get(p_instance); + const char * p_name = p_instance->p_name; + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, + "%s\r\n\t- Element size:\t%d + %d bytes of debug information\r\n" + "\t- Usage:\t%u%% (%u out of %u elements)\r\n" + "\t- Maximum:\t%u%% (%u out of %u elements)\r\n\r\n", + p_name, element_size, dbg_addon, + 100ul * util/pool_size, util,pool_size, + 100ul * max_util/pool_size, max_util,pool_size); + + } +} +// Register "balloc" command and its subcommands in CLI. +NRF_CLI_CREATE_STATIC_SUBCMD_SET(nrf_balloc_commands) +{ + NRF_CLI_CMD(status, NULL, "Print status of balloc instances.", nrf_balloc_status), + NRF_CLI_SUBCMD_SET_END +}; + +NRF_CLI_CMD_REGISTER(balloc, &nrf_balloc_commands, "Commands for BALLOC management", nrf_balloc_status); +#endif //NRF_BALLOC_CLI_CMDS + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED +/**@brief Validate block memory, prepare block guards, and calculate pointer to the element. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] p_head Pointer to the beginning of the block. + * + * @return Pointer to the element. + */ +__STATIC_INLINE void * nrf_balloc_block_unwrap(nrf_balloc_t const * p_pool, void * p_head) +{ + ASSERT((p_pool != NULL) && ((p_pool->block_size % sizeof(uint32_t)) == 0)); + ASSERT((p_head != NULL) && (((uint32_t)(p_head) % sizeof(uint32_t)) == 0)); + + uint32_t head_words = NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(p_pool->debug_flags); + uint32_t tail_words = NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(p_pool->debug_flags); + + uint32_t * p_tail = (uint32_t *)((size_t)(p_head) + p_pool->block_size); + uint32_t * p_element = (uint32_t *)p_head + head_words; + + if (NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(p_pool->debug_flags)) + { + for (uint32_t * ptr = p_head; ptr < p_tail; ptr++) + { + if (*ptr != FREE_MEM_FILL) + { + NRF_LOG_INST_ERROR(p_pool->p_log, + "Detected free memory corruption at 0x%08X (0x%08X != 0x%08X)", + ptr, *ptr, FREE_MEM_FILL); + APP_ERROR_CHECK_BOOL(false); + } + } + } + + for (uint32_t * ptr = p_head; ptr < p_element; ptr++) + { + *ptr = HEAD_GUARD_FILL; + } + + for (uint32_t * ptr = ( p_tail - tail_words); ptr < p_tail; ptr++) + { + *ptr = TAIL_GUARD_FILL; + } + + return p_element; +} + +/**@brief Calculate pointer to the block, validate block guards, and mark block memory as free. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] p_element Pointer to the element. + * + * @return Pointer to the beginning of the block. + */ +__STATIC_INLINE void * nrf_balloc_element_wrap(nrf_balloc_t const * p_pool, void * p_element) +{ + ASSERT((p_pool != NULL) && ((p_pool->block_size % sizeof(uint32_t)) == 0)); + ASSERT((p_element != NULL) && (((uint32_t)(p_element) % sizeof(uint32_t)) == 0)); + + uint32_t head_words = NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(p_pool->debug_flags); + uint32_t tail_words = NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(p_pool->debug_flags); + + uint32_t * p_head = (uint32_t *)p_element - head_words; + uint32_t * p_tail = (uint32_t *)((size_t)(p_head) + p_pool->block_size); + + for (uint32_t * ptr = p_head; ptr < (uint32_t *)p_element; ptr++) + { + if (*ptr != HEAD_GUARD_FILL) + { + NRF_LOG_INST_ERROR(p_pool->p_log, + "Detected Head Guard corruption at 0x%08X (0x%08X != 0x%08X)", + ptr, *ptr, HEAD_GUARD_FILL); + APP_ERROR_CHECK_BOOL(false); + } + } + + for (uint32_t * ptr = ( p_tail - tail_words); ptr < p_tail; ptr++) + { + if (*ptr != TAIL_GUARD_FILL) + { + NRF_LOG_INST_ERROR(p_pool->p_log, + "Detected Tail Guard corruption at 0x%08X (0x%08X != 0x%08X)", + ptr, *ptr, TAIL_GUARD_FILL); + APP_ERROR_CHECK_BOOL(false); + } + } + + if (NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(p_pool->debug_flags)) + { + for (uint32_t * ptr = p_head; ptr < p_tail; ptr++) + { + *ptr = FREE_MEM_FILL; + } + } + + return p_head; +} + +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + +/**@brief Convert block index to a pointer. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] idx Index of the block. + * + * @return Pointer to the beginning of the block. + */ +static void * nrf_balloc_idx2block(nrf_balloc_t const * p_pool, uint8_t idx) +{ + ASSERT(p_pool != NULL); + return (uint8_t *)(p_pool->p_memory_begin) + ((size_t)(idx) * p_pool->block_size); +} + +/**@brief Convert block pointer to index. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] p_block Pointer to the beginning of the block. + * + * @return Index of the block. + */ +static uint8_t nrf_balloc_block2idx(nrf_balloc_t const * p_pool, void const * p_block) +{ + ASSERT(p_pool != NULL); + return ((size_t)(p_block) - (size_t)(p_pool->p_memory_begin)) / p_pool->block_size; +} + +ret_code_t nrf_balloc_init(nrf_balloc_t const * p_pool) +{ + uint8_t pool_size; + + VERIFY_PARAM_NOT_NULL(p_pool); + + ASSERT(p_pool->p_cb); + ASSERT(p_pool->p_stack_base); + ASSERT(p_pool->p_stack_limit); + ASSERT(p_pool->p_memory_begin); + ASSERT(p_pool->block_size); + + pool_size = p_pool->p_stack_limit - p_pool->p_stack_base; + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + void *p_memory_end = (uint8_t *)(p_pool->p_memory_begin) + (pool_size * p_pool->block_size); + if (NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(p_pool->debug_flags)) + { + for (uint32_t * ptr = p_pool->p_memory_begin; ptr < (uint32_t *)(p_memory_end); ptr++) + { + *ptr = FREE_MEM_FILL; + } + } +#endif + + NRF_LOG_INST_INFO(p_pool->p_log, "Initialized (size: %u x %u = %u bytes)", + pool_size, + p_pool->block_size, + pool_size * p_pool->block_size); + + p_pool->p_cb->p_stack_pointer = p_pool->p_stack_base; + while (pool_size--) + { + *(p_pool->p_cb->p_stack_pointer)++ = pool_size; + } + + p_pool->p_cb->max_utilization = 0; + + return NRF_SUCCESS; +} + +void * nrf_balloc_alloc(nrf_balloc_t const * p_pool) +{ + ASSERT(p_pool != NULL); + + void * p_block = NULL; + + CRITICAL_REGION_ENTER(); + + if (p_pool->p_cb->p_stack_pointer > p_pool->p_stack_base) + { + // Allocate block. + p_block = nrf_balloc_idx2block(p_pool, *--(p_pool->p_cb->p_stack_pointer)); + + // Update utilization statistics. + uint8_t utilization = p_pool->p_stack_limit - p_pool->p_cb->p_stack_pointer; + if (p_pool->p_cb->max_utilization < utilization) + { + p_pool->p_cb->max_utilization = utilization; + } + } + + CRITICAL_REGION_EXIT(); + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + if (p_block != NULL) + { + p_block = nrf_balloc_block_unwrap(p_pool, p_block); + } +#endif + + NRF_LOG_INST_DEBUG(p_pool->p_log, "Allocating element: 0x%08X", p_block); + + return p_block; +} + +void nrf_balloc_free(nrf_balloc_t const * p_pool, void * p_element) +{ + ASSERT(p_pool != NULL); + ASSERT(p_element != NULL) + + NRF_LOG_INST_DEBUG(p_pool->p_log, "Freeing element: 0x%08X", p_element); + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + void * p_block = nrf_balloc_element_wrap(p_pool, p_element); + + // These checks could be done outside critical region as they use only pool configuration data. + if (NRF_BALLOC_DEBUG_BASIC_CHECKS_GET(p_pool->debug_flags)) + { + uint8_t pool_size = p_pool->p_stack_limit - p_pool->p_stack_base; + void *p_memory_end = (uint8_t *)(p_pool->p_memory_begin) + (pool_size * p_pool->block_size); + + // Check if the element belongs to this pool. + if ((p_block < p_pool->p_memory_begin) || (p_block >= p_memory_end)) + { + NRF_LOG_INST_ERROR(p_pool->p_log, + "Attempted to free element (0x%08X) that does not belong to the pool.", + p_element); + APP_ERROR_CHECK_BOOL(false); + } + + // Check if the pointer is valid. + if ((((size_t)(p_block) - (size_t)(p_pool->p_memory_begin)) % p_pool->block_size) != 0) + { + NRF_LOG_INST_ERROR(p_pool->p_log, + "Attempted to free corrupted element address (0x%08X).", p_element); + APP_ERROR_CHECK_BOOL(false); + } + } +#else + void * p_block = p_element; +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + + CRITICAL_REGION_ENTER(); + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + // These checks have to be done in critical region as they use p_pool->p_stack_pointer. + if (NRF_BALLOC_DEBUG_BASIC_CHECKS_GET(p_pool->debug_flags)) + { + // Check for allocated/free ballance. + if (p_pool->p_cb->p_stack_pointer >= p_pool->p_stack_limit) + { + NRF_LOG_INST_ERROR(p_pool->p_log, + "Attempted to free an element (0x%08X) while the pool is full.", + p_element); + APP_ERROR_CHECK_BOOL(false); + } + } + + if (NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_GET(p_pool->debug_flags)) + { + // Check for double free. + for (uint8_t * p_idx = p_pool->p_stack_base; p_idx < p_pool->p_cb->p_stack_pointer; p_idx++) + { + if (nrf_balloc_idx2block(p_pool, *p_idx) == p_block) + { + NRF_LOG_INST_ERROR(p_pool->p_log, "Attempted to double-free an element (0x%08X).", + p_element); + APP_ERROR_CHECK_BOOL(false); + } + } + } +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + + // Free the element. + *(p_pool->p_cb->p_stack_pointer)++ = nrf_balloc_block2idx(p_pool, p_block); + + CRITICAL_REGION_EXIT(); +} + +#endif // NRF_MODULE_ENABLED(NRF_BALLOC) diff --git a/components/libraries/balloc/nrf_balloc.h b/components/libraries/balloc/nrf_balloc.h new file mode 100644 index 0000000..4e4cabc --- /dev/null +++ b/components/libraries/balloc/nrf_balloc.h @@ -0,0 +1,351 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * @defgroup nrf_balloc Block memory allocator + * @{ + * @ingroup app_common + * @brief This module handles block memory allocator features. + */ + + +#ifndef NRF_BALLOC_H__ +#define NRF_BALLOC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sdk_errors.h" +#include "sdk_config.h" +#include "app_util_platform.h" +#include "app_util.h" +#include "nrf_log_instance.h" +#include "nrf_section.h" + +/** @brief Name of the module used for logger messaging. + */ +#define NRF_BALLOC_LOG_NAME balloc + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED || NRF_BALLOC_CLI_CMDS +#define NRF_BALLOC_HAS_NAME 1 +#else +#define NRF_BALLOC_HAS_NAME 0 +#endif + +/**@defgroup NRF_BALLOC_DEBUG Macros for preparing debug flags for block allocator module. + * @{ */ +#define NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_SET(words) (((words) & 0xFF) << 0) +#define NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(flags) (((flags) >> 0) & 0xFF) +#define NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_SET(words) (((words) & 0xFF) << 8) +#define NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(flags) (((flags) >> 8) & 0xFF) + +#define NRF_BALLOC_DEBUG_BASIC_CHECKS_SET(enable) (!!(enable) << 16) +#define NRF_BALLOC_DEBUG_BASIC_CHECKS_GET(flags) (flags & (1 << 16)) +#define NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_SET(enable) (!!(enable) << 17) +#define NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_GET(flags) (flags & (1 << 17)) +#define NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_SET(enable) (!!(enable) << 18) +#define NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(flags) (flags & (1 << 18)) +/**@} */ + +/**@brief Default debug flags for @ref nrf_balloc. This is used by the @ref NRF_BALLOC_DEF macro. + * Flags can be changed in @ref sdk_config. + */ +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + #define NRF_BALLOC_DEFAULT_DEBUG_FLAGS \ + ( \ + NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_SET(NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS) | \ + NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_SET(NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS) | \ + NRF_BALLOC_DEBUG_BASIC_CHECKS_SET(NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED) | \ + NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_SET(NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED) | \ + NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_SET(NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED) \ + ) +#else + #define NRF_BALLOC_DEFAULT_DEBUG_FLAGS 0 +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + +/**@brief Block memory allocator control block.*/ +typedef struct +{ + uint8_t * p_stack_pointer; //!< Current allocation stack pointer. + uint8_t max_utilization; //!< Maximum utilization of the memory pool. +} nrf_balloc_cb_t; + +/**@brief Block memory allocator pool instance. The pool is made of elements of the same size. */ +typedef struct +{ + nrf_balloc_cb_t * p_cb; //!< Pointer to the instance control block. + uint8_t * p_stack_base; //!< Base of the allocation stack. + /**< + * Stack is used to store handlers to not allocated elements. + */ + uint8_t * p_stack_limit; //!< Maximum possible value of the allocation stack pointer. + void * p_memory_begin; //!< Pointer to the start of the memory pool. + /**< + * Memory is used as a heap for blocks. + */ + NRF_LOG_INSTANCE_PTR_DECLARE(p_log) //!< Pointer to instance of the logger object (Conditionally compiled). +#if NRF_BALLOC_HAS_NAME + const char * p_name; //!< Pointer to string with pool name. +#endif +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + uint32_t debug_flags; //!< Debugging settings. + /**< + * Debug flag should be created by @ref NRF_BALLOC_DEBUG. + */ +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + uint16_t block_size; //!< Size of the allocated block (including debug overhead). + /**< + * Single block contains user element with header and tail + * words. + */ +} nrf_balloc_t; + +/**@brief Get total memory consumed by single block (element size with overhead caused by debug + * flags). + * + * @param[in] _element_size Size of an element. + * @param[in] _debug_flags Debug flags. + */ +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + #define NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags) \ + ( \ + (sizeof(uint32_t) * NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(_debug_flags)) + \ + ALIGN_NUM(sizeof(uint32_t), (_element_size)) + \ + (sizeof(uint32_t) * NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(_debug_flags)) \ + ) +#else + #define NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags) \ + ALIGN_NUM(sizeof(uint32_t), (_element_size)) +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + + +/**@brief Get element size ( excluding debugging overhead is present) + * flags). + * + * @param[in] _p_balloc Pointer to balloc instance. + */ +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED +#define NRF_BALLOC_ELEMENT_SIZE(_p_balloc) \ + (ALIGN_NUM(sizeof(uint32_t), (_p_balloc)->block_size) - \ + ((sizeof(uint32_t) * NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET((_p_balloc)->debug_flags)) + \ + (sizeof(uint32_t) * NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET((_p_balloc)->debug_flags)))) +#else +#define NRF_BALLOC_ELEMENT_SIZE(_p_balloc) \ + (_p_balloc)->block_size +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED +#define __NRF_BALLOC_ASSIGN_DEBUG_FLAGS(_debug_flags) .debug_flags = (_debug_flags), +#else +#define __NRF_BALLOC_ASSIGN_DEBUG_FLAGS(_debug_flags) +#endif + +#if NRF_BALLOC_HAS_NAME +#define __NRF_BALLOC_ASSIGN_POOL_NAME(_name) .p_name = STRINGIFY(_name), +#else +#define __NRF_BALLOC_ASSIGN_POOL_NAME(_name) +#endif + + +/**@brief Create a block allocator instance with custom debug flags. + * + * @note This macro reserves memory for the given block allocator instance. + * + * @param[in] _name Name of the allocator. + * @param[in] _element_size Size of one element. + * @param[in] _pool_size Size of the pool. + * @param[in] _debug_flags Debug flags (@ref NRF_BALLOC_DEBUG). + */ +#define NRF_BALLOC_DBG_DEF(_name, _element_size, _pool_size, _debug_flags) \ + STATIC_ASSERT((_pool_size) <= UINT8_MAX); \ + static uint8_t CONCAT_2(_name, _nrf_balloc_pool_stack)[(_pool_size)]; \ + static uint32_t CONCAT_2(_name,_nrf_balloc_pool_mem) \ + [NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags) * (_pool_size) / sizeof(uint32_t)]; \ + static nrf_balloc_cb_t CONCAT_2(_name,_nrf_balloc_cb); \ + NRF_LOG_INSTANCE_REGISTER(NRF_BALLOC_LOG_NAME, _name, \ + NRF_BALLOC_CONFIG_INFO_COLOR, \ + NRF_BALLOC_CONFIG_DEBUG_COLOR, \ + NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL, \ + NRF_BALLOC_CONFIG_LOG_ENABLED ? \ + NRF_BALLOC_CONFIG_LOG_LEVEL : NRF_LOG_SEVERITY_NONE); \ + NRF_SECTION_ITEM_REGISTER(nrf_balloc, const nrf_balloc_t _name) = \ + { \ + .p_cb = &CONCAT_2(_name,_nrf_balloc_cb), \ + .p_stack_base = CONCAT_2(_name,_nrf_balloc_pool_stack), \ + .p_stack_limit = CONCAT_2(_name,_nrf_balloc_pool_stack) + (_pool_size), \ + .p_memory_begin = CONCAT_2(_name,_nrf_balloc_pool_mem), \ + .block_size = NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags), \ + \ + NRF_LOG_INSTANCE_PTR_INIT(p_log, NRF_BALLOC_LOG_NAME, _name) \ + __NRF_BALLOC_ASSIGN_POOL_NAME(_name) \ + __NRF_BALLOC_ASSIGN_DEBUG_FLAGS(_debug_flags) \ + } + +/**@brief Create a block allocator instance. + * + * @note This macro reserves memory for the given block allocator instance. + * + * @param[in] _name Name of the allocator. + * @param[in] _element_size Size of one element. + * @param[in] _pool_size Size of the pool. + */ +#define NRF_BALLOC_DEF(_name, _element_size, _pool_size) \ + NRF_BALLOC_DBG_DEF(_name, _element_size, _pool_size, NRF_BALLOC_DEFAULT_DEBUG_FLAGS) + +/**@brief Create a block allocator interface. + * + * @param[in] _type Type which is allocated. + * @param[in] _name Name of the allocator. + */ +#define NRF_BALLOC_INTERFACE_DEC(_type, _name) \ + _type * CONCAT_2(_name,_alloc)(void); \ + void CONCAT_2(_name,_free)(_type * p_element) + +/**@brief Define a custom block allocator interface. + * + * @param[in] _attr Function attribute that will be added to allocator function definition. + * @param[in] _type Type which is allocated. + * @param[in] _name Name of the allocator. + * @param[in] _p_pool Pool from which data will be allocated. + */ +#define NRF_BALLOC_INTERFACE_CUSTOM_DEF(_attr, _type, _name, _p_pool) \ + _attr _type * CONCAT_2(_name,_alloc)(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_pool) != NULL); \ + ASSERT((_p_pool)->block_size >= \ + NRF_BALLOC_BLOCK_SIZE(sizeof(_type), (_p_pool)->debug_flags)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return (_type *)(nrf_balloc_alloc(_p_pool)); \ + } \ + \ + _attr void CONCAT_2(_name,_free)(_type * p_element) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_pool) != NULL); \ + ASSERT((_p_pool)->block_size >= \ + NRF_BALLOC_BLOCK_SIZE(sizeof(_type), (_p_pool)->debug_flags)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + nrf_balloc_free((_p_pool), p_element); \ + } + +/**@brief Define block allocator interface. + * + * @param[in] _type Type which is allocated. + * @param[in] _name Name of the allocator. + * @param[in] _p_pool Pool from which data will be allocated. + */ +#define NRF_BALLOC_INTERFACE_DEF(_type, _name, _p_pool) \ + NRF_BALLOC_INTERFACE_CUSTOM_DEF(/* empty */, _type, _name, _p_pool) + +/**@brief Define a local block allocator interface. + * + * @param[in] _type Type which is allocated. + * @param[in] _name Name of the allocator. + * @param[in] _p_pool Pool from which data will be allocated. + */ +#define NRF_BALLOC_INTERFACE_LOCAL_DEF(_type, _name, _p_pool) \ + NRF_BALLOC_INTERFACE_CUSTOM_DEF(static, _type, _name, _p_pool) + +/**@brief Function for initializing a block memory allocator pool. + * + * @param[out] p_pool Pointer to the pool that is to be initialized. + * + * @return NRF_SUCCESS on success, otherwise error code. + */ +ret_code_t nrf_balloc_init(nrf_balloc_t const * p_pool); + +/**@brief Function for allocating an element from the pool. + * + * @note This module guarantees that the returned memory is aligned to 4. + * + * @param[in] p_pool Pointer to the memory pool from which the element will be allocated. + * + * @return Allocated element or NULL if the specified pool is empty. + */ +void * nrf_balloc_alloc(nrf_balloc_t const * p_pool); + +/**@brief Function for freeing an element back to the pool. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] p_element Element to be freed. + */ +void nrf_balloc_free(nrf_balloc_t const * p_pool, void * p_element); + +/**@brief Function for getting maximum memory pool utilization. + * + * @param[in] p_pool Pointer to the memory pool instance. + * + * @return Maximum number of elements allocated from the pool. + */ +__STATIC_INLINE uint8_t nrf_balloc_max_utilization_get(nrf_balloc_t const * p_pool); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE uint8_t nrf_balloc_max_utilization_get(nrf_balloc_t const * p_pool) +{ + ASSERT(p_pool != NULL); + return p_pool->p_cb->max_utilization; +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION + +/**@brief Function for getting current memory pool utilization. + * + * @param[in] p_pool Pointer to the memory pool instance. + * + * @return Maximum number of elements allocated from the pool. + */ +__STATIC_INLINE uint8_t nrf_balloc_utilization_get(nrf_balloc_t const * p_pool); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE uint8_t nrf_balloc_utilization_get(nrf_balloc_t const * p_pool) +{ + ASSERT(p_pool != NULL); + return (p_pool->p_stack_limit - p_pool->p_cb->p_stack_pointer); +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION + +#ifdef __cplusplus +} +#endif + +#endif // NRF_BALLOC_H__ +/** @} */ diff --git a/components/libraries/bootloader/ant_dfu/nrf_dfu_ant.c b/components/libraries/bootloader/ant_dfu/nrf_dfu_ant.c new file mode 100644 index 0000000..5c53638 --- /dev/null +++ b/components/libraries/bootloader/ant_dfu/nrf_dfu_ant.c @@ -0,0 +1,772 @@ +/** + * This software is subject to the ANT+ Shared Source License + * www.thisisant.com/swlicenses + * Copyright (c) Garmin Canada Inc. 2018 + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1) Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3) Neither the name of Garmin nor the names of its + * contributors may be used to endorse or promote products + * derived from this software without specific prior + * written permission. + * + * The following actions are prohibited: + * + * 1) Redistribution of source code containing the ANT+ Network + * Key. The ANT+ Network Key is available to ANT+ Adopters. + * Please refer to http://thisisant.com to become an ANT+ + * Adopter and access the key. + * + * 2) Reverse engineering, decompilation, and/or disassembly of + * software provided in binary form under this license. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE HEREBY + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; DAMAGE TO ANY DEVICE, LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. SOME STATES DO NOT ALLOW + * THE EXCLUSION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE + * ABOVE LIMITATIONS MAY NOT APPLY TO YOU. + * + */ + +#include +#include +#include "sdk_common.h" + +#include "ant_channel_config.h" +#include "ant_interface.h" +#include "ant_parameters.h" +#include "nrf_assert.h" +#include "nrf_balloc.h" +#include "nrf_bootloader_info.h" +#include "nrf_dfu_handling_error.h" +#include "nrf_dfu_req_handler.h" +#include "nrf_dfu_transport.h" +#include "nrf_dfu_mbr.h" +#include "nrf_sdh.h" +#include "nrf_sdh_ant.h" +#include "nrf_soc.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_ant +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/**@file + * + * @defgroup nrf_dfu_ant ANT transport for reference DFU. + * @ingroup nrf_dfu + * @brief Device Firmware Update (DFU) transport layer using ANT. + * + * Transport documentation: + * + * The ANT transport uses all of the same opcodes and payload formats as the + * UART serial transport. The only differences are the packet header format and + * some extra details to deal with retransmissions. + * + * The device receiving the update is the ANT master. The format of the + * broadcast buffer is as follows; + * Byte 0: Current Slave -> Master sequence number. + * Byte 1: Current Master -> Slave sequence number. + * Bytes 2-7: Reserved, set to 0. + * + * The sequence numbers are used to detect retransmissions, any messages sent + * with a sequence number equivalent to the current sequence will be ignored. + * + * When the slave first connects to the master it should inspect the broadcast + * data in order to synchronize its sequence counters. + * + * All commands/responses are padded out to the nearest 8-byte boundary after + * framing, and then sent using either a burst or acknowledged data depending on + * length (ack data is used for 8-byte messages). The message transmission is + * retried until an EVENT_TRANSFER_TX_COMPLETE event is received. + * All messages are framed using the following format: + * Bytes 0-1: Message length before padding, little endian, includes header. + * Byte 2: Sequence number. Increment for every new message. + * Byte 3: Op code. Always 0x60 for responses. + * Bytes 4-N: Command/Response payload. This follows the same format as the + * UART serial transport, without any SLIP encoding. + * + * As a final note, the MTU for this protocol is the maximum size of a burst + * that can be received. + */ + +/** Packet header is always 2 byte length + seq num + op code */ +#define PKT_HEADER_SIZE 4 + +/** Maximum size of the payload in a write command. */ +#define MAX_WRITE_PAYLOAD (NRF_DFU_ANT_MTU - PKT_HEADER_SIZE) + +/** Bursts are always a multiple of the standard data size. */ +STATIC_ASSERT_MSG( + ALIGN_NUM(ANT_STANDARD_DATA_PAYLOAD_SIZE, NRF_DFU_ANT_MTU) == NRF_DFU_ANT_MTU, + "ANT MTU must be a multiple of " STRINGIFY(ANT_STANDARD_DATA_PAYLOAD_SIZE)); + +/** Number of buffers to reserve space for with balloc. */ +#if (NRF_DFU_ANT_BUFFERS_OVERRIDE) +#define NUM_BUFFERS NRF_DFU_ANT_BUFFERS +#else +#define NUM_BUFFERS CEIL_DIV(CODE_PAGE_SIZE, MAX_WRITE_PAYLOAD) +#endif + +static uint32_t ant_dfu_init(nrf_dfu_observer_t observer); +static uint32_t ant_dfu_close(nrf_dfu_transport_t const * p_exception); + +static ant_channel_config_t m_channel_config = { + .channel_number = 0, + .channel_type = CHANNEL_TYPE_MASTER, + .rf_freq = NRF_DFU_ANT_RF_FREQ, + .transmission_type = 1, // Non-shared, no global pages. + .device_type = NRF_DFU_ANT_DEV_TYPE, + .channel_period = NRF_DFU_ANT_CHANNEL_PERIOD, +}; + +static nrf_dfu_observer_t m_observer; +/** Has transport been initialized by DFU core */ +static bool m_initialized = false; +/** Has the channel started broadcasting */ +static bool m_started = false; +/** Has some data been received on the transport. */ +static bool m_active = false; + +/** State tracking for rx transfers. */ +static struct +{ + /** Buffer for holding the command. */ + uint8_t * buff; + /** Amount of data written */ + size_t offset; + /** Sequence of last processed command. */ + uint8_t seq; +} m_rx; + +/** State tracking for tx transfers. */ +static struct +{ + /** Raw data to send. */ + uint8_t resp[ALIGN_NUM(ANT_STANDARD_DATA_PAYLOAD_SIZE, + PKT_HEADER_SIZE + sizeof(nrf_dfu_response_t))]; + /** Length of data to send. 0 Indicates no response queued. */ + size_t len; + /** Sequence number of last queued response. */ + uint8_t seq; + /** + * Used as burst flag for softdevice, allows to busy loop until all data is + * accepted by softdevice. + */ + volatile bool buffering; + /** + * Indicate that a new response was generated before the last one was + * confirmed. + */ + bool response_overwritten; + /** Data buffer used for broadcast messages. */ + uint8_t bcast_data[ANT_STANDARD_DATA_PAYLOAD_SIZE]; +} m_tx; + +/** State tracking for progress notifications. */ +static struct +{ + /** Requested PRN */ + uint16_t limit; + /** How many more write commands until a CRC should be sent back. */ + uint16_t remaining; +} m_pkt_notify; + +DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const ant_dfu_transport) = { + .init_func = ant_dfu_init, + .close_func = ant_dfu_close, +}; + +NRF_BALLOC_DEF(m_buffer_pool, NRF_DFU_ANT_MTU, NUM_BUFFERS); + +static void release_rx_buff(void) +{ + if (m_rx.buff != NULL) + { + nrf_balloc_free(&m_buffer_pool, m_rx.buff); + m_rx.buff = NULL; + } +} + +static void transmit_response(void) +{ + uint32_t err_code = NRF_SUCCESS; + + size_t full_len = ALIGN_NUM(ANT_STANDARD_DATA_PAYLOAD_SIZE, m_tx.len); + + // Pad out with 0's. + memset(&m_tx.resp[m_tx.len], 0, full_len - m_tx.len); + + if (full_len > ANT_STANDARD_DATA_PAYLOAD_SIZE) + { + err_code = sd_ant_burst_handler_request( + m_channel_config.channel_number, + full_len, m_tx.resp, + BURST_SEGMENT_START | BURST_SEGMENT_END); + } else + { + err_code = sd_ant_acknowledge_message_tx( + m_channel_config.channel_number, + full_len, m_tx.resp); + } + + // Wait for buffer to be consumed. + // TODO: wait flag management needs to be improved if this will coexist with + // other channels. + while (err_code == NRF_SUCCESS && m_tx.buffering) + { + err_code = sd_app_evt_wait(); + } + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Sending response failed with error %d", err_code); + } +} + +static void update_bcast_data(void) +{ + memset(m_tx.bcast_data, 0, sizeof(m_tx.bcast_data)); + m_tx.bcast_data[0] = m_rx.seq; + m_tx.bcast_data[1] = m_tx.seq; + + if (NRF_SUCCESS != sd_ant_broadcast_message_tx( + m_channel_config.channel_number, + sizeof(m_tx.bcast_data), m_tx.bcast_data)) + { + NRF_LOG_WARNING("Unable to update broadcast data."); + } +} + +static void handle_write_complete(void * p_buf) +{ + nrf_balloc_free(&m_buffer_pool, p_buf); +} + +static void prepare_response(nrf_dfu_response_t * p_res) +{ + if (m_tx.len) + { + NRF_LOG_WARNING("Overwriting previous response."); + m_tx.response_overwritten = true; + } + + // reserve first 2 bytes for length. + m_tx.len = 2; + + m_tx.resp[m_tx.len++] = ++(m_tx.seq); + m_tx.resp[m_tx.len++] = NRF_DFU_OP_RESPONSE; + m_tx.resp[m_tx.len++] = p_res->request; + m_tx.resp[m_tx.len++] = p_res->result; + + if (p_res->result == NRF_DFU_RES_CODE_SUCCESS) + { + switch(p_res->request) + { + case NRF_DFU_OP_PROTOCOL_VERSION: + { + m_tx.resp[m_tx.len++] = p_res->protocol.version; + } break; + + case NRF_DFU_OP_CRC_GET: + { + m_tx.len += uint32_encode( + p_res->crc.offset, &m_tx.resp[m_tx.len]); + m_tx.len += uint32_encode( + p_res->crc.crc, &m_tx.resp[m_tx.len]); + } break; + + case NRF_DFU_OP_OBJECT_SELECT: + { + m_tx.len += uint32_encode( + p_res->select.max_size, &m_tx.resp[m_tx.len]); + m_tx.len += uint32_encode( + p_res->select.offset, &m_tx.resp[m_tx.len]); + m_tx.len += uint32_encode( + p_res->select.crc, &m_tx.resp[m_tx.len]); + } break; + + case NRF_DFU_OP_MTU_GET: + { + m_tx.len += uint16_encode( + p_res->mtu.size, &m_tx.resp[m_tx.len]); + } break; + + case NRF_DFU_OP_PING: + { + m_tx.resp[m_tx.len++] = p_res->ping.id; + } break; + + case NRF_DFU_OP_HARDWARE_VERSION: + { + m_tx.len += uint32_encode( + p_res->hardware.part, &m_tx.resp[m_tx.len]); + m_tx.len += uint32_encode( + p_res->hardware.variant, &m_tx.resp[m_tx.len]); + m_tx.len += uint32_encode( + p_res->hardware.memory.rom_size, &m_tx.resp[m_tx.len]); + m_tx.len += uint32_encode( + p_res->hardware.memory.rom_page_size, &m_tx.resp[m_tx.len]); + m_tx.len += uint32_encode( + p_res->hardware.memory.ram_size, &m_tx.resp[m_tx.len]); + } break; + + case NRF_DFU_OP_FIRMWARE_VERSION: + { + m_tx.resp[m_tx.len++] = p_res->firmware.type; + m_tx.len += uint32_encode( + p_res->firmware.version, &m_tx.resp[m_tx.len]); + m_tx.len += uint32_encode( + p_res->firmware.addr, &m_tx.resp[m_tx.len]); + m_tx.len += uint32_encode( + p_res->firmware.len, &m_tx.resp[m_tx.len]); + } break; + + default: + break; + } + } + else if (p_res->result == NRF_DFU_RES_CODE_EXT_ERROR) + { + m_tx.resp[m_tx.len++] = ext_error_get(); + UNUSED_RETURN_VALUE(ext_error_set(NRF_DFU_EXT_ERROR_NO_ERROR)); + } + + // Finally fill in the length. + UNUSED_RETURN_VALUE(uint16_encode(m_tx.len, m_tx.resp)); + + // Safety check buffer overflow. + ASSERT(m_tx.len <= sizeof(m_tx.resp)); + + if (!m_tx.response_overwritten) + { + // Can send out the response immediately if there wasn't a previous one + // queued. + transmit_response(); + } +} + +static void handle_response(nrf_dfu_response_t * p_res, void * p_context) +{ + UNUSED_PARAMETER(p_context); + + if (p_res->result != NRF_DFU_RES_CODE_SUCCESS) + { + NRF_LOG_WARNING("Operation %d had result %d", + p_res->request, p_res->result); + } + + if (p_res->request == NRF_DFU_OP_OBJECT_WRITE) + { + if (m_pkt_notify.limit == 0 || + --m_pkt_notify.remaining != 0) + { + // No packet notification needed, filter out response. + return; + } + + // Packet Notification time, send a CRC response. + m_pkt_notify.remaining = m_pkt_notify.limit; + p_res->request = NRF_DFU_OP_CRC_GET; + uint32_t offset = p_res->write.offset; + uint32_t crc = p_res->write.crc; + p_res->crc.offset = offset; + p_res->crc.crc = crc; + } + + prepare_response(p_res); +} + +static uint32_t handle_request(void) +{ + uint16_t len = uint16_decode(m_rx.buff); + uint16_t offset = sizeof(uint16_t); + + if (len < PKT_HEADER_SIZE || len > m_rx.offset) + { + NRF_LOG_WARNING("Ignoring command with invalid length."); + return NRF_ERROR_DATA_SIZE; + } + + uint8_t seq = m_rx.buff[offset++]; + if (!m_active) + { + m_active = true; + // Close all other transports. + UNUSED_RETURN_VALUE(nrf_dfu_transports_close(&ant_dfu_transport)); + } + else if (seq == m_rx.seq) + { + NRF_LOG_DEBUG("Ignoring repeated command"); + return NRF_SUCCESS; + } + + m_rx.seq = seq; + + nrf_dfu_request_t request = { + .request = (nrf_dfu_op_t)m_rx.buff[offset++], + .callback.response = handle_response, + }; + + switch(request.request) + { + case NRF_DFU_OP_OBJECT_CREATE: + { + request.create.object_type = m_rx.buff[offset++]; + request.create.object_size = uint32_decode(&m_rx.buff[offset]); + offset += sizeof(uint32_t); + } break; + + case NRF_DFU_OP_RECEIPT_NOTIF_SET: + { + request.prn.target = uint16_decode(&m_rx.buff[offset]); + offset += sizeof(uint16_t); + } break; + + case NRF_DFU_OP_OBJECT_SELECT: + { + request.select.object_type = m_rx.buff[offset++]; + } break; + + case NRF_DFU_OP_OBJECT_WRITE: + { + request.write.p_data = &m_rx.buff[offset]; + request.write.len = len - offset; + offset = len; + } break; + + case NRF_DFU_OP_PING: + { + request.ping.id = m_rx.buff[offset++]; + } break; + + case NRF_DFU_OP_FIRMWARE_VERSION: + { + request.firmware.image_number = m_rx.buff[offset++]; + } break; + + case NRF_DFU_OP_MTU_GET: + { + NRF_LOG_DEBUG("ANT DFU: Responding to MTU request with %d", + NRF_DFU_ANT_MTU); + request.mtu.size = NRF_DFU_ANT_MTU; + } break; + + default: + // Do nothing. + break; + } + + if (offset > len) + { + NRF_LOG_WARNING("Ignoring command with invalid length"); + return NRF_ERROR_DATA_SIZE; + } + + // Some processing that is only safe to do if accepting the command. + + switch (request.request) + { + case NRF_DFU_OP_RECEIPT_NOTIF_SET: + { + m_pkt_notify.limit = request.prn.target; + m_pkt_notify.remaining = m_pkt_notify.limit; + } break; + + case NRF_DFU_OP_OBJECT_CREATE: + case NRF_DFU_OP_OBJECT_SELECT: + { + m_pkt_notify.remaining = m_pkt_notify.limit; + } break; + + case NRF_DFU_OP_OBJECT_WRITE: + { + // Ownership of buffer is transferred to the write command. + request.callback.write = handle_write_complete; + m_rx.buff = NULL; + } break; + + default: + break; + } + + return nrf_dfu_req_handler_on_req(&request); +} + +static void handle_tx_transfer_complete(bool success) +{ + if (m_tx.response_overwritten) + { + // By treating the result as a failure the retransmission will send out + // the new response. + success = false; + m_tx.response_overwritten = false; + } + + if (success) + { + m_tx.len = 0; + update_bcast_data(); + } + else + { + transmit_response(); + } +} + +static void handle_rx_transfer_start() +{ + if (m_rx.buff == NULL) + { + m_rx.buff = nrf_balloc_alloc(&m_buffer_pool); + if (m_rx.buff != NULL) + { + NRF_LOG_INFO("Allocated buffer %x", m_rx.buff); + } + else + { + NRF_LOG_ERROR("Unable to allocate buffer for incoming packet."); + return; + } + } + + NRF_LOG_DEBUG("Resetting rx pointer."); + m_rx.offset = 0; +} + +static void handle_rx_transfer_complete(bool success) +{ + if (success) + { + uint32_t err_code = handle_request(); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Error %d handling request.", err_code); + } + } + + release_rx_buff(); +} + +static void handle_rx_transfer_data(uint8_t * data, size_t len) +{ + if (m_rx.buff == NULL) + { + NRF_LOG_DEBUG("Ignoring transfer data."); + return; + } + + if (m_rx.offset + len > NRF_DFU_ANT_MTU) + { + NRF_LOG_ERROR("Received packet overflows MTU."); + handle_rx_transfer_complete(false); + return; + } + + memcpy(&m_rx.buff[m_rx.offset], data, len); + m_rx.offset += len; +} + +static void handle_data_mesg(ANT_MESSAGE * p_msg) +{ + bool is_first = false; + bool is_last = false; + uint8_t len = ANT_STANDARD_DATA_PAYLOAD_SIZE; + + switch(p_msg->ANT_MESSAGE_ucMesgID) + { + case MESG_BROADCAST_DATA_ID: + { + // Broadcast data is ignored. + len = 0; + } break; + + case MESG_ACKNOWLEDGED_DATA_ID: + { + is_first = true; + is_last = true; + } break; + + case MESG_ADV_BURST_DATA_ID: + { + len = p_msg->ANT_MESSAGE_ucSize - MESG_CHANNEL_NUM_SIZE; + } // FALL-THROUGH : both burst types act the same other than len. + case MESG_BURST_DATA_ID: + { + uint8_t seq = p_msg->ANT_MESSAGE_ucChannel & SEQUENCE_NUMBER_MASK; + is_first = seq == SEQUENCE_FIRST_MESSAGE; + is_last = !!(seq & SEQUENCE_LAST_MESSAGE); + } break; + } + + if (len != 0) + { + if (is_first) + { + handle_rx_transfer_start(); + } + + handle_rx_transfer_data(p_msg->ANT_MESSAGE_aucPayload, len); + + if (is_last) + { + handle_rx_transfer_complete(true); + } + } +} + +static void ant_dfu_evt_handler(ant_evt_t * p_ant_evt, void * p_context) +{ + // Ignore messages meant for other channels. + if (p_ant_evt->channel != m_channel_config.channel_number) + { + return; + } + + switch(p_ant_evt->event) + { + case EVENT_TX: + { + if (!m_started) + { + m_started = true; + m_observer(NRF_DFU_EVT_TRANSPORT_ACTIVATED); + } + } break; + + case EVENT_TRANSFER_TX_COMPLETED: + handle_tx_transfer_complete(true); + break; + case EVENT_TRANSFER_TX_FAILED: + handle_tx_transfer_complete(false); + break; + + case EVENT_RX: + handle_data_mesg(&p_ant_evt->message); + break; + + case EVENT_TRANSFER_RX_FAILED: + handle_rx_transfer_complete(false); + break; + } +} + +static uint32_t ant_dfu_init(nrf_dfu_observer_t observer) +{ + uint32_t err_code = NRF_SUCCESS; + if (m_initialized) + { + return err_code; + } + + NRF_SDH_ANT_OBSERVER(ant_dfu_observer, NRF_DFU_ANT_EVT_HANDLER_PRIO, + ant_dfu_evt_handler, NULL); + + m_observer = observer; + m_tx.seq = m_rx.seq = 0; + m_active = false; + m_started = false; + + NRF_LOG_DEBUG("Initializing ANT DFU transport"); + + err_code = nrf_balloc_init(&m_buffer_pool); + VERIFY_SUCCESS(err_code); + + err_code = nrf_dfu_mbr_init_sd(); + VERIFY_SUCCESS(err_code); + + NRF_LOG_DEBUG("Setting up vector table: 0x%08x", BOOTLOADER_START_ADDR); + err_code = sd_softdevice_vector_table_base_set(BOOTLOADER_START_ADDR); + VERIFY_SUCCESS(err_code); + + NRF_LOG_DEBUG("Enabling softdevice"); + err_code = nrf_sdh_enable_request(); + VERIFY_SUCCESS(err_code); + + err_code = nrf_sdh_ant_enable(); + VERIFY_SUCCESS(err_code); + + static uint8_t adv_burst_conf[] = { + ADV_BURST_MODE_ENABLE, + ADV_BURST_MODES_SIZE_24_BYTES, + 0, // No required modes. + 0, 0, // Reserved + ADV_BURST_MODES_FREQ_HOP, // Optional Modes + 0, 0, // Reserved + // No optional configs. + }; + err_code = sd_ant_adv_burst_config_set(adv_burst_conf, sizeof(adv_burst_conf)); + VERIFY_SUCCESS(err_code); + + m_channel_config.device_number = NRF_FICR->DEVICEID[0]; + m_channel_config.transmission_type |= (NRF_FICR->DEVICEID[1] & 0xF) << 4; + + err_code = ant_channel_init(&m_channel_config); + VERIFY_SUCCESS(err_code); + + update_bcast_data(); + + err_code = sd_ant_channel_open(m_channel_config.channel_number); + VERIFY_SUCCESS(err_code); + + NRF_LOG_DEBUG("ANT transport intialized"); + + m_initialized = true; + return err_code; +} + +static uint32_t ant_dfu_close(nrf_dfu_transport_t const * p_exception) +{ + uint32_t err_code = NRF_SUCCESS; + + if (p_exception != &ant_dfu_transport && m_initialized) + { + NRF_LOG_DEBUG("Shutting down ANT DFU transport"); + + m_initialized = false; + + err_code = sd_ant_channel_close(m_channel_config.channel_number); + VERIFY_SUCCESS(err_code); + + uint8_t status; + do + { + // The initial wait is safe because the close command above would + // have generated at least 1 app event. + err_code = sd_app_evt_wait(); + VERIFY_SUCCESS(err_code); + err_code = sd_ant_channel_status_get( + m_channel_config.channel_number, &status); + VERIFY_SUCCESS(err_code); + } while ((status & STATUS_CHANNEL_STATE_MASK) != STATUS_ASSIGNED_CHANNEL); + + err_code = nrf_sdh_disable_request(); + VERIFY_SUCCESS(err_code); + + NRF_LOG_DEBUG("ANT transport disabled."); + } + + return err_code; +} diff --git a/components/libraries/bootloader/ble_dfu/nrf_dfu_ble.c b/components/libraries/bootloader/ble_dfu/nrf_dfu_ble.c new file mode 100644 index 0000000..a2fdf5e --- /dev/null +++ b/components/libraries/bootloader/ble_dfu/nrf_dfu_ble.c @@ -0,0 +1,1261 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu_ble.h" + +#include +#include "sdk_common.h" +#include "nrf_dfu_transport.h" +#include "nrf_dfu_types.h" +#include "nrf_dfu_req_handler.h" +#include "nrf_dfu_handling_error.h" +#include "nrf_sdm.h" +#include "nrf_dfu_mbr.h" +#include "nrf_bootloader_info.h" +#include "ble.h" +#include "ble_srv_common.h" +#include "ble_hci.h" +#include "nrf_sdh.h" +#include "nrf_sdh_ble.h" +#include "nrf_balloc.h" +#include "nrf_delay.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_ble.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_ble +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#ifndef NRF_DFU_BLE_ADV_INTERVAL +#define NRF_DFU_BLE_ADV_INTERVAL 40 /* 40 * 0,625ms = 25ms */ +#warning "sdk_config.h is not up to date." +#endif + +#define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */ + +#define APP_ADV_DATA_HEADER_SIZE 9 /**< Size of encoded advertisement data header (not including device name). */ +#define APP_ADV_DURATION BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED /**< The advertising duration in units of 10 milliseconds. This is set to @ref BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED so that the advertisement is done as long as there there is a call to @ref dfu_transport_close function.*/ + +#define GATT_HEADER_LEN 3 /**< GATT header length. */ +#define GATT_PAYLOAD(mtu) ((mtu) - GATT_HEADER_LEN) /**< Length of the ATT payload for a given ATT MTU. */ +#define MAX_DFU_PKT_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - GATT_HEADER_LEN) /**< Maximum length (in bytes) of the DFU Packet characteristic (3 bytes are used for the GATT opcode and handle). */ +#define MAX_RESPONSE_LEN 17 /**< Maximum length (in bytes) of the response to a Control Point command. */ +#define RESPONSE_HEADER_LEN 3 /**< The length of the header of a response. I.E. the index of the opcode-specific payload. */ + +#define DFU_BLE_FLAG_INITIALIZED (1 << 0) /**< Flag to check if the DFU service was initialized by the application.*/ +#define DFU_BLE_FLAG_USE_ADV_NAME (1 << 1) /**< Flag to indicate that advertisement name is to be used. */ +#define DFU_BLE_RESETTING_SOON (1 << 2) /**< Flag to indicate that the device will reset soon. */ + +#define BLE_OBSERVER_PRIO 2 /**< BLE observer priority. Controls the priority for BLE event handler. */ + +#if (NRF_DFU_BLE_BUFFERS_OVERRIDE) +/* If selected, use the override value. */ +#define MAX_DFU_BUFFERS NRF_DFU_BLE_BUFFERS +#else +#define MAX_DFU_BUFFERS ((CODE_PAGE_SIZE / MAX_DFU_PKT_LEN) + 1) +#endif + +#if (NRF_DFU_BLE_REQUIRES_BONDS) && (!NRF_SDH_BLE_SERVICE_CHANGED) +#error NRF_DFU_BLE_REQUIRES_BONDS requires NRF_SDH_BLE_SERVICE_CHANGED. \ + Please update the SoftDevice BLE stack configuration in sdk_config.h +#endif + +#if (MAX_DFU_PKT_LEN % 4) +#error Payload length should be a multiple of four. \ + Payload length is set to NRF_SDH_BLE_GATT_MAX_MTU_SIZE - 3. +#endif + + +DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const ble_dfu_transport) = +{ + .init_func = ble_dfu_transport_init, + .close_func = ble_dfu_transport_close, +}; + +#if (NRF_DFU_BLE_REQUIRES_BONDS) +static nrf_dfu_peer_data_t m_peer_data; +#else +static nrf_dfu_adv_name_t m_adv_name; +#endif + +static uint32_t m_flags; +static ble_dfu_t m_dfu; /**< Structure used to identify the Device Firmware Update service. */ +static uint16_t m_pkt_notif_target; /**< Number of packets of firmware data to be received before transmitting the next Packet Receipt Notification to the DFU Controller. */ +static uint16_t m_pkt_notif_target_cnt; /**< Number of packets of firmware data received after sending last Packet Receipt Notification or since the receipt of a @ref BLE_DFU_PKT_RCPT_NOTIF_ENABLED event from the DFU service, which ever occurs later.*/ +static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */ +static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; /**< Advertising handle used to identify an advertising set. */ +static nrf_dfu_observer_t m_observer; /**< Observer function called on certain events. */ + +static ble_gap_conn_params_t const m_gap_conn_params = +{ + .min_conn_interval = NRF_DFU_BLE_MIN_CONN_INTERVAL, + .max_conn_interval = NRF_DFU_BLE_MAX_CONN_INTERVAL, + /* This value is expressed in units of 10 ms, rather than 1 ms. */ + .conn_sup_timeout = NRF_DFU_BLE_CONN_SUP_TIMEOUT_MS / 10, + .slave_latency = 0, +}; + +NRF_BALLOC_DEF(m_buffer_pool, MAX_DFU_PKT_LEN, MAX_DFU_BUFFERS); + + +/**@brief Function for the Advertising functionality initialization. + * + * @details Encodes the required advertising data and passes it to the stack. + * The advertising data encoded here is specific for DFU. + */ +static uint32_t advertising_init(uint8_t adv_flags, ble_gap_adv_params_t const * const p_adv_params) +{ + uint32_t err_code; + uint16_t actual_device_name_length = BLE_GAP_ADV_SET_DATA_SIZE_MAX - APP_ADV_DATA_HEADER_SIZE; + + /* This needs to be static because of SoftDevice API requirements. */ + static uint8_t m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX]; + + ble_gap_adv_data_t m_adv_data = + { + .adv_data = + { + .p_data = m_enc_advdata, + .len = APP_ADV_DATA_HEADER_SIZE, + } + }; + + /* Encode flags. */ + m_enc_advdata[0] = 0x2; + m_enc_advdata[1] = BLE_GAP_AD_TYPE_FLAGS; + m_enc_advdata[2] = adv_flags; + + /* Encode 'more available' UUID list. */ + m_enc_advdata[3] = 0x3; + m_enc_advdata[4] = BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE; + m_enc_advdata[5] = LSB_16(BLE_DFU_SERVICE_UUID); + m_enc_advdata[6] = MSB_16(BLE_DFU_SERVICE_UUID); + + /* Get GAP device name and length. */ + err_code = sd_ble_gap_device_name_get(&m_enc_advdata[9], &actual_device_name_length); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + // Set GAP device in advertising data. + m_enc_advdata[7] = actual_device_name_length + 1; // (actual_length + ADV_AD_TYPE_FIELD_SIZE(1)) + m_enc_advdata[8] = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; + + m_adv_data.adv_data.len += actual_device_name_length; + + return sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, p_adv_params); +} + + +/**@brief Function for starting advertising. + */ +static uint32_t advertising_start(void) +{ + uint32_t err_code; + uint8_t adv_flag = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; + + ble_gap_adv_params_t adv_params = + { + .properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED, + .p_peer_addr = NULL, + .filter_policy = BLE_GAP_ADV_FP_ANY, + .interval = NRF_DFU_BLE_ADV_INTERVAL, + .duration = APP_ADV_DURATION, + .primary_phy = BLE_GAP_PHY_1MBPS, + }; + + NRF_LOG_DEBUG("Advertising..."); + +#if (NRF_DFU_BLE_REQUIRES_BONDS) + ble_gap_irk_t empty_irk = {{0}}; + + if (memcmp(m_peer_data.ble_id.id_info.irk, empty_irk.irk, sizeof(ble_gap_irk_t)) != 0) + { + adv_flag = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; + adv_params.filter_policy = BLE_GAP_ADV_FP_FILTER_CONNREQ; + + ble_gap_addr_t const * const p_gap_addr = &m_peer_data.ble_id.id_addr_info; + ble_gap_id_key_t const * const p_gap_id_key = &m_peer_data.ble_id; + + err_code = sd_ble_gap_whitelist_set(&p_gap_addr, 1); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_WARNING("sd_ble_gap_whitelist_set() returned %s", + NRF_LOG_ERROR_STRING_GET(err_code)); + } + + err_code = sd_ble_gap_device_identities_set(&p_gap_id_key, NULL, 1); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_WARNING("sd_ble_gap_device_identities_set() returned %s", + NRF_LOG_ERROR_STRING_GET(err_code)); + } + } +#endif /* NRF_DFU_BLE_REQUIRES_BONDS */ + + err_code = advertising_init(adv_flag, &adv_params); + VERIFY_SUCCESS(err_code); + + err_code = sd_ble_gap_adv_stop(m_adv_handle); + UNUSED_RETURN_VALUE(err_code); + + return sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG); +} + + +static bool is_cccd_configured(ble_dfu_t * p_dfu) +{ + uint8_t cccd_val_buf[BLE_CCCD_VALUE_LEN]; + + ble_gatts_value_t gatts_value = + { + .len = BLE_CCCD_VALUE_LEN, + .p_value = cccd_val_buf + }; + + /* Check the CCCD Value of DFU Control Point. */ + uint32_t err_code = sd_ble_gatts_value_get(m_conn_handle, + p_dfu->dfu_ctrl_pt_handles.cccd_handle, + &gatts_value); + VERIFY_SUCCESS(err_code); + + return ble_srv_is_notification_enabled(cccd_val_buf); +} + + +static ret_code_t response_send(uint8_t * p_buf, uint16_t len) +{ + ble_gatts_hvx_params_t hvx_params = + { + .handle = m_dfu.dfu_ctrl_pt_handles.value_handle, + .type = BLE_GATT_HVX_NOTIFICATION, + .p_data = (uint8_t *)(p_buf), + .p_len = &len, + }; + + return sd_ble_gatts_hvx(m_conn_handle, &hvx_params); +} + + +#if (NRF_DFU_BLE_REQUIRES_BONDS) +static uint32_t service_changed_send(void) +{ + uint32_t err_code; + + NRF_LOG_DEBUG("Sending Service Changed indication"); + + err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, + m_peer_data.sys_serv_attr, + sizeof(m_peer_data.sys_serv_attr), + BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS); + VERIFY_SUCCESS(err_code); + + err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, + NULL, + 0, + BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS); + VERIFY_SUCCESS(err_code); + + err_code = sd_ble_gatts_service_changed(m_conn_handle, m_dfu.service_handle, 0xFFFF); + + if ( (err_code == BLE_ERROR_INVALID_CONN_HANDLE) + || (err_code == NRF_ERROR_INVALID_STATE) + || (err_code == NRF_ERROR_BUSY)) + { + /* These errors can be expected when trying to send a Service Changed indication */ + /* if the CCCD is not set to indicate. Thus, set the returning error code to success. */ + NRF_LOG_WARNING("Client did not have the Service Changed indication set to enabled." + "Error: 0x%08x", err_code); + err_code = NRF_SUCCESS; + } + + return err_code; +} +#endif + + +/**@brief Function for encoding the beginning of a response. + * + * @param[inout] p_buffer The buffer to encode into. + * @param[in] op_code The opcode of the response. + * @param[in] result The result of the operation. + * + * @return The length added to the buffer. + */ +static uint32_t response_prepare(uint8_t * p_buffer, uint8_t op_code, uint8_t result) +{ + ASSERT(p_buffer); + p_buffer[0] = NRF_DFU_OP_RESPONSE; + p_buffer[1] = op_code; + p_buffer[2] = result; + return RESPONSE_HEADER_LEN; +} + + +/**@brief Function for encoding a select object response into a buffer. + * + * The select object response consists of a maximum object size, a firmware offset, and a CRC value. + * + * @param[inout] p_buffer The buffer to encode the response into. + * @param[in] max_size The maximum object size value to encode. + * @param[in] fw_offset The firmware offset value to encode. + * @param[in] crc The CRC value to encode. + * + * @return The length added to the buffer. + */ +static uint32_t response_select_obj_add(uint8_t * p_buffer, + uint32_t max_size, + uint32_t fw_offset, + uint32_t crc) +{ + uint16_t offset = uint32_encode(max_size, &p_buffer[RESPONSE_HEADER_LEN]); + offset += uint32_encode(fw_offset, &p_buffer[RESPONSE_HEADER_LEN + offset]); + offset += uint32_encode(crc, &p_buffer[RESPONSE_HEADER_LEN + offset]); + return offset; +} + + +/**@brief Function for encoding a CRC response into a buffer. + * + * The CRC response consists of a firmware offset and a CRC value. + * + * @param[inout] p_buffer The buffer to encode the response into. + * @param[in] fw_offset The firmware offset value to encode. + * @param[in] crc The CRC value to encode. + * + * @return The length added to the buffer. + */ +static uint32_t response_crc_add(uint8_t * p_buffer, uint32_t fw_offset, uint32_t crc) +{ + uint16_t offset = uint32_encode(fw_offset, &p_buffer[RESPONSE_HEADER_LEN]); + offset += uint32_encode(crc, &p_buffer[RESPONSE_HEADER_LEN + offset]); + return offset; +} + + +/**@brief Function for appending an extended error code to the response buffer. + * + * @param[inout] p_buffer The buffer to append the extended error code to. + * @param[in] result The error code to append. + * @param[in] buf_offset The current length of the buffer. + * + * @return The length added to the buffer. + */ +static uint32_t response_ext_err_payload_add(uint8_t * p_buffer, uint8_t result, uint32_t buf_offset) +{ + p_buffer[buf_offset] = ext_error_get(); + (void) ext_error_set(NRF_DFU_EXT_ERROR_NO_ERROR); + return 1; +} + + +static void ble_dfu_req_handler_callback(nrf_dfu_response_t * p_res, void * p_context) +{ + ASSERT(p_res); + ASSERT(p_context); + + uint8_t len = 0; + uint8_t buffer[MAX_RESPONSE_LEN] = {0}; + + if (p_res->request == NRF_DFU_OP_OBJECT_WRITE) + { + --m_pkt_notif_target_cnt; + if ((m_pkt_notif_target == 0) || (m_pkt_notif_target_cnt && m_pkt_notif_target > 0)) + { + return; + } + + /* Reply with a CRC message and reset the packet counter. */ + m_pkt_notif_target_cnt = m_pkt_notif_target; + + p_res->request = NRF_DFU_OP_CRC_GET; + } + + len += response_prepare(buffer, p_res->request, p_res->result); + + if (p_res->result != NRF_DFU_RES_CODE_SUCCESS) + { + NRF_LOG_WARNING("DFU request %d failed with error: 0x%x", p_res->request, p_res->result); + + if (p_res->result == NRF_DFU_RES_CODE_EXT_ERROR) + { + len += response_ext_err_payload_add(buffer, p_res->result, len); + } + + (void) response_send(buffer, len); + return; + } + + switch (p_res->request) + { + case NRF_DFU_OP_OBJECT_CREATE: + case NRF_DFU_OP_OBJECT_EXECUTE: + break; + + case NRF_DFU_OP_OBJECT_SELECT: + { + len += response_select_obj_add(buffer, + p_res->select.max_size, + p_res->select.offset, + p_res->select.crc); + } break; + + case NRF_DFU_OP_OBJECT_WRITE: + { + len += response_crc_add(buffer, p_res->write.offset, p_res->write.crc); + } break; + + case NRF_DFU_OP_CRC_GET: + { + len += response_crc_add(buffer, p_res->crc.offset, p_res->crc.crc); + } break; + + default: + { + // No action. + } break; + } + + (void) response_send(buffer, len); +} + + +/**@brief Function for handling a Write event on the Control Point characteristic. + * + * @param[in] p_dfu DFU Service Structure. + * @param[in] p_ble_write_evt Pointer to the write event received from BLE stack. + * + * @return NRF_SUCCESS on successful processing of control point write. Otherwise an error code. + */ +static uint32_t on_ctrl_pt_write(ble_dfu_t * p_dfu, ble_gatts_evt_write_t const * p_ble_write_evt) +{ + //lint -save -e415 -e416 : Out-of-bounds access on p_ble_write_evt->data + nrf_dfu_request_t request = + { + .request = (nrf_dfu_op_t)(p_ble_write_evt->data[0]), + .p_context = p_dfu, + .callback.response = ble_dfu_req_handler_callback, + }; + + switch (request.request) + { + case NRF_DFU_OP_OBJECT_SELECT: + { + /* Set object type to read info about */ + request.select.object_type = p_ble_write_evt->data[1]; + } break; + + case NRF_DFU_OP_OBJECT_CREATE: + { + /* Reset the packet receipt notification on create object */ + m_pkt_notif_target_cnt = m_pkt_notif_target; + + request.create.object_type = p_ble_write_evt->data[1]; + request.create.object_size = uint32_decode(&(p_ble_write_evt->data[2])); + + if (request.create.object_type == NRF_DFU_OBJ_TYPE_COMMAND) + { + /* Activity on the current transport. Close all except the current one. */ + (void) nrf_dfu_transports_close(&ble_dfu_transport); + } + } break; + + case NRF_DFU_OP_RECEIPT_NOTIF_SET: + { + NRF_LOG_DEBUG("Set receipt notif"); + + m_pkt_notif_target = uint16_decode(&(p_ble_write_evt->data[1])); + m_pkt_notif_target_cnt = m_pkt_notif_target; + } break; + + default: + break; + } + //lint -restore : Out-of-bounds access + + return nrf_dfu_req_handler_on_req(&request); +} + + +/**@brief Function for handling the @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event from the + * SoftDevice. + * + * @param[in] p_dfu DFU Service Structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static bool on_rw_authorize_req(ble_dfu_t * p_dfu, ble_evt_t const * p_ble_evt) +{ + uint32_t err_code; + + ble_gatts_evt_rw_authorize_request_t const * p_authorize_request; + ble_gatts_evt_write_t const * p_ble_write_evt; + + p_authorize_request = &(p_ble_evt->evt.gatts_evt.params.authorize_request); + p_ble_write_evt = &(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write); + + if ( (p_authorize_request->type != BLE_GATTS_AUTHORIZE_TYPE_WRITE) + || (p_authorize_request->request.write.handle != p_dfu->dfu_ctrl_pt_handles.value_handle) + || (p_authorize_request->request.write.op != BLE_GATTS_OP_WRITE_REQ)) + { + return false; + } + + ble_gatts_rw_authorize_reply_params_t auth_reply = + { + .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, + .params.write.update = 1, + .params.write.offset = p_ble_write_evt->offset, + .params.write.len = p_ble_write_evt->len, + .params.write.p_data = p_ble_write_evt->data, + }; + + if (!is_cccd_configured(p_dfu)) + { + /* Send an error response to the peer indicating that the CCCD is improperly configured. */ + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR; + + /* Ignore response of auth reply */ + (void) sd_ble_gatts_rw_authorize_reply(m_conn_handle, &auth_reply); + return false; + } + else + { + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + + err_code = sd_ble_gatts_rw_authorize_reply(m_conn_handle, &auth_reply); + return err_code == NRF_SUCCESS ? true : false; + } +} + + +static void on_flash_write(void * p_buf) +{ + NRF_LOG_DEBUG("Freeing buffer %p", p_buf); + nrf_balloc_free(&m_buffer_pool, p_buf); +} + + +/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice. + * + * @param[in] p_dfu DFU Service Structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_write(ble_dfu_t * p_dfu, ble_evt_t const * p_ble_evt) +{ + ble_gatts_evt_write_t const * const p_write_evt = &p_ble_evt->evt.gatts_evt.params.write; + + if (p_write_evt->handle != p_dfu->dfu_pkt_handles.value_handle) + { + return; + } + + /* Allocate a buffer to receive data. */ + uint8_t * p_balloc_buf = nrf_balloc_alloc(&m_buffer_pool); + if (p_balloc_buf == NULL) + { + /* Operations are retried by the host; do not give up here. */ + NRF_LOG_WARNING("cannot allocate memory buffer!"); + return; + } + + NRF_LOG_DEBUG("Buffer %p acquired, len %d (%d)", + p_balloc_buf, p_write_evt->len, MAX_DFU_PKT_LEN); + + /* Copy payload into buffer. */ + memcpy(p_balloc_buf, p_write_evt->data, p_write_evt->len); + + /* Set up the request. */ + nrf_dfu_request_t request = + { + .request = NRF_DFU_OP_OBJECT_WRITE, + .p_context = p_dfu, + .callback = + { + .response = ble_dfu_req_handler_callback, + .write = on_flash_write, + } + }; + + /* Set up the request buffer. */ + request.write.p_data = p_balloc_buf; + request.write.len = p_write_evt->len; + + /* Schedule handling of the request. */ + ret_code_t rc = nrf_dfu_req_handler_on_req(&request); + if (rc != NRF_SUCCESS) + { + /* The error is logged in nrf_dfu_req_handler_on_req(). + * Free the buffer. + */ + (void) nrf_balloc_free(&m_buffer_pool, p_balloc_buf); + } +} + + +/**@brief Function for the Application's SoftDevice event handler. + * + * @param[in] p_ble_evt SoftDevice event. + */ +static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) +{ + uint32_t err_code; + ble_gap_evt_t const * const p_gap = &p_ble_evt->evt.gap_evt; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + { + NRF_LOG_DEBUG("Connected"); + + m_conn_handle = p_gap->conn_handle; + + if (m_observer) + { + m_observer(NRF_DFU_EVT_TRANSPORT_ACTIVATED); + } + + err_code = sd_ble_gap_conn_param_update(m_conn_handle, &m_gap_conn_params); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failure to update connection parameters: 0x%x", err_code); + } + } break; + + case BLE_GAP_EVT_DISCONNECTED: + { + m_conn_handle = BLE_CONN_HANDLE_INVALID; + + /* Restart advertising so that the DFU Controller can reconnect if possible. */ + if (!(m_flags & DFU_BLE_RESETTING_SOON)) + { + err_code = advertising_start(); + APP_ERROR_CHECK(err_code); + } + + if (m_observer) + { + m_observer(NRF_DFU_EVT_TRANSPORT_DEACTIVATED); + } + } break; + + case BLE_GATTS_EVT_WRITE: + { + on_write(&m_dfu, p_ble_evt); + } break; + + case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: + { + uint16_t const mtu_requested = + p_ble_evt->evt.gatts_evt.params.exchange_mtu_request.client_rx_mtu; + + /* If the requested MTU is smaller than the maximum, we can accept with the given + * stack configuration, and the payload is not word-aligned, reply with a smaller MTU + * that has a word-aligned payload. This ensures that the length of data we write to + * flash is a multiple of the word size. + */ + uint16_t mtu_reply; + + if (mtu_requested < NRF_SDH_BLE_GATT_MAX_MTU_SIZE) + { + /* Round the payload size down to a multiple of 4 so it is word-aligned. */ + if (GATT_PAYLOAD(mtu_requested) % 4) + { + mtu_reply = GATT_PAYLOAD(mtu_requested) - 4; + mtu_reply = ALIGN_NUM(4, mtu_reply); + /* Add the header len to the MTU. */ + mtu_reply += GATT_HEADER_LEN; + } + else + { + mtu_reply = mtu_requested; + } + } + else + { + mtu_reply = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; + } + + NRF_LOG_DEBUG("Received BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST (request: %d, reply: %d).", + mtu_requested, mtu_reply); + + err_code = sd_ble_gatts_exchange_mtu_reply(m_conn_handle, mtu_reply); + APP_ERROR_CHECK(err_code); + } break; +#ifndef S112 + case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST."); + + ble_gap_data_length_params_t const dlp = + { + .max_rx_octets = BLE_GAP_DATA_LENGTH_AUTO, + .max_tx_octets = BLE_GAP_DATA_LENGTH_AUTO, + }; + + err_code = sd_ble_gap_data_length_update(p_ble_evt->evt.gatts_evt.conn_handle, + &dlp, NULL); + APP_ERROR_CHECK(err_code); + } break; + + case BLE_GAP_EVT_DATA_LENGTH_UPDATE: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_DATA_LENGTH_UPDATE (%u, max_rx_time %u).", + p_gap->params.data_length_update.effective_params.max_rx_octets, + p_gap->params.data_length_update.effective_params.max_rx_time_us); + } break; +#endif + + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_SEC_PARAMS_REQUEST"); + + uint16_t cccd; + ble_gatts_value_t gatts_value = + { + .len = BLE_CCCD_VALUE_LEN, + .p_value = (uint8_t*)&cccd + }; + + err_code = sd_ble_gatts_value_get(m_conn_handle, + BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED, + &gatts_value); + APP_ERROR_CHECK(err_code); + + NRF_LOG_DEBUG("CCCD for service changed is 0x%04x", cccd); + + err_code = sd_ble_gap_sec_params_reply(m_conn_handle, + BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, + NULL, + NULL); + APP_ERROR_CHECK(err_code); + } break; + + case BLE_GAP_EVT_CONN_PARAM_UPDATE: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_CONN_PARAM_UPDATE"); + + ble_gap_conn_params_t const * p_conn = + &p_gap->params.conn_param_update.conn_params; + + NRF_LOG_DEBUG("max_conn_interval: %d", p_conn->max_conn_interval); + NRF_LOG_DEBUG("min_conn_interval: %d", p_conn->min_conn_interval); + NRF_LOG_DEBUG("slave_latency: %d", p_conn->slave_latency); + NRF_LOG_DEBUG("conn_sup_timeout: %d", p_conn->conn_sup_timeout); + } break; + +#if !defined(S112) && !defined(S113) + case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST"); + + err_code = sd_ble_gap_conn_param_update(m_conn_handle, + &p_gap->params.conn_param_update_request.conn_params); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failure to update connection parameter request: 0x%x", err_code); + } + + APP_ERROR_CHECK(err_code); + } break; +#endif + + case BLE_GAP_EVT_PHY_UPDATE: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_PHY_UPDATE (RX:%d, TX:%d, status:%d)", + p_gap->params.phy_update.rx_phy, + p_gap->params.phy_update.tx_phy, + p_gap->params.phy_update.status); + break; + } + + case BLE_GAP_EVT_PHY_UPDATE_REQUEST: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_PHY_UPDATE_REQUEST."); + + ble_gap_phys_t const phys = + { + .rx_phys = BLE_GAP_PHY_AUTO, + .tx_phys = BLE_GAP_PHY_AUTO, + }; + + err_code = sd_ble_gap_phy_update(p_gap->conn_handle, &phys); + APP_ERROR_CHECK(err_code); + } break; + + case BLE_GATTS_EVT_TIMEOUT: + { + if (p_ble_evt->evt.gatts_evt.params.timeout.src == BLE_GATT_TIMEOUT_SRC_PROTOCOL) + { + err_code = sd_ble_gap_disconnect(m_conn_handle, + BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + APP_ERROR_CHECK(err_code); + } + } break; + + case BLE_EVT_USER_MEM_REQUEST: + { + err_code = sd_ble_user_mem_reply(m_conn_handle, NULL); + APP_ERROR_CHECK(err_code); + } break; + + case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: + { + if (p_ble_evt->evt.gatts_evt.params.authorize_request.type + != BLE_GATTS_AUTHORIZE_TYPE_INVALID) + { + if (on_rw_authorize_req(&m_dfu, p_ble_evt)) + { + err_code = on_ctrl_pt_write(&m_dfu, + &(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write)); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not handle on_ctrl_pt_write. err_code: 0x%04x", err_code); + } + } + } + } break; + + case BLE_GAP_EVT_SEC_INFO_REQUEST: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_SEC_INFO_REQUEST"); + + ble_gap_enc_info_t * p_enc_info = NULL; + ble_gap_irk_t * p_id_info = NULL; + + #if (NRF_DFU_BLE_REQUIRES_BONDS) + /* If there is a match in diversifier, then set the correct keys. */ + if (p_gap->params.sec_info_request.master_id.ediv == + m_peer_data.enc_key.master_id.ediv) + { + p_enc_info = &m_peer_data.enc_key.enc_info; + } + p_id_info = &m_peer_data.ble_id.id_info; + #endif + + err_code = sd_ble_gap_sec_info_reply(p_gap->conn_handle, p_enc_info, p_id_info, NULL); + APP_ERROR_CHECK(err_code); + } break; + + case BLE_GAP_EVT_CONN_SEC_UPDATE: + case BLE_GATTS_EVT_SYS_ATTR_MISSING: + { + #if (NRF_DFU_BLE_REQUIRES_BONDS) + err_code = service_changed_send(); + #else + err_code = sd_ble_gatts_sys_attr_set(p_gap->conn_handle, NULL, 0, 0); + #endif + APP_ERROR_CHECK(err_code); + NRF_LOG_DEBUG("Finished handling conn sec update"); + } break; + + default: + /* No implementation needed. */ + break; + } +} + + +#if (!NRF_DFU_BLE_REQUIRES_BONDS) +static uint32_t gap_address_change(void) +{ + uint32_t err_code; + ble_gap_addr_t addr; + + err_code = sd_ble_gap_addr_get(&addr); + VERIFY_SUCCESS(err_code); + + /* Increase the BLE address by one when advertising openly. */ + addr.addr[0] += 1; + + err_code = sd_ble_gap_addr_set(&addr); + VERIFY_SUCCESS(err_code); + + return NRF_SUCCESS; +} +#endif + + +/**@brief Function for initializing GAP. + * + * @details This function sets up all necessary GAP (Generic Access Profile) parameters of + * the device. It also sets the permissions and appearance. + */ +static uint32_t gap_params_init(void) +{ + uint32_t err_code; + ble_gap_conn_sec_mode_t sec_mode; + uint8_t const * device_name; + uint32_t name_len; + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); + +#if (!NRF_DFU_BLE_REQUIRES_BONDS) + + err_code = gap_address_change(); + VERIFY_SUCCESS(err_code); + + if ((m_flags & DFU_BLE_FLAG_USE_ADV_NAME) != 0) + { + NRF_LOG_DEBUG("Setting adv name: %s, length: %d", m_adv_name.name, m_adv_name.len); + device_name = m_adv_name.name; + name_len = m_adv_name.len; + } + else +#endif + { + NRF_LOG_DEBUG("Using default advertising name"); + device_name = (uint8_t const *)(NRF_DFU_BLE_ADV_NAME); + name_len = strlen(NRF_DFU_BLE_ADV_NAME); + } + + err_code = sd_ble_gap_device_name_set(&sec_mode, device_name, name_len); + VERIFY_SUCCESS(err_code); + + err_code = sd_ble_gap_ppcp_set(&m_gap_conn_params); + return err_code; +} + + +static uint32_t ble_stack_init() +{ + ret_code_t err_code; + uint32_t ram_start = 0; + + /* Register as a BLE event observer to receive BLE events. */ + NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, BLE_OBSERVER_PRIO, ble_evt_handler, NULL); + +#if (!defined(NRF_DFU_BLE_SKIP_SD_INIT)) || (NRF_DFU_BLE_SKIP_SD_INIT == 0) + err_code = nrf_dfu_mbr_init_sd(); + VERIFY_SUCCESS(err_code); + + NRF_LOG_DEBUG("Setting up vector table: 0x%08x", BOOTLOADER_START_ADDR); + err_code = sd_softdevice_vector_table_base_set(BOOTLOADER_START_ADDR); + VERIFY_SUCCESS(err_code); +#endif + + NRF_LOG_DEBUG("Enabling SoftDevice."); + err_code = nrf_sdh_enable_request(); + VERIFY_SUCCESS(err_code); + + /* Fetch the start address of the application RAM. */ + err_code = nrf_sdh_ble_app_ram_start_get(&ram_start); + VERIFY_SUCCESS(err_code); + + NRF_LOG_DEBUG("Configuring BLE stack."); + err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start); + VERIFY_SUCCESS(err_code); + + /* Enable the BLE stack. */ + NRF_LOG_DEBUG("Enabling the BLE stack."); + return nrf_sdh_ble_enable(&ram_start); +} + + +/**@brief Function for adding DFU Packet characteristic to the BLE Stack. + * + * @param[in] p_dfu DFU Service structure. + * + * @return NRF_SUCCESS on success. Otherwise an error code. + */ +static uint32_t dfu_pkt_char_add(ble_dfu_t * const p_dfu) +{ + ble_gatts_char_md_t char_md = + { + .char_props.write_wo_resp = 1, + }; + + ble_uuid_t char_uuid = + { + .type = p_dfu->uuid_type, + .uuid = BLE_DFU_PKT_CHAR_UUID, + }; + + ble_gatts_attr_md_t attr_md = + { + .vloc = BLE_GATTS_VLOC_STACK, + .vlen = 1, + .write_perm = + { + .sm = 1, + #if NRF_DFU_BLE_REQUIRES_BONDS + .lv = 2, + #else + .lv = 1, + #endif + } + }; + + ble_gatts_attr_t attr_char_value = + { + .p_uuid = &char_uuid, + .p_attr_md = &attr_md, + .max_len = MAX_DFU_PKT_LEN, + }; + + return sd_ble_gatts_characteristic_add(p_dfu->service_handle, + &char_md, + &attr_char_value, + &p_dfu->dfu_pkt_handles); +} + + +/**@brief Function for adding DFU Control Point characteristic to the BLE Stack. + * + * @param[in] p_dfu DFU Service structure. + * + * @return NRF_SUCCESS on success. Otherwise an error code. + */ +static uint32_t dfu_ctrl_pt_add(ble_dfu_t * const p_dfu) +{ + ble_gatts_char_md_t char_md = + { + .char_props.write = 1, + .char_props.notify = 1, + }; + + ble_uuid_t char_uuid = + { + .type = p_dfu->uuid_type, + .uuid = BLE_DFU_CTRL_PT_UUID, + }; + + ble_gatts_attr_md_t attr_md = + { + .vloc = BLE_GATTS_VLOC_STACK, + .wr_auth = 1, + .vlen = 1, + .write_perm = + { + .sm = 1, + #if NRF_DFU_BLE_REQUIRES_BONDS + .lv = 2, + #else + .lv = 1, + #endif + }, + }; + + ble_gatts_attr_t attr_char_value = + { + .p_uuid = &char_uuid, + .p_attr_md = &attr_md, + .max_len = BLE_GATT_ATT_MTU_DEFAULT, + }; + + return sd_ble_gatts_characteristic_add(p_dfu->service_handle, + &char_md, + &attr_char_value, + &p_dfu->dfu_ctrl_pt_handles); +} + + +/**@brief Function for checking if the CCCD of DFU Control point is configured for Notification. + * + * @details This function checks if the CCCD of DFU Control Point characteristic is configured + * for Notification by the DFU Controller. + * + * @param[in] p_dfu DFU Service structure. + * + * @return True if the CCCD of DFU Control Point characteristic is configured for Notification. + * False otherwise. + */ +uint32_t ble_dfu_init(ble_dfu_t * p_dfu) +{ + ASSERT(p_dfu != NULL); + + ble_uuid_t service_uuid; + uint32_t err_code; + + m_conn_handle = BLE_CONN_HANDLE_INVALID; + + BLE_UUID_BLE_ASSIGN(service_uuid, BLE_DFU_SERVICE_UUID); + + err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, + &service_uuid, + &(p_dfu->service_handle)); + VERIFY_SUCCESS(err_code); + + ble_uuid128_t const base_uuid128 = + { + { + 0x50, 0xEA, 0xDA, 0x30, 0x88, 0x83, 0xB8, 0x9F, + 0x60, 0x4F, 0x15, 0xF3, 0x00, 0x00, 0xC9, 0x8E + } + }; + + err_code = sd_ble_uuid_vs_add(&base_uuid128, &p_dfu->uuid_type); + VERIFY_SUCCESS(err_code); + + err_code = dfu_pkt_char_add(p_dfu); + VERIFY_SUCCESS(err_code); + + err_code = dfu_ctrl_pt_add(p_dfu); + VERIFY_SUCCESS(err_code); + + return NRF_SUCCESS; +} + + +uint32_t ble_dfu_transport_init(nrf_dfu_observer_t observer) +{ + uint32_t err_code = NRF_SUCCESS; + + if (m_flags & DFU_BLE_FLAG_INITIALIZED) + { + return err_code; + } + + NRF_LOG_DEBUG("Initializing BLE DFU transport"); + + m_observer = observer; + + err_code = nrf_balloc_init(&m_buffer_pool); + UNUSED_RETURN_VALUE(err_code); + + err_code = ble_stack_init(); + VERIFY_SUCCESS(err_code); + +#if (NRF_DFU_BLE_REQUIRES_BONDS) + /* Copy out the peer data if bonds are required */ + if (nrf_dfu_settings_peer_data_is_valid()) + { + NRF_LOG_DEBUG("Copying peer data"); + + err_code = nrf_dfu_settings_peer_data_copy(&m_peer_data); + UNUSED_RETURN_VALUE(err_code); + } + else + { + APP_ERROR_HANDLER(NRF_ERROR_INTERNAL); + } +#else + /* Copy out the new advertisement name when bonds are not required and the name is set. */ + if (nrf_dfu_settings_adv_name_is_valid()) + { + err_code = nrf_dfu_settings_adv_name_copy(&m_adv_name); + UNUSED_RETURN_VALUE(err_code); + + /* Set flags for advertisement name that is to be used */ + m_flags |= DFU_BLE_FLAG_USE_ADV_NAME; + } + else + { + NRF_LOG_DEBUG("No advertising name found"); + } +#endif + + err_code = gap_params_init(); + VERIFY_SUCCESS(err_code); + + /* Initialize the Device Firmware Update Service. */ + err_code = ble_dfu_init(&m_dfu); + VERIFY_SUCCESS(err_code); + + err_code = advertising_start(); + VERIFY_SUCCESS(err_code); + + m_flags |= DFU_BLE_FLAG_INITIALIZED; + + NRF_LOG_DEBUG("BLE DFU transport initialized."); + + return NRF_SUCCESS; +} + + +uint32_t ble_dfu_transport_close(nrf_dfu_transport_t const * p_exception) +{ + uint32_t err_code = NRF_SUCCESS; + + if ((m_flags & DFU_BLE_FLAG_INITIALIZED) && (p_exception != &ble_dfu_transport)) + { + NRF_LOG_DEBUG("Shutting down BLE transport."); + + if (m_conn_handle != BLE_CONN_HANDLE_INVALID) + { + NRF_LOG_DEBUG("Disconnecting."); + + /* Set flag to prevent advertisement from starting */ + m_flags |= DFU_BLE_RESETTING_SOON; + + /* Disconnect from the peer. */ + err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + VERIFY_SUCCESS(err_code); + + /* Wait a bit for the disconnect event to be sent on air. */ + nrf_delay_ms(200); + } + else + { + err_code = sd_ble_gap_adv_stop(m_adv_handle); + UNUSED_RETURN_VALUE(err_code); + } + + err_code = nrf_sdh_disable_request(); + if (err_code == NRF_SUCCESS) + { + NRF_LOG_DEBUG("BLE transport shut down."); + } + } + + return err_code; +} + +uint32_t ble_dfu_transport_disconnect(void) +{ + uint32_t err_code = NRF_SUCCESS; + + if (m_flags & DFU_BLE_FLAG_INITIALIZED) + { + NRF_LOG_DEBUG("Disconnect from BLE peer."); + + if (m_conn_handle != BLE_CONN_HANDLE_INVALID) + { + NRF_LOG_DEBUG("Disconnecting."); + + /* Disconnect from the peer. */ + err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + VERIFY_SUCCESS(err_code); + } + } + + return err_code; +} diff --git a/components/libraries/bootloader/ble_dfu/nrf_dfu_ble.h b/components/libraries/bootloader/ble_dfu/nrf_dfu_ble.h new file mode 100644 index 0000000..42d4163 --- /dev/null +++ b/components/libraries/bootloader/ble_dfu/nrf_dfu_ble.h @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_dfu_ble DFU BLE Service + * @{ + * @ingroup nrf_dfu + * @brief Device Firmware Update (DFU) transport layer for Bluetooth low energy. + * + * @details The Device Firmware Update (DFU) Service is a GATT-based service that can be used for + * performing firmware updates over BLE. Note that this implementation uses + * vendor-specific UUIDs for the service and characteristics, and is intended to demonstrate + * firmware updates over BLE. See @ref lib_dfu_transport_ble "DFU Transport: BLE" for more information on the service and the profile. + */ + +#ifndef NRF_DFU_BLE_H__ +#define NRF_DFU_BLE_H__ + +#include +#include "ble_gatts.h" +#include "ble.h" +#include "nrf_dfu_transport.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +// This is a 16-bit UUID. +#define BLE_DFU_SERVICE_UUID 0xFE59 //!< UUID of the DFU Service. + +// These UUIDs are used with the Nordic base address to create a 128-bit UUID (0x8EC9XXXXF3154F609FB8838830DAEA50). +#define BLE_DFU_CTRL_PT_UUID 0x0001 //!< UUID of the DFU Control Point. +#define BLE_DFU_PKT_CHAR_UUID 0x0002 //!< UUID of the DFU Packet Characteristic. + + +/**@brief DFU Service. + * + * @details This structure contains status information related to the service. + */ +typedef struct +{ + uint16_t service_handle; /**< Handle of the DFU Service (as provided by the SoftDevice). */ + uint8_t uuid_type; /**< UUID type assigned to the DFU Service by the SoftDevice. */ + ble_gatts_char_handles_t dfu_pkt_handles; /**< Handles related to the DFU Packet Characteristic. */ + ble_gatts_char_handles_t dfu_ctrl_pt_handles; /**< Handles related to the DFU Control Point Characteristic. */ +} ble_dfu_t; + + +/**@brief Function for initializing the BLE transport. + * + * @param[in] observer Callback function for receiving notifications from the BLE transport. + * + * @retval NRF_SUCCESS If successful. + * @return Error code from sub-call on error. + */ +uint32_t ble_dfu_transport_init(nrf_dfu_observer_t observer); + +/**@brief Function for closing the BLE transport. + * + * This function disconnects and disables the SoftDevice. + * + * @param[in] p_exception Optional exception. If the exception refers to this transport, + * this function will do nothing. Can be NULL to signify no exception. + * + * @retval NRF_SUCCESS If successful. + * @return Error code from sub-call on error. + */ +uint32_t ble_dfu_transport_close(nrf_dfu_transport_t const * p_exception); + +/**@brief Function for disconnecting from the BLE peer and starting advertising. + * + * @retval NRF_SUCCESS If successful. + * @return Error code from sub-call on error. + */ +uint32_t ble_dfu_transport_disconnect(void); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_BLE_H__ + +/** @} */ diff --git a/components/libraries/bootloader/ble_dfu/nrf_dfu_ble_svci_bond_sharing.h b/components/libraries/bootloader/ble_dfu/nrf_dfu_ble_svci_bond_sharing.h new file mode 100644 index 0000000..cd6cf95 --- /dev/null +++ b/components/libraries/bootloader/ble_dfu/nrf_dfu_ble_svci_bond_sharing.h @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_dfu_svci_bond_sharing Supervisor call interface for bond sharing + * @{ + * @ingroup nrf_dfu + * @brief The Supervisor call interface is a thread-safe method to call into the current application or into an external application using a Supervisor instruction. + * + */ + + +#ifndef NRF_DFU_BLE_SVCI_BOND_SHARING_H__ +#define NRF_DFU_BLE_SVCI_BOND_SHARING_H__ + +#include +#include "nrf_svci.h" +#include "nrf_svci_async_function.h" +#include "sdk_config.h" +#include "nrf_dfu_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define NRF_DFU_SVCI_SET_PEER_DATA 2 +#define NRF_DFU_SVCI_SET_ADV_NAME 3 + +#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE + +/**@brief Sets up the async SVCI interface for exchanging peer data like bonding and the system attribute table. + * + * @details The peer data will be stored in flash by the bootloader. This requires memory management and + * handling forwarding of system events and state from the main application to the bootloader. + * + * @note This is only available in the buttonless DFU that supports bond sharing. + */ +NRF_SVCI_ASYNC_FUNC_DECLARE(NRF_DFU_SVCI_SET_PEER_DATA, nrf_dfu_set_peer_data, nrf_dfu_peer_data_t, nrf_dfu_peer_data_state_t); + +/**@brief Sets up the async SVCI interface for exchanging advertisement name to use when entering DFU mode. + * + * @details The advertisement name will be stored in flash by the bootloader. This requires memory management + * and handling forwarding of system events and state from the main application to the bootloader. + * + * @note This is only available in the buttonless DFU that does not support bond sharing. + */ +NRF_SVCI_ASYNC_FUNC_DECLARE(NRF_DFU_SVCI_SET_ADV_NAME, nrf_dfu_set_adv_name, nrf_dfu_adv_name_t, nrf_dfu_set_adv_name_state_t); + +#endif // NRF_DFU_TRANSPORT_BLE + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_BLE_SVCI_BOND_SHARING_H__ + +/** @} */ diff --git a/components/libraries/bootloader/dfu/dfu-cc.options b/components/libraries/bootloader/dfu/dfu-cc.options new file mode 100644 index 0000000..de4fcdb --- /dev/null +++ b/components/libraries/bootloader/dfu/dfu-cc.options @@ -0,0 +1,5 @@ +dfu.Hash.hash max_size:32 +dfu.SignedCommand.signature max_size:64 +dfu.InitCommand.sd_req max_count:16 +dfu.InitCommand.boot_validation max_count:3 +dfu.BootValidation.bytes max_size:64 \ No newline at end of file diff --git a/components/libraries/bootloader/dfu/dfu-cc.pb.c b/components/libraries/bootloader/dfu/dfu-cc.pb.c new file mode 100644 index 0000000..769e6d3 --- /dev/null +++ b/components/libraries/bootloader/dfu/dfu-cc.pb.c @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.6-dev at Tue Sep 11 14:37:18 2018. */ + +#include "dfu-cc.pb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +const bool dfu_init_command_is_debug_default = false; + + +const pb_field_t dfu_hash_fields[3] = { + PB_FIELD( 1, UENUM , REQUIRED, STATIC , FIRST, dfu_hash_t, hash_type, hash_type, 0), + PB_FIELD( 2, BYTES , REQUIRED, STATIC , OTHER, dfu_hash_t, hash, hash_type, 0), + PB_LAST_FIELD +}; + +const pb_field_t dfu_boot_validation_fields[3] = { + PB_FIELD( 1, UENUM , REQUIRED, STATIC , FIRST, dfu_boot_validation_t, type, type, 0), + PB_FIELD( 2, BYTES , REQUIRED, STATIC , OTHER, dfu_boot_validation_t, bytes, type, 0), + PB_LAST_FIELD +}; + +const pb_field_t dfu_init_command_fields[11] = { + PB_FIELD( 1, UINT32 , OPTIONAL, STATIC , FIRST, dfu_init_command_t, fw_version, fw_version, 0), + PB_FIELD( 2, UINT32 , OPTIONAL, STATIC , OTHER, dfu_init_command_t, hw_version, fw_version, 0), + PB_FIELD( 3, UINT32 , REPEATED, STATIC , OTHER, dfu_init_command_t, sd_req, hw_version, 0), + PB_FIELD( 4, UENUM , OPTIONAL, STATIC , OTHER, dfu_init_command_t, type, sd_req, 0), + PB_FIELD( 5, UINT32 , OPTIONAL, STATIC , OTHER, dfu_init_command_t, sd_size, type, 0), + PB_FIELD( 6, UINT32 , OPTIONAL, STATIC , OTHER, dfu_init_command_t, bl_size, sd_size, 0), + PB_FIELD( 7, UINT32 , OPTIONAL, STATIC , OTHER, dfu_init_command_t, app_size, bl_size, 0), + PB_FIELD( 8, MESSAGE , OPTIONAL, STATIC , OTHER, dfu_init_command_t, hash, app_size, &dfu_hash_fields), + PB_FIELD( 9, BOOL , OPTIONAL, STATIC , OTHER, dfu_init_command_t, is_debug, hash, &dfu_init_command_is_debug_default), + PB_FIELD( 10, MESSAGE , REPEATED, STATIC , OTHER, dfu_init_command_t, boot_validation, is_debug, &dfu_boot_validation_fields), + PB_LAST_FIELD +}; + +const pb_field_t dfu_command_fields[3] = { + PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, dfu_command_t, op_code, op_code, 0), + PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, dfu_command_t, init, op_code, &dfu_init_command_fields), + PB_LAST_FIELD +}; + +const pb_field_t dfu_signed_command_fields[4] = { + PB_FIELD( 1, MESSAGE , REQUIRED, STATIC , FIRST, dfu_signed_command_t, command, command, &dfu_command_fields), + PB_FIELD( 2, UENUM , REQUIRED, STATIC , OTHER, dfu_signed_command_t, signature_type, command, 0), + PB_FIELD( 3, BYTES , REQUIRED, STATIC , OTHER, dfu_signed_command_t, signature, signature_type, 0), + PB_LAST_FIELD +}; + +const pb_field_t dfu_packet_fields[3] = { + PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, dfu_packet_t, command, command, &dfu_command_fields), + PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, dfu_packet_t, signed_command, command, &dfu_signed_command_fields), + PB_LAST_FIELD +}; + + +/* Check that field information fits in pb_field_t */ +#if !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_32BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in 8 or 16 bit + * field descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(dfu_init_command_t, hash) < 65536 && pb_membersize(dfu_init_command_t, boot_validation[0]) < 65536 && pb_membersize(dfu_command_t, init) < 65536 && pb_membersize(dfu_signed_command_t, command) < 65536 && pb_membersize(dfu_packet_t, command) < 65536 && pb_membersize(dfu_packet_t, signed_command) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_dfu_hash_dfu_boot_validation_dfu_init_command_dfu_command_dfu_signed_command_dfu_packet) +#endif + +#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_16BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in the default + * 8 bit descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(dfu_init_command_t, hash) < 256 && pb_membersize(dfu_init_command_t, boot_validation[0]) < 256 && pb_membersize(dfu_command_t, init) < 256 && pb_membersize(dfu_signed_command_t, command) < 256 && pb_membersize(dfu_packet_t, command) < 256 && pb_membersize(dfu_packet_t, signed_command) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_dfu_hash_dfu_boot_validation_dfu_init_command_dfu_command_dfu_signed_command_dfu_packet) +#endif + + +/* @@protoc_insertion_point(eof) */ diff --git a/components/libraries/bootloader/dfu/dfu-cc.pb.h b/components/libraries/bootloader/dfu/dfu-cc.pb.h new file mode 100644 index 0000000..377b5a1 --- /dev/null +++ b/components/libraries/bootloader/dfu/dfu-cc.pb.h @@ -0,0 +1,241 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.6-dev at Tue Sep 11 14:37:18 2018. */ + +#ifndef PB_DFU_CC_PB_H_INCLUDED +#define PB_DFU_CC_PB_H_INCLUDED +#include + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Enum definitions */ +typedef enum +{ + DFU_FW_TYPE_APPLICATION = 0, + DFU_FW_TYPE_SOFTDEVICE = 1, + DFU_FW_TYPE_BOOTLOADER = 2, + DFU_FW_TYPE_SOFTDEVICE_BOOTLOADER = 3, + DFU_FW_TYPE_EXTERNAL_APPLICATION = 4 +} dfu_fw_type_t; +#define DFU_FW_TYPE_MIN DFU_FW_TYPE_APPLICATION +#define DFU_FW_TYPE_MAX DFU_FW_TYPE_EXTERNAL_APPLICATION +#define DFU_FW_TYPE_ARRAYSIZE ((dfu_fw_type_t)(DFU_FW_TYPE_EXTERNAL_APPLICATION+1)) + +typedef enum +{ + DFU_HASH_TYPE_NO_HASH = 0, + DFU_HASH_TYPE_CRC = 1, + DFU_HASH_TYPE_SHA128 = 2, + DFU_HASH_TYPE_SHA256 = 3, + DFU_HASH_TYPE_SHA512 = 4 +} dfu_hash_type_t; +#define DFU_HASH_TYPE_MIN DFU_HASH_TYPE_NO_HASH +#define DFU_HASH_TYPE_MAX DFU_HASH_TYPE_SHA512 +#define DFU_HASH_TYPE_ARRAYSIZE ((dfu_hash_type_t)(DFU_HASH_TYPE_SHA512+1)) + +typedef enum +{ + DFU_OP_CODE_INIT = 1 +} dfu_op_code_t; +#define DFU_OP_CODE_MIN DFU_OP_CODE_INIT +#define DFU_OP_CODE_MAX DFU_OP_CODE_INIT +#define DFU_OP_CODE_ARRAYSIZE ((dfu_op_code_t)(DFU_OP_CODE_INIT+1)) + +typedef enum +{ + DFU_VALIDATION_TYPE_NO_VALIDATION = 0, + DFU_VALIDATION_TYPE_VALIDATE_GENERATED_CRC = 1, + DFU_VALIDATION_TYPE_VALIDATE_SHA256 = 2, + DFU_VALIDATION_TYPE_VALIDATE_ECDSA_P256_SHA256 = 3 +} dfu_validation_type_t; +#define DFU_VALIDATION_TYPE_MIN DFU_VALIDATION_TYPE_NO_VALIDATION +#define DFU_VALIDATION_TYPE_MAX DFU_VALIDATION_TYPE_VALIDATE_ECDSA_P256_SHA256 +#define DFU_VALIDATION_TYPE_ARRAYSIZE ((dfu_validation_type_t)(DFU_VALIDATION_TYPE_VALIDATE_ECDSA_P256_SHA256+1)) + +typedef enum +{ + DFU_SIGNATURE_TYPE_ECDSA_P256_SHA256 = 0, + DFU_SIGNATURE_TYPE_ED25519 = 1 +} dfu_signature_type_t; +#define DFU_SIGNATURE_TYPE_MIN DFU_SIGNATURE_TYPE_ECDSA_P256_SHA256 +#define DFU_SIGNATURE_TYPE_MAX DFU_SIGNATURE_TYPE_ED25519 +#define DFU_SIGNATURE_TYPE_ARRAYSIZE ((dfu_signature_type_t)(DFU_SIGNATURE_TYPE_ED25519+1)) + +/* Struct definitions */ +typedef PB_BYTES_ARRAY_T(64) dfu_boot_validation_bytes_t; +typedef struct { + dfu_validation_type_t type; + dfu_boot_validation_bytes_t bytes; +/* @@protoc_insertion_point(struct:dfu_boot_validation_t) */ +} dfu_boot_validation_t; + +typedef PB_BYTES_ARRAY_T(32) dfu_hash_hash_t; +typedef struct { + dfu_hash_type_t hash_type; + dfu_hash_hash_t hash; +/* @@protoc_insertion_point(struct:dfu_hash_t) */ +} dfu_hash_t; + +typedef struct { + bool has_fw_version; + uint32_t fw_version; + bool has_hw_version; + uint32_t hw_version; + pb_size_t sd_req_count; + uint32_t sd_req[16]; + bool has_type; + dfu_fw_type_t type; + bool has_sd_size; + uint32_t sd_size; + bool has_bl_size; + uint32_t bl_size; + bool has_app_size; + uint32_t app_size; + bool has_hash; + dfu_hash_t hash; + bool has_is_debug; + bool is_debug; + pb_size_t boot_validation_count; + dfu_boot_validation_t boot_validation[3]; +/* @@protoc_insertion_point(struct:dfu_init_command_t) */ +} dfu_init_command_t; + +typedef struct { + bool has_op_code; + dfu_op_code_t op_code; + bool has_init; + dfu_init_command_t init; +/* @@protoc_insertion_point(struct:dfu_command_t) */ +} dfu_command_t; + +typedef PB_BYTES_ARRAY_T(64) dfu_signed_command_signature_t; +typedef struct { + dfu_command_t command; + dfu_signature_type_t signature_type; + dfu_signed_command_signature_t signature; +/* @@protoc_insertion_point(struct:dfu_signed_command_t) */ +} dfu_signed_command_t; + +typedef struct { + bool has_command; + dfu_command_t command; + bool has_signed_command; + dfu_signed_command_t signed_command; +/* @@protoc_insertion_point(struct:dfu_packet_t) */ +} dfu_packet_t; + +/* Default values for struct fields */ +extern const bool dfu_init_command_is_debug_default; + +/* Initializer values for message structs */ +#define DFU_HASH_INIT_DEFAULT {(dfu_hash_type_t)0, {0, {0}}} +#define DFU_BOOT_VALIDATION_INIT_DEFAULT {(dfu_validation_type_t)0, {0, {0}}} +#define DFU_INIT_COMMAND_INIT_DEFAULT {false, 0, false, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false, (dfu_fw_type_t)0, false, 0, false, 0, false, 0, false, DFU_HASH_INIT_DEFAULT, false, false, 0, {DFU_BOOT_VALIDATION_INIT_DEFAULT, DFU_BOOT_VALIDATION_INIT_DEFAULT, DFU_BOOT_VALIDATION_INIT_DEFAULT}} +#define DFU_COMMAND_INIT_DEFAULT {false, (dfu_op_code_t)0, false, DFU_INIT_COMMAND_INIT_DEFAULT} +#define DFU_SIGNED_COMMAND_INIT_DEFAULT {DFU_COMMAND_INIT_DEFAULT, (dfu_signature_type_t)0, {0, {0}}} +#define DFU_PACKET_INIT_DEFAULT {false, DFU_COMMAND_INIT_DEFAULT, false, DFU_SIGNED_COMMAND_INIT_DEFAULT} +#define DFU_HASH_INIT_ZERO {(dfu_hash_type_t)0, {0, {0}}} +#define DFU_BOOT_VALIDATION_INIT_ZERO {(dfu_validation_type_t)0, {0, {0}}} +#define DFU_INIT_COMMAND_INIT_ZERO {false, 0, false, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false, (dfu_fw_type_t)0, false, 0, false, 0, false, 0, false, DFU_HASH_INIT_ZERO, false, 0, 0, {DFU_BOOT_VALIDATION_INIT_ZERO, DFU_BOOT_VALIDATION_INIT_ZERO, DFU_BOOT_VALIDATION_INIT_ZERO}} +#define DFU_COMMAND_INIT_ZERO {false, (dfu_op_code_t)0, false, DFU_INIT_COMMAND_INIT_ZERO} +#define DFU_SIGNED_COMMAND_INIT_ZERO {DFU_COMMAND_INIT_ZERO, (dfu_signature_type_t)0, {0, {0}}} +#define DFU_PACKET_INIT_ZERO {false, DFU_COMMAND_INIT_ZERO, false, DFU_SIGNED_COMMAND_INIT_ZERO} + +/* Field tags (for use in manual encoding/decoding) */ +#define DFU_BOOT_VALIDATION_TYPE_TAG 1 +#define DFU_BOOT_VALIDATION_BYTES_TAG 2 +#define DFU_HASH_HASH_TYPE_TAG 1 +#define DFU_HASH_HASH_TAG 2 +#define DFU_INIT_COMMAND_FW_VERSION_TAG 1 +#define DFU_INIT_COMMAND_HW_VERSION_TAG 2 +#define DFU_INIT_COMMAND_SD_REQ_TAG 3 +#define DFU_INIT_COMMAND_TYPE_TAG 4 +#define DFU_INIT_COMMAND_SD_SIZE_TAG 5 +#define DFU_INIT_COMMAND_BL_SIZE_TAG 6 +#define DFU_INIT_COMMAND_APP_SIZE_TAG 7 +#define DFU_INIT_COMMAND_HASH_TAG 8 +#define DFU_INIT_COMMAND_IS_DEBUG_TAG 9 +#define DFU_INIT_COMMAND_BOOT_VALIDATION_TAG 10 +#define DFU_COMMAND_OP_CODE_TAG 1 +#define DFU_COMMAND_INIT_TAG 2 +#define DFU_SIGNED_COMMAND_COMMAND_TAG 1 +#define DFU_SIGNED_COMMAND_SIGNATURE_TYPE_TAG 2 +#define DFU_SIGNED_COMMAND_SIGNATURE_TAG 3 +#define DFU_PACKET_COMMAND_TAG 1 +#define DFU_PACKET_SIGNED_COMMAND_TAG 2 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t dfu_hash_fields[3]; +extern const pb_field_t dfu_boot_validation_fields[3]; +extern const pb_field_t dfu_init_command_fields[11]; +extern const pb_field_t dfu_command_fields[3]; +extern const pb_field_t dfu_signed_command_fields[4]; +extern const pb_field_t dfu_packet_fields[3]; + +/* Maximum encoded size of messages (where known) */ +#define DFU_HASH_SIZE 36 +#define DFU_BOOT_VALIDATION_SIZE 68 +#define DFU_INIT_COMMAND_SIZE 378 +#define DFU_COMMAND_SIZE 383 +#define DFU_SIGNED_COMMAND_SIZE 454 +#define DFU_PACKET_SIZE 843 + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define DFU_CC_MESSAGES \ + + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/components/libraries/bootloader/dfu/dfu-cc.proto b/components/libraries/bootloader/dfu/dfu-cc.proto new file mode 100644 index 0000000..341b4e8 --- /dev/null +++ b/components/libraries/bootloader/dfu/dfu-cc.proto @@ -0,0 +1,82 @@ +package dfu; + +// Version 0.1 + +enum FwType { + APPLICATION = 0; + SOFTDEVICE = 1; + BOOTLOADER = 2; + SOFTDEVICE_BOOTLOADER = 3; + EXTERNAL_APPLICATION = 4; +} + +enum HashType { + NO_HASH = 0; + CRC = 1; + SHA128 = 2; + SHA256 = 3; + SHA512 = 4; +} + +enum OpCode { + INIT = 1; +} + +enum ValidationType { + NO_VALIDATION = 0; + VALIDATE_GENERATED_CRC = 1; + VALIDATE_SHA256 = 2; + VALIDATE_ECDSA_P256_SHA256 = 3; +} + +message Hash { + required HashType hash_type = 1; + required bytes hash = 2; +} + +message BootValidation { + + required ValidationType type = 1; + required bytes bytes = 2; +} + +// Commands data +message InitCommand { + optional uint32 fw_version = 1; + optional uint32 hw_version = 2; + repeated uint32 sd_req = 3 [packed = true]; + optional FwType type = 4; + + optional uint32 sd_size = 5; + optional uint32 bl_size = 6; + optional uint32 app_size = 7; + + optional Hash hash = 8; + + optional bool is_debug = 9 [default = false]; + repeated BootValidation boot_validation = 10; +} + +// Command type +message Command { + optional OpCode op_code = 1; + optional InitCommand init = 2; +} + +// Signed command types +enum SignatureType { + ECDSA_P256_SHA256 = 0; + ED25519 = 1; +} + +message SignedCommand { + required Command command = 1; + required SignatureType signature_type = 2; + required bytes signature = 3; +} + +// Parent packet type +message Packet { + optional Command command = 1; + optional SignedCommand signed_command = 2; +} diff --git a/components/libraries/bootloader/dfu/nrf_dfu.c b/components/libraries/bootloader/dfu/nrf_dfu.c new file mode 100644 index 0000000..c03ad0b --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu.c @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu.h" + +#include "nrf_dfu_utils.h" +#include "nrf_dfu_transport.h" +#include "nrf_dfu_req_handler.h" +#include "nrf_log.h" + +static nrf_dfu_observer_t m_user_observer; // +#include +#include "nrf_dfu_types.h" +#include "nrf_dfu_req_handler.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define NRF_DFU_SCHED_EVENT_DATA_SIZE (sizeof(nrf_dfu_request_t)) + + +/** @brief Function for initializing a DFU operation. + * + * This function initializes a DFU operation and any transports that are registered + * in the system. + * + * @param[in] observer Callback function for receiving DFU notifications. + * + * @retval NRF_SUCCESS If the DFU operation was successfully initialized. + */ +uint32_t nrf_dfu_init(nrf_dfu_observer_t observer); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_H__ + +/** @} */ diff --git a/components/libraries/bootloader/dfu/nrf_dfu_flash.c b/components/libraries/bootloader/dfu/nrf_dfu_flash.c new file mode 100644 index 0000000..5622494 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_flash.c @@ -0,0 +1,167 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_dfu_flash.h" +#include "nrf_dfu_types.h" + +#include "nrf_fstorage.h" +#include "nrf_fstorage_sd.h" +#include "nrf_fstorage_nvmc.h" + + +#define NRF_LOG_MODULE_NAME nrf_dfu_flash +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +void dfu_fstorage_evt_handler(nrf_fstorage_evt_t * p_evt); + + +NRF_FSTORAGE_DEF(nrf_fstorage_t m_fs) = +{ + .evt_handler = dfu_fstorage_evt_handler, + .start_addr = MBR_SIZE, + .end_addr = BOOTLOADER_SETTINGS_ADDRESS + BOOTLOADER_SETTINGS_PAGE_SIZE +}; + +static uint32_t m_flash_operations_pending; + +void dfu_fstorage_evt_handler(nrf_fstorage_evt_t * p_evt) +{ + if (NRF_LOG_ENABLED && (m_flash_operations_pending > 0)) + { + m_flash_operations_pending--; + } + + if (p_evt->result == NRF_SUCCESS) + { + NRF_LOG_DEBUG("Flash %s success: addr=%p, pending %d", + (p_evt->id == NRF_FSTORAGE_EVT_WRITE_RESULT) ? "write" : "erase", + p_evt->addr, m_flash_operations_pending); + } + else + { + NRF_LOG_DEBUG("Flash %s failed (0x%x): addr=%p, len=0x%x bytes, pending %d", + (p_evt->id == NRF_FSTORAGE_EVT_WRITE_RESULT) ? "write" : "erase", + p_evt->result, p_evt->addr, p_evt->len, m_flash_operations_pending); + } + + if (p_evt->p_param) + { + //lint -save -e611 (Suspicious cast) + ((nrf_dfu_flash_callback_t)(p_evt->p_param))((void*)p_evt->p_src); + //lint -restore + } +} + + +ret_code_t nrf_dfu_flash_init(bool sd_irq_initialized) +{ + nrf_fstorage_api_t * p_api_impl; + + /* Setup the desired API implementation. */ +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + if (sd_irq_initialized) + { + NRF_LOG_DEBUG("Initializing nrf_fstorage_sd backend."); + p_api_impl = &nrf_fstorage_sd; + } + else +#endif + { + NRF_LOG_DEBUG("Initializing nrf_fstorage_nvmc backend."); + p_api_impl = &nrf_fstorage_nvmc; + } + + return nrf_fstorage_init(&m_fs, p_api_impl, NULL); +} + + +ret_code_t nrf_dfu_flash_store(uint32_t dest, + void const * p_src, + uint32_t len, + nrf_dfu_flash_callback_t callback) +{ + ret_code_t rc; + + NRF_LOG_DEBUG("nrf_fstorage_write(addr=%p, src=%p, len=%d bytes), queue usage: %d", + dest, p_src, len, m_flash_operations_pending); + + //lint -save -e611 (Suspicious cast) + rc = nrf_fstorage_write(&m_fs, dest, p_src, len, (void *)callback); + //lint -restore + + if ((NRF_LOG_ENABLED) && (rc == NRF_SUCCESS)) + { + m_flash_operations_pending++; + } + else + { + NRF_LOG_WARNING("nrf_fstorage_write() failed with error 0x%x.", rc); + } + + return rc; +} + + +ret_code_t nrf_dfu_flash_erase(uint32_t page_addr, + uint32_t num_pages, + nrf_dfu_flash_callback_t callback) +{ + ret_code_t rc; + + NRF_LOG_DEBUG("nrf_fstorage_erase(addr=0x%p, len=%d pages), queue usage: %d", + page_addr, num_pages, m_flash_operations_pending); + + //lint -save -e611 (Suspicious cast) + rc = nrf_fstorage_erase(&m_fs, page_addr, num_pages, (void *)callback); + //lint -restore + + if ((NRF_LOG_ENABLED) && (rc == NRF_SUCCESS)) + { + m_flash_operations_pending++; + } + else + { + NRF_LOG_WARNING("nrf_fstorage_erase() failed with error 0x%x.", rc); + } + + return rc; +} diff --git a/components/libraries/bootloader/dfu/nrf_dfu_flash.h b/components/libraries/bootloader/dfu/nrf_dfu_flash.h new file mode 100644 index 0000000..79d7dec --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_flash.h @@ -0,0 +1,132 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_flash Flash operations + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_FLASH_H__ +#define NRF_DFU_FLASH_H__ + +#include +#include +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief nrf_fstorage event handler function for DFU fstorage operations. + * + * This function will be called after a flash operation has completed. + */ +typedef void (*nrf_dfu_flash_callback_t)(void * p_buf); + + +/**@brief Function for initializing the flash module. + * + * Depending on whether or not the SoftDevice is present and its IRQ have been initialized, + * this function initializes the correct @ref nrf_fstorage backend. + * + * @param[in] sd_irq_initialized Whether or not the SoftDevice IRQ have been initialized. + * + * @retval NRF_SUCCESS If the operation was successful. + */ +ret_code_t nrf_dfu_flash_init(bool sd_irq_initialized); + + +/**@brief Function for storing data to flash. + * + * This functions is asynchronous when the SoftDevice is enabled and synchronous when + * the SoftDevice is not present or disabled. In both cases, if a callback function is provided, + * it will be called when the operation has completed. + * + * @note The content of @p p_src should be kept in memory until the operation has completed. + * + * @param[in] dest The address where the data should be stored. + * @param[in] p_src Pointer to the address where the data should be copied from. + * This address can be in flash or RAM. + * @param[in] len The number of bytes to be copied from @p p_src to @p dest. + * @param[in] callback Callback function. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_STATE If nrf_dfu_flash is not initialized. + * @retval NRF_ERROR_INVALID_ADDR If @p p_src or @p dest is not word-aligned. + * @retval NRF_ERROR_INVALID_LENGTH If @p len is zero. + * @retval NRF_ERROR_NULL If @p p_src is NULL. + * @retval NRF_ERROR_NO_MEM If nrf_fstorage is out of memory. + */ +ret_code_t nrf_dfu_flash_store(uint32_t dest, + void const * p_src, + uint32_t len, + nrf_dfu_flash_callback_t callback); + + +/**@brief Function for erasing data from flash. + * + * This functions is asynchronous when the SoftDevice is enabled and synchronous when + * the SoftDevice is not present or disabled. In both cases, if a callback function is provided, + * it will be called when the operation has completed. + * + * @param[in] page_addr The address of the first flash page to be deleted. + * @param[in] num_pages The number of flash pages to be deleted. + * @param[in] callback Callback function. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_STATE If nrf_dfu_flash is not initialized. + * @retval NRF_ERROR_INVALID_ADDR If @p page_addr is not aligned to a page boundary or the + * operation would go beyond the flash memory boundaries. + * @retval NRF_ERROR_INVALID_LENGTH If @p num_pages is zero. + * @retval NRF_ERROR_NULL If @p page_addr is NULL. + * @retval NRF_ERROR_NO_MEM If the queue of nrf_fstorage is full. + */ +ret_code_t nrf_dfu_flash_erase(uint32_t page_addr, uint32_t num_pages, nrf_dfu_flash_callback_t callback); + + +#ifdef __cplusplus +} +#endif + + +#endif // NRF_DFU_FLASH_H__ +/** @} */ diff --git a/components/libraries/bootloader/dfu/nrf_dfu_handling_error.c b/components/libraries/bootloader/dfu/nrf_dfu_handling_error.c new file mode 100644 index 0000000..3103f59 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_handling_error.c @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_dfu_handling_error.h" + +#include "nrf_log.h" +#include "nrf_dfu_req_handler.h" + +static nrf_dfu_ext_error_code_t m_last_error = NRF_DFU_EXT_ERROR_NO_ERROR; + +nrf_dfu_result_t ext_error_set(nrf_dfu_ext_error_code_t error_code) +{ + m_last_error = error_code; + + return NRF_DFU_RES_CODE_EXT_ERROR; +} + +nrf_dfu_ext_error_code_t ext_error_get() +{ + nrf_dfu_ext_error_code_t last_error = m_last_error; + m_last_error = NRF_DFU_EXT_ERROR_NO_ERROR; + + return last_error; +} diff --git a/components/libraries/bootloader/dfu/nrf_dfu_handling_error.h b/components/libraries/bootloader/dfu/nrf_dfu_handling_error.h new file mode 100644 index 0000000..5249d39 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_handling_error.h @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + /**@file + * + * @defgroup nrf_dfu_rescodes DFU result codes + * @{ + * @ingroup sdk_nrf_dfu_transport + * @brief When the DFU controller sends requests to the DFU bootloader on + * the DFU target, the DFU bootloader answers with any of these result codes. + */ + + +#ifndef DFU_HANDLING_ERROR_H__ +#define DFU_HANDLING_ERROR_H__ + +#include "nrf_dfu_types.h" +#include "nrf_dfu_req_handler.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +/**@brief DFU request extended result codes. + * + * @details When an event returns @ref NRF_DFU_RES_CODE_EXT_ERROR, it also stores an extended error code. + * The transport layer can then send the extended error code together with the error code to give + * the controller additional information about the cause of the error. + */ +typedef enum +{ + NRF_DFU_EXT_ERROR_NO_ERROR = 0x00, /**< No extended error code has been set. This error indicates an implementation problem. */ + NRF_DFU_EXT_ERROR_INVALID_ERROR_CODE = 0x01, /**< Invalid error code. This error code should never be used outside of development. */ + NRF_DFU_EXT_ERROR_WRONG_COMMAND_FORMAT = 0x02, /**< The format of the command was incorrect. This error code is not used in the + current implementation, because @ref NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED + and @ref NRF_DFU_RES_CODE_INVALID_PARAMETER cover all + possible format errors. */ + NRF_DFU_EXT_ERROR_UNKNOWN_COMMAND = 0x03, /**< The command was successfully parsed, but it is not supported or unknown. */ + NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID = 0x04, /**< The init command is invalid. The init packet either has + an invalid update type or it is missing required fields for the update type + (for example, the init packet for a SoftDevice update is missing the SoftDevice size field). */ + NRF_DFU_EXT_ERROR_FW_VERSION_FAILURE = 0x05, /**< The firmware version is too low. For an application or SoftDevice, the version must be greater than + or equal to the current version. For a bootloader, it must be greater than the current version. + to the current version. This requirement prevents downgrade attacks.*/ + NRF_DFU_EXT_ERROR_HW_VERSION_FAILURE = 0x06, /**< The hardware version of the device does not match the required + hardware version for the update. */ + NRF_DFU_EXT_ERROR_SD_VERSION_FAILURE = 0x07, /**< The array of supported SoftDevices for the update does not contain + the FWID of the current SoftDevice or the first FWID is '0' on a + bootloader which requires the SoftDevice to be present. */ + NRF_DFU_EXT_ERROR_SIGNATURE_MISSING = 0x08, /**< The init packet does not contain a signature. This error code is not used in the + current implementation, because init packets without a signature + are regarded as invalid. */ + NRF_DFU_EXT_ERROR_WRONG_HASH_TYPE = 0x09, /**< The hash type that is specified by the init packet is not supported by the DFU bootloader. */ + NRF_DFU_EXT_ERROR_HASH_FAILED = 0x0A, /**< The hash of the firmware image cannot be calculated. */ + NRF_DFU_EXT_ERROR_WRONG_SIGNATURE_TYPE = 0x0B, /**< The type of the signature is unknown or not supported by the DFU bootloader. */ + NRF_DFU_EXT_ERROR_VERIFICATION_FAILED = 0x0C, /**< The hash of the received firmware image does not match the hash in the init packet. */ + NRF_DFU_EXT_ERROR_INSUFFICIENT_SPACE = 0x0D, /**< The available space on the device is insufficient to hold the firmware. */ +} nrf_dfu_ext_error_code_t; + + +/**@brief Function for setting an extended error code that can be retrieved later. + * + * @details When an extended error occurs in the DFU process, this function can be used to store the error. + * + * @param error_code The error code to store. + * + * @retval NRF_DFU_RES_CODE_EXT_ERROR + */ +nrf_dfu_result_t ext_error_set(nrf_dfu_ext_error_code_t error_code); + +/**@brief Function for getting the most recent extended error code. + * + * @details This function is used by the transport layer to fetch the most recent extended error code. + * + * @return The most recent error code. If the function is called again before a new error occurs, @ref NRF_DFU_EXT_ERROR_NO_ERROR is returned. + */ +nrf_dfu_ext_error_code_t ext_error_get( void ); + + +#ifdef __cplusplus +} +#endif + +#endif // DFU_HANDLING_ERROR_H__ + +/** @} */ diff --git a/components/libraries/bootloader/dfu/nrf_dfu_mbr.c b/components/libraries/bootloader/dfu/nrf_dfu_mbr.c new file mode 100644 index 0000000..3644ca3 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_mbr.c @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu_mbr.h" +#include "nrf_mbr.h" +#include "nrf_dfu_types.h" +#include "nrf_log.h" +#include "nrf_bootloader_info.h" + +#define MBR_IRQ_FORWARD_ADDRESS_ADDRESS (0x20000000) //!< The address of the variable that decides where the MBR forwards interrupts + +uint32_t nrf_dfu_mbr_copy_bl(uint32_t * p_src, uint32_t len) +{ + uint32_t ret_val; + uint32_t const len_words = len / sizeof(uint32_t); + + sd_mbr_command_t command = + { + .command = SD_MBR_COMMAND_COPY_BL, + .params.copy_bl.bl_src = p_src, + .params.copy_bl.bl_len = len_words + }; + + ret_val = sd_mbr_command(&command); + + return ret_val; +} + + +uint32_t nrf_dfu_mbr_init_sd(void) +{ + uint32_t ret_val; + + sd_mbr_command_t command = + { + .command = SD_MBR_COMMAND_INIT_SD + }; + + ret_val = sd_mbr_command(&command); + + return ret_val; +} + + +uint32_t nrf_dfu_mbr_irq_forward_address_set(void) +{ + uint32_t ret_val = NRF_ERROR_INVALID_PARAM; + uint32_t address = MBR_SIZE; + +#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD) + sd_mbr_command_t command = + { + .command = SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, + .params.irq_forward_address_set.address = address, + }; + + ret_val = sd_mbr_command(&command); +#endif + + if (ret_val == NRF_ERROR_INVALID_PARAM) + { + // Manually set the forward address if this MBR doesn't have the command. + *(uint32_t *)(MBR_IRQ_FORWARD_ADDRESS_ADDRESS) = address; + + ret_val = NRF_SUCCESS; + } + + return ret_val; +} diff --git a/components/libraries/bootloader/dfu/nrf_dfu_mbr.h b/components/libraries/bootloader/dfu/nrf_dfu_mbr.h new file mode 100644 index 0000000..ac72088 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_mbr.h @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_mbr MBR functions + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_MBR_H__ +#define NRF_DFU_MBR_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Function for copying the bootloader using an MBR command. + * + * @param[in] p_src Source address of the bootloader data to copy. + * @param[in] len Length of the data to copy in bytes. + * + * @return This function will return only if the command request could not be run. + * See @ref sd_mbr_command_copy_bl_t for possible return values. + */ +uint32_t nrf_dfu_mbr_copy_bl(uint32_t * p_src, uint32_t len); + + +/** @brief Function for initializing the SoftDevice using an MBR command. + * + * @retval NRF_SUCCESS If the SoftDevice was initialized successfully. + * Any other return value indicates that the SoftDevice + * could not be initialized. + */ +uint32_t nrf_dfu_mbr_init_sd(void); + + +/** @brief Function for setting the address of the IRQ table to the app's using an MBR command. + * + * @retval NRF_SUCCESS If the address of the new irq table was set. Any other + * return value indicates that the address could not be set. + */ +uint32_t nrf_dfu_mbr_irq_forward_address_set(void); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_MBR_H__ + +/** @} */ diff --git a/components/libraries/bootloader/dfu/nrf_dfu_req_handler.c b/components/libraries/bootloader/dfu/nrf_dfu_req_handler.c new file mode 100644 index 0000000..5b8b7d2 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_req_handler.c @@ -0,0 +1,865 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include "sdk_config.h" +#include "nrf_dfu.h" +#include "nrf_dfu_types.h" +#include "nrf_dfu_req_handler.h" +#include "nrf_dfu_handling_error.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_utils.h" +#include "nrf_dfu_flash.h" +#include "nrf_fstorage.h" +#include "nrf_bootloader_info.h" +#include "app_util.h" +#include "pb.h" +#include "pb_common.h" +#include "pb_decode.h" +#include "dfu-cc.pb.h" +#include "crc32.h" +#include "app_scheduler.h" +#include "sdk_macros.h" +#include "nrf_crypto.h" +#include "nrf_assert.h" +#include "nrf_dfu_validation.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_req_handler +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define NRF_DFU_PROTOCOL_VERSION (0x01) + +#ifndef NRF_DFU_PROTOCOL_REDUCED +#define NRF_DFU_PROTOCOL_REDUCED 0 +#endif + +STATIC_ASSERT(DFU_SIGNED_COMMAND_SIZE <= INIT_COMMAND_MAX_SIZE); + +static uint32_t m_firmware_start_addr; /**< Start address of the current firmware image. */ +static uint32_t m_firmware_size_req; /**< The size of the entire firmware image. Defined by the init command. */ + +static nrf_dfu_observer_t m_observer; + + +static void on_dfu_complete(nrf_fstorage_evt_t * p_evt) +{ + UNUSED_PARAMETER(p_evt); + + NRF_LOG_DEBUG("All flash operations have completed. DFU completed."); + + m_observer(NRF_DFU_EVT_DFU_COMPLETED); +} + + +static nrf_dfu_result_t ext_err_code_handle(nrf_dfu_result_t ret_val) +{ + if (ret_val < NRF_DFU_RES_CODE_EXT_ERROR) + { + return ret_val; + } + else + { + nrf_dfu_ext_error_code_t ext_err = + (nrf_dfu_ext_error_code_t)((uint8_t)ret_val - (uint8_t)NRF_DFU_RES_CODE_EXT_ERROR); + return ext_error_set(ext_err); + } +} + + +#if !NRF_DFU_PROTOCOL_REDUCED +static void on_protocol_version_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_PROTOCOL_VERSION"); + + if (NRF_DFU_PROTOCOL_VERSION_MSG) + { + p_res->protocol.version = NRF_DFU_PROTOCOL_VERSION; + } + else + { + NRF_LOG_DEBUG("NRF_DFU_OP_PROTOCOL_VERSION disabled."); + p_res->result = NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED; + } +} + + +static void on_hw_version_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_HARDWARE_VERSION"); + + p_res->hardware.part = NRF_FICR->INFO.PART; + p_res->hardware.variant = NRF_FICR->INFO.VARIANT; + + /* FICR values are in Kilobytes, we report them in bytes. */ + p_res->hardware.memory.ram_size = NRF_FICR->INFO.RAM * 1024; + p_res->hardware.memory.rom_size = NRF_FICR->INFO.FLASH * 1024; + p_res->hardware.memory.rom_page_size = NRF_FICR->CODEPAGESIZE; +} + + +static void on_fw_version_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_FIRMWARE_VERSION"); + NRF_LOG_DEBUG("Firmware image requested: %d", p_req->firmware.image_number); + + if (NRF_DFU_PROTOCOL_FW_VERSION_MSG) + { + uint8_t fw_count = 1; + + if (SD_PRESENT) + { + fw_count++; + } + + if (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP) + { + fw_count++; + } + + p_res->result = NRF_DFU_RES_CODE_SUCCESS; + + if (p_req->firmware.image_number == 0) + { + /* Bootloader is always present and it is always image zero. */ + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_BOOTLOADER; + p_res->firmware.version = s_dfu_settings.bootloader_version; + p_res->firmware.addr = BOOTLOADER_START_ADDR; + p_res->firmware.len = BOOTLOADER_SIZE; + } + else if ((p_req->firmware.image_number == 1) && SD_PRESENT) + { + /* If a SoftDevice is present, it will be firmware image one. */ + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_SOFTDEVICE; + p_res->firmware.version = SD_VERSION_GET(MBR_SIZE); + p_res->firmware.addr = MBR_SIZE; + p_res->firmware.len = SD_SIZE_GET(MBR_SIZE); + } + else if ((p_req->firmware.image_number < fw_count)) + { + /* Either there is no SoftDevice and the firmware image requested is one, + * or there is a SoftDevice and the firmware image requested is two. + */ + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_APPLICATION; + p_res->firmware.version = s_dfu_settings.app_version; + p_res->firmware.addr = nrf_dfu_app_start_address(); + p_res->firmware.len = s_dfu_settings.bank_0.image_size; + } + else + { + NRF_LOG_DEBUG("No such firmware image"); + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_UNKNOWN; + p_res->firmware.version = 0x00; + p_res->firmware.addr = 0x00; + p_res->firmware.len = 0x00; + } + } + else + { + NRF_LOG_DEBUG("NRF_DFU_OP_FIRMWARE_VERSION disabled."); + p_res->result = NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED; + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_UNKNOWN; + } +} + + +static void on_ping_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_PING"); + p_res->ping.id = p_req->ping.id; +} + + +static void on_mtu_get_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_MTU_GET"); + p_res->mtu.size = p_req->mtu.size; +} +#endif // !NRF_DFU_PROTOCOL_REDUCED + + +static void on_prn_set_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + UNUSED_PARAMETER(p_res); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_RECEIPT_NOTIF_SET"); +} + + +static void on_abort_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + UNUSED_PARAMETER(p_res); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_ABORT"); + + m_observer(NRF_DFU_EVT_DFU_ABORTED); +} + + +/* Set offset and CRC fields in the response for a 'command' message. */ +static void cmd_response_offset_and_crc_set(nrf_dfu_response_t * const p_res) +{ + ASSERT(p_res); + + /* Copy the CRC and offset of the init packet. */ + p_res->crc.offset = s_dfu_settings.progress.command_offset; + p_res->crc.crc = s_dfu_settings.progress.command_crc; +} + + +static void on_cmd_obj_select_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_SELECT (command)"); + + p_res->select.max_size = INIT_COMMAND_MAX_SIZE; + cmd_response_offset_and_crc_set(p_res); +} + + +static void on_cmd_obj_create_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_res); + + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_CREATE (command)"); + + m_observer(NRF_DFU_EVT_DFU_STARTED); + + nrf_dfu_result_t ret_val = nrf_dfu_validation_init_cmd_create(p_req->create.object_size); + p_res->result = ext_err_code_handle(ret_val); +} + + +static void on_cmd_obj_write_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_req->write.p_data); + ASSERT(p_req->write.len); + ASSERT(p_res); + + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_WRITE (command)"); + + nrf_dfu_result_t ret_val; + + ret_val = nrf_dfu_validation_init_cmd_append(p_req->write.p_data, p_req->write.len); + p_res->result = ext_err_code_handle(ret_val); + + /* Update response. This is only used when the PRN is triggered and the 'write' message + * is answered with a CRC message and these field are copied into the response. */ + cmd_response_offset_and_crc_set(p_res); + + /* If a callback to free the request payload buffer was provided, invoke it now. */ + if (p_req->callback.write) + { + p_req->callback.write((void*)p_req->write.p_data); + } +} + + +static void on_cmd_obj_execute_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_res); + + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_EXECUTE (command)"); + + nrf_dfu_result_t ret_val; + ret_val = nrf_dfu_validation_init_cmd_execute(&m_firmware_start_addr, &m_firmware_size_req); + p_res->result = ext_err_code_handle(ret_val); + + if (p_res->result == NRF_DFU_RES_CODE_SUCCESS) + { + if (nrf_dfu_settings_write_and_backup(NULL) == NRF_SUCCESS) + { + /* Setting DFU to initialized */ + NRF_LOG_DEBUG("Writing valid init command to flash."); + } + else + { + p_res->result = NRF_DFU_RES_CODE_OPERATION_FAILED; + } + } +} + + +static void on_cmd_obj_crc_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_CRC_GET (command)"); + + cmd_response_offset_and_crc_set(p_res); +} + + +/** @brief Function handling command requests from the transport layer. + * + * @param p_req[in] Pointer to the structure holding the DFU request. + * @param p_res[out] Pointer to the structure holding the DFU response. + * + * @retval NRF_SUCCESS If the command request was executed successfully. + * Any other error code indicates that the data request + * could not be handled. + */ +static void nrf_dfu_command_req(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_res); + + switch (p_req->request) + { + case NRF_DFU_OP_OBJECT_CREATE: + { + on_cmd_obj_create_request(p_req, p_res); + } break; + + case NRF_DFU_OP_CRC_GET: + { + on_cmd_obj_crc_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_WRITE: + { + on_cmd_obj_write_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_EXECUTE: + { + on_cmd_obj_execute_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_SELECT: + { + on_cmd_obj_select_request(p_req, p_res); + } break; + + default: + { + ASSERT(false); + } break; + } +} + + +static void on_data_obj_select_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_SELECT (data)"); + + p_res->select.crc = s_dfu_settings.progress.firmware_image_crc; + p_res->select.offset = s_dfu_settings.progress.firmware_image_offset; + + p_res->select.max_size = DATA_OBJECT_MAX_SIZE; + + NRF_LOG_DEBUG("crc = 0x%x, offset = 0x%x, max_size = 0x%x", + p_res->select.crc, + p_res->select.offset, + p_res->select.max_size); +} + + +static void on_data_obj_create_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_CREATE (data)"); + + if (!nrf_dfu_validation_init_cmd_present()) + { + /* Can't accept data because DFU isn't initialized by init command. */ + NRF_LOG_ERROR("Cannot create data object without valid init command"); + p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + return; + } + + if (p_req->create.object_size == 0) + { + NRF_LOG_ERROR("Object size cannot be 0.") + p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER; + return; + } + + if ( ((p_req->create.object_size & (CODE_PAGE_SIZE - 1)) != 0) + && (s_dfu_settings.progress.firmware_image_offset_last + p_req->create.object_size != m_firmware_size_req)) + { + NRF_LOG_ERROR("Object size must be page aligned"); + p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER; + return; + } + + if (p_req->create.object_size > DATA_OBJECT_MAX_SIZE) + { + /* It is impossible to handle the command because the size is too large */ + NRF_LOG_ERROR("Invalid size for object (too large)"); + p_res->result = NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES; + return; + } + + if ((s_dfu_settings.progress.firmware_image_offset_last + p_req->create.object_size) > + m_firmware_size_req) + { + NRF_LOG_ERROR("Creating the object with size 0x%08x would overflow firmware size. " + "Offset is 0x%08x and firmware size is 0x%08x.", + p_req->create.object_size, + s_dfu_settings.progress.firmware_image_offset_last, + m_firmware_size_req); + + p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + return; + } + + s_dfu_settings.progress.data_object_size = p_req->create.object_size; + s_dfu_settings.progress.firmware_image_crc = s_dfu_settings.progress.firmware_image_crc_last; + s_dfu_settings.progress.firmware_image_offset = s_dfu_settings.progress.firmware_image_offset_last; + s_dfu_settings.write_offset = s_dfu_settings.progress.firmware_image_offset_last; + + /* Erase the page we're at. */ + if (nrf_dfu_flash_erase((m_firmware_start_addr + s_dfu_settings.progress.firmware_image_offset), + CEIL_DIV(p_req->create.object_size, CODE_PAGE_SIZE), NULL) != NRF_SUCCESS) + { + NRF_LOG_ERROR("Erase operation failed"); + p_res->result = NRF_DFU_RES_CODE_INVALID_OBJECT; + return; + } + + NRF_LOG_DEBUG("Creating object with size: %d. Offset: 0x%08x, CRC: 0x%08x", + s_dfu_settings.progress.data_object_size, + s_dfu_settings.progress.firmware_image_offset, + s_dfu_settings.progress.firmware_image_crc); +} + + +static void on_data_obj_write_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_WRITE (data)"); + + if (!nrf_dfu_validation_init_cmd_present()) + { + /* Can't accept data because DFU isn't initialized by init command. */ + p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + return; + } + + uint32_t const data_object_offset = s_dfu_settings.progress.firmware_image_offset - + s_dfu_settings.progress.firmware_image_offset_last; + + if ((p_req->write.len + data_object_offset) > s_dfu_settings.progress.data_object_size) + { + /* Can't accept data because too much data has been received. */ + NRF_LOG_ERROR("Write request too long"); + p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER; + return; + } + + uint32_t const write_addr = m_firmware_start_addr + s_dfu_settings.write_offset; + /* CRC must be calculated before handing off the data to fstorage because the data is + * freed on write completion. + */ + uint32_t const next_crc = + crc32_compute(p_req->write.p_data, p_req->write.len, &s_dfu_settings.progress.firmware_image_crc); + + ASSERT(p_req->callback.write); + + ret_code_t ret = + nrf_dfu_flash_store(write_addr, p_req->write.p_data, p_req->write.len, p_req->callback.write); + + if (ret != NRF_SUCCESS) + { + /* When nrf_dfu_flash_store() fails because there is no space in the queue, + * stop processing the request so that the peer can detect a CRC error + * and retransmit this object. Remember to manually free the buffer ! + */ + p_req->callback.write((void*)p_req->write.p_data); + return; + } + + /* Update the CRC of the firmware image. */ + s_dfu_settings.write_offset += p_req->write.len; + s_dfu_settings.progress.firmware_image_offset += p_req->write.len; + s_dfu_settings.progress.firmware_image_crc = next_crc; + + /* This is only used when the PRN is triggered and the 'write' message + * is answered with a CRC message and these field are copied into the response. + */ + p_res->write.crc = s_dfu_settings.progress.firmware_image_crc; + p_res->write.offset = s_dfu_settings.progress.firmware_image_offset; +} + + +static void on_data_obj_crc_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_CRC_GET (data)"); + NRF_LOG_DEBUG("Offset:%d, CRC:0x%08x", + s_dfu_settings.progress.firmware_image_offset, + s_dfu_settings.progress.firmware_image_crc); + + p_res->crc.crc = s_dfu_settings.progress.firmware_image_crc; + p_res->crc.offset = s_dfu_settings.progress.firmware_image_offset; +} + + +static void on_data_obj_execute_request_sched(void * p_evt, uint16_t event_length) +{ + UNUSED_PARAMETER(event_length); + + ret_code_t ret; + nrf_dfu_request_t * p_req = (nrf_dfu_request_t *)(p_evt); + + /* Wait for all buffers to be written in flash. */ + if (nrf_fstorage_is_busy(NULL)) + { + ret = app_sched_event_put(p_req, sizeof(nrf_dfu_request_t), on_data_obj_execute_request_sched); + if (ret != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed to schedule object execute: 0x%x.", ret); + } + return; + } + + nrf_dfu_response_t res = + { + .request = NRF_DFU_OP_OBJECT_EXECUTE, + }; + + if (s_dfu_settings.progress.firmware_image_offset == m_firmware_size_req) + { + NRF_LOG_DEBUG("Whole firmware image received. Postvalidating."); + + #if NRF_DFU_IN_APP + res.result = nrf_dfu_validation_post_data_execute(m_firmware_start_addr, m_firmware_size_req); + #else + res.result = nrf_dfu_validation_activation_prepare(m_firmware_start_addr, m_firmware_size_req); + #endif + + res.result = ext_err_code_handle(res.result); + + /* Provide response to transport */ + p_req->callback.response(&res, p_req->p_context); + + ret = nrf_dfu_settings_write_and_backup((nrf_dfu_flash_callback_t)on_dfu_complete); + UNUSED_RETURN_VALUE(ret); + } + else + { + res.result = NRF_DFU_RES_CODE_SUCCESS; + + /* Provide response to transport */ + p_req->callback.response(&res, p_req->p_context); + + if (NRF_DFU_SAVE_PROGRESS_IN_FLASH) + { + /* Allowing skipping settings backup to save time and flash wear. */ + ret = nrf_dfu_settings_write_and_backup(NULL); + UNUSED_RETURN_VALUE(ret); + } + } + + NRF_LOG_DEBUG("Request handling complete. Result: 0x%x", res.result); +} + + +static bool on_data_obj_execute_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_EXECUTE (data)"); + + uint32_t const data_object_size = s_dfu_settings.progress.firmware_image_offset - + s_dfu_settings.progress.firmware_image_offset_last; + + if (s_dfu_settings.progress.data_object_size != data_object_size) + { + /* The size of the written object was not as expected. */ + NRF_LOG_ERROR("Invalid data. expected: %d, got: %d", + s_dfu_settings.progress.data_object_size, + data_object_size); + + p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + return true; + } + + /* Update the offset and crc values for the last object written. */ + s_dfu_settings.progress.data_object_size = 0; + s_dfu_settings.progress.firmware_image_crc_last = s_dfu_settings.progress.firmware_image_crc; + s_dfu_settings.progress.firmware_image_offset_last = s_dfu_settings.progress.firmware_image_offset; + + on_data_obj_execute_request_sched(p_req, 0); + + m_observer(NRF_DFU_EVT_OBJECT_RECEIVED); + + return false; +} + + +static bool nrf_dfu_data_req(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_res); + + bool response_ready = true; + + switch (p_req->request) + { + case NRF_DFU_OP_OBJECT_CREATE: + { + on_data_obj_create_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_WRITE: + { + on_data_obj_write_request(p_req, p_res); + } break; + + case NRF_DFU_OP_CRC_GET: + { + on_data_obj_crc_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_EXECUTE: + { + response_ready = on_data_obj_execute_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_SELECT: + { + on_data_obj_select_request(p_req, p_res); + } break; + + default: + { + ASSERT(false); + } break; + } + + return response_ready; +} + + +/**@brief Function for handling requests to manipulate data or command objects. + * + * @param[in] p_req Request. + * @param[out] p_res Response. + * + * @return Whether response is ready to be sent. + */ +static bool nrf_dfu_obj_op(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + /* Keep track of the current object type since write and execute requests don't contain it. */ + static nrf_dfu_obj_type_t current_object = NRF_DFU_OBJ_TYPE_COMMAND; + + if ( (p_req->request == NRF_DFU_OP_OBJECT_SELECT) + || (p_req->request == NRF_DFU_OP_OBJECT_CREATE)) + { + STATIC_ASSERT(offsetof(nrf_dfu_request_select_t, object_type) == + offsetof(nrf_dfu_request_create_t, object_type), + "Wrong object_type offset!"); + + current_object = (nrf_dfu_obj_type_t)(p_req->select.object_type); + } + + bool response_ready = true; + + switch (current_object) + { + case NRF_DFU_OBJ_TYPE_COMMAND: + nrf_dfu_command_req(p_req, p_res); + break; + + case NRF_DFU_OBJ_TYPE_DATA: + response_ready = nrf_dfu_data_req(p_req, p_res); + break; + + default: + /* The select request had an invalid object type. */ + NRF_LOG_ERROR("Invalid object type in request."); + current_object = NRF_DFU_OBJ_TYPE_INVALID; + p_res->result = NRF_DFU_RES_CODE_INVALID_OBJECT; + break; + } + + return response_ready; +} + + +static void nrf_dfu_req_handler_req_process(nrf_dfu_request_t * p_req) +{ + ASSERT(p_req->callback.response); + + bool response_ready = true; + + /* The request handlers assume these values to be set. */ + nrf_dfu_response_t response = + { + .request = p_req->request, + .result = NRF_DFU_RES_CODE_SUCCESS, + }; + + + switch (p_req->request) + { +#if !NRF_DFU_PROTOCOL_REDUCED + case NRF_DFU_OP_PROTOCOL_VERSION: + { + on_protocol_version_request(p_req, &response); + } break; + + case NRF_DFU_OP_HARDWARE_VERSION: + { + on_hw_version_request(p_req, &response); + } break; + + case NRF_DFU_OP_FIRMWARE_VERSION: + { + on_fw_version_request(p_req, &response); + } break; + + case NRF_DFU_OP_PING: + { + on_ping_request(p_req, &response); + } break; + + case NRF_DFU_OP_MTU_GET: + { + on_mtu_get_request(p_req, &response); + } break; +#endif + case NRF_DFU_OP_RECEIPT_NOTIF_SET: + { + on_prn_set_request(p_req, &response); + } break; + + case NRF_DFU_OP_ABORT: + { + on_abort_request(p_req, &response); + } break; + + case NRF_DFU_OP_OBJECT_CREATE: + /* Restart the inactivity timer on CREATE messages. */ + /* Fallthrough. */ + case NRF_DFU_OP_OBJECT_SELECT: + case NRF_DFU_OP_OBJECT_WRITE: + case NRF_DFU_OP_OBJECT_EXECUTE: + case NRF_DFU_OP_CRC_GET: + { + response_ready = nrf_dfu_obj_op(p_req, &response); + } break; + + default: + NRF_LOG_INFO("Invalid opcode received: 0x%x.", p_req->request); + response.result = NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED; + break; + } + + if (response_ready) + { + NRF_LOG_DEBUG("Request handling complete. Result: 0x%x", response.result); + + p_req->callback.response(&response, p_req->p_context); + + if (response.result != NRF_DFU_RES_CODE_SUCCESS) + { + m_observer(NRF_DFU_EVT_DFU_FAILED); + } + } +} + + +static void nrf_dfu_req_handler_req(void * p_evt, uint16_t event_length) +{ + nrf_dfu_request_t * p_req = (nrf_dfu_request_t *)(p_evt); + nrf_dfu_req_handler_req_process(p_req); +} + + +ret_code_t nrf_dfu_req_handler_on_req(nrf_dfu_request_t * p_req) +{ + ret_code_t ret; + + if (p_req->callback.response == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + + ret = app_sched_event_put(p_req, sizeof(nrf_dfu_request_t), nrf_dfu_req_handler_req); + if (ret != NRF_SUCCESS) + { + NRF_LOG_WARNING("Scheduler ran out of space!"); + } + + return ret; +} + + +ret_code_t nrf_dfu_req_handler_init(nrf_dfu_observer_t observer) +{ + ret_code_t ret_val; + nrf_dfu_result_t result; + + if (observer == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + ret_val = nrf_dfu_flash_init(true); +#else + ret_val = nrf_dfu_flash_init(false); +#endif + if (ret_val != NRF_SUCCESS) + { + return ret_val; + } + + nrf_dfu_validation_init(); + if (nrf_dfu_validation_init_cmd_present()) + { + /* Execute a previously received init packed. Subsequent executes will have no effect. */ + result = nrf_dfu_validation_init_cmd_execute(&m_firmware_start_addr, &m_firmware_size_req); + if (result != NRF_DFU_RES_CODE_SUCCESS) + { + /* Init packet in flash is not valid! */ + return NRF_ERROR_INTERNAL; + } + } + + m_observer = observer; + + /* Initialize extended error handling with "No error" as the most recent error. */ + result = ext_error_set(NRF_DFU_EXT_ERROR_NO_ERROR); + UNUSED_RETURN_VALUE(result); + + return NRF_SUCCESS; +} diff --git a/components/libraries/bootloader/dfu/nrf_dfu_req_handler.h b/components/libraries/bootloader/dfu/nrf_dfu_req_handler.h new file mode 100644 index 0000000..7d7cb72 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_req_handler.h @@ -0,0 +1,345 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_req_handler Request handling + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_REQ_HANDLER_H__ +#define NRF_DFU_REQ_HANDLER_H__ + +#include +#include +#include "app_util_platform.h" +#include "nrf_dfu_flash.h" +#include "nrf_dfu_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +ANON_UNIONS_ENABLE; + +/** + * @brief DFU object types. + */ +typedef enum +{ + NRF_DFU_OBJ_TYPE_INVALID, //!< Invalid object type. + NRF_DFU_OBJ_TYPE_COMMAND, //!< Command object. + NRF_DFU_OBJ_TYPE_DATA, //!< Data object. +} nrf_dfu_obj_type_t; + +/** + * @brief DFU protocol operation. + */ +typedef enum +{ + NRF_DFU_OP_PROTOCOL_VERSION = 0x00, //!< Retrieve protocol version. + NRF_DFU_OP_OBJECT_CREATE = 0x01, //!< Create selected object. + NRF_DFU_OP_RECEIPT_NOTIF_SET = 0x02, //!< Set receipt notification. + NRF_DFU_OP_CRC_GET = 0x03, //!< Request CRC of selected object. + NRF_DFU_OP_OBJECT_EXECUTE = 0x04, //!< Execute selected object. + NRF_DFU_OP_OBJECT_SELECT = 0x06, //!< Select object. + NRF_DFU_OP_MTU_GET = 0x07, //!< Retrieve MTU size. + NRF_DFU_OP_OBJECT_WRITE = 0x08, //!< Write selected object. + NRF_DFU_OP_PING = 0x09, //!< Ping. + NRF_DFU_OP_HARDWARE_VERSION = 0x0A, //!< Retrieve hardware version. + NRF_DFU_OP_FIRMWARE_VERSION = 0x0B, //!< Retrieve firmware version. + NRF_DFU_OP_ABORT = 0x0C, //!< Abort the DFU procedure. + NRF_DFU_OP_RESPONSE = 0x60, //!< Response. + NRF_DFU_OP_INVALID = 0xFF, +} nrf_dfu_op_t; + +/** + * @brief DFU operation result code. + */ +typedef enum +{ + NRF_DFU_RES_CODE_INVALID = 0x00, //!< Invalid opcode. + NRF_DFU_RES_CODE_SUCCESS = 0x01, //!< Operation successful. + NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED = 0x02, //!< Opcode not supported. + NRF_DFU_RES_CODE_INVALID_PARAMETER = 0x03, //!< Missing or invalid parameter value. + NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES = 0x04, //!< Not enough memory for the data object. + NRF_DFU_RES_CODE_INVALID_OBJECT = 0x05, //!< Data object does not match the firmware and hardware requirements, the signature is wrong, or parsing the command failed. + NRF_DFU_RES_CODE_UNSUPPORTED_TYPE = 0x07, //!< Not a valid object type for a Create request. + NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED = 0x08, //!< The state of the DFU process does not allow this operation. + NRF_DFU_RES_CODE_OPERATION_FAILED = 0x0A, //!< Operation failed. + NRF_DFU_RES_CODE_EXT_ERROR = 0x0B, //!< Extended error. The next byte of the response contains the error code of the extended error (see @ref nrf_dfu_ext_error_code_t. +} nrf_dfu_result_t; + +typedef enum +{ + NRF_DFU_FIRMWARE_TYPE_SOFTDEVICE = 0x00, + NRF_DFU_FIRMWARE_TYPE_APPLICATION = 0x01, + NRF_DFU_FIRMWARE_TYPE_BOOTLOADER = 0x02, + NRF_DFU_FIRMWARE_TYPE_UNKNOWN = 0xFF, +} nrf_dfu_firmware_type_t; + +/** + * @brief @ref NRF_DFU_OP_PROTOCOL_VERSION response details. + */ +typedef struct +{ + uint8_t version; //!< Protocol version. +} nrf_dfu_response_protocol_t; + +/** + * @brief @ref NRF_DFU_OP_HARDWARE_VERSION response details. + */ +typedef struct +{ + uint32_t part; //!< Hardware part, from FICR register. + uint32_t variant; //!< Hardware variant, from FICR register. + struct + { + uint32_t rom_size; //!< ROM size, in bytes. + uint32_t ram_size; //!< RAM size, in bytes. + uint32_t rom_page_size; //!< ROM flash page size, in bytes. + } memory; +} nrf_dfu_response_hardware_t; + +/** + * @brief @ref NRF_DFU_OP_FIRMWARE_VERSION response details. + */ +typedef struct +{ + nrf_dfu_firmware_type_t type; //!< Firmware type. + uint32_t version; //!< Firmware version. + uint32_t addr; //!< Firmware address in flash. + uint32_t len; //!< Firmware length in bytes. +} nrf_dfu_response_firmware_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_SELECT response details. + */ +typedef struct +{ + uint32_t offset; //!< Current offset. + uint32_t crc; //!< Current CRC. + uint32_t max_size; //!< Maximum size of selected object. +} nrf_dfu_response_select_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_CREATE response details. + */ +typedef struct +{ + uint32_t offset; //!< Current offset + uint32_t crc; //!< Current CRC. +} nrf_dfu_response_create_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_WRITE response details. + */ +typedef struct +{ + uint32_t offset; //!< Used only when packet receipt notification is used. + uint32_t crc; //!< Used only when packet receipt notification is used. +} nrf_dfu_response_write_t; + +/** + * @brief @ref NRF_DFU_OP_CRC_GET response details. + */ +typedef struct +{ + uint32_t offset; //!< Current offset. + uint32_t crc; //!< Current CRC. +} nrf_dfu_response_crc_t; + +/** + * @brief @ref NRF_DFU_OP_PING response details. + */ +typedef struct +{ + uint8_t id; //!< The received ID which is echoed back. +} nrf_dfu_response_ping_t; + +/** + * @brief @ref NRF_DFU_OP_MTU_GET response details. + */ +typedef struct +{ + uint16_t size; //!< The MTU size as specified by the local transport. +} nrf_dfu_response_mtu_t; + +/** + * @brief DFU response message. + */ +typedef struct +{ + nrf_dfu_op_t request; //!< Requested operation. + nrf_dfu_result_t result; //!< Result of the operation. + union + { + nrf_dfu_response_protocol_t protocol; //!< Protocol version response. + nrf_dfu_response_hardware_t hardware; //!< Hardware version response. + nrf_dfu_response_firmware_t firmware; //!< Firmware version response. + nrf_dfu_response_select_t select; //!< Select object response.. + nrf_dfu_response_create_t create; //!< Create object response.. + nrf_dfu_response_write_t write; //!< Write object response. + nrf_dfu_response_crc_t crc; //!< CRC response. + nrf_dfu_response_ping_t ping; //!< Ping response. + nrf_dfu_response_mtu_t mtu; //!< MTU response. + }; +} nrf_dfu_response_t; + +/** + * @brief @ref NRF_DFU_OP_FIRMWARE_VERSION request details. + */ +typedef struct +{ + uint8_t image_number; //!< Index of the firmware. +} nrf_dfu_request_firmware_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_SELECT request details. + */ +typedef struct +{ + uint32_t object_type; //!< Object type. See @ref nrf_dfu_obj_type_t. +} nrf_dfu_request_select_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_CREATE request details. + */ +typedef struct +{ + uint32_t object_type; //!< Object type. See @ref nrf_dfu_obj_type_t. + uint32_t object_size; //!< Object size in bytes. +} nrf_dfu_request_create_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_WRITE request details. + */ +typedef struct +{ + uint8_t const * p_data; //!< Data. + uint16_t len; //!< Length of data in @ref nrf_dfu_request_write_t::p_data. +} nrf_dfu_request_write_t; + +/** + * @brief @ref NRF_DFU_OP_PING request details. + */ +typedef struct +{ + uint8_t id; //!< Ping ID that will be returned in response. +} nrf_dfu_request_ping_t; + +/** + * @brief @ref NRF_DFU_OP_MTU_GET request details. + */ +typedef struct +{ + uint16_t size; //!< Transport MTU size in bytes. +} nrf_dfu_request_mtu_t; + +/** + * @brief @ref NRF_DFU_OP_RECEIPT_NOTIF_SET request details. + */ +typedef struct +{ + uint32_t target; //!< Target PRN. +} nrf_dfu_request_prn_t; + + +typedef void (*nrf_dfu_response_callback_t)(nrf_dfu_response_t * p_res, void * p_context); + +/** + *@brief DFU request. + */ +typedef struct +{ + nrf_dfu_op_t request; //!< Requested operation. + void * p_context; + struct + { + nrf_dfu_response_callback_t response; //!< Callback to call to send the response. + nrf_dfu_flash_callback_t write; + } callback; + union + { + nrf_dfu_request_firmware_t firmware; //!< Firmware version request. + nrf_dfu_request_select_t select; //!< Select object request. + nrf_dfu_request_create_t create; //!< Create object request. + nrf_dfu_request_write_t write; //!< Write object request. + nrf_dfu_request_ping_t ping; //!< Ping. + nrf_dfu_request_mtu_t mtu; //!< MTU size request. + nrf_dfu_request_prn_t prn; //!< Set receipt notification request. + }; +} nrf_dfu_request_t; + + +/**@brief Function for initializing the request handling module. + * + * @param observer Callback function for receiving notifications. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INTERNAL If the init packet in flash is not valid. + * @retval NRF_ERROR_INVALID_PARAM If observer is not provided. + */ +ret_code_t nrf_dfu_req_handler_init(nrf_dfu_observer_t observer); + + +/**@brief Function for scheduling processing of a DFU request. + * + * Requests are processed asynchronously by the scheduler. + * + * @param[in] p_req Request to be handled. The response callback must be non-null. + * + * @retval NRF_SUCCESS If the command request was executed successfully. + * @retval NRF_ERROR_NO_MEM If the scheduler ran out of memory. + * @retval NRF_ERROR_INVALID_PARAM If the response callback is NULL. + */ +ret_code_t nrf_dfu_req_handler_on_req(nrf_dfu_request_t * p_req); + + +ANON_UNIONS_DISABLE; + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_REQ_HANDLER_H__ + +/** @} */ diff --git a/components/libraries/bootloader/dfu/nrf_dfu_settings.c b/components/libraries/bootloader/dfu/nrf_dfu_settings.c new file mode 100644 index 0000000..794dfec --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_settings.c @@ -0,0 +1,433 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_dfu_settings.h" +#include +#include +#include "nrf_dfu_flash.h" +#include "nrf_soc.h" +#include "crc32.h" +#include "nrf_nvmc.h" +#include "sdk_config.h" + + +#define DFU_SETTINGS_VERSION_OFFSET (offsetof(nrf_dfu_settings_t, settings_version)) //crc != 0xFFFFFFFF) + { + // CRC is set. Content must be valid + uint32_t crc = settings_crc_get(p_settings); + if (crc == p_settings->crc) + { + return true; + } + } + return false; +} + + +static uint32_t boot_validation_crc(nrf_dfu_settings_t const * p_settings) +{ + return crc32_compute((const uint8_t *)&p_settings->boot_validation_softdevice, + DFU_SETTINGS_BOOT_VALIDATION_SIZE - 4, + NULL); +} + + +static bool boot_validation_crc_ok(nrf_dfu_settings_t const * p_settings) +{ + return (boot_validation_crc(p_settings) == p_settings->boot_validation_crc); +} + + +static bool settings_crc_ok(void) +{ + nrf_dfu_settings_t const * p_settings = (nrf_dfu_settings_t const *)m_dfu_settings_buffer; + return crc_ok(p_settings); +} + + +static bool settings_backup_crc_ok(void) +{ + nrf_dfu_settings_t const * p_settings = (nrf_dfu_settings_t const *)mp_dfu_settings_backup_buffer; + return crc_ok(p_settings) && ((p_settings->settings_version == 1) || boot_validation_crc_ok(p_settings)); +} + +#define REGION_COPY_BY_MEMBER(start_member, end_member, p_dst_addr) \ + memcpy(p_dst_addr + offsetof(nrf_dfu_settings_t, start_member), \ + mp_dfu_settings_backup_buffer + offsetof(nrf_dfu_settings_t, start_member), \ + offsetof(nrf_dfu_settings_t, end_member) - offsetof(nrf_dfu_settings_t, start_member)) + + +static void settings_forbidden_parts_copy_from_backup(uint8_t * p_dst_addr) +{ +#if NRF_DFU_IN_APP || NRF_BL_DFU_ALLOW_UPDATE_FROM_APP + REGION_COPY_BY_MEMBER(settings_version, bank_current, p_dst_addr); + REGION_COPY_BY_MEMBER(bank_0, write_offset, p_dst_addr); + REGION_COPY_BY_MEMBER(sd_size, progress, p_dst_addr); + REGION_COPY_BY_MEMBER(boot_validation_crc, peer_data, p_dst_addr); +#else + REGION_COPY_BY_MEMBER(settings_version, enter_buttonless_dfu, p_dst_addr); + REGION_COPY_BY_MEMBER(init_command, peer_data, p_dst_addr); +#endif +} + +void nrf_dfu_settings_reinit(void) +{ + bool settings_valid = settings_crc_ok(); + bool settings_backup_valid = settings_backup_crc_ok(); + + if (settings_valid) + { + NRF_LOG_DEBUG("Using settings page."); + memcpy(&s_dfu_settings, m_dfu_settings_buffer, sizeof(nrf_dfu_settings_t)); + if (settings_backup_valid) + { + NRF_LOG_DEBUG("Copying forbidden parts from backup page."); + settings_forbidden_parts_copy_from_backup((uint8_t *)&s_dfu_settings); + } + } + else if (settings_backup_valid) + { + NRF_LOG_INFO("Restoring settings from backup since the settings page contents are " + "invalid (CRC error)."); + memcpy(&s_dfu_settings, + mp_dfu_settings_backup_buffer, + sizeof(nrf_dfu_settings_t)); + } + else + { + NRF_LOG_WARNING("Resetting bootloader settings since neither the settings page nor the " + "backup are valid (CRC error)."); + memset(&s_dfu_settings, 0x00, sizeof(nrf_dfu_settings_t)); + s_dfu_settings.settings_version = NRF_DFU_SETTINGS_VERSION; + } + + if (NRF_DFU_SETTINGS_COMPATIBILITY_MODE && !NRF_DFU_IN_APP && (s_dfu_settings.settings_version == 1)) + { + NRF_LOG_INFO("Old settings page detected. Upgrading info."); + + // Old version. Translate. + memcpy(&s_dfu_settings.peer_data, (uint8_t *)&s_dfu_settings + DFU_SETTINGS_BOND_DATA_OFFSET_V1, NRF_DFU_PEER_DATA_LEN); + memcpy(&s_dfu_settings.adv_name, (uint8_t *)&s_dfu_settings + DFU_SETTINGS_ADV_NAME_OFFSET_V1, NRF_DFU_ADV_NAME_LEN); + + // Initialize with defaults. + s_dfu_settings.boot_validation_softdevice.type = NO_VALIDATION; + s_dfu_settings.boot_validation_app.type = VALIDATE_CRC; + s_dfu_settings.boot_validation_bootloader.type = NO_VALIDATION; + memcpy(s_dfu_settings.boot_validation_app.bytes, &s_dfu_settings.bank_0.image_crc, sizeof(uint32_t)); + + s_dfu_settings.settings_version = NRF_DFU_SETTINGS_VERSION; + } + + return; +} + +ret_code_t nrf_dfu_settings_init(bool sd_irq_initialized) +{ + NRF_LOG_DEBUG("Calling nrf_dfu_settings_init()..."); + + ret_code_t err_code = nrf_dfu_flash_init(sd_irq_initialized); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_dfu_flash_init() failed with error: %x", err_code); + return NRF_ERROR_INTERNAL; + } + + nrf_dfu_settings_reinit(); + + err_code = nrf_dfu_settings_write_and_backup(NULL); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_dfu_settings_write_and_backup() failed with error: %x", err_code); + return NRF_ERROR_INTERNAL; + } + + return NRF_SUCCESS; +} + + +static bool settings_forbidden_parts_equal_to_backup(uint8_t * p_compare_addr) +{ + nrf_dfu_settings_t temp_settings; + memcpy(&temp_settings, p_compare_addr, sizeof(nrf_dfu_settings_t)); + settings_forbidden_parts_copy_from_backup((uint8_t *)&temp_settings); + return memcmp(&temp_settings, p_compare_addr, sizeof(nrf_dfu_settings_t)) == 0; +} + + +static ret_code_t settings_write(void * p_dst, + void const * p_src, + nrf_dfu_flash_callback_t callback, + nrf_dfu_settings_t * p_dfu_settings_buffer) +{ + ret_code_t err_code; + + if (memcmp(p_dst, p_src, sizeof(nrf_dfu_settings_t)) == 0) + { + NRF_LOG_DEBUG("Destination settings are identical to source, write not needed. Skipping."); + if (callback != NULL) + { + callback(NULL); + } + return NRF_SUCCESS; + } + + if (NRF_DFU_IN_APP && !settings_forbidden_parts_equal_to_backup((uint8_t *)&s_dfu_settings)) + { + NRF_LOG_WARNING("Settings write aborted since it tries writing to forbidden settings."); + return NRF_ERROR_FORBIDDEN; + } + + NRF_LOG_DEBUG("Writing settings..."); + NRF_LOG_DEBUG("Erasing old settings at: 0x%08x", p_dst); + + // Not setting the callback function because ERASE is required before STORE + // Only report completion on successful STORE. + err_code = nrf_dfu_flash_erase((uint32_t)p_dst, 1, NULL); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not erase the settings page!"); + return NRF_ERROR_INTERNAL; + } + + ASSERT(p_dfu_settings_buffer != NULL); + memcpy(p_dfu_settings_buffer, p_src, sizeof(nrf_dfu_settings_t)); + + err_code = nrf_dfu_flash_store((uint32_t)p_dst, + p_dfu_settings_buffer, + sizeof(nrf_dfu_settings_t), + callback); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not write the DFU settings page!"); + return NRF_ERROR_INTERNAL; + } + + return NRF_SUCCESS; +} + + +ret_code_t nrf_dfu_settings_write(nrf_dfu_flash_callback_t callback) +{ + static nrf_dfu_settings_t dfu_settings_buffer; + s_dfu_settings.crc = settings_crc_get(&s_dfu_settings); + s_dfu_settings.boot_validation_crc = boot_validation_crc(&s_dfu_settings); + return settings_write(m_dfu_settings_buffer, + &s_dfu_settings, + callback, + &dfu_settings_buffer); +} + + +void settings_backup(nrf_dfu_flash_callback_t callback, void * p_src) +{ +#if NRF_DFU_IN_APP + NRF_LOG_INFO("Settings backup not available from app."); +#else + static nrf_dfu_settings_t dfu_settings_buffer; + NRF_LOG_INFO("Backing up settings page to address 0x%x.", mp_dfu_settings_backup_buffer); + ASSERT(crc_ok(p_src)); + ret_code_t err_code = settings_write(mp_dfu_settings_backup_buffer, + p_src, + callback, + &dfu_settings_buffer); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not perform backup of bootloader settings! Error: 0x%x", err_code); + } +#endif +} + + +void nrf_dfu_settings_backup(nrf_dfu_flash_callback_t callback) +{ + settings_backup(callback, m_dfu_settings_buffer); +} + + +ret_code_t nrf_dfu_settings_write_and_backup(nrf_dfu_flash_callback_t callback) +{ +#if NRF_DFU_IN_APP + ret_code_t err_code = nrf_dfu_settings_write(callback); +#else + ret_code_t err_code = nrf_dfu_settings_write(NULL); + if (err_code == NRF_SUCCESS) + { + settings_backup(callback, &s_dfu_settings); + } +#endif + return err_code; +} + + +__WEAK ret_code_t nrf_dfu_settings_additional_erase(void) +{ + NRF_LOG_WARNING("No additional data erased"); + return NRF_SUCCESS; +} + + +void nrf_dfu_settings_progress_reset(void) +{ + memset(s_dfu_settings.init_command, 0xFF, INIT_COMMAND_MAX_SIZE); // Remove the last init command + memset(&s_dfu_settings.progress, 0, sizeof(dfu_progress_t)); + s_dfu_settings.write_offset = 0; +} diff --git a/components/libraries/bootloader/dfu/nrf_dfu_settings.h b/components/libraries/bootloader/dfu/nrf_dfu_settings.h new file mode 100644 index 0000000..10f2c82 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_settings.h @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_dfu_settings DFU settings + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_SETTINGS_H__ +#define NRF_DFU_SETTINGS_H__ + +#include +#include "nrf_dfu_types.h" +#include "nrf_dfu_flash.h" +#include "sdk_config.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Global settings. + * + * @note Using this variable is not thread-safe. + * + */ +extern nrf_dfu_settings_t s_dfu_settings; + + +/**@brief Function for writing DFU settings to flash. + * + * @param[in] callback Pointer to a function that is called after completing the write operation. + * + * @retval NRF_SUCCESS If the write process was successfully initiated. + * @retval NRF_ERROR_INTERNAL If a flash error occurred. + */ +ret_code_t nrf_dfu_settings_write(nrf_dfu_flash_callback_t callback); + + +/**@brief Function for backing up the settings. + * + * This function copies the contents of the settings page (in flash) to a separate page (in flash). + * During @ref nrf_dfu_settings_init, the backup is restored if the original is invalid. + * + * @param[in] callback Pointer to a function that is called after completing the write operation. + */ +void nrf_dfu_settings_backup(nrf_dfu_flash_callback_t callback); + + +/**@brief Function for writing DFU settings to flash and to backup. + * + * This function first calls @ref nrf_dfu_settings_write and then @ref nrf_dfu_settings_backup. + * + * @param[in] callback Pointer to a function that is called after completing the write and backup operation. + * + * @retval NRF_SUCCESS If the write process was successfully initiated. + * @retval NRF_ERROR_INTERNAL If a flash error occurred during the first write. + */ +ret_code_t nrf_dfu_settings_write_and_backup(nrf_dfu_flash_callback_t callback); + + +/**@brief Function for initializing the DFU settings structure. + * + * Initializes the RAM structure from the flash contents. + * This function is called as part of @ref nrf_dfu_settings_init. + * + * @retval NRF_SUCCESS If the initialization was successful. + * @retval NRF_ERROR_INTERNAL If a flash error occurred. + */ +void nrf_dfu_settings_reinit(void); + + +/**@brief Function for initializing the DFU settings module. + * + * @retval NRF_SUCCESS If the initialization was successful. + * @retval NRF_ERROR_INTERNAL If a flash error occurred. + */ +ret_code_t nrf_dfu_settings_init(bool sd_irq_initialized); + + +#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE +/** @brief Function for storing peer data received through an SVCI call in DFU settings. + * + * @note The content of the type can be verified by a CRC value stored inside the struct + * If the CRC value is 0xFFFFFFFF, it means that no data is set. + * + * @note The storage operation is an asynchronous progress. Success will be notified + * through system events raised by the SoftDevice. + * + * @param[in] p_data Peer data to be stored in flash. + * + * @retval NRF_SUCCESS Asynchronous operation was successfully started. + * @retval NRF_ERROR_NULL p_data was NULL. + * @retval Any other error code reported by SoftDevice API calls. + */ +ret_code_t nrf_dfu_settings_peer_data_write(nrf_dfu_peer_data_t * p_data); + + +/** @brief Function for copying peer data from DFU settings to RAM. + * + * @param[in,out] p_data Structure to copy peer data to. + * + * @retval NRF_SUCCESS Peer data was successfully copied. + * @retval NRF_ERROR_NULL p_data was NULL. + */ +ret_code_t nrf_dfu_settings_peer_data_copy(nrf_dfu_peer_data_t * p_data); + + +/** @brief Function for validating peer data in DFU settings. + * + * @retval True if peer data is validated by CRC, false if not. + */ +bool nrf_dfu_settings_peer_data_is_valid(void); + + +/** @brief Function for storing an advertisement name received through an SVCI call in DFU settings. + * + * @note The content of the type is verifyable by a CRC-value stored inside the struct. + * + * @note The storage operation is an asynchronous progress. Success will be notified + * through system events raised by the SoftDevice. + * + * @param[in] p_adv_name Structure holding information about the new advertisement name. + * + * @retval NRF_SUCCESS Asynchronous operation was successfully started. + * @retval NRF_ERROR_NULL p_adv_name was NULL. + * @retval Any other error code reported by SoftDevice API calls. + */ +ret_code_t nrf_dfu_settings_adv_name_write(nrf_dfu_adv_name_t * p_adv_name); + + +/** @brief Function for copying the advertisement name from DFU settings to RAM. + * + * @param[in,out] p_adv_name Structure to copy the new advertisement name to. + * + * @retval NRF_SUCCESS Advertisement name was successfully copied. + * @retval NRF_ERROR_NULL p_adv_name was NULL. + */ +ret_code_t nrf_dfu_settings_adv_name_copy(nrf_dfu_adv_name_t * p_adv_name); + + +/** @brief Function for validating advertisement data in DFU settings. + * + * @retval True if advertisement name is validated by CRC, false if not. + */ +bool nrf_dfu_settings_adv_name_is_valid(void); + +#endif // NRF_DFU_TRANSPORT_BLE + +/** @brief Function for erasing additional data in DFU settings. + * + * @note Erasing additional data in DFU settings is only possible + * if nrf_dfu_flash is initialized to not use SoftDevice calls. + * + * @retval NRF_SUCCESS Additional data was successfully erased. + * @retval Any other error code reported by nrf_dfu_flash + */ +ret_code_t nrf_dfu_settings_additional_erase(void); + +/** @brief Function for resetting both init command and DFU transfer progress inside settings structure. + * + * @note This function does not perform flash operation. + * In order to save the reset state, please use @ref nrf_dfu_settings_write function. + */ +void nrf_dfu_settings_progress_reset(void); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_SETTINGS_H__ + +/**@} */ diff --git a/components/libraries/bootloader/dfu/nrf_dfu_settings_svci.c b/components/libraries/bootloader/dfu/nrf_dfu_settings_svci.c new file mode 100644 index 0000000..f16f0b4 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_settings_svci.c @@ -0,0 +1,185 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include "app_error.h" +#include "sdk_macros.h" +#include "nrf_dfu_settings.h" +#include "nrf_nvmc.h" +#include "crc32.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_settings_svci +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define DFU_SETTINGS_PEER_DATA_OFFSET offsetof(nrf_dfu_settings_t, peer_data) //crc = crc32_compute((uint8_t*)p_data + 4, sizeof(nrf_dfu_peer_data_t) - 4, NULL); + + // Using SoftDevice call since this function cannot use static memory. + ret_val = sd_flash_write(p_peer_data_settings, + (uint32_t*)p_data, + sizeof(nrf_dfu_peer_data_t)/4); + + return ret_val; +} + + +ret_code_t nrf_dfu_settings_peer_data_copy(nrf_dfu_peer_data_t * p_data) +{ + VERIFY_PARAM_NOT_NULL(p_data); + + memcpy(p_data, &m_dfu_settings_buffer[DFU_SETTINGS_PEER_DATA_OFFSET], sizeof(nrf_dfu_peer_data_t)); + + return NRF_SUCCESS; +} + + +bool nrf_dfu_settings_peer_data_is_valid(void) +{ + nrf_dfu_peer_data_t * p_peer_data = + (nrf_dfu_peer_data_t*) &m_dfu_settings_buffer[DFU_SETTINGS_PEER_DATA_OFFSET]; + + // Calculate the CRC for the structure excluding the CRC value itself. + uint32_t crc = crc32_compute((uint8_t*)p_peer_data + 4, sizeof(nrf_dfu_peer_data_t) - 4, NULL); + + return (p_peer_data->crc == crc); +} + +#else // not NRF_DFU_BLE_REQUIRES_BONDS + +ret_code_t nrf_dfu_settings_adv_name_write(nrf_dfu_adv_name_t * p_adv_name) +{ + uint32_t ret_val; + + uint32_t * p_adv_name_settings = + (uint32_t*) &m_dfu_settings_buffer[DFU_SETTINGS_ADV_NAME_OFFSET]; + + uint32_t crc = (uint32_t)*p_adv_name_settings; + + VERIFY_PARAM_NOT_NULL(p_adv_name); + + if (crc != 0xFFFFFFFF) + { + // Already written to, must be cleared out. + // Reset required + return NRF_ERROR_INVALID_STATE; + } + + // Calculate the CRC for the structure excluding the CRC value itself. + p_adv_name->crc = crc32_compute((uint8_t *)p_adv_name + 4, sizeof(nrf_dfu_adv_name_t) - 4, NULL); + + // Using SoftDevice call since this function cannot use static memory. + ret_val = sd_flash_write(p_adv_name_settings, + (uint32_t*) p_adv_name, + sizeof(nrf_dfu_adv_name_t)/4); + return ret_val; +} + + +ret_code_t nrf_dfu_settings_adv_name_copy(nrf_dfu_adv_name_t * p_adv_name) +{ + VERIFY_PARAM_NOT_NULL(p_adv_name); + memcpy(p_adv_name, &m_dfu_settings_buffer[DFU_SETTINGS_ADV_NAME_OFFSET], sizeof(nrf_dfu_adv_name_t)); + + return NRF_SUCCESS; +} + + +bool nrf_dfu_settings_adv_name_is_valid(void) +{ + nrf_dfu_adv_name_t * p_adv_name = + (nrf_dfu_adv_name_t*)&m_dfu_settings_buffer[DFU_SETTINGS_ADV_NAME_OFFSET]; + + // Calculate the CRC for the structure excluding the CRC value itself. + uint32_t crc = crc32_compute((uint8_t*)p_adv_name + 4, sizeof(nrf_dfu_adv_name_t) - 4, NULL); + + return (p_adv_name->crc == crc); +} + +#endif + + +//lint -save -e(14) +ret_code_t nrf_dfu_settings_additional_erase(void) +{ + ret_code_t ret_code = NRF_SUCCESS; + + // Check CRC for both types. + if ( (s_dfu_settings.peer_data.crc != 0xFFFFFFFF) + || (s_dfu_settings.adv_name.crc != 0xFFFFFFFF)) + { + NRF_LOG_DEBUG("Erasing settings page additional data."); + + // Erasing and resetting the settings page without the peer data/adv data + nrf_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS); + nrf_nvmc_write_words(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t const *)&s_dfu_settings, DFU_SETTINGS_PEER_DATA_OFFSET / 4); + } + + return ret_code; +} +//lint -restore + diff --git a/components/libraries/bootloader/dfu/nrf_dfu_svci.c b/components/libraries/bootloader/dfu/nrf_dfu_svci.c new file mode 100644 index 0000000..2821ec3 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_svci.c @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include "nrf_log.h" +#include "nrf_sdm.h" +#include "app_util.h" + +#define APP_START_ADDR CODE_START + + +uint32_t nrf_dfu_svci_vector_table_set(void) +{ + uint32_t err_code; + uint32_t bootloader_addr = BOOTLOADER_ADDRESS; + + if (bootloader_addr != 0xFFFFFFFF) + { + NRF_LOG_INFO("Setting vector table to bootloader: 0x%08x", bootloader_addr); + err_code = sd_softdevice_vector_table_base_set(bootloader_addr); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed running sd_softdevice_vector_table_base_set"); + return err_code; + } + + return NRF_SUCCESS; + } + + NRF_LOG_ERROR("No bootloader was found"); + return NRF_ERROR_NO_MEM; +} + + +uint32_t nrf_dfu_svci_vector_table_unset(void) +{ + uint32_t err_code; + + NRF_LOG_INFO("Setting vector table to main app: 0x%08x", APP_START_ADDR); + err_code = sd_softdevice_vector_table_base_set(APP_START_ADDR); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed running sd_softdevice_vector_table_base_set"); + return err_code; + } + + return NRF_SUCCESS; +} + diff --git a/components/libraries/bootloader/dfu/nrf_dfu_svci_handler.c b/components/libraries/bootloader/dfu/nrf_dfu_svci_handler.c new file mode 100644 index 0000000..bb1768a --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_svci_handler.c @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include "nrf_svci_async_handler.h" +#include "app_error.h" +#include "nrf_nvmc.h" +#include "nrf_dfu_types.h" +#include "nrf_dfu_ble_svci_bond_sharing.h" +#include "nrf_log.h" +#include "nrf_dfu_settings.h" +#include "sdk_config.h" + + +#if (NRF_DFU_TRANSPORT_BLE && NRF_DFU_BLE_REQUIRES_BONDS) + + +NRF_SVCI_ASYNC_HANDLER_CREATE(NRF_DFU_SVCI_SET_PEER_DATA, + nrf_dfu_set_peer_data, nrf_dfu_peer_data_t, nrf_dfu_peer_data_state_t); + + +static uint32_t nrf_dfu_set_peer_data_handler(nrf_dfu_set_peer_data_svci_async_t * p_async) +{ + VERIFY_PARAM_NOT_NULL(p_async); + + p_async->async_func = nrf_dfu_set_peer_data_on_call; + p_async->sys_evt_handler = nrf_dfu_set_peer_data_on_sys_evt; + p_async->state = DFU_PEER_DATA_STATE_INITIALIZED; + + return NRF_SUCCESS; +} + + +static uint32_t nrf_dfu_set_peer_data_on_call(nrf_dfu_peer_data_t * p_data, + nrf_dfu_peer_data_state_t * p_state) +{ + uint32_t ret_val = NRF_ERROR_BUSY; + + VERIFY_PARAM_NOT_NULL(p_state); + + switch (*p_state) + { + case DFU_PEER_DATA_STATE_INVALID: + return NRF_ERROR_INVALID_STATE; + + case DFU_PEER_DATA_STATE_INITIALIZED: + ret_val = nrf_dfu_settings_peer_data_write(p_data); + if (ret_val == NRF_SUCCESS) + { + *p_state = DFU_PEER_DATA_STATE_WRITE_REQUESTED; + } + break; + + case DFU_PEER_DATA_STATE_WRITE_REQUESTED: + return NRF_ERROR_BUSY; + + case DFU_PEER_DATA_STATE_WRITE_FINISHED: + return NRF_ERROR_INVALID_STATE; + + case DFU_PEER_DATA_STATE_WRITE_FAILED: + return NRF_ERROR_INVALID_STATE; + } + + return ret_val; +} + + +static uint32_t nrf_dfu_set_peer_data_on_sys_evt(uint32_t sys_event, nrf_dfu_peer_data_state_t * p_state) +{ + uint32_t ret_val = NRF_ERROR_INVALID_STATE; + + VERIFY_PARAM_NOT_NULL(p_state); + + if (*p_state == DFU_PEER_DATA_STATE_WRITE_REQUESTED) + { + switch (sys_event) + { + case NRF_EVT_FLASH_OPERATION_ERROR: + return NRF_ERROR_BUSY; + + case NRF_EVT_FLASH_OPERATION_SUCCESS: + ret_val = NRF_SUCCESS; + (*p_state) = DFU_PEER_DATA_STATE_WRITE_FINISHED; + break; + + default: + // Event not intended for us + break; + } + } + + return ret_val; +} + +#elif (NRF_DFU_TRANSPORT_BLE && !NRF_DFU_BLE_REQUIRES_BONDS) + + +NRF_SVCI_ASYNC_HANDLER_CREATE(NRF_DFU_SVCI_SET_ADV_NAME, + nrf_dfu_set_adv_name, nrf_dfu_adv_name_t, nrf_dfu_set_adv_name_state_t); + + +static uint32_t nrf_dfu_set_adv_name_handler(nrf_dfu_set_adv_name_svci_async_t * p_async) +{ + VERIFY_PARAM_NOT_NULL(p_async); + + p_async->async_func = nrf_dfu_set_adv_name_on_call; + p_async->sys_evt_handler = nrf_dfu_set_adv_name_on_sys_evt; + p_async->state = DFU_ADV_NAME_STATE_INITIALIZED; + + return NRF_SUCCESS; +} + + +static uint32_t nrf_dfu_set_adv_name_on_call(nrf_dfu_adv_name_t * p_adv_name, + nrf_dfu_set_adv_name_state_t * p_state) +{ + uint32_t ret_val = NRF_ERROR_BUSY; + + VERIFY_PARAM_NOT_NULL(p_state); + + switch (*p_state) + { + case DFU_ADV_NAME_STATE_INVALID: + return NRF_ERROR_INVALID_STATE; + + case DFU_ADV_NAME_STATE_INITIALIZED: + ret_val = nrf_dfu_settings_adv_name_write(p_adv_name); + if (ret_val == NRF_SUCCESS) + { + *p_state = DFU_ADV_NAME_STATE_WRITE_REQUESTED; + } + break; + + case DFU_ADV_NAME_STATE_WRITE_REQUESTED: + return NRF_ERROR_BUSY; + + case DFU_ADV_NAME_STATE_WRITE_FINISHED: + return NRF_ERROR_INVALID_STATE; + + case DFU_ADV_NAME_STATE_WRITE_FAILED: + return NRF_ERROR_INVALID_STATE; + } + + return ret_val; +} + + +static uint32_t nrf_dfu_set_adv_name_on_sys_evt(uint32_t sys_event, nrf_dfu_set_adv_name_state_t * p_state) +{ + uint32_t ret_val = NRF_ERROR_INVALID_STATE; + + VERIFY_PARAM_NOT_NULL(p_state); + + if (*p_state == DFU_ADV_NAME_STATE_WRITE_REQUESTED) + { + switch (sys_event) + { + case NRF_EVT_FLASH_OPERATION_ERROR: + return NRF_ERROR_BUSY; + + case NRF_EVT_FLASH_OPERATION_SUCCESS: + ret_val = NRF_SUCCESS; + (*p_state) = DFU_ADV_NAME_STATE_WRITE_FINISHED; + break; + + default: + // Event not intended for us + break; + } + } + + return ret_val; +} + +#endif // NRF_DFU_TRANSPORT_BLE && !NRF_DFU_BLE_REQUIRES_BONDS diff --git a/components/libraries/bootloader/dfu/nrf_dfu_transport.c b/components/libraries/bootloader/dfu/nrf_dfu_transport.c new file mode 100644 index 0000000..cb6e9a4 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_transport.c @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu_transport.h" +#include "nrf_log.h" + + +#define DFU_TRANS_SECTION_ITEM_GET(i) NRF_SECTION_ITEM_GET(dfu_trans, nrf_dfu_transport_t, (i)) +#define DFU_TRANS_SECTION_ITEM_COUNT NRF_SECTION_ITEM_COUNT(dfu_trans, nrf_dfu_transport_t) + +NRF_SECTION_DEF(dfu_trans, const nrf_dfu_transport_t); + + +uint32_t nrf_dfu_transports_init(nrf_dfu_observer_t observer) +{ + uint32_t const num_transports = DFU_TRANS_SECTION_ITEM_COUNT; + uint32_t ret_val = NRF_SUCCESS; + + NRF_LOG_DEBUG("Initializing transports (found: %d)", num_transports); + + for (uint32_t i = 0; i < num_transports; i++) + { + nrf_dfu_transport_t * const trans = DFU_TRANS_SECTION_ITEM_GET(i); + ret_val = trans->init_func(observer); + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_DEBUG("Failed to initialize transport %d, error %d", i, ret_val); + break; + } + } + + return ret_val; +} + + +uint32_t nrf_dfu_transports_close(nrf_dfu_transport_t const * p_exception) +{ + uint32_t const num_transports = DFU_TRANS_SECTION_ITEM_COUNT; + uint32_t ret_val = NRF_SUCCESS; + + NRF_LOG_DEBUG("Shutting down transports (found: %d)", num_transports); + + for (uint32_t i = 0; i < num_transports; i++) + { + nrf_dfu_transport_t * const trans = DFU_TRANS_SECTION_ITEM_GET(i); + ret_val = trans->close_func(p_exception); + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_DEBUG("Failed to shutdown transport %d, error %d", i, ret_val); + break; + } + } + + return ret_val; +} diff --git a/components/libraries/bootloader/dfu/nrf_dfu_transport.h b/components/libraries/bootloader/dfu/nrf_dfu_transport.h new file mode 100644 index 0000000..e10723e --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_transport.h @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_transport DFU transport + * @{ + * @ingroup nrf_dfu + * @brief Generic Device Firmware Update (DFU) transport interface. + * + * @details The DFU transport module defines a generic interface that must + * be implemented for each transport layer. + */ + +#ifndef NRF_DFU_TRANSPORT_H__ +#define NRF_DFU_TRANSPORT_H__ + +#include +#include "nrf_section.h" +#include "nrf_dfu_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Forward declaration of nrf_dfu_transport_t */ +typedef struct nrf_dfu_transport_s nrf_dfu_transport_t; + +/** @brief Function type for initializing a DFU transport. + * + * @details This function initializes a DFU transport. The implementation + * of the function must initialize DFU mode and stay in service + * until either the device is reset or the DFU operation is finalized. + * When the DFU transport receives requests, it should call @ref nrf_dfu_req_handler_on_req for handling the requests. + * + * @param observer Callback function for receiving DFU transport notifications. + * + * @retval NRF_SUCCESS If initialization was successful for the transport. Any other return code indicates that the DFU transport could not be initialized. + */ +typedef uint32_t (*nrf_dfu_init_fn_t)(nrf_dfu_observer_t observer); + + +/** @brief Function type for closing down a DFU transport. + * + * @details This function closes down a DFU transport in a gentle way. + * + * @param[in] p_exception If exception matches current transport closing should be omitted. + * + * @retval NRF_SUCCESS If closing was successful for the transport. Any other return code indicates that the DFU transport could not be closed closed down. + */ +typedef uint32_t (*nrf_dfu_close_fn_t)(nrf_dfu_transport_t const * p_exception); + + + +/** @brief DFU transport registration. + * + * @details Every DFU transport must provide a registration of the initialization function. + */ +struct nrf_dfu_transport_s +{ + nrf_dfu_init_fn_t init_func; /**< Registration of the init function to run to initialize a DFU transport. */ + nrf_dfu_close_fn_t close_func; /**< Registration of the close function to close down a DFU transport. */ +}; + + +/** @brief Function for initializing all the registered DFU transports. + * + * @retval NRF_SUCCESS If all DFU transport were initialized successfully. + * Any other error code indicates that at least one DFU + * transport could not be initialized. + */ +uint32_t nrf_dfu_transports_init(nrf_dfu_observer_t observer); + +/** @brief Function for closing down all (with optional exception) the registered DFU transports. + * + * @param[in] p_exception Transport which should not be closed. NULL if all transports should be closed. + * @retval NRF_SUCCESS If all DFU transport were closed down successfully. + * Any other error code indicates that at least one DFU + * transport could not be closed down. + */ +uint32_t nrf_dfu_transports_close(nrf_dfu_transport_t const * p_exception); + + +/** @brief Macro for registering a DFU transport by using section variables. + * + * @details This macro places a variable in a section named "dfu_trans", which + * is initialized by @ref nrf_dfu_transports_init. + */ +#define DFU_TRANSPORT_REGISTER(trans_var) NRF_SECTION_ITEM_REGISTER(dfu_trans, trans_var) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_TRANSPORT_H__ + +/** @} */ diff --git a/components/libraries/bootloader/dfu/nrf_dfu_trigger_usb.c b/components/libraries/bootloader/dfu/nrf_dfu_trigger_usb.c new file mode 100644 index 0000000..90b6929 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_trigger_usb.c @@ -0,0 +1,244 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu_trigger_usb.h" +#include "app_usbd.h" +#include "app_usbd_nrf_dfu_trigger.h" +#include "nrf_drv_clock.h" +#include "nrf_log_ctrl.h" +#include "nrf_gpio.h" +#include "boards.h" +#include "app_util.h" +#include "app_usbd_serial_num.h" +#define NRF_LOG_MODULE_NAME nrf_dfu_trigger_usb +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#ifndef BSP_SELF_PINRESET_PIN +#error "This module is intended to be used with boards that have the GP pin shortened with the RESET pin." +#endif + +/** + * @brief Enable power USB detection. + * + * Configure if the example supports USB port connection. + */ +#ifndef USBD_POWER_DETECTION +#define USBD_POWER_DETECTION true +#endif + +#define DFU_FLASH_PAGE_SIZE (NRF_FICR->CODEPAGESIZE) +#define DFU_FLASH_PAGE_COUNT (NRF_FICR->CODESIZE) + +// Semantic versioning string. +#define VERSION_STRING STRINGIFY(APP_VERSION_MAJOR) "." STRINGIFY(APP_VERSION_MINOR) "." STRINGIFY(APP_VERSION_PATCH) APP_VERSION_PRERELEASE APP_VERSION_METADATA + +static uint8_t m_version_string[] = APP_NAME " " VERSION_STRING; ///< Human-readable version string. +static app_usbd_nrf_dfu_trigger_nordic_info_t m_dfu_info; ///< Struct with various information about the current firmware. + +static void dfu_trigger_evt_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_nrf_dfu_trigger_user_event_t event) +{ + UNUSED_PARAMETER(p_inst); + + switch (event) + { + case APP_USBD_NRF_DFU_TRIGGER_USER_EVT_DETACH: + NRF_LOG_INFO("DFU Detach request received. Triggering a pin reset."); + NRF_LOG_FINAL_FLUSH(); + nrf_gpio_cfg_output(BSP_SELF_PINRESET_PIN); + nrf_gpio_pin_clear(BSP_SELF_PINRESET_PIN); + break; + default: + break; + } +} + + +APP_USBD_NRF_DFU_TRIGGER_GLOBAL_DEF(m_app_dfu, + NRF_DFU_TRIGGER_USB_INTERFACE_NUM, + &m_dfu_info, + m_version_string, + dfu_trigger_evt_handler); + + +static void usbd_user_evt_handler(app_usbd_event_type_t event) +{ + switch (event) + { + case APP_USBD_EVT_DRV_SUSPEND: + break; + case APP_USBD_EVT_DRV_RESUME: + break; + case APP_USBD_EVT_STARTED: + break; + case APP_USBD_EVT_STOPPED: + app_usbd_disable(); + break; + case APP_USBD_EVT_POWER_DETECTED: + NRF_LOG_INFO("USB power detected"); + + if (!nrf_drv_usbd_is_enabled()) + { + app_usbd_enable(); + } + break; + case APP_USBD_EVT_POWER_REMOVED: + NRF_LOG_INFO("USB power removed"); + app_usbd_stop(); + break; + case APP_USBD_EVT_POWER_READY: + NRF_LOG_INFO("USB ready"); + app_usbd_start(); + break; + default: + break; + } +} + + +static void strings_create(void) +{ + uint8_t prev_char = 'a'; // Arbitrary valid char, not '-'. + + // Remove characters that are not supported in semantic version strings. + for (size_t i = strlen(APP_NAME) + 1; i < strlen((char*)m_version_string); i++) + { + if (((m_version_string[i] >= 'a') && (m_version_string[i] <= 'z')) + || ((m_version_string[i] >= 'A') && (m_version_string[i] <= 'Z')) + || ((m_version_string[i] >= '0') && (m_version_string[i] <= '9')) + || (m_version_string[i] == '+') + || (m_version_string[i] == '.') + || (m_version_string[i] == '-')) + { + // Valid semantic version character. + } + else if (prev_char == '-') + { + m_version_string[i] = '0'; + } + else + { + m_version_string[i] = '-'; + } + + prev_char = m_version_string[i]; + } + +#if !NRF_DFU_TRIGGER_USB_USB_SHARED + app_usbd_serial_num_generate(); +#endif +} + +#if !(APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) +static void usbd_evt_handler(app_usbd_internal_evt_t const * const p_event) +{ + app_usbd_event_execute(p_event); +} +#endif + +ret_code_t nrf_dfu_trigger_usb_init(void) +{ + ret_code_t ret; + static bool initialized = false; + + if (initialized) + { + return NRF_SUCCESS; + } + + m_dfu_info.wAddress = CODE_START; + m_dfu_info.wFirmwareSize = CODE_SIZE; + m_dfu_info.wVersionMajor = APP_VERSION_MAJOR; + m_dfu_info.wVersionMinor = APP_VERSION_MINOR; + m_dfu_info.wFirmwareID = APP_ID; + m_dfu_info.wFlashPageSize = DFU_FLASH_PAGE_SIZE; + m_dfu_info.wFlashSize = m_dfu_info.wFlashPageSize * DFU_FLASH_PAGE_COUNT; + + strings_create(); + + if (!NRF_DFU_TRIGGER_USB_USB_SHARED) + { + static const app_usbd_config_t usbd_config = { + +#if !(APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) + .ev_handler = usbd_evt_handler, +#endif + .ev_state_proc = usbd_user_evt_handler + }; + + ret = nrf_drv_clock_init(); + if ((ret != NRF_SUCCESS) && (ret != NRF_ERROR_MODULE_ALREADY_INITIALIZED)) + { + return ret; + } + + ret = app_usbd_init(&usbd_config); + if (ret != NRF_SUCCESS) + { + return ret; + } + } + + app_usbd_class_inst_t const * class_dfu = app_usbd_nrf_dfu_trigger_class_inst_get(&m_app_dfu); + ret = app_usbd_class_append(class_dfu); + + if (!NRF_DFU_TRIGGER_USB_USB_SHARED) + { + if (USBD_POWER_DETECTION) + { + ret = app_usbd_power_events_enable(); + APP_ERROR_CHECK(ret); + } + else + { + NRF_LOG_INFO("No USB power detection enabled\r\nStarting USB now"); + + app_usbd_enable(); + app_usbd_start(); + } + } + + if (ret == NRF_SUCCESS) + { + initialized = true; + } + + return ret; +} diff --git a/components/libraries/bootloader/dfu/nrf_dfu_trigger_usb.h b/components/libraries/bootloader/dfu/nrf_dfu_trigger_usb.h new file mode 100644 index 0000000..0152636 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_trigger_usb.h @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_DFU_TRIGGER_USB_H +#define NRF_DFU_TRIGGER_USB_H + +#include "sdk_errors.h" + +/** + * @defgroup nrf_dfu_trigger_usb USB DFU trigger library + * @ingroup app_common + * + * @brief @tagAPI52840 USB DFU trigger library is used to enter the bootloader and read the firmware version. + * + * @details See @ref lib_dfu_trigger_usb for additional documentation. + * @{ + */ + +/** + * @brief Function for initializing the USB DFU trigger library. + * + * @note If the USB is also used for other purposes, then this function must be called after USB is + * initialized but before it is enabled. In this case, the configuration flag @ref + * NRF_DFU_TRIGGER_USB_USB_SHARED must be set to 1. + * + * @note Calling this again after the first success has no effect and returns @ref NRF_SUCCESS. + * + * @note If @ref APP_USBD_CONFIG_EVENT_QUEUE_ENABLE is on (1), USB events must be handled manually. + * See @ref app_usbd_event_queue_process. + * + * @retval NRF_SUCCESS On successful initialization. + * @return An error code on failure, for example if called at a wrong time. + */ +ret_code_t nrf_dfu_trigger_usb_init(void); + +/** @} */ + +#endif //NRF_DFU_TRIGGER_USB_H diff --git a/components/libraries/bootloader/dfu/nrf_dfu_types.h b/components/libraries/bootloader/dfu/nrf_dfu_types.h new file mode 100644 index 0000000..fd15f55 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_types.h @@ -0,0 +1,342 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_types DFU types + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_TYPES_H__ +#define NRF_DFU_TYPES_H__ + +#include +#include + +#include "sdk_common.h" +#include "nrf.h" +#include "nrf_mbr.h" +#include "app_util_platform.h" +#include "sdk_config.h" + +#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE +#include "ble_gap.h" +#define SYSTEM_SERVICE_ATT_SIZE 8 /**< Size of the system service attribute length including CRC-16 at the end. */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +#define INIT_COMMAND_MAX_SIZE 512 /**< Maximum size of the init command stored in dfu_settings. */ +#define INIT_COMMAND_MAX_SIZE_v1 256 /**< Maximum size of the init command in settings version 1. */ + +/** @brief Size of a flash page. This value is used for calculating the size of the reserved + * flash space in the bootloader region. + */ +#if defined(NRF51) + #define CODE_PAGE_SIZE (PAGE_SIZE_IN_WORDS * sizeof(uint32_t)) +#elif defined(NRF52_SERIES) + #define CODE_PAGE_SIZE (MBR_PAGE_SIZE_IN_WORDS * sizeof(uint32_t)) +#else + #error "Architecture not set." +#endif + +/** @brief Maximum size of a data object.*/ +#if defined(NRF51) + #define DATA_OBJECT_MAX_SIZE (CODE_PAGE_SIZE * 4) +#elif defined(NRF52_SERIES) || defined (__SDK_DOXYGEN__) + #define DATA_OBJECT_MAX_SIZE (CODE_PAGE_SIZE) +#else + #error "Architecture not set." +#endif + +/** @brief Page location of the bootloader settings address. + */ +#if defined (NRF51) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0003FC00UL) +#elif defined( NRF52810_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0002F000UL) +#elif defined( NRF52811_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0002F000UL) +#elif defined( NRF52820_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0003F000UL) +#elif defined( NRF52832_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0007F000UL) +#elif defined( NRF52833_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0007F000UL) +#elif defined(NRF52840_XXAA) + #define BOOTLOADER_SETTINGS_ADDRESS (0x000FF000UL) +#else + #error No valid target set for BOOTLOADER_SETTINGS_ADDRESS. +#endif + +#define BOOTLOADER_SETTINGS_PAGE_SIZE (CODE_PAGE_SIZE) +#define NRF_MBR_PARAMS_PAGE_SIZE (CODE_PAGE_SIZE) + +/** @brief Page location of the MBR parameters page address. + */ +#if defined(NRF52840_XXAA) || defined(NRF52840_XXAA_ENGA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x000FE000UL) +#elif defined(NRF52832_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0007E000UL) +#elif defined(NRF52833_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0007E000UL) +#elif defined(NRF52810_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0002E000UL) +#elif defined(NRF52811_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0002E000UL) +#elif defined(NRF52820_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0003E000UL) +#endif + +#define BOOTLOADER_SETTINGS_BACKUP_ADDRESS NRF_MBR_PARAMS_PAGE_ADDRESS + + +#ifndef NRF_DFU_APP_DATA_AREA_SIZE +#define NRF_DFU_APP_DATA_AREA_SIZE (CODE_PAGE_SIZE * 3) +#endif + +STATIC_ASSERT((NRF_DFU_APP_DATA_AREA_SIZE % CODE_PAGE_SIZE) == 0, "NRF_DFU_APP_DATA_AREA_SIZE must be a multiple of the flash page size."); + +#define DFU_APP_DATA_RESERVED NRF_DFU_APP_DATA_AREA_SIZE // For backward compatibility with 15.0.0. + +/** @brief Total size of the region between the SoftDevice and the bootloader. + */ +#define DFU_REGION_END(bootloader_start_addr) ((bootloader_start_addr) - (NRF_DFU_APP_DATA_AREA_SIZE)) + +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) +#define DFU_REGION_START (nrf_dfu_bank0_start_addr()) +#else +#define DFU_REGION_START (MBR_SIZE) +#endif + +#define DFU_REGION_TOTAL_SIZE ((DFU_REGION_END) - (DFU_REGION_START)) + +#define NRF_DFU_CURRENT_BANK_0 0x00 +#define NRF_DFU_CURRENT_BANK_1 0x01 + +#define NRF_DFU_BANK_LAYOUT_DUAL 0x00 +#define NRF_DFU_BANK_LAYOUT_SINGLE 0x01 + +/** @brief DFU bank state codes. + * + * @details The DFU bank state indicates the content of a bank: + * A valid image of a certain type or an invalid image. + */ + +#define NRF_DFU_BANK_INVALID 0x00 /**< Invalid image. */ +#define NRF_DFU_BANK_VALID_APP 0x01 /**< Valid application. */ +#define NRF_DFU_BANK_VALID_SD 0xA5 /**< Valid SoftDevice. */ +#define NRF_DFU_BANK_VALID_BL 0xAA /**< Valid bootloader. */ +#define NRF_DFU_BANK_VALID_SD_BL 0xAC /**< Valid SoftDevice and bootloader. */ +#define NRF_DFU_BANK_VALID_EXT_APP 0xB1 /**< Valid application designated for a remote node. */ + +/** @brief Description of a single bank. */ +#pragma pack(4) +typedef struct +{ + uint32_t image_size; /**< Size of the image in the bank. */ + uint32_t image_crc; /**< CRC of the image. If set to 0, the CRC is ignored. */ + uint32_t bank_code; /**< Identifier code for the bank. */ +} nrf_dfu_bank_t; + +/**@brief DFU progress. + * + * Be aware of the difference between objects and firmware images. A firmware image consists of multiple objects, each of a maximum size @ref DATA_OBJECT_MAX_SIZE. + * + * @note The union inside this struct is cleared when CREATE_OBJECT of command type is executed, and when there is a valid post-validation. + * In DFU activation (after reset) the @ref dfu_progress_t::update_start_address will be used in case of a SD/SD+BL update. + */ +ANON_UNIONS_ENABLE; +typedef struct +{ + uint32_t command_size; /**< The size of the current init command stored in the DFU settings. */ + uint32_t command_offset; /**< The offset of the currently received init command data. The offset will increase as the init command is received. */ + uint32_t command_crc; /**< The calculated CRC of the init command (calculated after the transfer is completed). */ + uint32_t data_object_size; /**< The size of the last object created. Note that this size is not the size of the whole firmware image.*/ + union + { + struct + { + uint32_t firmware_image_crc; /**< CRC value of the current firmware (continuously calculated as data is received). */ + uint32_t firmware_image_crc_last; /**< The CRC of the last executed object. */ + uint32_t firmware_image_offset; /**< The offset of the current firmware image being transferred. Note that this offset is the offset in the entire firmware image and not only the current object. */ + uint32_t firmware_image_offset_last;/**< The offset of the last executed object from the start of the firmware image. */ + }; + struct + { + uint32_t update_start_address; /**< Value indicating the start address of the new firmware (before copy). It's always used, but it's most important for an SD/SD+BL update where the SD changes size or if the DFU process had a power loss when updating a SD with changed size. */ + }; + }; +} dfu_progress_t; +ANON_UNIONS_DISABLE; + +/** @brief Event types in the bootloader and DFU process. */ +typedef enum +{ + NRF_DFU_EVT_DFU_INITIALIZED, /**< Starting DFU. */ + NRF_DFU_EVT_TRANSPORT_ACTIVATED, /**< Transport activated (e.g. BLE connected, USB plugged in). */ + NRF_DFU_EVT_TRANSPORT_DEACTIVATED, /**< Transport deactivated (e.g. BLE disconnected, USB plugged out). */ + NRF_DFU_EVT_DFU_STARTED, /**< DFU process started. */ + NRF_DFU_EVT_OBJECT_RECEIVED, /**< A DFU data object has been received. */ + NRF_DFU_EVT_DFU_FAILED, /**< DFU process has failed, been interrupted, or hung. */ + NRF_DFU_EVT_DFU_COMPLETED, /**< DFU process completed. */ + NRF_DFU_EVT_DFU_ABORTED, /**< DFU process aborted. */ +} nrf_dfu_evt_type_t; + +/** + * @brief Function for notifying DFU state. + */ +typedef void (*nrf_dfu_observer_t)(nrf_dfu_evt_type_t notification); + +#define NRF_DFU_PEER_DATA_LEN 64 /**< The length in bytes of nrf_dfu_peer_data_t expected by tools manipulating the settings page. Do not change without changing the settings page version. */ +#define NRF_DFU_ADV_NAME_LEN 28 /**< The length in bytes of nrf_dfu_adv_name_t expected by tools manipulating the settings page. Do not change without changing the settings page version. */ + +#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE + +typedef struct +{ + uint32_t crc; /**< CRC of the rest of the parameters in this struct. */ + ble_gap_id_key_t ble_id; /**< BLE GAP identity key of the device that initiated the DFU process. */ + ble_gap_enc_key_t enc_key; /**< Encryption key structure containing encrypted diversifier and LTK for reestablishing the bond. */ + uint8_t sys_serv_attr[SYSTEM_SERVICE_ATT_SIZE]; /**< System service attributes for restoring of Service Changed Indication setting in DFU mode. */ +} nrf_dfu_peer_data_t; + +typedef enum +{ + DFU_PEER_DATA_STATE_INVALID = 0, + DFU_PEER_DATA_STATE_INITIALIZED = 1, + DFU_PEER_DATA_STATE_WRITE_REQUESTED = 2, + DFU_PEER_DATA_STATE_WRITE_FINISHED = 3, + DFU_PEER_DATA_STATE_WRITE_FAILED = 4, +} nrf_dfu_peer_data_state_t; + +typedef struct +{ + uint32_t crc; /**< CRC of the rest of the parameters in this struct. Calculated by the bootloader. */ + uint8_t name[20]; /**< New advertisement name to set. */ + uint32_t len; /**< Length of the advertisement name. */ +} nrf_dfu_adv_name_t; + +typedef enum +{ + DFU_ADV_NAME_STATE_INVALID = 0, + DFU_ADV_NAME_STATE_INITIALIZED = 1, + DFU_ADV_NAME_STATE_WRITE_REQUESTED = 2, + DFU_ADV_NAME_STATE_WRITE_FINISHED = 3, + DFU_ADV_NAME_STATE_WRITE_FAILED = 4, +} nrf_dfu_set_adv_name_state_t; + +#else +typedef struct +{ + uint8_t dummy_data[NRF_DFU_PEER_DATA_LEN]; +} nrf_dfu_peer_data_t; + +typedef struct +{ + uint8_t dummy_data[NRF_DFU_ADV_NAME_LEN]; +} nrf_dfu_adv_name_t; +#endif // NRF_DFU_TRANSPORT_BLE + +STATIC_ASSERT(sizeof(nrf_dfu_peer_data_t) == NRF_DFU_PEER_DATA_LEN, "nrf_dfu_peer_data_t has unexpected length. This can cause incompatibility with tools."); +STATIC_ASSERT(sizeof(nrf_dfu_adv_name_t) == NRF_DFU_ADV_NAME_LEN, "nrf_dfu_adv_name_t has unexpected length. This can cause incompatibility with tools."); + +#define SETTINGS_RESERVED_AREA_SIZE 16 /**< The number of words in the reserved area of the DFU settings. */ +#define SETTINGS_BOOT_VALIDATION_SIZE 64 /**< The number of bytes reserved for boot_validation value. */ + + +typedef enum +{ + NO_VALIDATION, + VALIDATE_CRC, + VALIDATE_SHA256, + VALIDATE_ECDSA_P256_SHA256, +} boot_validation_type_t; + +typedef struct +{ + boot_validation_type_t type; + uint8_t bytes[SETTINGS_BOOT_VALIDATION_SIZE]; +} boot_validation_t; + +/**@brief DFU settings for application and bank data. + */ +typedef struct +{ + uint32_t crc; /**< CRC for the stored DFU settings, not including the CRC itself. If 0xFFFFFFF, the CRC has never been calculated. */ + uint32_t settings_version; /**< Version of the current DFU settings struct layout. */ + uint32_t app_version; /**< Version of the last stored application. */ + uint32_t bootloader_version; /**< Version of the last stored bootloader. */ + + uint32_t bank_layout; /**< Bank layout: single bank or dual bank. This value can change. */ + uint32_t bank_current; /**< The bank that is currently used. */ + + nrf_dfu_bank_t bank_0; /**< Bank 0. */ + nrf_dfu_bank_t bank_1; /**< Bank 1. */ + + uint32_t write_offset; /**< Write offset for the current operation. */ + uint32_t sd_size; /**< Size of the SoftDevice. */ + + dfu_progress_t progress; /**< Current DFU progress. */ + + uint32_t enter_buttonless_dfu; + uint8_t init_command[INIT_COMMAND_MAX_SIZE]; /**< Buffer for storing the init command. */ + + uint32_t boot_validation_crc; + boot_validation_t boot_validation_softdevice; + boot_validation_t boot_validation_app; + boot_validation_t boot_validation_bootloader; + + nrf_dfu_peer_data_t peer_data; /**< Not included in calculated CRC. */ + nrf_dfu_adv_name_t adv_name; /**< Not included in calculated CRC. */ +} nrf_dfu_settings_t; + +#pragma pack() // revert pack settings + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_TYPES_H__ + +/** @} */ diff --git a/components/libraries/bootloader/dfu/nrf_dfu_utils.c b/components/libraries/bootloader/dfu/nrf_dfu_utils.c new file mode 100644 index 0000000..978369a --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_utils.c @@ -0,0 +1,220 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu_utils.h" + +#include "nrf_dfu_settings.h" +#include "nrf_bootloader_info.h" +#include "crc32.h" +#include "nrf_log.h" +#include "nrf_dfu_validation.h" + +void nrf_dfu_bank_invalidate(nrf_dfu_bank_t * const p_bank) +{ + // Set the bank-code to invalid, and reset size/CRC + memset(p_bank, 0, sizeof(nrf_dfu_bank_t)); + + // Reset write pointer after completed operation + s_dfu_settings.write_offset = 0; +} + + +#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD) +void nrf_dfu_softdevice_invalidate(void) +{ + static const uint32_t all_zero = 0UL; + + if (SD_PRESENT && !NRF_DFU_IN_APP) + { + ret_code_t err_code = nrf_dfu_flash_store(SD_MAGIC_NUMBER_ABS_OFFSET_GET(MBR_SIZE), &all_zero, 4, NULL); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not invalidate SoftDevice.") + } + else + { + // If there is an app it must be invalidated since its start address can no longer be resolved. + if (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP) + { + s_dfu_settings.bank_0.bank_code = NRF_DFU_BANK_INVALID; + } + // Since the start of bank 0 has now implicitly been moved to the start + // of the invalidated SoftDevice, its image size must be increased by the + // same amount so the start of bank 1 will be correctly calculated. + s_dfu_settings.bank_0.image_size += SD_SIZE_GET(MBR_SIZE) - MBR_SIZE; + } + } +} +#endif + + +uint32_t nrf_dfu_bank0_start_addr(void) +{ + if (SD_PRESENT) + { + return ALIGN_TO_PAGE(SD_SIZE_GET(MBR_SIZE)); + } + else + { + return MBR_SIZE; + } +} + + +uint32_t nrf_dfu_bank1_start_addr(void) +{ + uint32_t bank0_addr = nrf_dfu_bank0_start_addr(); + return ALIGN_TO_PAGE(bank0_addr + s_dfu_settings.bank_0.image_size); +} + + +uint32_t nrf_dfu_app_start_address(void) +{ + return nrf_dfu_bank0_start_addr(); +} + + +uint32_t nrf_dfu_softdevice_start_address(void) +{ + return MBR_SIZE; +} + + +uint32_t nrf_dfu_cache_prepare(const uint32_t required_size, bool single_bank, bool keep_app, bool keep_softdevice) +{ + ret_code_t err_code; + bool cache_too_small; + enum + { + INITIAL_DELETE_APP = 0, + APP_DELETED_DELETE_SOFTDEVICE = 1, + SOFTDEVICE_DELETED = 2 + } pass; + + NRF_LOG_DEBUG("Enter nrf_dfu_cache_prepare()"); + NRF_LOG_DEBUG("required_size: 0x%x.", required_size); + NRF_LOG_DEBUG("single_bank: %s.", single_bank ? "true" : "false"); + NRF_LOG_DEBUG("keep_app: %s.", keep_app ? "true" : "false"); + NRF_LOG_DEBUG("keep_softdevice: %s.", keep_softdevice ? "true" : "false"); + NRF_LOG_DEBUG("SD_PRESENT: %s.", SD_PRESENT ? "true" : "false"); + NRF_LOG_DEBUG("Bank contents:"); + NRF_LOG_DEBUG("Bank 0 code: 0x%02x: Size: 0x%x", s_dfu_settings.bank_0.bank_code, s_dfu_settings.bank_0.image_size); + NRF_LOG_DEBUG("Bank 1 code: 0x%02x: Size: 0x%x", s_dfu_settings.bank_1.bank_code, s_dfu_settings.bank_1.image_size); + + // Pass 0 deletes the app if necessary or requested, and if so, proceeds to pass 1. + // Pass 1 deletes the SoftDevice if necessary or requested, and if so, proceeds to pass 2. + // Pass 2 does a last size check. + for (pass = INITIAL_DELETE_APP; pass <= SOFTDEVICE_DELETED; pass++) + { + uint32_t cache_address; + const uint32_t bootloader_start_addr = BOOTLOADER_START_ADDR; // Assign to a variable to prevent warning in Keil 4. + bool keep_firmware = true; + bool delete_more; + + switch (pass) + { + case INITIAL_DELETE_APP: + cache_address = nrf_dfu_bank1_start_addr(); + + // If there is no app, keep_app should be assumed false, so we can free up more space. + keep_firmware = keep_app && (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP); + break; + + case APP_DELETED_DELETE_SOFTDEVICE: + cache_address = nrf_dfu_bank0_start_addr(); + + // If there is no SoftDevice, keep_SoftDevice should be assumed true, because there is + // no point to continuing since the SoftDevice is the last firmware that can be deleted. + keep_firmware = keep_softdevice || !SD_PRESENT; + break; + + case SOFTDEVICE_DELETED: + cache_address = nrf_dfu_softdevice_start_address(); + break; + + default: + ASSERT(false); + cache_address = 0; + break; + } + + ASSERT(cache_address <= DFU_REGION_END(bootloader_start_addr)); + cache_too_small = required_size > (DFU_REGION_END(bootloader_start_addr) - cache_address); + delete_more = cache_too_small || single_bank; // Delete app or SoftDevice only if we need more room, or if single bank is requested. + + NRF_LOG_DEBUG("pass: %d.", pass); + NRF_LOG_DEBUG("cache_address: 0x%x.", cache_address); + NRF_LOG_DEBUG("cache_too_small: %s.", cache_too_small ? "true" : "false"); + NRF_LOG_DEBUG("keep_firmware: %s.", keep_firmware ? "true" : "false"); + NRF_LOG_DEBUG("delete_more: %s.", delete_more ? "true" : "false"); + + if (!delete_more || keep_firmware || (pass >= SOFTDEVICE_DELETED)) + { + // Stop, done. + break; + } + } + + if (cache_too_small) + { + NRF_LOG_WARNING("Aborting. Cannot fit new firmware on device"); + err_code = NRF_ERROR_NO_MEM; + } + else + { + // Room was found. Make the necessary preparations for receiving update. + +#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD) + if (pass >= SOFTDEVICE_DELETED) + { + NRF_LOG_DEBUG("Invalidating SoftDevice."); + nrf_dfu_softdevice_invalidate(); + } +#endif + if (pass >= APP_DELETED_DELETE_SOFTDEVICE) + { + NRF_LOG_DEBUG("Invalidating app."); + nrf_dfu_bank_invalidate(&s_dfu_settings.bank_0); + } + + err_code = NRF_SUCCESS; + } + + return err_code; +} diff --git a/components/libraries/bootloader/dfu/nrf_dfu_utils.h b/components/libraries/bootloader/dfu/nrf_dfu_utils.h new file mode 100644 index 0000000..0a5c552 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_utils.h @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_utils DFU utilities + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_UTILS_H__ +#define NRF_DFU_UTILS_H__ + +#include +#include +#include "nrf_dfu_types.h" +#include "app_util.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * Round up val to the next page boundary + */ +#define ALIGN_TO_PAGE(val) ALIGN_NUM((CODE_PAGE_SIZE), (val)) + + +/** @brief Function for getting the start address of bank 0. + * + * @note Bank 0 starts after the SoftDevice if a SoftDevice is present. + * + * @return The start address of bank 0. + */ +uint32_t nrf_dfu_bank0_start_addr(void); + + +/** @brief Function for getting the start address of bank 1. + * + * @return The start address of bank 1. + */ +uint32_t nrf_dfu_bank1_start_addr(void); + + +/** @brief Function for getting the start address of the app. + * + * @return The start address of the bootable app. + */ +uint32_t nrf_dfu_app_start_address(void); + + +/** @brief Function for getting the start address of the SoftDevice. + * + * @return The start address of the SoftDevivce. + */ +uint32_t nrf_dfu_softdevice_start_address(void); + + +/** @brief Function for finding and preparing a place in flash in which to store a DFU update. + * + * @details This function checks the size requirements and selects a location for + * placing the cache of the DFU images. + * The function tries to find enough space after the existing firmwares. If there is not + * enough space, the present application is deleted. If there is still not enough space, + * the SoftDevice is deleted. + * If @p single_bank is true, the default behavior is to immediately delete the app and + * SoftDevice as necessary to place the new firmware at its intended location. If the + * intended location cannot be made available, or if the update is a bootloader update, + * the update will be a dual bank update, and nothing will be deleted by this function + * except when needed for size. + * If @p keep_app is true, the app is never deleted by this function. Likewise if @p + * keep_softdevice is true, the SoftDevice is never deleted by this function. + * If the new firmware cannot fit within the constraints, nothing is deleted and the + * function fails. + * + * @param[in] required_size Requirements for the size of the new image. + * @param[in] single_bank Whether to put the firmware directly where it's meant to go. + * @p keep_app and @p keep_softdevice take precedence over this. + * @param[in] keep_app True to ensure the app is not deleted by this function. This + * effectively enforces dual bank update. + * @param[out] keep_softdevice True to ensure the SoftDevice is not deleted by this function. + * + * @retval NRF_SUCCESS If a cache location was found for the DFU process. + * @retval NRF_ERROR_NO_MEM If there is not enough space available to receive the update. + * Nothing has been deleted. + */ +uint32_t nrf_dfu_cache_prepare(uint32_t required_size, bool single_bank, bool keep_app, bool keep_softdevice); + + +/**@brief Function for making sure a SoftDevice is not recognized as such anymore. + * + * @details It works by overwriting the magic number of the SoftDevice with 0s. The + * magic number is used throughout the bootloader to detect whether a SoftDevice + * is present. + * + * @warning This function should only be called when both banks are already invalid. + * because the (implicit) position of the banks will shift when the SoftDevice + * is invalidated. + */ +void nrf_dfu_softdevice_invalidate(void); + + +/**@brief Function for making sure a bank is not copied or booted. + * + * @details This also sets the size of the bank to 0. + * + * @param[in] p_bank Pointer to the bank to be invalidated. + */ +void nrf_dfu_bank_invalidate(nrf_dfu_bank_t * const p_bank); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_UTILS_H__ + +/** @} */ diff --git a/components/libraries/bootloader/dfu/nrf_dfu_validation.c b/components/libraries/bootloader/dfu/nrf_dfu_validation.c new file mode 100644 index 0000000..e959605 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_validation.c @@ -0,0 +1,1087 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include "nrf_dfu_types.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_utils.h" +#include "nrf_dfu_flash.h" +#include "nrf_bootloader_info.h" +#include "pb.h" +#include "pb_common.h" +#include "pb_decode.h" +#include "dfu-cc.pb.h" +#include "crc32.h" +#include "nrf_crypto.h" +#include "nrf_crypto_shared.h" +#include "nrf_assert.h" +#include "nrf_dfu_validation.h" +#include "nrf_dfu_ver_validation.h" +#include "nrf_strerror.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_validation +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +NRF_LOG_MODULE_REGISTER(); + +#ifndef DFU_REQUIRES_SOFTDEVICE +#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD) +#define DFU_REQUIRES_SOFTDEVICE 0 +#else +#define DFU_REQUIRES_SOFTDEVICE 1 +#endif +#endif + +#define EXT_ERR(err) (nrf_dfu_result_t)((uint32_t)NRF_DFU_RES_CODE_EXT_ERROR + (uint32_t)err) + +/* Whether a complete init command has been received and prevalidated, but the firmware + * is not yet fully transferred. This value will also be correct after reset. + */ +static bool m_valid_init_cmd_present = false; +static dfu_packet_t m_packet = DFU_PACKET_INIT_DEFAULT; +static uint8_t* m_init_packet_data_ptr = 0; +static uint32_t m_init_packet_data_len = 0; +static pb_istream_t m_pb_stream; + +static dfu_init_command_t const * mp_init = NULL; + +__ALIGN(4) extern const uint8_t pk[64]; + +/** @brief Value length structure holding the public key. + * + * @details The pk value pointed to is the public key present in dfu_public_key.c + */ +static nrf_crypto_ecc_public_key_t m_public_key; + +/** @brief Structure to hold a signature + */ +static nrf_crypto_ecdsa_secp256r1_signature_t m_signature; + +/** @brief Structure to hold the hash for signature verification + */ +static nrf_crypto_hash_sha256_digest_t m_sig_hash; + +/** @brief Structure to hold the hash for the firmware image + */ +static nrf_crypto_hash_sha256_digest_t m_fw_hash; + +/** @brief Whether nrf_crypto and local keys have been initialized. + */ +static bool m_crypto_initialized = false; + +/** @brief Flag used by parser code to indicate that the init command has been found to be invalid. + */ +static bool m_init_packet_valid = false; + +static void pb_decoding_callback(pb_istream_t *str, + uint32_t tag, + pb_wire_type_t wire_type, + void *iter) +{ + pb_field_iter_t* p_iter = (pb_field_iter_t *) iter; + + // Match the beginning of the init command. + if (p_iter->pos->ptr == &dfu_init_command_fields[0]) + { + uint8_t * ptr = (uint8_t *)str->state; + uint32_t size = str->bytes_left; + + if (m_init_packet_data_ptr != NULL || m_init_packet_data_len != 0) + { + m_init_packet_valid = false; + return; + } + + // Remove tag. + while (*ptr & 0x80) + { + ptr++; + size--; + } + ptr++; + size--; + + // Store the info in init_packet_data. + m_init_packet_data_ptr = ptr; + m_init_packet_data_len = size; + m_init_packet_valid = true; + + NRF_LOG_DEBUG("PB: Init packet data len: %d", size); + } +} + +/** @brief Function for decoding byte stream into variable. + * + * @retval true If the stored init command was successfully decoded. + * @retval false If there was no stored init command, or the decoding failed. + */ +static bool stored_init_cmd_decode(void) +{ + m_pb_stream = pb_istream_from_buffer(s_dfu_settings.init_command, + s_dfu_settings.progress.command_size); + + dfu_init_command_t * p_init; + + // Attach our callback to follow the field decoding. + m_pb_stream.decoding_callback = pb_decoding_callback; + + m_init_packet_valid = false; + m_init_packet_data_ptr = NULL; + m_init_packet_data_len = 0; + memset(&m_packet, 0, sizeof(m_packet)); + + if (!pb_decode(&m_pb_stream, dfu_packet_fields, &m_packet)) + { + NRF_LOG_ERROR("Handler: Invalid protocol buffer m_pb_stream"); + return false; + } + + if (!m_init_packet_valid || (m_packet.has_signed_command && m_packet.has_command)) + { + NRF_LOG_ERROR("Handler: Invalid init command."); + return false; + } + else if (m_packet.has_signed_command && m_packet.signed_command.command.has_init) + { + p_init = &m_packet.signed_command.command.init; + + m_pb_stream = pb_istream_from_buffer(m_init_packet_data_ptr, m_init_packet_data_len); + memset(p_init, 0, sizeof(dfu_init_command_t)); + + if (!pb_decode(&m_pb_stream, dfu_init_command_fields, p_init)) + { + NRF_LOG_ERROR("Handler: Invalid protocol buffer m_pb_stream (init command)"); + return false; + } + } + else if (m_packet.has_command && m_packet.command.has_init) + { + p_init = &m_packet.command.init; + } + else + { + return false; + } + + mp_init = p_init; + + return true; +} + + +static void crypto_init(void) +{ + ret_code_t err_code; + uint8_t pk_copy[sizeof(pk)]; + + if (m_crypto_initialized) + { + return; + } + + err_code = nrf_crypto_init(); + ASSERT(err_code == NRF_SUCCESS); + UNUSED_PARAMETER(err_code); + + // Convert public key to big-endian format for use in nrf_crypto. + nrf_crypto_internal_double_swap_endian(pk_copy, pk, sizeof(pk) / 2); + + err_code = nrf_crypto_ecc_public_key_from_raw(&g_nrf_crypto_ecc_secp256r1_curve_info, + &m_public_key, + pk_copy, + sizeof(pk)); + ASSERT(err_code == NRF_SUCCESS); + UNUSED_PARAMETER(err_code); + + m_crypto_initialized = true; +} + + +void nrf_dfu_validation_init(void) +{ + // If the command is stored to flash, init command was valid. + if ((s_dfu_settings.progress.command_size != 0) && + stored_init_cmd_decode()) + { + m_valid_init_cmd_present = true; + } + else + { + m_valid_init_cmd_present = false; + } +} + + +nrf_dfu_result_t nrf_dfu_validation_init_cmd_create(uint32_t size) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + if (size == 0) + { + ret_val = NRF_DFU_RES_CODE_INVALID_PARAMETER; + } + else if (size > INIT_COMMAND_MAX_SIZE) + { + ret_val = NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES; + } + else + { + // Set DFU to uninitialized. + m_valid_init_cmd_present = false; + + // Reset all progress. + nrf_dfu_settings_progress_reset(); + + // Set the init command size. + s_dfu_settings.progress.command_size = size; + } + return ret_val; +} + + +nrf_dfu_result_t nrf_dfu_validation_init_cmd_append(uint8_t const * p_data, uint32_t length) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + if ((length + s_dfu_settings.progress.command_offset) > s_dfu_settings.progress.command_size) + { + NRF_LOG_ERROR("Init command larger than expected."); + ret_val = NRF_DFU_RES_CODE_INVALID_PARAMETER; + } + else + { + // Copy the received data to RAM, update offset and calculate CRC. + memcpy(&s_dfu_settings.init_command[s_dfu_settings.progress.command_offset], + p_data, + length); + + s_dfu_settings.progress.command_offset += length; + s_dfu_settings.progress.command_crc = crc32_compute(p_data, + length, + &s_dfu_settings.progress.command_crc); + } + return ret_val; +} + + +void nrf_dfu_validation_init_cmd_status_get(uint32_t * p_offset, + uint32_t * p_crc, + uint32_t * p_max_size) +{ + *p_offset = s_dfu_settings.progress.command_offset; + *p_crc = s_dfu_settings.progress.command_crc; + *p_max_size = INIT_COMMAND_MAX_SIZE; +} + + +bool nrf_dfu_validation_init_cmd_present(void) +{ + return m_valid_init_cmd_present; +} + + +// Function determines if init command signature is obligatory. +static bool signature_required(dfu_fw_type_t fw_type_to_be_updated) +{ + bool result = true; + + // DFU_FW_TYPE_EXTERNAL_APPLICATION and bootloader updates always require + // signature check + if ((!DFU_REQUIRES_SOFTDEVICE && (fw_type_to_be_updated == DFU_FW_TYPE_SOFTDEVICE)) || + (fw_type_to_be_updated == DFU_FW_TYPE_APPLICATION)) + { + result = NRF_DFU_REQUIRE_SIGNED_APP_UPDATE; + } + return result; +} + + +// Function to perform signature check if required. +static nrf_dfu_result_t nrf_dfu_validation_signature_check(dfu_signature_type_t signature_type, + uint8_t const * p_signature, + uint32_t signature_len, + uint8_t const * p_data, + uint32_t data_len) +{ + ret_code_t err_code; + size_t hash_len = NRF_CRYPTO_HASH_SIZE_SHA256; + + nrf_crypto_hash_context_t hash_context = {0}; + nrf_crypto_ecdsa_verify_context_t verify_context = {0}; + + crypto_init(); + + NRF_LOG_INFO("Signature required. Checking signature.") + if (p_signature == NULL) + { + NRF_LOG_WARNING("No signature found."); + return EXT_ERR(NRF_DFU_EXT_ERROR_SIGNATURE_MISSING); + } + + if (signature_type != DFU_SIGNATURE_TYPE_ECDSA_P256_SHA256) + { + NRF_LOG_INFO("Invalid signature type"); + return EXT_ERR(NRF_DFU_EXT_ERROR_WRONG_SIGNATURE_TYPE); + } + + NRF_LOG_INFO("Calculating hash (len: %d)", data_len); + err_code = nrf_crypto_hash_calculate(&hash_context, + &g_nrf_crypto_hash_sha256_info, + p_data, + data_len, + m_sig_hash, + &hash_len); + if (err_code != NRF_SUCCESS) + { + return NRF_DFU_RES_CODE_OPERATION_FAILED; + } + + if (sizeof(m_signature) != signature_len) + { + return NRF_DFU_RES_CODE_OPERATION_FAILED; + } + + // Prepare the signature received over the air. + memcpy(m_signature, p_signature, signature_len); + + // Calculate the signature. + NRF_LOG_INFO("Verify signature"); + + // The signature is in little-endian format. Change it to big-endian format for nrf_crypto use. + nrf_crypto_internal_double_swap_endian_in_place(m_signature, sizeof(m_signature) / 2); + + err_code = nrf_crypto_ecdsa_verify(&verify_context, + &m_public_key, + m_sig_hash, + hash_len, + m_signature, + sizeof(m_signature)); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Signature failed (err_code: 0x%x)", err_code); + NRF_LOG_DEBUG("Signature:"); + NRF_LOG_HEXDUMP_DEBUG(m_signature, sizeof(m_signature)); + NRF_LOG_DEBUG("Hash:"); + NRF_LOG_HEXDUMP_DEBUG(m_sig_hash, hash_len); + NRF_LOG_DEBUG("Public Key:"); + NRF_LOG_HEXDUMP_DEBUG(pk, sizeof(pk)); + NRF_LOG_FLUSH(); + + return NRF_DFU_RES_CODE_INVALID_OBJECT; + } + + NRF_LOG_INFO("Image verified"); + return NRF_DFU_RES_CODE_SUCCESS; +} + + +// Function to calculate the total size of the firmware(s) in the update. +static nrf_dfu_result_t update_data_size_get(dfu_init_command_t const * p_init, uint32_t * p_size) +{ + nrf_dfu_result_t ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID); + uint32_t fw_sz = 0; + + if ((p_init->type == DFU_FW_TYPE_APPLICATION || + p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) && + (p_init->has_app_size == true)) + { + fw_sz = p_init->app_size; + } + else + { + if ((p_init->type & DFU_FW_TYPE_SOFTDEVICE) && (p_init->has_sd_size == true)) + { + fw_sz = p_init->sd_size; + } + + if ((p_init->type & DFU_FW_TYPE_BOOTLOADER) && (p_init->has_bl_size == true)) + { + if (p_init->bl_size <= BOOTLOADER_SIZE) + { + fw_sz += p_init->bl_size; + } + else + { + NRF_LOG_ERROR("BL size (%d) over limit (%d)", p_init->bl_size, BOOTLOADER_SIZE); + fw_sz = 0; + ret_val = NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES; + } + } + } + + if (fw_sz) + { + *p_size = fw_sz; + ret_val = NRF_DFU_RES_CODE_SUCCESS; + } + else + { + NRF_LOG_ERROR("Init packet does not contain valid firmware size"); + } + + return ret_val; +} + + +/** + * @brief Function to check if single bank update should be used. + * + * @param new_fw_type Firmware type. + */ +static bool use_single_bank(dfu_fw_type_t new_fw_type) +{ + bool result = false; + + // DFU_FW_TYPE_EXTERNAL_APPLICATION never uses single bank + if (((new_fw_type == DFU_FW_TYPE_APPLICATION) || + (new_fw_type == DFU_FW_TYPE_SOFTDEVICE)) && + NRF_DFU_SINGLE_BANK_APP_UPDATES) + { + result = true; + } + + return result; +} + + +// Function to determine whether the new firmware needs a SoftDevice to be present. +static bool update_requires_softdevice(dfu_init_command_t const * p_init) +{ + return ((p_init->sd_req_count > 0) && (p_init->sd_req[0] != SD_REQ_APP_OVERWRITES_SD)); +} + + +// Function to determine whether the SoftDevice can be removed during the update or not. +static bool keep_softdevice(dfu_init_command_t const * p_init) +{ + UNUSED_PARAMETER(p_init); // It's unused when DFU_REQUIRES_SOFTDEVICE is true. + return DFU_REQUIRES_SOFTDEVICE || update_requires_softdevice(p_init); +} + + +/**@brief Function to determine where to temporarily store the incoming firmware. + * This also checks whether the update will fit, and deletes existing + * firmware to make room for the new firmware. + * + * @param[in] p_init Init command. + * @param[in] fw_size The size of the incoming firmware. + * @param[out] p_addr The address at which to initially store the firmware. + * + * @retval NRF_DFU_RES_CODE_SUCCESS If the size check passed and + * an address was found. + * @retval NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES If the size check failed. + */ +static nrf_dfu_result_t update_data_addr_get(dfu_init_command_t const * p_init, + uint32_t fw_size, + uint32_t * p_addr) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + ret_code_t err_code = nrf_dfu_cache_prepare(fw_size, + use_single_bank(p_init->type), + NRF_DFU_FORCE_DUAL_BANK_APP_UPDATES, + keep_softdevice(p_init)); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Can't find room for update"); + ret_val = NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES; + } + else + { + *p_addr = nrf_dfu_bank1_start_addr(); + NRF_LOG_DEBUG("Write address set to 0x%08x", *p_addr); + } + return ret_val; +} + + +nrf_dfu_result_t nrf_dfu_validation_prevalidate(void) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + dfu_command_t const * p_command = &m_packet.command; + dfu_signature_type_t signature_type = DFU_SIGNATURE_TYPE_MIN; + uint8_t const * p_signature = NULL; + uint32_t signature_len = 0; + + if (m_packet.has_signed_command) + { + p_command = &m_packet.signed_command.command; + signature_type = m_packet.signed_command.signature_type; + p_signature = m_packet.signed_command.signature.bytes; + signature_len = m_packet.signed_command.signature.size; + } + + // Validate signature. + if (signature_required(p_command->init.type)) + { + ret_val = nrf_dfu_validation_signature_check(signature_type, + p_signature, + signature_len, + m_init_packet_data_ptr, + m_init_packet_data_len); + } + + // Validate versions. + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + ret_val = nrf_dfu_ver_validation_check(&p_command->init); + } + + if (ret_val != NRF_DFU_RES_CODE_SUCCESS) + { + NRF_LOG_WARNING("Prevalidation failed."); + NRF_LOG_DEBUG("Init command:"); + NRF_LOG_HEXDUMP_DEBUG(m_init_packet_data_ptr, m_init_packet_data_len); + } + + return ret_val; +} + + +nrf_dfu_result_t nrf_dfu_validation_init_cmd_execute(uint32_t * p_dst_data_addr, + uint32_t * p_data_len) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + + if (s_dfu_settings.progress.command_offset != s_dfu_settings.progress.command_size) + { + // The object wasn't the right (requested) size. + NRF_LOG_ERROR("Execute with faulty offset"); + ret_val = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + } + else if (m_valid_init_cmd_present) + { + *p_dst_data_addr = nrf_dfu_bank1_start_addr(); + ret_val = update_data_size_get(mp_init, p_data_len); + } + else if (stored_init_cmd_decode()) + { + // Will only get here if init command was received since last reset. + // An init command should not be written to flash until after it's been checked here. + ret_val = nrf_dfu_validation_prevalidate(); + + *p_dst_data_addr = 0; + *p_data_len = 0; + + // Get size of binary. + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + ret_val = update_data_size_get(mp_init, p_data_len); + } + + // Get address where to flash the binary. + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + ret_val = update_data_addr_get(mp_init, *p_data_len, p_dst_data_addr); + } + + // Set flag validating the init command. + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + m_valid_init_cmd_present = true; + } + else + { + nrf_dfu_settings_progress_reset(); + } + } + else + { + NRF_LOG_ERROR("Failed to decode init packet"); + ret_val = NRF_DFU_RES_CODE_INVALID_OBJECT; + } + + return ret_val; +} + + +// Function to check the hash received in the init command against the received firmware. +// little_endian specifies the endianness of @p p_hash. +static bool nrf_dfu_validation_hash_ok(uint8_t const * p_hash, uint32_t src_addr, uint32_t data_len, bool little_endian) +{ + ret_code_t err_code; + bool result = true; + uint8_t hash_be[NRF_CRYPTO_HASH_SIZE_SHA256]; + size_t hash_len = NRF_CRYPTO_HASH_SIZE_SHA256; + + nrf_crypto_hash_context_t hash_context = {0}; + + crypto_init(); + + if (little_endian) + { + // Convert to hash to big-endian format for use in nrf_crypto. + nrf_crypto_internal_swap_endian(hash_be, + p_hash, + NRF_CRYPTO_HASH_SIZE_SHA256); + p_hash = hash_be; + } + + NRF_LOG_DEBUG("Hash verification. start address: 0x%x, size: 0x%x", + src_addr, + data_len); + + err_code = nrf_crypto_hash_calculate(&hash_context, + &g_nrf_crypto_hash_sha256_info, + (uint8_t*)src_addr, + data_len, + m_fw_hash, + &hash_len); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not run hash verification (err_code 0x%x).", err_code); + result = false; + } + else if (memcmp(m_fw_hash, p_hash, NRF_CRYPTO_HASH_SIZE_SHA256) != 0) + { + NRF_LOG_WARNING("Hash verification failed."); + NRF_LOG_DEBUG("Expected FW hash:") + NRF_LOG_HEXDUMP_DEBUG(p_hash, NRF_CRYPTO_HASH_SIZE_SHA256); + NRF_LOG_DEBUG("Actual FW hash:") + NRF_LOG_HEXDUMP_DEBUG(m_fw_hash, NRF_CRYPTO_HASH_SIZE_SHA256); + NRF_LOG_FLUSH(); + + result = false; + } + + return result; +} + + +// Function to check the hash received in the init command against the received firmware. +bool fw_hash_ok(dfu_init_command_t const * p_init, uint32_t fw_start_addr, uint32_t fw_size) +{ + ASSERT(p_init != NULL); + return nrf_dfu_validation_hash_ok((uint8_t *)p_init->hash.hash.bytes, fw_start_addr, fw_size, true); +} + + +// Function to check whether the update contains a SoftDevice and, if so, if it is of a different +// major version than the existing SoftDevice. +static bool is_major_softdevice_update(uint32_t new_sd_addr) +{ + // True if there is no SD right now, but there is a new one coming. This counts as a major update. + bool result = !SD_PRESENT && (SD_MAGIC_NUMBER_GET(new_sd_addr) == SD_MAGIC_NUMBER); + + if (SD_PRESENT && (SD_MAGIC_NUMBER_GET(new_sd_addr) == SD_MAGIC_NUMBER)) + { + // Both SoftDevices are present. + uint32_t current_SD_major = SD_MAJOR_VERSION_EXTRACT(SD_VERSION_GET(MBR_SIZE)); + uint32_t new_SD_major = SD_MAJOR_VERSION_EXTRACT(SD_VERSION_GET(new_sd_addr)); + + result = (current_SD_major != new_SD_major); + + NRF_LOG_INFO("SoftDevice update is a %s version update. Current: %d. New: %d.", + result ? "major" : "minor", + current_SD_major, + new_SD_major); + } + + return result; +} + + +/**@brief Validate the SoftDevice size and magic number in structure found at 0x2000 in received SoftDevice. + * + * @param[in] sd_start_addr Start address of received SoftDevice. + * @param[in] sd_size Size of received SoftDevice in bytes. + */ +static bool softdevice_info_ok(uint32_t sd_start_addr, uint32_t sd_size) +{ + bool result = true; + + if (SD_MAGIC_NUMBER_GET(sd_start_addr) != SD_MAGIC_NUMBER) + { + NRF_LOG_ERROR("The SoftDevice does not contain the magic number identifying it as a SoftDevice."); + result = false; + } + else if (SD_SIZE_GET(sd_start_addr) < ALIGN_TO_PAGE(sd_size + MBR_SIZE)) + { + // The size in the info struct should be rounded up to a page boundary + // and be larger than the actual size + the size of the MBR. + NRF_LOG_ERROR("The SoftDevice size in the info struct is too small compared with the size reported in the init command."); + result = false; + } + else if (SD_PRESENT && (SD_ID_GET(MBR_SIZE) != SD_ID_GET(sd_start_addr))) + { + NRF_LOG_ERROR("The new SoftDevice is of a different family than the present SoftDevice. Compatibility cannot be guaranteed."); + result = false; + } + + return result; +} + + +static bool boot_validation_extract(boot_validation_t * p_boot_validation, + dfu_init_command_t const * p_init, + uint32_t index, + uint32_t start_addr, + uint32_t data_len, + boot_validation_type_t default_type) +{ + ret_code_t err_code; + size_t hash_len = NRF_CRYPTO_HASH_SIZE_SHA256; + + nrf_crypto_hash_context_t hash_context = {0}; + + memset(p_boot_validation, 0, sizeof(boot_validation_t)); + p_boot_validation->type = (p_init->boot_validation_count > index) + ? (boot_validation_type_t)p_init->boot_validation[index].type + : default_type; // default + + switch(p_boot_validation->type) + { + case NO_VALIDATION: + break; + + case VALIDATE_CRC: + *(uint32_t *)&p_boot_validation->bytes[0] = crc32_compute((uint8_t *)start_addr, data_len, NULL); + break; + + case VALIDATE_SHA256: + err_code = nrf_crypto_hash_calculate(&hash_context, + &g_nrf_crypto_hash_sha256_info, + (uint8_t*)start_addr, + data_len, + p_boot_validation->bytes, + &hash_len); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_crypto_hash_calculate() failed with error %s", nrf_strerror_get(err_code)); + return false; + } + break; + + case VALIDATE_ECDSA_P256_SHA256: + memcpy(p_boot_validation->bytes, p_init->boot_validation[index].bytes.bytes, p_init->boot_validation[index].bytes.size); + break; + + default: + NRF_LOG_ERROR("Invalid boot validation type: %d", p_boot_validation->type); + return false; + } + + return nrf_dfu_validation_boot_validate(p_boot_validation, start_addr, data_len); +} + + +// The is_trusted argument specifies whether the function should have side effects. +static bool postvalidate_app(dfu_init_command_t const * p_init, uint32_t src_addr, uint32_t data_len, bool is_trusted) +{ + boot_validation_t boot_validation; + + ASSERT(p_init->type == DFU_FW_TYPE_APPLICATION); + + if (!boot_validation_extract(&boot_validation, p_init, 0, src_addr, data_len, VALIDATE_CRC)) + { + return false; + } +#if !NRF_DFU_IN_APP + else if (NRF_BL_APP_SIGNATURE_CHECK_REQUIRED && + (boot_validation.type != VALIDATE_ECDSA_P256_SHA256)) + { + NRF_LOG_WARNING("The boot validation of the app must be a signature check."); + return false; + } +#endif + + if (!is_trusted) + { + return true; + } + + memcpy(&s_dfu_settings.boot_validation_app, &boot_validation, sizeof(boot_validation)); + + s_dfu_settings.bank_1.bank_code = NRF_DFU_BANK_VALID_APP; + + NRF_LOG_DEBUG("Invalidating old application in bank 0."); + s_dfu_settings.bank_0.bank_code = NRF_DFU_BANK_INVALID; + + if (!DFU_REQUIRES_SOFTDEVICE && !update_requires_softdevice(p_init)) + { + // App does not need SD, so it should be placed where SD is. + nrf_dfu_softdevice_invalidate(); + } + + if (!NRF_DFU_DEBUG || + (NRF_DFU_DEBUG && (p_init->has_is_debug == false || p_init->is_debug == false))) + { + s_dfu_settings.app_version = p_init->fw_version; + } + + return true; +} + + +// Function to check a received SoftDevice or Bootloader firmware, or both, +// before it is copied into place. +// The is_trusted argument specifies whether the function should have side effects. +static bool postvalidate_sd_bl(dfu_init_command_t const * p_init, + bool with_sd, + bool with_bl, + uint32_t start_addr, + uint32_t data_len, + bool is_trusted) +{ + boot_validation_t boot_validation_sd = {NO_VALIDATION}; + boot_validation_t boot_validation_bl = {NO_VALIDATION}; + uint32_t bl_start = start_addr; + uint32_t bl_size = data_len; + + ASSERT(with_sd || with_bl); + + if (with_sd) + { + if (!softdevice_info_ok(start_addr, p_init->sd_size)) + { + return false; + } + + if (is_major_softdevice_update(start_addr)) + { + NRF_LOG_WARNING("Invalidating app because it is incompatible with the SoftDevice."); + if (DFU_REQUIRES_SOFTDEVICE && !with_bl) + { + NRF_LOG_ERROR("Major SD update but no BL. Abort to avoid incapacitating the BL."); + return false; + } + } + + if (!boot_validation_extract(&boot_validation_sd, p_init, 0, start_addr, p_init->sd_size, VALIDATE_CRC)) + { + return false; + } + + bl_start += p_init->sd_size; + bl_size -= p_init->sd_size; + } + if (with_bl) + { + if (!boot_validation_extract(&boot_validation_bl, p_init, with_sd ? 1 : 0, bl_start, bl_size, NO_VALIDATION)) + { + return false; + } + else if (boot_validation_bl.type != NO_VALIDATION) + { + NRF_LOG_WARNING("Boot validation of bootloader is not supported and will be ignored."); + } + } + + if (!is_trusted) + { + return true; + } + + if (with_sd) + { + if (is_major_softdevice_update(start_addr)) + { + // Invalidate app since it may not be compatible with new SD. + nrf_dfu_bank_invalidate(&s_dfu_settings.bank_0); + } + + memcpy(&s_dfu_settings.boot_validation_softdevice, &boot_validation_sd, sizeof(boot_validation_sd)); + + // Mark the update as valid. + s_dfu_settings.bank_1.bank_code = with_bl ? NRF_DFU_BANK_VALID_SD_BL + : NRF_DFU_BANK_VALID_SD; + + s_dfu_settings.sd_size = p_init->sd_size; + } + else + { + s_dfu_settings.bank_1.bank_code = NRF_DFU_BANK_VALID_BL; + } + + + if (with_bl) + { + memcpy(&s_dfu_settings.boot_validation_bootloader, &boot_validation_bl, sizeof(boot_validation_bl)); + + if (!NRF_DFU_DEBUG || + (NRF_DFU_DEBUG && (p_init->has_is_debug == false || p_init->is_debug == false))) + { + // If the update contains a bootloader, update the version. + // Unless the update is a debug packet. + s_dfu_settings.bootloader_version = p_init->fw_version; + } + } + + return true; +} + + +bool nrf_dfu_validation_boot_validate(boot_validation_t const * p_validation, uint32_t data_addr, uint32_t data_len) +{ + uint8_t const * p_data = (uint8_t*) data_addr; + switch(p_validation->type) + { + case NO_VALIDATION: + return true; + + case VALIDATE_CRC: + { + uint32_t current_crc = *(uint32_t *)p_validation->bytes; + uint32_t crc = crc32_compute(p_data, data_len, NULL); + + if (crc != current_crc) + { + // CRC does not match with what is stored. + NRF_LOG_DEBUG("CRC check of app failed. Return %d", NRF_DFU_DEBUG); + return NRF_DFU_DEBUG; + } + return true; + } + + case VALIDATE_SHA256: + return nrf_dfu_validation_hash_ok(p_validation->bytes, data_addr, data_len, false); + + case VALIDATE_ECDSA_P256_SHA256: + { + nrf_dfu_result_t res_code = nrf_dfu_validation_signature_check( + DFU_SIGNATURE_TYPE_ECDSA_P256_SHA256, + p_validation->bytes, + NRF_CRYPTO_ECDSA_SECP256R1_SIGNATURE_SIZE, + p_data, + data_len); + return (res_code == NRF_DFU_RES_CODE_SUCCESS); + } + + default: + ASSERT(false); + return false; + } +} + + +nrf_dfu_result_t postvalidate(uint32_t data_addr, uint32_t data_len, bool is_trusted) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + dfu_init_command_t const * p_init = mp_init; + + if (!fw_hash_ok(p_init, data_addr, data_len)) + { + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_VERIFICATION_FAILED); + } + else + { + if (p_init->type == DFU_FW_TYPE_APPLICATION) + { + if (!postvalidate_app(p_init, data_addr, data_len, is_trusted)) + { + ret_val = NRF_DFU_RES_CODE_INVALID_OBJECT; + } + } +#if NRF_DFU_SUPPORTS_EXTERNAL_APP + else if (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + if (!is_trusted) + { + // This function must be implemented externally + ret_val = nrf_dfu_validation_post_external_app_execute(p_init, is_trusted); + } + else + { + s_dfu_settings.bank_1.bank_code = NRF_DFU_BANK_VALID_EXT_APP; + } + } +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + else + { + bool with_sd = p_init->type & DFU_FW_TYPE_SOFTDEVICE; + bool with_bl = p_init->type & DFU_FW_TYPE_BOOTLOADER; + + if (!postvalidate_sd_bl(p_init, with_sd, with_bl, data_addr, data_len, is_trusted)) + { + ret_val = NRF_DFU_RES_CODE_INVALID_OBJECT; + if (is_trusted && with_sd && !DFU_REQUIRES_SOFTDEVICE && + (data_addr == nrf_dfu_softdevice_start_address())) + { + nrf_dfu_softdevice_invalidate(); + } + } + } + } + + if (!is_trusted) + { + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_1; + } + else + { + nrf_dfu_settings_progress_reset(); + } + } + else + { + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + // Mark the update as complete and valid. + s_dfu_settings.bank_1.image_crc = crc32_compute((uint8_t *)data_addr, data_len, NULL); + s_dfu_settings.bank_1.image_size = data_len; + } + else + { + nrf_dfu_bank_invalidate(&s_dfu_settings.bank_1); + } + + nrf_dfu_settings_progress_reset(); + s_dfu_settings.progress.update_start_address = data_addr; + } + + return ret_val; +} + + +nrf_dfu_result_t nrf_dfu_validation_post_data_execute(uint32_t data_addr, uint32_t data_len) +{ + return postvalidate(data_addr, data_len, false); +} + + +nrf_dfu_result_t nrf_dfu_validation_activation_prepare(uint32_t data_addr, uint32_t data_len) +{ + return postvalidate(data_addr, data_len, true); +} + + +bool nrf_dfu_validation_valid_external_app(void) +{ + return s_dfu_settings.bank_1.bank_code == NRF_DFU_BANK_VALID_EXT_APP; +} diff --git a/components/libraries/bootloader/dfu/nrf_dfu_validation.h b/components/libraries/bootloader/dfu/nrf_dfu_validation.h new file mode 100644 index 0000000..df35427 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_validation.h @@ -0,0 +1,199 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_dfu_validation Validation + * @{ + * @ingroup nrf_dfu + */ + +#ifndef __NRF_DFU_VALIDATION_H +#define __NRF_DFU_VALIDATION_H + +#include "stdint.h" +#include "sdk_errors.h" +#include "dfu-cc.pb.h" +#include "nrf_dfu_handling_error.h" + +/** + * @brief Function for module initialization. + * + * Function checks if there is a valid init packet in DFU settings written in flash. + */ +void nrf_dfu_validation_init(void); + +/** + * @brief Function called on reception of init command creation request. + * + * @param[in] size Size of incoming init packet. + * + * @return Operation result. See @ref nrf_dfu_result_t + */ +nrf_dfu_result_t nrf_dfu_validation_init_cmd_create(uint32_t size); + +/** + * @brief Function called on reception of fragment of init command. + * + * @param[in] p_data Init command fragment. + * @param[in] length Init command fragment size. + * + * @return Operation result. See @ref nrf_dfu_result_t + */ +nrf_dfu_result_t nrf_dfu_validation_init_cmd_append(uint8_t const * p_data, uint32_t length); + +/** + * @brief Function for getting init command status. + * + * @param[out] p_offset Current offset. + * @param[out] p_crc Current CRC. + * @param[out] p_max_size Maximum size of init command. + */ +void nrf_dfu_validation_init_cmd_status_get(uint32_t * p_offset, + uint32_t * p_crc, + uint32_t * p_max_size); + +/** + * @brief Function for inquiring whether a valid init command has been received. + * + * @return true if there is a valid init command. This can be true at boot time + * if the device was reset during a DFU operation. + */ +bool nrf_dfu_validation_init_cmd_present(void); + +/** + * @brief Function for validating init command and retrieving the address and length of the firmware. + * + * If init command is successfully validated Bank 1 details are written to out parameters. + * + * Until @ref nrf_dfu_validation_init_cmd_create is called, this function can be called + * again after the first time without side effects to retrieve address and length. + * + * @param[out] p_dst_data_addr Start address of received data, if validation is successful. + * @param[out] p_data_len Expected length of received data, if validation is successful. + * + * @return Operation result. See @ref nrf_dfu_result_t + */ +nrf_dfu_result_t nrf_dfu_validation_init_cmd_execute(uint32_t * p_dst_data_addr, + uint32_t * p_data_len); + +/** + * @brief Function for validating the init command. + * + * @return Operation result. See @ref nrf_dfu_result_t. + */ +nrf_dfu_result_t nrf_dfu_validation_prevalidate(void); + +/** + * @brief Function for validating the firmware for booting. + * + * @param[in] p_validation Validation parameters. + * @param[in] data_addr Start address of the firmware. + * @param[in] data_len Length of the firmware. + * + * @return Whether the firmware is valid for booting. + */ +bool nrf_dfu_validation_boot_validate(boot_validation_t const * p_validation, uint32_t data_addr, uint32_t data_len); + +/** + * @brief Function for postvalidating the update after all data is received. + * + * @param[in] data_addr Start address of the received data. + * @param[in] data_len Length of the received data. + * + * @return Operation result. See @ref nrf_dfu_result_t. + */ +nrf_dfu_result_t nrf_dfu_validation_post_data_execute(uint32_t data_addr, uint32_t data_len); + +/** + * @brief Function for preparing the update for activation. + * + * This function is called after a reset, after all data is received. This function also runs + * @ref nrf_dfu_validation_post_data_execute internally. If this succeeds, the update is + * activated by the activation machinery in the bootloader the next time it runs. + * + * @note The caller must have permissions to edit the relevant entries in the settings. + * + * @param[in] data_addr Start address of the received data. + * @param[in] data_len Length of the received data. + * + * @return Operation result. See @ref nrf_dfu_result_t + */ +nrf_dfu_result_t nrf_dfu_validation_activation_prepare(uint32_t data_addr, uint32_t data_len); + +/** + * @brief Function to execute on a validated external app. + * + * @details This function is called once all data is received with the parameter + * @p is_boot set to false. The function is called during bootup with the parameter + * set to true. + * + * + * + * @note This function requires that @ref NRF_DFU_SUPPORTS_EXTERNAL_APP is set to 1. + * It is up to the user to implement this function. + * + * @warning Parameter @p is_trusted must be used to ensure that no loss of security of process can happen. + * This parameter should only be set if the function is called after a root-of-trust + * reset on the device. + * + * Parameter @p is_trusted can be used for the following: + * - Ensuring that an external application is run only once (after root-of-trust). + * - Ensuring that a bank flag or any other flash access can only happen after root-of-trust. + * - Ensuring that the device reaches the correct state after a power failure on the device. + * + * @param[in] p_init Init command for the firmware upgrade. + * @param[in] is_trusted Must be set to true if this is called after root-of-trust boot. + * Must be set to false if this is called from DFU mode or background + * DFU operation. + * + * @return Operation result. see @ref nrf_dfu_result_t. + */ +nrf_dfu_result_t nrf_dfu_validation_post_external_app_execute(dfu_init_command_t const * p_init, bool is_trusted); + +/** +* @brief Function to check if there is a valid external app in Bank 1. +* +* @returns True if valid external app, otherwise false. +*/ +bool nrf_dfu_validation_valid_external_app(void); + +#endif //__NRF_DFU_VALIDATION_H + +/** @} */ diff --git a/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.c b/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.c new file mode 100644 index 0000000..f9e369d --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.c @@ -0,0 +1,312 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include "nrf_dfu_types.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_utils.h" +#include "nrf_bootloader_info.h" +#include "nrf_crypto.h" +#include "nrf_assert.h" +#include "dfu-cc.pb.h" +#include "nrf_dfu_ver_validation.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_ver_validation +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +/** @brief Macro for reading the Firmware ID of a SoftDevice at a given base address. + */ +#ifndef _SD_FWID_GET +#define _SD_FWID_GET(baseaddr) SD_OFFSET_GET_UINT16(baseaddr, 0x0C) +#endif + +#define EXT_ERR(err) (nrf_dfu_result_t)((uint32_t)NRF_DFU_RES_CODE_EXT_ERROR + (uint32_t)err) + +static bool sd_req_check(uint32_t const * p_sd_req, uint8_t sd_req_cnt, bool accept_any) +{ + bool result = false; + for (uint8_t i = 0; i < sd_req_cnt; i++) + { + if ((SD_PRESENT && (p_sd_req[i] == _SD_FWID_GET(MBR_SIZE))) || + (accept_any && (p_sd_req[i] == SD_REQ_ANY_VERSION)) + ) + { + // Found a matching sd_req field. sd_req is ok. + result = true; + break; + } + } + return result; +} + + +static bool sd_req_ok(dfu_init_command_t const * p_init) +{ + ASSERT(p_init != NULL); + bool result; +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + // The bootloader needs the SoftDevice, so disabling NRF_DFU_APP_DOWNGRADE_PREVENTION + // should not be applied to SoftDevice updates. + const bool prevent_downgrade = NRF_DFU_APP_DOWNGRADE_PREVENTION || (p_init->type == DFU_FW_TYPE_SOFTDEVICE); +#else + const bool prevent_downgrade = NRF_DFU_APP_DOWNGRADE_PREVENTION; +#endif + + if (SD_PRESENT) + { + if (p_init->sd_req_count == 0) + { + result = false; + } + else if (p_init->sd_req[0] != SD_REQ_APP_OVERWRITES_SD) + { + result = sd_req_check(p_init->sd_req, + p_init->sd_req_count, + (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION)); + } + else if (p_init->type == DFU_FW_TYPE_APPLICATION) + { + // The application wants to overwrite the SoftDevice. + if (prevent_downgrade && (p_init->sd_req_count > 1) && (p_init->sd_req[0] == SD_REQ_APP_OVERWRITES_SD)) + { + // The application can overwrite the SD if sd_req[0] == 0 and table has the FWID of the current SD. + result = sd_req_check(p_init->sd_req, p_init->sd_req_count, false); + + // Prevent BLE/ANT bootloaders from allowing applications overwriting the SoftDevice. +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + result = false; +#endif + } + else + { + result = true; + } + } +#if NRF_DFU_SUPPORTS_EXTERNAL_APP + else if(p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + // Won't accept FW upgrade using external application to + // enforce replacing SoftDevice (SD_REQ_APP_OVERWRITES_SD) + result = false; + } +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + else + { + // Don't allow SoftDevice updates which assume no SD is present already. + result = !prevent_downgrade || (p_init->type != DFU_FW_TYPE_SOFTDEVICE); + } + } + + else + { + if (p_init->sd_req_count && (p_init->sd_req[0] != SD_REQ_APP_OVERWRITES_SD)) + { + // Fail if there is no SD and the update requires SD. The special "any" FWID is valid + // for external apps only. + result = false; +#if NRF_DFU_SUPPORTS_EXTERNAL_APP + result = sd_req_check(p_init->sd_req, + p_init->sd_req_count, + (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION)); +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + } + else + { + // If there is no SD and update has SD it is accepted only if it has a fw_version. + result = !prevent_downgrade || p_init->has_fw_version; + } + } + return result; +} + + +static bool fw_hash_type_ok(dfu_init_command_t const * p_init) +{ + ASSERT(p_init != NULL); + + return (p_init->hash.hash_type == DFU_HASH_TYPE_SHA256); +} + + +static bool fw_version_required(dfu_fw_type_t new_fw_type) +{ + bool result = true; + + if (new_fw_type == DFU_FW_TYPE_SOFTDEVICE) + { + result = false; // fw_version is optional in SoftDevice updates. If present, it will be checked against the app version. + } + else if (new_fw_type == DFU_FW_TYPE_APPLICATION) + { + result = NRF_DFU_APP_DOWNGRADE_PREVENTION; // fw_version is configurable in app updates. + } +#if NRF_DFU_SUPPORTS_EXTERNAL_APP +#if !NRF_DFU_EXTERNAL_APP_VERSIONING + else if (new_fw_type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + return false; + } +#endif //!NRF_DFU_EXTERNAL_APP_VERSIONING +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + + return result; +} + + +static bool fw_type_ok(dfu_init_command_t const * p_init) +{ + ASSERT(p_init != NULL); + + return ((p_init->has_type) + && ( (p_init->type == DFU_FW_TYPE_APPLICATION) + || (p_init->type == DFU_FW_TYPE_SOFTDEVICE) + || (p_init->type == DFU_FW_TYPE_BOOTLOADER) + || (p_init->type == DFU_FW_TYPE_SOFTDEVICE_BOOTLOADER) +#if NRF_DFU_SUPPORTS_EXTERNAL_APP + || (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + )); + +} + + +#ifndef NRF_DFU_APP_ACCEPT_SAME_VERSION +#define NRF_DFU_APP_ACCEPT_SAME_VERSION 1 +#endif + + +// This function assumes p_init->has_fw_version. +static bool fw_version_ok(dfu_init_command_t const * p_init) +{ + ASSERT(p_init != NULL); + ASSERT(p_init->has_fw_version); + + if ((p_init->type == DFU_FW_TYPE_APPLICATION) || + (p_init->type == DFU_FW_TYPE_SOFTDEVICE)) + { + if (!NRF_DFU_APP_DOWNGRADE_PREVENTION) + { + return true; + } + else if ((p_init->fw_version > s_dfu_settings.app_version)) + { + return true; + } + else if ((p_init->fw_version == s_dfu_settings.app_version)) + { + return NRF_DFU_APP_ACCEPT_SAME_VERSION; + } + else + { + return false; + } + } +#if NRF_DFU_SUPPORTS_EXTERNAL_APP +#if NRF_DFU_EXTERNAL_APP_VERSIONING + else if (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + return (p_init->fw_version >= s_dfu_settings.app_version); + } +#else + else if(p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + return true; + } +#endif // NRF_DFU_EXTERNAL_APP_VERSIONING +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + else + { + return (p_init->fw_version > s_dfu_settings.bootloader_version); + } +} + + +nrf_dfu_result_t nrf_dfu_ver_validation_check(dfu_init_command_t const * p_init) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + if (!fw_type_ok(p_init)) + { + NRF_LOG_ERROR("Invalid firmware type."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID); + } + else if (!fw_hash_type_ok(p_init)) + { + NRF_LOG_ERROR("Invalid hash type."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_WRONG_HASH_TYPE); + } + else if (!NRF_DFU_DEBUG || + (NRF_DFU_DEBUG && ((p_init->has_is_debug == false) || (p_init->is_debug == false)))) + { + if (p_init->has_hw_version == false) + { + NRF_LOG_ERROR("No HW version."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID); + } + else if (p_init->hw_version != NRF_DFU_HW_VERSION) + { + NRF_LOG_WARNING("Faulty HW version."); + ret_val = EXT_ERR( NRF_DFU_EXT_ERROR_HW_VERSION_FAILURE); + } + + else if (!sd_req_ok(p_init)) + { + NRF_LOG_WARNING("SD req not met."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_SD_VERSION_FAILURE); + } + else if (p_init->has_fw_version) + { + if (!fw_version_ok(p_init)) + { + NRF_LOG_WARNING("FW version too low."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_FW_VERSION_FAILURE); + } + } + else + { + if (fw_version_required(p_init->type)) + { + NRF_LOG_ERROR("FW version missing."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID); + } + } + } + return ret_val; +} diff --git a/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.h b/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.h new file mode 100644 index 0000000..3b9fbb0 --- /dev/null +++ b/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.h @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __NRF_DFU_VER_VALIDATION_H +#define __NRF_DFU_VER_VALIDATION_H + +#include "stdint.h" +#include "sdk_errors.h" +#include "nrf_dfu_handling_error.h" +#include "dfu-cc.pb.h" + +/** @brief SD_REQ field value which indicates that Softdevice can be overwritten by the application. */ +#define SD_REQ_APP_OVERWRITES_SD 0 + +/** @brief SD_REQ_ANY_VERSION field value which indicates that any SoftDevice version is valid. + * + * @note This is used by external application in case SoftDevice version compatibility isn't needed. + */ +#define SD_REQ_ANY_VERSION (0xFFFE) + +/** + * @brief Function for validating version of new firmware. + * + * @return NRF_DFU_RES_CODE_SUCCESS if successful or error code otherwise + */ +nrf_dfu_result_t nrf_dfu_ver_validation_check(dfu_init_command_t const * p_init); + +#endif //__NRF_DFU_VER_VALIDATION_H diff --git a/components/libraries/bootloader/nrf_bootloader.c b/components/libraries/bootloader/nrf_bootloader.c new file mode 100644 index 0000000..03acd7f --- /dev/null +++ b/components/libraries/bootloader/nrf_bootloader.c @@ -0,0 +1,526 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_bootloader.h" + +#include "compiler_abstraction.h" +#include "nrf.h" +#include "boards.h" +#include "sdk_config.h" +#include "nrf_power.h" +#include "nrf_delay.h" +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +#include "nrf_dfu.h" +#include "nrf_error.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_utils.h" +#include "nrf_bootloader_wdt.h" +#include "nrf_bootloader_info.h" +#include "nrf_bootloader_app_start.h" +#include "nrf_bootloader_fw_activation.h" +#include "nrf_bootloader_dfu_timers.h" +#include "app_scheduler.h" +#include "nrf_dfu_validation.h" + +static nrf_dfu_observer_t m_user_observer; //= 100) || (NRF_BL_DFU_INACTIVITY_TIMEOUT_MS == 0), + "NRF_BL_DFU_INACTIVITY_TIMEOUT_MS must be 100 ms or more, or 0 to indicate that it is disabled."); + +#if defined(NRF_LOG_BACKEND_FLASH_START_PAGE) +STATIC_ASSERT(NRF_LOG_BACKEND_FLASH_START_PAGE != 0, + "If nrf_log flash backend is used it cannot use space after code because it would collide with settings page."); +#endif + +/**@brief Weak implemenation of nrf_dfu_init + * + * @note This function will be overridden if nrf_dfu.c is + * compiled and linked with the project + */ + #if (__LINT__ != 1) +__WEAK uint32_t nrf_dfu_init(nrf_dfu_observer_t observer) +{ + NRF_LOG_DEBUG("in weak nrf_dfu_init"); + return NRF_SUCCESS; +} +#endif + + +/**@brief Weak implementation of nrf_dfu_init + * + * @note This function must be overridden in application if + * user-specific initialization is needed. + */ +__WEAK uint32_t nrf_dfu_init_user(void) +{ + NRF_LOG_DEBUG("in weak nrf_dfu_init_user"); + return NRF_SUCCESS; +} + + +static void flash_write_callback(void * p_context) +{ + UNUSED_PARAMETER(p_context); + m_flash_write_done = true; +} + + +static void do_reset(void * p_context) +{ + UNUSED_PARAMETER(p_context); + + NRF_LOG_FINAL_FLUSH(); + + nrf_delay_ms(NRF_BL_RESET_DELAY_MS); + + NVIC_SystemReset(); +} + + +static void bootloader_reset(bool do_backup) +{ + NRF_LOG_DEBUG("Resetting bootloader."); + + if (do_backup) + { + m_flash_write_done = false; + nrf_dfu_settings_backup(do_reset); + } + else + { + do_reset(NULL); + } +} + + +static void inactivity_timeout(void) +{ + NRF_LOG_INFO("Inactivity timeout."); + bootloader_reset(true); +} + + +/**@brief Function for handling DFU events. + */ +static void dfu_observer(nrf_dfu_evt_type_t evt_type) +{ + switch (evt_type) + { + case NRF_DFU_EVT_DFU_STARTED: + case NRF_DFU_EVT_OBJECT_RECEIVED: + nrf_bootloader_dfu_inactivity_timer_restart( + NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS), + inactivity_timeout); + break; + case NRF_DFU_EVT_DFU_COMPLETED: + case NRF_DFU_EVT_DFU_ABORTED: + bootloader_reset(true); + break; + case NRF_DFU_EVT_TRANSPORT_DEACTIVATED: + // Reset the internal state of the DFU settings to the last stored state. + nrf_dfu_settings_reinit(); + break; + default: + break; + } + + if (m_user_observer) + { + m_user_observer(evt_type); + } +} + + +/**@brief Function for initializing the event scheduler. + */ +static void scheduler_init(void) +{ + APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE); +} + + +/**@brief Suspend the CPU until an interrupt occurs. + */ +static void wait_for_event(void) +{ +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + (void)sd_app_evt_wait(); +#else + // Wait for an event. + __WFE(); + // Clear the internal event register. + __SEV(); + __WFE(); +#endif +} + + +/**@brief Continually sleep and process tasks whenever woken. + */ +static void loop_forever(void) +{ + while (true) + { + //feed the watchdog if enabled. + nrf_bootloader_wdt_feed(); + + app_sched_execute(); + + if (!NRF_LOG_PROCESS()) + { + wait_for_event(); + } + } +} + +#if NRF_BL_DFU_ENTER_METHOD_BUTTON +#ifndef BUTTON_PULL + #error NRF_BL_DFU_ENTER_METHOD_BUTTON is enabled but not buttons seem to be available on the board. +#endif +/**@brief Function for initializing button used to enter DFU mode. + */ +static void dfu_enter_button_init(void) +{ + nrf_gpio_cfg_sense_input(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN, + BUTTON_PULL, + NRF_GPIO_PIN_SENSE_LOW); +} +#endif + + +static bool crc_on_valid_app_required(void) +{ + bool ret = true; + if (NRF_BL_APP_CRC_CHECK_SKIPPED_ON_SYSTEMOFF_RESET && + (nrf_power_resetreas_get() & NRF_POWER_RESETREAS_OFF_MASK)) + { + nrf_power_resetreas_clear(NRF_POWER_RESETREAS_OFF_MASK); + ret = false; + } + else if (NRF_BL_APP_CRC_CHECK_SKIPPED_ON_GPREGRET2 && + ((nrf_power_gpregret2_get() & BOOTLOADER_DFU_SKIP_CRC_MASK) == BOOTLOADER_DFU_SKIP_CRC)) + { + nrf_power_gpregret2_set(nrf_power_gpregret2_get() & ~BOOTLOADER_DFU_SKIP_CRC); + ret = false; + } + else + { + } + + return ret; +} + + + +static bool boot_validate(boot_validation_t const * p_validation, uint32_t data_addr, uint32_t data_len, bool do_crc) +{ + if (!do_crc && (p_validation->type == VALIDATE_CRC)) + { + return true; + } + return nrf_dfu_validation_boot_validate(p_validation, data_addr, data_len); +} + + +/** @brief Function for checking if the main application is valid. + * + * @details This function checks if there is a valid application + * located at Bank 0. + * + * @param[in] do_crc Perform CRC check on application. Only CRC checks + can be skipped. For other boot validation types, + this parameter is ignored. + * + * @retval true If a valid application has been detected. + * @retval false If there is no valid application. + */ +static bool app_is_valid(bool do_crc) +{ + if (s_dfu_settings.bank_0.bank_code != NRF_DFU_BANK_VALID_APP) + { + NRF_LOG_INFO("Boot validation failed. No valid app to boot."); + return false; + } + else if (NRF_BL_APP_SIGNATURE_CHECK_REQUIRED && + (s_dfu_settings.boot_validation_app.type != VALIDATE_ECDSA_P256_SHA256)) + { + NRF_LOG_WARNING("Boot validation failed. The boot validation of the app must be a signature check."); + return false; + } + else if (SD_PRESENT && !boot_validate(&s_dfu_settings.boot_validation_softdevice, MBR_SIZE, s_dfu_settings.sd_size, do_crc)) + { + NRF_LOG_WARNING("Boot validation failed. SoftDevice is present but invalid."); + return false; + } + else if (!boot_validate(&s_dfu_settings.boot_validation_app, nrf_dfu_bank0_start_addr(), s_dfu_settings.bank_0.image_size, do_crc)) + { + NRF_LOG_WARNING("Boot validation failed. App is invalid."); + return false; + } + // The bootloader itself is not checked, since a self-check of this kind gives little to no benefit + // compared to the cost incurred on each bootup. + + NRF_LOG_DEBUG("App is valid"); + return true; +} + + + +/**@brief Function for clearing all DFU enter flags that + * preserve state during reset. + * + * @details This is used to make sure that each of these flags + * is checked only once after reset. + */ +static void dfu_enter_flags_clear(void) +{ + if (NRF_BL_DFU_ENTER_METHOD_PINRESET && + (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk)) + { + // Clear RESETPIN flag. + NRF_POWER->RESETREAS |= POWER_RESETREAS_RESETPIN_Msk; + } + + if (NRF_BL_DFU_ENTER_METHOD_GPREGRET && + ((nrf_power_gpregret_get() & BOOTLOADER_DFU_START_MASK) == BOOTLOADER_DFU_START)) + { + // Clear DFU mark in GPREGRET register. + nrf_power_gpregret_set(nrf_power_gpregret_get() & ~BOOTLOADER_DFU_START); + } + + if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS && + (s_dfu_settings.enter_buttonless_dfu == 1)) + { + // Clear DFU flag in flash settings. + s_dfu_settings.enter_buttonless_dfu = 0; + APP_ERROR_CHECK(nrf_dfu_settings_write(NULL)); + } +} + + +/**@brief Function for checking whether to enter DFU mode or not. + */ +static bool dfu_enter_check(void) +{ + if (!app_is_valid(crc_on_valid_app_required())) + { + NRF_LOG_DEBUG("DFU mode because app is not valid."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_BUTTON && + (nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 0)) + { + NRF_LOG_DEBUG("DFU mode requested via button."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_PINRESET && + (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk)) + { + NRF_LOG_DEBUG("DFU mode requested via pin-reset."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_GPREGRET && + ((nrf_power_gpregret_get() & BOOTLOADER_DFU_START_MASK) == BOOTLOADER_DFU_START)) + { + NRF_LOG_DEBUG("DFU mode requested via GPREGRET."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS && + (s_dfu_settings.enter_buttonless_dfu == 1)) + { + NRF_LOG_DEBUG("DFU mode requested via bootloader settings."); + return true; + } + + return false; +} + + +#if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP +static void postvalidate(void) +{ + NRF_LOG_INFO("Postvalidating update after reset."); + nrf_dfu_validation_init(); + + if (nrf_dfu_validation_init_cmd_present()) + { + uint32_t firmware_start_addr; + uint32_t firmware_size; + + // Execute a previously received init packed. Subsequent executes will have no effect. + if (nrf_dfu_validation_init_cmd_execute(&firmware_start_addr, &firmware_size) == NRF_DFU_RES_CODE_SUCCESS) + { + if (nrf_dfu_validation_prevalidate() == NRF_DFU_RES_CODE_SUCCESS) + { + if (nrf_dfu_validation_activation_prepare(firmware_start_addr, firmware_size) == NRF_DFU_RES_CODE_SUCCESS) + { + NRF_LOG_INFO("Postvalidation successful."); + } + } + } + } + + s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_0; + UNUSED_RETURN_VALUE(nrf_dfu_settings_write_and_backup(flash_write_callback)); +} +#endif + + +ret_code_t nrf_bootloader_init(nrf_dfu_observer_t observer) +{ + NRF_LOG_DEBUG("In nrf_bootloader_init"); + + ret_code_t ret_val; + nrf_bootloader_fw_activation_result_t activation_result; + uint32_t initial_timeout; + bool dfu_enter = false; + + m_user_observer = observer; + + if (NRF_BL_DEBUG_PORT_DISABLE) + { + nrf_bootloader_debug_port_disable(); + } + +#if NRF_BL_DFU_ENTER_METHOD_BUTTON + dfu_enter_button_init(); +#endif + + ret_val = nrf_dfu_settings_init(false); + if (ret_val != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + #if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP + // Postvalidate if DFU has signaled that update is ready. + if (s_dfu_settings.bank_current == NRF_DFU_CURRENT_BANK_1) + { + postvalidate(); + } + #endif + + // Check if an update needs to be activated and activate it. + activation_result = nrf_bootloader_fw_activate(); + + switch (activation_result) + { + case ACTIVATION_NONE: + initial_timeout = NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS); + dfu_enter = dfu_enter_check(); + break; + + case ACTIVATION_SUCCESS_EXPECT_ADDITIONAL_UPDATE: + initial_timeout = NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_CONTINUATION_TIMEOUT_MS); + dfu_enter = true; + break; + + case ACTIVATION_SUCCESS: + bootloader_reset(true); + NRF_LOG_ERROR("Unreachable"); + return NRF_ERROR_INTERNAL; // Should not reach this. + + case ACTIVATION_ERROR: + default: + return NRF_ERROR_INTERNAL; + } + + if (dfu_enter) + { + nrf_bootloader_wdt_init(); + scheduler_init(); + dfu_enter_flags_clear(); + + // Call user-defined init function if implemented + ret_val = nrf_dfu_init_user(); + if (ret_val != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + nrf_bootloader_dfu_inactivity_timer_restart(initial_timeout, inactivity_timeout); + + ret_val = nrf_dfu_init(dfu_observer); + if (ret_val != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + NRF_LOG_DEBUG("Enter main loop"); + loop_forever(); // This function will never return. + NRF_LOG_ERROR("Unreachable"); + } + else + { + // Erase additional data like peer data or advertisement name + ret_val = nrf_dfu_settings_additional_erase(); + if (ret_val != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + m_flash_write_done = false; + nrf_dfu_settings_backup(flash_write_callback); + ASSERT(m_flash_write_done); + + nrf_bootloader_app_start(); + NRF_LOG_ERROR("Unreachable"); + } + + // Should not be reached. + return NRF_ERROR_INTERNAL; +} diff --git a/components/libraries/bootloader/nrf_bootloader.h b/components/libraries/bootloader/nrf_bootloader.h new file mode 100644 index 0000000..77bf4f2 --- /dev/null +++ b/components/libraries/bootloader/nrf_bootloader.h @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * + * @defgroup nrf_bootloader Bootloader modules + * @{ + * @ingroup app_common + * @brief Bootloader and DFU modules + * + * The bootloader module can be used to implement a basic bootloader that + * can be extended with, for example, Device Firmware Update (DFU) support + * or custom functionality. + */ + +#ifndef NRF_BOOTLOADER_H__ +#define NRF_BOOTLOADER_H__ + +#include +#include "nrf_dfu.h" +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Function for initializing the bootloader. + * + * @details This function is the entry point of all bootloader operations. + * If DFU functionality is compiled in, the DFU process is initialized + * when running this function. + * + * @note This function does not return unless an error occurred. + * + * @retval NRF_ERROR_INTERNAL Something went wrong. + */ +ret_code_t nrf_bootloader_init(nrf_dfu_observer_t observer); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_BOOTLOADER_H__ +/** @} */ diff --git a/components/libraries/bootloader/nrf_bootloader_app_start.c b/components/libraries/bootloader/nrf_bootloader_app_start.c new file mode 100644 index 0000000..07e5591 --- /dev/null +++ b/components/libraries/bootloader/nrf_bootloader_app_start.c @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include "nrf.h" +#include "nrf_bootloader_app_start.h" +#include "nrf_bootloader_info.h" +#include "nrf_log.h" +#include "nrf_dfu_mbr.h" +#include "nrf_log_ctrl.h" +#include "nrf_bootloader_info.h" + +// Do the final stages of app_start. Protect flash and run app. See nrf_bootloader_app_start_final.c +void nrf_bootloader_app_start_final(uint32_t start_addr); + +void nrf_bootloader_app_start(void) +{ + uint32_t start_addr = MBR_SIZE; // Always boot from end of MBR. If a SoftDevice is present, it will boot the app. + NRF_LOG_DEBUG("Running nrf_bootloader_app_start with address: 0x%08x", start_addr); + uint32_t err_code; + + // Disable and clear interrupts + // Notice that this disables only 'external' interrupts (positive IRQn). + NRF_LOG_DEBUG("Disabling interrupts. NVIC->ICER[0]: 0x%x", NVIC->ICER[0]); + + NVIC->ICER[0]=0xFFFFFFFF; + NVIC->ICPR[0]=0xFFFFFFFF; +#if defined(__NRF_NVIC_ISER_COUNT) && __NRF_NVIC_ISER_COUNT == 2 + NVIC->ICER[1]=0xFFFFFFFF; + NVIC->ICPR[1]=0xFFFFFFFF; +#endif + + err_code = nrf_dfu_mbr_irq_forward_address_set(); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed running nrf_dfu_mbr_irq_forward_address_set()"); + } + + NRF_LOG_FLUSH(); + nrf_bootloader_app_start_final(start_addr); +} diff --git a/components/libraries/bootloader/nrf_bootloader_app_start.h b/components/libraries/bootloader/nrf_bootloader_app_start.h new file mode 100644 index 0000000..e8b1104 --- /dev/null +++ b/components/libraries/bootloader/nrf_bootloader_app_start.h @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_bootloader_app Application start + * @{ + * @ingroup nrf_bootloader + */ + +#ifndef NRF_BOOTLOADER_APP_START_H__ +#define NRF_BOOTLOADER_APP_START_H__ + +#include +#include +#include "sdk_errors.h" + + +/**@brief Function for using hardware to protect flash from writing and reading. + * + * @details This function applies write/erase protection to a specific area, using the BPROT or ACL + * peripheral, depending on which is available. + * + * @param[in] address The start address of the area to protect. Must be a flash page + * boundary. + * @param[in] size The size of the area to protect, in bytes. Must be a multiple + * of flash page size. + * + * @retval NRF_SUCCESS Flash protection applied successfully. + * @retval NRF_ERROR_NO_MEM No more ACL instances to use for flash protection. + * @retval NRF_ERROR_INVALID_PARAM Address was out of range or size was not a multiple + * of flash page size. + */ +ret_code_t nrf_bootloader_flash_protect(uint32_t address, uint32_t size); + +/**@brief Function for starting another application (and aborting the current one). + * + * @details This function uses the provided address to swap the stack pointer and then load + * the address of the reset handler to be executed. It checks the current system mode + * (thread/handler). If in thread mode, it resets into the other application. + * If in handler mode, isr_abort is executed to ensure that handler mode is left correctly. + * It then jumps into the reset handler of the other application. + * + * @note This function assumes the SoftDevice has not previously been initialized. + * + * @note This function will never return, but issues a reset into the provided application. + */ +void nrf_bootloader_app_start(void); + +#endif // NRF_BOOTLOADER_APP_START_H__ + +/** @} */ diff --git a/components/libraries/bootloader/nrf_bootloader_app_start_final.c b/components/libraries/bootloader/nrf_bootloader_app_start_final.c new file mode 100644 index 0000000..31ffa70 --- /dev/null +++ b/components/libraries/bootloader/nrf_bootloader_app_start_final.c @@ -0,0 +1,188 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_config.h" +#include "nrf_bootloader_app_start.h" +#include +#include "nrf.h" +#include "nrf_peripherals.h" +#include "nrf_bootloader_info.h" +#include "nrf_dfu_types.h" +#include "nrf_dfu_utils.h" +#include "nrf_dfu_settings.h" +#include "nrf_assert.h" +#include "nrf_log.h" +#include "sdk_config.h" + + +#define HANDLER_MODE_EXIT 0xFFFFFFF9 // When this is jumped to, the CPU will exit interrupt context + // (handler mode), and pop values from the stack into registers. + // See ARM's documentation for "Exception entry and return". +#define EXCEPTION_STACK_WORD_COUNT 8 // The number of words popped from the stack when + // HANDLER_MODE_EXIT is branched to. + + +/**@brief Function that sets the stack pointer and starts executing a particular address. + * + * @param[in] new_msp The new value to set in the main stack pointer. + * @param[in] addr The address to execute. + */ +void jump_to_addr(uint32_t new_msp, uint32_t addr) +{ + __set_MSP(new_msp); + ((void (*)(void))addr)(); +} + + +/**@brief Function for booting an app as if the chip was reset. + * + * @param[in] vector_table_addr The address of the app's vector table. + */ +__STATIC_INLINE void app_start(uint32_t vector_table_addr) +{ + const uint32_t current_isr_num = (__get_IPSR() & IPSR_ISR_Msk); + const uint32_t new_msp = *((uint32_t *)(vector_table_addr)); // The app's Stack Pointer is found as the first word of the vector table. + const uint32_t reset_handler = *((uint32_t *)(vector_table_addr + sizeof(uint32_t))); // The app's Reset Handler is found as the second word of the vector table. + + __set_CONTROL(0x00000000); // Set CONTROL to its reset value 0. + __set_PRIMASK(0x00000000); // Set PRIMASK to its reset value 0. + __set_BASEPRI(0x00000000); // Set BASEPRI to its reset value 0. + __set_FAULTMASK(0x00000000); // Set FAULTMASK to its reset value 0. + + ASSERT(current_isr_num == 0); // If this is triggered, the CPU is currently in an interrupt. + + // The CPU is in Thread mode (main context). + jump_to_addr(new_msp, reset_handler); // Jump directly to the App's Reset Handler. +} + + +ret_code_t nrf_bootloader_flash_protect(uint32_t address, uint32_t size) +{ + if ((size & (CODE_PAGE_SIZE - 1)) || (address > BOOTLOADER_SETTINGS_ADDRESS)) + { + return NRF_ERROR_INVALID_PARAM; + } + +#if defined(ACL_PRESENT) + + // Protect using ACL. + static uint32_t acl_instance = 0; + + uint32_t const mask = (ACL_ACL_PERM_WRITE_Disable << ACL_ACL_PERM_WRITE_Pos); + + if (acl_instance >= ACL_REGIONS_COUNT) + { + return NRF_ERROR_NO_MEM; + } + + NRF_ACL->ACL[acl_instance].ADDR = address; + NRF_ACL->ACL[acl_instance].SIZE = size; + NRF_ACL->ACL[acl_instance].PERM = mask; + + acl_instance++; + +#elif defined (BPROT_PRESENT) + + // Protect using BPROT. BPROT does not support read protection. + uint32_t pagenum_start = address / CODE_PAGE_SIZE; + uint32_t pagenum_end = pagenum_start + ((size - 1) / CODE_PAGE_SIZE); + + for (uint32_t i = pagenum_start; i <= pagenum_end; i++) + { + uint32_t config_index = i / 32; + uint32_t mask = (1 << (i - config_index * 32)); + + switch (config_index) + { + case 0: + NRF_BPROT->CONFIG0 = mask; + break; + case 1: + NRF_BPROT->CONFIG1 = mask; + break; +#if BPROT_REGIONS_NUM > 64 + case 2: + NRF_BPROT->CONFIG2 = mask; + break; + case 3: + NRF_BPROT->CONFIG3 = mask; + break; +#endif + } + } + +#endif + + return NRF_SUCCESS; +} + + +void nrf_bootloader_app_start_final(uint32_t vector_table_addr) +{ + ret_code_t ret_val; + + // Size of the flash area to protect. + uint32_t area_size; + + area_size = BOOTLOADER_SIZE + NRF_MBR_PARAMS_PAGE_SIZE; + if (!NRF_BL_DFU_ALLOW_UPDATE_FROM_APP && !NRF_BL_DFU_ENTER_METHOD_BUTTONLESS && !NRF_DFU_TRANSPORT_BLE) + { + area_size += BOOTLOADER_SETTINGS_PAGE_SIZE; + } + + ret_val = nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR, area_size); + + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not protect bootloader and settings pages, 0x%x.", ret_val); + } + APP_ERROR_CHECK(ret_val); + + ret_val = nrf_bootloader_flash_protect(0, + nrf_dfu_bank0_start_addr() + ALIGN_TO_PAGE(s_dfu_settings.bank_0.image_size)); + + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not protect SoftDevice and application, 0x%x.", ret_val); + } + APP_ERROR_CHECK(ret_val); + + // Run application + app_start(vector_table_addr); +} diff --git a/components/libraries/bootloader/nrf_bootloader_dfu_timers.c b/components/libraries/bootloader/nrf_bootloader_dfu_timers.c new file mode 100644 index 0000000..d9d19d4 --- /dev/null +++ b/components/libraries/bootloader/nrf_bootloader_dfu_timers.c @@ -0,0 +1,268 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_bootloader_dfu_timers.h" + +#include +#include +#include +#include "nrf_clock.h" +#include "nrf_rtc.h" +#include "nrf_delay.h" +#include "nrf_log.h" + + +#define RTC_PRESCALER (0) //!< The value provided to the RTC as the prescaler. 0 corresponds to one tick per clock cycle of the LFCLK (32768 ticks/s). +#define RTC_WRAP_TICKS ((1 << 24) - 1) //!< The largest possible value in the RTC counter register. +#define MAX_TIMEOUT_TICKS (RTC_WRAP_TICKS) //!< The longest fire timeout allowed. Longer timeouts are handled by multiple firings. + +typedef struct +{ + nrf_bootloader_dfu_timeout_callback_t callback; //!< Callback that is called when this timer times out. + uint32_t timeout; //!< The number of ticks from the next firing until the actual timeout. This value will be different from 0 if the original timeout was longer than MAX_TIMEOUT_TICKS, so multiple firings were needed. + uint32_t repeated_timeout; //!< If different from 0, this timer will be reactivated with this value after timing out. + uint8_t cc_channel; //!< Which CC register this timer uses. +} dfu_timer_t; + + +dfu_timer_t m_timers[2] = {{.cc_channel = 0}, {.cc_channel = 1}}; //!< The timers used by this module. +dfu_timer_t * mp_inactivity = &m_timers[0]; //!< Direct pointer to the inactivity timer, for convenience and readability. +dfu_timer_t * mp_wdt_feed = &m_timers[1]; //!< Direct pointer to the wdt feed timer, for convenience and readability. +uint32_t m_counter_loops = 0; //!< The number of times the RTC counter register has overflowed (wrapped around) since the RTC was started. + +#if RTC_COUNT > 2 +#define RTC_INSTANCE 2 +#define RTC_STRUCT NRF_RTC2 +#define RTC_IRQHandler RTC2_IRQHandler +#define RTC_IRQn RTC2_IRQn +#define RTC_CC_COUNT NRF_RTC_CC_CHANNEL_COUNT(2)) +#elif RTC_COUNT > 1 +#define RTC_INSTANCE 1 +#define RTC_STRUCT NRF_RTC1 +#define RTC_IRQHandler RTC1_IRQHandler +#define RTC_IRQn RTC1_IRQn +#define RTC_CC_COUNT NRF_RTC_CC_CHANNEL_COUNT(1)) +#else +#error Not enough RTC instances. +#endif + +/**@brief Function for initializing the timer if it is not already initialized. + */ +static void timer_init(void) +{ + static bool m_timer_initialized; + + if (!m_timer_initialized) + { + if (!nrf_clock_lf_is_running()) + { + nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART); + } + + nrf_rtc_event_clear(RTC_STRUCT, NRF_RTC_EVENT_TICK); + nrf_rtc_event_clear(RTC_STRUCT, NRF_RTC_EVENT_COMPARE_0); + nrf_rtc_event_clear(RTC_STRUCT, NRF_RTC_EVENT_COMPARE_1); + NRFX_IRQ_PRIORITY_SET(RTC_IRQn, 5); + NRFX_IRQ_ENABLE(RTC_IRQn); + nrf_rtc_prescaler_set(RTC_STRUCT, RTC_PRESCALER); + nrf_rtc_task_trigger(RTC_STRUCT, NRF_RTC_TASK_CLEAR); + nrf_rtc_task_trigger(RTC_STRUCT, NRF_RTC_TASK_START); + nrf_rtc_int_enable(RTC_STRUCT, RTC_INTENSET_OVRFLW_Msk); + + m_timer_initialized = true; + } +} + +/**@brief Function for scheduling an RTC compare event. + * + * @param[in] cc_channel Which of the RTC compare registers to use. + * @param[in] cc_value The ticks value at which to receive the event. + */ +static void rtc_update(uint32_t cc_channel, uint32_t cc_value) +{ + ASSERT(cc_channel < NRF_RTC_CC_CHANNEL_COUNT(RTC_INSTANCE)); + + nrf_rtc_cc_set(RTC_STRUCT, cc_channel, cc_value); + nrf_delay_us(31); + nrf_rtc_event_clear(RTC_STRUCT, RTC_CHANNEL_EVENT_ADDR(cc_channel)); + nrf_rtc_int_enable(RTC_STRUCT, RTC_CHANNEL_INT_MASK(cc_channel)); +} + + +/**@brief Function for activating a timer, so that it will be fired. + * + * This can happen multiple times before the actual timeout happens if the timeout is longer than + * @ref MAX_TIMEOUT_TICKS. + * + * @param[in] p_timer The timer to activate. + * @param[in] timeout_ticks The number of ticks until the timeout. + * + * @retval true If the timer was activated. + * @retval false If the timer is already active. + */ +static void timer_activate(dfu_timer_t * p_timer, uint32_t timeout_ticks) +{ + NRF_LOG_DEBUG("timer_activate (0x%x)", p_timer); + + ASSERT(timeout_ticks <= MAX_TIMEOUT_TICKS); + ASSERT(timeout_ticks >= NRF_BOOTLOADER_MIN_TIMEOUT_TICKS); + uint32_t next_timeout_ticks = MIN(timeout_ticks, MAX_TIMEOUT_TICKS); + uint32_t cc_value = RTC_WRAP(next_timeout_ticks + nrf_rtc_counter_get(RTC_STRUCT)); + p_timer->timeout = timeout_ticks - next_timeout_ticks; + + if ((p_timer->timeout > 0) && (p_timer->timeout < NRF_BOOTLOADER_MIN_TIMEOUT_TICKS)) + { + p_timer->timeout += NRF_BOOTLOADER_MIN_TIMEOUT_TICKS; + cc_value -= NRF_BOOTLOADER_MIN_TIMEOUT_TICKS; + } + + rtc_update(p_timer->cc_channel, cc_value); +} + + +/**@brief Function for deactivating a timer, so that it will not fire. + * + * @param[in] p_timer The timer to deactivate. + * + * @retval true If the timer was deactivated. + * @retval false If the timer is already inactive. + */ +static void timer_stop(dfu_timer_t * p_timer) +{ + NRF_LOG_DEBUG("timer_stop (0x%x)", p_timer); + nrf_rtc_int_disable(RTC_STRUCT, RTC_CHANNEL_INT_MASK(p_timer->cc_channel)); +} + + +/**@brief Function for firing a timer. + * + * This can happen multiple times before the actual timeout happens if the timeout is longer than + * @ref MAX_TIMEOUT_TICKS. + * This function reactivates the timer if the timer is repeating, or if the timer has not yet + * timed out. It then calls the callback if the timer (repeating or not) has timed out. + * + * @param[in] p_timer The timer to fire. + */ +static void timer_fire(dfu_timer_t * p_timer) +{ + NRF_LOG_DEBUG("timer_fire (0x%x)", p_timer); + + if (p_timer->timeout != 0) + { + // The timer has not yet timed out. + timer_activate(p_timer, p_timer->timeout); + return; + } + + if (p_timer->repeated_timeout != 0) + { + timer_activate(p_timer, p_timer->repeated_timeout); + } + + if (p_timer->callback != NULL) + { + p_timer->callback(); + } +} + + +/**@brief Function for requesting a timeout. + * + * The timer will time out @p timeout_ticks ticks from now. When it times out, @p callback + * will be called, and if @p p_timer->repeated_timeout is not 0, a new timeout will be scheduled. + * + * @param[in] p_timer The timer to start. + * @param[in] timeout_ticks The number of ticks until the timeout. + * @param[in] callback The callback to call when the timer times out. + */ +static void timer_start(dfu_timer_t * p_timer, + uint32_t timeout_ticks, + nrf_bootloader_dfu_timeout_callback_t callback) +{ + timer_init(); // Initialize if needed. + p_timer->callback = callback; + timer_activate(p_timer, timeout_ticks); +} + + +/**@brief Interrupt handler for the RTC (Real Time Clock) used for the DFU timers. + */ +void RTC_IRQHandler(void) +{ + if (nrf_rtc_event_pending(RTC_STRUCT, NRF_RTC_EVENT_OVERFLOW)) + { + m_counter_loops++; + nrf_rtc_event_clear(RTC_STRUCT, NRF_RTC_EVENT_OVERFLOW); + } + + for (uint32_t channel = 0; channel < 2; channel++) + { + if (nrf_rtc_event_pending(RTC_STRUCT, RTC_CHANNEL_EVENT_ADDR(channel))) + { + nrf_rtc_event_clear(RTC_STRUCT, RTC_CHANNEL_EVENT_ADDR(channel)); + timer_stop(&m_timers[channel]); + timer_fire(&m_timers[channel]); + } + } +} + + +void nrf_bootloader_dfu_inactivity_timer_restart(uint32_t timeout_ticks, + nrf_bootloader_dfu_timeout_callback_t callback) +{ + timer_stop(mp_inactivity); + if (timeout_ticks != 0) + { + timer_start(mp_inactivity, timeout_ticks, callback); + } +} + + +void nrf_bootloader_wdt_feed_timer_start(uint32_t timeout_ticks, + nrf_bootloader_dfu_timeout_callback_t callback) +{ + mp_wdt_feed->repeated_timeout = timeout_ticks; + timer_start(mp_wdt_feed, timeout_ticks, callback); +} + + +uint32_t nrf_bootloader_dfu_timer_counter_get(void) +{ + return nrf_rtc_counter_get(RTC_STRUCT) + (m_counter_loops << 24); +} diff --git a/components/libraries/bootloader/nrf_bootloader_dfu_timers.h b/components/libraries/bootloader/nrf_bootloader_dfu_timers.h new file mode 100644 index 0000000..6dd64dc --- /dev/null +++ b/components/libraries/bootloader/nrf_bootloader_dfu_timers.h @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_bootloader_dfu_timers Timers for DFU in the bootloader + * @{ + * @ingroup nrf_bootloader + */ + +#ifndef NRF_BOOTLOADER_DFU_TIMERS_H__ +#define NRF_BOOTLOADER_DFU_TIMERS_H__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define NRF_BOOTLOADER_MIN_TIMEOUT_TICKS (150) //!< The shortest timeout allowed. To avoid the timeout not being activated before the time has passed. + +/**@brief Macro for converting milliseconds to timer ticks. + * + * @param[in] ms The milliseconds to convert. + * + * @return @p ms converted to ticks. + */ +#define NRF_BOOTLOADER_MS_TO_TICKS(ms) ((((uint64_t)(ms) * 32768)) / 1000) + +/**@brief Handler called on timeout of a timer requested by the watchdog. + */ +typedef void (*nrf_bootloader_dfu_timeout_callback_t)(void); + + +/**@brief Function for restarting the inactivity timer. + * + * @note Calling this function cancels any previous calls to this function. + * + * @param[in] timeout_ticks The number of ticks until reset. There are 32768 ticks per second. + * If 0 is passed, the timer will be stopped and not restarted. + * @param[in] callback Function to be called on timeout. + */ +void nrf_bootloader_dfu_inactivity_timer_restart(uint32_t timeout_ticks, + nrf_bootloader_dfu_timeout_callback_t callback); + + +/**@brief Function for initializing and starting a repeated timer for feeding the watchdog. + * + * @param[in] timeout_ticks The number of ticks between each feeding of the watchdog. There are + * 32768 ticks per second. + * @param[in] callback Function called on every timeout. + */ +void nrf_bootloader_wdt_feed_timer_start(uint32_t timeout_ticks, + nrf_bootloader_dfu_timeout_callback_t callback); + + +/**@brief Function for retrieving the number of ticks since the RTC was started. + * + * There are 32768 ticks per second. This value does not wrap, even when the RTC counter wraps. + * + * @note The value can be 2^24 ticks too small if sampled immediately after the RTC counter wraps, + * but before the internal loop counter has been incremented. + * + * @return The number of ticks since the RTC was started. + */ +uint32_t nrf_bootloader_dfu_timer_counter_get(void); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_BOOTLOADER_DFU_TIMERS_H__ + +/** @} */ diff --git a/components/libraries/bootloader/nrf_bootloader_fw_activation.c b/components/libraries/bootloader/nrf_bootloader_fw_activation.c new file mode 100644 index 0000000..364f21c --- /dev/null +++ b/components/libraries/bootloader/nrf_bootloader_fw_activation.c @@ -0,0 +1,441 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_bootloader_fw_activation.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_mbr.h" +#include "nrf_bootloader_info.h" +#include "crc32.h" +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +#include "nrf_dfu_utils.h" +#include "nrf_bootloader_wdt.h" + + +static volatile bool m_flash_write_done; + + +/** + * @brief Function for copying image. Image is copied in chunks. Frequency of storing progress + * in flash is configured by input parameter. + * + * @param[in] dst_addr Destination address. Must be page aligned. + * @param[in] src_addr Source address. Must be higher value than dst_addr. + * @param[in] size Image size. + * @param[in] progress_update_step Number of copied pages that triggers saving progress to non-volatile memory. + * Note that step can be decreased if there is a risk of corruption caused by source + * and destination overlapping. + * + * @return NRF_SUCCESS or error code in case of failure. + */ +static uint32_t image_copy(uint32_t dst_addr, + uint32_t src_addr, + uint32_t size, + uint32_t progress_update_step) +{ + if (src_addr == dst_addr) + { + NRF_LOG_DEBUG("No copy needed"); + return NRF_SUCCESS; + } + + ASSERT(src_addr >= dst_addr); + ASSERT(progress_update_step > 0); + if (size != 0) + { + ASSERT((dst_addr % CODE_PAGE_SIZE) == 0); + } + + uint32_t max_safe_progress_upd_step = (src_addr - dst_addr)/CODE_PAGE_SIZE; + ASSERT(max_safe_progress_upd_step > 0); + + uint32_t ret_val = NRF_SUCCESS; + uint32_t pages_left = CEIL_DIV(size, CODE_PAGE_SIZE); + + //Firmware copying is time consuming operation thus watchdog handling is started + nrf_bootloader_wdt_init(); + + progress_update_step = MIN(progress_update_step, max_safe_progress_upd_step); + + while (size > 0) + { + uint32_t pages; + uint32_t bytes; + if (pages_left <= progress_update_step) + { + pages = pages_left; + bytes = size; + } + else + { + pages = progress_update_step; + bytes = progress_update_step * CODE_PAGE_SIZE; + } + // Erase the target pages + ret_val = nrf_dfu_flash_erase(dst_addr, pages, NULL); + if (ret_val != NRF_SUCCESS) + { + return ret_val; + } + + // Flash one page + NRF_LOG_DEBUG("Copying 0x%x to 0x%x, size: 0x%x", src_addr, dst_addr, bytes); + ret_val = nrf_dfu_flash_store(dst_addr, + (uint32_t *)src_addr, + ALIGN_NUM(sizeof(uint32_t), bytes), + NULL); + if (ret_val != NRF_SUCCESS) + { + return ret_val; + } + + pages_left -= pages; + size -= bytes; + dst_addr += bytes; + src_addr += bytes; + s_dfu_settings.write_offset += bytes; + + //store progress in flash on every successful chunk write + ret_val = nrf_dfu_settings_write_and_backup(NULL); + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed to write image copying progress to settings page."); + return ret_val; + } + } + + return ret_val; +} + +/** @brief Function to continue application update. + * + * @details This function will be called after reset if there is a valid application in Bank1 + * required to be copied down to Bank 0. + * + * @return NRF_SUCCESS if continuation was successful, NRF_ERROR_INTERNAL if new firmware does not + * contain softdevice or other error coming from modules used by this function. + */ +static uint32_t app_activate(void) +{ + // This function is only in use when new app is present in Bank 1 + uint32_t const image_size = s_dfu_settings.bank_1.image_size; + + uint32_t src_addr = s_dfu_settings.progress.update_start_address; + uint32_t ret_val = NRF_SUCCESS; + uint32_t target_addr = nrf_dfu_bank0_start_addr() + s_dfu_settings.write_offset; + uint32_t length_left = (image_size - s_dfu_settings.write_offset); + uint32_t crc; + + NRF_LOG_DEBUG("Enter nrf_dfu_app_continue"); + + src_addr += s_dfu_settings.write_offset; + + if (src_addr == target_addr) + { + length_left = 0; + } + + ret_val = image_copy(target_addr, src_addr, length_left, NRF_BL_FW_COPY_PROGRESS_STORE_STEP); + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed to copy firmware."); + return ret_val; + } + + // Check the CRC of the copied data. Enable if so. + crc = crc32_compute((uint8_t*)nrf_dfu_bank0_start_addr(), image_size, NULL); + + if (crc == s_dfu_settings.bank_1.image_crc) + { + NRF_LOG_DEBUG("Setting app as valid"); + s_dfu_settings.bank_0.bank_code = NRF_DFU_BANK_VALID_APP; + s_dfu_settings.bank_0.image_crc = crc; + s_dfu_settings.bank_0.image_size = image_size; + } + else + { + NRF_LOG_ERROR("CRC computation failed for copied app: " + "src crc: 0x%08x, res crc: 0x%08x", + s_dfu_settings.bank_1.image_crc, + crc); + } + + return ret_val; +} + + +/** @brief Function to execute the continuation of a SoftDevice update. + * + * @return NRF_SUCCESS if continuation was successful, NRF_ERROR_INTERNAL if new firmware does not + * contain softdevice or other error coming from modules used by this function. + */ +static uint32_t sd_activate(void) +{ + uint32_t ret_val = NRF_SUCCESS; + uint32_t target_addr = nrf_dfu_softdevice_start_address() + s_dfu_settings.write_offset; + uint32_t src_addr = s_dfu_settings.progress.update_start_address; + uint32_t sd_size = s_dfu_settings.sd_size; + uint32_t length_left = ALIGN_TO_PAGE(sd_size - s_dfu_settings.write_offset); + + NRF_LOG_DEBUG("Enter nrf_bootloader_dfu_sd_continue"); + + if (SD_MAGIC_NUMBER_GET(src_addr) != SD_MAGIC_NUMBER) + { + NRF_LOG_ERROR("Source address does not contain a valid SoftDevice.") + return NRF_ERROR_INTERNAL; + } + + // This can be a continuation due to a power failure + src_addr += s_dfu_settings.write_offset; + + if (s_dfu_settings.write_offset == sd_size) + { + NRF_LOG_DEBUG("SD already copied"); + return NRF_SUCCESS; + } + + if (s_dfu_settings.write_offset == 0) + { + NRF_LOG_DEBUG("Updating SD. Old SD ver: %d, New ver: %d", + SD_VERSION_GET(MBR_SIZE) / 1000000, SD_VERSION_GET(src_addr) / 1000000); + } + + ret_val = image_copy(target_addr, src_addr, length_left, NRF_BL_FW_COPY_PROGRESS_STORE_STEP); + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed to copy firmware."); + return ret_val; + } + + ret_val = nrf_dfu_settings_write_and_backup(NULL); + + return ret_val; +} + + +/** @brief Function to continue bootloader update. + * + * @details This function will be called after reset if there is a valid bootloader in Bank 0 or Bank 1 + * required to be relocated and activated through MBR commands. + * + * @return This function will not return if the bootloader is copied successfully. + * After the copy is verified, the device will reset and start the new bootloader. + * + * @retval NRF_SUCCESS Continuation was successful. + * @retval NRF_ERROR_INVALID_LENGTH Invalid length of flash operation. + * @retval NRF_ERROR_NO_MEM If no parameter page is provided (see sds for more info). + * @retval NRF_ERROR_INVALID_PARAM If an invalid command is given. + * @retval NRF_ERROR_INTERNAL Internal error that should not happen. + * @retval NRF_ERROR_FORBIDDEN If NRF_UICR->BOOTADDR is not set. + */ +static uint32_t bl_activate(void) +{ + uint32_t ret_val = NRF_ERROR_INVALID_DATA; + nrf_dfu_bank_t * p_bank = &s_dfu_settings.bank_1; + uint32_t len = p_bank->image_size; + uint32_t src_addr = s_dfu_settings.progress.update_start_address; + + if (p_bank->bank_code == NRF_DFU_BANK_VALID_SD_BL) + { + src_addr += s_dfu_settings.sd_size; + len -= s_dfu_settings.sd_size; + } + else if (src_addr == 0) + { + src_addr = nrf_dfu_bank1_start_addr(); + } + + NRF_LOG_DEBUG("Verifying BL: Addr: 0x%08x, Src: 0x%08x, Len: 0x%08x", BOOTLOADER_START_ADDR, src_addr, len); + + // This code is a configurable workaround for updating SD+BL from SDK 12.x.y - 14.1.0 + // SoftDevice size increase would lead to unaligned source address when comparing new BL in SD+BL updates. + // This workaround is not required once BL is successfully installed with a version that is compiled SDK 14.1.0 +#if defined(NRF52832_XXAA) && defined(BLE_STACK_SUPPORT_REQD) + if ((p_bank->bank_code == NRF_DFU_BANK_VALID_SD_BL) && + (memcmp((void *)BOOTLOADER_START_ADDR, (void *)(src_addr - 0x4000), len) == 0)) + { + ret_val = NRF_SUCCESS; + } +#endif // defined(NRF52832_XXAA) + + // Check if the BL has already been copied. + if ((ret_val != NRF_SUCCESS) && + (memcmp((void *)BOOTLOADER_START_ADDR, (void *)src_addr, len) == 0)) + { + ret_val = NRF_SUCCESS; + } + + // If the bootloader is the same as the banked version, the copy is finished + if (ret_val == NRF_SUCCESS) + { + NRF_LOG_DEBUG("No bootloader copy needed, bootloader update complete."); + } + else + { + NRF_LOG_DEBUG("Copying bootloader: Src: 0x%08x, Len: 0x%08x", src_addr, len); + NRF_LOG_FLUSH(); + + nrf_bootloader_wdt_feed(); + + // Bootloader is different than the banked version. Continue copy + // Note that if the SD and BL was combined, then the split point between them is in s_dfu_settings.sd_size + // On success this function won't return. + ret_val = nrf_dfu_mbr_copy_bl((uint32_t*)src_addr, len); + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_ERROR("Request to copy BL failed"); + } + } + + return ret_val; +} + + +/** @brief Function to continue combined bootloader and SoftDevice update. + * + * @details This function will be called after reset if there is a valid bootloader and SoftDevice in Bank 0 or Bank 1 + * required to be relocated and activated through MBR commands. + * + * @retval NRF_SUCCESS Continuation was successful. + * @retval NRF_ERROR_INVALID_LENGTH Invalid length. + * @retval NRF_ERROR_NO_MEM If UICR.NRFFW[1] is not set (i.e. is 0xFFFFFFFF). + * @retval NRF_ERROR_INVALID_PARAM If an invalid command is given. + * @retval NRF_ERROR_INTERNAL Indicates that the contents of the memory blocks where not verified correctly after copying. + * @retval NRF_ERROR_NULL If the content of the memory blocks differs after copying. + * @retval NRF_ERROR_FORBIDDEN If NRF_UICR->BOOTADDR is not set. + */ +static uint32_t sd_bl_activate() +{ + uint32_t ret_val = NRF_SUCCESS; + + NRF_LOG_DEBUG("Enter nrf_dfu_sd_bl_continue"); + + ret_val = sd_activate(); + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_ERROR("SD+BL: SD copy failed"); + return ret_val; + } + + ret_val = bl_activate(); + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_ERROR("SD+BL: BL copy failed"); + return ret_val; + } + + return ret_val; +} + + +static void flash_write_callback(void * p_context) +{ + UNUSED_PARAMETER(p_context); + m_flash_write_done = true; +} + + +nrf_bootloader_fw_activation_result_t nrf_bootloader_fw_activate(void) +{ + nrf_bootloader_fw_activation_result_t result; + uint32_t ret_val = NRF_SUCCESS; + nrf_dfu_bank_t * p_bank = &s_dfu_settings.bank_1; + bool sd_update = false; + + NRF_LOG_DEBUG("Enter nrf_bootloader_fw_activate"); + + switch (p_bank->bank_code) + { + case NRF_DFU_BANK_VALID_APP: + NRF_LOG_DEBUG("Valid App"); + ret_val = app_activate(); + break; + case NRF_DFU_BANK_VALID_SD: + NRF_LOG_DEBUG("Valid SD"); + ret_val = sd_activate(); + sd_update = true; + break; + case NRF_DFU_BANK_VALID_BL: + NRF_LOG_DEBUG("Valid BL"); + ret_val = bl_activate(); + break; + case NRF_DFU_BANK_VALID_SD_BL: + NRF_LOG_DEBUG("Valid SD + BL"); + ret_val = sd_bl_activate(); + sd_update = true; + break; + case NRF_DFU_BANK_INVALID: + default: + NRF_LOG_INFO("No firmware to activate."); + return ACTIVATION_NONE; + } + + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_ERROR("Activation failed with error %d (bank code: 0x%x)", ret_val, p_bank->bank_code); + result = ACTIVATION_ERROR; + } + + // Invalidate bank, marking completion. + nrf_dfu_bank_invalidate(p_bank); + + m_flash_write_done = false; + ret_val = nrf_dfu_settings_write_and_backup(flash_write_callback); + ASSERT(m_flash_write_done); /* At this point flash module is performing blocking operation. It is expected that operation is already performed. */ + + if (ret_val == NRF_SUCCESS) + { + result = ACTIVATION_SUCCESS; + if (sd_update && (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP)) + { + //If SD was updated and application is valid we want to stay in DFU to receive application. + NRF_LOG_DEBUG("A SoftDevice has just been activated. It's likely that an application will come immediately"); + result = ACTIVATION_SUCCESS_EXPECT_ADDITIONAL_UPDATE; + } + } + else + { + NRF_LOG_ERROR("Could not write settings."); + result = ACTIVATION_ERROR; + } + + return result; +} + diff --git a/components/libraries/bootloader/nrf_bootloader_fw_activation.h b/components/libraries/bootloader/nrf_bootloader_fw_activation.h new file mode 100644 index 0000000..797c5e9 --- /dev/null +++ b/components/libraries/bootloader/nrf_bootloader_fw_activation.h @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_bootloader_fw_activation Firmware activation + * @{ + * @ingroup nrf_bootloader + */ + +#ifndef NRF_BOOTLOADER_FW_ACTIVATION_H__ +#define NRF_BOOTLOADER_FW_ACTIVATION_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef enum +{ + ACTIVATION_NONE, //!< No new update was found. + ACTIVATION_SUCCESS, //!< Update was successfully activated. + ACTIVATION_SUCCESS_EXPECT_ADDITIONAL_UPDATE, //!< Update was successfully activated, but there might be additional update(s) to be transferred. + ACTIVATION_ERROR, //!< Activation of an update failed. +} nrf_bootloader_fw_activation_result_t; + +/** @brief Function for activating a firmware received during DFU. + * + * @details This function initiates or continues the DFU copy-back + * routines. These routines are fail-safe operations to activate + * either a new SoftDevice, bootloader, combination of SoftDevice and + * bootloader, or a new application. + * + * @details This function relies on accessing MBR commands through supervisor calls. + * It does not rely on the SoftDevice for flash operations. + * + * @note When updating the bootloader or both bootloader and SoftDevice in combination, + * this function does not return, but rather initiates a reboot to activate + * the new bootloader. + * + * @retval ACTIVATION_NONE If no update was found. + * @retval ACTIVATION_SUCCESS If the firmware update was successfully activated. + * @retval ACTIVATION_SUCCESS_EXPECT_ADDITIONAL_UPDATE If the firmware update was successfully activated, + * but there are likely more updates to be transferred. + * @retval ACTIVATION_ERROR If the firmware update could not be activated. + */ +nrf_bootloader_fw_activation_result_t nrf_bootloader_fw_activate(void); + + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_BOOTLOADER_FW_ACTIVATION_H__ + +/** @} */ diff --git a/components/libraries/bootloader/nrf_bootloader_info.c b/components/libraries/bootloader/nrf_bootloader_info.c new file mode 100644 index 0000000..5228cca --- /dev/null +++ b/components/libraries/bootloader/nrf_bootloader_info.c @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_bootloader_info.h" +#include "nrf_dfu_types.h" +#include "nrf_nvmc.h" + +#define UICR_BOOTLOADER_ADDR 0x10001014 + +/** @brief This variable ensures that the linker script will write the bootloader start address + * to the UICR register. This value will be written in the HEX file and thus written to + * UICR when the bootloader is flashed into the chip. + */ +#if defined (__CC_ARM ) + #pragma push + #pragma diag_suppress 1296 + uint32_t m_uicr_bootloader_start_address __attribute__((at(UICR_BOOTLOADER_ADDR))) + = BOOTLOADER_START_ADDR; + #pragma pop +#elif defined ( __GNUC__ ) || defined ( __SES_ARM ) + volatile uint32_t m_uicr_bootloader_start_address __attribute__ ((section(".uicr_bootloader_start_address"))) + = BOOTLOADER_START_ADDR; +#elif defined ( __ICCARM__ ) + __root const uint32_t m_uicr_bootloader_start_address @ UICR_BOOTLOADER_ADDR + = BOOTLOADER_START_ADDR; +#endif + +void nrf_bootloader_mbr_addrs_populate(void) +{ + if (*(const uint32_t *)MBR_BOOTLOADER_ADDR == 0xFFFFFFFF) + { + nrf_nvmc_write_word(MBR_BOOTLOADER_ADDR, BOOTLOADER_START_ADDR); + } + if (*(const uint32_t *)MBR_PARAM_PAGE_ADDR == 0xFFFFFFFF) + { + nrf_nvmc_write_word(MBR_PARAM_PAGE_ADDR, NRF_MBR_PARAMS_PAGE_ADDRESS); + } +} + + +void nrf_bootloader_debug_port_disable(void) +{ + if (NRF_UICR->APPROTECT != 0x0) + { + nrf_nvmc_write_word((uint32_t)&NRF_UICR->APPROTECT, 0x0); + NVIC_SystemReset(); + } +#if (!defined (NRF52810_XXAA) && !defined (NRF52811_XXAA) && !defined (NRF52832_XXAA) && !defined (NRF52832_XXAB)) + if (NRF_UICR->DEBUGCTRL != 0x0) + { + nrf_nvmc_write_word((uint32_t)&NRF_UICR->DEBUGCTRL, 0x0); + NVIC_SystemReset(); + } +#endif +} diff --git a/components/libraries/bootloader/nrf_bootloader_info.h b/components/libraries/bootloader/nrf_bootloader_info.h new file mode 100644 index 0000000..d1fa89b --- /dev/null +++ b/components/libraries/bootloader/nrf_bootloader_info.h @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_bootloader_info Bootloader Information + * @{ + * @ingroup nrf_bootloader + */ + +#ifndef NRF_BOOTLOADER_INFO_H__ +#define NRF_BOOTLOADER_INFO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "app_util.h" +#include "nrf.h" +#include "nrf_mbr.h" + +/** @brief Macro for getting the start address of the bootloader image. + * + * The macro is not a compile time symbol. It cannot be used as a + * constant expression, for example, inside a static assert or linker script + * at-placement. + */ +#ifndef BOOTLOADER_START_ADDR +#if (__LINT__ == 1) + #define BOOTLOADER_START_ADDR (0x3AC00) +#elif defined(CODE_START) + #define BOOTLOADER_START_ADDR (CODE_START) +#else + #error Not a valid compiler/linker for BOOTLOADER_START_ADDR. +#endif +#endif + + +/** @brief Macro for getting the size of the bootloader image. + */ +#ifndef BOOTLOADER_SIZE +#if (__LINT__ == 1) + #define BOOTLOADER_SIZE (0x6000) +#elif defined ( NRF51 ) + #define BOOTLOADER_SIZE (BOOTLOADER_SETTINGS_ADDRESS - BOOTLOADER_START_ADDR) +#elif defined( NRF52_SERIES ) + #define BOOTLOADER_SIZE (NRF_MBR_PARAMS_PAGE_ADDRESS - BOOTLOADER_START_ADDR) +#endif +#endif + +// The following macros are for accessing the SoftDevice information structure, +// which is found inside the SoftDevice binary. + +/** @brief Macro for converting an offset inside the SoftDevice information struct to an absolute address. + */ +#define SD_INFO_ABS_OFFSET_GET(baseaddr, offset) ((baseaddr) + (SOFTDEVICE_INFO_STRUCT_OFFSET) + (offset)) + +/** @brief Macros for reading a byte or a word at a particular offset inside a SoftDevice information struct. + * Use MBR_SIZE as baseaddr when the SoftDevice is installed just above the MBR (the usual case). + */ +#define SD_OFFSET_GET_UINT32(baseaddr, offset) (*((uint32_t *) SD_INFO_ABS_OFFSET_GET(baseaddr, offset))) +#define SD_OFFSET_GET_UINT16(baseaddr, offset) (*((uint16_t *) SD_INFO_ABS_OFFSET_GET(baseaddr, offset))) +#define SD_OFFSET_GET_UINT8(baseaddr, offset) (*((uint8_t *) SD_INFO_ABS_OFFSET_GET(baseaddr, offset))) + + +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) +#include "nrf_sdm.h" +#else +/** @brief The offset inside the SoftDevice at which the information struct is placed. + * To see the layout of the information struct, see the SoftDevice specification. + */ +#define SOFTDEVICE_INFO_STRUCT_OFFSET (0x2000) + +#define SD_INFO_STRUCT_SIZE(baseaddr) SD_OFFSET_GET_UINT8(baseaddr, 0x00) + +/** @brief Macro for reading the size of a SoftDevice at a given base address. + */ +#ifndef SD_SIZE_GET +#define SD_SIZE_GET(baseaddr) SD_OFFSET_GET_UINT32(baseaddr, 0x08) +#endif + +/** @brief Macro for reading the version of a SoftDevice at a given base address. + * This expression checks the length of the information struct to see if the version is present. + * The version number is constructed like this: + * major_version * 1000000 + minor_version * 1000 + bugfix_version + */ +#ifndef SD_VERSION_GET +#define SD_VERSION_GET(baseaddr) ((SD_INFO_STRUCT_SIZE(baseaddr) > (0x14)) \ + ? SD_OFFSET_GET_UINT32(baseaddr, 0x14) \ + : 0) +#endif + +/** @brief Defines a macro for retrieving the actual SoftDevice ID from a given base address. Use + * @ref MBR_SIZE as the argument when the SoftDevice is installed just above the MBR (the + * usual case). */ +#ifndef SD_ID_GET +#define SD_ID_GET(baseaddr) ((SD_INFO_STRUCT_SIZE(baseaddr) > 0x10) \ + ? SD_OFFSET_GET_UINT32(baseaddr, 0x10) : 0) +#endif +#endif + + +/** @brief Macro for reading the magic number of a SoftDevice at a given base address. + */ +#ifndef SD_MAGIC_NUMBER_GET +#define SD_MAGIC_NUMBER_GET(baseaddr) SD_OFFSET_GET_UINT32(baseaddr, 0x04) +#endif + +/** @brief Macro for getting the absolute address of the magic number. + */ +#define SD_MAGIC_NUMBER_ABS_OFFSET_GET(baseaddr) SD_INFO_ABS_OFFSET_GET(baseaddr, 0x04) + +/** @brief The number present at a specific location in all SoftDevices. + */ +#define SD_MAGIC_NUMBER ((uint32_t)0x51B1E5DB) + +/** @brief Whether a SoftDevice is at its regular location. + */ +#ifndef SD_PRESENT +#define SD_PRESENT ((SD_MAGIC_NUMBER_GET(MBR_SIZE)) == (SD_MAGIC_NUMBER)) +#endif + +/** @brief The multiplier for the major version of the SoftDevice. See \ref SD_VERSION_GET + */ +#define SD_MAJOR_VERSION_MULTIPLIER (1000000) + +/** @brief Read the major version of the SoftDevice from the raw version number. See \ref SD_VERSION_GET. + */ +#define SD_MAJOR_VERSION_EXTRACT(raw_version) ((raw_version)/SD_MAJOR_VERSION_MULTIPLIER) + + +#define BOOTLOADER_DFU_GPREGRET_MASK (0xF8) /**< Mask for GPGPREGRET bits used for the magic pattern written to GPREGRET register to signal between main app and DFU. */ +#define BOOTLOADER_DFU_GPREGRET (0xB0) /**< Magic pattern written to GPREGRET register to signal between main app and DFU. The 3 lower bits are assumed to be used for signalling purposes.*/ +#define BOOTLOADER_DFU_START_BIT_MASK (0x01) /**< Bit mask to signal from main application to enter DFU mode using a buttonless service. */ + +#define BOOTLOADER_DFU_GPREGRET2_MASK (0xF8) /**< Mask for GPGPREGRET2 bits used for the magic pattern written to GPREGRET2 register to signal between main app and DFU. */ +#define BOOTLOADER_DFU_GPREGRET2 (0xA8) /**< Magic pattern written to GPREGRET2 register to signal between main app and DFU. The 3 lower bits are assumed to be used for signalling purposes.*/ +#define BOOTLOADER_DFU_SKIP_CRC_BIT_MASK (0x01) /**< Bit mask to signal from main application that CRC-check is not needed for image verification. */ + + +#define BOOTLOADER_DFU_START_MASK (BOOTLOADER_DFU_GPREGRET_MASK | BOOTLOADER_DFU_START_BIT_MASK) +#define BOOTLOADER_DFU_START (BOOTLOADER_DFU_GPREGRET | BOOTLOADER_DFU_START_BIT_MASK) /**< Magic number to signal that bootloader should enter DFU mode because of signal from Buttonless DFU in main app.*/ +#define BOOTLOADER_DFU_SKIP_CRC_MASK (BOOTLOADER_DFU_GPREGRET2_MASK | BOOTLOADER_DFU_SKIP_CRC_BIT_MASK) +#define BOOTLOADER_DFU_SKIP_CRC (BOOTLOADER_DFU_GPREGRET2 | BOOTLOADER_DFU_SKIP_CRC_BIT_MASK) /**< Magic number to signal that CRC can be skipped due to low power modes.*/ + + +/** @brief Macro based on @c NRF_DFU_DEBUG_VERSION that can be checked for true/false instead of defined/not defined. + */ +#ifndef NRF_DFU_DEBUG +#ifdef NRF_DFU_DEBUG_VERSION +#define NRF_DFU_DEBUG 1 +#else +#define NRF_DFU_DEBUG 0 +#endif +#endif + +/** @brief Function for populating addresses in the MBR code page. + * + * This function writes two words to flash if the flash is 0xFFFFFFFF. This is done in code because + * doing this through the hex file interferes with flashing algorithms. See nrf_mbr.h. + */ +void nrf_bootloader_mbr_addrs_populate(void); + +/** @brief Function for checking if the debug port access is disabled. + * + * If the debug port access is enabled, disable it. This function checks and writes to the UICR + * registers APPROTECT and DEBUGCTRL. + */ +void nrf_bootloader_debug_port_disable(void); + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef NRF_BOOTLOADER_INFO_H__ +/** @} */ diff --git a/components/libraries/bootloader/nrf_bootloader_wdt.c b/components/libraries/bootloader/nrf_bootloader_wdt.c new file mode 100644 index 0000000..e8db157 --- /dev/null +++ b/components/libraries/bootloader/nrf_bootloader_wdt.c @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_bootloader_wdt.h" +#include "nrf_wdt.h" +#include "nrf_bootloader_dfu_timers.h" +#include "nrf_log_ctrl.h" + +#define NRF_LOG_MODULE_NAME nrf_bootloader_wdt +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +static void wdt_feed(void) +{ + if (nrf_wdt_started()) + { + for (nrf_wdt_rr_register_t i = NRF_WDT_RR0; i < NRF_WDT_RR7; i++) + { + if (nrf_wdt_reload_request_is_enabled(i)) + { + nrf_wdt_reload_request_set(i); + } + } + } +} + + +static void wdt_feed_timer_handler(void) +{ + NRF_LOG_INFO("Internal feed"); + wdt_feed(); +} + + +void WDT_IRQHandler(void) +{ + nrf_wdt_event_clear(NRF_WDT_EVENT_TIMEOUT); + NRF_LOG_FINAL_FLUSH(); +} + +#define MAX_FLASH_OP_TIME_TICKS 3200 // ~100 ms + +void nrf_bootloader_wdt_init(void) +{ + static bool initialized = false; + + if (initialized) + { + return; + } + + if (nrf_wdt_started()) + { + uint32_t wdt_ticks = nrf_wdt_reload_value_get(); + + NRF_LOG_INFO("WDT enabled CRV:%d ticks", wdt_ticks); + + //wdt_ticks must be reduced to feed the watchdog before the timeout. + uint32_t reduced_timeout_ticks = MAX((int32_t)wdt_ticks - MAX_FLASH_OP_TIME_TICKS, + NRF_BOOTLOADER_MIN_TIMEOUT_TICKS); + + /* initial watchdog feed */ + wdt_feed(); + + NRF_LOG_INFO("Starting a timer (%d ticks) for feeding watchdog.", reduced_timeout_ticks); + nrf_bootloader_wdt_feed_timer_start(reduced_timeout_ticks, wdt_feed_timer_handler); + + NVIC_EnableIRQ(WDT_IRQn); + } + else + { + NRF_LOG_INFO("WDT is not enabled"); + } + + initialized = true; +} + +void nrf_bootloader_wdt_feed(void) +{ + if (nrf_wdt_started()) + { + wdt_feed(); + } +} diff --git a/components/libraries/bootloader/nrf_bootloader_wdt.h b/components/libraries/bootloader/nrf_bootloader_wdt.h new file mode 100644 index 0000000..27b72a5 --- /dev/null +++ b/components/libraries/bootloader/nrf_bootloader_wdt.h @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_BOOTLOADER_WDT_H +#define NRF_BOOTLOADER_WDT_H + +/**@file + * + * @defgroup nrf_bootloader_wdt Automated feeding of the watchdog + * @{ + * @ingroup nrf_bootloader + * @brief Module that keeps the WDT from timing out if the WDT has been started in the application. + */ + +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @brief Function for checking whether the WDT peripheral is started and for getting its configuration. + * + * The module uses a timer to start regular feeding of the watchdog. Timer interval + * is chosen based on watchdog settings. When @ref nrf_bootloader_wdt_feed is called, internal + * feeding is stopped assuming that the application takes responsibity of watchdog feeding. + * However, if @ref NRF_BL_WDT_MAX_SCHEDULER_LATENCY_MS or the watchdog is configured to + * run during sleep, then internal feeding (from timeout handler context) is kept active. + */ +void nrf_bootloader_wdt_init(void); + + +/** + * @brief Function for feeding the watchdog (if active). + */ +void nrf_bootloader_wdt_feed(void); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif //NRF_BOOTLOADER_WDT_H diff --git a/components/libraries/bootloader/serial_dfu/nrf_dfu_serial.c b/components/libraries/bootloader/serial_dfu/nrf_dfu_serial.c new file mode 100644 index 0000000..70ed176 --- /dev/null +++ b/components/libraries/bootloader/serial_dfu/nrf_dfu_serial.c @@ -0,0 +1,273 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_dfu_serial.h" +#include "nrf_dfu_req_handler.h" +#include "nrf_dfu_handling_error.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_serial +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define NRF_SERIAL_OPCODE_SIZE (sizeof(uint8_t)) + +#if defined(NRF_DFU_PROTOCOL_REDUCED) && NRF_DFU_PROTOCOL_REDUCED + #error Serial DFU (UART and USB) cannot function with the reduced protocol set. +#endif + +static uint32_t response_ext_err_payload_add(uint8_t * p_buffer, uint32_t buf_offset) +{ + p_buffer[buf_offset] = ext_error_get(); + (void) ext_error_set(NRF_DFU_EXT_ERROR_NO_ERROR); + + return 1; +} + + +static void response_send(nrf_dfu_serial_t * p_transport, + nrf_dfu_response_t const * p_response) +{ + uint8_t index = 0; + uint8_t * p_serialized_rsp = p_transport->p_rsp_buf; + + NRF_LOG_DEBUG("Sending Response: [0x%01x, 0x%01x]", p_response->request, p_response->result); + + p_serialized_rsp[index++] = NRF_DFU_OP_RESPONSE; + p_serialized_rsp[index++] = p_response->request; + p_serialized_rsp[index++] = (uint8_t)(p_response->result); + + if (p_response->result == NRF_DFU_RES_CODE_SUCCESS) + { + switch (p_response->request) + { + case NRF_DFU_OP_PROTOCOL_VERSION: + { + p_serialized_rsp[index] = p_response->protocol.version; + index += sizeof(uint8_t); + } break; + + case NRF_DFU_OP_HARDWARE_VERSION: + { + index += uint32_encode(p_response->hardware.part, &p_serialized_rsp[index]); + index += uint32_encode(p_response->hardware.variant, &p_serialized_rsp[index]); + index += uint32_encode(p_response->hardware.memory.rom_size, &p_serialized_rsp[index]); + index += uint32_encode(p_response->hardware.memory.ram_size, &p_serialized_rsp[index]); + index += uint32_encode(p_response->hardware.memory.rom_page_size, &p_serialized_rsp[index]); + } break; + + case NRF_DFU_OP_FIRMWARE_VERSION: + { + p_serialized_rsp[index++] = p_response->firmware.type; + index += uint32_encode(p_response->firmware.version, &p_serialized_rsp[index]); + index += uint32_encode(p_response->firmware.addr, &p_serialized_rsp[index]); + index += uint32_encode(p_response->firmware.len, &p_serialized_rsp[index]); + } break; + + case NRF_DFU_OP_CRC_GET: + index += uint32_encode(p_response->crc.offset, &p_serialized_rsp[index]); + index += uint32_encode(p_response->crc.crc, &p_serialized_rsp[index]); + break; + + case NRF_DFU_OP_OBJECT_SELECT: + index += uint32_encode(p_response->select.max_size, &p_serialized_rsp[index]); + index += uint32_encode(p_response->select.offset, &p_serialized_rsp[index]); + index += uint32_encode(p_response->select.crc, &p_serialized_rsp[index]); + break; + + case NRF_DFU_OP_MTU_GET: + index += uint16_encode(p_response->mtu.size, &p_serialized_rsp[index]); + break; + + case NRF_DFU_OP_PING: + p_serialized_rsp[index] = p_response->ping.id; + index += sizeof(uint8_t); + break; + + default: + // no implementation + break; + } + } + else if (p_response->result == NRF_DFU_RES_CODE_EXT_ERROR) + { + index += response_ext_err_payload_add(p_serialized_rsp, index); + } + + if (index > NRF_SERIAL_MAX_RESPONSE_SIZE) + { + NRF_LOG_ERROR("Message is larger than expected."); + } + + // Send response. + if (p_transport->rsp_func((uint8_t const *)(p_serialized_rsp), index) != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed to send data over serial interface!"); + } +} + + +void dfu_req_handler_rsp_clbk(nrf_dfu_response_t * p_res, void * p_context) +{ + nrf_dfu_serial_t * p_transport = (nrf_dfu_serial_t *)(p_context); + + if (p_res->result != NRF_DFU_RES_CODE_SUCCESS) + { + NRF_LOG_WARNING("DFU request completed with result: 0x%x", p_res->result); + } + + switch (p_res->request) + { + default: + /* Reply normally. + * Make sure to reply to NRF_DFU_OP_OBJECT_CREATE when running DFU over serial, + * otherwise the transfer might run very slow, without an apparent reason. + */ + break; + + case NRF_DFU_OP_OBJECT_WRITE: + { + p_transport->pkt_notif_target_count--; + + if ( (p_transport->pkt_notif_target == 0) + || (p_transport->pkt_notif_target_count != 0)) + { + /* Do not reply to _OBJECT_WRITE messages. */ + return; + } + + /* Reply with a CRC message and reset the packet counter. */ + p_transport->pkt_notif_target_count = p_transport->pkt_notif_target; + + p_res->request = NRF_DFU_OP_CRC_GET; + p_res->crc.offset = p_res->write.offset; + p_res->crc.crc = p_res->write.crc; + } break; + } + + response_send(p_transport, p_res); +} + + +void nrf_dfu_serial_on_packet_received(nrf_dfu_serial_t * p_transport, + uint8_t const * p_data, + uint32_t length) +{ + uint8_t const * p_payload = &p_data[NRF_SERIAL_OPCODE_SIZE]; + uint16_t const payload_len = (length - NRF_SERIAL_OPCODE_SIZE); + + nrf_dfu_request_t request = + { + .request = (nrf_dfu_op_t)(p_data[0]), + .callback.response = dfu_req_handler_rsp_clbk, + .p_context = p_transport + }; + + bool buf_free = true; + + switch (request.request) + { + case NRF_DFU_OP_FIRMWARE_VERSION: + { + request.firmware.image_number = p_payload[0]; + } break; + + case NRF_DFU_OP_RECEIPT_NOTIF_SET: + { + NRF_LOG_DEBUG("Set receipt notif target: %d", p_transport->pkt_notif_target); + + p_transport->pkt_notif_target = uint16_decode(&p_payload[0]); + p_transport->pkt_notif_target_count = p_transport->pkt_notif_target; + } break; + + case NRF_DFU_OP_OBJECT_SELECT: + { + request.select.object_type = p_payload[0]; + } break; + + case NRF_DFU_OP_OBJECT_CREATE: + { + // Reset the packet receipt notification on create object + p_transport->pkt_notif_target_count = p_transport->pkt_notif_target; + + request.create.object_type = p_payload[0]; + request.create.object_size = uint32_decode(&p_payload[1]); + + if (request.create.object_type == NRF_DFU_OBJ_TYPE_COMMAND) + { + /* Activity on the current transport. Close all except the current one. */ + (void) nrf_dfu_transports_close(p_transport->p_low_level_transport); + } + } break; + + case NRF_DFU_OP_OBJECT_WRITE: + { + // Buffer will be freed asynchronously + buf_free = false; + + request.write.p_data = p_payload; + request.write.len = payload_len; + request.callback.write = p_transport->payload_free_func; + } break; + + case NRF_DFU_OP_MTU_GET: + { + NRF_LOG_DEBUG("Received serial mtu"); + request.mtu.size = p_transport->mtu; + } break; + + case NRF_DFU_OP_PING: + { + NRF_LOG_DEBUG("Received ping %d", p_payload[0]); + request.ping.id = p_payload[0]; + } break; + + default: + /* Do nothing. */ + break; + } + + if (buf_free) + { + p_transport->payload_free_func((void *)(p_payload)); + } + + ret_code_t ret_code = nrf_dfu_req_handler_on_req(&request); + ASSERT(ret_code == NRF_SUCCESS); +} diff --git a/components/libraries/bootloader/serial_dfu/nrf_dfu_serial.h b/components/libraries/bootloader/serial_dfu/nrf_dfu_serial.h new file mode 100644 index 0000000..32006a8 --- /dev/null +++ b/components/libraries/bootloader/serial_dfu/nrf_dfu_serial.h @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DFU_SERIAL_H__ +#define NRF_DFU_SERIAL_H__ + +#include +#include "sdk_errors.h" +#include "nrf_dfu_req_handler.h" +#include "nrf_dfu_transport.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/**@file + * + * @defgroup nrf_dfu_serial DFU Serial transports shared part + * @{ + * @ingroup nrf_dfu + * @brief Shared part of Device Firmware Update (DFU) transport layers using serial interface (UART, USB CDC ACM). + * + * @defgroup nrf_dfu_serial_uart DFU Serial UART transport + * @ingroup nrf_dfu_serial + * @brief Configuration for Device Firmware Update (DFU) transport layer using UART. + * + * @defgroup nrf_dfu_serial_usb DFU Serial USB CDC ACM transport + * @ingroup nrf_dfu_serial + * @brief Configuration for Device Firmware Update (DFU) transport layer using USB CDC ACM. + * + */ + +#define NRF_SERIAL_MAX_RESPONSE_SIZE (sizeof(nrf_dfu_response_t)) + +/** + * Prototype for function for sending response over serial DFU transport. + */ +typedef ret_code_t (*nrf_serial_rsp_func_t)(uint8_t const * p_data, uint32_t length); + +/** + * Prototype for function for freeing RX buffer. + * + * Function is called when input data is processed. + */ +typedef void (*nrf_serial_rx_buf_free_func_t)(void * p_buf); + + +/**@brief DFU serial transport layer state. + * + * @details This structure contains status information related to the serial transport layer type. + */ +typedef struct +{ + uint16_t pkt_notif_target; + uint16_t pkt_notif_target_count; + nrf_serial_rsp_func_t rsp_func; + nrf_serial_rx_buf_free_func_t payload_free_func; + uint32_t mtu; + uint8_t * p_rsp_buf; + nrf_dfu_transport_t const * p_low_level_transport; +} nrf_dfu_serial_t; + +void nrf_dfu_serial_on_packet_received(nrf_dfu_serial_t * p_transport, + uint8_t const * p_data, + uint32_t length); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_SERIAL_H__ diff --git a/components/libraries/bootloader/serial_dfu/nrf_dfu_serial_uart.c b/components/libraries/bootloader/serial_dfu/nrf_dfu_serial_uart.c new file mode 100644 index 0000000..f83e810 --- /dev/null +++ b/components/libraries/bootloader/serial_dfu/nrf_dfu_serial_uart.c @@ -0,0 +1,238 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_dfu_serial.h" + +#include +#include "boards.h" +#include "app_util_platform.h" +#include "nrf_dfu_transport.h" +#include "nrf_dfu_req_handler.h" +#include "slip.h" +#include "nrf_balloc.h" +#include "nrf_drv_uart.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_serial_uart +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/**@file + * + * @defgroup nrf_dfu_serial_uart DFU Serial UART transport + * @ingroup nrf_dfu + * @brief Device Firmware Update (DFU) transport layer using UART. + */ + +#define NRF_SERIAL_OPCODE_SIZE (sizeof(uint8_t)) +#define NRF_UART_MAX_RESPONSE_SIZE_SLIP (2 * NRF_SERIAL_MAX_RESPONSE_SIZE + 1) +#define RX_BUF_SIZE (64) //to get 64bytes payload +#define OPCODE_OFFSET (sizeof(uint32_t) - NRF_SERIAL_OPCODE_SIZE) +#define DATA_OFFSET (OPCODE_OFFSET + NRF_SERIAL_OPCODE_SIZE) +#define UART_SLIP_MTU (2 * (RX_BUF_SIZE + 1) + 1) +#define BALLOC_BUF_SIZE ((CEIL_DIV((RX_BUF_SIZE+OPCODE_SIZE),sizeof(uint32_t))*sizeof(uint32_t))) + +NRF_BALLOC_DEF(m_payload_pool, (UART_SLIP_MTU + 1), NRF_DFU_SERIAL_UART_RX_BUFFERS); + +static nrf_drv_uart_t m_uart = NRF_DRV_UART_INSTANCE(0); +static uint8_t m_rx_byte; + +static nrf_dfu_serial_t m_serial; +static slip_t m_slip; +static uint8_t m_rsp_buf[NRF_UART_MAX_RESPONSE_SIZE_SLIP]; +static bool m_active; + +static nrf_dfu_observer_t m_observer; + +static uint32_t uart_dfu_transport_init(nrf_dfu_observer_t observer); +static uint32_t uart_dfu_transport_close(nrf_dfu_transport_t const * p_exception); + +DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const uart_dfu_transport) = +{ + .init_func = uart_dfu_transport_init, + .close_func = uart_dfu_transport_close, +}; + +static void payload_free(void * p_buf) +{ + uint8_t * p_buf_root = (uint8_t *)p_buf - DATA_OFFSET; //pointer is shifted to point to data + nrf_balloc_free(&m_payload_pool, p_buf_root); +} + +static ret_code_t rsp_send(uint8_t const * p_data, uint32_t length) +{ + uint32_t slip_len; + (void) slip_encode(m_rsp_buf, (uint8_t *)p_data, length, &slip_len); + + return nrf_drv_uart_tx(&m_uart, m_rsp_buf, slip_len); +} + +static __INLINE void on_rx_complete(nrf_dfu_serial_t * p_transport, uint8_t * p_data, uint8_t len) +{ + ret_code_t ret_code = NRF_ERROR_TIMEOUT; + + // Check if there is byte to process. Zero length transfer means that RXTO occured. + if (len) + { + ret_code = slip_decode_add_byte(&m_slip, p_data[0]); + } + + (void) nrf_drv_uart_rx(&m_uart, &m_rx_byte, 1); + + if (ret_code == NRF_SUCCESS) + { + nrf_dfu_serial_on_packet_received(p_transport, + (uint8_t const *)m_slip.p_buffer, + m_slip.current_index); + + uint8_t * p_rx_buf = nrf_balloc_alloc(&m_payload_pool); + if (p_rx_buf == NULL) + { + NRF_LOG_ERROR("Failed to allocate buffer"); + return; + } + NRF_LOG_INFO("Allocated buffer %x", p_rx_buf); + // reset the slip decoding + m_slip.p_buffer = &p_rx_buf[OPCODE_OFFSET]; + m_slip.current_index = 0; + m_slip.state = SLIP_STATE_DECODING; + } + +} + +static void uart_event_handler(nrf_drv_uart_event_t * p_event, void * p_context) +{ + switch (p_event->type) + { + case NRF_DRV_UART_EVT_RX_DONE: + on_rx_complete((nrf_dfu_serial_t*)p_context, + p_event->data.rxtx.p_data, + p_event->data.rxtx.bytes); + break; + + case NRF_DRV_UART_EVT_ERROR: + APP_ERROR_HANDLER(p_event->data.error.error_mask); + break; + + default: + // No action. + break; + } +} + +static uint32_t uart_dfu_transport_init(nrf_dfu_observer_t observer) +{ + uint32_t err_code = NRF_SUCCESS; + + if (m_active) + { + return err_code; + } + + NRF_LOG_DEBUG("serial_dfu_transport_init()"); + + m_observer = observer; + + err_code = nrf_balloc_init(&m_payload_pool); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + uint8_t * p_rx_buf = nrf_balloc_alloc(&m_payload_pool); + + m_slip.p_buffer = &p_rx_buf[OPCODE_OFFSET]; + m_slip.current_index = 0; + m_slip.buffer_len = UART_SLIP_MTU; + m_slip.state = SLIP_STATE_DECODING; + + m_serial.rsp_func = rsp_send; + m_serial.payload_free_func = payload_free; + m_serial.mtu = UART_SLIP_MTU; + m_serial.p_rsp_buf = &m_rsp_buf[NRF_UART_MAX_RESPONSE_SIZE_SLIP - + NRF_SERIAL_MAX_RESPONSE_SIZE]; + m_serial.p_low_level_transport = &uart_dfu_transport; + + nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG; + + uart_config.pseltxd = TX_PIN_NUMBER; + uart_config.pselrxd = RX_PIN_NUMBER; + uart_config.pselcts = CTS_PIN_NUMBER; + uart_config.pselrts = RTS_PIN_NUMBER; + uart_config.hwfc = NRF_DFU_SERIAL_UART_USES_HWFC ? + NRF_UART_HWFC_ENABLED : NRF_UART_HWFC_DISABLED; + uart_config.p_context = &m_serial; + + err_code = nrf_drv_uart_init(&m_uart, &uart_config, uart_event_handler); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed initializing uart"); + return err_code; + } + + err_code = nrf_drv_uart_rx(&m_uart, &m_rx_byte, 1); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed initializing rx"); + } + + NRF_LOG_DEBUG("serial_dfu_transport_init() completed"); + + m_active = true; + + if (m_observer) + { + m_observer(NRF_DFU_EVT_TRANSPORT_ACTIVATED); + } + + return err_code; +} + + +static uint32_t uart_dfu_transport_close(nrf_dfu_transport_t const * p_exception) +{ + if ((m_active == true) && (p_exception != &uart_dfu_transport)) + { + nrf_drv_uart_uninit(&m_uart); + m_active = false; + } + + return NRF_SUCCESS; +} + diff --git a/components/libraries/bootloader/serial_dfu/nrf_dfu_serial_usb.c b/components/libraries/bootloader/serial_dfu/nrf_dfu_serial_usb.c new file mode 100644 index 0000000..6e51bcc --- /dev/null +++ b/components/libraries/bootloader/serial_dfu/nrf_dfu_serial_usb.c @@ -0,0 +1,368 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include "nrf_dfu_req_handler.h" +#include "nrf_dfu_transport.h" +#include "slip.h" +#include "nrf_balloc.h" +#include "nrf_drv_power.h" +#include "nrf_drv_clock.h" +#include "nrf_drv_usbd.h" +#include "nrf_dfu_serial.h" +#include "app_scheduler.h" +#include "app_usbd.h" +#include "app_usbd_cdc_acm.h" +#include "app_usbd_core.h" +#include "app_usbd_string_desc.h" +#include "app_util_platform.h" +#include "app_usbd_serial_num.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_serial_usb +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/**@file + * + * @defgroup nrf_dfu_serial_usb DFU Serial USB CDC ACM transport + * @ingroup nrf_dfu + * @brief Device Firmware Update (DFU) transport layer using USB CDC ACM. + */ + +#define NRF_SERIAL_OPCODE_SIZE (sizeof(uint8_t)) + +#define NRF_USB_MAX_RESPONSE_SIZE_SLIP (2 * NRF_SERIAL_MAX_RESPONSE_SIZE + 1) + +#define RX_BUF_SIZE (1024) +#define SLIP_MTU (2 * (RX_BUF_SIZE + 1) + 1) +#define OPCODE_OFFSET (sizeof(uint32_t) - NRF_SERIAL_OPCODE_SIZE) +#define DATA_OFFSET (OPCODE_OFFSET + NRF_SERIAL_OPCODE_SIZE) + +#define CDC_ACM_COMM_INTERFACE 0 +#define CDC_ACM_COMM_EPIN NRF_DRV_USBD_EPIN2 +#define CDC_ACM_DATA_INTERFACE 1 +#define CDC_ACM_DATA_EPIN NRF_DRV_USBD_EPIN1 +#define CDC_ACM_DATA_EPOUT NRF_DRV_USBD_EPOUT1 + +/** + * @brief Enable power USB detection + * + * Configure if example supports USB port connection + */ +#ifndef USBD_POWER_DETECTION +#define USBD_POWER_DETECTION true +#endif + +/** + * @brief Interfaces list passed to @ref APP_USBD_CDC_ACM_GLOBAL_DEF + * */ +#define CDC_ACM_INTERFACES_CONFIG() \ + APP_USBD_CDC_ACM_CONFIG(CDC_ACM_COMM_INTERFACE, \ + CDC_ACM_COMM_EPIN, \ + CDC_ACM_DATA_INTERFACE, \ + CDC_ACM_DATA_EPIN, \ + CDC_ACM_DATA_EPOUT) + +/*lint -save -e26 -e64 -e505 -e651 */ +static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_cdc_acm_user_event_t event); + +/**@brief CDC_ACM class instance. */ +APP_USBD_CDC_ACM_GLOBAL_DEF(m_app_cdc_acm, + cdc_acm_user_ev_handler, + CDC_ACM_COMM_INTERFACE, + CDC_ACM_DATA_INTERFACE, + CDC_ACM_COMM_EPIN, + CDC_ACM_DATA_EPIN, + CDC_ACM_DATA_EPOUT, + APP_USBD_CDC_COMM_PROTOCOL_NONE); +/*lint -restore */ + +NRF_BALLOC_DEF(m_payload_pool, (SLIP_MTU+1), NRF_DFU_SERIAL_USB_RX_BUFFERS); + +static nrf_dfu_serial_t m_serial; +static slip_t m_slip; +static uint8_t m_rsp_buf[NRF_USB_MAX_RESPONSE_SIZE_SLIP]; +static uint8_t m_rx_buf[NRF_DRV_USBD_EPSIZE]; + +static nrf_dfu_observer_t m_observer; + +static uint32_t usb_dfu_transport_init(nrf_dfu_observer_t observer); +static uint32_t usb_dfu_transport_close(nrf_dfu_transport_t const * p_exception); + + +DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const usb_dfu_transport) = +{ + .init_func = usb_dfu_transport_init, + .close_func = usb_dfu_transport_close, +}; + + +static void payload_free(void * p_buf) +{ + uint8_t * p_buf_root = ((uint8_t *)(p_buf)) - DATA_OFFSET; //pointer is shifted to point to data + nrf_balloc_free(&m_payload_pool, p_buf_root); +} + + +static ret_code_t rsp_send(uint8_t const * p_data, uint32_t length) +{ + ASSERT(p_data); + ASSERT(length != 0); + + uint32_t slip_len; + + // Cannot fail if inputs are non-NULL. + (void) slip_encode(m_rsp_buf, (uint8_t *)(p_data), length, &slip_len); + + return app_usbd_cdc_acm_write(&m_app_cdc_acm, m_rsp_buf, slip_len); +} + + +static void on_rx_complete(nrf_dfu_serial_t * p_transport, uint8_t * p_data, uint8_t len) +{ + ret_code_t ret_code; + + for (uint32_t i = 0; i < len; i++) + { + ret_code = slip_decode_add_byte(&m_slip, p_data[i]); + if (ret_code != NRF_SUCCESS) + { + continue; + } + + nrf_dfu_serial_on_packet_received(p_transport, + (uint8_t const *)(m_slip.p_buffer), + m_slip.current_index); + + uint8_t * p_rx_buf = nrf_balloc_alloc(&m_payload_pool); + if (p_rx_buf == NULL) + { + NRF_LOG_ERROR("Failed to allocate buffer!"); + return; + } + + NRF_LOG_DEBUG("Allocated buffer %x", p_rx_buf); + // reset the slip decoding + m_slip.p_buffer = &p_rx_buf[OPCODE_OFFSET]; + m_slip.current_index = 0; + m_slip.state = SLIP_STATE_DECODING; + } +} + +/** + * @brief User event handler @ref app_usbd_cdc_acm_user_ev_handler_t (headphones) + * */ +static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_cdc_acm_user_event_t event) +{ + ret_code_t ret_code; + + switch (event) + { + case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN: + { + ret_code = app_usbd_cdc_acm_read(&m_app_cdc_acm, m_rx_buf, 1); + NRF_LOG_WARNING("Could not read from CDC. Error: 0x%x.", ret_code); + } break; + + case APP_USBD_CDC_ACM_USER_EVT_RX_DONE: + { + do + { + on_rx_complete(&m_serial, m_rx_buf, 1); + ret_code = app_usbd_cdc_acm_read(&m_app_cdc_acm, m_rx_buf, 1); + } while (ret_code == NRF_SUCCESS); + } break; + + default: + break; + } +} + + +static void usbd_dfu_transport_ev_handler(app_usbd_event_type_t event) +{ + switch (event) + { + case APP_USBD_EVT_STOPPED: + app_usbd_disable(); + break; + + case APP_USBD_EVT_POWER_DETECTED: + NRF_LOG_INFO("USB power detected"); + if (!nrf_drv_usbd_is_enabled()) + { + app_usbd_enable(); + } + + if (m_observer) + { + m_observer(NRF_DFU_EVT_TRANSPORT_ACTIVATED); + } + break; + + case APP_USBD_EVT_POWER_REMOVED: + NRF_LOG_INFO("USB power removed"); + app_usbd_stop(); + if (m_observer) + { + m_observer(NRF_DFU_EVT_TRANSPORT_DEACTIVATED); + } + break; + + case APP_USBD_EVT_POWER_READY: + NRF_LOG_INFO("USB ready"); + app_usbd_start(); + break; + + default: + break; + } +} + + +static void usbd_sched_event_handler(void * p_event_data, uint16_t event_size) +{ + app_usbd_event_execute(p_event_data); +} + + +static void usbd_event_handler(app_usbd_internal_evt_t const * const p_event) +{ + ret_code_t ret_code; + if (p_event->type == APP_USBD_EVT_DRV_SOF) + { + app_usbd_event_execute(p_event); + } + else + { + ret_code = app_sched_event_put(p_event, + sizeof(app_usbd_internal_evt_t), + usbd_sched_event_handler); + + if (ret_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not schedule USB event!"); + } + } +} + + +static uint32_t usb_dfu_transport_init(nrf_dfu_observer_t observer) +{ + uint32_t err_code; + + /* Execute event directly in interrupt handler */ + static const app_usbd_config_t usbd_config = + { + .ev_handler = usbd_event_handler, + .ev_state_proc = usbd_dfu_transport_ev_handler + }; + + (void) nrf_balloc_init(&m_payload_pool); //Result is checked by checking result of _alloc(). + + m_observer = observer; + + uint8_t * p_rx_buf = nrf_balloc_alloc(&m_payload_pool); + if (p_rx_buf == NULL) + { + NRF_LOG_ERROR("Could not allocate payload pool."); + return NRF_ERROR_INTERNAL; + } + + m_slip.p_buffer = &p_rx_buf[OPCODE_OFFSET]; + m_slip.current_index = 0; + m_slip.buffer_len = SLIP_MTU; + m_slip.state = SLIP_STATE_DECODING; + + m_serial.rsp_func = rsp_send; + m_serial.payload_free_func = payload_free; + m_serial.mtu = SLIP_MTU; + m_serial.p_rsp_buf = &m_rsp_buf[NRF_USB_MAX_RESPONSE_SIZE_SLIP - + NRF_SERIAL_MAX_RESPONSE_SIZE]; + m_serial.p_low_level_transport = &usb_dfu_transport; + + + NRF_LOG_DEBUG("Initializing drivers."); + + err_code = nrf_drv_clock_init(); + if (err_code != NRF_ERROR_MODULE_ALREADY_INITIALIZED) + { + VERIFY_SUCCESS(err_code); + } + + err_code = nrf_drv_power_init(NULL); + VERIFY_SUCCESS(err_code); + + app_usbd_serial_num_generate(); + + err_code = app_usbd_init(&usbd_config); + VERIFY_SUCCESS(err_code); + + app_usbd_class_inst_t const * class_cdc_acm = app_usbd_cdc_acm_class_inst_get(&m_app_cdc_acm); + err_code = app_usbd_class_append(class_cdc_acm); + VERIFY_SUCCESS(err_code); + + NRF_LOG_DEBUG("Starting USB"); + + if (USBD_POWER_DETECTION) + { + err_code = app_usbd_power_events_enable(); + VERIFY_SUCCESS(err_code); + } + else + { + NRF_LOG_DEBUG("No USB power detection enabled, starting USB now"); + + app_usbd_enable(); + app_usbd_start(); + } + + NRF_LOG_DEBUG("USB Transport initialized"); + + return err_code; +} + + +static uint32_t usb_dfu_transport_close(nrf_dfu_transport_t const * p_exception) +{ + return NRF_SUCCESS; +} diff --git a/components/libraries/bsp/bsp.c b/components/libraries/bsp/bsp.c new file mode 100644 index 0000000..3d40f7a --- /dev/null +++ b/components/libraries/bsp/bsp.c @@ -0,0 +1,638 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "bsp.h" +#include +#include +#include "nordic_common.h" +#include "nrf.h" +#include "nrf_gpio.h" +#include "nrf_error.h" +#include "bsp_config.h" +#include "boards.h" + +#ifndef BSP_SIMPLE +#include "app_timer.h" +#include "app_button.h" +#endif // BSP_SIMPLE + +#if LEDS_NUMBER > 0 && !(defined BSP_SIMPLE) +static bsp_indication_t m_stable_state = BSP_INDICATE_IDLE; +static bool m_leds_clear = false; +static uint32_t m_indication_type = 0; +static bool m_alert_on = false; +APP_TIMER_DEF(m_bsp_leds_tmr); +APP_TIMER_DEF(m_bsp_alert_tmr); +#endif // LEDS_NUMBER > 0 && !(defined BSP_SIMPLE) + +#if BUTTONS_NUMBER > 0 +#ifndef BSP_SIMPLE +static bsp_event_callback_t m_registered_callback = NULL; +static bsp_button_event_cfg_t m_events_list[BUTTONS_NUMBER] = {{BSP_EVENT_NOTHING, BSP_EVENT_NOTHING}}; +APP_TIMER_DEF(m_bsp_button_tmr); +static void bsp_button_event_handler(uint8_t pin_no, uint8_t button_action); +#endif // BSP_SIMPLE + +#ifndef BSP_SIMPLE +static const app_button_cfg_t app_buttons[BUTTONS_NUMBER] = +{ + #ifdef BSP_BUTTON_0 + {BSP_BUTTON_0, false, BUTTON_PULL, bsp_button_event_handler}, + #endif // BUTTON_0 + + #ifdef BSP_BUTTON_1 + {BSP_BUTTON_1, false, BUTTON_PULL, bsp_button_event_handler}, + #endif // BUTTON_1 + + #ifdef BSP_BUTTON_2 + {BSP_BUTTON_2, false, BUTTON_PULL, bsp_button_event_handler}, + #endif // BUTTON_2 + + #ifdef BSP_BUTTON_3 + {BSP_BUTTON_3, false, BUTTON_PULL, bsp_button_event_handler}, + #endif // BUTTON_3 + + #ifdef BSP_BUTTON_4 + {BSP_BUTTON_4, false, BUTTON_PULL, bsp_button_event_handler}, + #endif // BUTTON_4 + + #ifdef BSP_BUTTON_5 + {BSP_BUTTON_5, false, BUTTON_PULL, bsp_button_event_handler}, + #endif // BUTTON_5 + + #ifdef BSP_BUTTON_6 + {BSP_BUTTON_6, false, BUTTON_PULL, bsp_button_event_handler}, + #endif // BUTTON_6 + + #ifdef BSP_BUTTON_7 + {BSP_BUTTON_7, false, BUTTON_PULL, bsp_button_event_handler}, + #endif // BUTTON_7 + +}; +#endif // BSP_SIMPLE +#endif // BUTTONS_NUMBER > 0 + +#if (BUTTONS_NUMBER > 0) +bool bsp_button_is_pressed(uint32_t button) +{ + if (button < BUTTONS_NUMBER) + { + return bsp_board_button_state_get(button); + } + else + { + //If button is not present always return false + return false; + } +} +#endif + +#if (BUTTONS_NUMBER > 0) && !(defined BSP_SIMPLE) +/**@brief Function for handling button events. + * + * @param[in] pin_no The pin number of the button pressed. + * @param[in] button_action Action button. + */ +static void bsp_button_event_handler(uint8_t pin_no, uint8_t button_action) +{ + bsp_event_t event = BSP_EVENT_NOTHING; + uint32_t button = 0; + uint32_t err_code; + static uint8_t current_long_push_pin_no; /**< Pin number of a currently pushed button, that could become a long push if held long enough. */ + static bsp_event_t release_event_at_push[BUTTONS_NUMBER]; /**< Array of what the release event of each button was last time it was pushed, so that no release event is sent if the event was bound after the push of the button. */ + + button = bsp_board_pin_to_button_idx(pin_no); + + if (button < BUTTONS_NUMBER) + { + switch (button_action) + { + case APP_BUTTON_PUSH: + event = m_events_list[button].push_event; + if (m_events_list[button].long_push_event != BSP_EVENT_NOTHING) + { + err_code = app_timer_start(m_bsp_button_tmr, APP_TIMER_TICKS(BSP_LONG_PUSH_TIMEOUT_MS), (void*)¤t_long_push_pin_no); + if (err_code == NRF_SUCCESS) + { + current_long_push_pin_no = pin_no; + } + } + release_event_at_push[button] = m_events_list[button].release_event; + break; + case APP_BUTTON_RELEASE: + (void)app_timer_stop(m_bsp_button_tmr); + if (release_event_at_push[button] == m_events_list[button].release_event) + { + event = m_events_list[button].release_event; + } + break; + case BSP_BUTTON_ACTION_LONG_PUSH: + event = m_events_list[button].long_push_event; + } + } + + if ((event != BSP_EVENT_NOTHING) && (m_registered_callback != NULL)) + { + m_registered_callback(event); + } +} + +/**@brief Handle events from button timer. + * + * @param[in] p_context parameter registered in timer start function. + */ +static void button_timer_handler(void * p_context) +{ + bsp_button_event_handler(*(uint8_t *)p_context, BSP_BUTTON_ACTION_LONG_PUSH); +} + + +#endif // (BUTTONS_NUMBER > 0) && !(defined BSP_SIMPLE) + + +#if LEDS_NUMBER > 0 && !(defined BSP_SIMPLE) +static void leds_off(void) +{ + if (m_alert_on) + { + uint32_t i; + for (i = 0; i < LEDS_NUMBER; i++) + { + if (i != BSP_LED_ALERT) + { + bsp_board_led_off(i); + } + } + } + else + { + bsp_board_leds_off(); + } +} + + +/**@brief Configure leds to indicate required state. + * @param[in] indicate State to be indicated. + */ +static uint32_t bsp_led_indication(bsp_indication_t indicate) +{ + uint32_t err_code = NRF_SUCCESS; + uint32_t next_delay = 0; + + if (m_leds_clear) + { + m_leds_clear = false; + leds_off(); + } + + switch (indicate) + { + case BSP_INDICATE_IDLE: + leds_off(); + err_code = app_timer_stop(m_bsp_leds_tmr); + m_stable_state = indicate; + break; + + case BSP_INDICATE_SCANNING: + case BSP_INDICATE_ADVERTISING: + // in advertising blink LED_0 + if (bsp_board_led_state_get(BSP_LED_INDICATE_INDICATE_ADVERTISING)) + { + bsp_board_led_off(BSP_LED_INDICATE_INDICATE_ADVERTISING); + next_delay = indicate == + BSP_INDICATE_ADVERTISING ? ADVERTISING_LED_OFF_INTERVAL : + ADVERTISING_SLOW_LED_OFF_INTERVAL; + } + else + { + bsp_board_led_on(BSP_LED_INDICATE_INDICATE_ADVERTISING); + next_delay = indicate == + BSP_INDICATE_ADVERTISING ? ADVERTISING_LED_ON_INTERVAL : + ADVERTISING_SLOW_LED_ON_INTERVAL; + } + + m_stable_state = indicate; + err_code = app_timer_start(m_bsp_leds_tmr, APP_TIMER_TICKS(next_delay), NULL); + break; + + case BSP_INDICATE_ADVERTISING_WHITELIST: + // in advertising quickly blink LED_0 + if (bsp_board_led_state_get(BSP_LED_INDICATE_ADVERTISING_WHITELIST)) + { + bsp_board_led_off(BSP_LED_INDICATE_ADVERTISING_WHITELIST); + next_delay = indicate == + BSP_INDICATE_ADVERTISING_WHITELIST ? + ADVERTISING_WHITELIST_LED_OFF_INTERVAL : + ADVERTISING_SLOW_LED_OFF_INTERVAL; + } + else + { + bsp_board_led_on(BSP_LED_INDICATE_ADVERTISING_WHITELIST); + next_delay = indicate == + BSP_INDICATE_ADVERTISING_WHITELIST ? + ADVERTISING_WHITELIST_LED_ON_INTERVAL : + ADVERTISING_SLOW_LED_ON_INTERVAL; + } + m_stable_state = indicate; + err_code = app_timer_start(m_bsp_leds_tmr, APP_TIMER_TICKS(next_delay), NULL); + break; + + case BSP_INDICATE_ADVERTISING_SLOW: + // in advertising slowly blink LED_0 + if (bsp_board_led_state_get(BSP_LED_INDICATE_ADVERTISING_SLOW)) + { + bsp_board_led_off(BSP_LED_INDICATE_ADVERTISING_SLOW); + next_delay = indicate == + BSP_INDICATE_ADVERTISING_SLOW ? ADVERTISING_SLOW_LED_OFF_INTERVAL : + ADVERTISING_SLOW_LED_OFF_INTERVAL; + } + else + { + bsp_board_led_on(BSP_LED_INDICATE_ADVERTISING_SLOW); + next_delay = indicate == + BSP_INDICATE_ADVERTISING_SLOW ? ADVERTISING_SLOW_LED_ON_INTERVAL : + ADVERTISING_SLOW_LED_ON_INTERVAL; + } + m_stable_state = indicate; + err_code = app_timer_start(m_bsp_leds_tmr, APP_TIMER_TICKS(next_delay), NULL); + break; + + case BSP_INDICATE_ADVERTISING_DIRECTED: + // in advertising very quickly blink LED_0 + if (bsp_board_led_state_get(BSP_LED_INDICATE_ADVERTISING_DIRECTED)) + { + bsp_board_led_off(BSP_LED_INDICATE_ADVERTISING_DIRECTED); + next_delay = indicate == + BSP_INDICATE_ADVERTISING_DIRECTED ? + ADVERTISING_DIRECTED_LED_OFF_INTERVAL : + ADVERTISING_SLOW_LED_OFF_INTERVAL; + } + else + { + bsp_board_led_on(BSP_LED_INDICATE_ADVERTISING_DIRECTED); + next_delay = indicate == + BSP_INDICATE_ADVERTISING_DIRECTED ? + ADVERTISING_DIRECTED_LED_ON_INTERVAL : + ADVERTISING_SLOW_LED_ON_INTERVAL; + } + m_stable_state = indicate; + err_code = app_timer_start(m_bsp_leds_tmr, APP_TIMER_TICKS(next_delay), NULL); + break; + + case BSP_INDICATE_BONDING: + // in bonding fast blink LED_0 + bsp_board_led_invert(BSP_LED_INDICATE_BONDING); + + m_stable_state = indicate; + err_code = + app_timer_start(m_bsp_leds_tmr, APP_TIMER_TICKS(BONDING_INTERVAL), NULL); + break; + + case BSP_INDICATE_CONNECTED: + bsp_board_led_off(BSP_LED_INDICATE_CONNECTED); + m_stable_state = indicate; + break; + + case BSP_INDICATE_SENT_OK: + // when sending shortly invert LED_1 + m_leds_clear = true; + bsp_board_led_invert(BSP_LED_INDICATE_SENT_OK); + err_code = app_timer_start(m_bsp_leds_tmr, APP_TIMER_TICKS(SENT_OK_INTERVAL), NULL); + break; + + case BSP_INDICATE_SEND_ERROR: + // on receving error invert LED_1 for long time + m_leds_clear = true; + bsp_board_led_invert(BSP_LED_INDICATE_SEND_ERROR); + err_code = app_timer_start(m_bsp_leds_tmr, APP_TIMER_TICKS(SEND_ERROR_INTERVAL), NULL); + break; + + case BSP_INDICATE_RCV_OK: + // when receving shortly invert LED_1 + m_leds_clear = true; + bsp_board_led_invert(BSP_LED_INDICATE_RCV_OK); + err_code = app_timer_start(m_bsp_leds_tmr, APP_TIMER_TICKS(RCV_OK_INTERVAL), NULL); + break; + + case BSP_INDICATE_RCV_ERROR: + // on receving error invert LED_1 for long time + m_leds_clear = true; + bsp_board_led_invert(BSP_LED_INDICATE_RCV_ERROR); + err_code = app_timer_start(m_bsp_leds_tmr, APP_TIMER_TICKS(RCV_ERROR_INTERVAL), NULL); + break; + + case BSP_INDICATE_FATAL_ERROR: + // on fatal error turn on all leds + bsp_board_leds_on(); + m_stable_state = indicate; + break; + + case BSP_INDICATE_ALERT_0: + case BSP_INDICATE_ALERT_1: + case BSP_INDICATE_ALERT_2: + case BSP_INDICATE_ALERT_3: + case BSP_INDICATE_ALERT_OFF: + err_code = app_timer_stop(m_bsp_alert_tmr); + next_delay = (uint32_t)BSP_INDICATE_ALERT_OFF - (uint32_t)indicate; + + // a little trick to find out that if it did not fall through ALERT_OFF + if (next_delay && (err_code == NRF_SUCCESS)) + { + if (next_delay > 1) + { + err_code = app_timer_start(m_bsp_alert_tmr, + APP_TIMER_TICKS(((uint16_t)next_delay * ALERT_INTERVAL)), + NULL); + } + bsp_board_led_on(BSP_LED_ALERT); + m_alert_on = true; + } + else + { + bsp_board_led_off(BSP_LED_ALERT); + m_alert_on = false; + + } + break; + + case BSP_INDICATE_USER_STATE_OFF: + leds_off(); + m_stable_state = indicate; + break; + + case BSP_INDICATE_USER_STATE_0: + leds_off(); + bsp_board_led_on(BSP_LED_INDICATE_USER_LED1); + m_stable_state = indicate; + break; + + case BSP_INDICATE_USER_STATE_1: + leds_off(); + bsp_board_led_on(BSP_LED_INDICATE_USER_LED2); + m_stable_state = indicate; + break; + + case BSP_INDICATE_USER_STATE_2: + leds_off(); + bsp_board_led_on(BSP_LED_INDICATE_USER_LED1); + bsp_board_led_on(BSP_LED_INDICATE_USER_LED2); + m_stable_state = indicate; + break; + + case BSP_INDICATE_USER_STATE_3: + + case BSP_INDICATE_USER_STATE_ON: + bsp_board_leds_on(); + m_stable_state = indicate; + break; + + default: + break; + } + + return err_code; +} + + +/**@brief Handle events from leds timer. + * + * @note Timer handler does not support returning an error code. + * Errors from bsp_led_indication() are not propagated. + * + * @param[in] p_context parameter registered in timer start function. + */ +static void leds_timer_handler(void * p_context) +{ + UNUSED_PARAMETER(p_context); + + if (m_indication_type & BSP_INIT_LEDS) + { + UNUSED_VARIABLE(bsp_led_indication(m_stable_state)); + } +} + + +/**@brief Handle events from alert timer. + * + * @param[in] p_context parameter registered in timer start function. + */ +static void alert_timer_handler(void * p_context) +{ + UNUSED_PARAMETER(p_context); + bsp_board_led_invert(BSP_LED_ALERT); +} +#endif // #if LEDS_NUMBER > 0 && !(defined BSP_SIMPLE) + + +/**@brief Configure indicators to required state. + */ +uint32_t bsp_indication_set(bsp_indication_t indicate) +{ + uint32_t err_code = NRF_SUCCESS; + +#if LEDS_NUMBER > 0 && !(defined BSP_SIMPLE) + + if (m_indication_type & BSP_INIT_LEDS) + { + err_code = bsp_led_indication(indicate); + } + +#endif // LEDS_NUMBER > 0 && !(defined BSP_SIMPLE) + return err_code; +} + + +uint32_t bsp_init(uint32_t type, bsp_event_callback_t callback) +{ + uint32_t err_code = NRF_SUCCESS; + +#if LEDS_NUMBER > 0 && !(defined BSP_SIMPLE) + m_indication_type = type; +#endif // LEDS_NUMBER > 0 && !(defined BSP_SIMPLE) + +#if (BUTTONS_NUMBER > 0) && !(defined BSP_SIMPLE) + m_registered_callback = callback; + + // BSP will support buttons and generate events + if (type & BSP_INIT_BUTTONS) + { + uint32_t num; + + for (num = 0; ((num < BUTTONS_NUMBER) && (err_code == NRF_SUCCESS)); num++) + { + err_code = bsp_event_to_button_action_assign(num, BSP_BUTTON_ACTION_PUSH, BSP_EVENT_DEFAULT); + } + + if (err_code == NRF_SUCCESS) + { + err_code = app_button_init((app_button_cfg_t *)app_buttons, + BUTTONS_NUMBER, + APP_TIMER_TICKS(50)); + } + + if (err_code == NRF_SUCCESS) + { + err_code = app_button_enable(); + } + + if (err_code == NRF_SUCCESS) + { + err_code = app_timer_create(&m_bsp_button_tmr, + APP_TIMER_MODE_SINGLE_SHOT, + button_timer_handler); + } + } +#elif (BUTTONS_NUMBER > 0) && (defined BSP_SIMPLE) + bsp_board_init(type); +#endif // (BUTTONS_NUMBER > 0) && !(defined BSP_SIMPLE) + +#if LEDS_NUMBER > 0 && !(defined BSP_SIMPLE) + if (type & BSP_INIT_LEDS) + { + //handle LEDs only. Buttons are already handled. + bsp_board_init(BSP_INIT_LEDS); + + // timers module must be already initialized! + if (err_code == NRF_SUCCESS) + { + err_code = + app_timer_create(&m_bsp_leds_tmr, APP_TIMER_MODE_SINGLE_SHOT, leds_timer_handler); + } + + if (err_code == NRF_SUCCESS) + { + err_code = + app_timer_create(&m_bsp_alert_tmr, APP_TIMER_MODE_REPEATED, alert_timer_handler); + } + } +#endif // LEDS_NUMBER > 0 && !(defined BSP_SIMPLE) + + return err_code; +} + + +#ifndef BSP_SIMPLE +/**@brief Assign specific event to button. + */ +uint32_t bsp_event_to_button_action_assign(uint32_t button, bsp_button_action_t action, bsp_event_t event) +{ + uint32_t err_code = NRF_SUCCESS; + +#if BUTTONS_NUMBER > 0 + if (button < BUTTONS_NUMBER) + { + if (event == BSP_EVENT_DEFAULT) + { + // Setting default action: BSP_EVENT_KEY_x for PUSH actions, BSP_EVENT_NOTHING for RELEASE and LONG_PUSH actions. + event = (action == BSP_BUTTON_ACTION_PUSH) ? (bsp_event_t)(BSP_EVENT_KEY_0 + button) : BSP_EVENT_NOTHING; + } + switch (action) + { + case BSP_BUTTON_ACTION_PUSH: + m_events_list[button].push_event = event; + break; + case BSP_BUTTON_ACTION_LONG_PUSH: + m_events_list[button].long_push_event = event; + break; + case BSP_BUTTON_ACTION_RELEASE: + m_events_list[button].release_event = event; + break; + default: + err_code = NRF_ERROR_INVALID_PARAM; + break; + } + } + else + { + err_code = NRF_ERROR_INVALID_PARAM; + } +#else + err_code = NRF_ERROR_INVALID_PARAM; +#endif // BUTTONS_NUMBER > 0 + + return err_code; +} + +#endif // BSP_SIMPLE + + +uint32_t bsp_buttons_enable() +{ +#if (BUTTONS_NUMBER > 0) && !defined(BSP_SIMPLE) + return app_button_enable(); +#else + return NRF_ERROR_NOT_SUPPORTED; +#endif +} + +uint32_t bsp_buttons_disable() +{ +#if (BUTTONS_NUMBER > 0) && !defined(BSP_SIMPLE) + return app_button_disable(); +#else + return NRF_ERROR_NOT_SUPPORTED; +#endif +} +static uint32_t wakeup_button_cfg(uint32_t button_idx, bool enable) +{ +#if !defined(BSP_SIMPLE) + if (button_idx < BUTTONS_NUMBER) + { + nrf_gpio_pin_sense_t sense = enable ? + (BUTTONS_ACTIVE_STATE ? NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW) : + NRF_GPIO_PIN_NOSENSE; + nrf_gpio_cfg_sense_set(bsp_board_button_idx_to_pin(button_idx), sense); + return NRF_SUCCESS; + } +#else + UNUSED_PARAMETER(button_idx); + UNUSED_PARAMETER(enable); +#endif + return NRF_ERROR_NOT_SUPPORTED; + +} +uint32_t bsp_wakeup_button_enable(uint32_t button_idx) +{ + return wakeup_button_cfg(button_idx, true); +} + +uint32_t bsp_wakeup_button_disable(uint32_t button_idx) +{ + return wakeup_button_cfg(button_idx, false); +} diff --git a/components/libraries/bsp/bsp.h b/components/libraries/bsp/bsp.h new file mode 100644 index 0000000..d05dac2 --- /dev/null +++ b/components/libraries/bsp/bsp.h @@ -0,0 +1,308 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup bsp Board Support Package + * @{ + * @ingroup app_common + * + * @brief BSP module. + * @details This module provides a layer of abstraction from the board. + * It allows the user to indicate certain states on LEDs in a simple way. + * Module functionality can be modified by defining BSP_SIMPLE to reduce + * functionality of this module to enable and read state of the buttons. + */ + +#ifndef BSP_H__ +#define BSP_H__ + +#include +#include +#include "boards.h" + +#if !defined(BSP_DEFINES_ONLY) && !defined(BSP_SIMPLE) +#include "app_button.h" + +#define BSP_BUTTON_ACTION_PUSH (APP_BUTTON_PUSH) /**< Represents pushing a button. See @ref bsp_button_action_t. */ +#define BSP_BUTTON_ACTION_RELEASE (APP_BUTTON_RELEASE) /**< Represents releasing a button. See @ref bsp_button_action_t. */ +#define BSP_BUTTON_ACTION_LONG_PUSH (2) /**< Represents pushing and holding a button for @ref BSP_LONG_PUSH_TIMEOUT_MS milliseconds. See also @ref bsp_button_action_t. */ + +#endif + +/* BSP_UART_SUPPORT + * This define enables UART support module. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint8_t bsp_button_action_t; /**< The different actions that can be performed on a button. */ + +#define BSP_INDICATIONS_LIST { \ + "BSP_INDICATE_IDLE", \ + "BSP_INDICATE_SCANNING", \ + "BSP_INDICATE_ADVERTISING", \ + "BSP_INDICATE_ADVERTISING_WHITELIST", \ + "BSP_INDICATE_ADVERTISING_SLOW", \ + "BSP_INDICATE_ADVERTISING_DIRECTED", \ + "BSP_INDICATE_BONDING", \ + "BSP_INDICATE_CONNECTED", \ + "BSP_INDICATE_SENT_OK", \ + "BSP_INDICATE_SEND_ERROR", \ + "BSP_INDICATE_RCV_OK", \ + "BSP_INDICATE_RCV_ERROR", \ + "BSP_INDICATE_FATAL_ERROR", \ + "BSP_INDICATE_ALERT_0", \ + "BSP_INDICATE_ALERT_1", \ + "BSP_INDICATE_ALERT_2", \ + "BSP_INDICATE_ALERT_3", \ + "BSP_INDICATE_ALERT_OFF", \ + "BSP_INDICATE_USER_STATE_OFF", \ + "BSP_INDICATE_USER_STATE_0", \ + "BSP_INDICATE_USER_STATE_1", \ + "BSP_INDICATE_USER_STATE_2", \ + "BSP_INDICATE_USER_STATE_3", \ + "BSP_INDICATE_USER_STATE_ON" \ +} /**< See @ref examples_bsp_states for a list of how these states are indicated for the PCA10028/PCA10040 board and the PCA10031 dongle.*/ + + +/**@brief BSP indication states. + * + * @details See @ref examples_bsp_states for a list of how these states are indicated for the PCA10028/PCA10040 board and the PCA10031 dongle. + */ +typedef enum +{ + BSP_INDICATE_FIRST = 0, + BSP_INDICATE_IDLE = BSP_INDICATE_FIRST, /**< See \ref BSP_INDICATE_IDLE.*/ + BSP_INDICATE_SCANNING, /**< See \ref BSP_INDICATE_SCANNING.*/ + BSP_INDICATE_ADVERTISING, /**< See \ref BSP_INDICATE_ADVERTISING.*/ + BSP_INDICATE_ADVERTISING_WHITELIST, /**< See \ref BSP_INDICATE_ADVERTISING_WHITELIST.*/ + BSP_INDICATE_ADVERTISING_SLOW, /**< See \ref BSP_INDICATE_ADVERTISING_SLOW.*/ + BSP_INDICATE_ADVERTISING_DIRECTED, /**< See \ref BSP_INDICATE_ADVERTISING_DIRECTED.*/ + BSP_INDICATE_BONDING, /**< See \ref BSP_INDICATE_BONDING.*/ + BSP_INDICATE_CONNECTED, /**< See \ref BSP_INDICATE_CONNECTED.*/ + BSP_INDICATE_SENT_OK, /**< See \ref BSP_INDICATE_SENT_OK.*/ + BSP_INDICATE_SEND_ERROR, /**< See \ref BSP_INDICATE_SEND_ERROR.*/ + BSP_INDICATE_RCV_OK, /**< See \ref BSP_INDICATE_RCV_OK.*/ + BSP_INDICATE_RCV_ERROR, /**< See \ref BSP_INDICATE_RCV_ERROR.*/ + BSP_INDICATE_FATAL_ERROR, /**< See \ref BSP_INDICATE_FATAL_ERROR.*/ + BSP_INDICATE_ALERT_0, /**< See \ref BSP_INDICATE_ALERT_0.*/ + BSP_INDICATE_ALERT_1, /**< See \ref BSP_INDICATE_ALERT_1.*/ + BSP_INDICATE_ALERT_2, /**< See \ref BSP_INDICATE_ALERT_2.*/ + BSP_INDICATE_ALERT_3, /**< See \ref BSP_INDICATE_ALERT_3.*/ + BSP_INDICATE_ALERT_OFF, /**< See \ref BSP_INDICATE_ALERT_OFF.*/ + BSP_INDICATE_USER_STATE_OFF, /**< See \ref BSP_INDICATE_USER_STATE_OFF.*/ + BSP_INDICATE_USER_STATE_0, /**< See \ref BSP_INDICATE_USER_STATE_0.*/ + BSP_INDICATE_USER_STATE_1, /**< See \ref BSP_INDICATE_USER_STATE_1.*/ + BSP_INDICATE_USER_STATE_2, /**< See \ref BSP_INDICATE_USER_STATE_2.*/ + BSP_INDICATE_USER_STATE_3, /**< See \ref BSP_INDICATE_USER_STATE_3.*/ + BSP_INDICATE_USER_STATE_ON, /**< See \ref BSP_INDICATE_USER_STATE_ON.*/ + BSP_INDICATE_LAST = BSP_INDICATE_USER_STATE_ON +} bsp_indication_t; + +/**@brief BSP events. + * + * @note Events from BSP_EVENT_KEY_0 to BSP_EVENT_KEY_LAST are by default assigned to buttons. + */ +typedef enum +{ + BSP_EVENT_NOTHING = 0, /**< Assign this event to an action to prevent the action from generating an event (disable the action). */ + BSP_EVENT_DEFAULT, /**< Assign this event to an action to assign the default event to the action. */ + BSP_EVENT_CLEAR_BONDING_DATA, /**< Persistent bonding data should be erased. */ + BSP_EVENT_CLEAR_ALERT, /**< An alert should be cleared. */ + BSP_EVENT_DISCONNECT, /**< A link should be disconnected. */ + BSP_EVENT_ADVERTISING_START, /**< The device should start advertising. */ + BSP_EVENT_ADVERTISING_STOP, /**< The device should stop advertising. */ + BSP_EVENT_WHITELIST_OFF, /**< The device should remove its advertising whitelist. */ + BSP_EVENT_BOND, /**< The device should bond to the currently connected peer. */ + BSP_EVENT_RESET, /**< The device should reset. */ + BSP_EVENT_SLEEP, /**< The device should enter sleep mode. */ + BSP_EVENT_WAKEUP, /**< The device should wake up from sleep mode. */ + BSP_EVENT_SYSOFF, /**< The device should enter system off mode (without wakeup). */ + BSP_EVENT_DFU, /**< The device should enter DFU mode. */ + BSP_EVENT_KEY_0, /**< Default event of the push action of BSP_BUTTON_0 (only if this button is present). */ + BSP_EVENT_KEY_1, /**< Default event of the push action of BSP_BUTTON_1 (only if this button is present). */ + BSP_EVENT_KEY_2, /**< Default event of the push action of BSP_BUTTON_2 (only if this button is present). */ + BSP_EVENT_KEY_3, /**< Default event of the push action of BSP_BUTTON_3 (only if this button is present). */ + BSP_EVENT_KEY_4, /**< Default event of the push action of BSP_BUTTON_4 (only if this button is present). */ + BSP_EVENT_KEY_5, /**< Default event of the push action of BSP_BUTTON_5 (only if this button is present). */ + BSP_EVENT_KEY_6, /**< Default event of the push action of BSP_BUTTON_6 (only if this button is present). */ + BSP_EVENT_KEY_7, /**< Default event of the push action of BSP_BUTTON_7 (only if this button is present). */ + BSP_EVENT_POWER_CONTROL, /**< Can be control the device power. */ + BSP_EVENT_KEY_LAST = BSP_EVENT_POWER_CONTROL, +} bsp_event_t; + + +typedef struct +{ + bsp_event_t push_event; /**< The event to fire on regular button press. */ + bsp_event_t long_push_event; /**< The event to fire on long button press. */ + bsp_event_t release_event; /**< The event to fire on button release. */ +} bsp_button_event_cfg_t; + +/**@brief BSP module event callback function type. + * + * @details Upon an event in the BSP module, this callback function will be called to notify + * the application about the event. + * + * @param[in] bsp_event_t BSP event type. + */ +typedef void (* bsp_event_callback_t)(bsp_event_t); + + +/**@brief Function for initializing BSP. + * + * @details The function initializes the board support package to allow state indication and + * button reaction. Default events are assigned to buttons. + * @note Before calling this function, you must initiate the following required modules: + * - @ref app_timer for LED support + * - @ref app_gpiote for button support + * + * @param[in] type Type of peripherals used. + * @param[in] callback Function to be called when button press/event is detected. + * + * @retval NRF_SUCCESS If the BSP module was successfully initialized. + * @retval NRF_ERROR_INVALID_STATE If the application timer module has not been initialized. + * @retval NRF_ERROR_NO_MEM If the maximum number of timers has already been reached. + * @retval NRF_ERROR_INVALID_PARAM If GPIOTE has too many users. + * @retval NRF_ERROR_INVALID_STATE If button or GPIOTE has not been initialized. + */ +uint32_t bsp_init(uint32_t type, bsp_event_callback_t callback); + + +/**@brief Function for checking button states. + * + * @details This function checks if the button is pressed. If the button ID is out of range, + * the function returns false. + * + * @param[in] button Button ID to check. + * + * @retval true If the button is pressed. + * @retval false If the button is not pressed. + */ +bool bsp_button_is_pressed(uint32_t button); + + +/**@brief Function for assigning a specific event to a button. + * + * @details This function allows redefinition of standard events assigned to buttons. + * To unassign events, provide the event @ref BSP_EVENT_NOTHING. + * + * @param[in] button Button ID to be redefined. + * @param[in] action Button action to assign event to. + * @param[in] event Event to be assigned to button. + * + * @retval NRF_SUCCESS If the event was successfully assigned to button. + * @retval NRF_ERROR_INVALID_PARAM If the button ID or button action was invalid. + */ +uint32_t bsp_event_to_button_action_assign(uint32_t button, bsp_button_action_t action, bsp_event_t event); + + +/**@brief Function for configuring indicators to required state. + * + * @details This function indicates the required state by means of LEDs (if enabled). + * + * @note Alerts are indicated independently. + * + * @param[in] indicate State to be indicated. + * + * @retval NRF_SUCCESS If the state was successfully indicated. + * @retval NRF_ERROR_NO_MEM If the internal timer operations queue was full. + * @retval NRF_ERROR_INVALID_STATE If the application timer module has not been initialized, + * or internal timer has not been created. + */ +uint32_t bsp_indication_set(bsp_indication_t indicate); + + +/**@brief Function for enabling all buttons. + * + * @details After calling this function, all buttons will generate events when pressed, and + * all buttons will be able to wake the system up from sleep mode. + * + * @retval NRF_SUCCESS If the buttons were successfully enabled. + * @retval NRF_ERROR_NOT_SUPPORTED If the board has no buttons or BSP_SIMPLE is defined. + * @return A propagated error. + */ +uint32_t bsp_buttons_enable(void); + + +/**@brief Function for disabling all buttons. + * + * @details After calling this function, no buttons will generate events when pressed, and + * no buttons will be able to wake the system up from sleep mode. + * + * @retval NRF_SUCCESS If the buttons were successfully disabled. + * @retval NRF_ERROR_NOT_SUPPORTED If the board has no buttons or BSP_SIMPLE is defined. + * @return A propagated error. + */ +uint32_t bsp_buttons_disable(void); + + +/**@brief Function for enabling wakeup from SYSTEM OFF for given button. + * + * @details After calling this function, button can be used to wake up the chip. + * This function should only be called immediately before going into sleep. + * + * @param[in] button_idx Index of the button. + * + * @retval NRF_SUCCESS If the button was successfully enabled. + * @retval NRF_ERROR_NOT_SUPPORTED If the board has no buttons or BSP_SIMPLE is defined. + */ +uint32_t bsp_wakeup_button_enable(uint32_t button_idx); + + +/**@brief Function for disabling wakeup for the given button. + * + * @param[in] button_idx index of the button. + * + * @retval NRF_SUCCESS If the button was successfully disabled. + * @retval NRF_ERROR_NOT_SUPPORTED If the board has no buttons or BSP_SIMPLE is defined. + */ +uint32_t bsp_wakeup_button_disable(uint32_t button_idx); + + +#ifdef __cplusplus +} +#endif + +#endif // BSP_H__ + +/** @} */ diff --git a/components/libraries/bsp/bsp_btn_ant.c b/components/libraries/bsp/bsp_btn_ant.c new file mode 100644 index 0000000..6df1966 --- /dev/null +++ b/components/libraries/bsp/bsp_btn_ant.c @@ -0,0 +1,172 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(BSP_BTN_ANT) +#include "bsp_btn_ant.h" +#include "nrf_sdh_ant.h" +#include "bsp.h" + + +static bool m_connected = false; /**< Notify if channel is connected. */ +static uint8_t m_channel = UINT8_MAX; /**< ANT channel number linked to indication. */ +static uint8_t m_channel_type; /**< Type of linked ANT channel. */ + +/**@brief Function for configuring the buttons for connection. + * + * @retval NRF_SUCCESS Configured successfully. + * @return A propagated error code. + */ +static ret_code_t connection_buttons_configure(void) +{ + ret_code_t err_code = bsp_event_to_button_action_assign(BSP_BTN_ANT_CONFIG_SLEEP_BTN_ID, + BSP_BUTTON_ACTION_RELEASE, + BSP_EVENT_DEFAULT); + if (err_code == NRF_ERROR_INVALID_PARAM) + { + return NRF_SUCCESS; + } + + return err_code; +} + +/**@brief Function for configuring the buttons for searching. + * + * @retval NRF_SUCCESS Configured successfully. + * @return A propagated error code. + */ +static ret_code_t searching_buttons_configure(void) +{ + ret_code_t err_code = bsp_event_to_button_action_assign(BSP_BTN_ANT_CONFIG_SLEEP_BTN_ID, + BSP_BUTTON_ACTION_RELEASE, + BSP_EVENT_SLEEP); + if (err_code == NRF_ERROR_INVALID_PARAM) + { + return NRF_SUCCESS; + } + + return err_code; +} + + +ret_code_t bsp_btn_ant_sleep_mode_prepare(void) +{ + ret_code_t err_code = bsp_buttons_disable(); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = bsp_wakeup_button_enable(BSP_BTN_ANT_CONFIG_WAKEUP_BTN_ID); + if (err_code == NRF_ERROR_NOT_SUPPORTED) + { + return NRF_SUCCESS; + } + + return err_code; +} + +/** + * @brief Function for handling ANT events. + * + * @param[in] p_ant_evt Event received from the ANT stack. + * @param[in] p_context Context. + */ +static void ant_evt_handler(ant_evt_t * p_ant_evt, void * p_context) +{ + ret_code_t err_code = NRF_SUCCESS; + + if (m_channel != p_ant_evt->channel) + { + return; + } + + switch (m_channel_type) + { + case CHANNEL_TYPE_SLAVE: + /* fall through */ + case CHANNEL_TYPE_SLAVE_RX_ONLY: + switch (p_ant_evt->event) + { + case EVENT_RX: + if (!m_connected) + { + err_code = connection_buttons_configure(); + } + + m_connected = true; + break; + + case EVENT_RX_FAIL_GO_TO_SEARCH: + m_connected = false; + + err_code = searching_buttons_configure(); + break; + + default: + break; + } + break; + } + + APP_ERROR_CHECK(err_code); +} + +NRF_SDH_ANT_OBSERVER(m_ant_observer, BSP_BTN_ANT_OBSERVER_PRIO, ant_evt_handler, NULL); + +ret_code_t bsp_btn_ant_init(uint8_t channel, uint8_t channel_type) +{ + ret_code_t err_code = NRF_SUCCESS; + + m_channel = channel; + m_channel_type = channel_type; + + if (!m_connected) + { + err_code = searching_buttons_configure(); + } + else + { + err_code = connection_buttons_configure(); + } + + return err_code; +} + +#endif // NRF_MODULE_ENABLED(BSP_BTN_ANT) diff --git a/components/libraries/bsp/bsp_btn_ant.h b/components/libraries/bsp/bsp_btn_ant.h new file mode 100644 index 0000000..a50e85e --- /dev/null +++ b/components/libraries/bsp/bsp_btn_ant.h @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup bsp_btn_ant BSP: ANT Button Module + * @{ + * @ingroup bsp + * + * @brief Module for controlling ANT behavior through button actions. + * + * @details The application must propagate ANT events to the ANT Button Module. + * Based on these events, the ANT Button Module configures the Board Support Package + * to generate BSP events for certain button actions. These BSP events should then be + * handled by the application's BSP event handler. + * + */ + +#ifndef BSP_BTN_ANT_H__ +#define BSP_BTN_ANT_H__ + +#include +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /**@brief Function for initializing the ANT Button Module. + * + * Before calling this function, the BSP module must be initialized with buttons. + * + * @param[in] channel ANT channel number. + * @param[in] channel_type ANT channel type (see Assign Channel Parameters in ant_parameters.h: @ref ant_parameters). + * + * @retval NRF_SUCCESS If initialization was successful. Otherwise, a propagated error code is + * returned. + */ +ret_code_t bsp_btn_ant_init(uint8_t channel, uint8_t channel_type); + +/**@brief Function for setting up wakeup buttons before going into sleep mode. + * + * @retval NRF_SUCCESS If the buttons were prepared successfully. Otherwise, a propagated error + * code is returned. + */ +ret_code_t bsp_btn_ant_sleep_mode_prepare(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* BSP_BTN_ANT_H__ */ + +/** @} */ diff --git a/components/libraries/bsp/bsp_btn_ble.c b/components/libraries/bsp/bsp_btn_ble.c new file mode 100644 index 0000000..3ff779e --- /dev/null +++ b/components/libraries/bsp/bsp_btn_ble.c @@ -0,0 +1,266 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "bsp_btn_ble.h" +#include "nrf_sdh_ble.h" +#include "bsp.h" + +#define BTN_ID_WAKEUP 0 /**< ID of button used to wake up the application. */ +#define BTN_ID_SLEEP 0 /**< ID of button used to put the application into sleep mode. */ +#define BTN_ID_DISCONNECT 0 /**< ID of button used to gracefully terminate a connection on long press. */ +#define BTN_ID_WAKEUP_BOND_DELETE 1 /**< ID of button used to wake up the application and delete all bonding information. */ +#define BTN_ID_WHITELIST_OFF 1 /**< ID of button used to turn off usage of the whitelist. */ +#define BTN_ID_POWER_CONTROL 2 /**< ID of button used to power on/off */ + +#define BTN_ACTION_SLEEP BSP_BUTTON_ACTION_RELEASE /**< Button action used to put the application into sleep mode. */ +#define BTN_ACTION_DISCONNECT BSP_BUTTON_ACTION_LONG_PUSH /**< Button action used to gracefully terminate a connection on long press. */ +#define BTN_ACTION_WHITELIST_OFF BSP_BUTTON_ACTION_LONG_PUSH /**< Button action used to turn off usage of the whitelist. */ +#define BTN_ACTION_POWER_CONROL BSP_BUTTON_ACTION_LONG_PUSH /**< Button action used to power pn/off */ + +/**@brief This macro will return from the current function if err_code + * is not NRF_SUCCESS or NRF_ERROR_INVALID_PARAM. + */ +#define RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code) \ +do \ +{ \ + if (((err_code) != NRF_SUCCESS) && ((err_code) != NRF_ERROR_INVALID_PARAM)) \ + { \ + return err_code; \ + } \ +} \ +while (0) + + +/**@brief This macro will return from the current function if err_code + * is not NRF_SUCCESS or NRF_ERROR_NOT_SUPPORTED. + */ +#define RETURN_ON_ERROR_NOT_NOT_SUPPORTED(err_code) \ +do \ +{ \ + if (((err_code) != NRF_SUCCESS) && ((err_code) != NRF_ERROR_NOT_SUPPORTED)) \ + { \ + return err_code; \ + } \ +} \ +while (0) + + +/**@brief This macro will call the registered error handler if err_code + * is not NRF_SUCCESS and the error handler is not NULL. + */ +#define CALL_HANDLER_ON_ERROR(err_code) \ +do \ +{ \ + if (((err_code) != NRF_SUCCESS) && (m_error_handler != NULL)) \ + { \ + m_error_handler(err_code); \ + } \ +} \ +while (0) + + +static bsp_btn_ble_error_handler_t m_error_handler = NULL; /**< Error handler registered by the user. */ +static uint32_t m_num_connections = 0; /**< Number of connections the device is currently in. */ + + +/**@brief Function for configuring the buttons for connection. + * + * @retval NRF_SUCCESS Configured successfully. + * @return A propagated error code. + */ +static uint32_t connection_buttons_configure() +{ + uint32_t err_code; + + err_code = bsp_event_to_button_action_assign(BTN_ID_SLEEP, + BTN_ACTION_SLEEP, + BSP_EVENT_DEFAULT); + RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code); + + err_code = bsp_event_to_button_action_assign(BTN_ID_WHITELIST_OFF, + BTN_ACTION_WHITELIST_OFF, + BSP_EVENT_WHITELIST_OFF); + RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code); + + + err_code = bsp_event_to_button_action_assign(BTN_ID_DISCONNECT, + BTN_ACTION_DISCONNECT, + BSP_EVENT_DISCONNECT); + RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code); + + err_code = bsp_event_to_button_action_assign(BTN_ID_POWER_CONTROL, + BTN_ACTION_POWER_CONROL, + BSP_EVENT_POWER_CONTROL); + RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code); + + return NRF_SUCCESS; +} + + +/**@brief Function for configuring the buttons for advertisement. + * + * @retval NRF_SUCCESS Configured successfully. + * @return A propagated error code. + */ +static uint32_t advertising_buttons_configure() +{ + uint32_t err_code; + + err_code = bsp_event_to_button_action_assign(BTN_ID_DISCONNECT, + BTN_ACTION_DISCONNECT, + BSP_EVENT_DEFAULT); + RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code); + + err_code = bsp_event_to_button_action_assign(BTN_ID_WHITELIST_OFF, + BTN_ACTION_WHITELIST_OFF, + BSP_EVENT_WHITELIST_OFF); + RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code); + + err_code = bsp_event_to_button_action_assign(BTN_ID_SLEEP, + BTN_ACTION_SLEEP, + BSP_EVENT_SLEEP); + RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code); + + err_code = bsp_event_to_button_action_assign(BTN_ID_POWER_CONTROL, + BTN_ACTION_POWER_CONROL, + BSP_EVENT_POWER_CONTROL); + RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code); + + return NRF_SUCCESS; +} + + +/**@brief Function for extracting the BSP event valid at startup. + * + * @details When a button was used to wake up the device, the button press will not generate an + * interrupt. This function reads which button was pressed at startup, and returns the + * appropriate BSP event. + * + * @param[out] p_startup_event Where to put the extracted BSP event. + */ +static void startup_event_extract(bsp_event_t * p_startup_event) +{ + // React to button states + if (bsp_button_is_pressed(BTN_ID_WAKEUP_BOND_DELETE)) + { + *p_startup_event = BSP_EVENT_CLEAR_BONDING_DATA; + } + else if (bsp_button_is_pressed(BTN_ID_WAKEUP)) + { + *p_startup_event = BSP_EVENT_WAKEUP; + } + else + { + *p_startup_event = BSP_EVENT_NOTHING; + } +} + + +uint32_t bsp_btn_ble_sleep_mode_prepare(void) +{ + uint32_t err_code; + + err_code = bsp_wakeup_button_enable(BTN_ID_WAKEUP); + RETURN_ON_ERROR_NOT_NOT_SUPPORTED(err_code); + + err_code = bsp_wakeup_button_enable(BTN_ID_WAKEUP_BOND_DELETE); + RETURN_ON_ERROR_NOT_NOT_SUPPORTED(err_code); + + return NRF_SUCCESS; +} + + +/** + * @brief Function for handling BLE events. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context Context. + */ +static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) +{ + uint32_t err_code; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + if (m_num_connections == 0) + { + err_code = connection_buttons_configure(); + CALL_HANDLER_ON_ERROR(err_code); + } + + m_num_connections++; + break; + + case BLE_GAP_EVT_DISCONNECTED: + m_num_connections--; + + if (m_num_connections == 0) + { + err_code = advertising_buttons_configure(); + CALL_HANDLER_ON_ERROR(err_code); + } + break; + + default: + break; + } +} + +NRF_SDH_BLE_OBSERVER(m_ble_observer, BSP_BTN_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); + + +uint32_t bsp_btn_ble_init(bsp_btn_ble_error_handler_t error_handler, bsp_event_t * p_startup_bsp_evt) +{ + uint32_t err_code = NRF_SUCCESS; + + m_error_handler = error_handler; + + if (p_startup_bsp_evt != NULL) + { + startup_event_extract(p_startup_bsp_evt); + } + + if (m_num_connections == 0) + { + err_code = advertising_buttons_configure(); + } + + return err_code; +} diff --git a/components/libraries/bsp/bsp_btn_ble.h b/components/libraries/bsp/bsp_btn_ble.h new file mode 100644 index 0000000..55dd987 --- /dev/null +++ b/components/libraries/bsp/bsp_btn_ble.h @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup bsp_btn_ble BSP: BLE Button Module + * @{ + * @ingroup bsp + * + * @brief Module for controlling BLE behavior through button actions. + * + * @details The application must propagate BLE events to the BLE Button Module. + * Based on these events, the BLE Button Module configures the Board Support Package + * to generate BSP events for certain button actions. These BSP events should then be + * handled by the application's BSP event handler. + * + */ + +#ifndef BSP_BTN_BLE_H__ +#define BSP_BTN_BLE_H__ + +#include +#include "ble.h" +#include "bsp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief BLE Button Module error handler type. */ +typedef void (*bsp_btn_ble_error_handler_t) (uint32_t nrf_error); + +/**@brief Function for initializing the BLE Button Module. + * + * Before calling this function, the BSP module must be initialized with buttons. + * + * @param[out] error_handler Error handler to call in case of internal errors in BLE Button + * Module. + * @param[out] p_startup_bsp_evt If not a NULL pointer, the value is filled with an event + * (or BSP_EVENT_NOTHING) derived from the buttons pressed on + * startup. For example, if the bond delete wakeup button was pressed + * to wake up the device, *p_startup_bsp_evt is set to + * @ref BSP_EVENT_CLEAR_BONDING_DATA. + * + * @retval NRF_SUCCESS If initialization was successful. Otherwise, a propagated error code is + * returned. + */ +uint32_t bsp_btn_ble_init(bsp_btn_ble_error_handler_t error_handler, bsp_event_t * p_startup_bsp_evt); + +/**@brief Function for setting up wakeup buttons before going into sleep mode. + * + * @retval NRF_SUCCESS If the buttons were prepared successfully. Otherwise, a propagated error + * code is returned. + */ +uint32_t bsp_btn_ble_sleep_mode_prepare(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* BSP_BTN_BLE_H__ */ + +/** @} */ diff --git a/components/libraries/bsp/bsp_cli.c b/components/libraries/bsp/bsp_cli.c new file mode 100644 index 0000000..619cb71 --- /dev/null +++ b/components/libraries/bsp/bsp_cli.c @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "bsp_cli.h" + +static bsp_event_callback_t m_bsp_cli_callback = NULL; + +static void cmd_btn(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + uint32_t id; + ASSERT(m_bsp_cli_callback != NULL); + + sscanf(argv[1], "%"SCNu32, &id); + bsp_event_t ev = (bsp_event_t)(BSP_EVENT_KEY_0 + id); + m_bsp_cli_callback(ev); +} + +static void cmd_evt(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + uint32_t id; + ASSERT(m_bsp_cli_callback != NULL); + + sscanf(argv[1], "%"SCNu32, &id); + bsp_event_t ev = (bsp_event_t)id; + m_bsp_cli_callback(ev); +} + +ret_code_t bsp_cli_init(bsp_event_callback_t callback) +{ + m_bsp_cli_callback = callback; + + return NRF_SUCCESS; +} + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_bsp) +{ + NRF_CLI_CMD(btn, NULL, "BSP button event key", cmd_btn), + NRF_CLI_CMD(evt, NULL, "BSP event id", cmd_evt), + NRF_CLI_SUBCMD_SET_END +}; +NRF_CLI_CMD_REGISTER(bsp, &m_sub_bsp, "bsp", NULL); diff --git a/components/libraries/bsp/bsp_cli.h b/components/libraries/bsp/bsp_cli.h new file mode 100644 index 0000000..b74e9b7 --- /dev/null +++ b/components/libraries/bsp/bsp_cli.h @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup bsp_cli BSP over CLI Module + * @{ + * @ingroup bsp + * + * @brief Module for sending BSP events over CLI. + * + * @details The module uses Command Line Interface and enables user to send events + * to BSP. They are later handled by the event handler provided. + * Available commands: + * - bsp btn X (where X is button number) - sends BSP_EVENT_KEY_X + * - bsp evt X (where X is event number) - sends BSP event with X id + */ + +#ifndef BSP_CLI_H__ +#define BSP_CLI_H__ + +#include +#include "nrf_cli.h" +#include "bsp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Function for initializing the BSP over CLI Module. + * + * Before calling this function, the BSP module must be initialized. + * + * @param[in] callback Function to be called when event is recevied. + * + * @retval NRF_SUCCESS If initialization was successful. + */ + +ret_code_t bsp_cli_init(bsp_event_callback_t callback); + +#ifdef __cplusplus +} +#endif + +#endif /* BSP_CLI_H__ */ + +/** @} */ diff --git a/components/libraries/bsp/bsp_config.h b/components/libraries/bsp/bsp_config.h new file mode 100644 index 0000000..83492ba --- /dev/null +++ b/components/libraries/bsp/bsp_config.h @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup bsp Board Support Package + * @{ + * @ingroup app_common + * + * @brief BSP module. + * @details This module provides a layer of abstraction from the board. + * It allows the user to indicate certain states on LEDs in a simple way. + * Module functionality can be modified by additional defines: + * - BSP_SIMPLE - reduces functionality of this module to enable + * and read state of the buttons. + * - BSP_UART_SUPPORT - enables support for UART. + */ + +#ifndef BSP_CONFIG_H__ +#define BSP_CONFIG_H__ + +#include +#include +#include "boards.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(BSP_DEFINES_ONLY) && !defined(BSP_SIMPLE) +#include "app_button.h" + +#define BSP_BUTTON_ACTION_PUSH (APP_BUTTON_PUSH) /**< Represents pushing a button. See @ref bsp_button_action_t. */ +#define BSP_BUTTON_ACTION_RELEASE (APP_BUTTON_RELEASE) /**< Represents releasing a button. See @ref bsp_button_action_t. */ +#define BSP_BUTTON_ACTION_LONG_PUSH (2) /**< Represents pushing and holding a button for @ref BSP_LONG_PUSH_TIMEOUT_MS milliseconds. See also @ref bsp_button_action_t. */ +#endif + +#define BSP_MS_TO_TICK(MS) (m_app_ticks_per_100ms * (MS / 100)) + + +#define BUTTON_ERASE_BONDING BSP_BUTTON_0_MASK +#define BUTTON_ERASE_ALL BSP_BUTTON_1_MASK +#define BUTTON_ADVERTISE BSP_BUTTON_0_MASK +#define BUTTON_CLEAR_EVT BSP_BUTTON_1_MASK +#define BUTTON_CAPSLOCK BSP_BUTTON_2_MASK +#define BSP_BUTTONS_ALL 0xFFFFFFFF +#define BSP_BUTTONS_NONE 0 + +#define BSP_LONG_PUSH_TIMEOUT_MS (3000) /**< The time to hold for a long push (in milliseconds). */ +/**@brief Types of BSP initialization. + */ + +#define ADVERTISING_LED_ON_INTERVAL 500 +#define ADVERTISING_LED_OFF_INTERVAL 1500 + +#define ADVERTISING_DIRECTED_LED_ON_INTERVAL 200 +#define ADVERTISING_DIRECTED_LED_OFF_INTERVAL 200 + +#define ADVERTISING_WHITELIST_LED_ON_INTERVAL 200 +#define ADVERTISING_WHITELIST_LED_OFF_INTERVAL 800 + +#define ADVERTISING_SLOW_LED_ON_INTERVAL 400 +#define ADVERTISING_SLOW_LED_OFF_INTERVAL 4000 + +#define BONDING_INTERVAL 100 + +#define SENT_OK_INTERVAL 100 +#define SEND_ERROR_INTERVAL 500 + +#define RCV_OK_INTERVAL 100 +#define RCV_ERROR_INTERVAL 500 + +#define ALERT_INTERVAL 100 + +#define BSP_LED_INDICATE_SENT_OK BSP_BOARD_LED_1 +#define BSP_LED_INDICATE_SEND_ERROR BSP_BOARD_LED_1 +#define BSP_LED_INDICATE_RCV_OK BSP_BOARD_LED_1 +#define BSP_LED_INDICATE_RCV_ERROR BSP_BOARD_LED_1 +#define BSP_LED_INDICATE_CONNECTED BSP_BOARD_LED_0 +#define BSP_LED_INDICATE_BONDING BSP_BOARD_LED_0 +#define BSP_LED_INDICATE_ADVERTISING_DIRECTED BSP_BOARD_LED_0 +#define BSP_LED_INDICATE_ADVERTISING_SLOW BSP_BOARD_LED_0 +#define BSP_LED_INDICATE_ADVERTISING_WHITELIST BSP_BOARD_LED_0 +#define BSP_LED_INDICATE_INDICATE_ADVERTISING BSP_BOARD_LED_0 + +#define BSP_LED_INDICATE_USER_LED1 BSP_BOARD_LED_0 +#define BSP_LED_INDICATE_USER_LED2 BSP_BOARD_LED_1 +#define BSP_LED_INDICATE_USER_LED3 BSP_BOARD_LED_2 +#define BSP_LED_INDICATE_USER_LED4 BSP_BOARD_LED_3 + +#define BSP_LED_ALERT BSP_BOARD_LED_2 + +#ifdef __cplusplus +} +#endif + +#endif // BSP_CONFIG_H__ + +/** @} */ diff --git a/components/libraries/bsp/bsp_nfc.c b/components/libraries/bsp/bsp_nfc.c new file mode 100644 index 0000000..0baaddf --- /dev/null +++ b/components/libraries/bsp/bsp_nfc.c @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "bsp_nfc.h" +#include "bsp.h" +#include "nrf.h" +#include "app_util_platform.h" + +#ifndef BSP_SIMPLE +#define BTN_ACTION_SLEEP BSP_BUTTON_ACTION_RELEASE /**< Button action used to put the application into sleep mode. */ + +ret_code_t bsp_nfc_btn_init(uint32_t sleep_button) +{ + uint32_t err_code = bsp_event_to_button_action_assign(sleep_button, + BTN_ACTION_SLEEP, + BSP_EVENT_SLEEP); + return err_code; +} + +ret_code_t bsp_nfc_btn_deinit(uint32_t sleep_button) +{ + uint32_t err_code = bsp_event_to_button_action_assign(sleep_button, + BTN_ACTION_SLEEP, + BSP_EVENT_DEFAULT); + return err_code; +} + +ret_code_t bsp_nfc_sleep_mode_prepare(void) +{ +#if defined(NFCT_PRESENT) + // Check if peripheral is not used. + CRITICAL_REGION_ENTER(); +#ifdef NRF52832_XXAA + if ((*(uint32_t *)0x40005410 & 0x07) == 0) +#else + if ((NRF_NFCT->NFCTAGSTATE & NFCT_NFCTAGSTATE_NFCTAGSTATE_Msk) + == NFCT_NFCTAGSTATE_NFCTAGSTATE_Disabled) +#endif // NRF52832_XXAA + { + NRF_NFCT->TASKS_SENSE = 1; + } + CRITICAL_REGION_EXIT(); + return NRF_SUCCESS; +#else + return NRF_ERROR_NOT_SUPPORTED; +#endif +} +#endif //BSP_SIMPLE diff --git a/components/libraries/bsp/bsp_nfc.h b/components/libraries/bsp/bsp_nfc.h new file mode 100644 index 0000000..82d4958 --- /dev/null +++ b/components/libraries/bsp/bsp_nfc.h @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup bsp_nfc NFC BSP Module + * @{ + * @ingroup bsp + * + * @brief Module for setting the NFCT peripheral as a wakeup source. + * + * @details The application must notify this module before going into System OFF mode. + * Based on this notification, the NFC BSP Module sets the NFCT peripheral as a wakeup source + * through the Board Support Package. Additionally, any BSP Button can be configured to + * generate BSP sleep events. This module is applicable only if NFCT is used exclusively for + * wakeup. If NFCT is used for a different purpose, this module cannot be used. + */ + +#ifndef BSP_NFC_H__ +#define BSP_NFC_H__ + +#include +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Function for initializing the NFC Button Module. + * + * Before calling this function, the BSP module must be initialized with buttons. The chosen + * button is used to generate @ref BSP_EVENT_SLEEP events. + * + * @param[in] sleep_button Button ID used to generate @ref BSP_EVENT_SLEEP event. + * + * @retval NRF_SUCCESS If initialization was successful. Otherwise, a propagated error + * code is returned. + */ +ret_code_t bsp_nfc_btn_init(uint32_t sleep_button); + +/**@brief Function for deinitializing the NFC Button Module. + * + * Before calling this function, the BSP module must be initialized with buttons. The chosen + * button is used to generate default @ref BSP_EVENT_DEFAULT events. + * + * @param[in] sleep_button Button ID used to restore default event generation. + * + * @retval NRF_SUCCESS If initialization was successful. Otherwise, a propagated error + * code is returned. + */ +ret_code_t bsp_nfc_btn_deinit(uint32_t sleep_button); + +/**@brief Function for setting up NFCT peripheral as wake-up source. + * + * This function must be called before going into System OFF mode. + * + * @note This function is only applicable if NFCT is used exclusively for wakeup. + * If NFCT is used for a different purpose, this function cannot be used. + * + * @retval NRF_SUCCESS If NFCT peripheral was prepared successfully. Otherwise, + * a propagated error code is returned. + */ +ret_code_t bsp_nfc_sleep_mode_prepare(void); + +#ifdef __cplusplus +} +#endif + +#endif /* BSP_NFC_H__ */ + +/** @} */ diff --git a/components/libraries/button/app_button.c b/components/libraries/button/app_button.c new file mode 100644 index 0000000..68a89f3 --- /dev/null +++ b/components/libraries/button/app_button.c @@ -0,0 +1,349 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(BUTTON) +#include "app_button.h" +#include "app_timer.h" +#include "app_error.h" +#include "nrf_drv_gpiote.h" +#include "nrf_assert.h" + +#define NRF_LOG_MODULE_NAME app_button +#if APP_BUTTON_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL APP_BUTTON_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR APP_BUTTON_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR APP_BUTTON_CONFIG_DEBUG_COLOR +#else //APP_BUTTON_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //APP_BUTTON_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/* + * For each pin state machine is used. Since GPIOTE PORT event is common for all pin is might be + * missed. Module relies on interrupt from GPIOTE only to active periodic app_timer in which pin + * is sampled. Timer is stopped when there is no active buttons (all buttons are in idle state). + * + * Transition to the new state is based on currently sampled button value. State machine has + * following transitions: + * + * ----------------------------------------------------- + * | value | current state | new state | + * |---------------------------------------------------| + * | 0 | IDLE | IDLE | + * | 1 | IDLE | PRESS_ARMED | + * | 0 | PRESS_ARMED | IDLE | + * | 1 | PRESS_ARMED | PRESS_DETECTED | + * | 1 | PRESS_DETECTED | PRESSED (push event) | + * | 0 | PRESS_DETECTED | PRESS_ARMED | + * | 0 | PRESSED | RELEASE_DETECTED | + * | 1 | PRESSED | PRESSED | + * | 0 | RELEASE_DETECTED | IDLE (release event) | + * | 1 | RELEASE_DETECTED | PRESSED | + * ----------------------------------------------------- + * + */ +static app_button_cfg_t const * mp_buttons = NULL; /**< Button configuration. */ +static uint8_t m_button_count; /**< Number of configured buttons. */ +static uint32_t m_detection_delay; /**< Delay before a button is reported as pushed. */ +APP_TIMER_DEF(m_detection_delay_timer_id); /**< Polling timer id. */ + +static uint64_t m_pin_active; + +#define BIT_PER_PIN 4 +#define PINS 32*GPIO_COUNT + +STATIC_ASSERT(BIT_PER_PIN == 4); + +static uint8_t m_pin_states[PINS*BIT_PER_PIN/8]; + +typedef enum { + BTN_IDLE, + BTN_PRESS_ARMED, + BTN_PRESS_DETECTED, + BTN_PRESSED, + BTN_RELEASE_DETECTED +} btn_state_t; + +/* Retrieve given pin state. States are stored in pairs (4 bit per pin) in byte array. */ +static btn_state_t state_get(uint8_t pin) +{ + uint8_t pair_state = m_pin_states[pin >> 1]; + uint8_t state = (pin & 0x1) ? (pair_state >> BIT_PER_PIN) : (pair_state & 0x0F); + + return (btn_state_t)state; +} + +/* Set pin state. */ +static void state_set(uint8_t pin, btn_state_t state) +{ + uint8_t mask = (pin & 1) ? 0x0F : 0xF0; + uint8_t state_mask = (pin & 1) ? + ((uint8_t)state << BIT_PER_PIN) : (uint8_t)state; + m_pin_states[pin >> 1] &= mask; + m_pin_states[pin >> 1] |= state_mask; +} + +/* Find configuration structure for given pin. */ +static app_button_cfg_t const * button_get(uint8_t pin) +{ + for (int i = 0; i < m_button_count; i++) + { + app_button_cfg_t const * p_btn = &mp_buttons[i]; + if (pin == p_btn->pin_no) { + return p_btn; + } + } + + /* If button is not found then configuration is wrong. */ + ASSERT(false); + return NULL; +} + +static void usr_event(uint8_t pin, uint8_t type) +{ + app_button_cfg_t const * p_btn = button_get(pin); + + if (p_btn && p_btn->button_handler) + { + NRF_LOG_DEBUG("Pin %d %s", pin, (type == APP_BUTTON_PUSH) ? "pressed" : "released"); + p_btn->button_handler(pin, type); + } +} + +/* State machine processing. */ +void evt_handle(uint8_t pin, uint8_t value) +{ + switch(state_get(pin)) + { + case BTN_IDLE: + if (value) + { + NRF_LOG_DEBUG("Pin %d idle->armed", pin); + state_set(pin, BTN_PRESS_ARMED); + CRITICAL_REGION_ENTER(); + m_pin_active |= 1ULL << pin; + CRITICAL_REGION_EXIT(); + } + else + { + /* stay in IDLE */ + } + break; + case BTN_PRESS_ARMED: + state_set(pin, value ? BTN_PRESS_DETECTED : BTN_IDLE); + NRF_LOG_DEBUG("Pin %d armed->%s", pin, value ? "detected" : "idle"); + break; + case BTN_PRESS_DETECTED: + if (value) + { + state_set(pin, BTN_PRESSED); + usr_event(pin, APP_BUTTON_PUSH); + } + else + { + state_set(pin, BTN_PRESS_ARMED); + } + NRF_LOG_DEBUG("Pin %d detected->%s", pin, value ? "pressed" : "armed"); + break; + case BTN_PRESSED: + if (value == 0) + { + NRF_LOG_DEBUG("Pin %d pressed->release_detected", pin); + state_set(pin, BTN_RELEASE_DETECTED); + } + else + { + /* stay in pressed */ + } + break; + case BTN_RELEASE_DETECTED: + if (value) + { + state_set(pin, BTN_PRESSED); + } + else + { + state_set(pin, BTN_IDLE); + usr_event(pin, APP_BUTTON_RELEASE); + CRITICAL_REGION_ENTER(); + m_pin_active &= ~(1ULL << pin); + CRITICAL_REGION_EXIT(); + } + NRF_LOG_DEBUG("Pin %d release_detected->%s", pin, value ? "pressed" : "idle"); + break; + } +} + +static void timer_start(void) +{ + uint32_t err_code = app_timer_start(m_detection_delay_timer_id, m_detection_delay/2, NULL); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_WARNING("Failed to start app_timer (err:%d)", err_code); + } +} + +static void detection_delay_timeout_handler(void * p_context) +{ + for (int i = 0; i < m_button_count; i++) + { + app_button_cfg_t const * p_btn = &mp_buttons[i]; + bool is_set = nrf_drv_gpiote_in_is_set(p_btn->pin_no); + bool is_active = !((p_btn->active_state == APP_BUTTON_ACTIVE_HIGH) ^ is_set); + evt_handle(p_btn->pin_no, is_active); + } + + if (m_pin_active) + { + timer_start(); + } + else + { + NRF_LOG_DEBUG("No active buttons, stopping timer"); + } +} + +/* GPIOTE event is used only to start periodic timer when first button is activated. */ +static void gpiote_event_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) +{ + app_button_cfg_t const * p_btn = button_get(pin); + bool is_set = nrf_drv_gpiote_in_is_set(p_btn->pin_no); + bool is_active = !((p_btn->active_state == APP_BUTTON_ACTIVE_HIGH) ^ is_set); + + /* If event indicates that pin is active and no other pin is active start the timer. All + * action happens in timeout event. + */ + if (is_active && (m_pin_active == 0)) + { + NRF_LOG_DEBUG("First active button, starting periodic timer"); + timer_start(); + } +} + +uint32_t app_button_init(app_button_cfg_t const * p_buttons, + uint8_t button_count, + uint32_t detection_delay) +{ + uint32_t err_code; + + if (detection_delay < 2*APP_TIMER_MIN_TIMEOUT_TICKS) + { + return NRF_ERROR_INVALID_PARAM; + } + + if (!nrf_drv_gpiote_is_init()) + { + err_code = nrf_drv_gpiote_init(); + VERIFY_SUCCESS(err_code); + } + + /* Save configuration. */ + mp_buttons = p_buttons; + m_button_count = button_count; + m_detection_delay = detection_delay; + + memset(m_pin_states, 0, sizeof(m_pin_states)); + m_pin_active = 0; + + while (button_count--) + { + app_button_cfg_t const * p_btn = &p_buttons[button_count]; + +#if defined(BUTTON_HIGH_ACCURACY_ENABLED) && (BUTTON_HIGH_ACCURACY_ENABLED == 1) + nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(p_btn->hi_accuracy); +#else + nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false); +#endif + config.pull = p_btn->pull_cfg; + + err_code = nrf_drv_gpiote_in_init(p_btn->pin_no, &config, gpiote_event_handler); + VERIFY_SUCCESS(err_code); + } + + /* Create polling timer. */ + return app_timer_create(&m_detection_delay_timer_id, + APP_TIMER_MODE_SINGLE_SHOT, + detection_delay_timeout_handler); +} + +uint32_t app_button_enable(void) +{ + ASSERT(mp_buttons); + + uint32_t i; + for (i = 0; i < m_button_count; i++) + { + nrf_drv_gpiote_in_event_enable(mp_buttons[i].pin_no, true); + } + + return NRF_SUCCESS; +} + + +uint32_t app_button_disable(void) +{ + ASSERT(mp_buttons); + + uint32_t i; + for (i = 0; i < m_button_count; i++) + { + nrf_drv_gpiote_in_event_disable(mp_buttons[i].pin_no); + } + CRITICAL_REGION_ENTER(); + m_pin_active = 0; + CRITICAL_REGION_EXIT(); + + /* Make sure polling timer is not running. */ + return app_timer_stop(m_detection_delay_timer_id); +} + + +bool app_button_is_pushed(uint8_t button_id) +{ + ASSERT(button_id <= m_button_count); + ASSERT(mp_buttons != NULL); + + app_button_cfg_t const * p_btn = &mp_buttons[button_id]; + bool is_set = nrf_drv_gpiote_in_is_set(p_btn->pin_no); + + return !(is_set ^ (p_btn->active_state == APP_BUTTON_ACTIVE_HIGH)); +} +#endif //NRF_MODULE_ENABLED(BUTTON) diff --git a/components/libraries/button/app_button.h b/components/libraries/button/app_button.h new file mode 100644 index 0000000..87b26ee --- /dev/null +++ b/components/libraries/button/app_button.h @@ -0,0 +1,140 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup app_button Button Handler + * @{ + * @ingroup app_common + * + * @brief Buttons handling module. + * + * @details The button handler uses the @ref app_gpiote to detect that a button has been + * pushed. To handle debouncing, it will start a timer in the GPIOTE event handler. + * The button will only be reported as pushed if the corresponding pin is still active when + * the timer expires. If there is a new GPIOTE event while the timer is running, the timer + * is restarted. + * + * @note The app_button module uses the app_timer module. The user must ensure that the queue in + * app_timer is large enough to hold the app_timer_stop() / app_timer_start() operations + * which will be executed on each event from GPIOTE module (2 operations), as well as other + * app_timer operations queued simultaneously in the application. + * + * @note Even if the scheduler is not used, app_button.h will include app_scheduler.h, so when + * compiling, app_scheduler.h must be available in one of the compiler include paths. + */ + +#ifndef APP_BUTTON_H__ +#define APP_BUTTON_H__ + +#include +#include +#include "nrf.h" +#include "app_error.h" +#include "nrf_gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define APP_BUTTON_PUSH 1 /**< Indicates that a button is pushed. */ +#define APP_BUTTON_RELEASE 0 /**< Indicates that a button is released. */ +#define APP_BUTTON_ACTIVE_HIGH 1 /**< Indicates that a button is active high. */ +#define APP_BUTTON_ACTIVE_LOW 0 /**< Indicates that a button is active low. */ + +/**@brief Button event handler type. */ +typedef void (*app_button_handler_t)(uint8_t pin_no, uint8_t button_action); + +/**@brief Button configuration structure. */ +typedef struct +{ + uint8_t pin_no; /**< Pin to be used as a button. */ + uint8_t active_state; /**< APP_BUTTON_ACTIVE_HIGH or APP_BUTTON_ACTIVE_LOW. */ +#if defined(BUTTON_HIGH_ACCURACY_ENABLED) && (BUTTON_HIGH_ACCURACY_ENABLED == 1) + bool hi_accuracy; /**< True if GPIOTE high accuracy (IN_EVENT) is used. */ +#endif + nrf_gpio_pin_pull_t pull_cfg; /**< Pull-up or -down configuration. */ + app_button_handler_t button_handler; /**< Handler to be called when button is pushed. */ +} app_button_cfg_t; + +/**@brief Function for initializing the Buttons. + * + * @details This function will initialize the specified pins as buttons, and configure the Button + * Handler module as a GPIOTE user (but it will not enable button detection). + * + * @note app_button_enable() function must be called in order to enable the button detection. + * + * @param[in] p_buttons Array of buttons to be used (NOTE: Must be static!). + * @param[in] button_count Number of buttons. + * @param[in] detection_delay Delay from a GPIOTE event until a button is reported as pushed. + * + * @return NRF_SUCCESS on success, otherwise an error code. + */ +uint32_t app_button_init(app_button_cfg_t const * p_buttons, + uint8_t button_count, + uint32_t detection_delay); + +/**@brief Function for enabling button detection. + * + * @retval NRF_SUCCESS Module successfully enabled. + */ +uint32_t app_button_enable(void); + +/**@brief Function for disabling button detection. + * + * @retval NRF_SUCCESS Button detection successfully disabled. Error code otherwise. + */ +uint32_t app_button_disable(void); + +/**@brief Function for checking if a button is currently being pushed. + * + * @param[in] button_id Button index (in the app_button_cfg_t array given to app_button_init) to be checked. + * + * @return Button state. + */ +bool app_button_is_pushed(uint8_t button_id); + + +#ifdef __cplusplus +} +#endif + +#endif // APP_BUTTON_H__ + +/** @} */ diff --git a/components/libraries/cli/ble_uart/nrf_cli_ble_uart.c b/components/libraries/cli/ble_uart/nrf_cli_ble_uart.c new file mode 100644 index 0000000..60aee6c --- /dev/null +++ b/components/libraries/cli/ble_uart/nrf_cli_ble_uart.c @@ -0,0 +1,317 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CLI_BLE_UART) +#include "nrf_cli_ble_uart.h" +#include "ble_nus.h" +#include "nrf_ringbuf.h" +#include "app_timer.h" +#include "nrf_assert.h" +#include "nrf_ble_gatt.h" +#define NRF_LOG_MODULE_NAME cli_ble + +#if NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR NRF_CLI_BLE_UART_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR + +#else //NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#if NRF_CLI_BLE_UART_MAX_CLIENTS > NRF_SDH_BLE_TOTAL_LINK_COUNT + #error "Too few BLE peripheral links are supported by the BLE SDH module for the maximal number \ + of BLE transport instances" +#endif + +#define NRF_CLI_BLE_UART_TIMEOUT_MS 50 +#define OVERHEAD_LENGTH (OPCODE_LENGTH + HANDLE_LENGTH) + +BLE_NUS_DEF(m_nus, NRF_CLI_BLE_UART_MAX_CLIENTS); +BLE_LINK_CTX_MANAGER_DEF(m_link_ctx_storage, + NRF_CLI_BLE_UART_MAX_CLIENTS, + sizeof(nrf_cli_ble_uart_internal_t *)); + +static void tx_try(nrf_cli_ble_uart_internal_t * p_instance, uint32_t threshold) +{ + uint8_t * p_out_data; + size_t out_data_len = + nrf_ble_gatt_eff_mtu_get(p_instance->p_gatt, p_instance->p_cb->conn_handle) - + OVERHEAD_LENGTH; + + ret_code_t err_code = nrf_ringbuf_get(p_instance->p_tx_ringbuf, + &p_out_data, + &out_data_len, + true); + + if (err_code == NRF_SUCCESS) + { + if (out_data_len >= threshold) + { + size_t req_data_len = out_data_len; + err_code = ble_nus_data_send(&m_nus, + p_out_data, + (uint16_t*)&out_data_len, + p_instance->p_cb->conn_handle); + + if ((err_code == NRF_ERROR_BUSY) || (err_code == NRF_ERROR_RESOURCES)) + { + out_data_len = 0; + } + NRF_LOG_INFO("Conn_handle:%d TX req_len: %d, len: %d", + p_instance->p_cb->conn_handle, req_data_len, out_data_len); + NRF_LOG_HEXDUMP_DEBUG(p_out_data, out_data_len); + err_code = nrf_ringbuf_free(p_instance->p_tx_ringbuf, out_data_len); + ASSERT(err_code == NRF_SUCCESS); + } + else + { + err_code = nrf_ringbuf_free(p_instance->p_tx_ringbuf, 0); + ASSERT(err_code == NRF_SUCCESS); + } + } +} + +static void nus_data_handler(ble_nus_evt_t * p_nus_evt) +{ + ret_code_t err_code = NRF_SUCCESS; + nrf_cli_ble_uart_internal_t * p_instance; + nrf_cli_ble_uart_internal_t ** pp_instance; + + err_code = blcm_link_ctx_get(&m_link_ctx_storage, p_nus_evt->conn_handle, (void *) &pp_instance); + ASSERT(err_code == NRF_SUCCESS); + + p_instance = *pp_instance; + + switch (p_nus_evt->type) + { + case BLE_NUS_EVT_RX_DATA: + { + NRF_LOG_INFO("Conn_handle:%d, Received: %d", + p_instance->p_cb->conn_handle, p_nus_evt->params.rx_data.length); + NRF_LOG_HEXDUMP_DEBUG(p_nus_evt->params.rx_data.p_data, p_nus_evt->params.rx_data.length); + size_t len = ((size_t) p_nus_evt->params.rx_data.length) & 0x0000FFFF; + err_code = nrf_ringbuf_cpy_put(p_instance->p_rx_ringbuf, + p_nus_evt->params.rx_data.p_data, + (size_t *)&len); + ASSERT(err_code == NRF_SUCCESS); + + p_instance->p_cb->handler(NRF_CLI_TRANSPORT_EVT_RX_RDY, p_instance->p_cb->p_context); + break; + } + case BLE_NUS_EVT_TX_RDY: + { + //TX_Complete + uint32_t max_tx_len = nrf_ble_gatt_eff_mtu_get(p_instance->p_gatt, + p_instance->p_cb->conn_handle) - + OVERHEAD_LENGTH; + tx_try(p_instance, max_tx_len); + p_instance->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, p_instance->p_cb->p_context); + break; + } + case BLE_NUS_EVT_COMM_STARTED: + p_instance->p_cb->service_started = true; + err_code = app_timer_start(*p_instance->p_timer, + APP_TIMER_TICKS(NRF_CLI_BLE_UART_TIMEOUT_MS), + p_instance); + ASSERT(err_code == NRF_SUCCESS); + NRF_LOG_INFO("Conn_handle:%d, communication started", p_instance->p_cb->conn_handle); + break; + case BLE_NUS_EVT_COMM_STOPPED: + (void)app_timer_stop(*p_instance->p_timer); + p_instance->p_cb->service_started = false; + NRF_LOG_INFO("Conn_handle:%d, communication stopped", p_instance->p_cb->conn_handle); + break; + default: + break; + } +} + +static void timer_handler(void * p_context) +{ + nrf_cli_ble_uart_internal_t * p_instance = (nrf_cli_ble_uart_internal_t *) p_context; + tx_try(p_instance, 1); + + ret_code_t err_code = app_timer_start(*p_instance->p_timer, + APP_TIMER_TICKS(NRF_CLI_BLE_UART_TIMEOUT_MS), (void *)p_instance); + ASSERT(err_code == NRF_SUCCESS); + UNUSED_VARIABLE(err_code); + UNUSED_PARAMETER(p_context); +} + +ret_code_t nrf_cli_ble_uart_service_init(void) +{ + ble_nus_init_t nus_init; + + memset(&nus_init, 0, sizeof(nus_init)); + nus_init.data_handler = nus_data_handler; + + return ble_nus_init(&m_nus, &nus_init); +} + +static ret_code_t cli_ble_uart_init(nrf_cli_transport_t const * p_transport, + void const * p_config, + nrf_cli_transport_handler_t evt_handler, + void * p_context) +{ + ret_code_t err_code; + nrf_cli_ble_uart_internal_t ** pp_instance; + nrf_cli_ble_uart_internal_t * p_instance = + CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport); + nrf_cli_ble_uart_config_t * p_ble_uart_config = (nrf_cli_ble_uart_config_t *)p_config; + + p_instance->p_cb->handler = evt_handler; + p_instance->p_cb->p_context = p_context; + p_instance->p_cb->service_started = false; + p_instance->p_cb->conn_handle = p_ble_uart_config->conn_handle; + + NRF_LOG_INFO("Conn_handle:%d init.", p_ble_uart_config->conn_handle); + nrf_ringbuf_init(p_instance->p_rx_ringbuf); + nrf_ringbuf_init(p_instance->p_tx_ringbuf); + + err_code = blcm_link_ctx_get(&m_link_ctx_storage, + p_ble_uart_config->conn_handle, + (void *) &pp_instance); + VERIFY_SUCCESS(err_code); + + *pp_instance = p_instance; + + return NRF_SUCCESS; +} + +static ret_code_t cli_ble_uart_uninit(nrf_cli_transport_t const * p_transport) +{ + nrf_cli_ble_uart_internal_t * p_instance = + CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport); + + NRF_LOG_INFO("Conn_handle:%d uninit.", p_instance->p_cb->conn_handle); + ret_code_t ret = app_timer_stop(*p_instance->p_timer); + + return ret; +} + +static ret_code_t cli_ble_uart_enable(nrf_cli_transport_t const * p_transport, bool blocking) +{ + nrf_cli_ble_uart_internal_t * p_instance = + CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport); + + + NRF_LOG_INFO("Conn_handle:%d, enable blocking:%d", blocking, p_instance->p_cb->conn_handle); + if (blocking) + { + return NRF_ERROR_NOT_SUPPORTED; + } + else + { + ret_code_t err_code = NRF_SUCCESS; + if (!p_instance->p_cb->timer_created) + { + err_code = app_timer_create(p_instance->p_timer, + APP_TIMER_MODE_SINGLE_SHOT, + timer_handler); + p_instance->p_cb->timer_created = true; + } + return err_code; + } +} + +static ret_code_t cli_ble_uart_read(nrf_cli_transport_t const * p_transport, + void * p_data, + size_t length, + size_t * p_cnt) +{ + ASSERT(p_cnt); + nrf_cli_ble_uart_internal_t * p_instance = + CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport); + *p_cnt = length; + ret_code_t err_code = nrf_ringbuf_cpy_get(p_instance->p_rx_ringbuf, p_data, p_cnt); + + if (*p_cnt) + { + NRF_LOG_INFO("Conn_handle:%d, read req_len:%d read_len: %d", + p_instance->p_cb->conn_handle, + length, + *p_cnt); + NRF_LOG_HEXDUMP_DEBUG(p_data, *p_cnt); + } + + return err_code; +} + +static ret_code_t cli_ble_uart_write(nrf_cli_transport_t const * p_transport, + const void * p_data, + size_t length, + size_t * p_cnt) +{ + ASSERT(p_cnt); + nrf_cli_ble_uart_internal_t * p_instance = + CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport); + ret_code_t err_code = NRF_SUCCESS; + if (p_instance->p_cb->service_started) + { + *p_cnt = length; + err_code = nrf_ringbuf_cpy_put(p_instance->p_tx_ringbuf, p_data, p_cnt); + + NRF_LOG_INFO("Conn_handle:%d, write req:%d, buffered:%d", + p_instance->p_cb->conn_handle, length, *p_cnt); + NRF_LOG_HEXDUMP_DEBUG(p_data, *p_cnt); + } + else + { + NRF_LOG_INFO("Conn_handle:%d, write req:%d. Notifications not enabled", + p_instance->p_cb->conn_handle, length); + *p_cnt = length; + p_instance->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, p_instance->p_cb->p_context); + } + return err_code; +} + +const nrf_cli_transport_api_t nrf_cli_ble_uart_transport_api = { + .init = cli_ble_uart_init, + .uninit = cli_ble_uart_uninit, + .enable = cli_ble_uart_enable, + .read = cli_ble_uart_read, + .write = cli_ble_uart_write, +}; + +#endif //NRF_MODULE_ENABLED(NRF_CLI_BLE_UART) diff --git a/components/libraries/cli/ble_uart/nrf_cli_ble_uart.h b/components/libraries/cli/ble_uart/nrf_cli_ble_uart.h new file mode 100644 index 0000000..b02a6f9 --- /dev/null +++ b/components/libraries/cli/ble_uart/nrf_cli_ble_uart.h @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_CLI_BLE_UART_H__ +#define NRF_CLI_BLE_UART_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_cli.h" +#include "ble.h" +#include "app_timer.h" +#include "nrf_ringbuf.h" +#include "nordic_common.h" +#include "nrf_ble_gatt.h" +/**@file + * + * @defgroup nrf_cli_ble_uart BLE UART command line interface transport layer + * @ingroup nrf_cli + * + * @{ + * + */ + +/** + * @brief Command line interface transport. + */ + +ret_code_t nrf_cli_ble_uart_service_init(void); + +extern const nrf_cli_transport_api_t nrf_cli_ble_uart_transport_api; + +typedef struct nrf_cli_ble_uart_internal_s nrf_cli_ble_uart_internal_t; + +typedef struct { + nrf_cli_transport_handler_t handler; + void * p_context; + uint16_t conn_handle; + bool timer_created; + bool service_started; +} nrf_cli_ble_uart_internal_cb_t; + + +struct nrf_cli_ble_uart_internal_s { + nrf_cli_transport_t transport; + nrf_cli_ble_uart_internal_cb_t * p_cb; + app_timer_id_t const * p_timer; + nrf_ringbuf_t const * p_rx_ringbuf; + nrf_ringbuf_t const * p_tx_ringbuf; + nrf_ble_gatt_t const * p_gatt; +}; + +typedef struct { + uint16_t conn_handle; +} nrf_cli_ble_uart_config_t; + +/**@brief CLI Bluetooth transport definition. + * + * @param _name Name of the instance. + * @param _p_gatt Pointer to the nrf_ble_gatt module. + * @param _tx_buf_sz Size of TX ring buffer. + * @param _rx_buf_sz Size of RX ring buffer. + */ +#define NRF_CLI_BLE_UART_DEF(_name, _p_gatt, _tx_buf_sz, _rx_buf_sz) \ + APP_TIMER_DEF(CONCAT_2(_name, _timer)); \ + NRF_RINGBUF_DEF(CONCAT_2(_name,_tx_ringbuf), _tx_buf_sz); \ + NRF_RINGBUF_DEF(CONCAT_2(_name,_rx_ringbuf), _rx_buf_sz); \ + static nrf_cli_ble_uart_internal_cb_t CONCAT_2(_name, _cb); \ + static const nrf_cli_ble_uart_internal_t _name = { \ + .transport = {.p_api = &nrf_cli_ble_uart_transport_api}, \ + .p_cb = &CONCAT_2(_name, _cb), \ + .p_timer = &CONCAT_2(_name, _timer), \ + .p_rx_ringbuf = &CONCAT_2(_name,_rx_ringbuf), \ + .p_tx_ringbuf = &CONCAT_2(_name,_tx_ringbuf), \ + .p_gatt = _p_gatt, \ + } + + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_CLI_BLE_UART_H__ */ diff --git a/components/libraries/cli/cdc_acm/nrf_cli_cdc_acm.c b/components/libraries/cli/cdc_acm/nrf_cli_cdc_acm.c new file mode 100644 index 0000000..c1cfe3f --- /dev/null +++ b/components/libraries/cli/cdc_acm/nrf_cli_cdc_acm.c @@ -0,0 +1,243 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CLI_CDC_ACM) +#include "nrf_cli_cdc_acm.h" +#include "nrf_queue.h" +#include "app_error.h" +#include "nrf_assert.h" + + +#if APP_USBD_CONFIG_EVENT_QUEUE_ENABLE +#error "Current CLI CDC implementation supports only USB with event queue disabled (see APP_USBD_CONFIG_EVENT_QUEUE_ENABLE)" +#endif + +static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_cdc_acm_user_event_t event); + +/*lint -save -e26 -e40 -e64 -e123 -e505 -e651*/ + +/** + * @brief CDC_ACM class instance. + * */ +APP_USBD_CDC_ACM_GLOBAL_DEF(nrf_cli_cdc_acm, + cdc_acm_user_ev_handler, + NRF_CLI_CDC_ACM_COMM_INTERFACE, + NRF_CLI_CDC_ACM_DATA_INTERFACE, + NRF_CLI_CDC_ACM_COMM_EPIN, + NRF_CLI_CDC_ACM_DATA_EPIN, + NRF_CLI_CDC_ACM_DATA_EPOUT, + APP_USBD_CDC_COMM_PROTOCOL_AT_V250 +); + +/*lint -restore*/ + +NRF_QUEUE_DEF(uint8_t, + m_rx_queue, + 2*NRF_DRV_USBD_EPSIZE, + NRF_QUEUE_MODE_OVERFLOW); + +static char m_rx_buffer[NRF_DRV_USBD_EPSIZE]; + +static nrf_cli_cdc_acm_internal_t * mp_internal; + +/** + * @brief Set new buffer and process any data if already present + * + * This is internal function. + * The result of its execution is the library waiting for the event of the new data. + * If there is already any data that was returned from the CDC internal buffer + * it would be processed here. + */ +static void cdc_acm_process_and_prepare_buffer(app_usbd_cdc_acm_t const * p_cdc_acm) +{ + for (;;) + { + if (!nrf_queue_is_empty(&m_rx_queue)) + { + mp_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_RX_RDY, mp_internal->p_cb->p_context); + } + ret_code_t ret = app_usbd_cdc_acm_read_any(&nrf_cli_cdc_acm, + m_rx_buffer, + sizeof(m_rx_buffer)); + if (ret == NRF_SUCCESS) + { + size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm); + size_t qsize = nrf_queue_in(&m_rx_queue, m_rx_buffer, size); + ASSERT(size == qsize); + UNUSED_VARIABLE(qsize); + } + else if (ret == NRF_ERROR_IO_PENDING) + { + break; + } + else + { + APP_ERROR_CHECK(ret); + break; + } + } +} + +/** + * @brief User event handler. + * */ +static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_cdc_acm_user_event_t event) +{ + app_usbd_cdc_acm_t const * p_cdc_acm = app_usbd_cdc_acm_class_get(p_inst); + + + switch (event) + { + case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN: + { + /*Setup first transfer*/ + cdc_acm_process_and_prepare_buffer(p_cdc_acm); + break; + } + case APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE: + mp_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, mp_internal->p_cb->p_context); + break; + case APP_USBD_CDC_ACM_USER_EVT_TX_DONE: + mp_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, mp_internal->p_cb->p_context); + break; + case APP_USBD_CDC_ACM_USER_EVT_RX_DONE: + { + /*Get amount of data transfered*/ + size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm); + size_t qsize = nrf_queue_in(&m_rx_queue, m_rx_buffer, size); + ASSERT(size == qsize); + UNUSED_VARIABLE(qsize); + + /*Setup next transfer*/ + cdc_acm_process_and_prepare_buffer(p_cdc_acm); + break; + } + default: + break; + } +} + +static ret_code_t cli_cdc_acm_init(nrf_cli_transport_t const * p_transport, + void const * p_config, + nrf_cli_transport_handler_t evt_handler, + void * p_context) +{ + UNUSED_PARAMETER(p_config); + nrf_cli_cdc_acm_internal_t * p_internal = + CONTAINER_OF(p_transport, nrf_cli_cdc_acm_internal_t, transport); + p_internal->p_cb->handler = evt_handler; + p_internal->p_cb->p_context = p_context; + + mp_internal = p_internal; + return NRF_SUCCESS; +} + +static ret_code_t cli_cdc_acm_uninit(nrf_cli_transport_t const * p_transport) +{ + UNUSED_PARAMETER(p_transport); + return NRF_SUCCESS; +} + +static ret_code_t cli_cdc_acm_enable(nrf_cli_transport_t const * p_transport, + bool blocking) +{ + UNUSED_PARAMETER(p_transport); + if (blocking) + { + return NRF_ERROR_NOT_SUPPORTED; + } + else + { + return NRF_SUCCESS; + } +} + +static ret_code_t cli_cdc_acm_read(nrf_cli_transport_t const * p_transport, + void * p_data, + size_t length, + size_t * p_cnt) +{ + ASSERT(p_cnt); + UNUSED_PARAMETER(p_transport); + size_t size = nrf_queue_out(&m_rx_queue, p_data, length); + *p_cnt = size; + + return NRF_SUCCESS; +} + +static ret_code_t cli_cdc_acm_write(nrf_cli_transport_t const * p_transport, + void const * p_data, + size_t length, + size_t * p_cnt) +{ + ASSERT(p_cnt); + UNUSED_PARAMETER(p_transport); + ret_code_t ret; + + ret = app_usbd_cdc_acm_write(&nrf_cli_cdc_acm, p_data, length); + if (ret == NRF_SUCCESS || ret == NRF_ERROR_INVALID_STATE) + { + *p_cnt = length; + ret = NRF_SUCCESS; + } + else if (ret == NRF_ERROR_BUSY) + { + *p_cnt = 0; + ret = NRF_SUCCESS; + } + else + { + /* Nothing to do */ + } + + return ret; +} + +const nrf_cli_transport_api_t nrf_cli_cdc_acm_transport_api = { + .init = cli_cdc_acm_init, + .uninit = cli_cdc_acm_uninit, + .enable = cli_cdc_acm_enable, + .read = cli_cdc_acm_read, + .write = cli_cdc_acm_write, +}; + +#endif // NRF_MODULE_ENABLED(NRF_CLI_CDC_ACM) diff --git a/components/libraries/cli/cdc_acm/nrf_cli_cdc_acm.h b/components/libraries/cli/cdc_acm/nrf_cli_cdc_acm.h new file mode 100644 index 0000000..e472295 --- /dev/null +++ b/components/libraries/cli/cdc_acm/nrf_cli_cdc_acm.h @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_CLI_CDC_ACM_H__ +#define NRF_CLI_CDC_ACM_H__ + +#include + +#include "nrf_cli.h" +#include "app_usbd_cdc_acm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@file + * + * @defgroup nrf_cli_cdc_acm CDC ACM command line interface transport layer + * @ingroup nrf_cli + * + * @{ + * + */ + +/** + * @brief Command line interface transport. + */ +extern const nrf_cli_transport_api_t nrf_cli_cdc_acm_transport_api; + +/** + * @brief Command line interface class instance. + */ +extern const app_usbd_cdc_acm_t nrf_cli_cdc_acm; + +typedef struct { + nrf_cli_transport_handler_t handler; + void * p_context; +} nrf_cli_cdc_acm_internal_cb_t; + +typedef struct { + nrf_cli_transport_t transport; + nrf_cli_cdc_acm_internal_cb_t * p_cb; +} nrf_cli_cdc_acm_internal_t; + +/**@brief CLI USB transport definition */ +#define NRF_CLI_CDC_ACM_DEF(_name_) \ + static nrf_cli_cdc_acm_internal_cb_t CONCAT_2(_name_, _cb); \ + static const nrf_cli_cdc_acm_internal_t _name_ = { \ + .transport = {.p_api = &nrf_cli_cdc_acm_transport_api}, \ + .p_cb = &CONCAT_2(_name_, _cb), \ + } + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_CLI_CDC_ACM_H__ */ diff --git a/components/libraries/cli/cli_utils_cmds.c b/components/libraries/cli/cli_utils_cmds.c new file mode 100644 index 0000000..4555723 --- /dev/null +++ b/components/libraries/cli/cli_utils_cmds.c @@ -0,0 +1,164 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_cli.h" +#include "nrf_log.h" + +static void cmd_reset(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + + NVIC_SystemReset(); +} + + +static void cmd_error(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + + APP_ERROR_CHECK(NRF_ERROR_INTERNAL); +} + + +static void cmd_app_size(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + + nrf_cli_fprintf(p_cli, + NRF_CLI_NORMAL, + "Application address:%d (0x%08X), size: %d (0x%08X)\r\n", + CODE_START, + CODE_START, + CODE_SIZE, + CODE_SIZE); +} + + +static void cmd_log_msg_error(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + + switch (argc-1) + { + case 0: + NRF_LOG_ERROR("test error message"); + break; + case 1: + NRF_LOG_ERROR("test error message: %d", strtol(argv[1], NULL, 10)); + break; + case 2: + NRF_LOG_ERROR("test error message: %d %d", strtol(argv[1], NULL, 10), + strtol(argv[2], NULL, 10)); + break; + default: + NRF_LOG_ERROR("test error message with more than 3 arguments"); + break; + } +} + + +static void cmd_log_msg_warning(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + + switch (argc-1) + { + case 0: + NRF_LOG_WARNING("test warning message"); + break; + case 1: + NRF_LOG_WARNING("test warning message: %d", strtol(argv[1], NULL, 10)); + break; + case 2: + NRF_LOG_WARNING("test warning message: %d %d", strtol(argv[1], NULL, 10), + strtol(argv[2], NULL, 10)); + break; + default: + NRF_LOG_WARNING("test warning message with more than 3 arguments"); + break; + } +} + +/** + * @brief Command set array + * */ + +NRF_CLI_CMD_REGISTER(reset, NULL, "System reset.", cmd_reset); + +NRF_CLI_CMD_REGISTER(error, NULL, "Trigger error.", cmd_error); + +NRF_CLI_CMD_REGISTER(app_size, NULL, "Print application size.", cmd_app_size); + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_log_msg) +{ + NRF_CLI_CMD(error, NULL, "Error log message with parameters", cmd_log_msg_error), + NRF_CLI_CMD(warning, NULL, "Warning log message with parameters", cmd_log_msg_warning), + NRF_CLI_SUBCMD_SET_END +}; + +NRF_CLI_CMD_REGISTER(log_msg, &m_sub_log_msg, "Trigger log message with decimal arguments", NULL); diff --git a/components/libraries/cli/libuarte/nrf_cli_libuarte.c b/components/libraries/cli/libuarte/nrf_cli_libuarte.c new file mode 100644 index 0000000..f879c2f --- /dev/null +++ b/components/libraries/cli/libuarte/nrf_cli_libuarte.c @@ -0,0 +1,252 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#include "nrf_cli_libuarte.h" +#include "nrf_libuarte_async.h" +#include "nrf_assert.h" +#include "nrf_atomic.h" +#define NRF_LOG_MODULE_NAME cli_libuarte +#if NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL NRF_CLI_LIBUARTE_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR NRF_CLI_LIBUARTE_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR NRF_CLI_LIBUARTE_CONFIG_DEBUG_COLOR +#else //NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +static cli_libuarte_internal_t * mp_internal; +static nrf_atomic_flag_t m_uart_busy; + +NRF_LIBUARTE_ASYNC_DEFINE(libuarte, + NRF_CLI_LIBUARTE_UARTE_INSTANCE, + NRF_CLI_LIBUARTE_TIMER_INSTANCE, + NRF_CLI_LIBUARTE_TIMEOUT_RTC_INSTANCE, + NRF_CLI_LIBUARTE_TIMEOUT_TIMER_INSTANCE, + 3, 255); + +static void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_event) +{ + cli_libuarte_internal_t * p_internal = mp_internal; + ret_code_t err_code = NRF_SUCCESS; + size_t len; + UNUSED_VARIABLE(err_code); + switch (p_event->type) + { + case NRF_LIBUARTE_ASYNC_EVT_ERROR: + NRF_LOG_WARNING("(evt) ERROR"); + + break; + + case NRF_LIBUARTE_ASYNC_EVT_RX_DATA: + { + len = (size_t)((uint32_t)p_event->data.rxtx.length & 0x0000FFFF); + err_code = nrf_ringbuf_cpy_put(p_internal->p_rx_ringbuf, + p_event->data.rxtx.p_data, + &len); + ASSERT(err_code == NRF_SUCCESS); + + if (len != p_event->data.rxtx.length) + { + NRF_LOG_WARNING("Data lost, no room in RX ringbuf"); + } + nrf_libuarte_async_rx_free(&libuarte, p_event->data.rxtx.p_data, p_event->data.rxtx.length); + + if (p_event->data.rxtx.length) + { + NRF_LOG_DEBUG("(evt) RXRDY length:%d", p_event->data.rxtx.length); + NRF_LOG_HEXDUMP_DEBUG(p_event->data.rxtx.p_data, p_event->data.rxtx.length); + p_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_RX_RDY, + p_internal->p_cb->p_context); + } + + break; + } + + case NRF_LIBUARTE_ASYNC_EVT_TX_DONE: + err_code = nrf_ringbuf_free(p_internal->p_tx_ringbuf, p_event->data.rxtx.length); + ASSERT(err_code == NRF_SUCCESS); + uint8_t * p_data; + len = 255; + err_code = nrf_ringbuf_get(p_internal->p_tx_ringbuf, &p_data, &len, true); + ASSERT(err_code == NRF_SUCCESS); + if (len) + { + NRF_LOG_DEBUG("(evt) Started TX (%d).", len); + err_code = nrf_libuarte_async_tx(&libuarte, p_data, len); + ASSERT(err_code == NRF_SUCCESS); + } + else + { + m_uart_busy = false; + } + p_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, p_internal->p_cb->p_context); + NRF_LOG_DEBUG("(evt) TX completed (%d)", p_event->data.rxtx.length); + break; + + default: + NRF_LOG_ERROR("(evt) Unknown event"); + ASSERT(false); + break; + } +} + +static ret_code_t cli_libuarte_init(nrf_cli_transport_t const * p_transport, + void const * p_config, + nrf_cli_transport_handler_t evt_handler, + void * p_context) +{ + cli_libuarte_internal_t * p_internal = CONTAINER_OF(p_transport, + cli_libuarte_internal_t, + transport); + mp_internal = p_internal; + m_uart_busy = false; + + p_internal->p_cb->handler = evt_handler; + p_internal->p_cb->p_context = p_context; + p_internal->p_cb->blocking = false; + + cli_libuarte_config_t const * p_cli_libuarte_config = (cli_libuarte_config_t *)p_config; + nrf_libuarte_async_config_t uart_async_config = { + .tx_pin = p_cli_libuarte_config->tx_pin, + .rx_pin = p_cli_libuarte_config->rx_pin, + .baudrate = p_cli_libuarte_config->baudrate, + .parity = p_cli_libuarte_config->parity, + .hwfc = p_cli_libuarte_config->hwfc, + .timeout_us = 100, + .int_prio = APP_IRQ_PRIORITY_LOW + }; + ret_code_t err_code = nrf_libuarte_async_init(&libuarte, &uart_async_config, uart_event_handler, NULL); + if (err_code == NRF_SUCCESS) + { + nrf_ringbuf_init(p_internal->p_rx_ringbuf); + nrf_ringbuf_init(p_internal->p_tx_ringbuf); + } + return err_code; +} + +static ret_code_t cli_libuarte_uninit(nrf_cli_transport_t const * p_transport) +{ + UNUSED_PARAMETER(p_transport); + nrf_libuarte_async_uninit(&libuarte); + return NRF_SUCCESS; +} + +static ret_code_t cli_libuarte_enable(nrf_cli_transport_t const * p_transport, + bool blocking) +{ + UNUSED_PARAMETER(p_transport); + if (blocking) + { + return NRF_ERROR_NOT_SUPPORTED; + } + else + { + nrf_libuarte_async_enable(&libuarte); + } + return NRF_SUCCESS; +} + +static ret_code_t cli_libuarte_read(nrf_cli_transport_t const * p_transport, + void * p_data, + size_t length, + size_t * p_cnt) +{ + ASSERT(p_cnt); + cli_libuarte_internal_t * p_instance = + CONTAINER_OF(p_transport, cli_libuarte_internal_t, transport); + + *p_cnt = length; + ret_code_t err_code = nrf_ringbuf_cpy_get(p_instance->p_rx_ringbuf, p_data, p_cnt); + + if (*p_cnt) + { + NRF_LOG_DEBUG("Read %d bytes (requested %d)", *p_cnt, length); + } + + return err_code; +} + +static ret_code_t cli_libuarte_write(nrf_cli_transport_t const * p_transport, + void const * p_data, + size_t length, + size_t * p_cnt) +{ + ASSERT(p_cnt); + cli_libuarte_internal_t * p_instance = CONTAINER_OF(p_transport, + cli_libuarte_internal_t, + transport); + *p_cnt = length; + ret_code_t err_code = nrf_ringbuf_cpy_put(p_instance->p_tx_ringbuf, p_data, p_cnt); + if (err_code == NRF_SUCCESS) + { + NRF_LOG_DEBUG("Requested write: %d, copied to ringbuf: %d.", length, *p_cnt); + + if (nrf_atomic_flag_set_fetch(&m_uart_busy)) + { + return err_code; + } + + uint8_t * p_buf; + size_t len = 255; + if (nrf_ringbuf_get(p_instance->p_tx_ringbuf, &p_buf, &len, true) == NRF_SUCCESS) + { + NRF_LOG_DEBUG("Started TX (%d).", len); + + err_code = nrf_libuarte_async_tx(&libuarte, p_buf, len); + if (p_instance->p_cb->blocking && (err_code == NRF_SUCCESS)) + { + (void)nrf_ringbuf_free(p_instance->p_tx_ringbuf, len); + m_uart_busy = false; + } + } + } + return err_code; +} + +const nrf_cli_transport_api_t cli_libuarte_transport_api = { + .init = cli_libuarte_init, + .uninit = cli_libuarte_uninit, + .enable = cli_libuarte_enable, + .read = cli_libuarte_read, + .write = cli_libuarte_write, +}; + diff --git a/components/libraries/cli/libuarte/nrf_cli_libuarte.h b/components/libraries/cli/libuarte/nrf_cli_libuarte.h new file mode 100644 index 0000000..248aced --- /dev/null +++ b/components/libraries/cli/libuarte/nrf_cli_libuarte.h @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_LOG_BACKEND_LIBUARTE_H__ +#define NRF_LOG_BACKEND_LIBUARTE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_cli.h" +#include "nrf_ringbuf.h" +#include "app_timer.h" +#include "nrf_uarte.h" + +/**@file + * + * @defgroup nrf_cli_libuarte libUARTE command line interface transport layer. + * @ingroup nrf_cli + * + * @{ + * + */ + +/** + * @brief Command line interface transport. + * */ +extern const nrf_cli_transport_api_t cli_libuarte_transport_api; + +typedef struct cli_libuarte_internal_s cli_libuarte_internal_t; + +typedef struct { + nrf_cli_transport_handler_t handler; + void * p_context; + bool blocking; +} cli_libuarte_internal_cb_t; + +struct cli_libuarte_internal_s { + nrf_cli_transport_t transport; + cli_libuarte_internal_cb_t * p_cb; + nrf_ringbuf_t const * p_rx_ringbuf; + nrf_ringbuf_t const * p_tx_ringbuf; +}; + +typedef struct +{ + uint32_t tx_pin; + uint32_t rx_pin; + nrf_uarte_hwfc_t hwfc; ///< Flow control configuration. + nrf_uarte_parity_t parity; ///< Parity configuration. + nrf_uarte_baudrate_t baudrate; ///< Baudrate. +} cli_libuarte_config_t; + +/**@brief CLI libUARTE transport definition. + * + * @param _name Name of instance. + * @param _tx_buf_sz Size of TX ring buffer. + * @param _rx_buf_sz Size of RX ring buffer. + */ +#define NRF_CLI_LIBUARTE_DEF(_name, _tx_buf_sz, _rx_buf_sz) \ + NRF_RINGBUF_DEF(CONCAT_2(_name,_tx_ringbuf), _tx_buf_sz); \ + NRF_RINGBUF_DEF(CONCAT_2(_name,_rx_ringbuf), _rx_buf_sz); \ + static cli_libuarte_internal_cb_t CONCAT_2(_name, _cb); \ + static const cli_libuarte_internal_t _name = { \ + .transport = {.p_api = &cli_libuarte_transport_api}, \ + .p_cb = &CONCAT_2(_name, _cb), \ + .p_rx_ringbuf = &CONCAT_2(_name,_rx_ringbuf), \ + .p_tx_ringbuf = &CONCAT_2(_name,_tx_ringbuf), \ + } +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_LOG_BACKEND_LIBUARTE_H__ */ diff --git a/components/libraries/cli/nrf_cli.c b/components/libraries/cli/nrf_cli.c new file mode 100644 index 0000000..98002da --- /dev/null +++ b/components/libraries/cli/nrf_cli.c @@ -0,0 +1,3700 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CLI) +#include +#include +#include +#include "nrf_cli.h" +#include "nrf_cli_vt100.h" +#include "app_error.h" +#include "nrf_assert.h" +#include "nrf_delay.h" +#include "nrf_pwr_mgmt.h" +#include "nrf_atomic.h" + +#if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD) +#include "fnmatch.h" +#endif + +#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) + #if NRF_CLI_HISTORY_ELEMENT_SIZE * NRF_CLI_HISTORY_ELEMENT_COUNT == 0 + #error Not proper memory size allocated for NRF_CLI_HISTORY + #endif +#endif + +/* 2 == 1 char for cmd + 1 char for '\0' */ +#if NRF_CLI_CMD_BUFF_SIZE < 2 + #error too small NRF_CLI_CMD_BUFF_SIZE +#endif + +#if NRF_CLI_PRINTF_BUFF_SIZE < 1 + #error too small NRF_CLI_PRINTF_BUFF_SIZE +#endif + +#define NRF_CLI_HELP_CLEAR "Clear screen." +#define NRF_CLI_HELP_COLORS "Toggle colored syntax." +#define NRF_CLI_HELP_COLORS_OFF "Disable colored syntax." +#define NRF_CLI_HELP_COLORS_ON "Enable colored syntax." +#define NRF_CLI_HELP_STATISTICS "CLI statistics." +#define NRF_CLI_HELP_STATISTICS_SHOW "Get CLI statistics for the Logger module." +#define NRF_CLI_HELP_STATISTICS_RESET "Reset CLI statistics for the Logger module." +#define NRF_CLI_HELP_RESIZE "Console gets terminal screen size or assumes 80 in case " \ + "the readout fails. It must be executed after each terminal " \ + "width change to ensure correct text display." +#define NRF_CLI_HELP_RESIZE_DEFAULT "Assume 80 chars screen width and send this setting " \ + "to the terminal." +#define NRF_CLI_HELP_HISTORY "Command history." +#define NRF_CLI_HELP_ECHO "Toggle CLI echo." +#define NRF_CLI_HELP_ECHO_ON "Enable CLI echo." +#define NRF_CLI_HELP_ECHO_OFF "Disable CLI echo. Arrows and buttons: Backspace, " \ + "Delete, End, Home, Insert are not handled." +#define NRF_CLI_HELP_CLI "Useful, not Unix-like CLI commands." + +#define NRF_CLI_MSG_SPECIFY_SUBCOMMAND "Please specify a subcommand." +#define NRF_CLI_MSG_UNKNOWN_PARAMETER " unknown parameter: " +#define NRF_CLI_MSG_COMMAND_NOT_FOUND ": command not found" +#define NRF_CLI_MSG_TAB_OVERFLOWED "Tab function: commands counter overflowed." + +/*lint -save -esym(526,cli_command*) -esym(526,cli_sorted_cmd_ptrs*)*/ +NRF_SECTION_DEF(cli_command, nrf_cli_cmd_entry_t); +#define CLI_DATA_SECTION_ITEM_GET(i) NRF_SECTION_ITEM_GET(cli_command, nrf_cli_cmd_entry_t, (i)) +#define CLI_DATA_SECTION_ITEM_COUNT NRF_SECTION_ITEM_COUNT(cli_command, nrf_cli_cmd_entry_t) + +NRF_SECTION_DEF(cli_sorted_cmd_ptrs, const char *); +/*lint -restore*/ +#define CLI_SORTED_CMD_PTRS_ITEM_GET(i) NRF_SECTION_ITEM_GET(cli_sorted_cmd_ptrs, const char *, (i)) +#define CLI_SORTED_CMD_PTRS_START_ADDR_GET NRF_SECTION_START_ADDR(cli_sorted_cmd_ptrs) + +#if defined(NRF_CLI_LOG_BACKEND) && NRF_CLI_LOG_BACKEND +#include "nrf_log_str_formatter.h" +#include "nrf_log_internal.h" +#endif + +#define NRF_CLI_INIT_OPTION_PRINTER (NULL) + +#define NRF_CLI_MAX_TERMINAL_SIZE (250u) +#define NRF_CLI_CURSOR_POSITION_BUFFER (10u) /* 10 == {esc, [, 2, 5, 0, ;, 2, 5, 0, '\0'} */ +#define NRF_CLI_DEFAULT_TERMINAL_WIDTH (80u) /* Default PuTTY width. */ +#define NRF_CLI_DEFAULT_TERMINAL_HEIGHT (24u) /* Default PuTTY height. */ +#define NRF_CLI_INITIAL_CURS_POS (1u) /* Initial cursor position is: (1, 1). */ + +#define NRF_CLI_CMD_ROOT_LVL (0u) + +/* Macro to send VT100 commands. */ +#define NRF_CLI_VT100_CMD(_p_cli_, _cmd_) { \ + ASSERT(_p_cli_); \ + ASSERT(_p_cli_->p_fprintf_ctx); \ + static char const cmd[] = _cmd_; \ + nrf_fprintf(_p_cli_->p_fprintf_ctx, "%s", cmd); \ +} + +#if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD) +typedef enum +{ + WILDCARD_CMD_ADDED, + WILDCARD_CMD_ADDED_MISSING_SPACE, + WILDCARD_CMD_NO_MATCH_FOUND +} wildcard_cmd_status_t; +#endif + + +static bool cli_log_entry_process(nrf_cli_t const * p_cli, bool skip); +static void cli_execute(nrf_cli_t const * p_cli); + + +static inline void transport_buffer_flush(nrf_cli_t const * p_cli) +{ + nrf_fprintf_buffer_flush(p_cli->p_fprintf_ctx); +} + +static inline void cli_flag_help_set(nrf_cli_t const * p_cli) +{ + p_cli->p_ctx->internal.flag.show_help = 1; +} +static inline void cli_flag_help_clear(nrf_cli_t const * p_cli) +{ + p_cli->p_ctx->internal.flag.show_help = 0; +} + +#if NRF_MODULE_ENABLED(NRF_CLI_BUILD_IN_CMDS) +static inline void cli_flag_echo_set(nrf_cli_t const * p_cli) +{ + p_cli->p_ctx->internal.flag.echo = 1; +} + +static inline void cli_flag_echo_clear(nrf_cli_t const * p_cli) +{ + p_cli->p_ctx->internal.flag.echo = 0; +} +#endif /* NRF_MODULE_ENABLED(NRF_CLI_BUILD_IN_CMDS) */ + +static inline bool cli_flag_echo_is_set(nrf_cli_t const * p_cli) +{ + return p_cli->p_ctx->internal.flag.echo == 1 ? true : false; +} + +static inline bool cli_flag_processing_is_set(nrf_cli_t const * p_cli) +{ + return p_cli->p_ctx->internal.flag.processing == 1 ? true : false; +} + +static inline uint8_t cli_flag_last_nl_get(nrf_cli_t const * p_cli) +{ + return p_cli->p_ctx->internal.flag.last_nl; +} + +static inline void cli_flag_last_nl_set(nrf_cli_t const * p_cli, uint8_t val) +{ + p_cli->p_ctx->internal.flag.last_nl = val; +} + +static inline void receive_state_change(nrf_cli_t const * p_cli, nrf_cli_receive_t state) +{ + p_cli->p_ctx->receive_state = state; +} + +static inline size_t cli_strlen(char const * str) +{ + return str == NULL ? 0 : strlen(str); +} + +static void cli_cmd_buffer_clear(nrf_cli_t const * p_cli) +{ + p_cli->p_ctx->cmd_buff[0] = '\0'; /* clear command buffer */ + p_cli->p_ctx->cmd_buff_pos = 0; + p_cli->p_ctx->cmd_buff_len = 0; +} + +/* Function returns true if cursor is at beginning of an empty line. */ +static inline bool cursor_in_empty_line(nrf_cli_t const * p_cli) +{ + return ( (p_cli->p_ctx->cmd_buff_pos + cli_strlen(p_cli->p_name)) % + p_cli->p_ctx->vt100_ctx.cons.terminal_wid == 0); +} + +/* Function returns true if command length is equal to multiplicity of terminal width. */ +static inline bool full_line_cmd(nrf_cli_t const * p_cli) +{ + return ((p_cli->p_ctx->cmd_buff_len + cli_strlen(p_cli->p_name)) % + p_cli->p_ctx->vt100_ctx.cons.terminal_wid == 0); +} + +#if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD) +/* Function returns true if string contains wildcard character: '?' or '*'. */ +static bool wildcard_character_exist(char * p_str) +{ + size_t str_len = cli_strlen(p_str); + for (size_t i = 0; i < str_len; i++) + { + if ((p_str[i] == '?') || (p_str[i] == '*')) + { + return true; + } + } + return false; +} +#endif + +/* Function sends data stream to the CLI instance. Each time before the cli_write function is called, + * it must be ensured that IO buffer of fprintf is flushed to avoid synchronization issues. + * For that purpose, use function transport_buffer_flush(p_cli) */ +static void cli_write(nrf_cli_t const * p_cli, + void const * p_data, + size_t length, + size_t * p_cnt) +{ + ASSERT(p_cli && p_data); + ASSERT(p_cli->p_iface->p_api); + size_t offset = 0; + size_t cnt; + while (length) + { + ret_code_t ret = p_cli->p_iface->p_api->write(p_cli->p_iface, + &((uint8_t const *)p_data)[offset], + length, + &cnt); + UNUSED_VARIABLE(ret); + ASSERT(ret == NRF_SUCCESS); + ASSERT(length >= cnt); + offset += cnt; + length -= cnt; + if (cnt == 0 && (p_cli->p_ctx->state != NRF_CLI_STATE_PANIC_MODE_ACTIVE)) + { +#if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER) + (void)task_events_wait(NRF_CLI_TRANSPORT_TX_RDY_TASK_EVT); +#else + while (p_cli->p_ctx->internal.flag.tx_rdy == 0) + { + ; + } + p_cli->p_ctx->internal.flag.tx_rdy = 0; +#endif + } + } + + if (p_cnt) + { + *p_cnt = cnt; + } +} + +/* Function sends 1 character to the CLI instance. */ +static inline void cli_putc(nrf_cli_t const * p_cli, char ch) +{ + nrf_fprintf(p_cli->p_fprintf_ctx, "%c", ch); +} + +/* Function reads data from the CLI instance. */ +static void cli_read(nrf_cli_t const * p_cli, + void * p_data, + size_t length, + size_t * p_cnt) +{ + ASSERT(p_cli && p_data); + ASSERT(p_cli->p_iface); + + ret_code_t ret = p_cli->p_iface->p_api->read(p_cli->p_iface, p_data, length, p_cnt); + UNUSED_VARIABLE(ret); +} + +/* Function cmd_get shall be used to search commands. It moves the pointer pp_entry to command + * of static command structure. If the command cannot be found, the function will set pp_entry to NULL. + * p_command Pointer to command which will be processed (no matter the root command). + * lvl Level of the requested command. + * idx Index of the requested command. + * pp_entry Pointer which points to subcommand[idx] after function execution. + * p_st_entry Pointer to the structure where dynamic entry data can be stored. + */ +static void cmd_get(nrf_cli_cmd_entry_t const * p_command, + size_t lvl, + size_t idx, + nrf_cli_static_entry_t const ** pp_entry, + nrf_cli_static_entry_t * p_st_entry) +{ + ASSERT (pp_entry != NULL); + ASSERT (p_st_entry != NULL); + + if (lvl == NRF_CLI_CMD_ROOT_LVL) + { + if (idx < CLI_DATA_SECTION_ITEM_COUNT) + { + nrf_cli_cmd_entry_t const * p_cmd = NULL; + char const * * pp_sorted_cmds = (char const * *)CLI_SORTED_CMD_PTRS_START_ADDR_GET; + for (size_t i = 0; i < CLI_DATA_SECTION_ITEM_COUNT; i++) + { + p_cmd = CLI_DATA_SECTION_ITEM_GET(i); + if (!strcmp(pp_sorted_cmds[idx], p_cmd->u.p_static->p_syntax)) + { + *pp_entry = p_cmd->u.p_static; + return; + } + } + } + *pp_entry = NULL; + return; + } + + if (p_command == NULL) + { + *pp_entry = NULL; + return; + } + + if (p_command->is_dynamic) + { + p_command->u.p_dynamic_get(idx, p_st_entry); + if (p_st_entry->p_syntax == NULL) + { + *pp_entry = NULL; + } + else + { + *pp_entry = p_st_entry; + } + } + else + { + if (p_command->u.p_static[idx].p_syntax != NULL) + { + *pp_entry = &p_command->u.p_static[idx]; + } + else + { + *pp_entry = NULL; + } + } +} + +/* Function multiline_console_data_check checks the current cursor position (x, y) on terminal screen + * based on: command length, console name length, and terminal width. + * Example 1: + * || - cursor + * ---------------------------- + * |console_name $: || | + * ---------------------------- + * => coordinates are: cur_x = 17, cur_x_end = 17, + * cur_y = 1, cur_y_end = 1 + * Example 2: + * ---------------------------- + * |console_name $: test command| + * |showing |e|xample | + * ---------------------------- + * => coordinates are: cur_x = 9, cur_x_end = 18 (cursor can be one column after 'e') + * => cur_y = 2, cur_y_end = 2 + * Example 3: + * ---------------------------- + * |console_name $: test command| + * |showing e|x|ample with more | + * |parameters | + * ---------------------------- + * => coordinates are: cur_x = 10, cur_x_end = 11 (cursor can be one column after 's') + * => cur_y = 2, cur_y_end = 3 + */ +static nrf_cli_multiline_cons_t const * multiline_console_data_check(nrf_cli_t const * p_cli) +{ + nrf_cli_ctx_t * p_ctx = p_cli->p_ctx; + nrf_cli_multiline_cons_t * p_cons = &p_cli->p_ctx->vt100_ctx.cons; + + p_cons->name_len = cli_strlen(p_cli->p_name); + + /* Current cursor position in command. + * +1 -> because home position is (1, 1) */ + p_cons->cur_x = (p_ctx->cmd_buff_pos + p_cons->name_len) % p_cons->terminal_wid + 1; + p_cons->cur_y = (p_ctx->cmd_buff_pos + p_cons->name_len) / p_cons->terminal_wid + 1; + + /* Extreme position when cursor is at the end of command. */ + p_cons->cur_y_end = (p_ctx->cmd_buff_len + p_cons->name_len) / p_cons->terminal_wid + 1; + p_cons->cur_x_end = (p_ctx->cmd_buff_len + p_cons->name_len) % p_cons->terminal_wid + 1; + + return p_cons; +} + + +#if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS) +/* Calculates relative line number of given position in buffer */ +static uint32_t cli_line_num_with_buffer_offset_get(nrf_cli_t const * p_cli, + nrf_cli_cmd_len_t buffer_pos) +{ + uint32_t name_len; + nrf_cli_multiline_cons_t *p_cons = &p_cli->p_ctx->vt100_ctx.cons; + + name_len = cli_strlen(p_cli->p_name); + + return ((buffer_pos + name_len) / p_cons->terminal_wid); +} +#endif + + +#if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS) +/* Calculates column number of given position in buffer */ +static uint32_t cli_col_num_with_buffer_offset_get(nrf_cli_t const * p_cli, + nrf_cli_cmd_len_t buffer_pos) +{ + uint32_t name_len; + nrf_cli_multiline_cons_t *p_cons = &p_cli->p_ctx->vt100_ctx.cons; + + name_len = cli_strlen(p_cli->p_name); + + /* columns are counted from 1 */ + return (1 + ((buffer_pos + name_len) % p_cons->terminal_wid)); +} +#endif + + +#if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS) +/* For the given buffer, calculates row span between position2 and position1 */ +static int32_t cli_row_span_with_buffer_offsets_get(nrf_cli_t const * p_cli, + nrf_cli_cmd_len_t offset1, + nrf_cli_cmd_len_t offset2) +{ + return cli_line_num_with_buffer_offset_get(p_cli, offset2) + - cli_line_num_with_buffer_offset_get(p_cli, offset1); +} +#endif + +#if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS) +/* For the given buffer, calculates column span between position2 and position 1 */ +static int32_t cli_column_span_with_buffer_offsets_get(nrf_cli_t const * p_cli, + nrf_cli_cmd_len_t offset1, + nrf_cli_cmd_len_t offset2) +{ + return cli_col_num_with_buffer_offset_get(p_cli, offset2) + - cli_col_num_with_buffer_offset_get(p_cli, offset1); +} +#endif + + +/* Function sends VT100 command to clear the screen from cursor position to end of the screen. */ +static inline void cli_clear_eos(nrf_cli_t const * p_cli) +{ + NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CLEAREOS); +} + +/* Function sends VT100 command to save cursor position. */ +static inline void cli_cursor_save(nrf_cli_t const * p_cli) +{ + NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_SAVECURSOR); +} + +/* Function sends VT100 command to restore saved cursor position. */ +static inline void cli_cursor_restore(nrf_cli_t const * p_cli) +{ + NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_RESTORECURSOR); +} + +/* Function forcing new line - cannot be replaced with function cursor_down_move. */ +static inline void cursor_next_line_move(nrf_cli_t const * p_cli) +{ + nrf_fprintf(p_cli->p_fprintf_ctx, "\n"); +} + +/* Function moves cursor left by n positions. */ +static inline void cursor_left_move(nrf_cli_t const * p_cli, nrf_cli_cmd_len_t n) +{ + if (n > 0) + { + nrf_fprintf(p_cli->p_fprintf_ctx, "\033[%dD", n); + } +} + +/* Function moves cursor right by n positions. */ +static inline void cursor_right_move(nrf_cli_t const * p_cli, nrf_cli_cmd_len_t n) +{ + if (n > 0) + { + nrf_fprintf(p_cli->p_fprintf_ctx, "\033[%dC", n); + } +} + +#if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS) +/* Moves cursor horizontally by a number. Positive is right */ +static void cursor_horiz_move(nrf_cli_t const * p_cli, int32_t delta) +{ + if (delta > 0) + { + cursor_right_move(p_cli, delta); + } + else if (delta < 0) + { + cursor_left_move(p_cli, -delta); + } + else { } +} +#endif + +/* Function moves cursor up by n positions. */ +static inline void cursor_up_move(nrf_cli_t const * p_cli, nrf_cli_cmd_len_t n) +{ + if (n > 0) + { + nrf_fprintf(p_cli->p_fprintf_ctx, "\033[%dA", n); + } +} + +/* Function moves cursor down by n positions but it will bring no effect if cursor is in the last + * line of terminal screen. In such case, the cursor_next_line_move function shall be invoked. */ +static inline void cursor_down_move(nrf_cli_t const * p_cli, nrf_cli_cmd_len_t n) +{ + if (n > 0) + { + nrf_fprintf(p_cli->p_fprintf_ctx, "\033[%dB", n); + } +} + +#if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS) +/* Moves cursor vertically by a number. Positive is down */ +static void cursor_vert_move(nrf_cli_t const * p_cli, int32_t delta) +{ + if (delta > 0) + { + cursor_down_move(p_cli, delta); + } + else if (delta < 0) + { + cursor_up_move(p_cli, -delta); + } + else { } +} +#endif + +/* Function increments cursor position (if possible) and moves cursor to new line if necessary. */ +static void cursor_position_increment(nrf_cli_t const * p_cli) +{ + if (p_cli->p_ctx->cmd_buff_pos >= p_cli->p_ctx->cmd_buff_len) + { + return; /* incrementation not possible */ + } + + nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli); + nrf_cli_cmd_len_t cur_y = p_cons->cur_y; + ++p_cli->p_ctx->cmd_buff_pos; + p_cons = multiline_console_data_check(p_cli); + + if (cur_y == p_cons->cur_y) + { + cursor_right_move(p_cli, 1); + } + else + { + cursor_next_line_move(p_cli); + } +} + +/* Function will move cursor back to position == cmd_buff_pos. Example usage is when cursor needs + * to be moved back after printing some text. This function cannot be used to move cursor to new + * location by manual change of cmd_buff_pos.*/ +static void cursor_position_synchronize(nrf_cli_t const * p_cli) +{ + nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli); + bool last_line = p_cons->cur_y == p_cons->cur_y_end ? true : false; + + /* In case cursor reaches the bottom line of a terminal, it will be moved to the next line. */ + if (cursor_in_empty_line(p_cli) || full_line_cmd(p_cli)) + { + cursor_next_line_move(p_cli); + } + + if (last_line) + { + cursor_left_move(p_cli, p_cons->cur_x_end - p_cons->cur_x); + } + else + { + cursor_up_move(p_cli, p_cons->cur_y_end - p_cons->cur_y); + if (p_cons->cur_x > p_cons->cur_x_end) + { + cursor_right_move(p_cli, p_cons->cur_x - p_cons->cur_x_end); + } + else + { + cursor_left_move(p_cli, p_cons->cur_x_end - p_cons->cur_x); + } + } +} + +#if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS) +/** + * Removes the "word" to the left of the cursor: + * - if there are spaces at the cursor position, remove all spaces to the left + * - remove the non-spaces (word) until a space is found or a beginning of buffer + */ +static void cli_cmd_word_remove(nrf_cli_t const * p_cli) +{ + nrf_cli_cmd_len_t new_pos; + nrf_cli_cmd_len_t chars_to_delete; + int32_t row_span; + int32_t col_span; + + /* Line must not be empty and cursor must not be at 0 to continue */ + if ((p_cli->p_ctx->cmd_buff_len == 0) || (p_cli->p_ctx->cmd_buff_pos == 0)) + { + return; + } + + /* start at the current position */ + new_pos = p_cli->p_ctx->cmd_buff_pos; + chars_to_delete = 0; + + /* look back for all spaces then for non-spaces */ + while ((new_pos >= 1) && (p_cli->p_ctx->cmd_buff[new_pos - 1] == ' ')) + { + ++chars_to_delete; + --new_pos; + } + + while ((new_pos >= 1) && (p_cli->p_ctx->cmd_buff[new_pos - 1] != ' ')) + { + --new_pos; + ++chars_to_delete; + } + + /* calculate the new cursor */ + row_span = cli_row_span_with_buffer_offsets_get(p_cli, p_cli->p_ctx->cmd_buff_pos, new_pos); + col_span = cli_column_span_with_buffer_offsets_get(p_cli, p_cli->p_ctx->cmd_buff_pos, new_pos); + + /* manage the buffer */ + memmove(&p_cli->p_ctx->cmd_buff[new_pos], + &p_cli->p_ctx->cmd_buff[new_pos + chars_to_delete], + p_cli->p_ctx->cmd_buff_len - chars_to_delete); + p_cli->p_ctx->cmd_buff_len -= chars_to_delete; + p_cli->p_ctx->cmd_buff_pos = new_pos; + p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_len] = '\0'; + + /* update display */ + cursor_horiz_move(p_cli, col_span); + cursor_vert_move(p_cli, row_span); + cli_cursor_save(p_cli); + nrf_cli_fprintf(p_cli, + NRF_CLI_NORMAL, + "%s", + &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]); + cli_clear_eos(p_cli); + cli_cursor_restore(p_cli); +} +#endif + +#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) || NRF_MODULE_ENABLED(NRF_CLI_METAKEYS) +/* Function moves cursor to begin of command position, just after console name. */ +static void cursor_home_position_move(nrf_cli_t const * p_cli) +{ + nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli); + + if ((p_cons->cur_x == p_cons->name_len + NRF_CLI_INITIAL_CURS_POS) && + (p_cons->cur_y == NRF_CLI_INITIAL_CURS_POS)) + { + return; /* nothing to handle because cursor is in start position */ + } + + if (p_cons->cur_y > NRF_CLI_INITIAL_CURS_POS) + { + cursor_up_move(p_cli, p_cons->cur_y - NRF_CLI_INITIAL_CURS_POS); + } + + if (p_cons->cur_x > p_cons->name_len) + { + cursor_left_move(p_cli, p_cons->cur_x - NRF_CLI_INITIAL_CURS_POS - p_cons->name_len); + } + else + { + cursor_right_move(p_cli, p_cons->name_len + NRF_CLI_INITIAL_CURS_POS - p_cons->cur_x); + } + /* align data buffer pointer with cursor position */ + p_cli->p_ctx->cmd_buff_pos = 0; +} +#endif + +/* Function moves cursor to end of command. */ +static void cursor_end_position_move(nrf_cli_t const * p_cli) +{ + nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli); + + if ((p_cons->cur_x == p_cons->cur_x_end) && (p_cons->cur_y == p_cons->cur_y_end)) + { + return; /* nothing to handle because cursor is in end position */ + } + + if (p_cons->cur_y_end > p_cons->cur_y) + { + cursor_down_move(p_cli, p_cons->cur_y_end - p_cons->cur_y); + } + + if (p_cons->cur_x > p_cons->cur_x_end) + { + cursor_left_move(p_cli, p_cons->cur_x - p_cons->cur_x_end); + } + else + { + cursor_right_move(p_cli, p_cons->cur_x_end - p_cons->cur_x); + } + /* align data buffer pointer with cursor position */ + p_cli->p_ctx->cmd_buff_pos = p_cli->p_ctx->cmd_buff_len; +} + +#if NRF_MODULE_ENABLED(NRF_CLI_BUILD_IN_CMDS) +/* Function reads cursor position from terminal. */ +static ret_code_t cursor_position_get(nrf_cli_t const * p_cli) +{ + size_t cnt; + uint16_t x = 0; /* horizontal position */ + uint16_t y = 0; /* vertical position */ + char c = 0; + + nrf_cli_cmd_len_t buff_idx = 0; + + /* clear temp buffer */ + memset(p_cli->p_ctx->temp_buff, 0, sizeof(p_cli->p_ctx->temp_buff)); + + /* escape code asking terminal about its size */ + static char const cmd_get_terminal_size[] = "\033[6n"; + + nrf_fprintf(p_cli->p_fprintf_ctx, cmd_get_terminal_size); + /* fprintf buffer needs to be flushed to start sending prepared escape code to the terminal */ + transport_buffer_flush(p_cli); + + /* timeout for terminal response = ~1s */ + for (uint16_t i = 0; i < 1000; i++) + { + do + { + cli_read(p_cli, &c, sizeof(c), &cnt); + if (cnt == 0) + { + nrf_delay_us(999); + continue; + } + if ((c != NRF_CLI_VT100_ASCII_ESC) && + (p_cli->p_ctx->temp_buff[0] != NRF_CLI_VT100_ASCII_ESC)) + { + continue; + } + + if (c == 'R') /* end of response from the terminal */ + { + p_cli->p_ctx->temp_buff[buff_idx] = '\0'; + if (p_cli->p_ctx->temp_buff[1] != '[') + { + p_cli->p_ctx->temp_buff[0] = 0; + return NRF_ERROR_INVALID_DATA; + } + buff_idx = 2; /* index start position in the buffer where 'y' is stored */ + while (p_cli->p_ctx->temp_buff[buff_idx] != ';') + { + y = y * 10 + (p_cli->p_ctx->temp_buff[buff_idx++] - '0'); + if (buff_idx >= NRF_CLI_CMD_BUFF_SIZE) + { + return NRF_ERROR_DATA_SIZE; + } + } + if (++buff_idx >= NRF_CLI_CMD_BUFF_SIZE) + { + return NRF_ERROR_DATA_SIZE; + } + while (p_cli->p_ctx->temp_buff[buff_idx] != '\0') + { + x = x * 10 + (p_cli->p_ctx->temp_buff[buff_idx++] - '0'); + if (buff_idx >= NRF_CLI_CMD_BUFF_SIZE) + { + return NRF_ERROR_DATA_SIZE; + } + } + /* horizontal cursor position */ + if (x > NRF_CLI_MAX_TERMINAL_SIZE) + { + p_cli->p_ctx->vt100_ctx.cons.cur_x = NRF_CLI_MAX_TERMINAL_SIZE; + } + else + { + p_cli->p_ctx->vt100_ctx.cons.cur_x = (nrf_cli_cmd_len_t)x; + } + /* vertical cursor position */ + if (y > NRF_CLI_MAX_TERMINAL_SIZE) + { + p_cli->p_ctx->vt100_ctx.cons.cur_y = NRF_CLI_MAX_TERMINAL_SIZE; + } + else + { + p_cli->p_ctx->vt100_ctx.cons.cur_y = (nrf_cli_cmd_len_t)y; + } + p_cli->p_ctx->temp_buff[0] = 0; + return NRF_SUCCESS; + } + else + { + p_cli->p_ctx->temp_buff[buff_idx] = c; + } + + if (++buff_idx > NRF_CLI_CURSOR_POSITION_BUFFER - 1) + { + p_cli->p_ctx->temp_buff[0] = 0; + /* data_buf[NRF_CLI_CURSOR_POSITION_BUFFER - 1] is reserved for '\0' */ + return NRF_ERROR_NO_MEM; + } + + } while (cnt > 0); + } + return NRF_ERROR_TIMEOUT; +} + +/* Function gets terminal width and height. */ +static ret_code_t terminal_size_get(nrf_cli_t const * p_cli, + nrf_cli_cmd_len_t * p_length, + nrf_cli_cmd_len_t * p_height) +{ + ASSERT(p_length); + ASSERT(p_height); + + uint16_t x; + uint16_t y; + + if (cursor_position_get(p_cli) == NRF_SUCCESS) + { + x = p_cli->p_ctx->vt100_ctx.cons.cur_x; + y = p_cli->p_ctx->vt100_ctx.cons.cur_y; + /* assumption: terminal widht and height < 999 */ + cursor_right_move(p_cli, NRF_CLI_MAX_TERMINAL_SIZE); /* move to last column */ + cursor_down_move(p_cli, NRF_CLI_MAX_TERMINAL_SIZE); /* move to last row */ + } + else + { + return NRF_ERROR_NOT_SUPPORTED; + } + + if (cursor_position_get(p_cli) == NRF_SUCCESS) + { + *p_length = p_cli->p_ctx->vt100_ctx.cons.cur_x; + *p_height = p_cli->p_ctx->vt100_ctx.cons.cur_y; + cursor_left_move(p_cli, *p_length - x); + cursor_up_move(p_cli, *p_height - y); + + return NRF_SUCCESS; + } + return NRF_ERROR_NOT_SUPPORTED; +} +#endif // NRF_MODULE_ENABLED(NRF_CLI_BUILD_IN_CMDS) + +#if NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS) +static void vt100_color_set(nrf_cli_t const * p_cli, nrf_cli_vt100_color_t color) +{ + if (color != NRF_CLI_DEFAULT) + { + if (p_cli->p_ctx->vt100_ctx.col.col == color) + { + return; + } + + uint8_t cmd[] = NRF_CLI_VT100_COLOR(color - 1); + + p_cli->p_ctx->vt100_ctx.col.col = color; + nrf_fprintf(p_cli->p_fprintf_ctx, "%s", cmd); + } + else + { + static uint8_t const cmd[] = NRF_CLI_VT100_MODESOFF; + + p_cli->p_ctx->vt100_ctx.col.col = color; + nrf_fprintf(p_cli->p_fprintf_ctx, "%s", cmd); + } +} + +static void vt100_bgcolor_set(nrf_cli_t const * p_cli, nrf_cli_vt100_color_t bgcolor) +{ + if (bgcolor != NRF_CLI_DEFAULT) + { + if (p_cli->p_ctx->vt100_ctx.col.bgcol == bgcolor) + { + return; + } + /* -1 because default value is first in enum */ + uint8_t cmd[] = NRF_CLI_VT100_BGCOLOR(bgcolor - 1); + + p_cli->p_ctx->vt100_ctx.col.bgcol = bgcolor; + nrf_fprintf(p_cli->p_fprintf_ctx, "%s", cmd); + } +} + +static inline void vt100_colors_store(nrf_cli_t const * p_cli, + nrf_cli_vt100_colors_t * p_color) +{ + memcpy(p_color, &p_cli->p_ctx->vt100_ctx.col, sizeof(nrf_cli_vt100_colors_t)); +} + +static void vt100_colors_restore(nrf_cli_t const * p_cli, + nrf_cli_vt100_colors_t const * p_color) +{ + vt100_color_set(p_cli, p_color->col); + vt100_bgcolor_set(p_cli, p_color->bgcol); +} +#endif // NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS) + +static void left_arrow_handle(nrf_cli_t const * p_cli) +{ + nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli); + + if ((p_cons->cur_x == p_cons->name_len + NRF_CLI_INITIAL_CURS_POS) && + (p_cons->cur_y == NRF_CLI_INITIAL_CURS_POS)) + { + return; /* nothing to handle because cursor is in start position */ + } + + if (p_cons->cur_x == NRF_CLI_INITIAL_CURS_POS) + { /* go to previous line */ + cursor_up_move(p_cli, 1); + cursor_right_move(p_cli, p_cons->terminal_wid); + --p_cli->p_ctx->cmd_buff_pos; + } + else + { + cursor_left_move(p_cli, 1); + --p_cli->p_ctx->cmd_buff_pos; + } +} + +static void right_arrow_handle(nrf_cli_t const * p_cli) +{ + nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli); + + if ((p_cons->cur_x == p_cons->cur_x_end) && + (p_cons->cur_y == p_cons->cur_y_end)) + { + return; /* nothing to handle because cursor is in start position */ + } + + if (p_cons->cur_x == p_cons->terminal_wid) /* go to next line */ + { + cursor_down_move(p_cli, 1); + cursor_left_move(p_cli, p_cons->terminal_wid); + ++p_cli->p_ctx->cmd_buff_pos; + } + else + { + cursor_right_move(p_cli, 1); + ++p_cli->p_ctx->cmd_buff_pos; + } +} + +static inline void char_insert_echo_off(nrf_cli_t const * p_cli, char data) +{ + if (p_cli->p_ctx->cmd_buff_len >= (NRF_CLI_CMD_BUFF_SIZE - 1)) + { + return; + } + + p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos++] = data; + p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos] = '\0'; + ++p_cli->p_ctx->cmd_buff_len; +} + +static void char_insert(nrf_cli_t const * p_cli, char data) +{ + nrf_cli_cmd_len_t diff; + bool ins_mode = (bool)p_cli->p_ctx->internal.flag.insert_mode; + + diff = p_cli->p_ctx->cmd_buff_len - p_cli->p_ctx->cmd_buff_pos; + + if (!ins_mode) + { + if (p_cli->p_ctx->cmd_buff_len >= (NRF_CLI_CMD_BUFF_SIZE - 1)) + { + return; + } + if (diff > 0) + { + memmove(&p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos + 1], + &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos], + diff); + } + } + else + { + if ((p_cli->p_ctx->cmd_buff_len >= (NRF_CLI_CMD_BUFF_SIZE - 1)) && + (diff == 0)) + { + /* If cmd buffer is full, it is possible to replace chars but adding new + is not allowed. */ + return; + } + } + + p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos] = data; + + if (!ins_mode) + { + p_cli->p_ctx->cmd_buff[++p_cli->p_ctx->cmd_buff_len] = '\0'; + } + + if (diff > 0) + { + nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli); + bool last_line = p_cons->cur_y == p_cons->cur_y_end ? true : false; + + /* Below if-else statement is to minimize esc codes transmission. */ + if (last_line) + { + nrf_cli_fprintf(p_cli, + NRF_CLI_NORMAL, + "%s", + &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]); + /* Move cursor one position left less in case of insert mode. */ + cursor_left_move(p_cli, diff - ins_mode); + } + else + { + /* Save the current cursor position in order to get back after fprintf function. */ + cli_cursor_save(p_cli); + nrf_cli_fprintf(p_cli, + NRF_CLI_NORMAL, + "%s", + &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]); + cli_cursor_restore(p_cli); + /* Move cursor right by one position to edit the next character. */ + cursor_right_move(p_cli, 1); + } + } + else + { + /* New char appended at the end of buffer. */ + if (ins_mode) + { + p_cli->p_ctx->cmd_buff[++p_cli->p_ctx->cmd_buff_len] = '\0'; + } + cli_putc(p_cli, data); + } + + /* Incrementation needs to be executed before invoking function: cursor_in_empty_line. */ + ++p_cli->p_ctx->cmd_buff_pos; + + /* Forcing terminal to switch to a new line if the command is too long. */ + if (cursor_in_empty_line(p_cli)) + { + cursor_next_line_move(p_cli); + return; + } + + if (full_line_cmd(p_cli)) + { + nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli); + + /* The code below will force the terminal to scroll one line down when the currently entered command + * reaches lower right corner of the terminal screen. */ + cursor_down_move(p_cli, p_cons->cur_y_end - p_cons->cur_y - 1); + cursor_next_line_move(p_cli); + cursor_up_move(p_cli, p_cons->cur_y_end - p_cons->cur_y); + cursor_right_move(p_cli, p_cons->cur_x - 1); + return; + } +} + +static void char_backspace(nrf_cli_t const * p_cli) +{ + nrf_cli_cmd_len_t diff; + + if ((p_cli->p_ctx->cmd_buff_len == 0) || (p_cli->p_ctx->cmd_buff_pos == 0)) + { + return; + } + + diff = p_cli->p_ctx->cmd_buff_len - p_cli->p_ctx->cmd_buff_pos; + + memmove(&p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos - 1], + &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos], + diff + 1); + + --p_cli->p_ctx->cmd_buff_pos; + --p_cli->p_ctx->cmd_buff_len; + + if (diff > 0) + { + cli_putc(p_cli, NRF_CLI_VT100_ASCII_BSPACE); + + nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli); + bool last_line = p_cons->cur_y == p_cons->cur_y_end ? true : false; + + if (last_line) + { + nrf_cli_fprintf(p_cli, + NRF_CLI_NORMAL, + "%s", + &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]); + cli_clear_eos(p_cli); + cursor_left_move(p_cli, diff); + } + else + { + /* If cursor is not in last cmd line, its position needs to be saved by + * VT100 command. */ + cli_cursor_save(p_cli); + cli_clear_eos(p_cli); + nrf_cli_fprintf(p_cli, + NRF_CLI_NORMAL, + "%s", + &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]); + cli_cursor_restore(p_cli); + } + } + else + { + static char const cmd_bspace[] = { + NRF_CLI_VT100_ASCII_BSPACE, ' ', NRF_CLI_VT100_ASCII_BSPACE, '\0'}; + nrf_fprintf(p_cli->p_fprintf_ctx, "%s", cmd_bspace); + } +} + +static void char_delete(nrf_cli_t const * p_cli) +{ + nrf_cli_cmd_len_t diff; + + diff = p_cli->p_ctx->cmd_buff_len - p_cli->p_ctx->cmd_buff_pos; + + if (diff == 0) + { + return; + } + + memmove(&p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos], + &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos + 1], + diff); + + --p_cli->p_ctx->cmd_buff_len; + + nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli); + bool last_line = p_cons->cur_y == p_cons->cur_y_end ? true : false; + + /* If last line of command is edited, there is no need for saving cursor position. */ + if (last_line) + { + nrf_cli_fprintf(p_cli, + NRF_CLI_NORMAL, + "%s", + &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]); + NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CLEAREOL); + cursor_left_move(p_cli, --diff); + } + else + { + cli_cursor_save(p_cli); + cli_clear_eos(p_cli); + nrf_cli_fprintf(p_cli, + NRF_CLI_NORMAL, + "%s", + &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]); + cli_cursor_restore(p_cli); + } +} + +static char make_argv(size_t * p_argc, char ** pp_argv, char * p_cmd, uint8_t max_argc) +{ + char c; + char quote = 0; + + *p_argc = 0; + do + { + c = *p_cmd; + if (c == '\0') + { + break; + } + + if (isspace((int)c)) + { + *p_cmd++ = '\0'; + continue; + } + + pp_argv[(*p_argc)++] = p_cmd; + quote = 0; + + while (1) + { + c = *p_cmd; + + if (c == '\0') + { + break; + } + + if (!quote) + { + switch (c) + { + case '\\': + memmove(p_cmd, p_cmd + 1, cli_strlen(p_cmd)); + p_cmd += 1; + continue; + + case '\'': + case '\"': + memmove(p_cmd, p_cmd + 1, cli_strlen(p_cmd)); + quote = c; + continue; + default: + break; + } + } + + if (quote == c) + { + memmove(p_cmd, p_cmd + 1, cli_strlen(p_cmd)); + quote = 0; + continue; + } + + if (quote && c == '\\') + { + char t = *(p_cmd + 1); + + if (t == quote) + { + memmove(p_cmd, p_cmd + 1, cli_strlen(p_cmd)); + p_cmd += 1; + continue; + } + + if (t == '0') + { + uint8_t i; + uint8_t v = 0; + + for (i = 2; i < (2 + 3); i++) + { + t = *(p_cmd + i); + + if (t >= '0' && t <= '7') + { + v = (v << 3) | (t - '0'); + } + else + { + break; + } + } + + if (i > 2) + { + memmove(p_cmd, p_cmd + (i - 1), cli_strlen(p_cmd) - (i - 2)); + *p_cmd++ = v; + continue; + } + } + + if (t == 'x') + { + uint8_t i; + uint8_t v = 0; + + for (i = 2; i < (2 + 2); i++) + { + t = *(p_cmd + i); + + if (t >= '0' && t <= '9') + { + v = (v << 4) | (t - '0'); + } + else if (t >= 'a' && t <= 'f') + { + v = (v << 4) | (t - 'a' + 10); + } + else if (t >= 'A' && t <= 'F') + { + v = (v << 4) | (t - 'A' + 10); + } + else + { + break; + } + } + + if (i > 2) + { + memmove(p_cmd, p_cmd + (i - 1), cli_strlen(p_cmd) - (i - 2)); + *p_cmd++ = v; + continue; + } + } + } + if (!quote && isspace((int)c)) + { + break; + } + + p_cmd += 1; + } + } while (*p_argc < max_argc); + + ASSERT(*p_argc <= NRF_CLI_ARGC_MAX); + pp_argv[*p_argc] = 0; + + return quote; +} + +static void cli_state_set(nrf_cli_t const * p_cli, nrf_cli_state_t state) +{ + p_cli->p_ctx->state = state; + + if (state == NRF_CLI_STATE_ACTIVE) + { + cli_cmd_buffer_clear(p_cli); + nrf_cli_fprintf(p_cli, NRF_CLI_INFO, "%s", p_cli->p_name); + } +} + +#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) +static inline void history_mode_exit(nrf_cli_t const * p_cli) +{ + p_cli->p_ctx->p_cmd_list_element = NULL; +} + +static void history_handle(nrf_cli_t const * p_cli, bool up) +{ + nrf_cli_memobj_header_t header = { + .p_prev = NULL, + .p_next = NULL, + .cmd_len = 0 + }; + nrf_cli_cmd_len_t current_cmd_len; + bool skip = false; + + if (!up) /* button down */ + { + if (p_cli->p_ctx->p_cmd_list_element == NULL) + { + return; + } + cursor_home_position_move(p_cli); + + nrf_memobj_read(p_cli->p_ctx->p_cmd_list_element, + &header, + NRF_CLI_HISTORY_HEADER_SIZE, + 0); + + p_cli->p_ctx->p_cmd_list_element = header.p_next; + current_cmd_len = p_cli->p_ctx->cmd_buff_len; + + if (p_cli->p_ctx->p_cmd_list_element == NULL) + { + if (cli_strlen(p_cli->p_ctx->temp_buff) > 0) + { + strcpy(p_cli->p_ctx->cmd_buff, p_cli->p_ctx->temp_buff); + } + else + { + p_cli->p_ctx->cmd_buff[0] = '\0'; + } + header.cmd_len = cli_strlen(p_cli->p_ctx->cmd_buff); + skip = true; + } + } + else /* button up */ + { + if ((p_cli->p_ctx->p_cmd_list_element == p_cli->p_ctx->p_cmd_list_tail) || + (p_cli->p_ctx->p_cmd_list_head == NULL)) + { + /* Nothing to display. */ + return; + } + cursor_home_position_move(p_cli); + + if (p_cli->p_ctx->p_cmd_list_element == NULL) + { + current_cmd_len = cli_strlen(p_cli->p_ctx->cmd_buff); + + p_cli->p_ctx->p_cmd_list_element = p_cli->p_ctx->p_cmd_list_head; + /* Save the currently entered and not executed command. */ + if (current_cmd_len > 0) + { + strcpy(p_cli->p_ctx->temp_buff, p_cli->p_ctx->cmd_buff); + } + else + { + p_cli->p_ctx->temp_buff[0] = '\0'; + } + } + else + { + nrf_memobj_read(p_cli->p_ctx->p_cmd_list_element, + &header, + NRF_CLI_HISTORY_HEADER_SIZE, + 0); + current_cmd_len = header.cmd_len; + p_cli->p_ctx->p_cmd_list_element = header.p_prev; + } + } + if (!skip) + { + nrf_memobj_read(p_cli->p_ctx->p_cmd_list_element, + &header, + NRF_CLI_HISTORY_HEADER_SIZE, + 0); + + nrf_memobj_read(p_cli->p_ctx->p_cmd_list_element, + p_cli->p_ctx->cmd_buff, + header.cmd_len + 1, /* +1 for '\0' */ + NRF_CLI_HISTORY_HEADER_SIZE); + } + + p_cli->p_ctx->cmd_buff_pos = header.cmd_len; + p_cli->p_ctx->cmd_buff_len = header.cmd_len; + + if (current_cmd_len > header.cmd_len) + { + cli_clear_eos(p_cli); + } + + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%s", p_cli->p_ctx->cmd_buff); + if (cursor_in_empty_line(p_cli) || full_line_cmd(p_cli)) + { + cursor_next_line_move(p_cli); + } +} + +static void history_list_element_add(nrf_cli_t const * p_cli, nrf_memobj_t * p_memobj) +{ + ASSERT(p_memobj != NULL); + + nrf_cli_memobj_header_t header; + + if (p_cli->p_ctx->p_cmd_list_head == NULL) + { + p_cli->p_ctx->p_cmd_list_head = p_memobj; + p_cli->p_ctx->p_cmd_list_tail = p_memobj; + header.p_prev = NULL; + header.p_next = NULL; + header.cmd_len = p_cli->p_ctx->cmd_buff_len; + } + else + { + nrf_memobj_read(p_cli->p_ctx->p_cmd_list_head, + &header, + NRF_CLI_HISTORY_HEADER_SIZE, + 0); + + header.p_next = p_memobj; + + nrf_memobj_write(p_cli->p_ctx->p_cmd_list_head, + &header, + NRF_CLI_HISTORY_HEADER_SIZE, + 0); + + header.p_next = NULL; + header.p_prev = p_cli->p_ctx->p_cmd_list_head; + header.cmd_len = p_cli->p_ctx->cmd_buff_len; + + p_cli->p_ctx->p_cmd_list_head = p_memobj; + } + + nrf_memobj_write(p_memobj, + &header, + NRF_CLI_HISTORY_HEADER_SIZE, + 0); + + nrf_memobj_write(p_memobj, + p_cli->p_ctx->cmd_buff, + p_cli->p_ctx->cmd_buff_len + 1, /* +1 for '\0' */ + NRF_CLI_HISTORY_HEADER_SIZE); +} + +static void history_list_element_oldest_remove(nrf_cli_t const * p_cli) +{ + if (p_cli->p_ctx->p_cmd_list_tail == NULL) + { + return; // nothing to do + } + + nrf_cli_memobj_header_t header; + nrf_memobj_t * p_memobj = p_cli->p_ctx->p_cmd_list_tail; + + nrf_memobj_read(p_memobj, + &header, + NRF_CLI_HISTORY_HEADER_SIZE, + 0); + + p_cli->p_ctx->p_cmd_list_tail = header.p_next; + memset(&header, 0, sizeof(nrf_cli_memobj_header_t)); + nrf_memobj_write(p_memobj, &header, NRF_CLI_HISTORY_HEADER_SIZE, 0); + nrf_memobj_free(p_memobj); + + /* Checking if memory objects list is empty. */ + if (p_cli->p_ctx->p_cmd_list_tail == NULL) + { + p_cli->p_ctx->p_cmd_list_head = NULL; + return; + } + + nrf_memobj_read(p_cli->p_ctx->p_cmd_list_tail, + &header, + NRF_CLI_HISTORY_HEADER_SIZE, + 0); + + header.p_prev = NULL; + nrf_memobj_write(p_cli->p_ctx->p_cmd_list_tail, &header, NRF_CLI_HISTORY_HEADER_SIZE, 0); +} + +static void history_list_free_memory(nrf_cli_t const * p_cli) +{ + while (p_cli->p_ctx->p_cmd_list_tail != NULL) + { + history_list_element_oldest_remove(p_cli); + } +} + +static void history_save(nrf_cli_t const * p_cli) +{ + nrf_cli_cmd_len_t cmd_new_len = cli_strlen(p_cli->p_ctx->cmd_buff); + + history_mode_exit(p_cli); + + if (cmd_new_len == 0) + { + return; + } + + /* Checking if newly entered command is not duplicated with previous one. */ + if (p_cli->p_ctx->p_cmd_list_head != NULL) + { + nrf_cli_memobj_header_t header; + + nrf_memobj_read(p_cli->p_ctx->p_cmd_list_head, + &header, + NRF_CLI_HISTORY_HEADER_SIZE, + 0); + if (cmd_new_len == header.cmd_len) + { + nrf_memobj_read(p_cli->p_ctx->p_cmd_list_head, + p_cli->p_ctx->temp_buff, + header.cmd_len + 1, /* +1 for '\0' */ + NRF_CLI_HISTORY_HEADER_SIZE); + + if (strcmp(p_cli->p_ctx->cmd_buff, p_cli->p_ctx->temp_buff) == 0) + { + /* Duplicated command, nothing to save. */ + p_cli->p_ctx->temp_buff[0] = '\0'; + return; + } + p_cli->p_ctx->temp_buff[0] = '\0'; + } + } + + for (size_t idx = 0; idx < NRF_CLI_HISTORY_ELEMENT_COUNT; idx++) + { + nrf_memobj_t * p_memobj; + + p_memobj = nrf_memobj_alloc(p_cli->p_cmd_hist_mempool, + ((size_t)NRF_CLI_HISTORY_HEADER_SIZE + cmd_new_len + 1)); + if (p_memobj != NULL) + { + history_list_element_add(p_cli, p_memobj); + return; + } + else + { + history_list_element_oldest_remove(p_cli); + } + } + return; +} +#endif // NRF_MODULE_ENABLED(NRF_CLI_HISTORY) + +/* Function checks how many identical characters have two strings starting from the first character. */ +static nrf_cli_cmd_len_t str_similarity_check(char const * str_a, char const * str_b) +{ + nrf_cli_cmd_len_t cnt = 0; + + while (str_a[cnt] != '\0') + { + if (str_a[cnt] != str_b[cnt]) + { + return cnt; + } + + if (++cnt == 0) + { + return --cnt; /* too long strings */ + } + } + return cnt; +} + +static void completion_insert(nrf_cli_t const * p_cli, + char const * p_compl, + nrf_cli_cmd_len_t compl_len) +{ + ASSERT (p_compl); + + nrf_cli_cmd_len_t diff = p_cli->p_ctx->cmd_buff_len - p_cli->p_ctx->cmd_buff_pos; + + if ((p_cli->p_ctx->cmd_buff_len + compl_len > NRF_CLI_CMD_BUFF_SIZE - 1) || + (compl_len == 0)) + { + return; + } + + /* Make space for completion. */ + memmove(&p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos + compl_len], + &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos], + diff + 1); /* + 1 for '\0' */ + + /* Insert completion. */ + memmove(&p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos], + p_compl, + compl_len); + + p_cli->p_ctx->cmd_buff_len = cli_strlen(p_cli->p_ctx->cmd_buff); + nrf_cli_fprintf(p_cli, + NRF_CLI_NORMAL, + "%s", + &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]); + p_cli->p_ctx->cmd_buff_pos += compl_len; + + if (cursor_in_empty_line(p_cli) || full_line_cmd(p_cli)) + { + cursor_next_line_move(p_cli); + } + + if (diff > 0) + { + cursor_position_synchronize(p_cli); + } +} + +static void option_print(nrf_cli_t const * p_cli, + char const * p_option, + nrf_cli_cmd_len_t longest_option) +{ + static char const * tab = " "; + + /* Function initialization has been requested. */ + if (p_option == NULL) + { + p_cli->p_ctx->vt100_ctx.printed_cmd = 0; + return; + } + longest_option += cli_strlen(tab); + + nrf_cli_cmd_len_t columns = + (p_cli->p_ctx->vt100_ctx.cons.terminal_wid - cli_strlen(tab)) / longest_option; + nrf_cli_cmd_len_t diff = longest_option - cli_strlen(p_option); + + if (p_cli->p_ctx->vt100_ctx.printed_cmd++ % columns == 0) + { + nrf_cli_fprintf(p_cli, NRF_CLI_OPTION, "\n%s%s", tab, p_option); + } + else + { + nrf_cli_fprintf(p_cli, NRF_CLI_OPTION, "%s", p_option); + } + cursor_right_move(p_cli, diff); +} + +static inline bool is_completion_candidate(const char *candidate, + const char *str, + size_t len) +{ + return (strncmp(candidate, str, len) == 0) ? true : false; +} + +static void cli_tab_handle(nrf_cli_t const * p_cli) +{ + size_t cmd_idx; + size_t cmd_last = 0; + size_t cmd_first = 0; + size_t cmd_cnt = 0; + + size_t argc; + char * argv[NRF_CLI_ARGC_MAX + 1]; /* +1 reserved for NULL in function make_argv */ + + nrf_cli_cmd_len_t cmd_lvl = NRF_CLI_CMD_ROOT_LVL; + nrf_cli_cmd_len_t cmd_longest = 0; /* longest matching command */ + + /* Calculating the longest possible completion length. -1 for '\0'. */ + nrf_cli_cmd_len_t compl_len = (NRF_CLI_CMD_BUFF_SIZE - 1) - p_cli->p_ctx->cmd_buff_len; + + if (compl_len == 0) + { + return; + } + + /* Copy command from its beginning to cursor position. */ + memcpy(p_cli->p_ctx->temp_buff, + p_cli->p_ctx->cmd_buff, + p_cli->p_ctx->cmd_buff_pos); + + p_cli->p_ctx->temp_buff[p_cli->p_ctx->cmd_buff_pos] = '\0'; + + /* Check if the current cursor position points to the 'space' character. */ + bool space = isspace((int)p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos - 1]); + +#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) + /* If the Tab key is pressed, "history mode" must be terminated because tab and history handlers + are sharing the same array: temp_buff. */ + history_mode_exit(p_cli); +#endif + + /* Create argument list. */ + (void)make_argv(&argc, + &argv[0], + p_cli->p_ctx->temp_buff, + NRF_CLI_ARGC_MAX); + + nrf_cli_cmd_len_t arg_len = cli_strlen(argv[cmd_lvl]); + + /* Variable 'static_entry' is needed to handle dynamic commands. */ + nrf_cli_static_entry_t static_entry; + + nrf_cli_cmd_entry_t const * p_cmd = NULL; + nrf_cli_static_entry_t const * p_st_cmd = NULL; + nrf_cli_static_entry_t const * p_st_cmd_last = NULL; + + do + { + if ((argc == 0) || + (cmd_lvl >= argc - 1 + space)) + { + if (space) + { + arg_len = 0; + } + else + { + arg_len = cli_strlen(argv[cmd_lvl]); + } + + cmd_idx = 0; + + while (1) + { + cmd_get(p_cmd, cmd_lvl, cmd_idx++, &p_st_cmd, &static_entry); + + if (p_st_cmd == NULL) + { + /* No more commands available. */ + break; + } + + if (!is_completion_candidate(argv[cmd_lvl], + p_st_cmd->p_syntax, + arg_len)) + { + continue; + } + + cmd_cnt++; + + if (p_st_cmd_last == NULL) + { + cmd_first = cmd_idx - 1; + cmd_longest = cli_strlen(p_st_cmd->p_syntax); + if (compl_len > (cmd_longest - arg_len)) + { + compl_len = cmd_longest - arg_len; + } + } + else + { + nrf_cli_cmd_len_t len = cli_strlen(p_st_cmd->p_syntax); + if (len > cmd_longest) + { + cmd_longest = len; + } + + if (compl_len > 0) /* Checking if partial completion is possible */ + { + nrf_cli_static_entry_t last_entry; + cmd_get(p_cmd, cmd_lvl, cmd_last, &p_st_cmd_last, &last_entry); + + len = str_similarity_check(p_st_cmd->p_syntax + arg_len, + p_st_cmd_last->p_syntax + arg_len); + if (compl_len > len) + { + /* Determining the longest possible completion. */ + compl_len = len; + } + } + } + cmd_last = cmd_idx - 1; + p_st_cmd_last = p_st_cmd; + + if (cmd_idx == 0) /* Too many possibilities */ + { + nrf_cli_warn(p_cli, NRF_CLI_MSG_TAB_OVERFLOWED); + break; + } + } + } + else + { + cmd_idx = 0; + + while (1) + { + cmd_get(p_cmd, cmd_lvl, cmd_idx++, &p_st_cmd, &static_entry); + + if (cmd_idx == 0) + { + /* No match found and commands counter overflowed. */ + nrf_cli_warn(p_cli, NRF_CLI_MSG_TAB_OVERFLOWED); + return; + } + + if (p_st_cmd == NULL) /* No more commands available */ + { + return; + } + +#if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD) + /* Ignore wildcard character arguments if they are "standalone". Example: + 1. log enable info b* -> "b*" is treated as a command so no match found + 2. log enable info b* -> "b* " is ignored, will prompt all available + commands. */ + if (wildcard_character_exist(argv[cmd_lvl])) + { + break; + } +#endif + /* Fuction "strcmp" is used because an exact match is required. */ + if (strcmp(argv[cmd_lvl], p_st_cmd->p_syntax) == 0) + { + p_cmd = p_st_cmd->p_subcmd; + break; + } + } + } + + if ((p_cmd == NULL) || (p_st_cmd == NULL)) + { + break; + } + + } while (++cmd_lvl < argc + space); + + if (cmd_cnt == 0) + { + /* No match found. */ + return; + } + + if (cmd_cnt == 1) /* only one match found */ + { + if (p_cmd->is_dynamic) + { + /* In case of dynamic entry, function cmd_get shall be called again for matching + * command index (cmd_last). It is because static_entry is most likely appended by + * not valid data. + */ + cmd_get(p_cmd, cmd_lvl, cmd_last, &p_st_cmd_last, &static_entry); + } + if (cli_strlen(p_st_cmd_last->p_syntax) != arg_len) /* no exact match found */ + { + completion_insert(p_cli, p_st_cmd_last->p_syntax + arg_len, compl_len); + } + + /* Next character in the buffer is not 'space'. */ + if (!isspace((int)p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos])) + { + if (p_cli->p_ctx->internal.flag.insert_mode) + { + p_cli->p_ctx->internal.flag.insert_mode = 0; + char_insert(p_cli, ' '); + p_cli->p_ctx->internal.flag.insert_mode = 1; + } + else + { + char_insert(p_cli, ' '); + } + } + else + { + /* case: + | | -> cursor + cons_name $: valid_cmd valid_sub_cmd| |argument + */ + cursor_position_increment(p_cli); + /* result: + cons_name $: valid_cmd valid_sub_cmd |a|rgument + */ + } + return; + } + + /* Printing all matching commands (options). */ + option_print(p_cli, NRF_CLI_INIT_OPTION_PRINTER, cmd_longest); + cmd_idx = cmd_first; + while (cmd_cnt) + { + cmd_get(p_cmd, cmd_lvl, cmd_idx++, &p_st_cmd, &static_entry); + if (!is_completion_candidate(argv[cmd_lvl], + p_st_cmd->p_syntax, + arg_len)) + { + continue; + } + cmd_cnt--; + option_print(p_cli, p_st_cmd->p_syntax, cmd_longest); + } + + nrf_cli_fprintf(p_cli, NRF_CLI_INFO, "\n%s", p_cli->p_name); + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%s", p_cli->p_ctx->cmd_buff); + + cursor_position_synchronize(p_cli); + completion_insert(p_cli, p_st_cmd_last->p_syntax + arg_len, compl_len); +} + +/* Functions returns true if new line character shall be processed */ +static bool process_nl(nrf_cli_t const * p_cli, uint8_t data) +{ + if ((data != '\r') && (data != '\n')) + { + cli_flag_last_nl_set(p_cli, 0); + return false; + } + + if ((cli_flag_last_nl_get(p_cli) == 0) || + (data == cli_flag_last_nl_get(p_cli))) + { + cli_flag_last_nl_set(p_cli, data); + return true; + } + + return false; +} + +#define NRF_CLI_ASCII_MAX_CHAR (127u) +static inline ret_code_t ascii_filter(char const data) +{ + return (uint8_t)data > NRF_CLI_ASCII_MAX_CHAR ? NRF_ERROR_INVALID_DATA : NRF_SUCCESS; +} + +static void cli_state_collect(nrf_cli_t const * p_cli) +{ + size_t count = 0; + char data; + + while (1) + { + cli_read(p_cli, &data, sizeof(data), &count); + if (count == 0) + { + return; + } + + if (ascii_filter(data) != NRF_SUCCESS) + { + continue; + } + +#if NRF_MODULE_ENABLED(NRF_PWR_MGMT) + nrf_pwr_mgmt_feed(); +#endif + + switch (p_cli->p_ctx->receive_state) + { + case NRF_CLI_RECEIVE_DEFAULT: + if (process_nl(p_cli, data)) + { + if (p_cli->p_ctx->cmd_buff_len == 0) + { +#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) + history_mode_exit(p_cli); +#endif + cursor_next_line_move(p_cli); + } + else + { + /* Command execution */ + cli_execute(p_cli); + } + + cli_state_set(p_cli, NRF_CLI_STATE_ACTIVE); + return; + } + switch (data) + { + case NRF_CLI_VT100_ASCII_ESC: /* ESCAPE */ + receive_state_change(p_cli, NRF_CLI_RECEIVE_ESC); + break; + case '\0': + break; +#if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS) + case NRF_CLI_VT100_ASCII_CTRL_A: /* CTRL + A */ + cursor_home_position_move(p_cli); + break; + case NRF_CLI_VT100_ASCII_CTRL_C: /* CTRL + C */ + cursor_end_position_move(p_cli); + if (!cursor_in_empty_line(p_cli)) + { + cursor_next_line_move(p_cli); + } + cli_state_set(p_cli, NRF_CLI_STATE_ACTIVE); + break; + case NRF_CLI_VT100_ASCII_CTRL_E: /* CTRL + E */ + cursor_end_position_move(p_cli); + break; + case NRF_CLI_VT100_ASCII_CTRL_L: /* CTRL + L */ + NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CURSORHOME); + NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CLEARSCREEN); + nrf_cli_fprintf(p_cli, NRF_CLI_INFO, "%s", p_cli->p_name); + if (cli_flag_echo_is_set(p_cli)) + { + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%s", p_cli->p_ctx->cmd_buff); + cursor_position_synchronize(p_cli); + } + break; + case NRF_CLI_VT100_ASCII_CTRL_U: /* CTRL + U */ + cursor_home_position_move(p_cli); + cli_cmd_buffer_clear(p_cli); + cli_clear_eos(p_cli); + break; + case NRF_CLI_VT100_ASCII_CTRL_W: /* CTRL + W */ + cli_cmd_word_remove(p_cli); + break; +#endif + case '\t': /* TAB */ + if (cli_flag_echo_is_set(p_cli)) + { + cli_tab_handle(p_cli); + } + break; + case NRF_CLI_VT100_ASCII_BSPACE: /* BACKSPACE */ + if (cli_flag_echo_is_set(p_cli)) + { + char_backspace(p_cli); + } + break; + case NRF_CLI_VT100_ASCII_DEL: /* DELETE */ + if (cli_flag_echo_is_set(p_cli)) + { + char_delete(p_cli); + } + break; + default: + if (isprint((int)data)) + { + if (cli_flag_echo_is_set(p_cli)) + { + char_insert(p_cli, data); + } + else + { + char_insert_echo_off(p_cli, data); + } + } + break; + } + break; + case NRF_CLI_RECEIVE_ESC: + if (data == '[') + { + receive_state_change(p_cli, NRF_CLI_RECEIVE_ESC_SEQ); + } + else + { + receive_state_change(p_cli, NRF_CLI_RECEIVE_DEFAULT); + } + break; + case NRF_CLI_RECEIVE_ESC_SEQ: + receive_state_change(p_cli, NRF_CLI_RECEIVE_DEFAULT); + + if (!cli_flag_echo_is_set(p_cli)) + { + return; + } + + switch (data) + { +#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) + case 'A': /* UP arrow */ + history_handle(p_cli, true); + break; + case 'B': /* DOWN arrow */ + history_handle(p_cli, false); + break; +#endif + case 'C': /* RIGHT arrow */ + right_arrow_handle(p_cli); + break; + case 'D': /* LEFT arrow */ + left_arrow_handle(p_cli); + break; + case '4': /* END Button in ESC[n~ mode */ + receive_state_change(p_cli, NRF_CLI_RECEIVE_TILDE_EXP); + /* fall through */ + case 'F': /* END Button in VT100 mode */ + cursor_end_position_move(p_cli); + break; + case '1': /* HOME Button in ESC[n~ mode */ + receive_state_change(p_cli, NRF_CLI_RECEIVE_TILDE_EXP); + /* fall through */ + case 'H': /* HOME Button in VT100 mode */ + cursor_home_position_move(p_cli); + break; + case '2': /* INSERT Button in ESC[n~ mode */ + receive_state_change(p_cli, NRF_CLI_RECEIVE_TILDE_EXP); + /* fall through */ + case 'L': /* INSERT Button in VT100 mode */ + p_cli->p_ctx->internal.flag.insert_mode ^= 1; + break; + case '3':/* DELETE Button in ESC[n~ mode */ + receive_state_change(p_cli, NRF_CLI_RECEIVE_TILDE_EXP); + if (cli_flag_echo_is_set(p_cli)) + { + char_delete(p_cli); + } + break; + default: + break; + } + break; + case NRF_CLI_RECEIVE_TILDE_EXP: + receive_state_change(p_cli, NRF_CLI_RECEIVE_DEFAULT); + break; + default: + receive_state_change(p_cli, NRF_CLI_RECEIVE_DEFAULT); + break; + } + } +} + +/* Function remove white chars from beginning and end of command buffer. */ +static void cmd_trim(nrf_cli_t const * p_cli) +{ + nrf_cli_cmd_len_t i = 0; + + if (p_cli->p_ctx->cmd_buff[0] == '\0') /* no command in the buffer */ + { + return; + } + + /* Counting white characters starting from beginning of the command. */ + while (isspace((int)p_cli->p_ctx->cmd_buff[i++])) + { + if (i == 0) + { + p_cli->p_ctx->cmd_buff[0] = '\0'; + return; + } + } + + /* Removing counted white characters. */ + if (--i > 0) + { + memmove(p_cli->p_ctx->cmd_buff, + p_cli->p_ctx->cmd_buff + i, + (p_cli->p_ctx->cmd_buff_len + 1) - i); /* +1 for '\0' */ + p_cli->p_ctx->cmd_buff_len = p_cli->p_ctx->cmd_buff_len - i; + p_cli->p_ctx->cmd_buff_pos = p_cli->p_ctx->cmd_buff_len; + } + + /* Counting white characters starting from end of command. */ + char * p_end = &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_len - 1]; + i = 0; + while (isspace((int)*p_end)) + { + ++i; + --p_end; + } + + /* Removing counted white characters. */ + if (p_end != &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_len - 1]) + { + p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_len - i] = '\0'; + p_cli->p_ctx->cmd_buff_len = p_cli->p_ctx->cmd_buff_len - i; + p_cli->p_ctx->cmd_buff_pos = p_cli->p_ctx->cmd_buff_len; + } +} + +#if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD) +static void spaces_trim(char * p_char) +{ + nrf_cli_cmd_len_t shift = 0; + nrf_cli_cmd_len_t len = cli_strlen(p_char); + + if (p_char == NULL) + { + return; + } + + for (nrf_cli_cmd_len_t i = 0; i < len - 1; i++) + { + if (isspace((int)p_char[i])) + { + for (nrf_cli_cmd_len_t j = i + 1; j < len; j++) + { + if (isspace((int)p_char[j])) + { + shift++; + continue; + } + if (shift > 0) + { + memmove(&p_char[i + 1], &p_char[j], len - shift - i); + len -= shift; + shift = 0; + } + break; + } + } + } +} + +/* Adds new command and one space just before pattern */ +static bool command_to_tmp_buffer_add(nrf_cli_t const * p_cli, + char const * p_new_cmd, + char const * p_pattern) +{ + nrf_cli_cmd_len_t cmd_len = cli_strlen(p_new_cmd); + nrf_cli_cmd_len_t shift; + char * p_cmd_source_addr; + + /* +1 for space */ + if (((size_t)p_cli->p_ctx->cmd_tmp_buff_len + cmd_len + 1) > NRF_CLI_CMD_BUFF_SIZE) + { + nrf_cli_warn(p_cli, + "Command buffer is too short to expand all commands matching " + "wildcard pattern"); + return false; + } + + p_cmd_source_addr = strstr(p_cli->p_ctx->temp_buff, p_pattern); + + if (p_cmd_source_addr == NULL) + { + return false; + } + + shift = cli_strlen(p_cmd_source_addr); + + /* make place for new command: + 1 for space + 1 for EOS */ + memmove(p_cmd_source_addr + cmd_len + 1, p_cmd_source_addr, shift + 1); + memcpy(p_cmd_source_addr, p_new_cmd, cmd_len); + p_cmd_source_addr[cmd_len] = ' '; + + p_cli->p_ctx->cmd_tmp_buff_len += cmd_len + 1; // + 1 for space + + return true; +} + +/* removes pattern and following space */ +static void pattern_from_tmp_buffer_remove(nrf_cli_t const * p_cli, + char const * p_pattern) +{ + size_t shift; + char * p_pattern_addr = strstr(p_cli->p_ctx->temp_buff, p_pattern); + + nrf_cli_cmd_len_t pattern_len = cli_strlen(p_pattern); + + if (p_pattern_addr == NULL) + { + return; + } + + if (p_pattern_addr > p_cli->p_ctx->temp_buff) + { + if (*(p_pattern_addr - 1) == ' ') + { + pattern_len++; /* space needs to be removed as well */ + p_pattern_addr--; /* set pointer to space */ + } + } + + shift = cli_strlen(p_pattern_addr) - pattern_len + 1; /* +1 for EOS */ + p_cli->p_ctx->cmd_tmp_buff_len -= pattern_len; + + memmove(p_pattern_addr, p_pattern_addr + pattern_len, shift); +} + +/** + * @internal @brief Function for searching and adding commands matching to wildcard pattern. + * + * This function is internal to nrf_cli module and shall be not called directly. + * + * @param[in/out] p_cli Pointer to the CLI instance. + * @param[in] p_cmd Pointer to command which will be processed + * @param[in] cmd_lvl Command level in the command tree. + * @param[in] p_pattern Pointer to wildcard pattern. + * @param[out] p_counter Number of found and added commands. + * + * @retval WILDCARD_CMD_ADDED All matching commands added to the buffer. + * @retval WILDCARD_CMD_ADDED_MISSING_SPACE Not all matching commands added because + * NRF_CLI_CMD_BUFF_SIZE is too small. + * @retval WILDCARD_CMD_NO_MATCH_FOUND No matching command found. + */ +static wildcard_cmd_status_t commands_expand(nrf_cli_t const * p_cli, + nrf_cli_cmd_entry_t const * p_cmd, + size_t cmd_lvl, + char * p_pattern, + size_t * p_counter) +{ + size_t cmd_idx = 0; + size_t counter = 0; + bool success = false; + + nrf_cli_static_entry_t static_entry; + nrf_cli_static_entry_t const * p_static_entry = NULL; + wildcard_cmd_status_t ret_val = WILDCARD_CMD_NO_MATCH_FOUND; + + do + { + cmd_get(p_cmd, + cmd_lvl, + cmd_idx++, + &p_static_entry, + &static_entry); + + if (p_static_entry == NULL) + { + break; + } + + if (0 == fnmatch(p_pattern, p_static_entry->p_syntax, 0)) + { + success = command_to_tmp_buffer_add(p_cli, + p_static_entry->p_syntax, + p_pattern); + if (!success) + { + break; + } + counter++; + } + + } while(cmd_idx != 0); + + if (counter > 0) + { + *p_counter = counter; + pattern_from_tmp_buffer_remove(p_cli, p_pattern); + + if (success) + { + ret_val = WILDCARD_CMD_ADDED; + } + else + { + ret_val = WILDCARD_CMD_ADDED_MISSING_SPACE; + } + } + + return ret_val; +} +#endif // NRF_MODULE_ENABLED(NRF_CLI_WILDCARD) + +/* Function is analyzing the command buffer to find matching commands. Next, it invokes the last recognized + * command which has a handler and passes the rest of command buffer as arguments. */ +static void cli_execute(nrf_cli_t const * p_cli) +{ + char quote; + size_t argc; + char * argv[NRF_CLI_ARGC_MAX + 1]; /* +1 reserved for NULL added by function make_argv */ + + size_t cmd_idx; /* currently analyzed command in cmd_level */ + size_t cmd_lvl = NRF_CLI_CMD_ROOT_LVL; /* currently analyzed command level */ + size_t cmd_handler_lvl = 0; /* last command level for which a handler has been found */ + + nrf_cli_cmd_entry_t const * p_cmd = NULL; + + cmd_trim(p_cli); + +#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) + history_save(p_cli); +#endif + +#if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD) +/* Wildcard can be correctly handled under following conditions: + - wildcard command does not have a handler + - wildcard command is on the deepest commands level + - other commands on the same level as wildcard command shall also not have a handler + + Algorithm: + 1. Command buffer is copied to Temp buffer. + 2. Algorithm goes through Command buffer to find handlers and subcommands. + 3. If algorithm will find a wildcard character it switches to Temp buffer. + 4. In the Temp buffer command with found wildcard character is changed into matching command(s). + 5. Algorithm switch back to Command buffer and analyzes next command. + 6. When all arguments are analyzed from Command buffer, Temp buffer is copied to Command buffer. + 7. Last found handler is executed with all arguments in the Command buffer. +*/ + size_t commands_expanded = 0; + + memset(p_cli->p_ctx->temp_buff, 0, sizeof(p_cli->p_ctx->temp_buff)); + memcpy(p_cli->p_ctx->temp_buff, + p_cli->p_ctx->cmd_buff, + p_cli->p_ctx->cmd_buff_len); + + /* Function spaces_trim must be used instead of make_argv. At this point it is important to keep + temp_buff as a one string. It will allow to find wildcard commands easly with strstr + function. */ + spaces_trim(p_cli->p_ctx->temp_buff); + p_cli->p_ctx->cmd_tmp_buff_len = cli_strlen(p_cli->p_ctx->temp_buff) + 1; // +1 for EOS +#endif + + cursor_end_position_move(p_cli); + if (!cursor_in_empty_line(p_cli)) + { + cursor_next_line_move(p_cli); + } + + /* create argument list */ + quote = make_argv(&argc, + &argv[0], + p_cli->p_ctx->cmd_buff, + NRF_CLI_ARGC_MAX); + + if (!argc) + { + cursor_next_line_move(p_cli); + return; + } + + if (quote != 0) + { + nrf_cli_error(p_cli, "not terminated: %c", quote); + return; + } + + /* Searching for a matching root command. */ + for (cmd_idx = 0; cmd_idx <= CLI_DATA_SECTION_ITEM_COUNT; ++cmd_idx) + { + if (cmd_idx >= CLI_DATA_SECTION_ITEM_COUNT) + { + nrf_cli_error(p_cli, "%s%s", argv[0], NRF_CLI_MSG_COMMAND_NOT_FOUND); + return; + } + + p_cmd = CLI_DATA_SECTION_ITEM_GET(cmd_idx); + if (strcmp(argv[cmd_lvl], p_cmd->u.p_static->p_syntax) != 0) + { + continue; + } + break; + } + + /* Root command shall be always static. */ + ASSERT(p_cmd->is_dynamic == false); + + /* Memory reserved for dynamic commands. */ + nrf_cli_static_entry_t static_entry; + nrf_cli_static_entry_t const * p_static_entry = NULL; + + memset(&p_cli->p_ctx->active_cmd, 0, sizeof(p_cli->p_ctx->active_cmd)); + if (p_cmd->u.p_static->handler != NULL) + { + p_cli->p_ctx->active_cmd = *p_cmd->u.p_static; + } + + p_cmd = p_cmd->u.p_static->p_subcmd; + cmd_lvl++; + cmd_idx = 0; + + while (1) + { + if (cmd_lvl >= argc) + { + break; + } + + if (!strcmp(argv[cmd_lvl], "-h") || !strcmp(argv[cmd_lvl], "--help")) + { + /* Command called with help option so it makes no sense to search deeper commands. */ + cli_flag_help_set(p_cli); + break; + } + +#if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD) + /* Wildcard character is found */ + if (wildcard_character_exist(argv[cmd_lvl])) + { + size_t counter = 0; + wildcard_cmd_status_t status; + + /* Function will search commands tree for commands matching wildcard pattern stored in + argv[cmd_lvl]. If match is found wildcard pattern will be replaced by matching + commands in temp_buffer. If there is no space to add all matching commands function + will add as many as possible. Next it will continue to search for next wildcard + pattern and it will try to add matching commands. */ + status = commands_expand(p_cli, p_cmd, cmd_lvl, argv[cmd_lvl], &counter); + if (WILDCARD_CMD_NO_MATCH_FOUND == status) + { + break; + } + commands_expanded += counter; + cmd_lvl++; + continue; + } +#endif + + cmd_get(p_cmd, + cmd_lvl, + cmd_idx++, + &p_static_entry, + &static_entry); + + if ((cmd_idx == 0) || (p_static_entry == NULL)) + { + break; + } + + if (strcmp(argv[cmd_lvl], p_static_entry->p_syntax) == 0) + { + /* checking if command has a handler */ + if (p_static_entry->handler != NULL) + { +#if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD) + if (commands_expanded > 0) + { + cursor_end_position_move(p_cli); + if (!cursor_in_empty_line(p_cli)) + { + cursor_next_line_move(p_cli); + } + /* An error occured, fnmatch argument cannot be followed by argument + * with a handler to avoid multiple function calls. */ + nrf_cli_error(p_cli, "Error: requested multiple function executions"); + cli_flag_help_clear(p_cli); + return; + } +#endif + /* Storing p_st_cmd->handler is not feasible for dynamic commands. Data will be + * invalid with the next loop iteration. */ + cmd_handler_lvl = cmd_lvl; + p_cli->p_ctx->active_cmd = *p_static_entry; + } + + cmd_lvl++; + cmd_idx = 0; + p_cmd = p_static_entry->p_subcmd; + } + } +#if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD) + if (commands_expanded > 0) + { + /* Copy temp_buff to cmd_buff */ + memcpy(p_cli->p_ctx->cmd_buff, + p_cli->p_ctx->temp_buff, + p_cli->p_ctx->cmd_tmp_buff_len); + p_cli->p_ctx->cmd_buff_len = p_cli->p_ctx->cmd_tmp_buff_len; + + /* calling make_arg function again because cmd_buffer has additional commads */ + (void)make_argv(&argc, + &argv[0], + p_cli->p_ctx->cmd_buff, + NRF_CLI_ARGC_MAX); + } + #endif + + if (p_cli->p_ctx->active_cmd.handler != NULL) + { + p_cli->p_ctx->active_cmd.handler(p_cli, + argc - cmd_handler_lvl, + &argv[cmd_handler_lvl]); + } + else + { + nrf_cli_error(p_cli, NRF_CLI_MSG_SPECIFY_SUBCOMMAND); + } + cli_flag_help_clear(p_cli); +} + +/* Function required by qsort. */ +static int string_cmp(void const * pp_a, void const * pp_b) +{ + ASSERT(pp_a); + ASSERT(pp_b); + + char const ** pp_str_a = (char const **)pp_a; + char const ** pp_str_b = (char const **)pp_b; + + return strcmp(*pp_str_a, *pp_str_b); +} + +static void cli_transport_evt_handler(nrf_cli_transport_evt_t evt_type, void * p_context) +{ + nrf_cli_t * p_cli = (nrf_cli_t *)p_context; + ASSERT(p_cli); +#if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER) + task_events_set(p_cli->p_ctx->task_id, evt_type == NRF_CLI_TRANSPORT_EVT_RX_RDY ? + NRF_CLI_TRANSPORT_RX_RDY_TASK_EVT : NRF_CLI_TRANSPORT_TX_RDY_TASK_EVT); +#else + + if (evt_type == NRF_CLI_TRANSPORT_EVT_RX_RDY) + { + + } + else + { + /* wr done evt */ + p_cli->p_ctx->internal.flag.tx_rdy = 1; + } +#endif +} + +static ret_code_t nrf_cli_instance_init(nrf_cli_t const * p_cli, + void const * p_config, + bool use_colors) +{ + ASSERT(p_cli); + ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name); + +#if defined(NRF_CLI_LOG_BACKEND) && NRF_CLI_LOG_BACKEND + ((nrf_cli_log_backend_t *)p_cli->p_log_backend->p_ctx)->p_cli = p_cli; +#endif + ret_code_t ret = p_cli->p_iface->p_api->init(p_cli->p_iface, + p_config, + cli_transport_evt_handler, + (void *)p_cli); + if (ret != NRF_SUCCESS) + { + return ret; + } + +#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) + ASSERT(p_cli->p_cmd_hist_mempool); + ret = nrf_memobj_pool_init(p_cli->p_cmd_hist_mempool); + if (ret != NRF_SUCCESS) + { + return ret; + } + p_cli->p_ctx->p_cmd_list_head = NULL; + p_cli->p_ctx->p_cmd_list_tail = NULL; +#endif + + memset(p_cli->p_ctx, 0, sizeof(nrf_cli_ctx_t)); + p_cli->p_ctx->internal.flag.tx_rdy = 1; + +#if NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS) + p_cli->p_ctx->internal.flag.use_colors = use_colors; +#endif + p_cli->p_ctx->internal.flag.echo = NRF_CLI_ECHO_STATUS; + p_cli->p_ctx->state = NRF_CLI_STATE_INITIALIZED; + p_cli->p_ctx->vt100_ctx.cons.terminal_wid = NRF_CLI_DEFAULT_TERMINAL_WIDTH; + p_cli->p_ctx->vt100_ctx.cons.terminal_hei = NRF_CLI_DEFAULT_TERMINAL_HEIGHT; + + const char * * pp_sorted_cmds = (const char * *)CLI_SORTED_CMD_PTRS_START_ADDR_GET; + for (size_t i = 0; i < CLI_DATA_SECTION_ITEM_COUNT; i++) + { + const nrf_cli_cmd_entry_t * cmd; + cmd = CLI_DATA_SECTION_ITEM_GET(i); + + /* NULL syntax commands not allowed. */ + ASSERT(cmd); + ASSERT(cmd->u.p_static->p_syntax); + + pp_sorted_cmds[i] = cmd->u.p_static->p_syntax; + } + + if (CLI_DATA_SECTION_ITEM_COUNT > 0) + { + qsort(pp_sorted_cmds, + CLI_DATA_SECTION_ITEM_COUNT, + sizeof (char *), + string_cmp); + } + + return NRF_SUCCESS; +} + +#if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER) +static ret_code_t nrf_cli_instance_uninit(nrf_cli_t const * p_cli); +void console_task(void * p_context) +{ + nrf_cli_t * p_cli = (nrf_cli_t *)p_context; + + ret_code_t ret = nrf_cli_start(p_cli); + APP_ERROR_CHECK(ret); + + while (1) + { + uint32_t evts = task_events_wait(NRF_CLI_TASK_EVTS); + + if (evts & NRF_CLI_KILL_TASK_EVT) + { + (void)nrf_cli_instance_uninit(p_cli); + task_exit(); + } + else + { + nrf_cli_process(p_cli); + } + } +} +#endif + +ret_code_t nrf_cli_init(nrf_cli_t const * p_cli, + void const * p_config, + bool use_colors, + bool log_backend, + nrf_log_severity_t init_lvl) +{ + ASSERT(p_cli); + + ret_code_t err_code = nrf_cli_instance_init(p_cli, p_config, use_colors); + +#if NRF_CLI_LOG_BACKEND && NRF_MODULE_ENABLED(NRF_LOG) + if ((err_code == NRF_SUCCESS) && log_backend && NRF_CLI_LOG_BACKEND) + { + int32_t id = nrf_log_backend_add(p_cli->p_log_backend, init_lvl); + if (id < 0) + { + return NRF_ERROR_NO_MEM; + } + + nrf_log_backend_enable(p_cli->p_log_backend); + } +#endif + return err_code; +} + +ret_code_t nrf_cli_task_create(nrf_cli_t const * p_cli) +{ +#if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER) + p_cli->p_ctx->task_id = task_create(console_task, p_cli->p_name,(void *)p_cli); + if (p_cli->p_ctx->task_id == TASK_ID_INVALID) + { + return NRF_ERROR_NO_MEM; + } + else + { + return NRF_SUCCESS; + } +#else + return NRF_ERROR_NOT_SUPPORTED; +#endif +} + +static ret_code_t nrf_cli_instance_uninit(nrf_cli_t const * p_cli) +{ + ASSERT(p_cli); + ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name); + + if (cli_flag_processing_is_set(p_cli)) + { + return NRF_ERROR_BUSY; + } + +#if NRF_CLI_LOG_BACKEND && NRF_MODULE_ENABLED(NRF_LOG) + if (p_cli->p_log_backend != NULL) + { + nrf_log_backend_disable(p_cli->p_log_backend); + nrf_log_backend_remove(p_cli->p_log_backend); + } +#endif + + ret_code_t ret = p_cli->p_iface->p_api->uninit(p_cli->p_iface); + if (ret != NRF_SUCCESS) + { + return ret; + } + +#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) + history_list_free_memory(p_cli); +#endif + + memset(p_cli->p_ctx, 0, sizeof(nrf_cli_ctx_t)); + p_cli->p_ctx->state = NRF_CLI_STATE_UNINITIALIZED; + + return NRF_SUCCESS; +} + +ret_code_t nrf_cli_uninit(nrf_cli_t const * p_cli) +{ +#if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER) + if (cli_flag_processing_is_set(p_cli)) + { + return NRF_ERROR_BUSY; + } + task_events_set(p_cli->p_ctx->task_id, NRF_CLI_KILL_TASK_EVT); + return NRF_SUCCESS; +#else + return nrf_cli_instance_uninit(p_cli); +#endif +} + +ret_code_t nrf_cli_start(nrf_cli_t const * p_cli) +{ + ASSERT(p_cli); + ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name); + + if (p_cli->p_ctx->state != NRF_CLI_STATE_INITIALIZED) + { + return NRF_ERROR_INVALID_STATE; + } + +#if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER) + void * p_context = (void *)((uint32_t)task_id_get()); + ((nrf_cli_log_backend_t *)p_cli->p_log_backend->p_ctx)->p_context = p_context; +#endif + + ret_code_t err_code = p_cli->p_iface->p_api->enable(p_cli->p_iface, false); + +#if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER) + task_events_set(task_id_get(), NRF_CLI_TRANSPORT_RX_RDY_TASK_EVT); +#endif + + if (err_code == NRF_SUCCESS) + { +#if NRF_CLI_VT100_COLORS_ENABLED + vt100_color_set(p_cli, NRF_CLI_NORMAL); + vt100_bgcolor_set(p_cli, NRF_CLI_VT100_COLOR_BLACK); +#endif + nrf_fprintf(p_cli->p_fprintf_ctx, "\n\n"); + cli_state_set(p_cli, NRF_CLI_STATE_ACTIVE); + } + + return err_code; +} + +ret_code_t nrf_cli_stop(nrf_cli_t const * p_cli) +{ + ASSERT(p_cli); + ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name); + + if (p_cli->p_ctx->state == NRF_CLI_STATE_INITIALIZED || + p_cli->p_ctx->state == NRF_CLI_STATE_UNINITIALIZED) + { + return NRF_ERROR_INVALID_STATE; + } + + cli_state_set(p_cli, NRF_CLI_STATE_INITIALIZED); + return NRF_SUCCESS; +} + +void nrf_cli_process(nrf_cli_t const * p_cli) +{ + ASSERT(p_cli); + ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name); + + nrf_cli_internal_t internal; + internal.value = 0; + internal.flag.processing = 1; + (void)nrf_atomic_u32_or((nrf_atomic_u32_t *)&p_cli->p_ctx->internal.value, + internal.value); + + switch (p_cli->p_ctx->state) + { + case NRF_CLI_STATE_UNINITIALIZED: + case NRF_CLI_STATE_INITIALIZED: + /* Console initialized but not started. */ + break; + case NRF_CLI_STATE_ACTIVE: + { + cli_state_collect(p_cli); + bool log_processed = cli_log_entry_process(p_cli, false); + if (log_processed) + { + nrf_cli_fprintf(p_cli, NRF_CLI_INFO, "%s", p_cli->p_name); + if (cli_flag_echo_is_set(p_cli)) + { + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%s", p_cli->p_ctx->cmd_buff); + cursor_position_synchronize(p_cli); + } + } + break; + } + default: + break; + } + transport_buffer_flush(p_cli); + internal.value = (uint32_t)0xFFFFFFFF; + internal.flag.processing = 0; + (void)nrf_atomic_u32_and((nrf_atomic_u32_t *)&p_cli->p_ctx->internal.value, + internal.value); +} + +/* Function shall be only used by the nrf_fprintf module. */ +void nrf_cli_print_stream(void const * p_user_ctx, char const * p_data, size_t data_len) +{ + cli_write((nrf_cli_t const *)p_user_ctx, + p_data, + data_len, + NULL); +} + +void nrf_cli_fprintf(nrf_cli_t const * p_cli, + nrf_cli_vt100_color_t color, + char const * p_fmt, + ...) +{ + ASSERT(p_fmt); + ASSERT(p_cli); + ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name); + + va_list args = {0}; + va_start(args, p_fmt); + +#if NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS) + if ((p_cli->p_ctx->internal.flag.use_colors) && + (color != p_cli->p_ctx->vt100_ctx.col.col)) + { + nrf_cli_vt100_colors_t col; + + vt100_colors_store(p_cli, &col); + vt100_color_set(p_cli, color); + + nrf_fprintf_fmt(p_cli->p_fprintf_ctx, p_fmt, &args); + + vt100_colors_restore(p_cli, &col); + } + else +#endif // NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS) + { + nrf_fprintf_fmt(p_cli->p_fprintf_ctx, p_fmt, &args); + } + + va_end(args); +} + +/* Function prints a string on terminal screen with requested margin. + * It takes care to not divide words. + * p_cli Pointer to CLI instance. + * p_str Pointer to string to be printed. + * terminal_offset Requested left margin. + * offset_first_line Add margin to the first printed line. + */ +static void format_offset_string_print(nrf_cli_t const * p_cli, + char const * p_str, + size_t terminal_offset, + bool offset_first_line) +{ + if (p_str == NULL) + { + return; + } + + if (offset_first_line) + { + cursor_right_move(p_cli, terminal_offset); + } + + size_t length; + size_t offset = 0; + + /* Skipping whitespace. */ + while (isspace((int)*(p_str + offset))) + { + ++offset; + } + + while (1) + { + size_t idx = 0; + length = cli_strlen(p_str) - offset; + + if (length <= p_cli->p_ctx->vt100_ctx.cons.terminal_wid - terminal_offset) + { + for (idx = 0; idx < length; idx++) + { + if (*(p_str + offset + idx) == '\n') + { + transport_buffer_flush(p_cli); + cli_write(p_cli, p_str + offset, idx, NULL); + offset += idx + 1; + cursor_next_line_move(p_cli); + cursor_right_move(p_cli, terminal_offset); + break; + } + } + /* String will fit in one line. */ + nrf_fprintf(p_cli->p_fprintf_ctx, p_str + offset); + break; + } + else + { + /* String is longer than terminal line so text needs to divide in the way + to not divide words. */ + length = p_cli->p_ctx->vt100_ctx.cons.terminal_wid - terminal_offset; + + while (1) + { + /* Determining line break. */ + if (isspace((int)(*(p_str + offset + idx)))) + { + length = idx; + if (*(p_str + offset + idx) == '\n') + { + break; + } + } + if ((idx + terminal_offset) >= p_cli->p_ctx->vt100_ctx.cons.terminal_wid) + { + /* End of line reached. */ + break; + } + ++idx; + } + + /* Writing one line, fprintf IO buffer must be flushed before calling cli_write. */ + transport_buffer_flush(p_cli); + cli_write(p_cli, p_str + offset, length, NULL); + offset += length; + + /* Calculating text offset to ensure that next line will not begin with a space. */ + while (isspace((int)(*(p_str + offset)))) + { + ++offset; + } + cursor_next_line_move(p_cli); + cursor_right_move(p_cli, terminal_offset); + } + } + cursor_next_line_move(p_cli); +} + +void nrf_cli_help_print(nrf_cli_t const * p_cli, + nrf_cli_getopt_option_t const * p_opt, + size_t opt_len) +{ + ASSERT(p_cli); + ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name); + + static uint8_t const tab_len = 2; + static char const opt_sep[] =", "; /* options separator */ + static char const help[] = "-h, --help"; + static char const cmd_sep[] = " - "; /* command separator */ + uint16_t field_width = 0; + uint16_t longest_string = cli_strlen(help) - cli_strlen(opt_sep); + + /* Printing help string for command. */ + nrf_cli_fprintf(p_cli, + NRF_CLI_NORMAL, + "%s%s", + p_cli->p_ctx->active_cmd.p_syntax, + cmd_sep); + + field_width = cli_strlen(p_cli->p_ctx->active_cmd.p_syntax) + cli_strlen(cmd_sep); + format_offset_string_print(p_cli, p_cli->p_ctx->active_cmd.p_help, field_width, false); + + nrf_cli_print(p_cli, "Options:"); + + /* Looking for the longest option string. */ + if ((opt_len > 0) && (p_opt != NULL)) + { + for (size_t i = 0; i < opt_len; ++i) + { + if (cli_strlen(p_opt[i].p_optname_short) + cli_strlen(p_opt[i].p_optname) + > longest_string) + { + longest_string = cli_strlen(p_opt[i].p_optname_short) + + cli_strlen(p_opt[i].p_optname); + } + } + } + longest_string += cli_strlen(opt_sep) + tab_len; + + nrf_cli_fprintf(p_cli, + NRF_CLI_NORMAL, + " %-*s:", + longest_string, + help); + + /* Print help string for options (only -h and --help). */ + field_width = longest_string + tab_len + 1; /* tab_len + 1 == " " and ':' from: " %-*s:" */ + format_offset_string_print(p_cli, "Show command help.", field_width, false); + + /* Formating and printing all available options (except -h, --help). */ + if (p_opt != NULL) + { + for (size_t i = 0; i < opt_len; ++i) + { + if ((p_opt[i].p_optname_short != NULL) && (p_opt[i].p_optname != NULL)) + { + nrf_cli_fprintf(p_cli, + NRF_CLI_NORMAL, + " %s%s%s", + p_opt[i].p_optname_short, + opt_sep, + p_opt[i].p_optname); + field_width = longest_string + tab_len; + cursor_right_move(p_cli, + field_width - ( cli_strlen(p_opt[i].p_optname_short) + + cli_strlen(p_opt[i].p_optname) + + tab_len + + cli_strlen(opt_sep))); + cli_putc(p_cli, ':'); + ++field_width; /* incrementing because char ':' was already printed above */ + } + else if (p_opt[i].p_optname_short != NULL) + { + nrf_cli_fprintf(p_cli, + NRF_CLI_NORMAL, + " %-*s:", + longest_string, + p_opt[i].p_optname_short); + /* tab_len + 1 == " " and ':' from: " %-*s:" */ + field_width = longest_string + tab_len + 1; + } + else if (p_opt[i].p_optname != NULL) + { + nrf_cli_fprintf(p_cli, + NRF_CLI_NORMAL, + " %-*s:", + longest_string, + p_opt[i].p_optname); + /* tab_len + 1 == " " and ':' from: " %-*s:" */ + field_width = longest_string + tab_len + 1; + } + else + { + /* Do nothing. */ + } + + if (p_opt[i].p_optname_help != NULL) + { + format_offset_string_print(p_cli, p_opt[i].p_optname_help, field_width, false); + } + else + { + cursor_next_line_move(p_cli); + } + } + } + + /* Checking if there are any subcommands avilable. */ + if (p_cli->p_ctx->active_cmd.p_subcmd == NULL) + { + return; + } + + /* Printing formatted help of one level deeper subcommands. */ + nrf_cli_static_entry_t static_entry; + nrf_cli_cmd_entry_t const * p_cmd = p_cli->p_ctx->active_cmd.p_subcmd; + nrf_cli_static_entry_t const * p_st_cmd = NULL; + + field_width = 0; + longest_string = 0; + + size_t cmd_idx = 0; + + /* Searching for the longest subcommand to print. */ + while (1) + { + cmd_get(p_cmd, !NRF_CLI_CMD_ROOT_LVL, cmd_idx++, &p_st_cmd, &static_entry); + + if (p_st_cmd == NULL) + { + break; + } + if (cli_strlen(p_st_cmd->p_syntax) > longest_string) + { + longest_string = cli_strlen(p_st_cmd->p_syntax); + } + } + + /* Checking if there are dynamic subcommands. */ + if (cmd_idx == 1) + { + /* No dynamic subcommands available. */ + return; + } + + nrf_cli_print(p_cli, "Subcommands:"); + + /* Printing subcommands and help string (if exists). */ + cmd_idx = 0; + while (1) + { + cmd_get(p_cmd, !NRF_CLI_CMD_ROOT_LVL, cmd_idx++, &p_st_cmd, &static_entry); + + if (p_st_cmd == NULL) + { + break; + } + + field_width = longest_string + tab_len; + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL," %-*s:", field_width, p_st_cmd->p_syntax); + field_width += tab_len + 1; /* tab_len + 1 == " " and ':' from: " %-*s:" */ + + if (p_st_cmd->p_help != NULL) + { + format_offset_string_print(p_cli, p_st_cmd->p_help, field_width, false); + } + else + { + cursor_next_line_move(p_cli); + } + } +} + +#if NRF_CLI_LOG_BACKEND && NRF_MODULE_ENABLED(NRF_LOG) + +#define NRF_CLI_LOG_MSG_OVERFLOW_MSK ((uint32_t)7) +static bool cli_log_entry_process(nrf_cli_t const * p_cli, bool skip) +{ + nrf_log_entry_t entry; + +#if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS) + bool print_msg = false; +#endif + + if (nrf_queue_pop(((nrf_cli_log_backend_t *)p_cli->p_log_backend->p_ctx)->p_queue, &entry) != + NRF_SUCCESS) + { + return false; + } + + if (skip) + { + nrf_memobj_put(entry); +#if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS) + ++p_cli->p_ctx->statistics.log_lost_cnt; + if ((p_cli->p_ctx->statistics.log_lost_cnt & NRF_CLI_LOG_MSG_OVERFLOW_MSK) == 1) + { + /* Set flag to print a message after clearing the currently entered command. */ + print_msg = true; + } + else +#endif + { + return true; + } + } + { + /* Erasing the currently displayed command and console name. */ + nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli); + + if (p_cons->cur_y > NRF_CLI_INITIAL_CURS_POS) + { + cursor_up_move(p_cli, p_cons->cur_y - NRF_CLI_INITIAL_CURS_POS); + } + + if (p_cons->cur_x > NRF_CLI_INITIAL_CURS_POS) + { + cursor_left_move(p_cli, p_cons->cur_x - NRF_CLI_INITIAL_CURS_POS); + } + cli_clear_eos(p_cli); + } + +#if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS) + if (print_msg) + { + /* Print the requested string and exit function. */ + nrf_cli_error(p_cli, "Lost logs - increase log backend queue size."); + + return true; + } +#endif + + /* Printing logs from the queue. */ + do + { + nrf_log_header_t header; + size_t memobj_offset = 0; + nrf_log_str_formatter_entry_params_t params; + + nrf_memobj_read(entry, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset); + memobj_offset = HEADER_SIZE * sizeof(uint32_t); + + params.timestamp = header.timestamp; + params.module_id = header.module_id; + params.dropped = header.dropped; + params.use_colors = NRF_LOG_USES_COLORS; /* Color will be provided by the console application. */ + + if (header.base.generic.type == HEADER_TYPE_STD) + { + char const * p_log_str = (char const *)((uint32_t)header.base.std.addr); + params.severity = (nrf_log_severity_t)header.base.std.severity; + uint32_t nargs = header.base.std.nargs; + uint32_t args[6]; + + nrf_memobj_read(entry, args, nargs*sizeof(uint32_t), memobj_offset); + nrf_log_std_entry_process(p_log_str, + args, + nargs, + ¶ms, + p_cli->p_fprintf_ctx); + } + else if (header.base.generic.type == HEADER_TYPE_HEXDUMP) + { + uint32_t data_len; + uint8_t data_buf[8]; + uint32_t chunk_len; + + data_len = header.base.hexdump.len; + params.severity = (nrf_log_severity_t)header.base.hexdump.severity; + + do + { + chunk_len = sizeof(data_buf) > data_len ? data_len : sizeof(data_buf); + nrf_memobj_read(entry, data_buf, chunk_len, memobj_offset); + memobj_offset += chunk_len; + data_len -= chunk_len; + nrf_log_hexdump_entry_process(data_buf, chunk_len, ¶ms, p_cli->p_fprintf_ctx); + } while (data_len > 0); + } + + nrf_memobj_put(entry); + } while (nrf_queue_pop(((nrf_cli_log_backend_t *)p_cli->p_log_backend->p_ctx)->p_queue, &entry) + == NRF_SUCCESS); + return true; +} + +static void nrf_log_backend_cli_put(nrf_log_backend_t const * p_backend, nrf_log_entry_t * p_msg) +{ + nrf_cli_log_backend_t * p_backend_cli = (nrf_cli_log_backend_t *)p_backend->p_ctx; + nrf_cli_t const * p_cli = p_backend_cli->p_cli; + + //If panic mode cannot be handled, stop handling new requests. + if (p_cli->p_ctx->state != NRF_CLI_STATE_PANIC_MODE_INACTIVE) + { + bool panic_mode = (p_cli->p_ctx->state == NRF_CLI_STATE_PANIC_MODE_ACTIVE); + //If there is no place for a new log entry, remove the oldest one. + ret_code_t err_code = nrf_queue_push(p_backend_cli->p_queue, &p_msg); + while (err_code != NRF_SUCCESS) + { + (void)cli_log_entry_process(p_cli, panic_mode ? false : true); + + err_code = nrf_queue_push(p_backend_cli->p_queue, &p_msg); + } + nrf_memobj_get(p_msg); + + if (panic_mode) + { + (void)cli_log_entry_process(p_cli, false); + } +#if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER) + else + { + task_events_set((task_id_t)((uint32_t)p_backend_cli->p_context & 0x000000FF), + NRF_CLI_LOG_PENDING_TASK_EVT); + } +#endif + } +} + +static void nrf_log_backend_cli_flush(nrf_log_backend_t const * p_backend) +{ + nrf_cli_log_backend_t * p_backend_cli = (nrf_cli_log_backend_t *)p_backend->p_ctx; + nrf_cli_t const * p_cli = p_backend_cli->p_cli; + + (void)cli_log_entry_process(p_cli, true); + + UNUSED_PARAMETER(p_backend); +} + +static void nrf_log_backend_cli_panic_set(nrf_log_backend_t const * p_backend) +{ + nrf_cli_log_backend_t * p_backend_cli = (nrf_cli_log_backend_t *)p_backend->p_ctx; + nrf_cli_t const * p_cli = p_backend_cli->p_cli; + + if (p_cli->p_iface->p_api->enable(p_cli->p_iface, true) == NRF_SUCCESS) + { + p_cli->p_ctx->state = NRF_CLI_STATE_PANIC_MODE_ACTIVE; + } + else + { + p_cli->p_ctx->state = NRF_CLI_STATE_PANIC_MODE_INACTIVE; + } +} + +const nrf_log_backend_api_t nrf_log_backend_cli_api = { + .put = nrf_log_backend_cli_put, + .flush = nrf_log_backend_cli_flush, + .panic_set = nrf_log_backend_cli_panic_set, +}; +#else +static bool cli_log_entry_process(nrf_cli_t const * p_cli, bool skip) +{ + UNUSED_PARAMETER(p_cli); + UNUSED_PARAMETER(skip); + return false; +} +#endif // NRF_CLI_LOG_BACKEND + +/* ============ built-in commands ============ */ +#if NRF_MODULE_ENABLED(NRF_CLI_BUILD_IN_CMDS) + +static bool nrf_cli_build_in_cmd_common_executed(nrf_cli_t const * p_cli, + bool arg_cnt_nok, + nrf_cli_getopt_option_t const * p_opt, + size_t opt_len) +{ + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, p_opt, opt_len); + return true; + } + + if (arg_cnt_nok) + { + nrf_cli_error(p_cli, "%s: wrong parameter count", p_cli->p_ctx->active_cmd.p_syntax); + return true; + } + + return false; +} + +static void nrf_cli_cmd_clear(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + ASSERT(p_cli); + ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name); + UNUSED_PARAMETER(argv); + + if ((argc == 2) && (nrf_cli_help_requested(p_cli))) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CURSORHOME); + NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CLEARSCREEN); +} + +static void nrf_cli_cmd_cli(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + ASSERT(p_cli); + ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name); + UNUSED_PARAMETER(argv); + + if ((argc == 1) || ((argc == 2) && nrf_cli_help_requested(p_cli)) ) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + nrf_cli_error(p_cli, NRF_CLI_MSG_SPECIFY_SUBCOMMAND); +} + +#if NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS) +static void nrf_cli_cmd_colors_off(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0)) + { + return; + } + p_cli->p_ctx->internal.flag.use_colors = 0; +} + +static void nrf_cli_cmd_colors_on(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0)) + { + return; + } + p_cli->p_ctx->internal.flag.use_colors = 1; +} + +static void nrf_cli_cmd_colors(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + ASSERT(p_cli); + ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name); + + if (argc == 1) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + + if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 2), NULL, 0)) + { + return; + } + + nrf_cli_error(p_cli, "%s:%s%s", argv[0], NRF_CLI_MSG_UNKNOWN_PARAMETER, argv[1]); +} +#endif // NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS) + +static void nrf_cli_cmd_echo(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc > 2), NULL, 0)) + { + return; + } + + if (argc == 2) + { + nrf_cli_error(p_cli, "%s:%s%s", argv[0], NRF_CLI_MSG_UNKNOWN_PARAMETER, argv[1]); + return; + } + nrf_cli_print(p_cli, "Echo status: %s", cli_flag_echo_is_set(p_cli) ? "on" : "off"); +} + +static void nrf_cli_cmd_echo_off(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0)) + { + return; + } + + cli_flag_echo_clear(p_cli); +} + +static void nrf_cli_cmd_echo_on(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0)) + { + return; + } + + cli_flag_echo_set(p_cli); +} + +#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) +static void nrf_cli_cmd_history(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + ASSERT(p_cli); + ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name); + + if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0)) + { + return; + } + + size_t i = 0; + nrf_memobj_t const * p_cmd_list = p_cli->p_ctx->p_cmd_list_tail; + nrf_cli_memobj_header_t header; + + while (1) + { + if ((p_cmd_list == NULL) || (i >= NRF_CLI_HISTORY_ELEMENT_COUNT)) + { + break; + } + nrf_memobj_read((nrf_memobj_t * )p_cmd_list, + &header, + NRF_CLI_HISTORY_HEADER_SIZE, + 0); + nrf_memobj_read((nrf_memobj_t * )p_cmd_list, + p_cli->p_ctx->temp_buff, + header.cmd_len + 1, + NRF_CLI_HISTORY_HEADER_SIZE); + p_cmd_list = header.p_next; + nrf_cli_print(p_cli, "[%3d] %s", i++, p_cli->p_ctx->temp_buff); + } + p_cli->p_ctx->temp_buff[0] = '\0'; +} +#endif // NRF_MODULE_ENABLED(NRF_CLI_HISTORY) + +#if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS) +void nrf_cli_cmd_cli_stats(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if (argc == 1) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + + if (argc == 2) + { + nrf_cli_error(p_cli, "%s:%s%s", argv[0], NRF_CLI_MSG_UNKNOWN_PARAMETER, argv[1]); + return; + } + + UNUSED_RETURN_VALUE(nrf_cli_build_in_cmd_common_executed(p_cli, (argc > 2), NULL, 0)); +} + +void nrf_cli_cmd_cli_stats_show(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0)) + { + return; + } + + nrf_queue_t const * p_queue = ((nrf_cli_log_backend_t *)p_cli->p_log_backend->p_ctx)->p_queue; + uint8_t max_util = nrf_queue_max_utilization_get(p_queue); + uint8_t utilization = (uint8_t)(max_util * 100ul / p_queue->size); + + nrf_cli_print(p_cli, + "Lost logs: %u\nMax log queue utilization: %u%% [%u/%u]", + p_cli->p_ctx->statistics.log_lost_cnt, + utilization, + max_util, + p_queue->size); +} + +void nrf_cli_cmd_cli_stats_reset(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0)) + { + return; + } + + p_cli->p_ctx->statistics.log_lost_cnt = 0; + nrf_queue_max_utilization_reset( + ((nrf_cli_log_backend_t *)p_cli->p_log_backend->p_ctx)->p_queue); +} +#endif // NRF_MODULE_ENABLED(NRF_CLI_STATISTICS) + +static void nrf_cli_cmd_resize_default(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0)) + { + return; + } + + NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_SETCOL_80); + p_cli->p_ctx->vt100_ctx.cons.terminal_wid = NRF_CLI_DEFAULT_TERMINAL_WIDTH; + p_cli->p_ctx->vt100_ctx.cons.terminal_hei = NRF_CLI_DEFAULT_TERMINAL_HEIGHT; +} + +static void nrf_cli_cmd_resize(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + ASSERT(p_cli); + ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name); + + if (argc == 1) + { + if (terminal_size_get(p_cli, + &p_cli->p_ctx->vt100_ctx.cons.terminal_wid, + &p_cli->p_ctx->vt100_ctx.cons.terminal_hei) != NRF_SUCCESS) + { + p_cli->p_ctx->vt100_ctx.cons.terminal_wid = NRF_CLI_DEFAULT_TERMINAL_WIDTH; + p_cli->p_ctx->vt100_ctx.cons.terminal_hei = NRF_CLI_DEFAULT_TERMINAL_HEIGHT; + nrf_cli_warn(p_cli, "No response from the terminal, assumed 80x24 screen size"); + } + return; + } + + if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc > 2), NULL, 0)) + { + return; + } + nrf_cli_error(p_cli, "%s:%s%s", argv[0], NRF_CLI_MSG_UNKNOWN_PARAMETER, argv[1]); +} + +#if NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS) +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_colors) +{ + NRF_CLI_CMD(off, NULL, NRF_CLI_HELP_COLORS_OFF, nrf_cli_cmd_colors_off), + NRF_CLI_CMD(on, NULL, NRF_CLI_HELP_COLORS_ON, nrf_cli_cmd_colors_on), + NRF_CLI_SUBCMD_SET_END +}; +#endif + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_echo) +{ + NRF_CLI_CMD(off, NULL, NRF_CLI_HELP_ECHO_OFF, nrf_cli_cmd_echo_off), + NRF_CLI_CMD(on, NULL, NRF_CLI_HELP_ECHO_ON, nrf_cli_cmd_echo_on), + NRF_CLI_SUBCMD_SET_END +}; + +#if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS) +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_cli_stats) +{ + NRF_CLI_CMD(reset, NULL, NRF_CLI_HELP_STATISTICS_RESET, nrf_cli_cmd_cli_stats_reset), + NRF_CLI_CMD(show, NULL, NRF_CLI_HELP_STATISTICS_SHOW, nrf_cli_cmd_cli_stats_show), + NRF_CLI_SUBCMD_SET_END +}; +#endif // NRF_MODULE_ENABLED(NRF_CLI_STATISTICS) + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_cli) +{ +#if NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS) + NRF_CLI_CMD(colors, &m_sub_colors, NRF_CLI_HELP_COLORS, nrf_cli_cmd_colors), +#endif + NRF_CLI_CMD(echo, &m_sub_echo, NRF_CLI_HELP_ECHO, nrf_cli_cmd_echo), +#if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS) + NRF_CLI_CMD(stats, &m_sub_cli_stats, NRF_CLI_HELP_STATISTICS, nrf_cli_cmd_cli_stats), +#endif + NRF_CLI_SUBCMD_SET_END +}; + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_resize) +{ + NRF_CLI_CMD(default, NULL, NRF_CLI_HELP_RESIZE_DEFAULT, nrf_cli_cmd_resize_default), + NRF_CLI_SUBCMD_SET_END +}; + +NRF_CLI_CMD_REGISTER(clear, NULL, NRF_CLI_HELP_CLEAR, nrf_cli_cmd_clear); +NRF_CLI_CMD_REGISTER(cli, &m_sub_cli, NRF_CLI_HELP_CLI, nrf_cli_cmd_cli); +#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) +NRF_CLI_CMD_REGISTER(history, NULL, NRF_CLI_HELP_HISTORY, nrf_cli_cmd_history); +#endif +NRF_CLI_CMD_REGISTER(resize, &m_sub_resize, NRF_CLI_HELP_RESIZE, nrf_cli_cmd_resize); + +#endif // NRF_MODULE_ENABLED(NRF_CLI_BUILD_IN_CMDS) + +#endif // NRF_MODULE_ENABLED(NRF_CLI) + diff --git a/components/libraries/cli/nrf_cli.h b/components/libraries/cli/nrf_cli.h new file mode 100644 index 0000000..d2b1860 --- /dev/null +++ b/components/libraries/cli/nrf_cli.h @@ -0,0 +1,704 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_CLI_H__ +#define NRF_CLI_H__ + +#include "sdk_common.h" +#include "nrf_cli_types.h" +#include "nrf_section.h" +#include "nrf_log_backend_interface.h" +#include "nrf_queue.h" +#include "nrf_log_ctrl.h" +#include "app_util_platform.h" +#include "nrf_memobj.h" + +#if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER) +#include "task_manager.h" +#endif + +#include "nrf_fprintf.h" +#include "nrf_fprintf_format.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_CLI_RX_BUFF_SIZE 16 + +/* CLI reserves top task manager flags, bits 0...18 are available for application. */ +#define NRF_CLI_TRANSPORT_TX_RDY_TASK_EVT (1UL << 19) +#define NRF_CLI_TRANSPORT_RX_RDY_TASK_EVT (1UL << 20) +#define NRF_CLI_LOG_PENDING_TASK_EVT (1UL << 21) +#define NRF_CLI_CMD_EXECUTE_EVT (1UL << 22) +#define NRF_CLI_KILL_TASK_EVT (1UL << 23) + +#define NRF_CLI_TASK_EVTS (NRF_CLI_TRANSPORT_TX_RDY_TASK_EVT | \ + NRF_CLI_TRANSPORT_RX_RDY_TASK_EVT | \ + NRF_CLI_LOG_PENDING_TASK_EVT | \ + NRF_CLI_CMD_EXECUTE_EVT | \ + NRF_CLI_KILL_TASK_EVT) +/** + * @defgroup nrf_cli Command Line Interface + * @ingroup app_common + * + * @brief Module for unified command line handling. + * + * @{ + */ + +/** + * @brief Aliases to: @ref nrf_cli, @ref nrf_cli_cmd_entry, and @ref nrf_cli_static_entry. + * Must be created here to satisfy module declaration order dependencies. + */ +typedef struct nrf_cli nrf_cli_t; +typedef struct nrf_cli_cmd_entry nrf_cli_cmd_entry_t; +typedef struct nrf_cli_static_entry nrf_cli_static_entry_t; + +/** + * @brief CLI dynamic command descriptor. + * + * @details Function shall fill the received @ref nrf_cli_static_entry structure with requested (idx) + * dynamic subcommand data. If there is more than one dynamic subcommand available, + * the function shall ensure that the returned commands: p_static->p_syntax are sorted in + * alphabetical order. If idx exceeds the available dynamic subcommands, the function must write + * to p_static->p_syntax NULL value. This will indicate to the CLI module that + * there are no more dynamic commands to read. + */ +typedef void (*nrf_cli_dynamic_get)(size_t idx, nrf_cli_static_entry_t * p_static); + +/** + * @brief CLI command descriptor. + */ +struct nrf_cli_cmd_entry +{ + bool is_dynamic; + union + { + nrf_cli_dynamic_get p_dynamic_get; //!< Pointer to function returning dynamic commands. + nrf_cli_static_entry_t const * p_static; //!< Pointer to array of static commands. + } u; +}; + +/** + * @brief CLI command handler prototype. + */ +typedef void (*nrf_cli_cmd_handler)(nrf_cli_t const * p_cli, size_t argc, char **argv); + +/** + * @brief CLI static command descriptor. + */ +struct nrf_cli_static_entry +{ + char const * p_syntax; //!< Command syntax strings. + char const * p_help; //!< Command help string. + + nrf_cli_cmd_entry_t const * p_subcmd; //!< Pointer to subcommand. + + nrf_cli_cmd_handler handler; //!< Command handler. +}; + +/** + * @brief Macro for defining and adding a root command (level 0). + * + * @note Each root command shall have unique syntax. + * + * @param[in] p_syntax Command syntax (for example: history). + * @param[in] p_subcmd Pointer to a subcommands array. + * @param[in] p_help Pointer to a command help string. + * @param[in] p_handler Pointer to a function handler. + */ +#define NRF_CLI_CMD_REGISTER(p_syntax, p_subcmd, p_help, p_handler) \ + nrf_cli_static_entry_t const CONCAT_3(nrf_cli_, p_syntax, _raw) = \ + NRF_CLI_CMD(p_syntax, p_subcmd, p_help, p_handler); \ + NRF_SECTION_ITEM_REGISTER(cli_command, \ + nrf_cli_cmd_entry_t const CONCAT_3(nrf_cli_, p_syntax, _const)) = { \ + .is_dynamic = false, \ + .u = {.p_static = &CONCAT_3(nrf_cli_, p_syntax, _raw)} \ + }; \ + NRF_SECTION_ITEM_REGISTER(cli_sorted_cmd_ptrs, char const * CONCAT_2(p_syntax, _str_ptr)) + +/** + * @brief Macro for creating a subcommand set. It must be used outside of any function body. + * + * @param[in] name Name of the subcommand set. + */ +#define NRF_CLI_CREATE_STATIC_SUBCMD_SET(name) \ + /*lint -save -e85 -e31*/ \ + static nrf_cli_static_entry_t const CONCAT_2(name, _raw)[]; \ + static nrf_cli_cmd_entry_t const name = { \ + .is_dynamic = false, \ + .u = {.p_static = CONCAT_2(name, _raw) } \ + }; \ + static nrf_cli_static_entry_t const CONCAT_2(name, _raw)[] = /*lint -restore*/ + +/** + * @brief Define ending subcommands set. + * + */ +#define NRF_CLI_SUBCMD_SET_END {NULL} + +/** + * @brief Macro for creating a dynamic entry. + * + * @param[in] name Name of the dynamic entry. + * @param[in] p_get Pointer to the function returning dynamic commands array @ref nrf_cli_dynamic_get. + */ +#define NRF_CLI_CREATE_DYNAMIC_CMD(name, p_get) \ + /*lint -save -e19*/ \ + static nrf_cli_cmd_entry_t const name = { \ + .is_dynamic = true, \ + .u = { .p_dynamic_get = p_get } \ +}; /*lint -restore*/ + +/** @brief Macro for creating subcommands when C++ compiler is used. + * + * Example usage: + * @code + * NRF_CLI_CPP_CREATE_STATIC_SUBCMD_SET(cmd_syntax, + * NRF_CLI_CMD(abc, ...), + * NRF_CLI_CMD(def, ...), + * NRF_CLI_SUBCMD_SET_END + * ); + * @endcode + */ +#define NRF_CLI_CPP_CREATE_STATIC_SUBCMD_SET(name, ...) \ + static nrf_cli_static_entry_t const CONCAT_2(name, _raw)[] = { \ + __VA_ARGS__ \ + }; \ + static nrf_cli_cmd_entry_t const name = { \ + .is_dynamic = false, \ + .u = { .p_static = CONCAT_2(name, _raw) } \ + } + +/** + * @brief Initializes a CLI command (@ref nrf_cli_static_entry). + * + * @param[in] _p_syntax Command syntax (for example: history). + * @param[in] _p_subcmd Pointer to a subcommands array. + * @param[in] _p_help Pointer to a command help string. + * @param[in] _p_handler Pointer to a function handler. + */ +#define NRF_CLI_CMD(_p_syntax, _p_subcmd, _p_help, _p_handler) { \ + .p_syntax = (const char *) STRINGIFY(_p_syntax), \ + .p_help = (const char *) _p_help, \ + .p_subcmd = _p_subcmd, \ + .handler = _p_handler \ +} + +/** + * @internal @brief Internal CLI state in response to data received from the terminal. + */ +typedef enum +{ + NRF_CLI_RECEIVE_DEFAULT, + NRF_CLI_RECEIVE_ESC, + NRF_CLI_RECEIVE_ESC_SEQ, + NRF_CLI_RECEIVE_TILDE_EXP +} nrf_cli_receive_t; + + +/** + * @internal @brief Internal CLI state. + */ +typedef enum +{ + NRF_CLI_STATE_UNINITIALIZED, //!< State uninitialized. + NRF_CLI_STATE_INITIALIZED, //!< State initialized but not active. + NRF_CLI_STATE_ACTIVE, //!< State active. + NRF_CLI_STATE_PANIC_MODE_ACTIVE, //!< State panic mode activated. + NRF_CLI_STATE_PANIC_MODE_INACTIVE //!< State panic mode requested but not supported. +} nrf_cli_state_t; + +/** + * @brief Event type from CLI transport. + */ +typedef enum +{ + NRF_CLI_TRANSPORT_EVT_RX_RDY, + NRF_CLI_TRANSPORT_EVT_TX_RDY +} nrf_cli_transport_evt_t; + +typedef void (*nrf_cli_transport_handler_t)(nrf_cli_transport_evt_t evt_type, void * p_context); + +typedef struct nrf_cli_transport_s nrf_cli_transport_t; + +/** + * @brief Unified CLI transport interface. + */ +typedef struct +{ + /** + * @brief Function for initializing the CLI transport interface. + * + * @param[in] p_transport Pointer to the transfer instance. + * @param[in] p_config Pointer to instance configuration. + * @param[in] evt_handler Event handler. + * @param[in] p_context Pointer to the context passed to event handler. + * + * @return Standard error code. + */ + ret_code_t (*init)(nrf_cli_transport_t const * p_transport, + void const * p_config, + nrf_cli_transport_handler_t evt_handler, + void * p_context); + + /** + * @brief Function for uninitializing the CLI transport interface. + * + * @param[in] p_transport Pointer to the transfer instance. + * + * @return Standard error code. + */ + ret_code_t (*uninit)(nrf_cli_transport_t const * p_transport); + + /** + * @brief Function for reconfiguring the transport to work in blocking mode. + * + * @param p_transport Pointer to the transfer instance. + * @param blocking If true, the transport is enabled in blocking mode. + * + * @return NRF_SUCCESS on successful enabling, error otherwise (also if not supported). + */ + ret_code_t (*enable)(nrf_cli_transport_t const * p_transport, + bool blocking); + + /** + * @brief Function for writing data to the transport interface. + * + * @param[in] p_transport Pointer to the transfer instance. + * @param[in] p_data Pointer to the source buffer. + * @param[in] length Source buffer length. + * @param[in] p_cnt Pointer to the sent bytes counter. + * + * @return Standard error code. + */ + ret_code_t (*write)(nrf_cli_transport_t const * p_transport, + const void * p_data, + size_t length, + size_t * p_cnt); + + /** + * @brief Function for reading data from the transport interface. + * + * @param[in] p_transport Pointer to the transfer instance. + * @param[in] p_data Pointer to the destination buffer. + * @param[in] length Destination buffer length. + * @param[in] p_cnt Pointer to the received bytes counter. + * + * @return Standard error code. + */ + ret_code_t (*read)(nrf_cli_transport_t const * p_transport, + void * p_data, + size_t length, + size_t * p_cnt); + +} nrf_cli_transport_api_t; + +struct nrf_cli_transport_s +{ + nrf_cli_transport_api_t const * p_api; +}; + +#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) +/** + * @brief CLI history object header. + */ +typedef PACKED_STRUCT +{ + nrf_memobj_t * p_prev; //!< Pointer to the next object. + nrf_memobj_t * p_next; //!< Pointer to the previous object. + nrf_cli_cmd_len_t cmd_len; //!< Command length. +} nrf_cli_memobj_header_t; +#endif + +#if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS) +typedef struct +{ + uint32_t log_lost_cnt; //!< Lost log counter. +} nrf_cli_statistics_t; +#endif + +/** + * @internal @brief Flags for internal CLI usage. + */ +typedef struct +{ + uint32_t insert_mode : 1; //!< Enables or disables console insert mode for text introduction. + uint32_t show_help : 1; //!< Shows help if the command was called with -h or --help parameter. + uint32_t use_colors : 1; //!< Enables or disables colored syntax. + uint32_t echo : 1; //!< Enables or disables CLI echo. + uint32_t processing : 1; //!< CLI is executing process function. + uint32_t tx_rdy : 1; + uint32_t last_nl : 8; //!< The last received newline character. +} nrf_cli_flag_t; +STATIC_ASSERT(sizeof(nrf_cli_flag_t) == sizeof(uint32_t)); + +/** + * @internal @brief Union for internal CLI usage. + */ +typedef union +{ + uint32_t value; + nrf_cli_flag_t flag; +} nrf_cli_internal_t; + +/** + * @brief CLI instance context. + */ +typedef struct +{ + nrf_cli_state_t state; //!< Internal module state. + nrf_cli_receive_t receive_state; //!< Escape sequence indicator. + + nrf_cli_static_entry_t active_cmd; //!< Currently executed command + + nrf_cli_vt100_ctx_t vt100_ctx; //!< VT100 color and cursor position, terminal width. + + nrf_cli_cmd_len_t cmd_buff_len; //!< Command length. + nrf_cli_cmd_len_t cmd_buff_pos; //!< Command buffer cursor position. + +#if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD) + nrf_cli_cmd_len_t cmd_tmp_buff_len; //!< Command length in tmp buffer +#endif + + char cmd_buff[NRF_CLI_CMD_BUFF_SIZE]; //!< Command input buffer. + char temp_buff[NRF_CLI_CMD_BUFF_SIZE]; //!< Temporary buffer used by various functions. + char printf_buff[NRF_CLI_PRINTF_BUFF_SIZE]; //!< Printf buffer size. + +#if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS) + nrf_cli_statistics_t statistics; //!< CLI statistics. +#endif + +#if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER) + task_id_t task_id; +#endif + +#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) + nrf_memobj_t * p_cmd_list_head; //!< Pointer to the head of history list. + nrf_memobj_t * p_cmd_list_tail; //!< Pointer to the tail of history list. + nrf_memobj_t * p_cmd_list_element; //!< Pointer to an element of history list. +#endif + volatile nrf_cli_internal_t internal; //!< Internal CLI data +} nrf_cli_ctx_t; + +extern const nrf_log_backend_api_t nrf_log_backend_cli_api; + +typedef struct +{ + nrf_queue_t const * p_queue; + void * p_context; + nrf_cli_t const * p_cli; +} nrf_cli_log_backend_t; + +#if NRF_CLI_LOG_BACKEND && NRF_MODULE_ENABLED(NRF_LOG) +#define NRF_LOG_BACKEND_CLI_DEF(_name_, _queue_size_) \ + NRF_QUEUE_DEF(nrf_log_entry_t, \ + CONCAT_2(_name_, _queue),_queue_size_, NRF_QUEUE_MODE_NO_OVERFLOW); \ + static nrf_cli_log_backend_t CONCAT_2(cli_log_backend,_name_) = { \ + .p_queue = &CONCAT_2(_name_, _queue), \ + }; \ + NRF_LOG_BACKEND_DEF(_name_, nrf_log_backend_cli_api, &CONCAT_2(cli_log_backend,_name_)) + +#define NRF_CLI_BACKEND_PTR(_name_) &CONCAT_2(_name_, _log_backend) +#else +#define NRF_LOG_BACKEND_CLI_DEF(_name_, _queue_sz_) +#define NRF_CLI_BACKEND_PTR(_name_) NULL +#endif + +#if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) +/* Header consists memory for cmd length and pointer to: prev and next element. */ +#define NRF_CLI_HISTORY_HEADER_SIZE (sizeof(nrf_cli_memobj_header_t)) + +#define NRF_CLI_HISTORY_MEM_OBJ(name) \ + NRF_MEMOBJ_POOL_DEF(CONCAT_2(name, _cmd_hist_memobj), \ + NRF_CLI_HISTORY_HEADER_SIZE + \ + NRF_CLI_HISTORY_ELEMENT_SIZE, \ + NRF_CLI_HISTORY_ELEMENT_COUNT) + +#define NRF_CLI_MEMOBJ_PTR(_name_) &CONCAT_2(_name_, _cmd_hist_memobj) +#else +#define NRF_CLI_MEMOBJ_PTR(_name_) NULL +#define NRF_CLI_HISTORY_MEM_OBJ(name) +#endif + +/** + * @brief CLI instance internals. + * + * @ref nrf_cli_t + */ +struct nrf_cli +{ + char const * const p_name; //!< Terminal name. + + nrf_cli_transport_t const * p_iface; //!< Transport interface. + nrf_cli_ctx_t * p_ctx; //!< Internal context. + nrf_log_backend_t const * p_log_backend; //!< Logger backend. + nrf_fprintf_ctx_t * p_fprintf_ctx; //!< fprintf context. + nrf_memobj_pool_t const * p_cmd_hist_mempool; //!< Memory reserved for commands history. +}; + +/** + * @brief Macro for defining a command line interface instance. + * + * @param[in] name Instance name. + * @param[in] cli_prefix CLI prefix string. + * @param[in] p_transport_iface Pointer to the transport interface. + * @param[in] newline_ch Deprecated parameter, not used any more. Any uint8_t value can be used. + * @param[in] log_queue_size Logger processing queue size. + */ +#define NRF_CLI_DEF(name, cli_prefix, p_transport_iface, newline_ch, log_queue_size) \ + static nrf_cli_t const name; \ + static nrf_cli_ctx_t CONCAT_2(name, _ctx); \ + NRF_FPRINTF_DEF(CONCAT_2(name, _fprintf_ctx), \ + &name, \ + CONCAT_2(name, _ctx).printf_buff, \ + NRF_CLI_PRINTF_BUFF_SIZE, \ + false, \ + nrf_cli_print_stream); \ + NRF_LOG_BACKEND_CLI_DEF(CONCAT_2(name, _log_backend), log_queue_size); \ + NRF_CLI_HISTORY_MEM_OBJ(name); \ + /*lint -save -e31*/ \ + static nrf_cli_t const name = { \ + .p_name = cli_prefix, \ + .p_iface = p_transport_iface, \ + .p_ctx = &CONCAT_2(name, _ctx), \ + .p_log_backend = NRF_CLI_BACKEND_PTR(name), \ + .p_fprintf_ctx = &CONCAT_2(name, _fprintf_ctx), \ + .p_cmd_hist_mempool = NRF_CLI_MEMOBJ_PTR(name), \ + } /*lint -restore*/ + +/** + * @brief Function for initializing a transport layer and internal CLI state. + * + * @param[in] p_cli Pointer to CLI instance. + * @param[in] p_transport_config Configuration forwarded to the transport during initialization. + * @param[in] use_colors Enables colored prints. + * @param[in] log_backend If true, the console will be used as logger backend. + * @param[in] init_lvl Default severity level for the logger. + * + * @return Standard error code. + */ +ret_code_t nrf_cli_init(nrf_cli_t const * p_cli, + void const * p_transport_config, + bool use_colors, + bool log_backend, + nrf_log_severity_t init_lvl); + +ret_code_t nrf_cli_task_create(nrf_cli_t const * p_cli); + +/** + * @brief Function for uninitializing a transport layer and internal CLI state. + * If function returns NRF_ERROR_BUSY, you must call @ref nrf_cli_process before calling + * nrf_cli_uninit again. + * + * @param p_cli Pointer to CLI instance. + * + * @return Standard error code. + */ +ret_code_t nrf_cli_uninit(nrf_cli_t const * p_cli); + +/** + * @brief Function for starting CLI processing. + * + * @param p_cli Pointer to the CLI instance. + * + * @return Standard error code. + */ +ret_code_t nrf_cli_start(nrf_cli_t const * p_cli); + +/** + * @brief Function for stopping CLI processing. + * + * @param p_cli Pointer to CLI instance. + * + * @return Standard error code. + */ +ret_code_t nrf_cli_stop(nrf_cli_t const * p_cli); + +/** + * @brief CLI colors for @ref nrf_cli_fprintf function. + */ +#define NRF_CLI_DEFAULT NRF_CLI_VT100_COLOR_DEFAULT /**< Turn off character attributes. */ +#define NRF_CLI_NORMAL NRF_CLI_VT100_COLOR_WHITE /**< Normal color printf. */ +#define NRF_CLI_INFO NRF_CLI_VT100_COLOR_GREEN /**< Info color printf. */ +#define NRF_CLI_OPTION NRF_CLI_VT100_COLOR_CYAN /**< Option color printf. */ +#define NRF_CLI_WARNING NRF_CLI_VT100_COLOR_YELLOW /**< Warning color printf. */ +#define NRF_CLI_ERROR NRF_CLI_VT100_COLOR_RED /**< Error color printf. */ + +/** + * @brief Printf-like function which sends formatted data stream to the CLI. + * This function shall not be used outside of the CLI module or CLI command context. + * + * @param[in] p_cli Pointer to the CLI instance. + * @param[in] color Printf color. + * @param[in] p_fmt Format string. + * @param[in] ... List of parameters to print. + */ +void nrf_cli_fprintf(nrf_cli_t const * p_cli, + nrf_cli_vt100_color_t color, + char const * p_fmt, + ...); + +/** + * @brief Print an info message to the CLI. + * + * See @ref nrf_cli_fprintf. + * + * @param[in] _p_cli Pointer to the CLI instance. + * @param[in] _ft Format string. + * @param[in] ... List of parameters to print. + */ +#define nrf_cli_info(_p_cli, _ft, ...) \ + nrf_cli_fprintf(_p_cli, NRF_CLI_INFO, _ft "\n", ##__VA_ARGS__) + +/** + * @brief Print a normal message to the CLI. + * + * See @ref nrf_cli_fprintf. + * + * @param[in] _p_cli Pointer to the CLI instance. + * @param[in] _ft Format string. + * @param[in] ... List of parameters to print. + */ +#define nrf_cli_print(_p_cli, _ft, ...) \ + nrf_cli_fprintf(_p_cli, NRF_CLI_DEFAULT, _ft "\n", ##__VA_ARGS__) + +/** + * @brief Print a warning message to the CLI. + * + * See @ref nrf_cli_fprintf. + * + * @param[in] _p_cli Pointer to the CLI instance. + * @param[in] _ft Format string. + * @param[in] ... List of parameters to print. + */ +#define nrf_cli_warn(_p_cli, _ft, ...) \ + nrf_cli_fprintf(_p_cli, NRF_CLI_WARNING, _ft "\n", ##__VA_ARGS__) + +/** + * @brief Print an error message to the CLI. + * + * See @ref nrf_cli_fprintf. + * + * @param[in] _p_cli Pointer to the CLI instance. + * @param[in] _ft Format string. + * @param[in] ... List of parameters to print. + */ +#define nrf_cli_error(_p_cli, _ft, ...) \ + nrf_cli_fprintf(_p_cli, NRF_CLI_ERROR, _ft "\n", ##__VA_ARGS__) + +/** + * @brief Process function, which should be executed when data is ready in the transport interface. + * + * @param[in] p_cli Pointer to the CLI instance. + */ +void nrf_cli_process(nrf_cli_t const * p_cli); + + +/** + * @brief Option descriptor. + */ +typedef struct nrf_cli_getopt_option +{ + char const * p_optname; //!< Option long name. + char const * p_optname_short; //!< Option short name. + char const * p_optname_help; //!< Option help string. +} nrf_cli_getopt_option_t; + + +/** + * @brief Option structure initializer @ref nrf_cli_getopt_option. + * + * @param[in] _p_optname Option name long. + * @param[in] _p_shortname Option name short. + * @param[in] _p_help Option help string. + */ +#define NRF_CLI_OPT(_p_optname, _p_shortname, _p_help) { \ + .p_optname = _p_optname, \ + .p_optname_short = _p_shortname, \ + .p_optname_help = _p_help, \ +} + +/** + * @brief Informs that a command has been called with -h or --help option. + * + * @param[in] p_cli Pointer to the CLI instance. + * + * @return True if help has been requested. + */ +__STATIC_INLINE bool nrf_cli_help_requested(nrf_cli_t const * p_cli); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE bool nrf_cli_help_requested(nrf_cli_t const * p_cli) +{ + return p_cli->p_ctx->internal.flag.show_help; +} +#endif + +/** + * @brief Prints the current command help. + * @details Function will print a help string with: the currently entered command, its options, + * and subcommands (if they exist). + * + * @param[in] p_cli Pointer to the CLI instance. + * @param[in] p_opt Pointer to the optional option array. + * @param[in] opt_len Option array size. + */ +void nrf_cli_help_print(nrf_cli_t const * p_cli, + nrf_cli_getopt_option_t const * p_opt, + size_t opt_len); + +/** + * @internal @brief This function shall not be used directly, it is required by the + * nrf_fprintf module. + * + * @param[in] p_user_ctx Pointer to the context for the CLI instance. + * @param[in] p_data Pointer to the data buffer. + * @param[in] data_len Data buffer size. + */ +void nrf_cli_print_stream(void const * p_user_ctx, char const * p_data, size_t data_len); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_CLI_H__ */ diff --git a/components/libraries/cli/nrf_cli_types.h b/components/libraries/cli/nrf_cli_types.h new file mode 100644 index 0000000..8936582 --- /dev/null +++ b/components/libraries/cli/nrf_cli_types.h @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_CLI_TYPES_H__ +#define NRF_CLI_TYPES_H__ + +#include +#include "sdk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if (NRF_CLI_CMD_BUFF_SIZE > 65535) + typedef uint32_t nrf_cli_cmd_len_t; +#elif (NRF_CLI_CMD_BUFF_SIZE > 255) + typedef uint16_t nrf_cli_cmd_len_t; +#else + typedef uint8_t nrf_cli_cmd_len_t; +#endif + +typedef enum +{ + NRF_CLI_VT100_COLOR_DEFAULT, + NRF_CLI_VT100_COLOR_BLACK, + NRF_CLI_VT100_COLOR_RED, + NRF_CLI_VT100_COLOR_GREEN, + NRF_CLI_VT100_COLOR_YELLOW, + NRF_CLI_VT100_COLOR_BLUE, + NRF_CLI_VT100_COLOR_MAGENTA, + NRF_CLI_VT100_COLOR_CYAN, + NRF_CLI_VT100_COLOR_WHITE, + + VT100_COLOR_END +} nrf_cli_vt100_color_t; + +typedef struct +{ + nrf_cli_vt100_color_t col; // text color + nrf_cli_vt100_color_t bgcol; // background color +} nrf_cli_vt100_colors_t; + +typedef struct +{ + nrf_cli_cmd_len_t cur_x; // horizontal cursor position in edited command line + nrf_cli_cmd_len_t cur_x_end; // horizontal cursor position at the end of command + nrf_cli_cmd_len_t cur_y; // vertical cursor position in edited command + nrf_cli_cmd_len_t cur_y_end; // vertical cursor position at the end of command + nrf_cli_cmd_len_t terminal_hei; // terminal screen height + nrf_cli_cmd_len_t terminal_wid; // terminal screen width + uint8_t name_len; // console name length +} nrf_cli_multiline_cons_t; + +typedef struct +{ + nrf_cli_multiline_cons_t cons; + nrf_cli_vt100_colors_t col; + nrf_cli_cmd_len_t printed_cmd; // printed commands counter +} nrf_cli_vt100_ctx_t; + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_CLI_TYPES_H__ */ + diff --git a/components/libraries/cli/nrf_cli_vt100.h b/components/libraries/cli/nrf_cli_vt100.h new file mode 100644 index 0000000..4362244 --- /dev/null +++ b/components/libraries/cli/nrf_cli_vt100.h @@ -0,0 +1,632 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_CLI_VT100_H__ +#define NRF_CLI_VT100_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_CLI_VT100_ASCII_ESC (0x1b) +#define NRF_CLI_VT100_ASCII_DEL (0x7F) +#define NRF_CLI_VT100_ASCII_BSPACE (0x08) +#define NRF_CLI_VT100_ASCII_CTRL_A (0x1) +#define NRF_CLI_VT100_ASCII_CTRL_C (0x03) +#define NRF_CLI_VT100_ASCII_CTRL_E (0x5) +#define NRF_CLI_VT100_ASCII_CTRL_L (0x0C) +#define NRF_CLI_VT100_ASCII_CTRL_U (0x15) +#define NRF_CLI_VT100_ASCII_CTRL_W (0x17) + + +#define NRF_CLI_VT100_SETNL \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '2', '0', 'h', '\0' \ + } /* Set new line mode */ +#define NRF_CLI_VT100_SETAPPL \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '1', 'h', '\0' \ + } /* Set cursor key to application */ +#define NRF_CLI_VT100_SETCOL_132 \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '3', 'h', '\0' \ + } /* Set number of columns to 132 */ +#define NRF_CLI_VT100_SETSMOOTH \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '4', 'h', '\0' \ + } /* Set smooth scrolling */ +#define NRF_CLI_VT100_SETREVSCRN \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '5', 'h', '\0' \ + } /* Set reverse video on screen */ +#define NRF_CLI_VT100_SETORGREL \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '6', 'h', '\0' \ + } /* Set origin to relative */ +#define NRF_CLI_VT100_SETWRAP_ON \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '7', 'h', '\0' \ + } /* Set auto-wrap mode */ +#define NRF_CLI_VT100_SETWRAP_OFF \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '7', 'l', '\0' \ + } /* Set auto-wrap mode */ + +#define NRF_CLI_VT100_SETREP \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '8', 'h', '\0' \ + } /* Set auto-repeat mode */ +#define NRF_CLI_VT100_SETINTER \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '9', 'h', '\0' \ + } /* Set interlacing mode */ + +#define NRF_CLI_VT100_SETLF \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '2', '0', 'l', '\0' \ + } /* Set line feed mode */ +#define NRF_CLI_VT100_SETCURSOR \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '1', 'l', '\0' \ + } /* Set cursor key to cursor */ +#define NRF_CLI_VT100_SETVT52 \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '2', 'l', '\0' \ + } /* Set VT52 (versus ANSI) */ +#define NRF_CLI_VT100_SETCOL_80 \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '3', 'l', '\0' \ + } /* Set number of columns to 80 */ +#define NRF_CLI_VT100_SETJUMP \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '4', 'l', '\0' \ + } /* Set jump scrolling */ +#define NRF_CLI_VT100_SETNORMSCRN \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '5', 'l', '\0' \ + } /* Set normal video on screen */ +#define NRF_CLI_VT100_SETORGABS \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '6', 'l', '\0' \ + } /* Set origin to absolute */ +#define NRF_CLI_VT100_RESETWRAP \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '7', 'l', '\0' \ + } /* Reset auto-wrap mode */ +#define NRF_CLI_VT100_RESETREP \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '8', 'l', '\0' \ + } /* Reset auto-repeat mode */ +#define NRF_CLI_VT100_RESETINTER \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '9', 'l', '\0' \ + } /* Reset interlacing mode */ + +#define NRF_CLI_VT100_ALTKEYPAD \ + { \ + NRF_CLI_VT100_ASCII_ESC, '=', '\0' \ + } /* Set alternate keypad mode */ +#define NRF_CLI_VT100_NUMKEYPAD \ + { \ + NRF_CLI_VT100_ASCII_ESC, '>', '\0' \ + } /* Set numeric keypad mode */ + +#define NRF_CLI_VT100_SETUKG0 \ + { \ + NRF_CLI_VT100_ASCII_ESC, '(', 'A', '\0' \ + } /* Set United Kingdom G0 character set */ +#define NRF_CLI_VT100_SETUKG1 \ + { \ + NRF_CLI_VT100_ASCII_ESC, ')', 'A', '\0' \ + } /* Set United Kingdom G1 character set */ +#define NRF_CLI_VT100_SETUSG0 \ + { \ + NRF_CLI_VT100_ASCII_ESC, '(', 'B', '\0' \ + } /* Set United States G0 character set */ +#define NRF_CLI_VT100_SETUSG1 \ + { \ + NRF_CLI_VT100_ASCII_ESC, ')', 'B', '\0' \ + } /* Set United States G1 character set */ +#define NRF_CLI_VT100_SETSPECG0 \ + { \ + NRF_CLI_VT100_ASCII_ESC, '(', '0', '\0' \ + } /* Set G0 special chars. & line set */ +#define NRF_CLI_VT100_SETSPECG1 \ + { \ + NRF_CLI_VT100_ASCII_ESC, ')', '0', '\0' \ + } /* Set G1 special chars. & line set */ +#define NRF_CLI_VT100_SETALTG0 \ + { \ + NRF_CLI_VT100_ASCII_ESC, '(', '1', '\0' \ + } /* Set G0 alternate character ROM */ +#define NRF_CLI_VT100_SETALTG1 \ + { \ + NRF_CLI_VT100_ASCII_ESC, ')', '1', '\0' \ + } /* Set G1 alternate character ROM */ +#define NRF_CLI_VT100_SETALTSPECG0 \ + { \ + NRF_CLI_VT100_ASCII_ESC, '(', '2', '\0' \ + } /* Set G0 alt char ROM and spec. graphics */ +#define NRF_CLI_VT100_SETALTSPECG1 \ + { \ + NRF_CLI_VT100_ASCII_ESC, ')', '2', '\0' \ + } /* Set G1 alt char ROM and spec. graphics */ + +#define NRF_CLI_VT100_SETSS2 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'N', '\0' \ + } /* Set single shift 2 */ +#define NRF_CLI_VT100_SETSS3 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', '\0' \ + } /* Set single shift 3 */ + +#define NRF_CLI_VT100_MODESOFF \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', 'm', '\0' \ + } /* Turn off character attributes */ +#define NRF_CLI_VT100_MODESOFF_ \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '0', 'm', '\0' \ + } /* Turn off character attributes */ +#define NRF_CLI_VT100_BOLD \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '1', 'm', '\0' \ + } /* Turn bold mode on */ +#define NRF_CLI_VT100_LOWINT \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '2', 'm', '\0' \ + } /* Turn low intensity mode on */ +#define NRF_CLI_VT100_UNDERLINE \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '4', 'm', '\0' \ + } /* Turn underline mode on */ +#define NRF_CLI_VT100_BLINK \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '5', 'm', '\0' \ + } /* Turn blinking mode on */ +#define NRF_CLI_VT100_REVERSE \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '7', 'm', '\0' \ + } /* Turn reverse video on */ +#define NRF_CLI_VT100_INVISIBLE \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '8', 'm', '\0' \ + } /* Turn invisible text mode on */ + +#define NRF_CLI_VT100_SETWIN(t, b) \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', (t), ';', (b), 'r', '\0' \ + } /* Set top and bottom line#s of a window */ + +#define NRF_CLI_VT100_CURSORUP(n) \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', (n), 'A', '\0' \ + } /* Move cursor up n lines */ +#define NRF_CLI_VT100_CURSORDN(n) \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', (n), 'B', '\0' \ + } /* Move cursor down n lines */ +#define NRF_CLI_VT100_CURSORRT(n) \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', (n), 'C', '\0' \ + } /* Move cursor right n lines */ +#define NRF_CLI_VT100_CURSORLF(n) \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', (n), 'D', '\0' \ + } /* Move cursor left n lines */ +#define NRF_CLI_VT100_CURSORHOME \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', 'H', '\0' \ + } /* Move cursor to upper left corner */ +#define NRF_CLI_VT100_CURSORHOME_ \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', ';', 'H', '\0' \ + } /* Move cursor to upper left corner */ +#define NRF_CLI_VT100_CURSORPOS(v, h) \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', (v), ';', (h), 'H', '\0' \ + } /* Move cursor to screen location v,h */ + +#define NRF_CLI_VT100_HVHOME \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', 'f', '\0' \ + } /* Move cursor to upper left corner */ +#define NRF_CLI_VT100_HVHOME_ \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', ';', 'f', '\0' \ + } /* Move cursor to upper left corner */ +#define NRF_CLI_VT100_HVPOS(v, h) \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', (v), ';', (h), 'f', '\0' \ + } /* Move cursor to screen location v,h */ +#define NRF_CLI_VT100_INDEX \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'D', '\0' \ + } /* Move/scroll window up one line */ +#define NRF_CLI_VT100_REVINDEX \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'M', '\0' \ + } /* Move/scroll window down one line */ +#define NRF_CLI_VT100_NEXTLINE \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'E', '\0' \ + } /* Move to next line */ +#define NRF_CLI_VT100_SAVECURSOR \ + { \ + NRF_CLI_VT100_ASCII_ESC, '7', '\0' \ + } /* Save cursor position and attributes */ +#define NRF_CLI_VT100_RESTORECURSOR \ + { \ + NRF_CLI_VT100_ASCII_ESC, '8', '\0' \ + } /* Restore cursor position and attribute */ + +#define NRF_CLI_VT100_TABSET \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'H', '\0' \ + } /* Set a tab at the current column */ +#define NRF_CLI_VT100_TABCLR \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', 'g', '\0' \ + } /* Clear a tab at the current column */ +#define NRF_CLI_VT100_TABCLR_ \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '0', 'g', '\0' \ + } /* Clear a tab at the current column */ +#define NRF_CLI_VT100_TABCLRALL \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '3', 'g', '\0' \ + } /* Clear all tabs */ + +#define NRF_CLI_VT100_DHTOP \ + { \ + NRF_CLI_VT100_ASCII_ESC, '#', '3', '\0' \ + } /* Double-height letters, top half */ +#define NRF_CLI_VT100_DHBOT \ + { \ + NRF_CLI_VT100_ASCII_ESC, '#', '4', '\0' \ + } /* Double-height letters, bottom hal */ +#define NRF_CLI_VT100_SWSH \ + { \ + NRF_CLI_VT100_ASCII_ESC, '#', '5', '\0' \ + } /* Single width, single height letters */ +#define NRF_CLI_VT100_DWSH \ + { \ + NRF_CLI_VT100_ASCII_ESC, '#', '6', '\0' \ + } /* Double width, single height letters */ + +#define NRF_CLI_VT100_CLEAREOL \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', 'K', '\0' \ + } /* Clear line from cursor right */ +#define NRF_CLI_VT100_CLEAREOL_ \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '0', 'K', '\0' \ + } /* Clear line from cursor right */ +#define NRF_CLI_VT100_CLEARBOL \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '1', 'K', '\0' \ + } /* Clear line from cursor left */ +#define NRF_CLI_VT100_CLEARLINE \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '2', 'K', '\0' \ + } /* Clear entire line */ + +#define NRF_CLI_VT100_CLEAREOS \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', 'J', '\0' \ + } /* Clear screen from cursor down */ +#define NRF_CLI_VT100_CLEAREOS_ \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '0', 'J', '\0' \ + } /* Clear screen from cursor down */ +#define NRF_CLI_VT100_CLEARBOS \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '1', 'J', '\0' \ + } /* Clear screen from cursor up */ +#define NRF_CLI_VT100_CLEARSCREEN \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '2', 'J', '\0' \ + } /* Clear entire screen */ + +#define NRF_CLI_VT100_DEVSTAT \ + { \ + NRF_CLI_VT100_ASCII_ESC, '5', 'n', '\0' \ + } /* Device status report */ +#define NRF_CLI_VT100_TERMOK \ + { \ + NRF_CLI_VT100_ASCII_ESC, '0', 'n', '\0' \ + } /* Response: terminal is OK */ +#define NRF_CLI_VT100_TERMNOK \ + { \ + NRF_CLI_VT100_ASCII_ESC, '3', 'n', '\0' \ + } /* Response: terminal is not OK */ + +#define NRF_CLI_VT100_GETCURSOR \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '6', 'n', '\0' \ + } /* Get cursor position */ +#define NRF_CLI_VT100_CURSORPOSAT \ + { \ + NRF_CLI_VT100_ASCII_ESC, (v), ';', (h), 'R', '\0' \ + } /* Response: cursor is at v,h */ + +#define NRF_CLI_VT100_IDENT \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', 'c', '\0' \ + } /* Identify what terminal type */ +#define NRF_CLI_VT100_IDENT_ \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '0', 'c', '\0' \ + } /* Identify what terminal type */ +#define NRF_CLI_VT100_GETTYPE \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '?', '1', ';', (n), '0', 'c', '\0'\ + } /* Response: terminal type code n */ + +#define NRF_CLI_VT100_RESET \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'c', '\0' \ + } /* Reset terminal to initial state */ + +#define NRF_CLI_VT100_ALIGN \ + { \ + NRF_CLI_VT100_ASCII_ESC, '#', '8', '\0' \ + } /* Screen alignment display */ +#define NRF_CLI_VT100_TESTPU \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '2', ';', '1', 'y', '\0' \ + } /* Confidence power up test */ +#define NRF_CLI_VT100_TESTLB \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '2', ';', '2', 'y', '\0' \ + } /* Confidence loopback test */ +#define NRF_CLI_VT100_TESTPUREP \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '2', ';', '9', 'y', '\0' \ + } /* Repeat power up test */ +#define NRF_CLI_VT100_TESTLBREP \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '2', ';', '1', '0', 'y', '\0' \ + } /* Repeat loopback test */ + +#define NRF_CLI_VT100_LEDSOFF \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '0', 'q', '\0' \ + } /* Turn off all four leds */ +#define NRF_CLI_VT100_LED1 \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '1', 'q', '\0' \ + } /* Turn on LED #1 */ +#define NRF_CLI_VT100_LED2 \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '2', 'q', '\0' \ + } /* Turn on LED #2 */ +#define NRF_CLI_VT100_LED3 \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '3', 'q', '\0' \ + } /* Turn on LED #3 */ +#define NRF_CLI_VT100_LED4 \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '4', 'q', '\0' \ + } /* Turn on LED #4 */ + +/* Function Keys */ + +#define NRF_CLI_VT100_PF1 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'P', '\0' \ + } +#define NRF_CLI_VT100_PF2 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'Q', '\0' \ + } +#define NRF_CLI_VT100_PF3 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'R', '\0' \ + } +#define NRF_CLI_VT100_PF4 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'S', '\0' \ + } + +/* Arrow keys */ + +#define NRF_CLI_VT100_UP_RESET \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'A', '\0' \ + } +#define NRF_CLI_VT100_UP_SET \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'A', '\0' \ + } +#define NRF_CLI_VT100_DOWN_RESET \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'B', '\0' \ + } +#define NRF_CLI_VT100_DOWN_SET \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'B', '\0' \ + } +#define NRF_CLI_VT100_RIGHT_RESET \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'C', '\0' \ + } +#define NRF_CLI_VT100_RIGHT_SET \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'C', '\0' \ + } +#define NRF_CLI_VT100_LEFT_RESET \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'D', '\0' \ + } +#define NRF_CLI_VT100_LEFT_SET \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'D', '\0' \ + } + +/* Numeric Keypad Keys */ + +#define NRF_CLI_VT100_NUMERIC_0 \ + { \ + '0', '\0' \ + } +#define NRF_CLI_VT100_ALT_0 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'p', '\0' \ + } +#define NRF_CLI_VT100_NUMERIC_1 \ + { \ + '1', '\0' \ + } +#define NRF_CLI_VT100_ALT_1 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'q', '\0' \ + } +#define NRF_CLI_VT100_NUMERIC_2 \ + { \ + '2', '\0' \ + } +#define NRF_CLI_VT100_ALT_2 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'r', '\0' \ + } +#define NRF_CLI_VT100_NUMERIC_3 \ + { \ + '3', '\0' \ + } +#define NRF_CLI_VT100_ALT_3 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 's', '\0' \ + } +#define NRF_CLI_VT100_NUMERIC_4 \ + { \ + '4', '\0' \ + } +#define NRF_CLI_VT100_ALT_4 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 't', '\0' \ + } +#define NRF_CLI_VT100_NUMERIC_5 \ + { \ + '5', '\0' \ + } +#define NRF_CLI_VT100_ALT_5 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'u', '\0' \ + } +#define NRF_CLI_VT100_NUMERIC_6 \ + { \ + '6', '\0' \ + } +#define NRF_CLI_VT100_ALT_6 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'v', '\0' \ + } +#define NRF_CLI_VT100_NUMERIC_7 \ + { \ + '7', '\0' \ + } +#define NRF_CLI_VT100_ALT_7 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'w', '\0' \ + } +#define NRF_CLI_VT100_NUMERIC_8 \ + { \ + '8', '\0' \ + } +#define NRF_CLI_VT100_ALT_8 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'x', '\0' \ + } +#define NRF_CLI_VT100_NUMERIC_9 \ + { \ + '9', '\0' +#define NRF_CLI_VT100_ALT_9 \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'y' \ + } +#define NRF_CLI_VT100_NUMERIC_MINUS \ + { \ + '-', '\0' \ + } +#define NRF_CLI_VT100_ALT_MINUS \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'm', '\0' \ + } +#define NRF_CLI_VT100_NUMERIC_COMMA \ + { \ + ',', '\0' \ + } +#define NRF_CLI_VT100_ALT_COMMA \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'l', '\0' \ + } +#define NRF_CLI_VT100_NUMERIC_PERIOD \ + { \ + '.', '\0' \ + } +#define NRF_CLI_VT100_ALT_PERIOD \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'n', '\0' \ + } +#define NRF_CLI_VT100_NUMERIC_ENTER \ + { \ + ASCII_CR \ + } +#define NRF_CLI_VT100_ALT_ENTER \ + { \ + NRF_CLI_VT100_ASCII_ESC, 'O', 'M', '\0' \ + } + +#define NRF_CLI_VT100_COLOR(__col) \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '1', ';', '3', '0' + (__col), 'm', '\0' \ + } +#define NRF_CLI_VT100_BGCOLOR(__col) \ + { \ + NRF_CLI_VT100_ASCII_ESC, '[', '4', '0' + (__col), 'm', '\0' \ + } + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_CLI_VT100_H__ */ + diff --git a/components/libraries/cli/rtt/nrf_cli_rtt.c b/components/libraries/cli/rtt/nrf_cli_rtt.c new file mode 100644 index 0000000..01ca094 --- /dev/null +++ b/components/libraries/cli/rtt/nrf_cli_rtt.c @@ -0,0 +1,223 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CLI_RTT) +#include +#include +#include "nrf_cli_rtt.h" +#include "nrf_assert.h" +#include "nrf_delay.h" + +#define RTT_RX_TIMEOUT 100 + +static bool m_host_present; + +static void timer_handler(void * p_context) +{ + nrf_cli_rtt_internal_t * p_internal = (nrf_cli_rtt_internal_t *)p_context; + if (SEGGER_RTT_HasData(0)) + { + p_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_RX_RDY, p_internal->p_cb->p_context); + } + p_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, p_internal->p_cb->p_context); + + ret_code_t err_code = app_timer_start(*p_internal->p_timer, + APP_TIMER_TICKS(RTT_RX_TIMEOUT), + p_context); + ASSERT(err_code == NRF_SUCCESS); + UNUSED_VARIABLE(err_code); +} + +static ret_code_t cli_rtt_init(nrf_cli_transport_t const * p_transport, + void const * p_config, + nrf_cli_transport_handler_t evt_handler, + void * p_context) +{ + UNUSED_PARAMETER(p_config); + + nrf_cli_rtt_internal_t * p_internal = + CONTAINER_OF(p_transport, nrf_cli_rtt_internal_t, transport); + p_internal->p_cb->handler = evt_handler; + p_internal->p_cb->p_context = p_context; + p_internal->p_cb->timer_created = false; + + SEGGER_RTT_Init(); + + m_host_present = true; + + return NRF_SUCCESS; +} + +static ret_code_t cli_rtt_uninit(nrf_cli_transport_t const * p_transport) +{ + nrf_cli_rtt_internal_t * p_internal = + CONTAINER_OF(p_transport, nrf_cli_rtt_internal_t, transport); + + return app_timer_stop(*p_internal->p_timer); +} + +static ret_code_t cli_rtt_enable(nrf_cli_transport_t const * p_transport, + bool blocking) +{ + nrf_cli_rtt_internal_t * p_internal = + CONTAINER_OF(p_transport, nrf_cli_rtt_internal_t, transport); + ret_code_t err_code = NRF_SUCCESS; + + if (p_internal->p_cb->timer_created) + { + err_code = app_timer_stop(*p_internal->p_timer); //Timer may be running or inactive + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) + { + return err_code; + } + else + { + err_code = NRF_SUCCESS; + } + } + if (!blocking) + { + if (!p_internal->p_cb->timer_created) + { + err_code = app_timer_create(p_internal->p_timer, + APP_TIMER_MODE_SINGLE_SHOT, + timer_handler); + p_internal->p_cb->timer_created = true; + } + if (err_code == NRF_SUCCESS) + { + err_code = app_timer_start(*p_internal->p_timer, + APP_TIMER_TICKS(RTT_RX_TIMEOUT), + p_internal); + SEGGER_RTT_Init(); + } + } + return err_code; +} +static ret_code_t cli_rtt_read(nrf_cli_transport_t const * p_transport, + void * p_data, + size_t length, + size_t * p_cnt) +{ + ASSERT(p_cnt); + UNUSED_PARAMETER(p_transport); + + size_t rcnt = SEGGER_RTT_Read(NRF_CLI_RTT_TERMINAL_ID, p_data, length); + *p_cnt = rcnt; + + return NRF_SUCCESS; +} + +static ret_code_t cli_rtt_write(nrf_cli_transport_t const * p_transport, + const void * p_data, + size_t length, + size_t * p_cnt) +{ + ASSERT(p_cnt); + UNUSED_PARAMETER(p_transport); + + if (!(CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk)) + { + /* If an RTT session is not active, but the RTT console is processed, the program may hang. + * Workaround: If the debugger is not connected, always return NRF_SUCCESS. + */ + *p_cnt = length; + return NRF_SUCCESS; + } + + size_t idx = 0; + uint32_t processed; + uint32_t watchdog_counter = NRF_CLI_RTT_TX_RETRY_CNT; + const uint8_t * p_buffer = (const uint8_t *)p_data; + do { + processed = SEGGER_RTT_Write(NRF_CLI_RTT_TERMINAL_ID, &p_buffer[idx], length); + if (processed == 0) + { + /* There are two possible reasons for not writing any data to RTT: + * - The host is not connected and not reading the data. + * - The buffer got full and will be read by the host. + * These two situations are distinguished using the following algorithm. + * At the begining, the module assumes that the host is active, + * so when no data is read, it busy waits and retries. + * If, after retrying, the host reads the data, the module assumes that the host is active. + * If it fails, the module assumes that the host is inactive and stores that information. On next + * call, only one attempt takes place. The host is marked as active if the attempt is successful. + */ + if (!m_host_present) + { + break; + } + else + { + nrf_delay_ms(NRF_CLI_RTT_TX_RETRY_DELAY_MS); + watchdog_counter--; + if (watchdog_counter == 0) + { + m_host_present = false; + break; + } + } + } + m_host_present = true; + idx += processed; + length -= processed; + } while (length); + + if (idx > 0) + { + *p_cnt = idx; + } + else + { + *p_cnt = length; + } + return NRF_SUCCESS; +} + +const nrf_cli_transport_api_t nrf_cli_rtt_transport_api = { + .init = cli_rtt_init, + .uninit = cli_rtt_uninit, + .enable = cli_rtt_enable, + .read = cli_rtt_read, + .write = cli_rtt_write, +}; + +#endif diff --git a/components/libraries/cli/rtt/nrf_cli_rtt.h b/components/libraries/cli/rtt/nrf_cli_rtt.h new file mode 100644 index 0000000..42e60d7 --- /dev/null +++ b/components/libraries/cli/rtt/nrf_cli_rtt.h @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_CLI_RTT_H__ +#define NRF_CLI_RTT_H__ + +#include "nrf_cli.h" +#include "app_timer.h" +#include "nordic_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@file + * + * @defgroup nrf_cli_rtt RTT command line interface transport layer + * @ingroup nrf_cli + * + * @{ + * + */ + +/** + * @brief Command line interface transport. + */ +extern const nrf_cli_transport_api_t nrf_cli_rtt_transport_api; + +/** + * @brief CLI RTT transport control block structure. + */ +typedef struct { + nrf_cli_transport_handler_t handler; //!< Event handler + void * p_context; //!< User context. + bool timer_created;//!< Flag indicating whether a timer is created. +} nrf_cli_rtt_internal_cb_t; + +/** + * @brief CLI RTT transport instance structure. + */ +typedef struct { + nrf_cli_transport_t transport; //!< Transport structure. + nrf_cli_rtt_internal_cb_t * p_cb; //!< Pointer to the instance control block. + app_timer_id_t const * p_timer; //!< Pointer to the app_timer instance. +} nrf_cli_rtt_internal_t; + +/**@brief CLI RTT transport definition */ +#define NRF_CLI_RTT_DEF(_name_) \ + APP_TIMER_DEF(CONCAT_2(_name_, _timer)); \ + static nrf_cli_rtt_internal_cb_t CONCAT_2(_name_, _cb); \ + static const nrf_cli_rtt_internal_t _name_ = { \ + .transport = {.p_api = &nrf_cli_rtt_transport_api}, \ + .p_cb = &CONCAT_2(_name_, _cb), \ + .p_timer = &CONCAT_2(_name_, _timer) \ + } + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_CLI_RTT_H__ */ diff --git a/components/libraries/cli/uart/nrf_cli_uart.c b/components/libraries/cli/uart/nrf_cli_uart.c new file mode 100644 index 0000000..09531dd --- /dev/null +++ b/components/libraries/cli/uart/nrf_cli_uart.c @@ -0,0 +1,308 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CLI_UART) +#include "nrf_cli_uart.h" +#include "nrf_drv_uart.h" +#include "nrf_assert.h" + +#define NRF_LOG_MODULE_NAME cli_uart + +#define NRF_LOG_LEVEL (NRF_CLI_UART_CONFIG_LOG_ENABLED ? NRF_CLI_UART_CONFIG_LOG_LEVEL : 0) +#define NRF_LOG_INFO_COLOR NRF_CLI_UART_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR NRF_CLI_UART_CONFIG_DEBUG_COLOR + +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define CLI_UART_RX_TIMEOUT 100 + +static ret_code_t rx_try(nrf_cli_uart_internal_t * p_internal) +{ + ret_code_t err_code; + size_t len = 255; + uint8_t * p_data; + + err_code = nrf_ringbuf_alloc(p_internal->p_rx_ringbuf, &p_data, &len, true); + ASSERT(err_code == NRF_SUCCESS); + + if ((err_code == NRF_SUCCESS) && len) + { + err_code = nrf_drv_uart_rx(p_internal->p_uart, p_data, len); + + if (err_code == NRF_SUCCESS) + { + err_code = app_timer_start(*p_internal->p_timer, + APP_TIMER_TICKS(CLI_UART_RX_TIMEOUT), + p_internal); + } + } + + return err_code; +} + +static void uart_event_handler(nrf_drv_uart_event_t * p_event, void * p_context) +{ + nrf_cli_uart_internal_t * p_internal = (nrf_cli_uart_internal_t *)p_context; + ret_code_t err_code = NRF_SUCCESS; + UNUSED_VARIABLE(err_code); + uint8_t * p_data; + size_t len = 255; + switch (p_event->type) + { + case NRF_DRV_UART_EVT_ERROR: + NRF_LOG_WARNING("id:%d, evt: ERROR:%d", + p_internal->p_uart->inst_idx, + p_event->data.error.error_mask); + err_code = nrf_ringbuf_put(p_internal->p_rx_ringbuf, p_event->data.error.rxtx.bytes); + ASSERT((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NO_MEM)); + err_code = rx_try(p_internal); + ASSERT(err_code == NRF_SUCCESS); + + break; + + case NRF_DRV_UART_EVT_RX_DONE: + err_code = nrf_ringbuf_put(p_internal->p_rx_ringbuf, p_event->data.rxtx.bytes); + ASSERT((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NO_MEM)); + + if (p_event->data.rxtx.bytes) + { + NRF_LOG_INFO("id:%d, evt: RXRDY len:%d", + p_internal->p_uart->inst_idx, + p_event->data.rxtx.bytes); + NRF_LOG_HEXDUMP_DEBUG(p_event->data.rxtx.p_data, p_event->data.rxtx.bytes); + p_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_RX_RDY, + p_internal->p_cb->p_context); + } + err_code = rx_try(p_internal); + ASSERT(err_code == NRF_SUCCESS); + + break; + + case NRF_DRV_UART_EVT_TX_DONE: + err_code = nrf_ringbuf_free(p_internal->p_tx_ringbuf, p_event->data.rxtx.bytes); + ASSERT(err_code == NRF_SUCCESS); + len = 255; + err_code = nrf_ringbuf_get(p_internal->p_tx_ringbuf, &p_data, &len, true); + ASSERT(err_code == NRF_SUCCESS); + if (len) + { + NRF_LOG_INFO("id:%d, evt uart_tx, len:%d", p_internal->p_uart->inst_idx, len); + err_code = nrf_drv_uart_tx(p_internal->p_uart, p_data, len); + ASSERT(err_code == NRF_SUCCESS); + } + p_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, p_internal->p_cb->p_context); + NRF_LOG_INFO("id:%d, evt: TXRDY, len:%d", + p_internal->p_uart->inst_idx, + p_event->data.rxtx.bytes); + break; + + default: + NRF_LOG_ERROR("Unknown event"); + ASSERT(false); + } +} + +static void timer_handler(void * p_context) +{ + nrf_cli_uart_internal_t * p_internal = (nrf_cli_uart_internal_t *)p_context; + NRF_LOG_DEBUG("id:%d, evt: Timeout", p_internal->p_uart->inst_idx); + nrf_drv_uart_rx_abort(p_internal->p_uart); +} + +static ret_code_t cli_uart_init(nrf_cli_transport_t const * p_transport, + void const * p_config, + nrf_cli_transport_handler_t evt_handler, + void * p_context) +{ + nrf_cli_uart_internal_t * p_internal = + CONTAINER_OF(p_transport, + nrf_cli_uart_internal_t, + transport); + p_internal->p_cb->handler = evt_handler; + p_internal->p_cb->p_context = p_context; + p_internal->p_cb->timer_created = false; + p_internal->p_cb->blocking = false; + + nrf_drv_uart_config_t * p_uart_config = (nrf_drv_uart_config_t *)p_config; + memcpy(&p_internal->p_cb->uart_config, p_uart_config, sizeof(nrf_drv_uart_config_t)); + p_uart_config->p_context = (void *)p_internal; + ret_code_t err_code = nrf_drv_uart_init(p_internal->p_uart, + p_uart_config, + uart_event_handler); + if (err_code == NRF_SUCCESS) + { + nrf_ringbuf_init(p_internal->p_rx_ringbuf); + nrf_ringbuf_init(p_internal->p_tx_ringbuf); + } + return err_code; +} + +static ret_code_t cli_uart_uninit(nrf_cli_transport_t const * p_transport) +{ + nrf_cli_uart_internal_t * p_internal = + CONTAINER_OF(p_transport, + nrf_cli_uart_internal_t, + transport); + + nrf_drv_uart_uninit(p_internal->p_uart); + + return app_timer_stop(*p_internal->p_timer); +} + +static ret_code_t cli_uart_enable(nrf_cli_transport_t const * p_transport, + bool blocking) +{ + nrf_cli_uart_internal_t * p_internal = + CONTAINER_OF(p_transport, + nrf_cli_uart_internal_t, + transport); + ret_code_t err_code = NRF_SUCCESS; + + if (p_internal->p_cb->timer_created) + { + err_code = app_timer_stop(*p_internal->p_timer); //Timer may be running or inactive + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) + { + return err_code; + } + else + { + err_code = NRF_SUCCESS; + } + } + + if (blocking) + { + nrf_drv_uart_uninit(p_internal->p_uart); + err_code = nrf_drv_uart_init(p_internal->p_uart, &p_internal->p_cb->uart_config, NULL); + if (err_code == NRF_SUCCESS) + { + p_internal->p_cb->blocking = true; + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_NOT_SUPPORTED; + } + } + else + { + if (!p_internal->p_cb->timer_created) + { + err_code = app_timer_create(p_internal->p_timer, + APP_TIMER_MODE_SINGLE_SHOT, + timer_handler); + p_internal->p_cb->timer_created = true; + } + if (err_code == NRF_SUCCESS) + { + err_code = rx_try(p_internal); + } + } + return err_code; +} + +static ret_code_t cli_uart_read(nrf_cli_transport_t const * p_transport, + void * p_data, + size_t length, + size_t * p_cnt) +{ + ASSERT(p_cnt); + nrf_cli_uart_internal_t * p_instance = + CONTAINER_OF(p_transport, nrf_cli_uart_internal_t, transport); + + *p_cnt = length; + ret_code_t err_code = nrf_ringbuf_cpy_get(p_instance->p_rx_ringbuf, p_data, p_cnt); + + if (*p_cnt) + { + NRF_LOG_INFO("id:%d, read:%d", p_instance->p_uart->inst_idx, *p_cnt); + } + + return err_code; +} + +static ret_code_t cli_uart_write(nrf_cli_transport_t const * p_transport, + void const * p_data, + size_t length, + size_t * p_cnt) +{ + ASSERT(p_cnt); + nrf_cli_uart_internal_t * p_instance = + CONTAINER_OF(p_transport, nrf_cli_uart_internal_t, transport); + ret_code_t err_code; + *p_cnt = length; + err_code = nrf_ringbuf_cpy_put(p_instance->p_tx_ringbuf, p_data, p_cnt); + if (err_code == NRF_SUCCESS) + { + NRF_LOG_INFO("id:%d, write, req:%d, done:%d", + p_instance->p_uart->inst_idx, + length, + *p_cnt); + + if (!nrf_drv_uart_tx_in_progress(p_instance->p_uart)) + { + uint8_t * p_buf; + size_t len = 255; + if (nrf_ringbuf_get(p_instance->p_tx_ringbuf, &p_buf, &len, true) == NRF_SUCCESS) + { + NRF_LOG_INFO("id:%d, uart_tx, len:%d", p_instance->p_uart->inst_idx, len); + + err_code = nrf_drv_uart_tx(p_instance->p_uart, p_buf, len); + if (p_instance->p_cb->blocking && (err_code == NRF_SUCCESS)) + { + (void)nrf_ringbuf_free(p_instance->p_tx_ringbuf, len); + } + } + } + } + return err_code; +} + +const nrf_cli_transport_api_t nrf_cli_uart_transport_api = { + .init = cli_uart_init, + .uninit = cli_uart_uninit, + .enable = cli_uart_enable, + .read = cli_uart_read, + .write = cli_uart_write, +}; + +#endif diff --git a/components/libraries/cli/uart/nrf_cli_uart.h b/components/libraries/cli/uart/nrf_cli_uart.h new file mode 100644 index 0000000..c01f11d --- /dev/null +++ b/components/libraries/cli/uart/nrf_cli_uart.h @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_CLI_UART_H__ +#define NRF_CLI_UART_H__ + +#include "nrf_cli.h" +#include "nrf_drv_uart.h" +#include "nrf_ringbuf.h" +#include "app_timer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@file + * + * @defgroup nrf_cli_uart UART command line interface transport layer + * @ingroup nrf_cli + * + * @{ + * + */ + +/** + * @brief Command line interface transport. + */ +extern const nrf_cli_transport_api_t nrf_cli_uart_transport_api; + +typedef struct nrf_cli_uart_internal_s nrf_cli_uart_internal_t; + +typedef struct { + nrf_cli_transport_handler_t handler; + void * p_context; + nrf_drv_uart_config_t uart_config; + bool timer_created; + bool blocking; +} nrf_cli_uart_internal_cb_t; + +struct nrf_cli_uart_internal_s { + nrf_cli_transport_t transport; + nrf_cli_uart_internal_cb_t * p_cb; + app_timer_id_t const * p_timer; + nrf_ringbuf_t const * p_rx_ringbuf; + nrf_ringbuf_t const * p_tx_ringbuf; + nrf_drv_uart_t const * p_uart; +}; + +typedef nrf_drv_uart_config_t nrf_cli_uart_config_t; + +/**@brief CLI UART transport definition. + * + * @param _name Name of the instance. + * @param _uart_id UART instance ID. + * @param _tx_buf_sz Size of TX ring buffer. + * @param _rx_buf_sz Size of RX ring buffer. + */ +#define NRF_CLI_UART_DEF(_name, _uart_id, _tx_buf_sz, _rx_buf_sz) \ + APP_TIMER_DEF(CONCAT_2(_name, _timer)); \ + NRF_RINGBUF_DEF(CONCAT_2(_name,_tx_ringbuf), _tx_buf_sz); \ + NRF_RINGBUF_DEF(CONCAT_2(_name,_rx_ringbuf), _rx_buf_sz); \ + static const nrf_drv_uart_t CONCAT_2(_name,_uart) = \ + NRF_DRV_UART_INSTANCE(_uart_id); \ + static nrf_cli_uart_internal_cb_t CONCAT_2(_name, _cb); \ + static const nrf_cli_uart_internal_t _name = { \ + .transport = {.p_api = &nrf_cli_uart_transport_api}, \ + .p_cb = &CONCAT_2(_name, _cb), \ + .p_timer = &CONCAT_2(_name, _timer), \ + .p_rx_ringbuf = &CONCAT_2(_name,_rx_ringbuf), \ + .p_tx_ringbuf = &CONCAT_2(_name,_tx_ringbuf), \ + .p_uart = &CONCAT_2(_name,_uart), \ + } +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_CLI_UART_H__ */ diff --git a/components/libraries/crc16/crc16.c b/components/libraries/crc16/crc16.c new file mode 100644 index 0000000..7a64521 --- /dev/null +++ b/components/libraries/crc16/crc16.c @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2013 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(CRC16) +#include "crc16.h" + +#include + +uint16_t crc16_compute(uint8_t const * p_data, uint32_t size, uint16_t const * p_crc) +{ + uint16_t crc = (p_crc == NULL) ? 0xFFFF : *p_crc; + + for (uint32_t i = 0; i < size; i++) + { + crc = (uint8_t)(crc >> 8) | (crc << 8); + crc ^= p_data[i]; + crc ^= (uint8_t)(crc & 0xFF) >> 4; + crc ^= (crc << 8) << 4; + crc ^= ((crc & 0xFF) << 4) << 1; + } + + return crc; +} +#endif //NRF_MODULE_ENABLED(CRC16) diff --git a/components/libraries/crc16/crc16.h b/components/libraries/crc16/crc16.h new file mode 100644 index 0000000..61e11d6 --- /dev/null +++ b/components/libraries/crc16/crc16.h @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2013 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup crc16 CRC16 compute + * @{ + * @ingroup hci_transport + * + * @brief This module implements CRC-16-CCITT (polynomial 0x1021) with 0xFFFF initial value. + * The data can be passed in multiple blocks. + */ + +#ifndef CRC16_H__ +#define CRC16_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Function for calculating CRC-16 in blocks. + * + * Feed each consecutive data block into this function, along with the current value of p_crc as + * returned by the previous call of this function. The first call of this function should pass NULL + * as the initial value of the crc in p_crc. + * + * @param[in] p_data The input data block for computation. + * @param[in] size The size of the input data block in bytes. + * @param[in] p_crc The previous calculated CRC-16 value or NULL if first call. + * + * @return The updated CRC-16 value, based on the input supplied. + */ +uint16_t crc16_compute(uint8_t const * p_data, uint32_t size, uint16_t const * p_crc); + + +#ifdef __cplusplus +} +#endif + +#endif // CRC16_H__ + +/** @} */ diff --git a/components/libraries/crc32/crc32.c b/components/libraries/crc32/crc32.c new file mode 100644 index 0000000..b3ef00a --- /dev/null +++ b/components/libraries/crc32/crc32.c @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2013 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(CRC32) +#include "crc32.h" + +#include + +uint32_t crc32_compute(uint8_t const * p_data, uint32_t size, uint32_t const * p_crc) +{ + uint32_t crc; + + crc = (p_crc == NULL) ? 0xFFFFFFFF : ~(*p_crc); + for (uint32_t i = 0; i < size; i++) + { + crc = crc ^ p_data[i]; + for (uint32_t j = 8; j > 0; j--) + { + crc = (crc >> 1) ^ (0xEDB88320U & ((crc & 1) ? 0xFFFFFFFF : 0)); + } + } + return ~crc; +} +#endif //NRF_MODULE_ENABLED(CRC32) diff --git a/components/libraries/crc32/crc32.h b/components/libraries/crc32/crc32.h new file mode 100644 index 0000000..97fb11b --- /dev/null +++ b/components/libraries/crc32/crc32.h @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup crc32 CRC32 compute + * @{ + * @ingroup hci_transport + * + * @brief This module implements the CRC-32 calculation in the blocks. + */ + +#ifndef CRC32_H__ +#define CRC32_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Function for calculating CRC-32 in blocks. + * + * Feed each consecutive data block into this function, along with the current value of p_crc as + * returned by the previous call of this function. The first call of this function should pass NULL + * as the initial value of the crc in p_crc. + * + * @param[in] p_data The input data block for computation. + * @param[in] size The size of the input data block in bytes. + * @param[in] p_crc The previous calculated CRC-32 value or NULL if first call. + * + * @return The updated CRC-32 value, based on the input supplied. + */ +uint32_t crc32_compute(uint8_t const * p_data, uint32_t size, uint32_t const * p_crc); + + +#ifdef __cplusplus +} +#endif + +#endif // CRC32_H__ + +/** @} */ diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_aes.c b/components/libraries/crypto/backend/cc310/cc310_backend_aes.c new file mode 100644 index 0000000..bc4eacc --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_aes.c @@ -0,0 +1,867 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#include +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include +#include "ssi_aes_error.h" +#include "cc310_backend_aes.h" +#include "cc310_backend_mutex.h" +#include "cc310_backend_shared.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_CC310_AES) + +/**@internal @brief Type declarations of templates matching all possible context sizes + * for this backend. + */ +typedef struct +{ + nrf_crypto_aes_internal_context_t header; /**< Common header for context. */ + SaSiAesUserContext_t context; /**< AES context internal to mbed TLS. */ + nrf_crypto_backend_aes_ctx_t backend; /**< Backend-specific internal context. */ +} nrf_crypto_backend_cc310_aes_any_context_t; + +/**@internal @brief Type declarations of templates matching all possible context sizes + * for this backend. + */ +typedef union +{ + nrf_crypto_backend_cc310_aes_any_context_t any; /**< Common for all contexts. */ + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_ECB) + nrf_crypto_backend_aes_ecb_context_t ecb; +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CBC) + nrf_crypto_backend_aes_cbc_context_t cbc; +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CTR) + nrf_crypto_backend_aes_ctr_context_t ctr; +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CBC_MAC) + nrf_crypto_backend_aes_cbc_mac_context_t cbc_mac; +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CMAC) + nrf_crypto_backend_aes_cmac_context_t cmac; +#endif +} nrf_crypto_backend_cc310_aes_context_t; + + +static ret_code_t result_get(SaSiError_t error) +{ + ret_code_t ret_val; + switch (error) + { + case SASI_SUCCESS: + ret_val = NRF_SUCCESS; + break; + + case SASI_AES_INVALID_USER_CONTEXT_POINTER_ERROR: + ret_val = NRF_ERROR_CRYPTO_CONTEXT_NULL; + break; + + case SASI_AES_ILLEGAL_KEY_SIZE_ERROR: + case SASI_AES_DATA_IN_SIZE_ILLEGAL: + case SASI_AES_DATA_IN_BUFFER_SIZE_ERROR: + ret_val = NRF_ERROR_CRYPTO_INPUT_LENGTH; + break; + + case SASI_AES_INVALID_IV_OR_TWEAK_PTR_ERROR: + case SASI_AES_INVALID_KEY_POINTER_ERROR: + case SASI_AES_DATA_IN_POINTER_INVALID_ERROR: + ret_val = NRF_ERROR_CRYPTO_INPUT_NULL; + break; + + case SASI_AES_ILLEGAL_OPERATION_MODE_ERROR: + case SASI_AES_KEY_TYPE_NOT_SUPPORTED_ERROR: + case SASI_AES_INVALID_ENCRYPT_MODE_ERROR: + case SASI_AES_ILLEGAL_PADDING_TYPE_ERROR: + case SASI_AES_INCORRECT_PADDING_ERROR: + case SASI_AES_DECRYPTION_NOT_ALLOWED_ON_THIS_MODE: + case SASI_AES_ADDITIONAL_BLOCK_NOT_PERMITTED_ERROR: + case SASI_AES_IS_NOT_SUPPORTED: + ret_val = NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + break; + + case SASI_AES_DATA_OUT_BUFFER_SIZE_ERROR: + ret_val = NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + break; + + case SASI_AES_DATA_OUT_POINTER_INVALID_ERROR: + case SASI_AES_DATA_OUT_SIZE_POINTER_INVALID_ERROR: + ret_val = NRF_ERROR_CRYPTO_OUTPUT_NULL; + break; + + case SASI_AES_CTX_SIZES_ERROR: + default: + ret_val = NRF_ERROR_CRYPTO_INTERNAL; + break; + } + return ret_val; +} + +static ret_code_t params_validate(nrf_crypto_backend_cc310_aes_context_t const * const p_ctx, + SaSiAesOperationMode_t * p_mode, + nrf_crypto_operation_t operation) +{ + ret_code_t ret_val = NRF_SUCCESS; + + switch (p_ctx->any.header.p_info->mode) + { +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_ECB) + case NRF_CRYPTO_AES_MODE_ECB: + case NRF_CRYPTO_AES_MODE_ECB_PAD_PCKS7: + *p_mode = SASI_AES_MODE_ECB; + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CBC) + case NRF_CRYPTO_AES_MODE_CBC: + case NRF_CRYPTO_AES_MODE_CBC_PAD_PCKS7: + *p_mode = SASI_AES_MODE_CBC; + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CTR) + case NRF_CRYPTO_AES_MODE_CTR: + *p_mode = SASI_AES_MODE_CTR; + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CBC_MAC) + case NRF_CRYPTO_AES_MODE_CBC_MAC: + case NRF_CRYPTO_AES_MODE_CBC_MAC_PAD_PCKS7: + *p_mode = SASI_AES_MODE_CBC_MAC; + VERIFY_TRUE((operation == NRF_CRYPTO_MAC_CALCULATE), NRF_ERROR_CRYPTO_INVALID_PARAM); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CMAC) + case NRF_CRYPTO_AES_MODE_CMAC: + *p_mode = SASI_AES_MODE_CMAC; + VERIFY_TRUE((operation == NRF_CRYPTO_MAC_CALCULATE), NRF_ERROR_CRYPTO_INVALID_PARAM); + break; +#endif + + default: + ret_val = NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + break; + } + + return ret_val; +} + +static ret_code_t backend_cc310_init(void * const p_context, nrf_crypto_operation_t operation) +{ + SaSiError_t result; + ret_code_t ret_val; + bool mutex_locked; + + SaSiAesOperationMode_t mode; + SaSiAesEncryptMode_t operation_cc310; + + nrf_crypto_backend_cc310_aes_context_t * p_ctx = + (nrf_crypto_backend_cc310_aes_context_t *)p_context; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + if (!nrfx_is_in_ram(&p_ctx->any.context)) + { + ret_val = NRF_ERROR_CRYPTO_INPUT_LOCATION; + goto exit; + } + if (p_ctx->any.header.p_info->key_size != NRF_CRYPTO_KEY_SIZE_128) + { + ret_val = NRF_ERROR_CRYPTO_KEY_SIZE; + goto exit; + } + + ret_val = params_validate(p_ctx, &mode, operation); + + if (ret_val != NRF_SUCCESS) + { + goto exit; + } + + if (operation == NRF_CRYPTO_DECRYPT) + { + operation_cc310 = SASI_AES_DECRYPT; + } + else if ((operation == NRF_CRYPTO_ENCRYPT) || (operation == NRF_CRYPTO_MAC_CALCULATE)) + { + operation_cc310 = SASI_AES_ENCRYPT; + } + else + { + ret_val = NRF_ERROR_CRYPTO_INVALID_PARAM; + goto exit; + } + p_ctx->any.backend.operation = operation; + + result = SaSi_AesInit(&p_ctx->any.context, + operation_cc310, + mode, + SASI_AES_PADDING_NONE); /* CC310 does not support padding */ + ret_val = result_get(result); + +exit: + cc310_backend_mutex_unlock(); + return ret_val; +} + +static ret_code_t backend_cc310_uninit(void * const p_context) +{ + SaSiError_t result; + ret_code_t ret_val; + + nrf_crypto_backend_cc310_aes_context_t * p_ctx = + (nrf_crypto_backend_cc310_aes_context_t *)p_context; + + bool mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + result = SaSi_AesFree(&p_ctx->any.context); + ret_val = result_get(result); + + cc310_backend_mutex_unlock(); + return ret_val; +} + +static ret_code_t backend_cc310_key_set(void * const p_context, uint8_t * p_key) +{ + SaSiError_t result; + ret_code_t ret_val; + bool mutex_locked; + + SaSiAesUserKeyData_t key_data; + + nrf_crypto_backend_cc310_aes_context_t * p_ctx = + (nrf_crypto_backend_cc310_aes_context_t *)p_context; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + if (!nrfx_is_in_ram(p_key)) + { + ret_val = NRF_ERROR_CRYPTO_INPUT_LOCATION; + goto exit; + } + + key_data.pKey = p_key; + key_data.keySize = (p_ctx->any.header.p_info->key_size) >> 3; // change bits to bytes + + result = SaSi_AesSetKey(&p_ctx->any.context, + SASI_AES_USER_KEY, + &key_data, + sizeof(key_data)); + ret_val = result_get(result); + +exit: + cc310_backend_mutex_unlock(); + return ret_val; +} + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CBC) || \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CTR) || \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CBC_MAC) +static ret_code_t backend_cc310_iv_set(void * const p_context, uint8_t * p_iv) +{ + SaSiError_t result; + ret_code_t ret_val; + bool mutex_locked; + + nrf_crypto_backend_cc310_aes_context_t * p_ctx = + (nrf_crypto_backend_cc310_aes_context_t *)p_context; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + if (!nrfx_is_in_ram(p_iv)) + { + ret_val = NRF_ERROR_CRYPTO_INPUT_LOCATION; + goto exit; + } + + result = SaSi_AesSetIv(&p_ctx->any.context, p_iv); + ret_val = result_get(result); + +exit: + cc310_backend_mutex_unlock(); + return ret_val; +} + +static ret_code_t backend_cc310_iv_get(void * const p_context, uint8_t * p_iv) +{ + SaSiError_t result; + ret_code_t ret_val = NRF_ERROR_CRYPTO_INTERNAL; + bool mutex_locked; + + nrf_crypto_backend_cc310_aes_context_t * p_ctx = + (nrf_crypto_backend_cc310_aes_context_t *)p_context; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + if (!nrfx_is_in_ram(p_iv)) + { + ret_val = NRF_ERROR_CRYPTO_INPUT_LOCATION; + goto exit; + } + + result = SaSi_AesGetIv(&p_ctx->any.context, p_iv); + + /* Below code allows to read IV after calling nrf_crypto_aes_finalize */ + if (result == SASI_AES_ILLEGAL_OPERATION_MODE_ERROR) + { + if (p_ctx->any.header.init_value == NRF_CRYPTO_AES_UNINIT_MAGIC_VALUE) + { + memcpy(p_iv, p_ctx->any.backend.iv, NRF_CRYPTO_MBEDTLS_AES_IV_SIZE); + ret_val = NRF_SUCCESS; + } + } + else + { + ret_val = result_get(result); + } + +exit: + cc310_backend_mutex_unlock(); + return ret_val; +} +#endif + +static ret_code_t backend_cc310_update(void * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out) +{ + SaSiError_t result; + ret_code_t ret_val; + bool mutex_locked; + size_t size; + size_t offset = 0; + + nrf_crypto_backend_cc310_aes_context_t * p_ctx = + (nrf_crypto_backend_cc310_aes_context_t *)p_context; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + if (!nrfx_is_in_ram(p_data_in) || !nrfx_is_in_ram(p_data_out)) + { + ret_val = NRF_ERROR_CRYPTO_INPUT_LOCATION; + goto exit; + } + + do + { + /* CC310 allows only 64kB blocks, operation must be devided */ + if (data_size > CC310_MAX_LENGTH_DMA_AES_OPERATIONS) + { + size = CC310_MAX_LENGTH_DMA_AES_OPERATIONS; + data_size -= CC310_MAX_LENGTH_DMA_AES_OPERATIONS; + } + else + { + size = data_size; + data_size = 0; + } + + if (p_ctx->any.backend.operation == NRF_CRYPTO_MAC_CALCULATE) + { + result = SaSi_AesBlock(&p_ctx->any.context, + p_data_in + offset, + size, + p_data_out); + } + else + { + result = SaSi_AesBlock(&p_ctx->any.context, + p_data_in + offset, + size, + p_data_out + offset); + } + + offset += size; + ret_val = result_get(result); + + } while ((data_size > 0) && (ret_val == NRF_SUCCESS)); + +exit: + cc310_backend_mutex_unlock(); + return ret_val; +} + +static ret_code_t backend_cc310_finalize(void * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out, + size_t * p_data_out_size) +{ + SaSiError_t result; + ret_code_t ret_val; + bool mutex_locked; + size_t size; + size_t offset = 0; + + nrf_crypto_backend_cc310_aes_context_t * p_ctx = + (nrf_crypto_backend_cc310_aes_context_t *)p_context; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + if (*p_data_out_size < data_size) + { + ret_val = NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + goto exit; + } + + /* This function does not support padding */ + if (((data_size & 0xF) != 0) && + (p_ctx->any.header.p_info->mode != NRF_CRYPTO_AES_MODE_CTR)) + { + ret_val = NRF_ERROR_CRYPTO_INPUT_LENGTH; + goto exit; + } + + if (!nrfx_is_in_ram(p_data_in) || !nrfx_is_in_ram(p_data_out)) + { + ret_val = NRF_ERROR_CRYPTO_INPUT_LOCATION; + goto exit; + } + + /* CC310 allows only 64kB blocks, operation must be devided */ + while (data_size > CC310_MAX_LENGTH_DMA_AES_OPERATIONS) + { + size = CC310_MAX_LENGTH_DMA_AES_OPERATIONS; + data_size -= CC310_MAX_LENGTH_DMA_AES_OPERATIONS; + + result = SaSi_AesBlock(&p_ctx->any.context, + p_data_in + offset, + size, + p_data_out + offset); + + offset += size; + ret_val = result_get(result); + + if (ret_val != NRF_SUCCESS) + { + goto exit; + } + } + + /* Calculate space in the output buffer */ + *p_data_out_size -= offset; + + result = SaSi_AesFinish(&p_ctx->any.context, + data_size, + p_data_in + offset, + data_size, + p_data_out + offset, + p_data_out_size); + + ret_val = result_get(result); + + if (ret_val == NRF_SUCCESS) + { + /* update information about size of encrypted data */ + *p_data_out_size += offset; + } + + /* Store IV value in case it will be needed after finalize operation */ + if ((p_ctx->any.header.p_info->mode == NRF_CRYPTO_AES_MODE_CBC) || + (p_ctx->any.header.p_info->mode == NRF_CRYPTO_AES_MODE_CTR)) + { + result = SaSi_AesGetIv(&p_ctx->any.context, &p_ctx->any.backend.iv[0]); + ret_val = result_get(result); + } + +exit: + cc310_backend_mutex_unlock(); + return ret_val; +} + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CMAC) || \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CBC_MAC) +static ret_code_t backend_cc310_mac_finalize(void * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out, + size_t * p_data_out_size) +{ + SaSiError_t result; + ret_code_t ret_val; + bool mutex_locked; + size_t size; + size_t offset = 0; + + nrf_crypto_backend_cc310_aes_context_t * p_ctx = + (nrf_crypto_backend_cc310_aes_context_t *)p_context; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + if (*p_data_out_size < NRF_CRYPTO_AES_BLOCK_SIZE) + { + ret_val = NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + goto exit; + } + + if (!nrfx_is_in_ram(p_data_in) || !nrfx_is_in_ram(p_data_out)) + { + ret_val = NRF_ERROR_CRYPTO_INPUT_LOCATION; + goto exit; + } + + /* This function does not support padding for CBC-MAC */ + if (((data_size & 0xF) != 0) && + (NRF_CRYPTO_AES_MODE_CBC_MAC == p_ctx->any.header.p_info->mode)) + { + ret_val = NRF_ERROR_CRYPTO_INPUT_LENGTH; + goto exit; + } + + /* CC310 allows only 64kB blocks, operation must be devided */ + while (data_size > CC310_MAX_LENGTH_DMA_AES_OPERATIONS) + { + size = CC310_MAX_LENGTH_DMA_AES_OPERATIONS; + data_size -= CC310_MAX_LENGTH_DMA_AES_OPERATIONS; + + result = SaSi_AesBlock(&p_ctx->any.context, + p_data_in + offset, + size, + p_data_out); + + offset += size; + ret_val = result_get(result); + + if (ret_val != NRF_SUCCESS) + { + goto exit; + } + } + + result = SaSi_AesFinish(&p_ctx->any.context, + data_size, + p_data_in + offset, + data_size, + p_data_out, + p_data_out_size); + + ret_val = result_get(result); + + if (ret_val == NRF_SUCCESS) + { + /* update information about size of encrypted data */ + *p_data_out_size = NRF_CRYPTO_AES_BLOCK_SIZE; + } + + /* Store IV value in case it will be needed after finalize operation */ + if (p_ctx->any.header.p_info->mode == NRF_CRYPTO_AES_MODE_CBC_MAC_PAD_PCKS7) + { + result = SaSi_AesGetIv(&p_ctx->any.context, &p_ctx->any.backend.iv[0]); + ret_val = result_get(result); + } + +exit: + cc310_backend_mutex_unlock(); + return ret_val; +} +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CBC_MAC) +static ret_code_t backend_cc310_cbc_mac_padding_finalize(void * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out, + size_t * p_data_out_size) +{ + ret_code_t ret_val; + uint8_t padding_buffer[NRF_CRYPTO_AES_BLOCK_SIZE] = {0}; + uint8_t msg_ending = (uint8_t)(data_size & (size_t)0x0F); + + if (*p_data_out_size < NRF_CRYPTO_AES_BLOCK_SIZE) + { + /* output buffer too small */ + return NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + } + + data_size -= msg_ending; + + if (data_size > 0) + { + ret_val = backend_cc310_update(p_context, + p_data_in, + data_size, + p_data_out); + VERIFY_SUCCESS(ret_val); + } + + ret_val = padding_pkcs7_add(&padding_buffer[0], + p_data_in + data_size, + msg_ending); + VERIFY_SUCCESS(ret_val); + + ret_val = backend_cc310_mac_finalize(p_context, + &padding_buffer[0], + NRF_CRYPTO_AES_BLOCK_SIZE, + p_data_out, + p_data_out_size); + VERIFY_SUCCESS(ret_val); + + return ret_val; +} +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CBC) || \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_ECB) +static ret_code_t backend_cc310_padding_finalize(void * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out, + size_t * p_data_out_size) +{ + SaSiError_t result; + ret_code_t ret_val; + uint8_t padding_buffer[NRF_CRYPTO_AES_BLOCK_SIZE] = {0}; + uint8_t msg_ending = (uint8_t)(data_size & (size_t)0x0F); + size_t buff_out_size; + + nrf_crypto_backend_cc310_aes_context_t * p_ctx = + (nrf_crypto_backend_cc310_aes_context_t *)p_context; + + if (p_ctx->any.backend.operation == NRF_CRYPTO_DECRYPT) + { + ret_val = backend_cc310_finalize(p_context, + p_data_in, + data_size, + p_data_out, + p_data_out_size); + VERIFY_SUCCESS(ret_val); + + + ret_val = padding_pkcs7_remove(p_data_out, + p_data_out_size); + return ret_val; + } + + /* -------------- ENCRYPTION --------------*/ + data_size -= msg_ending; + + if (*p_data_out_size < (data_size + NRF_CRYPTO_AES_BLOCK_SIZE)) + { + /* no space for padding */ + return NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + } + + if (data_size > 0) + { + ret_val = backend_cc310_update(p_context, + p_data_in, + data_size, + p_data_out); + VERIFY_SUCCESS(ret_val); + } + + ret_val = padding_pkcs7_add(&padding_buffer[0], + p_data_in + data_size, + msg_ending); + VERIFY_SUCCESS(ret_val); + + buff_out_size = *p_data_out_size - data_size; + + ret_val = backend_cc310_finalize(p_context, + &padding_buffer[0], + NRF_CRYPTO_AES_BLOCK_SIZE, + p_data_out + data_size, + &buff_out_size); + VERIFY_SUCCESS(ret_val); + + *p_data_out_size = buff_out_size + data_size; + + /* Store IV value in case it will be needed after finalize operation */ + if (p_ctx->any.header.p_info->mode == NRF_CRYPTO_AES_MODE_CBC_PAD_PCKS7) + { + result = SaSi_AesGetIv(&p_ctx->any.context, &p_ctx->any.backend.iv[0]); + ret_val = result_get(result); + } + + return ret_val; +} +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CBC) +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_128_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_context_t), + + .init_fn = backend_cc310_init, + .uninit_fn = backend_cc310_uninit, + .key_set_fn = backend_cc310_key_set, + .iv_set_fn = backend_cc310_iv_set, + .iv_get_fn = backend_cc310_iv_get, + .update_fn = backend_cc310_update, + .finalize_fn = backend_cc310_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_128_pad_pkcs7_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC_PAD_PCKS7, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_context_t), + + .init_fn = backend_cc310_init, + .uninit_fn = backend_cc310_uninit, + .key_set_fn = backend_cc310_key_set, + .iv_set_fn = backend_cc310_iv_set, + .iv_get_fn = backend_cc310_iv_get, + .update_fn = backend_cc310_update, + .finalize_fn = backend_cc310_padding_finalize +}; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CTR) +nrf_crypto_aes_info_t const g_nrf_crypto_aes_ctr_128_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CTR, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_ctr_context_t), + + .init_fn = backend_cc310_init, + .uninit_fn = backend_cc310_uninit, + .key_set_fn = backend_cc310_key_set, + .iv_set_fn = backend_cc310_iv_set, + .iv_get_fn = backend_cc310_iv_get, + .update_fn = backend_cc310_update, + .finalize_fn = backend_cc310_finalize +}; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_ECB) +nrf_crypto_aes_info_t const g_nrf_crypto_aes_ecb_128_info = +{ + .mode = NRF_CRYPTO_AES_MODE_ECB, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_ecb_context_t), + + .init_fn = backend_cc310_init, + .uninit_fn = backend_cc310_uninit, + .key_set_fn = backend_cc310_key_set, + .iv_set_fn = NULL, + .iv_get_fn = NULL, + .update_fn = backend_cc310_update, + .finalize_fn = backend_cc310_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_ecb_128_pad_pkcs7_info = +{ + .mode = NRF_CRYPTO_AES_MODE_ECB_PAD_PCKS7, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_ecb_context_t), + + .init_fn = backend_cc310_init, + .uninit_fn = backend_cc310_uninit, + .key_set_fn = backend_cc310_key_set, + .iv_set_fn = NULL, + .iv_get_fn = NULL, + .update_fn = backend_cc310_update, + .finalize_fn = backend_cc310_padding_finalize +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CBC_MAC) +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_mac_128_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC_MAC, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_mac_context_t), + + .init_fn = backend_cc310_init, + .uninit_fn = backend_cc310_uninit, + .key_set_fn = backend_cc310_key_set, + .iv_set_fn = backend_cc310_iv_set, + .iv_get_fn = backend_cc310_iv_get, + .update_fn = backend_cc310_update, + .finalize_fn = backend_cc310_mac_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_mac_128_pad_pkcs7_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC_MAC_PAD_PCKS7, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_mac_context_t), + + .init_fn = backend_cc310_init, + .uninit_fn = backend_cc310_uninit, + .key_set_fn = backend_cc310_key_set, + .iv_set_fn = backend_cc310_iv_set, + .iv_get_fn = backend_cc310_iv_get, + .update_fn = backend_cc310_update, + .finalize_fn = backend_cc310_cbc_mac_padding_finalize +}; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CMAC) +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cmac_128_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CMAC, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_cmac_context_t), + + .init_fn = backend_cc310_init, + .uninit_fn = backend_cc310_uninit, + .key_set_fn = backend_cc310_key_set, + .iv_set_fn = NULL, + .iv_get_fn = NULL, + .update_fn = backend_cc310_update, + .finalize_fn = backend_cc310_mac_finalize +}; +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_AES_BACKEND_CC310) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) + diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_aes.h b/components/libraries/crypto/backend/cc310/cc310_backend_aes.h new file mode 100644 index 0000000..c016db9 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_aes.h @@ -0,0 +1,187 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BACKEND_AES_H__ +#define CC310_BACKEND_AES_H__ + +/** @file + * + * @defgroup nrf_crypto_cc310_backend_aes nrf_crypto CC310 backend AES + * @{ + * @ingroup nrf_crypto_cc310_backend + * + * @brief AES functionality provided by the nrf_crypto CC310 backend. + */ + +#include "sdk_config.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) || defined(__SDK_DOXYGEN__) + +#include "ssi_aes.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_types.h" +#include "nrf_crypto_aes_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* AES CBC */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CBC) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CBC) +#error "Duplicate definition of AES CBC mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_AES_CBC_ENABLED 1 +#undef NRF_CRYPTO_AES_ENABLED +#define NRF_CRYPTO_AES_ENABLED 1 // Flag that nrf_crypto_aes frontend can be compiled +#undef NRF_CRYPTO_CC310_AES_ENABLED +#define NRF_CRYPTO_CC310_AES_ENABLED 1 + +/* define for test purposes */ +#define NRF_CRYPTO_AES_CBC_128_ENABLED 1 + +typedef struct +{ + nrf_crypto_aes_internal_context_t header; /**< Common header for context. */ + SaSiAesUserContext_t context; /**< AES context internal to CC310. */ + nrf_crypto_backend_aes_ctx_t backend; +} nrf_crypto_backend_aes_cbc_context_t; +#endif + +/* AES CTR */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CTR) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CTR) +#error "Duplicate definition of AES CTR mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_AES_CTR_ENABLED 1 +#undef NRF_CRYPTO_AES_ENABLED +#define NRF_CRYPTO_AES_ENABLED 1 // Flag that nrf_crypto_aes frontend can be compiled +#undef NRF_CRYPTO_CC310_AES_ENABLED +#define NRF_CRYPTO_CC310_AES_ENABLED 1 + +/* define for test purposes */ +#define NRF_CRYPTO_AES_CTR_128_ENABLED 1 + +typedef struct +{ + nrf_crypto_aes_internal_context_t header; /**< Common header for context. */ + SaSiAesUserContext_t context; /**< AES context internal to CC310. */ + nrf_crypto_backend_aes_ctx_t backend; +} nrf_crypto_backend_aes_ctr_context_t; +#endif + +/* AES ECB */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_ECB) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_ECB) +#error "Duplicate definition of AES ECB mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_AES_ECB_ENABLED 1 +#undef NRF_CRYPTO_AES_ENABLED +#define NRF_CRYPTO_AES_ENABLED 1 // Flag that nrf_crypto_aes frontend can be compiled +#undef NRF_CRYPTO_CC310_AES_ENABLED +#define NRF_CRYPTO_CC310_AES_ENABLED 1 + +/* define for test purposes */ +#define NRF_CRYPTO_AES_ECB_128_ENABLED 1 + +typedef struct +{ + nrf_crypto_aes_internal_context_t header; /**< Common header for context. */ + SaSiAesUserContext_t context; /**< AES context internal to CC310. */ + nrf_crypto_backend_no_iv_aes_ctx_t backend; +} nrf_crypto_backend_aes_ecb_context_t; +#endif + + +/* AES CBC_MAC */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CBC_MAC) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CBC_MAC) +#error "Duplicate definition of AES CBC_MAC mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_AES_CBC_MAC_ENABLED 1 +#undef NRF_CRYPTO_AES_ENABLED +#define NRF_CRYPTO_AES_ENABLED 1 // Flag that nrf_crypto_aes frontend can be compiled +#undef NRF_CRYPTO_CC310_AES_ENABLED +#define NRF_CRYPTO_CC310_AES_ENABLED 1 + +/* define for test purposes */ +#define NRF_CRYPTO_AES_CBC_MAC_128_ENABLED 1 + +typedef struct +{ + nrf_crypto_aes_internal_context_t header; /**< Common header for context. */ + SaSiAesUserContext_t context; /**< AES context internal to CC310. */ + nrf_crypto_backend_aes_ctx_t backend; +} nrf_crypto_backend_aes_cbc_mac_context_t; +#endif + +/* AES CMAC */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CMAC) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CMAC) +#error "Duplicate definition of AES CMAC mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_AES_CMAC_ENABLED 1 +#undef NRF_CRYPTO_AES_ENABLED +#define NRF_CRYPTO_AES_ENABLED 1 // Flag that nrf_crypto_aes frontend can be compiled +#undef NRF_CRYPTO_CC310_AES_ENABLED +#define NRF_CRYPTO_CC310_AES_ENABLED 1 + +/* define for test purposes */ +#define NRF_CRYPTO_AES_CMAC_128_ENABLED 1 + +typedef struct +{ + nrf_crypto_aes_internal_context_t header; /**< Common header for context. */ + SaSiAesUserContext_t context; /**< AES context internal to CC310. */ + nrf_crypto_backend_no_iv_aes_ctx_t backend; +} nrf_crypto_backend_aes_cmac_context_t; + +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +/** @} */ + +#endif // CC310_BACKEND_AES_H__ diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_aes_aead.c b/components/libraries/crypto/backend/cc310/cc310_backend_aes_aead.c new file mode 100644 index 0000000..8b96fb9 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_aes_aead.c @@ -0,0 +1,355 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#include +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include +#include "crys_aesccm_error.h" +#include "cc310_backend_aes_aead.h" +#include "cc310_backend_mutex.h" +#include "cc310_backend_shared.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_CC310_AES_AEAD) + +/**@internal @brief Type declaration of a template suiting all possible context sizes + * for this backend. + */ +typedef struct +{ + nrf_crypto_aead_internal_context_t header; /**< Common header for context. */ + CRYS_AESCCM_UserContext_t context; + uint8_t key[16]; /**< Only supported key size by CC310 is 128 bit */ +} nrf_crypto_backend_cc310_aes_aead_context_t; + +static ret_code_t result_get(CRYSError_t error) +{ + ret_code_t ret_val; + + switch (error) + { + case CRYS_OK: + ret_val = NRF_SUCCESS; + break; + + case CRYS_AESCCM_INVALID_USER_CONTEXT_POINTER_ERROR: + ret_val = NRF_ERROR_CRYPTO_CONTEXT_NULL; + break; + + case CRYS_AESCCM_ILLEGAL_KEY_SIZE_ERROR: + ret_val = NRF_ERROR_CRYPTO_KEY_SIZE; + break; + + case CRYS_AESCCM_ILLEGAL_TAG_SIZE_ERROR: + ret_val = NRF_ERROR_CRYPTO_AEAD_MAC_SIZE; + break; + + case CRYS_AESCCM_ILLEGAL_NONCE_SIZE_ERROR: + ret_val = NRF_ERROR_CRYPTO_AEAD_NONCE_SIZE; + break; + + case CRYS_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR: + case CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL: + ret_val = NRF_ERROR_CRYPTO_INPUT_LENGTH; + break; + + case CRYS_AESCCM_INVALID_KEY_POINTER_ERROR: + case CRYS_AESCCM_ILLEGAL_PARAMETER_PTR_ERROR: + case CRYS_AESCCM_DATA_IN_POINTER_INVALID_ERROR: + ret_val = NRF_ERROR_CRYPTO_INPUT_NULL; + break; + + case CRYS_AESCCM_IS_NOT_SUPPORTED: + case CRYS_AESCCM_INVALID_ENCRYPT_MODE_ERROR: + ret_val = NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + break; + + case CRYS_AESCCM_DATA_OUT_SIZE_INVALID_ERROR: + ret_val = NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + break; + + case CRYS_AESCCM_DATA_OUT_POINTER_INVALID_ERROR: + ret_val = NRF_ERROR_CRYPTO_OUTPUT_NULL; + break; + + case CRYS_AESCCM_ILLEGAL_PARAMETER_ERROR: + ret_val = NRF_ERROR_CRYPTO_INVALID_PARAM; + break; + + case CRYS_AESCCM_CCM_MAC_INVALID_ERROR: + ret_val = NRF_ERROR_CRYPTO_AEAD_INVALID_MAC; + break; + + case CRYS_AESCCM_CTX_SIZES_ERROR: + default: + ret_val = NRF_ERROR_CRYPTO_INTERNAL; + break; + } + return ret_val; +} + +static ret_code_t backend_cc310_init(void * const p_context, uint8_t * p_key) +{ + ret_code_t ret_val; + + nrf_crypto_backend_cc310_aes_aead_context_t * p_ctx = + (nrf_crypto_backend_cc310_aes_aead_context_t *)p_context; + + if (!nrfx_is_in_ram(p_ctx)) + { + return NRF_ERROR_CRYPTO_INPUT_LOCATION; + } + if (p_ctx->header.p_info->key_size != NRF_CRYPTO_KEY_SIZE_128) + { + return NRF_ERROR_CRYPTO_KEY_SIZE; + } + + switch (p_ctx->header.p_info->mode) + { +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CCM) + case NRF_CRYPTO_AEAD_MODE_AES_CCM: + ret_val = NRF_SUCCESS; + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CCM_STAR) + case NRF_CRYPTO_AEAD_MODE_AES_CCM_STAR: + ret_val = NRF_SUCCESS; + break; +#endif + + default: + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + } + + memcpy(p_ctx->key, p_key, sizeof(p_ctx->key)); + + return ret_val; +} + +static ret_code_t backend_cc310_uninit(void * const p_context) +{ + nrf_crypto_backend_cc310_aes_aead_context_t * p_ctx = + (nrf_crypto_backend_cc310_aes_aead_context_t *)p_context; + + memset(&p_ctx->context, 0, sizeof(CRYS_AESCCM_UserContext_t)); + + return NRF_SUCCESS; +} + +static ret_code_t backend_cc310_crypt(void * const p_context, + nrf_crypto_operation_t operation, + uint8_t * p_nonce, + uint8_t nonce_size, + uint8_t * p_adata, + size_t adata_size, + uint8_t * p_data_in, + size_t data_in_size, + uint8_t * p_data_out, + uint8_t * p_mac, + uint8_t mac_size) + +{ + uint32_t mode; + CRYSError_t result; + ret_code_t ret_val; + bool mutex_locked; + + SaSiAesEncryptMode_t operation_cc310; + CRYS_AESCCM_Mac_Res_t mac_buffer; + + nrf_crypto_backend_cc310_aes_aead_context_t * p_ctx = + (nrf_crypto_backend_cc310_aes_aead_context_t *)p_context; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + if (!nrfx_is_in_ram(p_adata) && (adata_size > 0)) + { + ret_val = NRF_ERROR_CRYPTO_INPUT_LOCATION; + goto exit; + } + + /* CC310 supports: CCM & CCM*, where nonce_size must be > 0, so p_nonce must always + point to RAM. */ + if (!nrfx_is_in_ram(p_nonce) || + !nrfx_is_in_ram(p_data_in) || + !nrfx_is_in_ram(p_data_out) || + !nrfx_is_in_ram(p_mac)) + { + ret_val = NRF_ERROR_CRYPTO_INPUT_LOCATION; + goto exit; + } + + if (operation == NRF_CRYPTO_DECRYPT) + { + operation_cc310 = SASI_AES_DECRYPT; + } + else if (operation == NRF_CRYPTO_ENCRYPT) + { + operation_cc310 = SASI_AES_ENCRYPT; + } + else + { + ret_val = NRF_ERROR_CRYPTO_INVALID_PARAM; + goto exit; + } + + if (p_ctx->header.p_info->mode == NRF_CRYPTO_AEAD_MODE_AES_CCM) + { + mode = CRYS_AESCCM_MODE_CCM; + + /* Allowed MAC size in CCM mode: [4, 6, 8, 10, 12, 14, 16] */ + if ((mac_size < NRF_CRYPTO_AES_CCM_MAC_MIN) || + (mac_size > NRF_CRYPTO_AES_CCM_MAC_MAX) || + ((mac_size & 0x01) != 0)) + { + ret_val = NRF_ERROR_CRYPTO_AEAD_MAC_SIZE; + goto exit; + } + + if ((nonce_size < NRF_CRYPTO_AES_CCM_NONCE_SIZE_MIN) || + (nonce_size > NRF_CRYPTO_AES_CCM_NONCE_SIZE_MAX)) + { + ret_val = NRF_ERROR_CRYPTO_AEAD_NONCE_SIZE; + goto exit; + } + } + else + { + mode = CRYS_AESCCM_MODE_STAR; + + /* Allowed MAC size in CCM* mode: [0, 4, 8, 16] */ + if ((mac_size | NRF_CRYPTO_AES_CCM_STAR_MAC_BITMASK) != NRF_CRYPTO_AES_CCM_STAR_MAC_BITMASK) + { + ret_val = NRF_ERROR_CRYPTO_AEAD_MAC_SIZE; + goto exit; + } + + /* Allowed nonce size in CCM* mode: [13] */ + if (nonce_size != NRF_CRYPTO_AES_CCM_STAR_NONCE_SIZE) + { + ret_val = NRF_ERROR_CRYPTO_AEAD_NONCE_SIZE; + goto exit; + } + } + + result = CC_AESCCM_Init(&p_ctx->context, + operation_cc310, + p_ctx->key, + CRYS_AES_Key128BitSize, // the only allowed key size for CC310 + (uint32_t)adata_size, + (uint32_t)data_in_size, + p_nonce, + nonce_size, + mac_size, + mode); + + ret_val = result_get(result); + + if (ret_val != NRF_SUCCESS) + { + goto exit; + } + + if ((adata_size > 0) && (p_adata != NULL)) + { + + result = CRYS_AESCCM_BlockAdata(&p_ctx->context, + p_adata, + (uint32_t)adata_size); + + ret_val = result_get(result); + + if (ret_val != NRF_SUCCESS) + { + goto exit; + } + } + + /* CC310 backend always needs 16 bytes buffer for MAC calculation. */ + memcpy(mac_buffer, p_mac, mac_size); + + result = CRYS_AESCCM_Finish(&p_ctx->context, + p_data_in, + (uint32_t)data_in_size, + p_data_out, + mac_buffer, + &mac_size); + + ret_val = result_get(result); + if (ret_val == NRF_SUCCESS) + { + memcpy(p_mac, mac_buffer, mac_size); + } + +exit: + cc310_backend_mutex_unlock(); + return ret_val; +} + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CCM) +nrf_crypto_aead_info_t const g_nrf_crypto_aes_ccm_128_info = +{ + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .mode = NRF_CRYPTO_AEAD_MODE_AES_CCM, + + .init_fn = backend_cc310_init, + .uninit_fn = backend_cc310_uninit, + .crypt_fn = backend_cc310_crypt +}; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CCM_STAR) +nrf_crypto_aead_info_t const g_nrf_crypto_aes_ccm_star_128_info = +{ + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .mode = NRF_CRYPTO_AEAD_MODE_AES_CCM_STAR, + + .init_fn = backend_cc310_init, + .uninit_fn = backend_cc310_uninit, + .crypt_fn = backend_cc310_crypt +}; +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_CC310_AES_AEAD) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) + diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_aes_aead.h b/components/libraries/crypto/backend/cc310/cc310_backend_aes_aead.h new file mode 100644 index 0000000..8f7d00a --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_aes_aead.h @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BACKEND_AES_AEAD_H__ +#define CC310_BACKEND_AES_AEAD_H__ + +/** @file + * + * @defgroup nrf_crypto_cc310_backend_aes_aead nrf_crypto CC310 backend AES AEAD + * @{ + * @ingroup nrf_crypto_cc310_backend + * + * @brief AES AEAD functionality provided by the nrf_crypto CC310 backend. + */ + +#include "sdk_config.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#include "crys_aesccm.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_types.h" +#include "nrf_crypto_aead_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_CRYPTO_CC310_AES_BACKEND_KEY_SIZE (16) + + +/* AES CCM */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CCM) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CCM) +#error "Duplicate definition of AES CCM mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_AES_CCM_ENABLED 1 +#undef NRF_CRYPTO_AEAD_ENABLED +#define NRF_CRYPTO_AEAD_ENABLED 1 // Flag that nrf_crypto_aead frontend can be compiled +#undef NRF_CRYPTO_CC310_AES_AEAD_ENABLED +#define NRF_CRYPTO_CC310_AES_AEAD_ENABLED 1 // aead backend for cc310 can be compiled + +/* define for test purposes */ +#define NRF_CRYPTO_AES_CCM_128_ENABLED 1 + +typedef struct +{ + nrf_crypto_aead_internal_context_t header; /**< Common header for context. */ + CRYS_AESCCM_UserContext_t context; /**< AES CCM context internal to CC310. */ + + uint8_t key[NRF_CRYPTO_CC310_AES_BACKEND_KEY_SIZE]; +} nrf_crypto_backend_aes_ccm_context_t; +#endif + +/* AES CCM* (CCM STAR) */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_AES_CCM_STAR) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CCM_STAR) +#error "Duplicate definition of AES CCM* (star) mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_AES_CCM_STAR_ENABLED 1 +#undef NRF_CRYPTO_AEAD_ENABLED +#define NRF_CRYPTO_AEAD_ENABLED 1 // Flag that nrf_crypto_aes_aead frontend can be compiled +#undef NRF_CRYPTO_CC310_AES_AEAD_ENABLED +#define NRF_CRYPTO_CC310_AES_AEAD_ENABLED 1 // aead backend for cc310 can be compiled + +/* define for test purposes */ +#define NRF_CRYPTO_AES_CCM_STAR_128_ENABLED 1 + +typedef struct +{ + nrf_crypto_aead_internal_context_t header; /**< Common header for context. */ + CRYS_AESCCM_UserContext_t context; /**< AES CCM context internal to CC310. */ + + uint8_t key[NRF_CRYPTO_CC310_AES_BACKEND_KEY_SIZE]; +} nrf_crypto_backend_aes_ccm_star_context_t; +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +/** @} */ + +#endif // CC310_BACKEND_AES_AEAD_H__ + diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_chacha_poly_aead.c b/components/libraries/crypto/backend/cc310/cc310_backend_chacha_poly_aead.c new file mode 100644 index 0000000..18c3726 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_chacha_poly_aead.c @@ -0,0 +1,211 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include +#include +#include "cc310_backend_mutex.h" +#include "crys_chacha_poly_error.h" +#include "cc310_backend_chacha_poly_aead.h" +#include "cc310_backend_shared.h" +#include "cc310_backend_shared.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_CC310_CHACHA_POLY_AEAD) + +static ret_code_t result_get(CRYSError_t error) +{ + ret_code_t ret_val; + + switch (error) + { + case CRYS_OK: + ret_val = NRF_SUCCESS; + break; + + /*! Invalid Additional data. */ + case CRYS_CHACHA_POLY_DATA_INVALID_ERROR: + case CRYS_CHACHA_POLY_ADATA_INVALID_ERROR: + ret_val = NRF_ERROR_CRYPTO_INPUT_NULL; + break; + + /*! Illegal encryption mode. */ + case CRYS_CHACHA_POLY_ENC_MODE_INVALID_ERROR: + ret_val = NRF_ERROR_CRYPTO_INVALID_PARAM; + break; + + /*! Illegal data size. */ + case CRYS_CHACHA_POLY_DATA_SIZE_INVALID_ERROR: + ret_val = NRF_ERROR_CRYPTO_INPUT_LENGTH; + break; + + /*! MAC comparison error. */ + case CRYS_CHACHA_POLY_MAC_ERROR: + ret_val = NRF_ERROR_CRYPTO_AEAD_INVALID_MAC; + break; + + default: + ret_val = NRF_ERROR_CRYPTO_INTERNAL; + break; + } + return ret_val; +} + +static ret_code_t backend_cc310_init(void * const p_context, uint8_t * p_key) +{ + nrf_crypto_backend_chacha_poly_context_t * p_ctx = + (nrf_crypto_backend_chacha_poly_context_t *)p_context; + + if (!nrfx_is_in_ram(p_ctx)) + { + return NRF_ERROR_CRYPTO_INPUT_LOCATION; + } + + if (p_ctx->header.p_info->key_size != NRF_CRYPTO_KEY_SIZE_256) + { + return NRF_ERROR_CRYPTO_KEY_SIZE; + } + + memcpy(p_ctx->key, p_key, sizeof(p_ctx->key)); + return NRF_SUCCESS; +} + +static inline ret_code_t backend_cc310_uninit(void * const p_context) +{ + return NRF_SUCCESS; +} + +static ret_code_t backend_cc310_crypt(void * const p_context, + nrf_crypto_operation_t operation, + uint8_t * p_nonce, + uint8_t nonce_size, + uint8_t * p_adata, + size_t adata_size, + uint8_t * p_data_in, + size_t data_in_size, + uint8_t * p_data_out, + uint8_t * p_mac, + uint8_t mac_size) + +{ + CRYSError_t result; + ret_code_t ret_val; + bool mutex_locked; + + CRYS_CHACHA_EncryptMode_t operation_cc310; + + nrf_crypto_backend_chacha_poly_context_t * p_ctx = + (nrf_crypto_backend_chacha_poly_context_t *)p_context; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + if ((adata_size == 0) || (data_in_size == 0)) + { + ret_val = NRF_ERROR_CRYPTO_INPUT_LENGTH; + goto exit; + } + + if (mac_size != NRF_CRYPTO_CHACHA_POLY_MAC_SIZE) + { + ret_val = NRF_ERROR_CRYPTO_AEAD_MAC_SIZE; + goto exit; + } + + if (nonce_size != NRF_CRYPTO_CHACHA_POLY_NONCE_SIZE) + { + ret_val = NRF_ERROR_CRYPTO_AEAD_NONCE_SIZE; + goto exit; + } + + if (!nrfx_is_in_ram(p_data_in) || !nrfx_is_in_ram(p_data_out) || + !nrfx_is_in_ram(p_mac) || !nrfx_is_in_ram(p_adata) || + !nrfx_is_in_ram(p_nonce)) + { + ret_val = NRF_ERROR_CRYPTO_INPUT_LOCATION; + goto exit; + } + + if (operation == NRF_CRYPTO_DECRYPT) + { + operation_cc310 = CRYS_CHACHA_Decrypt; + } + else if (operation == NRF_CRYPTO_ENCRYPT) + { + operation_cc310 = CRYS_CHACHA_Encrypt; + } + else + { + ret_val = NRF_ERROR_CRYPTO_INVALID_PARAM; + goto exit; + } + + result = CRYS_CHACHA_POLY(p_nonce, + p_ctx->key, + operation_cc310, + p_adata, + adata_size, + p_data_in, + data_in_size, + p_data_out, + (uint32_t *)p_mac); + + ret_val = result_get(result); + +exit: + cc310_backend_mutex_unlock(); + return ret_val; +} + +nrf_crypto_aead_info_t const g_nrf_crypto_chacha_poly_256_info = +{ + .key_size = NRF_CRYPTO_KEY_SIZE_256, + .mode = NRF_CRYPTO_AEAD_MODE_CHACHA_POLY, + + .init_fn = backend_cc310_init, + .uninit_fn = backend_cc310_uninit, + .crypt_fn = backend_cc310_crypt +}; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_CC310_CHACHA_POLY_AEAD) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) + diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_chacha_poly_aead.h b/components/libraries/crypto/backend/cc310/cc310_backend_chacha_poly_aead.h new file mode 100644 index 0000000..e5e3559 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_chacha_poly_aead.h @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BACKEND_CHACHA_POLY_AEAD_H__ +#define CC310_BACKEND_CHACHA_POLY_AEAD_H__ + +/** @file + * + * @defgroup nrf_crypto_cc310_backend_chacha_poly_aead nrf_crypto CC310 backend CHACHA_POLY AEAD + * @{ + * @ingroup nrf_crypto_cc310_backend + * + * @brief CHACHA_POLY AEAD functionality provided by the nrf_crypto CC310 backend. + */ + +#include "sdk_config.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#include "crys_chacha_poly.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_types.h" +#include "nrf_crypto_aead_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_CRYPTO_CC310_CHACHA_POLY_BACKEND_KEY_SIZE (32) + +/* CHACHA-POLY */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_CHACHA_POLY) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_CHACHA_POLY) +#error "Duplicate definition of CHACHA-POLY mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_CHACHA_POLY_ENABLED 1 +#undef NRF_CRYPTO_AEAD_ENABLED +#define NRF_CRYPTO_AEAD_ENABLED 1 // Flag that nrf_crypto_aead frontend can be compiled +#undef NRF_CRYPTO_CC310_CHACHA_POLY_AEAD_ENABLED +#define NRF_CRYPTO_CC310_CHACHA_POLY_AEAD_ENABLED 1 // aead backend for cc310 can be compiled + +/* defines for test purposes */ +#define NRF_CRYPTO_CHACHA_POLY_256_ENABLED 1 + +typedef struct +{ + nrf_crypto_aead_internal_context_t header; /**< Common header for context. */ + + uint8_t key[NRF_CRYPTO_CC310_CHACHA_POLY_BACKEND_KEY_SIZE]; +} nrf_crypto_backend_chacha_poly_context_t; +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +/** @} */ + +#endif // CC310_BACKEND_CHACHA_POLY_AEAD_H__ diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_ecc.c b/components/libraries/crypto/backend/cc310/cc310_backend_ecc.c new file mode 100644 index 0000000..3b43fec --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_ecc.c @@ -0,0 +1,708 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#include + +#include "nrf_crypto_mem.h" +#include "nrf_crypto_ecc.h" +#include "cc310_backend_ecc.h" +#include "cc310_backend_shared.h" +#include "cc310_backend_mutex.h" +#include "crys_ecpki_kg.h" +#include "crys_ecpki_domain.h" +#include "crys_ecpki_build.h" +#include "crys_ecpki_error.h" +#include "crys_rnd_error.h" +#include "crys_ec_mont_api.h" +#include "crys_ec_edw_api.h" +#include "crys_ec_mont_edw_error.h" +#include "nrf_crypto_shared.h" + + +#define CC310_UNCOMPRESSED_PUBLIC_KEY_ID_BYTE 0x04 /**< @brief @internal Byte value used by CC310 library to prefix uncompressed public key. */ + + +ret_code_t nrf_crypto_backend_cc310_ecc_error_convert(uint32_t crys_error) +{ + switch (crys_error) + { + case CRYS_OK: + return NRF_SUCCESS; + + case CRYS_ECDSA_VERIFY_INCONSISTENT_VERIFY_ERROR: + case CRYS_ECEDW_SIGN_VERIFY_FAILED_ERROR: + return NRF_ERROR_CRYPTO_ECDSA_INVALID_SIGNATURE; + + case CRYS_RND_INSTANTIATION_NOT_DONE_ERROR: + return NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED; + + default: + return NRF_ERROR_CRYPTO_INTERNAL; + } +} + + +/** @internal @brief Returns domain value from @ref CRYS_ECPKI_DomainID_t enum based on + * value from info structure. + * + * @param[in] p_info Curve info. + * @returns Pointer to CC310 domain. + */ +static CRYS_ECPKI_Domain_t const * get_domain(nrf_crypto_ecc_curve_info_t const * p_info) +{ + CRYS_ECPKI_DomainID_t domain_id = (CRYS_ECPKI_DomainID_t)(intptr_t)p_info->p_backend_data; + const CRYS_ECPKI_Domain_t * domain = CRYS_ECPKI_GetEcDomain(domain_id); + return domain; +} + + +ret_code_t nrf_crypto_backend_cc310_ecc_public_key_convert( + nrf_crypto_backend_cc310_ecc_public_key_t * p_pub, + CRYS_ECPKI_BUILD_TempData_t * p_temp_data) +{ + ret_code_t result; + CRYSError_t crys_error; + CRYS_ECPKI_Domain_t const * p_domain; + uint8_t ucompressed_key[NRF_CRYPTO_ECC_RAW_PUBLIC_KEY_MAX_SIZE + 1]; + bool mutex_locked; + + nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info; + + if (p_pub->key_converted) + { + return NRF_SUCCESS; + } + + p_domain = get_domain(p_info); + + // Tell CC310 library that this is raw public key in uncompressed format. + ucompressed_key[0] = CC310_UNCOMPRESSED_PUBLIC_KEY_ID_BYTE; + memcpy(&ucompressed_key[1], p_pub->key.raw_public_key, p_info->raw_public_key_size); + + mutex_locked = cc310_backend_mutex_trylock(); + if (!mutex_locked) + { + return NRF_ERROR_CRYPTO_BUSY; + } + + crys_error = CRYS_ECPKI_BuildPublKeyPartlyCheck(p_domain, + ucompressed_key, + p_info->raw_public_key_size + 1, + &p_pub->key.cc310_public_key, + p_temp_data); + + cc310_backend_mutex_unlock(); + + result = nrf_crypto_backend_cc310_ecc_error_convert(crys_error); + if (result == NRF_SUCCESS) + { + p_pub->key_converted = true; + } + else + { + memcpy(p_pub->key.raw_public_key, &ucompressed_key[1], p_info->raw_public_key_size); + } + + return result; +} + + +ret_code_t nrf_crypto_backend_cc310_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key) +{ + ret_code_t result; + CRYSError_t crys_error; + CRYS_ECPKI_Domain_t const * p_domain; + bool mutex_locked; + + nrf_crypto_backend_cc310_key_pair_generate_context_t * p_ctx = + (nrf_crypto_backend_cc310_key_pair_generate_context_t *)p_context; + + nrf_crypto_backend_cc310_ecc_private_key_t * p_prv = + (nrf_crypto_backend_cc310_ecc_private_key_t *)p_private_key; + + nrf_crypto_backend_cc310_ecc_public_key_t * p_pub = + (nrf_crypto_backend_cc310_ecc_public_key_t *)p_public_key; + + p_domain = get_domain(p_prv->header.p_info); + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + crys_error = CRYS_ECPKI_GenKeyPair(p_context, + nrf_crypto_backend_cc310_rng, + p_domain, + &p_prv->private_key, + &p_pub->key.cc310_public_key, + &p_ctx->temp_data, + NULL); + + cc310_backend_mutex_unlock(); + + p_pub->key_converted = true; + + result = nrf_crypto_backend_cc310_ecc_error_convert(crys_error); + return result; +} + + +ret_code_t nrf_crypto_backend_cc310_private_key_from_raw( + void * p_private_key, + uint8_t const * p_raw_data) +{ + ret_code_t result; + CRYSError_t crys_error; + CRYS_ECPKI_Domain_t const * p_domain; + bool mutex_locked; + + nrf_crypto_backend_cc310_ecc_private_key_t * p_prv = + (nrf_crypto_backend_cc310_ecc_private_key_t *)p_private_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info; + + p_domain = get_domain(p_info); + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + crys_error = CRYS_ECPKI_BuildPrivKey(p_domain, + p_raw_data, + p_info->raw_private_key_size, + &p_prv->private_key); + + cc310_backend_mutex_unlock(); + + result = nrf_crypto_backend_cc310_ecc_error_convert(crys_error); + return result; +} + + +ret_code_t nrf_crypto_backend_cc310_private_key_to_raw( + void const * p_private_key, + uint8_t * p_raw_data) +{ + ret_code_t result; + CRYSError_t crys_error; + uint32_t key_size; + + nrf_crypto_backend_cc310_ecc_private_key_t * p_prv = + (nrf_crypto_backend_cc310_ecc_private_key_t *)p_private_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info; + + key_size = p_info->raw_private_key_size; + + crys_error = CRYS_ECPKI_ExportPrivKey(&p_prv->private_key, + p_raw_data, + &key_size); + + if (key_size != p_info->raw_private_key_size) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + result = nrf_crypto_backend_cc310_ecc_error_convert(crys_error); + + return result; +} + + +ret_code_t nrf_crypto_backend_cc310_public_key_from_raw( + void * p_public_key, + uint8_t const * p_raw_data) +{ + nrf_crypto_backend_cc310_ecc_public_key_t * p_pub = + (nrf_crypto_backend_cc310_ecc_public_key_t *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info; + + memcpy(p_pub->key.raw_public_key, p_raw_data, p_info->raw_public_key_size); + p_pub->key_converted = false; + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_cc310_public_key_to_raw( + void const * p_public_key, + uint8_t * p_raw_data) +{ + ret_code_t result; + CRYSError_t crys_error; + uint8_t ucompressed_key[NRF_CRYPTO_ECC_RAW_PUBLIC_KEY_MAX_SIZE + 1]; + uint32_t key_size; + bool mutex_locked; + + nrf_crypto_backend_cc310_ecc_public_key_t * p_pub = + (nrf_crypto_backend_cc310_ecc_public_key_t *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info; + + if (!p_pub->key_converted) + { + memcpy(p_raw_data, p_pub->key.raw_public_key, p_info->raw_public_key_size); + return NRF_SUCCESS; + } + + mutex_locked = cc310_backend_mutex_trylock(); + if (!mutex_locked) + { + return NRF_ERROR_CRYPTO_BUSY; + } + + key_size = p_info->raw_public_key_size + 1; + + crys_error = CRYS_ECPKI_ExportPublKey(&p_pub->key.cc310_public_key, + CRYS_EC_PointUncompressed, + ucompressed_key, + &key_size); + + cc310_backend_mutex_unlock(); + + if ((key_size != p_info->raw_public_key_size + 1) + || (ucompressed_key[0] != CC310_UNCOMPRESSED_PUBLIC_KEY_ID_BYTE)) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + memcpy(p_raw_data, &ucompressed_key[1], p_info->raw_public_key_size); + + result = nrf_crypto_backend_cc310_ecc_error_convert(crys_error); + return result; +} + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519) + +ret_code_t nrf_crypto_backend_cc310_curve25519_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key) +{ + ret_code_t result; + CRYSError_t crys_error; + bool mutex_locked; + + nrf_crypto_backend_cc310_curve25519_context_t * p_ctx = + (nrf_crypto_backend_cc310_curve25519_context_t *)p_context; + + nrf_crypto_backend_curve25519_private_key_t * p_prv = + (nrf_crypto_backend_curve25519_private_key_t *)p_private_key; + + nrf_crypto_backend_curve25519_public_key_t * p_pub = + (nrf_crypto_backend_curve25519_public_key_t *)p_public_key; + + size_t pub_key_size = sizeof(p_pub->key); + size_t prv_key_size = sizeof(p_prv->key); + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + crys_error = CRYS_ECMONT_KeyPair(p_pub->key, + &pub_key_size, + p_prv->key, + &prv_key_size, + p_context, + nrf_crypto_backend_cc310_rng, + &p_ctx->temp_data); + + cc310_backend_mutex_unlock(); + + result = nrf_crypto_backend_cc310_ecc_error_convert(crys_error); + return result; +} + + +ret_code_t nrf_crypto_backend_cc310_curve25519_key_from_raw( + void * p_key, + uint8_t const * p_raw_data) +{ + nrf_crypto_backend_curve25519_key_t * p_internal_key = + (nrf_crypto_backend_curve25519_key_t *)p_key; + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_CURVE25519_BIG_ENDIAN) + nrf_crypto_internal_swap_endian(p_internal_key->key, p_raw_data, sizeof(p_internal_key->key)); +#else + memcpy(p_internal_key->key, p_raw_data, sizeof(p_internal_key->key)); +#endif + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_cc310_curve25519_key_to_raw( + void const * p_key, + uint8_t * p_raw_data) +{ + nrf_crypto_backend_curve25519_key_t * p_internal_key = + (nrf_crypto_backend_curve25519_key_t *)p_key; + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_CURVE25519_BIG_ENDIAN) + nrf_crypto_internal_swap_endian(p_raw_data, p_internal_key->key, sizeof(p_internal_key->key)); +#else + memcpy(p_raw_data, p_internal_key->key, sizeof(p_internal_key->key)); +#endif + + return NRF_SUCCESS; +} + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_ED25519) + +ret_code_t nrf_crypto_backend_cc310_ed25519_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key) +{ + ret_code_t result; + CRYSError_t crys_error; + bool mutex_locked; + + nrf_crypto_backend_cc310_ed25519_context_t * p_ctx = + (nrf_crypto_backend_cc310_ed25519_context_t *)p_context; + + nrf_crypto_backend_ed25519_private_key_t * p_prv = + (nrf_crypto_backend_ed25519_private_key_t *)p_private_key; + + nrf_crypto_backend_ed25519_public_key_t * p_pub = + (nrf_crypto_backend_ed25519_public_key_t *)p_public_key; + + size_t pub_key_size = sizeof(p_pub->key); + size_t prv_key_size = sizeof(p_prv->key); + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + crys_error = CRYS_ECEDW_KeyPair(p_prv->key, + &prv_key_size, + p_pub->key, + &pub_key_size, + p_context, + nrf_crypto_backend_cc310_rng, + &p_ctx->temp_data); + + cc310_backend_mutex_unlock(); + + result = nrf_crypto_backend_cc310_ecc_error_convert(crys_error); + return result; +} + + +ret_code_t nrf_crypto_backend_cc310_ed25519_private_key_from_raw( + void * p_key, + uint8_t const * p_raw_data) +{ + uint8_t pub_key_dummy[CRYS_ECEDW_ORD_SIZE_IN_BYTES]; // Throw away buffer + CRYSError_t crys_error; + bool mutex_locked; + ret_code_t result; + CRYS_ECEDW_TempBuff_t * p_temp_data = NULL; + + nrf_crypto_backend_ed25519_private_key_t * p_internal_prv_key = + (nrf_crypto_backend_ed25519_private_key_t *)p_key; + + size_t prv_key_size = sizeof(p_internal_prv_key->key); + size_t pub_key_size = sizeof(pub_key_dummy); + + // Generate public key using CRYS_ECEDW_SeedKeyPair + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + // Use memory allocation (instead of stack) for the temporary data, as it is ~700 bytes. + p_temp_data = NRF_CRYPTO_ALLOC(sizeof(CRYS_ECEDW_TempBuff_t)); + if (p_temp_data == NULL) + { + return NRF_ERROR_CRYPTO_ALLOC_FAILED; + } + + crys_error = CRYS_ECEDW_SeedKeyPair(p_raw_data, + CRYS_ECEDW_ORD_SIZE_IN_BYTES, + p_internal_prv_key->key, + &prv_key_size, + pub_key_dummy, + &pub_key_size, + p_temp_data); + + cc310_backend_mutex_unlock(); + + NRF_CRYPTO_FREE(p_temp_data); + + result = nrf_crypto_backend_cc310_ecc_error_convert(crys_error); + return result; +} + + +ret_code_t nrf_crypto_backend_cc310_ed25519_private_key_to_raw( + void const * p_key, + uint8_t * p_raw_data) +{ + nrf_crypto_backend_ed25519_private_key_t * p_internal_key = + (nrf_crypto_backend_ed25519_private_key_t *)p_key; + + memcpy(p_raw_data, p_internal_key->key, CRYS_ECEDW_ORD_SIZE_IN_BYTES); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_cc310_ed25519_public_key_from_raw( + void * p_key, + uint8_t const * p_raw_data) +{ + nrf_crypto_backend_ed25519_public_key_t * p_internal_key = + (nrf_crypto_backend_ed25519_public_key_t *)p_key; + + memcpy(p_internal_key->key, p_raw_data, sizeof(p_internal_key->key)); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_cc310_ed25519_public_key_to_raw( + void const * p_key, + uint8_t * p_raw_data) +{ + nrf_crypto_backend_ed25519_public_key_t * p_internal_key = + (nrf_crypto_backend_ed25519_public_key_t *)p_key; + + memcpy(p_raw_data, p_internal_key->key, sizeof(p_internal_key->key)); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_ed25519_public_key_calculate( + void * p_context, + void const * p_private_key, + void * p_public_key) +{ + nrf_crypto_backend_ed25519_private_key_t * p_prv = + (nrf_crypto_backend_ed25519_private_key_t *)p_private_key; + + nrf_crypto_backend_ed25519_public_key_t * p_pub = + (nrf_crypto_backend_ed25519_public_key_t *)p_public_key; + + memcpy(p_pub->key, p_prv->key+CRYS_ECEDW_ORD_SIZE_IN_BYTES, CRYS_ECEDW_ORD_SIZE_IN_BYTES); + + return NRF_SUCCESS; +} + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_ED25519) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp160r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_cc310_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_cc310_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP160R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP160R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP160R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)CRYS_ECPKI_DomainID_secp160r1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R2) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp160r2_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_cc310_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_cc310_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP160R2_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP160R2_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP160R2_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)CRYS_ECPKI_DomainID_secp160r2, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP192R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp192r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_cc310_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_cc310_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP192R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP192R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP192R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)CRYS_ECPKI_DomainID_secp192r1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP224R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp224r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_cc310_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_cc310_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP224R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP224R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)CRYS_ECPKI_DomainID_secp224r1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP256R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp256r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_cc310_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_cc310_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP256R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)CRYS_ECPKI_DomainID_secp256r1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP384R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp384r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_cc310_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_cc310_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP384R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP384R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP384R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)CRYS_ECPKI_DomainID_secp384r1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP521R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp521r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_cc310_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_cc310_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP521R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP521R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP521R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)CRYS_ECPKI_DomainID_secp521r1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160K1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp160k1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_cc310_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_cc310_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP160K1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP160K1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP160K1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)CRYS_ECPKI_DomainID_secp160k1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP192K1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp192k1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_cc310_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_cc310_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP192K1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP192K1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP192K1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)CRYS_ECPKI_DomainID_secp192k1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP224K1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp224k1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_cc310_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_cc310_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP224K1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP224K1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP224K1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)CRYS_ECPKI_DomainID_secp224k1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP256K1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp256k1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_cc310_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_cc310_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP256K1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP256K1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP256K1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)CRYS_ECPKI_DomainID_secp256k1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_curve25519_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_curve25519_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_curve25519_private_key_t), + .curve_type = NRF_CRYPTO_ECC_CURVE25519_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_CURVE25519_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_CURVE25519_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)CRYS_ECMONT_DOMAIN_CURVE_25519, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_ED25519) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_ed25519_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_ed25519_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_ed25519_private_key_t), + .curve_type = NRF_CRYPTO_ECC_ED25519_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_ED25519_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_ED25519_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = NULL, +}; +#endif + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_ecc.h b/components/libraries/crypto/backend/cc310/cc310_backend_ecc.h new file mode 100644 index 0000000..d09104d --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_ecc.h @@ -0,0 +1,734 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BACKEND_ECC_H__ +#define CC310_BACKEND_ECC_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#include +#include "nrf_crypto_ecc_shared.h" +#include "crys_ecpki_kg.h" +#include "crys_ec_mont_api.h" +#include "crys_ec_edw_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @internal @brief Common structure holding private key for CC310. + * + * @details Used for most curves (except Curve25519 and Ed25519). + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + CRYS_ECPKI_UserPrivKey_t private_key; /**< @internal @brief CC310 specific key representation */ +} nrf_crypto_backend_cc310_ecc_private_key_t; + + +/** @internal @brief Common structure holding public key for CC310. + * + * @details Used for most curves (except Curve25519 and Ed25519). + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + bool key_converted; /**< @internal @brief True if key was already converted from raw_public_key to cc310_public_key */ + union + { + CRYS_ECPKI_UserPublKey_t cc310_public_key; /**< @internal @brief CC310 specific key representation */ + uint8_t raw_public_key[132]; /**< @internal @brief raw key representation */ + } key; +} nrf_crypto_backend_cc310_ecc_public_key_t; + + +/** @internal @brief Common structure holding context for key pair generation. + * + * @details Used for most curves (except Curve25519 and Ed25519). + */ +typedef struct +{ + CRYS_ECPKI_KG_TempData_t temp_data; /**< @internal @brief Temporary buffer for CC310 internal storage */ +} nrf_crypto_backend_cc310_key_pair_generate_context_t; + + +/** @internal See @ref nrf_crypto_backend_ecc_key_pair_generate_fn_t. + * + * @details Used for most curves (except Curve25519 and Ed25519). + */ +ret_code_t nrf_crypto_backend_cc310_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key); + + +/** @internal See @ref nrf_crypto_backend_ecc_private_key_from_raw_fn_t. + * + * @details Used for most curves (except Curve25519 and Ed25519). +*/ +ret_code_t nrf_crypto_backend_cc310_private_key_from_raw( + void * p_private_key, + uint8_t const * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_private_key_to_raw_fn_t. + * + * @details Used for most curves (except Curve25519 and Ed25519). +*/ +ret_code_t nrf_crypto_backend_cc310_private_key_to_raw( + void const * p_private_key, + uint8_t * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_from_raw_fn_t. + * + * @details Used for most curves (except Curve25519 and Ed25519). +*/ +ret_code_t nrf_crypto_backend_cc310_public_key_from_raw( + void * p_public_key, + uint8_t const * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_to_raw_fn_t. + * + * @details Used for most curves (except Curve25519 and Ed25519). +*/ +ret_code_t nrf_crypto_backend_cc310_public_key_to_raw( + void const * p_public_key, + uint8_t * p_raw_data); + + +/** @internal @brief Convert error code from CC310 to nrf_crypto error code. + * + * @param[in] crys_error CC310 error code. + * @return nrf_crypto error code. + */ +ret_code_t nrf_crypto_backend_cc310_ecc_error_convert(uint32_t crys_error); + + +/** @internal @brief Converts public key from raw to CC310 representation if not converted already. + * + * Data are read from p_pub->key.raw_public_key to stored into p_pub->cc310_public_key. + * + * @param[in] p_pub Public key to convert. + * @param[in] p_temp_data Buffer for temporary data used by CC310 lib. + * @return nrf_crypto error code. + */ +ret_code_t nrf_crypto_backend_cc310_ecc_public_key_convert( + nrf_crypto_backend_cc310_ecc_public_key_t * p_pub, + CRYS_ECPKI_BUILD_TempData_t * p_temp_data); + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP160R1) +#error "More than one backend enabled for secp160r1 (NIST 160-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP160R1_ENABLED 1 + +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp160r1_key_pair_generate nrf_crypto_backend_cc310_key_pair_generate +#define nrf_crypto_backend_secp160r1_public_key_calculate NULL +#define nrf_crypto_backend_secp160r1_private_key_from_raw nrf_crypto_backend_cc310_private_key_from_raw +#define nrf_crypto_backend_secp160r1_private_key_to_raw nrf_crypto_backend_cc310_private_key_to_raw +#define nrf_crypto_backend_secp160r1_public_key_from_raw nrf_crypto_backend_cc310_public_key_from_raw +#define nrf_crypto_backend_secp160r1_public_key_to_raw nrf_crypto_backend_cc310_public_key_to_raw +#define nrf_crypto_backend_secp160r1_private_key_free NULL +#define nrf_crypto_backend_secp160r1_public_key_free NULL + +// Context sizes required by CC310 +#define NRF_CRYPTO_BACKEND_SECP160R1_KEY_PAIR_GENERATE_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_key_pair_generate_context_t) +#define NRF_CRYPTO_BACKEND_SECP160R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Most CC310 curve types share the same data structures for keys +typedef nrf_crypto_backend_cc310_ecc_private_key_t nrf_crypto_backend_secp160r1_private_key_t; +typedef nrf_crypto_backend_cc310_ecc_public_key_t nrf_crypto_backend_secp160r1_public_key_t; + +// Most CC310 curve types share the same data structures for context +typedef nrf_crypto_backend_cc310_key_pair_generate_context_t + nrf_crypto_backend_secp160r1_key_pair_generate_context_t; + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp160r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R2) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP160R2) +#error "More than one backend enabled for secp160r2 (NIST 160-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP160R2_ENABLED 1 + +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp160r2_key_pair_generate nrf_crypto_backend_cc310_key_pair_generate +#define nrf_crypto_backend_secp160r2_public_key_calculate NULL +#define nrf_crypto_backend_secp160r2_private_key_from_raw nrf_crypto_backend_cc310_private_key_from_raw +#define nrf_crypto_backend_secp160r2_private_key_to_raw nrf_crypto_backend_cc310_private_key_to_raw +#define nrf_crypto_backend_secp160r2_public_key_from_raw nrf_crypto_backend_cc310_public_key_from_raw +#define nrf_crypto_backend_secp160r2_public_key_to_raw nrf_crypto_backend_cc310_public_key_to_raw +#define nrf_crypto_backend_secp160r2_private_key_free NULL +#define nrf_crypto_backend_secp160r2_public_key_free NULL + +// Context sizes required by CC310 +#define NRF_CRYPTO_BACKEND_SECP160R2_KEY_PAIR_GENERATE_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_key_pair_generate_context_t) +#define NRF_CRYPTO_BACKEND_SECP160R2_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Most CC310 curve types share the same data structures for keys +typedef nrf_crypto_backend_cc310_ecc_private_key_t nrf_crypto_backend_secp160r2_private_key_t; +typedef nrf_crypto_backend_cc310_ecc_public_key_t nrf_crypto_backend_secp160r2_public_key_t; + +// Most CC310 curve types share the same data structures for context +typedef nrf_crypto_backend_cc310_key_pair_generate_context_t + nrf_crypto_backend_secp160r2_key_pair_generate_context_t; + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp160r2_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R2) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP192R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP192R1) +#error "More than one backend enabled for secp192r1 (NIST 192-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP192R1_ENABLED 1 + +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp192r1_key_pair_generate nrf_crypto_backend_cc310_key_pair_generate +#define nrf_crypto_backend_secp192r1_public_key_calculate NULL +#define nrf_crypto_backend_secp192r1_private_key_from_raw nrf_crypto_backend_cc310_private_key_from_raw +#define nrf_crypto_backend_secp192r1_private_key_to_raw nrf_crypto_backend_cc310_private_key_to_raw +#define nrf_crypto_backend_secp192r1_public_key_from_raw nrf_crypto_backend_cc310_public_key_from_raw +#define nrf_crypto_backend_secp192r1_public_key_to_raw nrf_crypto_backend_cc310_public_key_to_raw +#define nrf_crypto_backend_secp192r1_private_key_free NULL +#define nrf_crypto_backend_secp192r1_public_key_free NULL + +// Context sizes required by CC310 +#define NRF_CRYPTO_BACKEND_SECP192R1_KEY_PAIR_GENERATE_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_key_pair_generate_context_t) +#define NRF_CRYPTO_BACKEND_SECP192R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Most CC310 curve types share the same data structures for keys +typedef nrf_crypto_backend_cc310_ecc_private_key_t nrf_crypto_backend_secp192r1_private_key_t; +typedef nrf_crypto_backend_cc310_ecc_public_key_t nrf_crypto_backend_secp192r1_public_key_t; + +// Most CC310 curve types share the same data structures for context +typedef nrf_crypto_backend_cc310_key_pair_generate_context_t + nrf_crypto_backend_secp192r1_key_pair_generate_context_t; + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp192r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP192R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP224R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP224R1) +#error "More than one backend enabled for secp224r1 (NIST 224-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP224R1_ENABLED 1 + +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp224r1_key_pair_generate nrf_crypto_backend_cc310_key_pair_generate +#define nrf_crypto_backend_secp224r1_public_key_calculate NULL +#define nrf_crypto_backend_secp224r1_private_key_from_raw nrf_crypto_backend_cc310_private_key_from_raw +#define nrf_crypto_backend_secp224r1_private_key_to_raw nrf_crypto_backend_cc310_private_key_to_raw +#define nrf_crypto_backend_secp224r1_public_key_from_raw nrf_crypto_backend_cc310_public_key_from_raw +#define nrf_crypto_backend_secp224r1_public_key_to_raw nrf_crypto_backend_cc310_public_key_to_raw +#define nrf_crypto_backend_secp224r1_private_key_free NULL +#define nrf_crypto_backend_secp224r1_public_key_free NULL + +// Context sizes required by CC310 +#define NRF_CRYPTO_BACKEND_SECP224R1_KEY_PAIR_GENERATE_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_key_pair_generate_context_t) +#define NRF_CRYPTO_BACKEND_SECP224R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Most CC310 curve types share the same data structures for keys +typedef nrf_crypto_backend_cc310_ecc_private_key_t nrf_crypto_backend_secp224r1_private_key_t; +typedef nrf_crypto_backend_cc310_ecc_public_key_t nrf_crypto_backend_secp224r1_public_key_t; + +// Most CC310 curve types share the same data structures for context +typedef nrf_crypto_backend_cc310_key_pair_generate_context_t + nrf_crypto_backend_secp224r1_key_pair_generate_context_t; + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp224r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP224R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP256R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP256R1) +#error "More than one backend enabled for secp256r1 (NIST 256-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP256R1_ENABLED 1 + +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp256r1_key_pair_generate nrf_crypto_backend_cc310_key_pair_generate +#define nrf_crypto_backend_secp256r1_public_key_calculate NULL +#define nrf_crypto_backend_secp256r1_private_key_from_raw nrf_crypto_backend_cc310_private_key_from_raw +#define nrf_crypto_backend_secp256r1_private_key_to_raw nrf_crypto_backend_cc310_private_key_to_raw +#define nrf_crypto_backend_secp256r1_public_key_from_raw nrf_crypto_backend_cc310_public_key_from_raw +#define nrf_crypto_backend_secp256r1_public_key_to_raw nrf_crypto_backend_cc310_public_key_to_raw +#define nrf_crypto_backend_secp256r1_private_key_free NULL +#define nrf_crypto_backend_secp256r1_public_key_free NULL + +// Context sizes required by CC310 +#define NRF_CRYPTO_BACKEND_SECP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_key_pair_generate_context_t) +#define NRF_CRYPTO_BACKEND_SECP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Most CC310 curve types share the same data structures for keys +typedef nrf_crypto_backend_cc310_ecc_private_key_t nrf_crypto_backend_secp256r1_private_key_t; +typedef nrf_crypto_backend_cc310_ecc_public_key_t nrf_crypto_backend_secp256r1_public_key_t; + +// Most CC310 curve types share the same data structures for context +typedef nrf_crypto_backend_cc310_key_pair_generate_context_t + nrf_crypto_backend_secp256r1_key_pair_generate_context_t; + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp256r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP256R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP384R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP384R1) +#error "More than one backend enabled for secp384r1 (NIST 384-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP384R1_ENABLED 1 + +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp384r1_key_pair_generate nrf_crypto_backend_cc310_key_pair_generate +#define nrf_crypto_backend_secp384r1_public_key_calculate NULL +#define nrf_crypto_backend_secp384r1_private_key_from_raw nrf_crypto_backend_cc310_private_key_from_raw +#define nrf_crypto_backend_secp384r1_private_key_to_raw nrf_crypto_backend_cc310_private_key_to_raw +#define nrf_crypto_backend_secp384r1_public_key_from_raw nrf_crypto_backend_cc310_public_key_from_raw +#define nrf_crypto_backend_secp384r1_public_key_to_raw nrf_crypto_backend_cc310_public_key_to_raw +#define nrf_crypto_backend_secp384r1_private_key_free NULL +#define nrf_crypto_backend_secp384r1_public_key_free NULL + +// Context sizes required by CC310 +#define NRF_CRYPTO_BACKEND_SECP384R1_KEY_PAIR_GENERATE_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_key_pair_generate_context_t) +#define NRF_CRYPTO_BACKEND_SECP384R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Most CC310 curve types share the same data structures for keys +typedef nrf_crypto_backend_cc310_ecc_private_key_t nrf_crypto_backend_secp384r1_private_key_t; +typedef nrf_crypto_backend_cc310_ecc_public_key_t nrf_crypto_backend_secp384r1_public_key_t; + +// Most CC310 curve types share the same data structures for context +typedef nrf_crypto_backend_cc310_key_pair_generate_context_t + nrf_crypto_backend_secp384r1_key_pair_generate_context_t; + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp384r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP384R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP521R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP521R1) +#error "More than one backend enabled for secp521r1 (NIST 521-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP521R1_ENABLED 1 + +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp521r1_key_pair_generate nrf_crypto_backend_cc310_key_pair_generate +#define nrf_crypto_backend_secp521r1_public_key_calculate NULL +#define nrf_crypto_backend_secp521r1_private_key_from_raw nrf_crypto_backend_cc310_private_key_from_raw +#define nrf_crypto_backend_secp521r1_private_key_to_raw nrf_crypto_backend_cc310_private_key_to_raw +#define nrf_crypto_backend_secp521r1_public_key_from_raw nrf_crypto_backend_cc310_public_key_from_raw +#define nrf_crypto_backend_secp521r1_public_key_to_raw nrf_crypto_backend_cc310_public_key_to_raw +#define nrf_crypto_backend_secp521r1_private_key_free NULL +#define nrf_crypto_backend_secp521r1_public_key_free NULL + +// Context sizes required by CC310 +#define NRF_CRYPTO_BACKEND_SECP521R1_KEY_PAIR_GENERATE_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_key_pair_generate_context_t) +#define NRF_CRYPTO_BACKEND_SECP521R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Most CC310 curve types share the same data structures for keys +typedef nrf_crypto_backend_cc310_ecc_private_key_t nrf_crypto_backend_secp521r1_private_key_t; +typedef nrf_crypto_backend_cc310_ecc_public_key_t nrf_crypto_backend_secp521r1_public_key_t; + +// Most CC310 curve types share the same data structures for context +typedef nrf_crypto_backend_cc310_key_pair_generate_context_t + nrf_crypto_backend_secp521r1_key_pair_generate_context_t; + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp521r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP521R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160K1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP160K1) +#error "More than one backend enabled for secp160k1 (Koblitz 160-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP160K1_ENABLED 1 + +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp160k1_key_pair_generate nrf_crypto_backend_cc310_key_pair_generate +#define nrf_crypto_backend_secp160k1_public_key_calculate NULL +#define nrf_crypto_backend_secp160k1_private_key_from_raw nrf_crypto_backend_cc310_private_key_from_raw +#define nrf_crypto_backend_secp160k1_private_key_to_raw nrf_crypto_backend_cc310_private_key_to_raw +#define nrf_crypto_backend_secp160k1_public_key_from_raw nrf_crypto_backend_cc310_public_key_from_raw +#define nrf_crypto_backend_secp160k1_public_key_to_raw nrf_crypto_backend_cc310_public_key_to_raw +#define nrf_crypto_backend_secp160k1_private_key_free NULL +#define nrf_crypto_backend_secp160k1_public_key_free NULL + +// Context sizes required by CC310 +#define NRF_CRYPTO_BACKEND_SECP160K1_KEY_PAIR_GENERATE_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_key_pair_generate_context_t) +#define NRF_CRYPTO_BACKEND_SECP160K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Most CC310 curve types share the same data structures for keys +typedef nrf_crypto_backend_cc310_ecc_private_key_t nrf_crypto_backend_secp160k1_private_key_t; +typedef nrf_crypto_backend_cc310_ecc_public_key_t nrf_crypto_backend_secp160k1_public_key_t; + +// Most CC310 curve types share the same data structures for context +typedef nrf_crypto_backend_cc310_key_pair_generate_context_t + nrf_crypto_backend_secp160k1_key_pair_generate_context_t; + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp160k1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160K1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP192K1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP192K1) +#error "More than one backend enabled for secp192k1 (Koblitz 192-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP192K1_ENABLED 1 + +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp192k1_key_pair_generate nrf_crypto_backend_cc310_key_pair_generate +#define nrf_crypto_backend_secp192k1_public_key_calculate NULL +#define nrf_crypto_backend_secp192k1_private_key_from_raw nrf_crypto_backend_cc310_private_key_from_raw +#define nrf_crypto_backend_secp192k1_private_key_to_raw nrf_crypto_backend_cc310_private_key_to_raw +#define nrf_crypto_backend_secp192k1_public_key_from_raw nrf_crypto_backend_cc310_public_key_from_raw +#define nrf_crypto_backend_secp192k1_public_key_to_raw nrf_crypto_backend_cc310_public_key_to_raw +#define nrf_crypto_backend_secp192k1_private_key_free NULL +#define nrf_crypto_backend_secp192k1_public_key_free NULL + +// Context sizes required by CC310 +#define NRF_CRYPTO_BACKEND_SECP192K1_KEY_PAIR_GENERATE_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_key_pair_generate_context_t) +#define NRF_CRYPTO_BACKEND_SECP192K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Most CC310 curve types share the same data structures for keys +typedef nrf_crypto_backend_cc310_ecc_private_key_t nrf_crypto_backend_secp192k1_private_key_t; +typedef nrf_crypto_backend_cc310_ecc_public_key_t nrf_crypto_backend_secp192k1_public_key_t; + +// Most CC310 curve types share the same data structures for context +typedef nrf_crypto_backend_cc310_key_pair_generate_context_t + nrf_crypto_backend_secp192k1_key_pair_generate_context_t; + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp192k1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP192K1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP224K1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP224K1) +#error "More than one backend enabled for secp224k1 (Koblitz 224-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP224K1_ENABLED 1 + +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp224k1_key_pair_generate nrf_crypto_backend_cc310_key_pair_generate +#define nrf_crypto_backend_secp224k1_public_key_calculate NULL +#define nrf_crypto_backend_secp224k1_private_key_from_raw nrf_crypto_backend_cc310_private_key_from_raw +#define nrf_crypto_backend_secp224k1_private_key_to_raw nrf_crypto_backend_cc310_private_key_to_raw +#define nrf_crypto_backend_secp224k1_public_key_from_raw nrf_crypto_backend_cc310_public_key_from_raw +#define nrf_crypto_backend_secp224k1_public_key_to_raw nrf_crypto_backend_cc310_public_key_to_raw +#define nrf_crypto_backend_secp224k1_private_key_free NULL +#define nrf_crypto_backend_secp224k1_public_key_free NULL + +// Context sizes required by CC310 +#define NRF_CRYPTO_BACKEND_SECP224K1_KEY_PAIR_GENERATE_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_key_pair_generate_context_t) +#define NRF_CRYPTO_BACKEND_SECP224K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Most CC310 curve types share the same data structures for keys +typedef nrf_crypto_backend_cc310_ecc_private_key_t nrf_crypto_backend_secp224k1_private_key_t; +typedef nrf_crypto_backend_cc310_ecc_public_key_t nrf_crypto_backend_secp224k1_public_key_t; + +// Most CC310 curve types share the same data structures for context +typedef nrf_crypto_backend_cc310_key_pair_generate_context_t + nrf_crypto_backend_secp224k1_key_pair_generate_context_t; + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp224k1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP224K1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP256K1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP256K1) +#error "More than one backend enabled for secp256k1 (Koblitz 256-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP256K1_ENABLED 1 + +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp256k1_key_pair_generate nrf_crypto_backend_cc310_key_pair_generate +#define nrf_crypto_backend_secp256k1_public_key_calculate NULL +#define nrf_crypto_backend_secp256k1_private_key_from_raw nrf_crypto_backend_cc310_private_key_from_raw +#define nrf_crypto_backend_secp256k1_private_key_to_raw nrf_crypto_backend_cc310_private_key_to_raw +#define nrf_crypto_backend_secp256k1_public_key_from_raw nrf_crypto_backend_cc310_public_key_from_raw +#define nrf_crypto_backend_secp256k1_public_key_to_raw nrf_crypto_backend_cc310_public_key_to_raw +#define nrf_crypto_backend_secp256k1_private_key_free NULL +#define nrf_crypto_backend_secp256k1_public_key_free NULL + +// Context sizes required by CC310 +#define NRF_CRYPTO_BACKEND_SECP256K1_KEY_PAIR_GENERATE_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_key_pair_generate_context_t) +#define NRF_CRYPTO_BACKEND_SECP256K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Most CC310 curve types share the same data structures for keys +typedef nrf_crypto_backend_cc310_ecc_private_key_t nrf_crypto_backend_secp256k1_private_key_t; +typedef nrf_crypto_backend_cc310_ecc_public_key_t nrf_crypto_backend_secp256k1_public_key_t; + +// Most CC310 curve types share the same data structures for context +typedef nrf_crypto_backend_cc310_key_pair_generate_context_t + nrf_crypto_backend_secp256k1_key_pair_generate_context_t; + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp256k1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP256K1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_CURVE25519) +#error "More than one backend enabled for Curve25519."); +#endif +#define NRF_CRYPTO_ECC_CURVE25519_ENABLED 1 + +/** @internal @brief Common structure holding context for Curve25519 (all operations). + */ +typedef struct +{ + CRYS_ECMONT_TempBuff_t temp_data; /**< @internal @brief Temporary buffer for CC310 internal storage */ +} nrf_crypto_backend_cc310_curve25519_context_t; + +/** @internal @brief Structure holding keys for Curve25519. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header. */ + uint8_t key[32]; /**< @internal @brief Raw key in little-endian order. */ +} nrf_crypto_backend_curve25519_key_t; + +// Most CC310 curve types share the same data structures for keys +typedef nrf_crypto_backend_curve25519_key_t nrf_crypto_backend_curve25519_private_key_t; +typedef nrf_crypto_backend_curve25519_key_t nrf_crypto_backend_curve25519_public_key_t; + +/** @internal See @ref nrf_crypto_backend_ecc_key_pair_generate_fn_t. + */ +ret_code_t nrf_crypto_backend_cc310_curve25519_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key); + +ret_code_t nrf_crypto_backend_cc310_curve25519_key_from_raw( + void * p_key, + uint8_t const * p_raw_data); + +ret_code_t nrf_crypto_backend_cc310_curve25519_key_to_raw( + void const * p_key, + uint8_t * p_raw_data); + +// Aliases for Curve25519-specific CC310 implementation. +#define nrf_crypto_backend_curve25519_key_pair_generate \ + nrf_crypto_backend_cc310_curve25519_key_pair_generate +#define nrf_crypto_backend_curve25519_private_key_from_raw \ + nrf_crypto_backend_cc310_curve25519_key_from_raw +#define nrf_crypto_backend_curve25519_private_key_to_raw \ + nrf_crypto_backend_cc310_curve25519_key_to_raw +#define nrf_crypto_backend_curve25519_public_key_from_raw \ + nrf_crypto_backend_cc310_curve25519_key_from_raw +#define nrf_crypto_backend_curve25519_public_key_to_raw \ + nrf_crypto_backend_cc310_curve25519_key_to_raw + +// Aliases for unused or unimplemented functions. +#define nrf_crypto_backend_curve25519_public_key_calculate NULL +#define nrf_crypto_backend_curve25519_private_key_free NULL +#define nrf_crypto_backend_curve25519_public_key_free NULL + +// Context sizes required by CC310 Curve25519. +#define NRF_CRYPTO_BACKEND_CURVE25519_KEY_PAIR_GENERATE_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_curve25519_context_t) +#define NRF_CRYPTO_BACKEND_CURVE25519_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// All CC310 Curve25519 operations share the same data structures for context. +typedef nrf_crypto_backend_cc310_curve25519_context_t + nrf_crypto_backend_curve25519_key_pair_generate_context_t; + +// Dummy typedef for unused context. +typedef nrf_crypto_backend_cc310_curve25519_context_t + nrf_crypto_backend_curve25519_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_ED25519) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_ED25519) +#error "More than one backend enabled for Ed25519."); +#endif +#define NRF_CRYPTO_ECC_ED25519_ENABLED 1 + +/** @internal @brief Common structure holding context for Ed25519 (all operations). + */ +typedef struct +{ + CRYS_ECEDW_TempBuff_t temp_data; /**< @internal @brief Temporary buffer for CC310 internal storage. */ +} nrf_crypto_backend_cc310_ed25519_context_t; + + +/** @internal @brief Structure holding private key for Ed25519. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header. */ + uint8_t key[2 * CRYS_ECEDW_ORD_SIZE_IN_BYTES]; /**< @internal @brief Raw private key (seed || pubKey) in little-endian order. */ +} nrf_crypto_backend_ed25519_private_key_t; + + +/** @internal @brief Structure holding public key for Ed25519. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header. */ + uint8_t key[CRYS_ECEDW_ORD_SIZE_IN_BYTES]; /**< @internal @brief Raw public key in little-endian order. */ +} nrf_crypto_backend_ed25519_public_key_t; + + +/** @internal See @ref nrf_crypto_backend_ecc_key_pair_generate_fn_t. + */ +ret_code_t nrf_crypto_backend_cc310_ed25519_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key); + +ret_code_t nrf_crypto_backend_cc310_ed25519_private_key_from_raw( + void * p_key, + uint8_t const * p_raw_data); + +ret_code_t nrf_crypto_backend_cc310_ed25519_private_key_to_raw( + void const * p_key, + uint8_t * p_raw_data); + +ret_code_t nrf_crypto_backend_cc310_ed25519_public_key_from_raw( + void * p_key, + uint8_t const * p_raw_data); + +ret_code_t nrf_crypto_backend_cc310_ed25519_public_key_to_raw( + void const * p_key, + uint8_t * p_raw_data); + +ret_code_t nrf_crypto_backend_cc310_ed25519_public_key_calculate( + void * p_context, + void const * p_private_key, + void * p_public_key); + +// Aliases for Ed25519-specific CC310 implementation. +#define nrf_crypto_backend_ed25519_key_pair_generate \ + nrf_crypto_backend_cc310_ed25519_key_pair_generate +#define nrf_crypto_backend_ed25519_private_key_from_raw \ + nrf_crypto_backend_cc310_ed25519_private_key_from_raw +#define nrf_crypto_backend_ed25519_private_key_to_raw \ + nrf_crypto_backend_cc310_ed25519_private_key_to_raw +#define nrf_crypto_backend_ed25519_public_key_from_raw \ + nrf_crypto_backend_cc310_ed25519_public_key_from_raw +#define nrf_crypto_backend_ed25519_public_key_to_raw \ + nrf_crypto_backend_cc310_ed25519_public_key_to_raw +#define nrf_crypto_backend_ed25519_public_key_calculate \ + nrf_crypto_backend_cc310_ed25519_public_key_calculate + +// Aliases for unused or unimplemented functions. +#define nrf_crypto_backend_ed25519_private_key_free NULL +#define nrf_crypto_backend_ed25519_public_key_free NULL + +// Context sizes required by CC310 Ed25519 +#define NRF_CRYPTO_BACKEND_ED25519_KEY_PAIR_GENERATE_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_ed25519_context_t) +#define NRF_CRYPTO_BACKEND_ED25519_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// All CC310 Ed25519 operations share the same data structures for context. +typedef nrf_crypto_backend_cc310_ed25519_context_t + nrf_crypto_backend_ed25519_key_pair_generate_context_t; + +// Dummy typedef for unused context. +typedef nrf_crypto_backend_cc310_ed25519_context_t + nrf_crypto_backend_ed25519_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_ED25519) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#endif // CC310_BACKEND_ECC_H__ diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_ecdh.c b/components/libraries/crypto/backend/cc310/cc310_backend_ecdh.c new file mode 100644 index 0000000..ebcffa3 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_ecdh.c @@ -0,0 +1,183 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#include + +#include "nrf_crypto_ecc_shared.h" +#include "nrf_crypto_ecdh_shared.h" +#include "nrf_crypto_ecdh.h" +#include "nrf_crypto_mem.h" +#include "nrf_crypto_shared.h" +#include "cc310_backend_mutex.h" +#include "cc310_backend_shared.h" +#include "cc310_backend_ecdh.h" + + +ret_code_t nrf_crypto_backend_cc310_ecdh_compute( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret) +{ + ret_code_t result; + CRYSError_t crys_error; + uint32_t shared_secret_size; + uint8_t aligned_buffer[(NRF_CRYPTO_ECDH_SHARED_SECRET_MAX_SIZE + 3) & ~3]; + uint8_t * p_output_buffer; + bool mutex_locked; + + nrf_crypto_backend_cc310_ecdh_compute_context_t * p_ctx = + (nrf_crypto_backend_cc310_ecdh_compute_context_t *)p_context; + + nrf_crypto_backend_cc310_ecc_private_key_t * p_prv = + (nrf_crypto_backend_cc310_ecc_private_key_t *)p_private_key; + + nrf_crypto_backend_cc310_ecc_public_key_t * p_pub = + (nrf_crypto_backend_cc310_ecc_public_key_t *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info; + + result = nrf_crypto_backend_cc310_ecc_public_key_convert(p_pub, &p_ctx->key_build_temp_data); + if (result != NRF_SUCCESS) + { + return result; + } + + shared_secret_size = p_info->raw_private_key_size; + + if ((shared_secret_size & 3) != 0) // Check if shared_secret_size is word aligned + { + shared_secret_size = (shared_secret_size + 3) & ~3; + p_output_buffer = &aligned_buffer[0]; + } + else + { + p_output_buffer = p_shared_secret; + } + + mutex_locked = cc310_backend_mutex_trylock(); + if (!mutex_locked) + { + return NRF_ERROR_CRYPTO_BUSY; + } + + crys_error = CRYS_ECDH_SVDP_DH(&p_pub->key.cc310_public_key, + &p_prv->private_key, + p_output_buffer, + &shared_secret_size, + &p_ctx->temp_data); + + cc310_backend_mutex_unlock(); + + if (p_output_buffer != p_shared_secret) + { + //lint -save -e645 (Symbol 'aligned_buffer' may not have been initialized) + memcpy(p_shared_secret, + &aligned_buffer[3 - ((p_info->raw_private_key_size + 3) & 3)], // Bytes at the beginning that were added during padding are now skipped + p_info->raw_private_key_size); + //lint -restore + } + + result = nrf_crypto_backend_cc310_ecc_error_convert(crys_error); + return result; +} + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519) + +ret_code_t nrf_crypto_backend_cc310_curve25519_ecdh_compute( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret) +{ + ret_code_t result; + CRYSError_t crys_error; + bool mutex_locked; + + nrf_crypto_backend_cc310_curve25519_context_t * p_ctx = + (nrf_crypto_backend_cc310_curve25519_context_t *)p_context; + + nrf_crypto_backend_curve25519_private_key_t * p_prv = + (nrf_crypto_backend_curve25519_private_key_t *)p_private_key; + + nrf_crypto_backend_curve25519_public_key_t * p_pub = + (nrf_crypto_backend_curve25519_public_key_t *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info; + size_t shared_secret_size = p_info->raw_private_key_size; + size_t pub_key_size = sizeof(p_pub->key); + size_t prv_key_size = sizeof(p_prv->key); + + mutex_locked = cc310_backend_mutex_trylock(); + if (!mutex_locked) + { + return NRF_ERROR_CRYPTO_BUSY; + } + + crys_error = CRYS_ECMONT_Scalarmult(p_shared_secret, + &shared_secret_size, + p_prv->key, + prv_key_size, + p_pub->key, + pub_key_size, + &p_ctx->temp_data); + + cc310_backend_mutex_unlock(); + + // Swap endianess (only for Curve25519) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_CURVE25519_BIG_ENDIAN) + nrf_crypto_internal_swap_endian_in_place(p_shared_secret, + NRF_CRYPTO_ECDH_CURVE25519_SHARED_SECRET_SIZE); +#endif + + result = nrf_crypto_backend_cc310_ecc_error_convert(crys_error); + return result; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519) + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_ecdh.h b/components/libraries/crypto/backend/cc310/cc310_backend_ecdh.h new file mode 100644 index 0000000..8ebef22 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_ecdh.h @@ -0,0 +1,199 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BACKEND_ECDH_H__ +#define CC310_BACKEND_ECDH_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdh_shared.h" +#include "crys_ecpki_dh.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @internal @brief Common structure holding context for ECDH. + */ +typedef union +{ + CRYS_ECDH_TempData_t temp_data; /**< @internal @brief Temporary buffer for CC310 internal storage */ + CRYS_ECPKI_BUILD_TempData_t key_build_temp_data; /**< @internal @brief Temporary buffer for CC310 public key build */ +} nrf_crypto_backend_cc310_ecdh_compute_context_t; + + +/** @internal See @ref nrf_crypto_backend_ecdh_compute_fn_t. + */ +ret_code_t nrf_crypto_backend_cc310_ecdh_compute( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret); + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R1) +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp160r1_ecdh_compute nrf_crypto_backend_cc310_ecdh_compute +#define NRF_CRYPTO_BACKEND_SECP160R1_ECDH_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_ecdh_compute_context_t) +typedef nrf_crypto_backend_cc310_ecdh_compute_context_t nrf_crypto_backend_secp160r1_ecdh_context_t; +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R2) +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp160r2_ecdh_compute nrf_crypto_backend_cc310_ecdh_compute +#define NRF_CRYPTO_BACKEND_SECP160R2_ECDH_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_ecdh_compute_context_t) +typedef nrf_crypto_backend_cc310_ecdh_compute_context_t nrf_crypto_backend_secp160r2_ecdh_context_t; +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R2) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP192R1) +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp192r1_ecdh_compute nrf_crypto_backend_cc310_ecdh_compute +#define NRF_CRYPTO_BACKEND_SECP192R1_ECDH_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_ecdh_compute_context_t) +typedef nrf_crypto_backend_cc310_ecdh_compute_context_t nrf_crypto_backend_secp192r1_ecdh_context_t; +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP192R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP224R1) +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp224r1_ecdh_compute nrf_crypto_backend_cc310_ecdh_compute +#define NRF_CRYPTO_BACKEND_SECP224R1_ECDH_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_ecdh_compute_context_t) +typedef nrf_crypto_backend_cc310_ecdh_compute_context_t nrf_crypto_backend_secp224r1_ecdh_context_t; +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP224R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP256R1) +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp256r1_ecdh_compute nrf_crypto_backend_cc310_ecdh_compute +#define NRF_CRYPTO_BACKEND_SECP256R1_ECDH_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_ecdh_compute_context_t) +typedef nrf_crypto_backend_cc310_ecdh_compute_context_t nrf_crypto_backend_secp256r1_ecdh_context_t; +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP256R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP384R1) +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp384r1_ecdh_compute nrf_crypto_backend_cc310_ecdh_compute +#define NRF_CRYPTO_BACKEND_SECP384R1_ECDH_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_ecdh_compute_context_t) +typedef nrf_crypto_backend_cc310_ecdh_compute_context_t nrf_crypto_backend_secp384r1_ecdh_context_t; +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP384R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP521R1) +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp521r1_ecdh_compute nrf_crypto_backend_cc310_ecdh_compute +#define NRF_CRYPTO_BACKEND_SECP521R1_ECDH_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_ecdh_compute_context_t) +typedef nrf_crypto_backend_cc310_ecdh_compute_context_t nrf_crypto_backend_secp521r1_ecdh_context_t; +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP521R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160K1) +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp160k1_ecdh_compute nrf_crypto_backend_cc310_ecdh_compute +#define NRF_CRYPTO_BACKEND_SECP160K1_ECDH_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_ecdh_compute_context_t) +typedef nrf_crypto_backend_cc310_ecdh_compute_context_t nrf_crypto_backend_secp160k1_ecdh_context_t; +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160K1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP192K1) +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp192k1_ecdh_compute nrf_crypto_backend_cc310_ecdh_compute +#define NRF_CRYPTO_BACKEND_SECP192K1_ECDH_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_ecdh_compute_context_t) +typedef nrf_crypto_backend_cc310_ecdh_compute_context_t nrf_crypto_backend_secp192k1_ecdh_context_t; +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP192K1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP224K1) +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp224k1_ecdh_compute nrf_crypto_backend_cc310_ecdh_compute +#define NRF_CRYPTO_BACKEND_SECP224K1_ECDH_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_ecdh_compute_context_t) +typedef nrf_crypto_backend_cc310_ecdh_compute_context_t nrf_crypto_backend_secp224k1_ecdh_context_t; +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP224K1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP256K1) +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_secp256k1_ecdh_compute nrf_crypto_backend_cc310_ecdh_compute +#define NRF_CRYPTO_BACKEND_SECP256K1_ECDH_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_ecdh_compute_context_t) +typedef nrf_crypto_backend_cc310_ecdh_compute_context_t nrf_crypto_backend_secp256k1_ecdh_context_t; +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP256K1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519) + +ret_code_t nrf_crypto_backend_cc310_curve25519_ecdh_compute( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret); + +// Aliases for one common CC310 implementation +#define nrf_crypto_backend_curve25519_ecdh_compute nrf_crypto_backend_cc310_curve25519_ecdh_compute +#define NRF_CRYPTO_BACKEND_CURVE25519_ECDH_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_ecdh_compute_context_t) +typedef nrf_crypto_backend_cc310_ecdh_compute_context_t nrf_crypto_backend_curve25519_ecdh_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#endif // CC310_BACKEND_ECDH_H__ diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_ecdsa.c b/components/libraries/crypto/backend/cc310/cc310_backend_ecdsa.c new file mode 100644 index 0000000..7a8de0c --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_ecdsa.c @@ -0,0 +1,215 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#include +#include "ssi_pal_types.h" +#include "ssi_pal_mem.h" +#include "sns_silib.h" +#include "crys_rnd.h" +#include "crys_ecpki_ecdsa.h" +#include "crys_ecpki_error.h" +#include "crys_kdf_error.h" +#include "crys_hash_error.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_ecc_shared.h" +#include "nrf_crypto_ecdsa_shared.h" +#include "nrf_crypto_ecdsa.h" +#include "cc310_backend_ecdsa.h" +#include "cc310_backend_shared.h" +#include "cc310_backend_mutex.h" + + +#define CC310_SHA1_DIGEST_SIZE (160 / 8) /**< @internal @brief Digest size of SHA-1 */ +#define CC310_SHA224_DIGEST_SIZE (224 / 8) /**< @internal @brief Digest size of SHA-224 */ +#define CC310_SHA256_DIGEST_SIZE (256 / 8) /**< @internal @brief Digest size of SHA-256 */ +#define CC310_SHA384_DIGEST_SIZE (384 / 8) /**< @internal @brief Digest size of SHA-384 */ +#define CC310_SHA512_DIGEST_SIZE (512 / 8) /**< @internal @brief Digest size of SHA-512 */ + + +/** @internal @brief Returns enum value of @ref CRYS_ECPKI_HASH_OpMode_t based on provided hash size. + * + * @param[in] data_size Hash size + * @return Value from @ref CRYS_ECPKI_HASH_OpMode_t or CRYS_ECPKI_HASH_OpModeLast if + * cannot find implemented hash with provided size. + */ +static CRYS_ECPKI_HASH_OpMode_t hash_mode_from_size(uint32_t data_size) +{ + CRYS_ECPKI_HASH_OpMode_t hash_mode; + + switch (data_size) + { + case CC310_SHA1_DIGEST_SIZE: + hash_mode = CRYS_ECPKI_AFTER_HASH_SHA1_mode; + break; + + case CC310_SHA224_DIGEST_SIZE: + hash_mode = CRYS_ECPKI_AFTER_HASH_SHA224_mode; + break; + + case CC310_SHA256_DIGEST_SIZE: + hash_mode = CRYS_ECPKI_AFTER_HASH_SHA256_mode; + break; + + case CC310_SHA384_DIGEST_SIZE: + hash_mode = CRYS_ECPKI_AFTER_HASH_SHA384_mode; + break; + + case CC310_SHA512_DIGEST_SIZE: + hash_mode = CRYS_ECPKI_AFTER_HASH_SHA512_mode; + break; + + default: + hash_mode = CRYS_ECPKI_HASH_OpModeLast; + break; + } + + return hash_mode; +} + + +ret_code_t nrf_crypto_backend_cc310_sign( + void * p_context, + void const * p_private_key, + uint8_t const * p_data, + size_t data_size, + uint8_t * p_signature) +{ + ret_code_t result; + CRYSError_t crys_error; + uint32_t signature_size; + CRYS_ECPKI_HASH_OpMode_t hash_mode = hash_mode_from_size(data_size); + bool mutex_locked; + + nrf_crypto_backend_cc310_sign_context_t * p_ctx = + (nrf_crypto_backend_cc310_sign_context_t *)p_context; + + nrf_crypto_backend_cc310_ecc_private_key_t * p_prv = + (nrf_crypto_backend_cc310_ecc_private_key_t *)p_private_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info; + + if (hash_mode == CRYS_ECPKI_HASH_OpModeLast) + { + return NRF_ERROR_CRYPTO_INPUT_LENGTH; + } + + signature_size = p_info->raw_public_key_size; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + crys_error = CRYS_ECDSA_Sign(p_context, + nrf_crypto_backend_cc310_rng, + &p_ctx->user_context, + &p_prv->private_key, + hash_mode, + (uint8_t *)p_data, + data_size, + p_signature, + &signature_size); + + cc310_backend_mutex_unlock(); + + result = nrf_crypto_backend_cc310_ecc_error_convert(crys_error); + + if (result == NRF_SUCCESS && signature_size != p_info->raw_public_key_size) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + return result; +} + + +ret_code_t nrf_crypto_backend_cc310_verify( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature) +{ + ret_code_t result; + CRYSError_t crys_error; + CRYS_ECPKI_HASH_OpMode_t hash_mode = hash_mode_from_size(data_size); + bool mutex_locked; + + nrf_crypto_backend_cc310_verify_context_t * p_ctx = + (nrf_crypto_backend_cc310_verify_context_t *)p_context; + + nrf_crypto_backend_cc310_ecc_public_key_t * p_pub = + (nrf_crypto_backend_cc310_ecc_public_key_t *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info; + + result = nrf_crypto_backend_cc310_ecc_public_key_convert(p_pub, &p_ctx->key_build_temp_data); + if (result != NRF_SUCCESS) + { + return result; + } + + if (hash_mode == CRYS_ECPKI_HASH_OpModeLast) + { + return NRF_ERROR_CRYPTO_INPUT_LENGTH; + } + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + crys_error = CRYS_ECDSA_Verify(&p_ctx->user_context, + &p_pub->key.cc310_public_key, + hash_mode, + (uint8_t *)p_signature, + p_info->raw_public_key_size, + (uint8_t *)p_data, + data_size); + + cc310_backend_mutex_unlock(); + + result = nrf_crypto_backend_cc310_ecc_error_convert(crys_error); + return result; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_ecdsa.h b/components/libraries/crypto/backend/cc310/cc310_backend_ecdsa.h new file mode 100644 index 0000000..73f4fe2 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_ecdsa.h @@ -0,0 +1,245 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BACKEND_ECDSA_H__ +#define CC310_BACKEND_ECDSA_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#include "nrf_crypto_ecc_shared.h" +#include "nrf_crypto_ecdsa_shared.h" +#include "crys_ecpki_types.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @internal @brief Common structure holding context for ECDSA sign. + */ +typedef struct +{ + CRYS_ECDSA_SignUserContext_t user_context; /**< @internal @brief Temporary buffer for CC310 internal storage */ +} nrf_crypto_backend_cc310_sign_context_t; + + +/** @internal @brief Common structure holding context for ECDSA verify. + */ +typedef union +{ + CRYS_ECDSA_VerifyUserContext_t user_context; /**< @internal @brief Temporary buffer for CC310 internal storage */ + CRYS_ECPKI_BUILD_TempData_t key_build_temp_data; /**< @internal @brief Temporary buffer for CC310 public key build */ +} nrf_crypto_backend_cc310_verify_context_t; + + +/** @internal See @ref nrf_crypto_backend_ecdsa_sign_fn_t. + */ +ret_code_t nrf_crypto_backend_cc310_sign( + void * p_context, + void const * p_private_key, + uint8_t const * p_data, + size_t data_size, + uint8_t * p_signature); + + +/** @internal See @ref nrf_crypto_backend_ecdsa_verify_fn_t. + */ +ret_code_t nrf_crypto_backend_cc310_verify( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature); + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R1) +#define NRF_CRYPTO_BACKEND_SECP160R1_SIGN_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_sign_context_t) +#define NRF_CRYPTO_BACKEND_SECP160R1_VERIFY_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_verify_context_t) +typedef nrf_crypto_backend_cc310_sign_context_t nrf_crypto_backend_secp160r1_sign_context_t; +typedef nrf_crypto_backend_cc310_verify_context_t nrf_crypto_backend_secp160r1_verify_context_t; +#define nrf_crypto_backend_secp160r1_sign nrf_crypto_backend_cc310_sign +#define nrf_crypto_backend_secp160r1_verify nrf_crypto_backend_cc310_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R2) +#define NRF_CRYPTO_BACKEND_SECP160R2_SIGN_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_sign_context_t) +#define NRF_CRYPTO_BACKEND_SECP160R2_VERIFY_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_verify_context_t) +typedef nrf_crypto_backend_cc310_sign_context_t nrf_crypto_backend_secp160r2_sign_context_t; +typedef nrf_crypto_backend_cc310_verify_context_t nrf_crypto_backend_secp160r2_verify_context_t; +#define nrf_crypto_backend_secp160r2_sign nrf_crypto_backend_cc310_sign +#define nrf_crypto_backend_secp160r2_verify nrf_crypto_backend_cc310_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP192R1) +#define NRF_CRYPTO_BACKEND_SECP192R1_SIGN_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_sign_context_t) +#define NRF_CRYPTO_BACKEND_SECP192R1_VERIFY_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_verify_context_t) +typedef nrf_crypto_backend_cc310_sign_context_t nrf_crypto_backend_secp192r1_sign_context_t; +typedef nrf_crypto_backend_cc310_verify_context_t nrf_crypto_backend_secp192r1_verify_context_t; +#define nrf_crypto_backend_secp192r1_sign nrf_crypto_backend_cc310_sign +#define nrf_crypto_backend_secp192r1_verify nrf_crypto_backend_cc310_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP224R1) +#define NRF_CRYPTO_BACKEND_SECP224R1_SIGN_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_sign_context_t) +#define NRF_CRYPTO_BACKEND_SECP224R1_VERIFY_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_verify_context_t) +typedef nrf_crypto_backend_cc310_sign_context_t nrf_crypto_backend_secp224r1_sign_context_t; +typedef nrf_crypto_backend_cc310_verify_context_t nrf_crypto_backend_secp224r1_verify_context_t; +#define nrf_crypto_backend_secp224r1_sign nrf_crypto_backend_cc310_sign +#define nrf_crypto_backend_secp224r1_verify nrf_crypto_backend_cc310_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP256R1) +#define NRF_CRYPTO_BACKEND_SECP256R1_SIGN_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_sign_context_t) +#define NRF_CRYPTO_BACKEND_SECP256R1_VERIFY_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_verify_context_t) +typedef nrf_crypto_backend_cc310_sign_context_t nrf_crypto_backend_secp256r1_sign_context_t; +typedef nrf_crypto_backend_cc310_verify_context_t nrf_crypto_backend_secp256r1_verify_context_t; +#define nrf_crypto_backend_secp256r1_sign nrf_crypto_backend_cc310_sign +#define nrf_crypto_backend_secp256r1_verify nrf_crypto_backend_cc310_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP384R1) +#define NRF_CRYPTO_BACKEND_SECP384R1_SIGN_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_sign_context_t) +#define NRF_CRYPTO_BACKEND_SECP384R1_VERIFY_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_verify_context_t) +typedef nrf_crypto_backend_cc310_sign_context_t nrf_crypto_backend_secp384r1_sign_context_t; +typedef nrf_crypto_backend_cc310_verify_context_t nrf_crypto_backend_secp384r1_verify_context_t; +#define nrf_crypto_backend_secp384r1_sign nrf_crypto_backend_cc310_sign +#define nrf_crypto_backend_secp384r1_verify nrf_crypto_backend_cc310_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP521R1) +#define NRF_CRYPTO_BACKEND_SECP521R1_SIGN_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_sign_context_t) +#define NRF_CRYPTO_BACKEND_SECP521R1_VERIFY_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_verify_context_t) +typedef nrf_crypto_backend_cc310_sign_context_t nrf_crypto_backend_secp521r1_sign_context_t; +typedef nrf_crypto_backend_cc310_verify_context_t nrf_crypto_backend_secp521r1_verify_context_t; +#define nrf_crypto_backend_secp521r1_sign nrf_crypto_backend_cc310_sign +#define nrf_crypto_backend_secp521r1_verify nrf_crypto_backend_cc310_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP160K1) +#define NRF_CRYPTO_BACKEND_SECP160K1_SIGN_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_sign_context_t) +#define NRF_CRYPTO_BACKEND_SECP160K1_VERIFY_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_verify_context_t) +typedef nrf_crypto_backend_cc310_sign_context_t nrf_crypto_backend_secp160k1_sign_context_t; +typedef nrf_crypto_backend_cc310_verify_context_t nrf_crypto_backend_secp160k1_verify_context_t; +#define nrf_crypto_backend_secp160k1_sign nrf_crypto_backend_cc310_sign +#define nrf_crypto_backend_secp160k1_verify nrf_crypto_backend_cc310_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP192K1) +#define NRF_CRYPTO_BACKEND_SECP192K1_SIGN_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_sign_context_t) +#define NRF_CRYPTO_BACKEND_SECP192K1_VERIFY_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_verify_context_t) +typedef nrf_crypto_backend_cc310_sign_context_t nrf_crypto_backend_secp192k1_sign_context_t; +typedef nrf_crypto_backend_cc310_verify_context_t nrf_crypto_backend_secp192k1_verify_context_t; +#define nrf_crypto_backend_secp192k1_sign nrf_crypto_backend_cc310_sign +#define nrf_crypto_backend_secp192k1_verify nrf_crypto_backend_cc310_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP224K1) +#define NRF_CRYPTO_BACKEND_SECP224K1_SIGN_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_sign_context_t) +#define NRF_CRYPTO_BACKEND_SECP224K1_VERIFY_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_verify_context_t) +typedef nrf_crypto_backend_cc310_sign_context_t nrf_crypto_backend_secp224k1_sign_context_t; +typedef nrf_crypto_backend_cc310_verify_context_t nrf_crypto_backend_secp224k1_verify_context_t; +#define nrf_crypto_backend_secp224k1_sign nrf_crypto_backend_cc310_sign +#define nrf_crypto_backend_secp224k1_verify nrf_crypto_backend_cc310_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_SECP256K1) +#define NRF_CRYPTO_BACKEND_SECP256K1_SIGN_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_sign_context_t) +#define NRF_CRYPTO_BACKEND_SECP256K1_VERIFY_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_cc310_verify_context_t) +typedef nrf_crypto_backend_cc310_sign_context_t nrf_crypto_backend_secp256k1_sign_context_t; +typedef nrf_crypto_backend_cc310_verify_context_t nrf_crypto_backend_secp256k1_verify_context_t; +#define nrf_crypto_backend_secp256k1_sign nrf_crypto_backend_cc310_sign +#define nrf_crypto_backend_secp256k1_verify nrf_crypto_backend_cc310_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519) +// Curve25519 is not designed for ECDSA +#define NRF_CRYPTO_BACKEND_CURVE25519_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_CURVE25519_VERIFY_CONTEXT_SIZE 0 +typedef uint32_t nrf_crypto_backend_curve25519_sign_context_t; +typedef uint32_t nrf_crypto_backend_curve25519_verify_context_t; +#define nrf_crypto_backend_curve25519_sign NULL +#define nrf_crypto_backend_curve25519_verify NULL +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#endif // CC310_BACKEND_ECDSA_H__ diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_eddsa.c b/components/libraries/crypto/backend/cc310/cc310_backend_eddsa.c new file mode 100644 index 0000000..2a0c335 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_eddsa.c @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) && \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_ED25519) + +#include +#include +#include + +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_rng.h" +#include "nrf_crypto_eddsa.h" +#include "cc310_backend_ecc.h" +#include "cc310_backend_shared.h" +#include "cc310_backend_mutex.h" +#include "crys_ec_edw_api.h" +#include "crys_ec_mont_edw_error.h" + + +ret_code_t nrf_crypto_backend_ed25519_sign( + void * p_context, + nrf_crypto_ecc_private_key_t const * p_private_key, + uint8_t const * p_message, + size_t message_size, + uint8_t * p_signature) +{ + ret_code_t result; + CRYSError_t crys_error; + bool mutex_locked; + size_t signature_size = 2 * CRYS_ECEDW_ORD_SIZE_IN_BYTES; + + nrf_crypto_backend_cc310_ed25519_context_t * p_ctx = + (nrf_crypto_backend_cc310_ed25519_context_t *)p_context; + + nrf_crypto_backend_ed25519_private_key_t * p_prv = + (nrf_crypto_backend_ed25519_private_key_t *)p_private_key; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + crys_error = CRYS_ECEDW_Sign(p_signature, + &signature_size, + p_message, + message_size, + p_prv->key, + sizeof(p_prv->key), + &p_ctx->temp_data); + + cc310_backend_mutex_unlock(); + + result = nrf_crypto_backend_cc310_ecc_error_convert(crys_error); + + return result; +} + +ret_code_t nrf_crypto_backend_ed25519_verify( + void * p_context, + nrf_crypto_ecc_public_key_t const * p_public_key, + uint8_t const * p_message, + size_t message_size, + uint8_t const * p_signature) +{ + ret_code_t result; + CRYSError_t crys_error; + bool mutex_locked; + + nrf_crypto_backend_cc310_ed25519_context_t * p_ctx = + (nrf_crypto_backend_cc310_ed25519_context_t *)p_context; + + nrf_crypto_backend_ed25519_public_key_t * p_pub = + (nrf_crypto_backend_ed25519_public_key_t *)p_public_key; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + crys_error = CRYS_ECEDW_Verify(p_signature, + 2 * CRYS_ECEDW_ORD_SIZE_IN_BYTES, + p_pub->key, + CRYS_ECEDW_ORD_SIZE_IN_BYTES, + (uint8_t *)p_message, + message_size, + &p_ctx->temp_data); + + cc310_backend_mutex_unlock(); + + result = nrf_crypto_backend_cc310_ecc_error_convert(crys_error); + + return result; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_ED25519) diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_eddsa.h b/components/libraries/crypto/backend/cc310/cc310_backend_eddsa.h new file mode 100644 index 0000000..e31e681 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_eddsa.h @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BACKEND_EDDSA_H__ +#define CC310_BACKEND_EDDSA_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) && \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_ED25519) + +#include +#include "nrf_crypto_ecc_shared.h" +#include "nrf_crypto_eddsa_shared.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_CRYPTO_BACKEND_ED25519_SIGN_CONTEXT_SIZE sizeof(nrf_crypto_backend_cc310_ed25519_context_t) +#define NRF_CRYPTO_BACKEND_ED25519_VERIFY_CONTEXT_SIZE sizeof(nrf_crypto_backend_cc310_ed25519_context_t) +typedef nrf_crypto_backend_cc310_ed25519_context_t nrf_crypto_backend_ed25519_sign_context_t; +typedef nrf_crypto_backend_cc310_ed25519_context_t nrf_crypto_backend_ed25519_verify_context_t; + +#ifdef __cplusplus +} +#endif + + +#endif // #if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_ECC_ED25519) + +#endif // CC310_BACKEND_EDDSA_H__ diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_hash.c b/components/libraries/crypto/backend/cc310/cc310_backend_hash.c new file mode 100644 index 0000000..e5eea83 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_hash.c @@ -0,0 +1,303 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#include "nrf.h" +#include "cc310_backend_hash.h" +#include "crys_hash.h" +#include "crys_hash_error.h" +#include "nrf_crypto_init.h" +#include "nrf_crypto_types.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_hash_shared.h" +#include "sdk_macros.h" +#include "nrf_log.h" +#include "nrf_assert.h" +#include "cc310_backend_mutex.h" +#include "cc310_backend_shared.h" +#include + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HASH_SHA256) || \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HASH_SHA512) + +static ret_code_t hash_result_get(CRYSError_t error) +{ + ret_code_t ret_val; + + switch (error) + { + case CRYS_OK: + ret_val = NRF_SUCCESS; + break; + + case CRYS_HASH_INVALID_USER_CONTEXT_POINTER_ERROR: + ret_val = NRF_ERROR_CRYPTO_CONTEXT_NULL; + break; + + case CRYS_HASH_ILLEGAL_OPERATION_MODE_ERROR: + ret_val = NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + break; + + case CRYS_HASH_USER_CONTEXT_CORRUPTED_ERROR: + ret_val = NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED; + break; + + // May be added to specialized errors for hash. + case CRYS_HASH_LAST_BLOCK_ALREADY_PROCESSED_ERROR: + ret_val = NRF_ERROR_CRYPTO_INTERNAL; + break; + + case CRYS_HASH_IS_NOT_SUPPORTED: + ret_val = NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + break; + + default: + ret_val = NRF_ERROR_CRYPTO_INTERNAL; + break; + } + + return ret_val; +} + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HASH_SHA256) + +static ret_code_t cc310_backend_hash_sha256_init(void * const p_context) +{ + uint32_t ret_val; + CRYSError_t crys_error; + CRYS_HASH_OperationMode_t hash_mode = CRYS_HASH_SHA256_mode; + + // No parameter testing on this level. + // This has been done on upper level. + + CRYS_HASHUserContext_t * const p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t *)p_context)->context); + + crys_error = CRYS_HASH_Init(p_backend_context, hash_mode); + + ret_val = hash_result_get(crys_error); + + return ret_val; +} + + +static ret_code_t cc310_backend_hash_sha256_update(void * const p_context, + uint8_t const * p_data, + size_t size) +{ + ret_code_t ret_val; + CRYSError_t crys_error; + bool mutex_locked; + size_t cur_len; + size_t len_left = size; + uint8_t const * p_cur = p_data; + + // Limited parameter testing on this level. + // This has been done on upper level. + + CRYS_HASHUserContext_t * const p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t *)p_context)->context); + + // Data in flash could lead to silently calculating wrong Hash. + VERIFY_TRUE(nrfx_is_in_ram(p_data), NRF_ERROR_CRYPTO_INPUT_LOCATION); + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + // If the input is larger than CC310_MAX_LENGTH_DMA_OPERATIONS, split into smaller + do + { + cur_len = (len_left > CC310_MAX_LENGTH_DMA_OPERATIONS) ? + CC310_MAX_LENGTH_DMA_OPERATIONS : len_left; + + crys_error = CRYS_HASH_Update(p_backend_context, (uint8_t *)p_cur, cur_len); + + len_left -= cur_len; + p_cur += cur_len; + + } while (crys_error == CRYS_OK && len_left > 0); + + cc310_backend_mutex_unlock(); + + ret_val = hash_result_get(crys_error); + + + return ret_val; +} + + +static ret_code_t cc310_backend_hash_sha256_finalize(void * const p_context, + uint8_t * p_digest, + size_t * const p_digest_size) +{ + ret_code_t ret_val; + CRYSError_t crys_error; + bool mutex_locked; + CRYS_HASH_Result_t * p_int_digest = (CRYS_HASH_Result_t *)p_digest; + + // Limited parameter testing on this level. + // This has been done on upper level. + + CRYS_HASHUserContext_t * const p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t * )p_context)->context); + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + // Do the hash finalize calculation + crys_error = CRYS_HASH_Finish(p_backend_context, *p_int_digest); + + cc310_backend_mutex_unlock(); + + ret_val = hash_result_get(crys_error); + if (ret_val == NRF_SUCCESS) + { + *p_digest_size = NRF_CRYPTO_HASH_SIZE_SHA256; + } + + return ret_val; +} + + +const nrf_crypto_hash_info_t g_nrf_crypto_hash_sha256_info = +{ + .init_fn = cc310_backend_hash_sha256_init, + .update_fn = cc310_backend_hash_sha256_update, + .finalize_fn = cc310_backend_hash_sha256_finalize, + .digest_size = NRF_CRYPTO_HASH_SIZE_SHA256, + .context_size = sizeof(nrf_crypto_backend_hash_sha256_context_t), + .hash_mode = NRF_CRYPTO_HASH_MODE_SHA256 +}; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HASH_SHA256) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HASH_SHA512) + +// SHA-512 does not use CC310 hardware and therefore will not use a mutex lock + +static ret_code_t cc310_backend_hash_sha512_init(void * p_context) +{ + uint32_t ret_val; + CRYSError_t crys_error; + CRYS_HASH_OperationMode_t hash_mode = CRYS_HASH_SHA512_mode; + + // No parameter testing on this level. + // This has been done on upper level. + + CRYS_HASHUserContext_t * const p_backend_context + = &(((nrf_crypto_backend_hash_sha512_context_t * ) p_context)->context); + + crys_error = CRYS_HASH_Init(p_backend_context, hash_mode); + ret_val = hash_result_get(crys_error); + + return ret_val; +} + + +static ret_code_t cc310_backend_hash_sha512_update(void * const p_context, + uint8_t const * p_data, + size_t size) +{ + ret_code_t ret_val; + CRYSError_t crys_error; + + // Limited parameter testing on this level. + // This has been done on upper level. + + CRYS_HASHUserContext_t * const p_backend_context + = &(((nrf_crypto_backend_hash_sha512_context_t *)p_context)->context); + + // Data in flash could lead to silently calculating wrong Hash. + VERIFY_TRUE(nrfx_is_in_ram(p_data), NRF_ERROR_CRYPTO_INPUT_LOCATION); + + crys_error = CRYS_HASH_Update(p_backend_context, (uint8_t *)p_data, size); + + ret_val = hash_result_get(crys_error); + + return ret_val; +} + + +static ret_code_t cc310_backend_hash_sha512_finalize(void * const p_context, + uint8_t * p_digest, + size_t * const p_digest_size) +{ + ret_code_t ret_val; + CRYSError_t crys_error; + CRYS_HASH_Result_t * p_int_digest = (CRYS_HASH_Result_t *)p_digest; + + // Limited parameter testing on this level. + // This has been done on upper level. + + CRYS_HASHUserContext_t * const p_backend_context + = &(((nrf_crypto_backend_hash_sha512_context_t *) p_context)->context); + + crys_error = CRYS_HASH_Finish(p_backend_context, *p_int_digest); + ret_val = hash_result_get(crys_error); + + if (ret_val == NRF_SUCCESS) + { + *p_digest_size = NRF_CRYPTO_HASH_SIZE_SHA512; + } + + return ret_val; +} + + +const nrf_crypto_hash_info_t g_nrf_crypto_hash_sha512_info = +{ + .init_fn = cc310_backend_hash_sha512_init, + .update_fn = cc310_backend_hash_sha512_update, + .finalize_fn = cc310_backend_hash_sha512_finalize, + .digest_size = NRF_CRYPTO_HASH_SIZE_SHA512, + .context_size = sizeof(nrf_crypto_backend_hash_sha512_context_t), + .hash_mode = NRF_CRYPTO_HASH_MODE_SHA512 +}; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HASH_SHA512) + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HASH_SHA256) || NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HASH_SHA512) + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && #if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_hash.h b/components/libraries/crypto/backend/cc310/cc310_backend_hash.h new file mode 100644 index 0000000..917b9c6 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_hash.h @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BACKEND_HASH_H__ +#define CC310_BACKEND_HASH_H__ + +/** @file + * + * @defgroup nrf_crypto_cc310_backend_hash nrf_crypto CC310 backend hash + * @{ + * @ingroup nrf_crypto_cc310_backend + * + * @brief Hash functionality provided by the nrf_crypto CC310 backend. + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#include "sdk_errors.h" +#include "nrf_crypto_hash_shared.h" +#include "crys_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HASH_SHA256) + +// Flag that nrf_crypto_hash frontend can be compiled +#undef NRF_CRYPTO_HASH_ENABLED +#define NRF_CRYPTO_HASH_ENABLED 1 + +// Flag that SHA-256 is enabled in backend +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HASH_SHA256) +#error "Duplicate definition of SHA-256. More than one backend enabled"); +#endif +#define NRF_CRYPTO_HASH_SHA256_ENABLED 1 + + +/**@internal @brief nrf_crypto_hash context for SHA-256 in nrf_crypto CC310 backend. */ +typedef struct +{ + nrf_crypto_hash_internal_context_t header; /**< Common header for context. */ + CRYS_HASHUserContext_t context; /**< Hash context internal to CC310. */ +} nrf_crypto_backend_hash_sha256_context_t; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HASH_SHA256) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HASH_SHA512) + +// Flag that nrf_crypto_hash frontend can be compiled +#undef NRF_CRYPTO_HASH_ENABLED +#define NRF_CRYPTO_HASH_ENABLED 1 + +// Duplicate backend enabled test for SHA-512 +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HASH_SHA512) +#error "Duplicate definition of SHA-512. More than one backend enabled"); +#endif + +// Flag that SHA-512 is enabled in backend +#define NRF_CRYPTO_HASH_SHA512_ENABLED 1 + + +/**@internal @brief nrf_crypto_hash context for SHA-512 in nrf_crypto CC310 backend. */ +typedef struct +{ + nrf_crypto_hash_internal_context_t header; /**< Common header for context. */ + CRYS_HASHUserContext_t context; /**< Hash context internal to CC310. */ +} nrf_crypto_backend_hash_sha512_context_t; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HASH_SHA512) + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +/**@} */ + +#endif // CC310_BACKEND_HASH_H__ diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_hmac.c b/components/libraries/crypto/backend/cc310/cc310_backend_hmac.c new file mode 100644 index 0000000..1abf1cd --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_hmac.c @@ -0,0 +1,260 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#include "sdk_common.h" +#include "nrf_log.h" +#include "nrf_crypto_hmac_shared.h" +#include "cc310_backend_hmac.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_types.h" +#include +#include "crys_hmac.h" +#include "crys_hmac_defs.h" +#include "crys_hmac_error.h" +#include "crys_hash.h" +#include "cc310_backend_mutex.h" +#include "cc310_backend_shared.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256) || \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HMAC_SHA512) + +static ret_code_t result_get(CRYSError_t err_code) +{ + ret_code_t ret_val; + + switch (err_code) + { + case CRYS_OK: + ret_val = NRF_SUCCESS; + break; + + case CRYS_HMAC_INVALID_USER_CONTEXT_POINTER_ERROR: + ret_val = NRF_ERROR_CRYPTO_CONTEXT_NULL; + break; + + case CRYS_HMAC_USER_CONTEXT_CORRUPTED_ERROR: + ret_val = NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED; + break; + + case CRYS_HMAC_DATA_IN_POINTER_INVALID_ERROR: + case CRYS_HMAC_INVALID_KEY_POINTER_ERROR: + ret_val = NRF_ERROR_CRYPTO_INPUT_NULL; + break; + + case CRYS_HMAC_INVALID_RESULT_BUFFER_POINTER_ERROR: + ret_val = NRF_ERROR_CRYPTO_OUTPUT_NULL; + break; + + case CRYS_HMAC_ILLEGAL_PARAMS_ERROR: + ret_val = NRF_ERROR_CRYPTO_INVALID_PARAM; + break; + + case CRYS_HMAC_UNVALID_KEY_SIZE_ERROR: + case CRYS_HMAC_DATA_SIZE_ILLEGAL: + ret_val = NRF_ERROR_CRYPTO_INPUT_LENGTH; + break; + + case CRYS_HMAC_ILLEGAL_OPERATION_MODE_ERROR: + case CRYS_HMAC_LAST_BLOCK_ALREADY_PROCESSED_ERROR: + case CRYS_HMAC_IS_NOT_SUPPORTED: + case CRYS_HMAC_CTX_SIZES_ERROR: + default: + ret_val = NRF_ERROR_CRYPTO_INTERNAL; + break; + } + return ret_val; +} + + +static ret_code_t cc310_backend_hmac_init(void * const p_context, + uint8_t const * p_key, + size_t key_size) +{ + CRYSError_t err_code; + CRYS_HASH_OperationMode_t hash_mode; + ret_code_t ret_val; + bool mutex_locked; + + + nrf_crypto_backend_cc310_hmac_context_t * p_ctx = + (nrf_crypto_backend_cc310_hmac_context_t *)p_context; + + switch (p_ctx->header.p_info->type) + { + case NRF_CRYPTO_HMAC_SHA256_TYPE: + { + hash_mode = CRYS_HASH_SHA256_mode; + } break; + case NRF_CRYPTO_HMAC_SHA512_TYPE: + { + hash_mode = CRYS_HASH_SHA512_mode; + } break; + default: + { + NRF_LOG_ERROR("Hash algorithm not supported by CC310 backend wrapper"); + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + } + } + + // Key in flash could lead to silently calculating wrong HMAC. + VERIFY_TRUE(nrfx_is_in_ram(p_key), NRF_ERROR_CRYPTO_INPUT_LOCATION); + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + err_code = CRYS_HMAC_Init(&p_ctx->crys_context, hash_mode, (uint8_t *)p_key, key_size); + + cc310_backend_mutex_unlock(); + + ret_val = result_get(err_code); + + return ret_val; +} + + +static ret_code_t cc310_backend_hmac_update(void * const p_context, + uint8_t const * p_data, + size_t size) +{ + CRYSError_t err_code; + ret_code_t ret_val; + bool mutex_locked; + size_t cur_len; + size_t len_left = size; + uint8_t const * p_cur = p_data; + + nrf_crypto_backend_cc310_hmac_context_t * p_ctx = + (nrf_crypto_backend_cc310_hmac_context_t *)p_context; + + // Data in flash could lead to silently calculating wrong HMAC. + VERIFY_TRUE(nrfx_is_in_ram(p_data), NRF_ERROR_CRYPTO_INPUT_LOCATION); + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + // If the input is larger than CC310_MAX_LENGTH_DMA_OPERATIONS, split into smaller + do + { + cur_len = (len_left > CC310_MAX_LENGTH_DMA_OPERATIONS) ? + CC310_MAX_LENGTH_DMA_OPERATIONS : len_left; + + err_code = CRYS_HMAC_Update(&p_ctx->crys_context, (uint8_t *)p_cur, cur_len); + + len_left -= cur_len; + p_cur += cur_len; + + } while (err_code == CRYS_OK && len_left > 0); + + cc310_backend_mutex_unlock(); + + ret_val = result_get(err_code); + + return ret_val; +} + + +static ret_code_t cc310_backend_hmac_finalize(void * const p_context, + uint8_t * p_digest, + size_t * const p_size) +{ + CRYSError_t err_code; + ret_code_t ret_val; + bool mutex_locked; + CRYS_HASH_Result_t * p_int_digest = (CRYS_HASH_Result_t *)p_digest; + + nrf_crypto_backend_cc310_hmac_context_t * p_ctx = + (nrf_crypto_backend_cc310_hmac_context_t *)p_context; + + // Set the digest length to 0 so that this is used in case of any error. + *p_size = 0; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + err_code = CRYS_HMAC_Finish(&p_ctx->crys_context, *p_int_digest); + + cc310_backend_mutex_unlock(); + + ret_val = result_get(err_code); + if (err_code != NRF_SUCCESS) + { + return ret_val; + } + + *p_size = p_ctx->header.p_info->digest_size; + + return ret_val; +} + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256) + +// Information structure for HMAC SHA256 using CC310 backend. +const nrf_crypto_hmac_info_t g_nrf_crypto_hmac_sha256_info = +{ + .init_fn = cc310_backend_hmac_init, + .update_fn = cc310_backend_hmac_update, + .finalize_fn = cc310_backend_hmac_finalize, + .digest_size = NRF_CRYPTO_HASH_SIZE_SHA256, + .context_size = sizeof(nrf_crypto_backend_hmac_sha256_context_t), + .type = NRF_CRYPTO_HMAC_SHA256_TYPE, +}; + +#endif // NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256_ENABLED + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HMAC_SHA512) + +// Information structure for HMAC SHA512 using CC310 backend. +const nrf_crypto_hmac_info_t g_nrf_crypto_hmac_sha512_info = +{ + .init_fn = cc310_backend_hmac_init, + .update_fn = cc310_backend_hmac_update, + .finalize_fn = cc310_backend_hmac_finalize, + .digest_size = NRF_CRYPTO_HASH_SIZE_SHA512, + .context_size = sizeof(nrf_crypto_backend_hmac_sha512_context_t), + .type = NRF_CRYPTO_HMAC_SHA512_TYPE, +}; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HMAC_SHA512) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256) || NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HMAC_SHA512) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_hmac.h b/components/libraries/crypto/backend/cc310/cc310_backend_hmac.h new file mode 100644 index 0000000..6e086f6 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_hmac.h @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BACKEND_HMAC_H__ +#define CC310_BACKEND_HMAC_H__ + +/** @file + * + * @defgroup nrf_crypto_cc310_backend_hmac CC310 backend for HMAC + * @{ + * @ingroup nrf_crypto_cc310_backend + * + * @brief Backend wrapper for CryptoCell (CC310). None of these types should be used directly by the + * application. + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) && \ + ( NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256) || \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HMAC_SHA512) ) + +#include "nrf_crypto_hmac_shared.h" +#include "crys_hmac.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#undef NRF_CRYPTO_HMAC_ENABLED +#define NRF_CRYPTO_HMAC_ENABLED 1 + + +/** + * @internal @brief Internal context object used by the CC310 backend wrapper. + * + * @details The same type is used for all variants (hash types). + * + * @note This should never be used directly. Use @ref nrf_crypto_backend_hmac_sha256_context_t or + * @ref nrf_crypto_backend_hmac_sha512_context_t instead. + */ +typedef struct +{ + nrf_crypto_hmac_internal_context_t header; //!< Internal nrf_crypto_hmac context header. + CRYS_HMACUserContext_t crys_context; //!< CC310 context object. +} nrf_crypto_backend_cc310_hmac_context_t; + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HMAC_SHA256) +#error "Duplicate definition of HMAC SHA-256. More than one backend enabled" +#endif // NRF_CRYPTO_HMAC_SHA256_ENABLED +#define NRF_CRYPTO_HMAC_SHA256_ENABLED 1 + +/** + * @internal @brief Context for HMAC SHA256 using CC310 backend. + */ +typedef nrf_crypto_backend_cc310_hmac_context_t nrf_crypto_backend_hmac_sha256_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HMAC_SHA512) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HMAC_SHA512) +#error "Duplicate definition of HMAC SHA-512. More than one backend enabled" +#endif // NRF_CRYPTO_HMAC_SHA512_ENABLED +#define NRF_CRYPTO_HMAC_SHA512_ENABLED 1 + +/** + * @internal @brief Context for HMAC SHA512 using CC310 backend. + */ +typedef nrf_crypto_backend_cc310_hmac_context_t nrf_crypto_backend_hmac_sha512_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256) + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) && ( NRF_MODULE_ENABLED((NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256) || NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_HMAC_SHA512) ) + +/**@} */ + +#endif // CC310_BACKEND_HMAC_H__ diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_init.c b/components/libraries/crypto/backend/cc310/cc310_backend_init.c new file mode 100644 index 0000000..1e729a4 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_init.c @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#include "nrf.h" +#include "nrf_crypto_init.h" +#include "cc310_backend_shared.h" +#include "sns_silib.h" +#include "cc310_backend_mutex.h" +#include "nrf_crypto_rng.h" + + +static uint32_t init_result_get(uint32_t crys_error) +{ + uint32_t ret_val = NRF_ERROR_INTERNAL; + switch (crys_error) + { + case CRYS_OK: + ret_val = NRF_SUCCESS; + break; + + default: + ret_val = NRF_ERROR_INTERNAL; + break; + } + + return ret_val; +} + +static ret_code_t cc310_backend_init(void) +{ + uint32_t ret_val; + CRYSError_t crys_error; + + cc310_backend_mutex_init(); + + // Initialize the CC310 run-time library + crys_error = SaSi_LibInit(); + + ret_val = init_result_get(crys_error); + VERIFY_SUCCESS(ret_val); + +#if defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 1) + + ret_val = nrf_crypto_rng_init(NULL, NULL); + VERIFY_SUCCESS(ret_val); + +#elif defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 0) + + // Do nothing + +#else + + #warning NRF_CRYPTO_RNG_AUTO_INIT_ENABLED define not found in sdk_config.h (Is the sdk_config.h valid?). + +#endif // NRF_CRYPTO_RNG_AUTO_INIT_ENABLED + + return ret_val; +} + + +static ret_code_t cc310_backend_uninit(void) +{ +#if defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 1) + + uint32_t ret_val; + ret_val = nrf_crypto_rng_init(NULL, NULL); + VERIFY_SUCCESS(ret_val); + +#elif defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 0) + + // Do nothing + +#else + + #warning NRF_CRYPTO_RNG_AUTO_INIT_ENABLED define not found in sdk_config.h (Is the sdk_config.h valid?). + +#endif // NRF_CRYPTO_RNG_AUTO_INIT_ENABLED + + SaSi_LibFini(); + + return NRF_SUCCESS; +} + + +CRYPTO_BACKEND_REGISTER(nrf_crypto_backend_info_t const cc310_backend) = +{ + .init_fn = cc310_backend_init, + .uninit_fn = cc310_backend_uninit, +}; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_mutex.c b/components/libraries/crypto/backend/cc310/cc310_backend_mutex.c new file mode 100644 index 0000000..d44b12e --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_mutex.c @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#include +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include +#include "cc310_backend_mutex.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +nrf_mtx_t g_cc310_mutex; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_mutex.h b/components/libraries/crypto/backend/cc310/cc310_backend_mutex.h new file mode 100644 index 0000000..92b3c15 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_mutex.h @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BACKEND_MUTEX_H__ +#define CC310_BACKEND_MUTEX_H__ + +/** @file + * + * @defgroup nrf_crypto_cc310_backend_mutex nrf_crypto CC310 backend mutex. + * @{ + * @ingroup nrf_crypto_cc310_backend + * + * @brief Mutex control for the nrf_crypto CC310 backend. + */ + +#include "sdk_config.h" +#include "nrf_mtx.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) || NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +#ifdef __cplusplus +extern "C" { +#endif + +extern nrf_mtx_t g_cc310_mutex; + +__STATIC_INLINE void cc310_backend_mutex_init(void); +__STATIC_INLINE bool cc310_backend_mutex_trylock(void); +__STATIC_INLINE void cc310_backend_mutex_unlock(void); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +/**@internal @brief Function initializing CC310 mutex. + * + * This function _must_ be called before other mutex operations. + */ +__STATIC_INLINE void cc310_backend_mutex_init(void) +{ + nrf_mtx_init(&g_cc310_mutex); +} + +/**@internal @brief Function try to lock a CC310 mutex. + * + * @return true if lock was acquired, false if not. + */ +__STATIC_INLINE bool cc310_backend_mutex_trylock(void) +{ + return nrf_mtx_trylock(&g_cc310_mutex); +} + + +/**@internal @brief Unlock a CC310 mutex. + * + * This function _must_ only be called when holding the lock. Unlocking a mutex which you do not + * hold will give undefined behavior. + * + */ +__STATIC_INLINE void cc310_backend_mutex_unlock(void) +{ + nrf_mtx_unlock(&g_cc310_mutex); +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) || NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +/** @} */ + +#endif // CC310_BACKEND_MUTEX_H__ + diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_rng.c b/components/libraries/crypto/backend/cc310/cc310_backend_rng.c new file mode 100644 index 0000000..acd0ede --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_rng.c @@ -0,0 +1,257 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_RNG) + +#include "nrf_crypto_error.h" +#include "nrf_log.h" +#include "cc310_backend_mutex.h" +#include "cc310_backend_rng.h" +#include "crys_rnd.h" +#include "crys_rnd_error.h" +#include "cc310_backend_shared.h" + +static ret_code_t result_get(CRYSError_t err_code) +{ + ret_code_t ret_val; + + switch (err_code) + { + case CRYS_OK: + ret_val = NRF_SUCCESS; + break; + + case CRYS_RND_ILLEGAL_PARAMETER_ERROR: + ret_val = NRF_ERROR_CRYPTO_INVALID_PARAM; + break; + + case CRYS_RND_INIT_FAILED: + case CRYS_RND_STARTUP_FAILED: + case CRYS_RND_INSTANTIATION_ERROR: + ret_val = NRF_ERROR_CRYPTO_RNG_INIT_FAILED; + break; + + case CRYS_RND_IS_NOT_SUPPORTED: + case CRYS_RND_CAN_NOT_GENERATE_RAND_IN_RANGE: + case CRYS_RND_TRNG_KAT_NOT_SUPPORTED_ERROR: + case CRYS_RND_SRAM_NOT_SUPPORTED_ERROR: + case CRYS_RND_OPERATION_IS_NOT_SUPPORTED_ERROR: + ret_val = NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + break; + + case CRYS_RND_DATA_OUT_POINTER_INVALID_ERROR: + case CRYS_RND_VECTOR_OUT_PTR_ERROR: + ret_val = NRF_ERROR_CRYPTO_OUTPUT_NULL; + break; + + case CRYS_RND_ADDITIONAL_INPUT_BUFFER_NULL: + case CRYS_RND_WORK_BUFFER_PTR_INVALID_ERROR: + case CRYS_RND_ILLEGAL_DATA_PTR_ERROR: + ret_val = NRF_ERROR_CRYPTO_INPUT_NULL; + break; + + case CRYS_RND_DATA_SIZE_OVERFLOW_ERROR: + case CRYS_RND_ADDITIONAL_INPUT_SIZE_ERROR: + case CRYS_RND_ILLEGAL_DATA_SIZE_ERROR: + case CRYS_RND_MAX_VECTOR_IS_TOO_SMALL_ERROR: + ret_val = NRF_ERROR_CRYPTO_INPUT_LENGTH; + break; + + case CRYS_RND_ILLEGAL_AES_KEY_SIZE_ERROR: + case CRYS_RND_VECTOR_OUT_SIZE_ERROR: + case CRYS_RND_VECTOR_SIZE_ERROR: + ret_val = NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + break; + + case CRYS_RND_CONTEXT_PTR_INVALID_ERROR: + case CRYS_RND_STATE_PTR_INVALID_ERROR: + ret_val = NRF_ERROR_CRYPTO_CONTEXT_NULL; + break; + + case CRYS_RND_INSTANTIATION_NOT_DONE_ERROR: + ret_val = NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED; + break; + + case CRYS_RND_RESEED_COUNTER_OVERFLOW_ERROR: + ret_val = NRF_ERROR_CRYPTO_RNG_RESEED_REQUIRED; + break; + + case CRYS_RND_CPRNG_TEST_FAIL_ERROR: + case CRYS_RND_TRNG_LOSS_SAMPLES_ERROR: + case CRYS_RND_TRNG_TIME_EXCEED_ERROR: + case CRYS_RND_TRNG_LOSS_SAMPLES_AND_TIME_EXCEED_ERROR: + case CRYS_RND_IS_KAT_MODE_ERROR: + case CRYS_RND_STATE_VALIDATION_TAG_ERROR: + case CRYS_RND_GEN_VECTOR_FUNC_ERROR: + case CRYS_RND_TRNG_ERRORS_ERROR: + case CRYS_RND_KAT_DATA_PARAMS_ERROR: + case CRYS_RND_AES_ERROR: + default: + ret_val = NRF_ERROR_CRYPTO_INTERNAL; + break; + } + return ret_val; +} + + +ret_code_t nrf_crypto_rng_backend_init(void * const p_context, + void * const p_temp_buffer) +{ + bool mutex_locked; + CRYSError_t err_code; + ret_code_t ret_val; + CRYS_RND_WorkBuff_t * p_work_buffer = (CRYS_RND_WorkBuff_t *)p_temp_buffer; + nrf_crypto_backend_rng_context_t * p_ctx = (nrf_crypto_backend_rng_context_t *)p_context; + + // Save time by not reinitializing an already valid CC310 RNG context. + // (Useful for example in case the context was stored in retained memory during system OFF.) + if (p_ctx->header.init_value == NRF_CRYPTO_RNG_CONTEXT_INIT_MAGIC_VALUE) + { + return NRF_SUCCESS; + } + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + err_code = CRYS_RndInit(&p_ctx->crys_rnd_state, p_work_buffer); + ret_val = result_get(err_code); + + cc310_backend_mutex_unlock(); + + return ret_val; +} + + +ret_code_t nrf_crypto_rng_backend_uninit(void * const p_context) +{ + bool mutex_locked; + CRYSError_t err_code; + ret_code_t ret_val; + CRYS_RND_State_t * p_crys_rnd_state = + &((nrf_crypto_backend_rng_context_t *)p_context)->crys_rnd_state; + + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + err_code = CRYS_RND_UnInstantiation(p_crys_rnd_state); + + ret_val = result_get(err_code); + + cc310_backend_mutex_unlock(); + + return ret_val; +} + + +ret_code_t nrf_crypto_rng_backend_vector_generate(void * const p_context, + uint8_t * const p_target, + size_t size, + bool use_mutex) +{ + bool mutex_locked; + CRYSError_t err_code; + ret_code_t ret_val; + CRYS_RND_State_t * p_crys_rnd_state = + &((nrf_crypto_backend_rng_context_t *)p_context)->crys_rnd_state; + + if (use_mutex) + { + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + } + + err_code = CRYS_RND_GenerateVector(p_crys_rnd_state, size, p_target); + + ret_val = result_get(err_code); + + if (use_mutex) + { + cc310_backend_mutex_unlock(); + } + + return ret_val; +} + + +ret_code_t nrf_crypto_rng_backend_reseed(void * const p_context, + void * p_temp_buffer, + uint8_t * p_input_data, + size_t size) +{ + bool mutex_locked; + CRYSError_t err_code; + ret_code_t ret_val = NRF_SUCCESS; + CRYS_RND_WorkBuff_t * p_work_buffer = (CRYS_RND_WorkBuff_t *)p_temp_buffer; + CRYS_RND_State_t * p_crys_rnd_state = + &((nrf_crypto_backend_rng_context_t *)p_context)->crys_rnd_state; + + VERIFY_TRUE(size <= CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS, NRF_ERROR_CRYPTO_INPUT_LENGTH); + VERIFY_TRUE((size & 0x3) == 0, NRF_ERROR_CRYPTO_INTERNAL); + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + if (size > 0) + { + err_code = CRYS_RND_AddAdditionalInput(p_crys_rnd_state, p_input_data, size); + ret_val = result_get(err_code); + if (ret_val != NRF_SUCCESS) + { + goto exit; + } + } + + err_code = CRYS_RND_Reseeding(p_crys_rnd_state, p_work_buffer); + ret_val = result_get(err_code); + +exit: + cc310_backend_mutex_unlock(); + return ret_val; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_RNG) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_rng.h b/components/libraries/crypto/backend/cc310/cc310_backend_rng.h new file mode 100644 index 0000000..820a9e1 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_rng.h @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BACKEND_RNG_H__ +#define CC310_BACKEND_RNG_H__ + +/** @file + * + * @defgroup nrf_crypto_cc310_backend_rng nRF Crypto CC310 RNG backend + * @{ + * @ingroup nrf_crypto_cc310_backend + * + * @brief RNG functionality provided by the nrf_crypto CC310 backend. + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_RNG) + +#include "nrf_crypto_rng_shared.h" +#include "crys_rnd.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) +#error "More than one RNG backend enabled." +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) +#define NRF_CRYPTO_RNG_ENABLED 1 + + +/** + * @internal @brief Internal context for CC310 RNG. + */ +typedef struct +{ + nrf_crypto_rng_internal_context_t header; //!< Internal common context header. + CRYS_RND_State_t crys_rnd_state; //!< CC310 RNG context +} nrf_crypto_backend_rng_context_t; + + +/** + * @internal @brief Temporary work buffer needed during initialization of the CC310 backend. + */ +typedef CRYS_RND_WorkBuff_t nrf_crypto_backend_rng_temp_buffer_t; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_RNG) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +/**@} */ + +#endif // CC310_BACKEND_RNG_H__ diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_shared.c b/components/libraries/crypto/backend/cc310/cc310_backend_shared.c new file mode 100644 index 0000000..5064321 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_shared.c @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) + +#include "nrf.h" +#include "cc310_backend_shared.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_rng.h" +#include "crys_rnd_error.h" +#include "nrf_crypto_shared.h" +#include "cc310_backend_shared.h" + +uint32_t nrf_crypto_backend_cc310_rng(void * p_state, uint16_t size, uint8_t * p_data) +{ +#if defined(NRF_CRYPTO_RNG_ENABLED) && (NRF_CRYPTO_RNG_ENABLED == 1) + + ret_code_t result = nrf_crypto_rng_vector_generate_no_mutex(p_data, (size_t)size); + if (result == NRF_SUCCESS) + { + return CRYS_OK; + } + else if (result == NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED) + { + return CRYS_RND_INSTANTIATION_NOT_DONE_ERROR; + } + else + { + return CRYS_RND_IS_NOT_SUPPORTED; + } + +#elif defined(NRF_CRYPTO_RNG_ENABLED) && (NRF_CRYPTO_RNG_ENABLED == 0) + + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + +#else + + #warning NRF_CRYPTO_RNG_ENABLED define not found in sdk_config.h (Is the sdk_config.h valid?). + +#endif // NRF_CRYPTO_RNG_ENABLED +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310) diff --git a/components/libraries/crypto/backend/cc310/cc310_backend_shared.h b/components/libraries/crypto/backend/cc310/cc310_backend_shared.h new file mode 100644 index 0000000..c96cc23 --- /dev/null +++ b/components/libraries/crypto/backend/cc310/cc310_backend_shared.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BACKEND_SHARED_H__ +#define CC310_BACKEND_SHARED_H__ + +/** @file + * + * @defgroup nrf_crypto_cc310_backend_shared nrf_crypto CC310 backend shared + * @{ + * @ingroup nrf_crypto_cc310_backend + * + * @brief Shared functionality for the nrf_crypto CC310 backend. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/**@internal @brief Macro definition for largest possible input data on CC310 DMA. */ +#define CC310_MAX_LENGTH_DMA_OPERATIONS (0xFFFF) +#define CC310_MAX_LENGTH_DMA_AES_OPERATIONS (0xFFF0) + + +/**@internal @brief Function to pass to CC310 library API as random number generator. It uses + * nrf_crypto libary frontend API to generate random number. + * @param[in,out] p_state Unused. Required by CC310 library API. + * @param[in] size Number of bytes in generated vector. + * @param[out] p_data Place where generated bytes will be written. + */ +uint32_t nrf_crypto_backend_cc310_rng(void * p_state, uint16_t size, uint8_t * p_data); + + +#ifdef __cplusplus +} +#endif + +/**@} */ + +#endif // CC310_BACKEND_SHARED_H__ diff --git a/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecc.c b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecc.c new file mode 100644 index 0000000..b244a91 --- /dev/null +++ b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecc.c @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +#include + +#include "nrf_crypto_mem.h" +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_shared.h" +#include "cc310_bl_backend_ecc.h" + + +#if defined(NRF_CRYPTO_BACKEND_CC310_BL_ECC_LITTLE_ENDIAN_ENABLED) + +#error The configuration NRF_CRYPTO_BACKEND_CC310_BL_ECC_LITTLE_ENDIAN_ENABLED was removed in SDK 15.1.0. Please see release notes for details on removing this error message. + +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1) + + +ret_code_t nrf_crypto_backend_secp224r1_public_key_from_raw( + void * p_public_key, + uint8_t const * p_raw_data) +{ + nrf_crypto_backend_secp224r1_public_key_t * p_pub = + (nrf_crypto_backend_secp224r1_public_key_t *)p_public_key; + + memcpy(&p_pub->public_key.x[0], + &p_raw_data[0], + NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE); + memcpy(&p_pub->public_key.y[0], + &p_raw_data[NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE], + NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_secp224r1_public_key_to_raw( + void const * p_public_key, + uint8_t * p_raw_data) +{ + nrf_crypto_backend_secp224r1_public_key_t const * p_pub = + (nrf_crypto_backend_secp224r1_public_key_t const *)p_public_key; + + memcpy(&p_raw_data[0], + &p_pub->public_key.x[0], + NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE); + memcpy(&p_raw_data[NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE], + &p_pub->public_key.y[0], + NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE); + + return NRF_SUCCESS; +} + + +nrf_crypto_ecc_curve_info_t const g_nrf_crypto_ecc_secp224r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_secp224r1_public_key_t), + .private_key_size = 0, + .curve_type = NRF_CRYPTO_ECC_SECP224R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP224R1_RAW_PUBLIC_KEY_SIZE, +}; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1) + + +ret_code_t nrf_crypto_backend_secp256r1_public_key_from_raw( + void * p_public_key, + uint8_t const * p_raw_data) +{ + nrf_crypto_backend_secp256r1_public_key_t * p_pub = + (nrf_crypto_backend_secp256r1_public_key_t *)p_public_key; + + memcpy(&p_pub->public_key.x[0], + &p_raw_data[0], + NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE); + memcpy(&p_pub->public_key.y[0], + &p_raw_data[NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE], + NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_secp256r1_public_key_to_raw( + void const * p_public_key, + uint8_t * p_raw_data) +{ + nrf_crypto_backend_secp256r1_public_key_t const * p_pub = + (nrf_crypto_backend_secp256r1_public_key_t const *)p_public_key; + + memcpy(&p_raw_data[0], + &p_pub->public_key.x[0], + NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE); + memcpy(&p_raw_data[NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE], + &p_pub->public_key.y[0], + NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE); + + return NRF_SUCCESS; +} + + +nrf_crypto_ecc_curve_info_t const g_nrf_crypto_ecc_secp256r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_secp256r1_public_key_t), + .private_key_size = 0, + .curve_type = NRF_CRYPTO_ECC_SECP256R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE, +}; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1) + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) diff --git a/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecc.h b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecc.h new file mode 100644 index 0000000..760ee18 --- /dev/null +++ b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecc.h @@ -0,0 +1,155 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BL_BACKEND_ECC_H__ +#define CC310_BL_BACKEND_ECC_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +#include "nrf_crypto_ecc_shared.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1) +#include "nrf_cc310_bl_ecdsa_verify_secp224r1.h" +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1) +#include "nrf_cc310_bl_ecdsa_verify_secp256r1.h" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP224R1) +#error "More than one backend enabled for secp224r1 (NIST 224-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP224R1_ENABLED 1 + +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + nrf_cc310_bl_ecc_public_key_secp224r1_t public_key; /**< @internal @brief CC310_BL specific key representation */ +} nrf_crypto_backend_secp224r1_public_key_t; + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_from_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_secp224r1_public_key_from_raw( + void * p_public_key, + uint8_t const * p_raw_data); + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_to_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_secp224r1_public_key_to_raw( + void const * p_public_key, + uint8_t * p_raw_data); + +// Dummy and empty definitions for unused symbols +#define nrf_crypto_backend_secp224r1_key_pair_generate NULL +#define nrf_crypto_backend_secp224r1_public_key_calculate NULL +#define nrf_crypto_backend_secp224r1_private_key_from_raw NULL +#define nrf_crypto_backend_secp224r1_private_key_to_raw NULL +#define nrf_crypto_backend_secp224r1_private_key_free NULL +#define nrf_crypto_backend_secp224r1_public_key_free NULL + +#define NRF_CRYPTO_BACKEND_SECP224R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP224R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +typedef uint32_t nrf_crypto_backend_secp224r1_private_key_t; +typedef uint32_t nrf_crypto_backend_secp224r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp224r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP256R1) +#error "More than one backend enabled for secp256r1 (NIST 256-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP256R1_ENABLED 1 + +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + nrf_cc310_bl_ecc_public_key_secp256r1_t public_key; /**< @internal @brief CC310_BL specific key representation */ +} nrf_crypto_backend_secp256r1_public_key_t; + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_from_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_secp256r1_public_key_from_raw( + void * p_public_key, + uint8_t const * p_raw_data); + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_to_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_secp256r1_public_key_to_raw( + void const * p_public_key, + uint8_t * p_raw_data); + +// Dummy and empty definitions for unused symbols +#define nrf_crypto_backend_secp256r1_key_pair_generate NULL +#define nrf_crypto_backend_secp256r1_public_key_calculate NULL +#define nrf_crypto_backend_secp256r1_private_key_from_raw NULL +#define nrf_crypto_backend_secp256r1_private_key_to_raw NULL +#define nrf_crypto_backend_secp256r1_private_key_free NULL +#define nrf_crypto_backend_secp256r1_public_key_free NULL + +#define NRF_CRYPTO_BACKEND_SECP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +typedef uint32_t nrf_crypto_backend_secp256r1_private_key_t; +typedef uint32_t nrf_crypto_backend_secp256r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp256r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +#endif // CC310_BL_BACKEND_ECC_H__ diff --git a/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecdh.h b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecdh.h new file mode 100644 index 0000000..e308222 --- /dev/null +++ b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecdh.h @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BL_BACKEND_ECDH_H__ +#define CC310_BL_BACKEND_ECDH_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdh_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1) +#define nrf_crypto_backend_secp224r1_ecdh_compute NULL +typedef uint32_t nrf_crypto_backend_secp224r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP224R1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1) +#define nrf_crypto_backend_secp256r1_ecdh_compute NULL +typedef uint32_t nrf_crypto_backend_secp256r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP256R1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1) + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +#endif // CC310_BL_BACKEND_ECDH_H__ diff --git a/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecdsa.c b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecdsa.c new file mode 100644 index 0000000..3f0219a --- /dev/null +++ b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecdsa.c @@ -0,0 +1,197 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + + +#if defined(NRF_CRYPTO_BACKEND_CC310_BL_ECC_LITTLE_ENDIAN_ENABLED) + +#error The configuration NRF_CRYPTO_BACKEND_CC310_BL_ECC_LITTLE_ENDIAN_ENABLED was removed in SDK 15.1.0. Please see release notes for details on removing this error message. + +#endif // defined(NRF_CRYPTO_BACKEND_CC310_BL_ECC_LITTLE_ENDIAN_ENABLED) + + + +#include +#include "app_util.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_mem.h" +#include "nrf_crypto_shared.h" +#include "cc310_bl_backend_ecdsa.h" +#include "cc310_bl_backend_shared.h" +#include "cc310_backend_mutex.h" +#include "crys_ecpki_error.h" + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1) || \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1) + +static ret_code_t crys_error_to_ret_code(CRYSError_t crys_error) +{ + switch (crys_error) + { + case CRYS_OK: + return NRF_SUCCESS; + + case CRYS_ECDSA_VERIFY_INCONSISTENT_VERIFY_ERROR: + return NRF_ERROR_CRYPTO_ECDSA_INVALID_SIGNATURE; + + default: + break; + } + + return NRF_ERROR_CRYPTO_INTERNAL; +} + +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1) + +STATIC_ASSERT(offsetof(nrf_cc310_bl_ecc_signature_secp224r1_t, r) == 0, + "Offset of r in nrf_cc310_bl_ecc_signature_secp224r1_t is unexpected"); +STATIC_ASSERT(offsetof(nrf_cc310_bl_ecc_signature_secp224r1_t, s) == + NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE, + "Offset of s in nrf_cc310_bl_ecc_signature_secp224r1_t is unexpected"); + + +ret_code_t nrf_crypto_backend_secp224r1_verify( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature) +{ + ret_code_t result; + CRYSError_t crys_error; + bool mutex_locked; + + nrf_crypto_backend_secp224r1_verify_context_t * p_ctx = + (nrf_crypto_backend_secp224r1_verify_context_t *)p_context; + + nrf_crypto_backend_secp224r1_public_key_t * p_pub = + (nrf_crypto_backend_secp224r1_public_key_t *)p_public_key; + + p_ctx->user_context.init_val = NRF_CC310_BL_ECDSA_CONTEXT_INITIALIZED; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + cc310_bl_backend_enable(); + + crys_error = nrf_cc310_bl_ecdsa_verify_secp224r1( + &p_ctx->user_context, + &p_pub->public_key, + (nrf_cc310_bl_ecc_signature_secp224r1_t const *)p_signature, + p_data, + data_size); + + cc310_bl_backend_disable(); + + cc310_backend_mutex_unlock(); + + result = crys_error_to_ret_code(crys_error); + + return result; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1) + + +STATIC_ASSERT(offsetof(nrf_cc310_bl_ecc_signature_secp256r1_t, r) == 0, + "Offset of r in nrf_cc310_bl_ecc_signature_secp256r1_t is unexpected"); + +STATIC_ASSERT(offsetof(nrf_cc310_bl_ecc_signature_secp256r1_t, s) == + NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE, + "Offset of s in nrf_cc310_bl_ecc_signature_secp256r1_t is unexpected"); + + +ret_code_t nrf_crypto_backend_secp256r1_verify( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature) +{ + ret_code_t result; + CRYSError_t crys_error; + bool mutex_locked; + + + nrf_crypto_backend_secp256r1_verify_context_t * p_ctx = + (nrf_crypto_backend_secp256r1_verify_context_t *)p_context; + + nrf_crypto_backend_secp256r1_public_key_t * p_pub = + (nrf_crypto_backend_secp256r1_public_key_t *)p_public_key; + + p_ctx->user_context.init_val = NRF_CC310_BL_ECDSA_CONTEXT_INITIALIZED; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + cc310_bl_backend_enable(); + + crys_error = nrf_cc310_bl_ecdsa_verify_secp256r1( + &p_ctx->user_context, + &p_pub->public_key, + (nrf_cc310_bl_ecc_signature_secp256r1_t const *)p_signature, + p_data, + data_size); + + cc310_bl_backend_disable(); + + cc310_backend_mutex_unlock(); + + result = crys_error_to_ret_code(crys_error); + + return result; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1) + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) diff --git a/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecdsa.h b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecdsa.h new file mode 100644 index 0000000..dbc9d57 --- /dev/null +++ b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_ecdsa.h @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BL_BACKEND_ECDSA_H__ +#define CC310_BL_BACKEND_ECDSA_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +#include "nrf_crypto_ecc_shared.h" +#include "nrf_crypto_ecdsa_shared.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1) +#include "nrf_cc310_bl_ecdsa_verify_secp224r1.h" +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1) +#include "nrf_cc310_bl_ecdsa_verify_secp256r1.h" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1) + +/** @internal @brief Common structure holding context for ECDSA verify. + */ +typedef struct +{ + nrf_cc310_bl_ecdsa_verify_context_secp224r1_t user_context; /**< @internal @brief Temporary buffer for CC310_BL internal storage */ +} nrf_crypto_backend_secp224r1_verify_context_t; + +#define NRF_CRYPTO_BACKEND_SECP224R1_VERIFY_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_secp224r1_verify_context_t) + +ret_code_t nrf_crypto_backend_secp224r1_verify( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature); + +// Dummy and empty definitions for unused symbols +#define NRF_CRYPTO_BACKEND_SECP224R1_SIGN_CONTEXT_SIZE 0 +typedef uint32_t nrf_crypto_backend_secp224r1_sign_context_t; +#define nrf_crypto_backend_secp224r1_sign NULL + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1) + +/** @internal @brief Common structure holding context for ECDSA verify. + */ +typedef struct +{ + nrf_cc310_bl_ecdsa_verify_context_secp256r1_t user_context; /**< @internal @brief Temporary buffer for CC310_BL internal storage */ +} nrf_crypto_backend_secp256r1_verify_context_t; + +#define NRF_CRYPTO_BACKEND_SECP256R1_VERIFY_CONTEXT_SIZE \ + sizeof(nrf_crypto_backend_secp256r1_verify_context_t) + +ret_code_t nrf_crypto_backend_secp256r1_verify( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature); + +// Dummy and empty definitions for unused symbols +#define NRF_CRYPTO_BACKEND_SECP256R1_SIGN_CONTEXT_SIZE 0 +typedef uint32_t nrf_crypto_backend_secp256r1_sign_context_t; +#define nrf_crypto_backend_secp256r1_sign NULL + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +#endif // CC310_BL_BACKEND_ECDSA_H__ diff --git a/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_hash.c b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_hash.c new file mode 100644 index 0000000..25d26e4 --- /dev/null +++ b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_hash.c @@ -0,0 +1,276 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +#include "nrf.h" +#include "cc310_bl_backend_hash.h" +#include "cc310_bl_backend_shared.h" +#include "cc310_backend_mutex.h" +#include "cc310_backend_shared.h" +#include "nrf_cc310_bl_hash_sha256.h" +#include "crys_hash_error.h" +#include "nrf_crypto_init.h" +#include "nrf_crypto_types.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_shared.h" +#include "nrf_crypto_hash_shared.h" +#include "sdk_macros.h" +#include "nrf_log.h" +#include "nrf_assert.h" +#include + + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256) + + +#if defined(NRF_CRYPTO_BACKEND_CC310_BL_HASH_LITTLE_ENDIAN_DIGEST_ENABLED) + +#error The configuration NRF_CRYPTO_BACKEND_CC310_BL_HASH_LITTLE_ENDIAN_DIGEST_ENABLED was removed in SDK 15.1.0. Please see release notes for details on removing this error message. + +#endif // defined(NRF_CRYPTO_BACKEND_CC310_BL_HASH_LITTLE_ENDIAN_DIGEST_ENABLED) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER) + +__ALIGN(4) static uint8_t m_hash_buffer[NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_SIZE]; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER) + + +static ret_code_t hash_result_get(CRYSError_t error) +{ + ret_code_t ret_val; + + switch (error) + { + case CRYS_OK: + ret_val = NRF_SUCCESS; + break; + + case CRYS_HASH_INVALID_USER_CONTEXT_POINTER_ERROR: + ret_val = NRF_ERROR_CRYPTO_CONTEXT_NULL; + break; + + case CRYS_HASH_ILLEGAL_OPERATION_MODE_ERROR: + ret_val = NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + break; + + case CRYS_HASH_USER_CONTEXT_CORRUPTED_ERROR: + ret_val = NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED; + break; + + // May be added to specialized errors for hash. + case CRYS_HASH_LAST_BLOCK_ALREADY_PROCESSED_ERROR: + ret_val = NRF_ERROR_CRYPTO_INTERNAL; + break; + + case CRYS_HASH_IS_NOT_SUPPORTED: + ret_val = NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + break; + + default: + ret_val = NRF_ERROR_CRYPTO_INTERNAL; + break; + } + + return ret_val; +} + + +static ret_code_t cc310_bl_backend_hash_sha256_init(void * const p_context) +{ + uint32_t ret_val; + CRYSError_t crys_error; + + // Limited parameter testing on this level. + // This has been done on upper level. + + nrf_cc310_bl_hash_context_sha256_t * const p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t *)p_context)->context); + + crys_error = nrf_cc310_bl_hash_sha256_init(p_backend_context); + + ret_val = hash_result_get(crys_error); + + return ret_val; +} + + +static uint32_t cc310_bl_backend_hash_sha256_update(void * const p_context, + uint8_t const * p_data, + size_t size) +{ + ret_code_t ret_val; + CRYSError_t crys_error; + uint32_t cur_size; + uint32_t size_left; + uint8_t * p_cur; + bool mutex_locked; + + // Limited parameter testing on this level. + // This has been done on upper level. + + nrf_cc310_bl_hash_context_sha256_t * const p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t *)p_context)->context); + + p_cur = (uint8_t *)p_data; + size_left = size; + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + cc310_bl_backend_enable(); + +#if defined (NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_ENABLED) && (NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_ENABLED == 1) + + do + { + // Copy a block from FLASH to RAM for use in CC310 + cur_size = (size_left > NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_SIZE) ? + NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_SIZE : size_left; + + // Copy from FLASH to ram + memcpy(m_hash_buffer, p_cur, cur_size); + + // Update the hash with current input. + crys_error = nrf_cc310_bl_hash_sha256_update(p_backend_context, m_hash_buffer, cur_size); + + size_left -= cur_size; + p_cur += cur_size; + + } while(crys_error == SASI_OK && size_left > 0); + +#elif defined(NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_ENABLED) && (NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_ENABLED == 0) + + // Verify that the data is in RAM (required for CC310 hashing) + VERIFY_TRUE(nrfx_is_in_ram(p_data), NRF_ERROR_CRYPTO_INPUT_LOCATION); + + do + { + // Get the largest block that can sent to the CC310 through DMA + cur_size = (size_left > CC310_MAX_LENGTH_DMA_OPERATIONS) ? + CC310_MAX_LENGTH_DMA_OPERATIONS : size_left; + + crys_error = nrf_cc310_bl_hash_sha256_update(p_backend_context, p_cur, cur_size); + + size_left -= cur_size; + p_cur += cur_size; + } while(crys_error == SASI_OK && size_left > 0); + +#else + + UNUSED_PARAMETER(p_backend_context); + UNUSED_PARAMETER(cur_size); + UNUSED_PARAMETER(size_left); + UNUSED_PARAMETER(p_cur); + + #warning NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_ENABLED define not found in sdk_config.h (Is the sdk_config.h valid?). + +#endif + + cc310_bl_backend_disable(); + + cc310_backend_mutex_unlock(); + + ret_val = hash_result_get(crys_error); + + return ret_val; +} + + +static uint32_t cc310_bl_backend_hash_sha256_finalize(void * const p_context, + uint8_t * p_digest, + size_t * const p_digest_size) +{ + ret_code_t ret_val; + CRYSError_t crys_error; + bool mutex_locked; + + // Limited parameter testing on this level. + // This has been done on upper level. + + nrf_cc310_bl_hash_context_sha256_t * const p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t * )p_context)->context); + + nrf_cc310_bl_hash_digest_sha256_t * p_int_digest + = (nrf_cc310_bl_hash_digest_sha256_t *)p_digest; + + if (NRF_CRYPTO_HASH_SIZE_SHA256 > *p_digest_size) + { + return NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + } + + mutex_locked = cc310_backend_mutex_trylock(); + VERIFY_TRUE(mutex_locked, NRF_ERROR_CRYPTO_BUSY); + + cc310_bl_backend_enable(); + + // Do the hash finalize calculation + crys_error = nrf_cc310_bl_hash_sha256_finalize(p_backend_context, p_int_digest); + + cc310_bl_backend_disable(); + + cc310_backend_mutex_unlock(); + + ret_val = hash_result_get(crys_error); + + if (ret_val == NRF_SUCCESS) + { + *p_digest_size = NRF_CRYPTO_HASH_SIZE_SHA256; + } + + return ret_val; +} + +const nrf_crypto_hash_info_t g_nrf_crypto_hash_sha256_info = +{ + .init_fn = cc310_bl_backend_hash_sha256_init, + .update_fn = cc310_bl_backend_hash_sha256_update, + .finalize_fn = cc310_bl_backend_hash_sha256_finalize, + .digest_size = NRF_CRYPTO_HASH_SIZE_SHA256, + .hash_mode = NRF_CRYPTO_HASH_MODE_SHA256 +}; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256) + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && #if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) diff --git a/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_hash.h b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_hash.h new file mode 100644 index 0000000..8a66164 --- /dev/null +++ b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_hash.h @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BL_BACKEND_HASH_H__ +#define CC310_BL_BACKEND_HASH_H__ + +/** @file + * + * @defgroup nrf_crypto_cc310_bl_backend_hash nrf_crypto CC310_BL backend hash + * @{ + * @ingroup nrf_crypto_cc310_bl_backend + * + * @brief Hash functionality provided by the nrf_crypto CC310_BL backend. + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +#include "sdk_errors.h" +#include "nrf_crypto_hash_shared.h" +#include "nrf_cc310_bl_hash_sha256.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256) + +// Flag that nrf_crypto_hash frontend can be compiled +#undef NRF_CRYPTO_HASH_ENABLED +#define NRF_CRYPTO_HASH_ENABLED 1 + +// Flag that SHA-256 is enabled in backend +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HASH_SHA256) +#error "Duplicate definition of SHA-256. More than one backend enabled"); +#endif +#define NRF_CRYPTO_HASH_SHA256_ENABLED 1 + + +/**@internal @brief nrf_crypto_hash context for SHA-256 in nrf_crypto CC310_BL backend. */ +typedef struct +{ + nrf_crypto_hash_internal_context_t header; /**< Common header for context. */ + nrf_cc310_bl_hash_context_sha256_t context; /**< Hash context internal to CC310_BL. */ +} nrf_crypto_backend_hash_sha256_context_t; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256) + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +/**@} */ + +#endif // CC310_BL_BACKEND_HASH_H__ diff --git a/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_init.c b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_init.c new file mode 100644 index 0000000..3b9df48 --- /dev/null +++ b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_init.c @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +#include "nrf.h" +#include "nrf_crypto_init.h" +#include "nrf_crypto_error.h" + +#include "cc310_bl_backend_shared.h" +#include "cc310_backend_mutex.h" +#include "sns_silib.h" +#include "nrf_cc310_bl_init.h" + +/**@brief Mutex to ensure single access to nrf_cc310_bl resources */ +nrf_mtx_t g_cc310_mutex; + +static uint32_t init_result_get(uint32_t crys_error) +{ + uint32_t ret_val = NRF_ERROR_INTERNAL; + switch (crys_error) + { + case SA_SILIB_RET_OK: + ret_val = NRF_SUCCESS; + break; + + case SA_SILIB_RET_EINVAL_HW_VERSION: + ret_val = NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + break; + + default: + ret_val = NRF_ERROR_INTERNAL; + break; + } + + return ret_val; +} + + +static ret_code_t cc310_bl_backend_init(void) +{ + uint32_t ret_val; + CRYSError_t crys_error; + + cc310_backend_mutex_init(); + + // Enable the CC310 HW. + NRF_CRYPTOCELL->ENABLE = 1; + + // Initialize the CC310_BL run-time library + crys_error = nrf_cc310_bl_init(); + + // Disable the CC310 HW after initialization. + NRF_CRYPTOCELL->ENABLE = 0; + + ret_val = init_result_get(crys_error); + + return ret_val; +} + + +static ret_code_t cc310_bl_backend_uninit(void) +{ + // Disable the CC310 HW. + NRF_CRYPTOCELL->ENABLE = 0; + + return NRF_SUCCESS; +} + + +CRYPTO_BACKEND_REGISTER(nrf_crypto_backend_info_t const cc310_bl_backend) = +{ + .init_fn = cc310_bl_backend_init, + .uninit_fn = cc310_bl_backend_uninit +}; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) diff --git a/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_shared.c b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_shared.c new file mode 100644 index 0000000..1e2298a --- /dev/null +++ b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_shared.c @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +#include "nrf.h" +#include "cc310_bl_backend_shared.h" +#include "nrf_crypto_error.h" + + +void cc310_bl_backend_enable(void) +{ + // Enable the cryptocell hardware + NRF_CRYPTOCELL->ENABLE = 1; + +#if defined(NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED) && (NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED == 1) + + // Enable the CryptoCell IRQ + NVIC_EnableIRQ(CRYPTOCELL_IRQn); + +#elif defined(NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED) && (NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED == 0) + + // Do nothing + +#else + + #warning NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED define not found in sdk_config.h (Is the sdk_config.h valid?). + +#endif + +} + + +void cc310_bl_backend_disable(void) +{ + // Enable the cryptocell hardware + NRF_CRYPTOCELL->ENABLE = 0; + +#if defined(NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED) && (NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED == 1) + + // Disable the CryptoCell IRQ + NVIC_DisableIRQ(CRYPTOCELL_IRQn); + +#elif defined(NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED) && (NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED == 0) + + // Do nothing + +#else + + #warning NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED define not found in sdk_config.h (Is the sdk_config.h valid?). + +#endif + +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) diff --git a/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_shared.h b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_shared.h new file mode 100644 index 0000000..4ee7ec3 --- /dev/null +++ b/components/libraries/crypto/backend/cc310_bl/cc310_bl_backend_shared.h @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CC310_BL_BACKEND_SHARED_H__ +#define CC310_BL_BACKEND_SHARED_H__ + +/** @file + * + * @defgroup nrf_crypto_cc310_bl_backend_shared nrf_crypto CC310_BL backend shared + * @{ + * @ingroup nrf_crypto_cc310_bl_backend + * + * @brief Shared functionality for the nrf_crypto CC310_BL backend. + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +#include "sdk_errors.h" +#include "nrf_crypto_hash_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@internal @brief Function to enable CC310 (in HW) + */ +void cc310_bl_backend_enable(void); + + +/**@internal @brief Function to disable CC310 (in HW) + */ +void cc310_bl_backend_disable(void); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL) + +/**@} */ + +#endif // CC310_BL_BACKEND_SHARED_H__ diff --git a/components/libraries/crypto/backend/cifra/cifra_backend_aes_aead.c b/components/libraries/crypto/backend/cifra/cifra_backend_aes_aead.c new file mode 100644 index 0000000..af04ec8 --- /dev/null +++ b/components/libraries/crypto/backend/cifra/cifra_backend_aes_aead.c @@ -0,0 +1,205 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include +#include "cifra_backend_aes_aead.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_CIFRA_AES_AEAD) + +/**@internal @brief Type declaration of a template matching all possible context sizes + * for this backend. + */ +typedef struct +{ + nrf_crypto_aead_internal_context_t header; /**< Common header for context. */ + cf_aes_context context; +} nrf_crypto_backend_cifra_aes_aead_context_t; + + +static ret_code_t result_get(int error) +{ + switch (error) + { + case 0: + return NRF_SUCCESS; + + case 1: + return NRF_ERROR_CRYPTO_AEAD_INVALID_MAC; + + default: + return NRF_ERROR_CRYPTO_INTERNAL; + } +} + +static ret_code_t backend_cifra_init(void * const p_context, uint8_t * p_key) +{ + nrf_crypto_backend_cifra_aes_aead_context_t * p_ctx = + (nrf_crypto_backend_cifra_aes_aead_context_t *)p_context; + + if ((p_ctx->header.p_info->key_size != NRF_CRYPTO_KEY_SIZE_128) && + (p_ctx->header.p_info->key_size != NRF_CRYPTO_KEY_SIZE_192) && + (p_ctx->header.p_info->key_size != NRF_CRYPTO_KEY_SIZE_256)) + { + return NRF_ERROR_CRYPTO_KEY_SIZE; + } + + VERIFY_TRUE((p_ctx->header.p_info->mode == NRF_CRYPTO_AEAD_MODE_AES_EAX), + NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE); + + cf_aes_init(&p_ctx->context, + p_key, + (p_ctx->header.p_info->key_size)>>3); // >>3: changes bits to bytes + + return NRF_SUCCESS; +} + + +static ret_code_t backend_cifra_uninit(void * const p_context) +{ + nrf_crypto_backend_cifra_aes_aead_context_t * p_ctx = + (nrf_crypto_backend_cifra_aes_aead_context_t *)p_context; + + cf_aes_finish(&p_ctx->context); + + return NRF_SUCCESS; +} + +static ret_code_t backend_cifra_crypt(void * const p_context, + nrf_crypto_operation_t operation, + uint8_t * p_nonce, + uint8_t nonce_size, + uint8_t * p_adata, + size_t adata_size, + uint8_t * p_data_in, + size_t data_in_size, + uint8_t * p_data_out, + uint8_t * p_mac, + uint8_t mac_size) +{ + + int result; + ret_code_t ret_val; + + nrf_crypto_backend_cifra_aes_aead_context_t * p_ctx = + (nrf_crypto_backend_cifra_aes_aead_context_t *)p_context; + + ret_val = NRF_SUCCESS; + + /* EAX mode allows following mac size: [1 ... 16] */ + if ((mac_size < 1) || (mac_size > NRF_CRYPTO_AES_BLOCK_SIZE)) + { + return NRF_ERROR_CRYPTO_AEAD_MAC_SIZE; + } + + if (operation == NRF_CRYPTO_ENCRYPT) + { + cf_eax_encrypt(&cf_aes, + &p_ctx->context, + p_data_in, + data_in_size, + p_adata, + adata_size, + p_nonce, + (size_t)nonce_size, + p_data_out, + p_mac, + mac_size); + } + else if (operation == NRF_CRYPTO_DECRYPT) + { + result = cf_eax_decrypt(&cf_aes, + &p_ctx->context, + p_data_in, + data_in_size, + p_adata, + adata_size, + p_nonce, + (size_t)nonce_size, + p_mac, + mac_size, + p_data_out); + ret_val = result_get(result); + } + else + { + return NRF_ERROR_CRYPTO_INVALID_PARAM; + } + + return ret_val; +} + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CIFRA_AES_EAX) +nrf_crypto_aead_info_t const g_nrf_crypto_aes_eax_128_info = +{ + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .mode = NRF_CRYPTO_AEAD_MODE_AES_EAX, + + .init_fn = backend_cifra_init, + .uninit_fn = backend_cifra_uninit, + .crypt_fn = backend_cifra_crypt +}; + +nrf_crypto_aead_info_t const g_nrf_crypto_aes_eax_192_info = +{ + .key_size = NRF_CRYPTO_KEY_SIZE_192, + .mode = NRF_CRYPTO_AEAD_MODE_AES_EAX, + + .init_fn = backend_cifra_init, + .uninit_fn = backend_cifra_uninit, + .crypt_fn = backend_cifra_crypt +}; + +nrf_crypto_aead_info_t const g_nrf_crypto_aes_eax_256_info = +{ + .key_size = NRF_CRYPTO_KEY_SIZE_256, + .mode = NRF_CRYPTO_AEAD_MODE_AES_EAX, + + .init_fn = backend_cifra_init, + .uninit_fn = backend_cifra_uninit, + .crypt_fn = backend_cifra_crypt +}; +#endif + +#endif // MODULE_ENABLED(NRF_CRYPTO_AES_CCM_BACKEND_MBEDTLS) +#endif // MODULE_ENABLED(NRF_CRYPTO) diff --git a/components/libraries/crypto/backend/cifra/cifra_backend_aes_aead.h b/components/libraries/crypto/backend/cifra/cifra_backend_aes_aead.h new file mode 100644 index 0000000..bf7e692 --- /dev/null +++ b/components/libraries/crypto/backend/cifra/cifra_backend_aes_aead.h @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CIFRA_BACKEND_AES_AEAD_H__ +#define CIFRA_BACKEND_AES_AEAD_H__ + +/** @file + * + * @defgroup nrf_crypto_cifra_backend_aes_aead nrf_crypto Cifra backend AES AEAD + * @{ + * @ingroup nrf_crypto_cifra_backend + * + * @brief AES AEAD functionality provided by the nrf_crypto Cifra backend. + */ + +#include "sdk_config.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CIFRA) + +#include "modes.h" +#include "cifra_eax_aes.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_types.h" +#include "nrf_crypto_aead_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* AES EAX */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CIFRA_AES_EAX) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_EAX) +#error "Duplicate definition of AES EAX mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_AES_EAX_ENABLED 1 +#undef NRF_CRYPTO_AEAD_ENABLED +#define NRF_CRYPTO_AEAD_ENABLED 1 // Flag that nrf_crypto_aes_aead frontend can be compiled +#undef NRF_CRYPTO_CIFRA_AES_AEAD_ENABLED +#define NRF_CRYPTO_CIFRA_AES_AEAD_ENABLED 1 // aes_aead backend cifra can be compiled + +/* defines for test purposes */ +#define NRF_CRYPTO_AES_EAX_128_ENABLED 1 +#define NRF_CRYPTO_AES_EAX_192_ENABLED 1 +#define NRF_CRYPTO_AES_EAX_256_ENABLED 1 + +typedef struct +{ + nrf_crypto_aead_internal_context_t header; /**< Common header for context. */ + cf_aes_context context; /**< AES EAX context internal to Cifra. */ +} nrf_crypto_backend_aes_eax_context_t; +#endif + +#ifdef __cplusplus +} +#endif +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CIFRA) + +/** @} */ + +#endif // CIFRA_BACKEND_AES_AEAD_H__ + diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_aes.c b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_aes.c new file mode 100644 index 0000000..099d0b2 --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_aes.c @@ -0,0 +1,1213 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +/*lint -save -e????*/ +#include "mbedtls/md.h" +#include "mbedtls/aes.h" +#include "mbedtls/cipher.h" +/*lint -restore*/ +#include "nrf_crypto_error.h" +#include "mbedtls_backend_aes.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_MBEDTLS_AES) + +/* macro changing bits to bytes */ +#define BITS_TO_BYTES(bits) ((bits)>>3) +#define BACKEND_ERROR_CHECK(error) \ + do { \ + if ((error) != 0) \ + { \ + return result_get((error)); \ + } \ + } while (0); + +/**@internal @brief Type declarations of templates matching all possible context sizes + * for this backend. + */ +typedef struct +{ + nrf_crypto_aes_internal_context_t header; /**< Common header for context. */ + nrf_crypto_backend_aes_ctx_t backend; /**< Backend-specific internal context. */ + uint32_t context[1]; /**< AES context internal to mbed TLS. */ +} nrf_crypto_backend_mbedtls_aes_any_context_t; + +/**@internal @brief Type declarations of templates matching all possible context sizes + * for this backend. + */ +typedef union +{ + nrf_crypto_backend_mbedtls_aes_any_context_t any; /**< Common for all contexts. */ + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB) + nrf_crypto_backend_aes_ecb_context_t ecb; +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC) + nrf_crypto_backend_aes_cbc_context_t cbc; +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CTR) + nrf_crypto_backend_aes_ctr_context_t ctr; +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CFB) + nrf_crypto_backend_aes_cfb_context_t cfb; +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC) + nrf_crypto_backend_aes_cbc_mac_context_t cbc_mac; +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC) + nrf_crypto_backend_aes_cmac_context_t cmac; +#endif +} nrf_crypto_backend_mbedtls_aes_context_t; + + +static ret_code_t result_get(int error) +{ + ret_code_t ret_val; + switch (error) + { + case 0: + ret_val = NRF_SUCCESS; + break; + + case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH: + ret_val = NRF_ERROR_CRYPTO_INPUT_LENGTH; + break; + + case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA: + ret_val = NRF_ERROR_CRYPTO_INPUT_LENGTH; + break; + + case MBEDTLS_ERR_CIPHER_ALLOC_FAILED: + ret_val = NRF_ERROR_CRYPTO_ALLOC_FAILED; + break; + + case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE: + ret_val = NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + break; + + case MBEDTLS_ERR_MD_BAD_INPUT_DATA: + ret_val = NRF_ERROR_CRYPTO_INVALID_PARAM; + break; + + default: + ret_val = NRF_ERROR_CRYPTO_INTERNAL; + break; + } + + return ret_val; +} + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC) +static ret_code_t backend_cmac_init(nrf_crypto_backend_aes_cmac_context_t * const p_cmac_ctx) +{ + int error; + + mbedtls_cipher_type_t cipher_type; + mbedtls_cipher_info_t const * p_cipher_info; + + mbedtls_cipher_init(&p_cmac_ctx->context); + + switch (p_cmac_ctx->header.p_info->key_size) + { + case NRF_CRYPTO_KEY_SIZE_128: + cipher_type = MBEDTLS_CIPHER_AES_128_ECB; + break; + + case NRF_CRYPTO_KEY_SIZE_192: + cipher_type = MBEDTLS_CIPHER_AES_192_ECB; + break; + + case NRF_CRYPTO_KEY_SIZE_256: + cipher_type = MBEDTLS_CIPHER_AES_256_ECB; + break; + + default: + return NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED; + } + + p_cipher_info = mbedtls_cipher_info_from_type(cipher_type); + + if (p_cipher_info == NULL) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + error = mbedtls_cipher_setup(&p_cmac_ctx->context, p_cipher_info); + BACKEND_ERROR_CHECK(error); + + return NRF_SUCCESS; +} +#endif + +static ret_code_t backend_mbedtls_init(void * const p_context, nrf_crypto_operation_t operation) +{ + ret_code_t ret_val = NRF_SUCCESS; + + nrf_crypto_backend_mbedtls_aes_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_aes_context_t *)p_context; + + switch (p_ctx->any.header.p_info->key_size) + { + case NRF_CRYPTO_KEY_SIZE_128: + case NRF_CRYPTO_KEY_SIZE_192: + case NRF_CRYPTO_KEY_SIZE_256: + break; + + default: + return NRF_ERROR_CRYPTO_KEY_SIZE; + } + + switch (p_ctx->any.header.p_info->mode) + { +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC) + case NRF_CRYPTO_AES_MODE_CBC: + case NRF_CRYPTO_AES_MODE_CBC_PAD_PCKS7: + VERIFY_FALSE(((operation != NRF_CRYPTO_ENCRYPT) && (operation != NRF_CRYPTO_DECRYPT)), + NRF_ERROR_CRYPTO_INVALID_PARAM); + memset(&p_ctx->cbc.backend, 0, sizeof(p_ctx->cbc.backend)); + + mbedtls_aes_init(&p_ctx->cbc.context); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CTR) + case NRF_CRYPTO_AES_MODE_CTR: + VERIFY_FALSE(((operation != NRF_CRYPTO_ENCRYPT) && (operation != NRF_CRYPTO_DECRYPT)), + NRF_ERROR_CRYPTO_INVALID_PARAM); + memset(&p_ctx->ctr.backend, 0, sizeof(p_ctx->ctr.backend)); + + mbedtls_aes_init(&p_ctx->ctr.context); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CFB) + case NRF_CRYPTO_AES_MODE_CFB: + VERIFY_FALSE(((operation != NRF_CRYPTO_ENCRYPT) && (operation != NRF_CRYPTO_DECRYPT)), + NRF_ERROR_CRYPTO_INVALID_PARAM); + memset(&p_ctx->cfb.backend, 0, sizeof(p_ctx->cfb.backend)); + + mbedtls_aes_init(&p_ctx->cfb.context); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB) + case NRF_CRYPTO_AES_MODE_ECB: + case NRF_CRYPTO_AES_MODE_ECB_PAD_PCKS7: + VERIFY_FALSE(((operation != NRF_CRYPTO_ENCRYPT) && (operation != NRF_CRYPTO_DECRYPT)), + NRF_ERROR_CRYPTO_INVALID_PARAM); + memset(&p_ctx->ecb.backend, 0, sizeof(p_ctx->ecb.backend)); + + mbedtls_aes_init(&p_ctx->ecb.context); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC) + case NRF_CRYPTO_AES_MODE_CBC_MAC: + case NRF_CRYPTO_AES_MODE_CBC_MAC_PAD_PCKS7: + VERIFY_TRUE((operation == NRF_CRYPTO_MAC_CALCULATE), NRF_ERROR_CRYPTO_INVALID_PARAM); + memset(&p_ctx->cbc_mac.backend, 0, sizeof(p_ctx->cbc_mac.backend)); + + mbedtls_aes_init(&p_ctx->cbc_mac.context); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC) + case NRF_CRYPTO_AES_MODE_CMAC: + VERIFY_TRUE((operation == NRF_CRYPTO_MAC_CALCULATE), NRF_ERROR_CRYPTO_INVALID_PARAM); + + ret_val = backend_cmac_init(&p_ctx->cmac); + break; +#endif + default: + ret_val = NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + break; + } + + p_ctx->any.backend.operation = operation; + + return ret_val; +} + +static ret_code_t backend_mbedtls_uninit(void * const p_context) +{ + nrf_crypto_backend_mbedtls_aes_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_aes_context_t *)p_context; + + switch (p_ctx->any.header.p_info->mode) + { +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC) + case NRF_CRYPTO_AES_MODE_CBC: + case NRF_CRYPTO_AES_MODE_CBC_PAD_PCKS7: + mbedtls_aes_free(&p_ctx->cbc.context); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CTR) + case NRF_CRYPTO_AES_MODE_CTR: + mbedtls_aes_free(&p_ctx->ctr.context); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CFB) + case NRF_CRYPTO_AES_MODE_CFB: + mbedtls_aes_free(&p_ctx->cfb.context); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB) + case NRF_CRYPTO_AES_MODE_ECB: + case NRF_CRYPTO_AES_MODE_ECB_PAD_PCKS7: + mbedtls_aes_free(&p_ctx->ecb.context); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC) + case NRF_CRYPTO_AES_MODE_CBC_MAC: + case NRF_CRYPTO_AES_MODE_CBC_MAC_PAD_PCKS7: + mbedtls_aes_free(&p_ctx->cbc_mac.context); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC) + case NRF_CRYPTO_AES_MODE_CMAC: + mbedtls_cipher_free(&p_ctx->cmac.context); + break; +#endif + + default: + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + } + + return NRF_SUCCESS; +} + +static ret_code_t backend_mbedtls_key_set(void * const p_context, uint8_t * p_key) +{ + int error; + ret_code_t ret_val; + + nrf_crypto_backend_mbedtls_aes_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_aes_context_t *)p_context; + + switch (p_ctx->any.header.p_info->mode) + { +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC) + case NRF_CRYPTO_AES_MODE_CBC: + case NRF_CRYPTO_AES_MODE_CBC_PAD_PCKS7: + if (p_ctx->cbc.backend.operation == NRF_CRYPTO_ENCRYPT) + { + error = mbedtls_aes_setkey_enc(&p_ctx->cbc.context, + (uint8_t const *)p_key, + p_ctx->cbc.header.p_info->key_size); + } + else + { + error = mbedtls_aes_setkey_dec(&p_ctx->cbc.context, + (uint8_t const *)p_key, + p_ctx->cbc.header.p_info->key_size); + } + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CTR) + case NRF_CRYPTO_AES_MODE_CTR: + /* Due to the nature of CFB / CTR, you should use the same key schedule for both + encryption and decryption.*/ + error = mbedtls_aes_setkey_enc(&p_ctx->ctr.context, + (uint8_t const *)p_key, + p_ctx->ctr.header.p_info->key_size); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CFB) + case NRF_CRYPTO_AES_MODE_CFB: + /* Due to the nature of CFB / CTR, you should use the same key schedule for both + encryption and decryption.*/ + error = mbedtls_aes_setkey_enc(&p_ctx->cfb.context, + (uint8_t const *)p_key, + p_ctx->cfb.header.p_info->key_size); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB) + case NRF_CRYPTO_AES_MODE_ECB: + case NRF_CRYPTO_AES_MODE_ECB_PAD_PCKS7: + if (p_ctx->ecb.backend.operation == NRF_CRYPTO_ENCRYPT) + { + error = mbedtls_aes_setkey_enc(&p_ctx->ecb.context, + (uint8_t const *)p_key, + p_ctx->ecb.header.p_info->key_size); + } + else + { + error = mbedtls_aes_setkey_dec(&p_ctx->ecb.context, + (uint8_t const *)p_key, + p_ctx->ecb.header.p_info->key_size); + } + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC) + case NRF_CRYPTO_AES_MODE_CBC_MAC: + case NRF_CRYPTO_AES_MODE_CBC_MAC_PAD_PCKS7: + error = mbedtls_aes_setkey_enc(&p_ctx->cbc_mac.context, + (uint8_t const *)p_key, + p_ctx->cbc_mac.header.p_info->key_size); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC) + case NRF_CRYPTO_AES_MODE_CMAC: + error = mbedtls_cipher_cmac_starts(&p_ctx->cmac.context, + p_key, + p_ctx->cmac.header.p_info->key_size); + break; +#endif + + default: + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + } + + ret_val = result_get(error); + + return ret_val; +} + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC) || \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CTR) || \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CFB) || \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC) +static ret_code_t backend_mbedtls_iv_set(void * const p_context, uint8_t * p_iv) +{ + nrf_crypto_backend_mbedtls_aes_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_aes_context_t *)p_context; + + memcpy(&p_ctx->any.backend.iv[0], p_iv, sizeof(p_ctx->any.backend.iv)); + + return NRF_SUCCESS; +} + +static ret_code_t backend_mbedtls_iv_get(void * const p_context, uint8_t * p_iv) +{ + nrf_crypto_backend_mbedtls_aes_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_aes_context_t *)p_context; + + memcpy(p_iv, p_ctx->any.backend.iv, sizeof(p_ctx->any.backend.iv)); + + return NRF_SUCCESS; +} +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB) +/* Function extending mbedtls_aes_crypt_ecb functionality. It allows to process more than 1 + data block. It is returning MBEDTLS error type. */ +static int backend_mbedtls_ecb_crypt(nrf_crypto_backend_aes_ecb_context_t * const p_ctx, + uint8_t * p_text_in, + uint8_t * p_text_out, + size_t text_size) +{ + int error = 0; + size_t crypted_text = 0; + + if ((text_size & 0x0F) != 0) + { + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + } + + while (crypted_text < text_size) + { + error = mbedtls_aes_crypt_ecb(&p_ctx->context, + (int)p_ctx->backend.operation, + p_text_in + crypted_text, + p_text_out + crypted_text); + if (error != 0) + { + break; + } + crypted_text += NRF_CRYPTO_AES_BLOCK_SIZE; + } + + return error; +} +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC) +static int backend_mbedtls_cbc_mac_update(void * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out) +{ + int error = 0; + + nrf_crypto_backend_mbedtls_aes_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_aes_context_t *)p_context; + + for (size_t i = 0; i < data_size; i += NRF_CRYPTO_AES_BLOCK_SIZE) + { + error = mbedtls_aes_crypt_cbc(&p_ctx->cbc_mac.context, + MBEDTLS_AES_ENCRYPT, + NRF_CRYPTO_AES_BLOCK_SIZE, + p_ctx->cbc_mac.backend.iv, + (uint8_t const *)p_data_in + i, + p_data_out); + if (error != 0) + { + return error; + } + } + + return error; +} + +static ret_code_t backend_mbedtls_cbc_mac_finalize(void * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out, + size_t * p_data_out_size) +{ + int error; + + if (*p_data_out_size < NRF_CRYPTO_AES_BLOCK_SIZE) + { + return NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + } + + /* this function does not support padding */ + if ((data_size & 0xF) != 0) + { + return NRF_ERROR_CRYPTO_INPUT_LENGTH; + } + + error = backend_mbedtls_cbc_mac_update(p_context, p_data_in, data_size, p_data_out); + BACKEND_ERROR_CHECK(error); + + *p_data_out_size = NRF_CRYPTO_AES_BLOCK_SIZE; + + return NRF_SUCCESS; +} + +static ret_code_t backend_mbedtls_cbc_mac_padding_finalize(void * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out, + size_t * p_data_out_size) +{ + ret_code_t ret_val; + uint8_t padding_buffer[NRF_CRYPTO_AES_BLOCK_SIZE] = {0}; + uint8_t msg_ending = (uint8_t)(data_size & (size_t)0x0F); + + if (*p_data_out_size < NRF_CRYPTO_AES_BLOCK_SIZE) + { + /* output buffer too small */ + return NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + } + + data_size -= msg_ending; + + if (data_size > 0) + { + ret_val = backend_mbedtls_cbc_mac_update(p_context, + p_data_in, + data_size, + p_data_out); + VERIFY_SUCCESS(ret_val); + } + + ret_val = padding_pkcs7_add(&padding_buffer[0], + p_data_in + data_size, + msg_ending); + VERIFY_SUCCESS(ret_val); + + ret_val = backend_mbedtls_cbc_mac_finalize(p_context, + &padding_buffer[0], + NRF_CRYPTO_AES_BLOCK_SIZE, + p_data_out, + p_data_out_size); + VERIFY_SUCCESS(ret_val); + + return ret_val; +} +#endif + +static ret_code_t backend_mbedtls_update(void * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out) +{ + int error; + + nrf_crypto_backend_mbedtls_aes_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_aes_context_t *)p_context; + + switch (p_ctx->any.header.p_info->mode) + { +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC) + case NRF_CRYPTO_AES_MODE_CBC: + case NRF_CRYPTO_AES_MODE_CBC_PAD_PCKS7: + error = mbedtls_aes_crypt_cbc(&p_ctx->cbc.context, + (int)p_ctx->cbc.backend.operation, + data_size, + p_ctx->cbc.backend.iv, + (uint8_t const *)p_data_in, + p_data_out); + break; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CTR) + case NRF_CRYPTO_AES_MODE_CTR: + { + size_t nc_off = 0; + uint8_t stream_block[NRF_CRYPTO_AES_BLOCK_SIZE]; + + error = mbedtls_aes_crypt_ctr(&p_ctx->ctr.context, + data_size, + &nc_off, + p_ctx->ctr.backend.iv, + stream_block, + (uint8_t const *)p_data_in, + p_data_out); + break; + } +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CFB) + case NRF_CRYPTO_AES_MODE_CFB: + error = mbedtls_aes_crypt_cfb8(&p_ctx->cfb.context, + (int)p_ctx->cfb.backend.operation, + data_size, + p_ctx->cfb.backend.iv, + (uint8_t const *)p_data_in, + p_data_out); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB) + case NRF_CRYPTO_AES_MODE_ECB: + case NRF_CRYPTO_AES_MODE_ECB_PAD_PCKS7: + error = backend_mbedtls_ecb_crypt(&p_ctx->ecb, p_data_in, p_data_out, data_size); + break; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC) + case NRF_CRYPTO_AES_MODE_CBC_MAC: + case NRF_CRYPTO_AES_MODE_CBC_MAC_PAD_PCKS7: + error = backend_mbedtls_cbc_mac_update(p_context, p_data_in, data_size, p_data_out); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC) + case NRF_CRYPTO_AES_MODE_CMAC: + error = mbedtls_cipher_cmac_update(&p_ctx->cmac.context, + p_data_in, + data_size); + break; +#endif + + default: + return NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED; + } + BACKEND_ERROR_CHECK(error); + + return NRF_SUCCESS; +} + +static ret_code_t backend_mbedtls_finalize(void * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out, + size_t * p_data_out_size) +{ + ret_code_t ret_val; + + nrf_crypto_backend_mbedtls_aes_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_aes_context_t *)p_context; + + if (*p_data_out_size < data_size) + { + return NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + } + + /* data is not multiple of 16 bytes */ + if ((data_size & 0x0F) != 0) + { + if ((p_ctx->any.header.p_info->mode != NRF_CRYPTO_AES_MODE_CTR) && + (p_ctx->any.header.p_info->mode != NRF_CRYPTO_AES_MODE_CFB)) + { + /* There are separate handlers for AES modes with padding and for MAC modes. */ + return NRF_ERROR_CRYPTO_INPUT_LENGTH; + } + } + + ret_val = backend_mbedtls_update(p_context, p_data_in, data_size, p_data_out); + VERIFY_SUCCESS(ret_val); + + *p_data_out_size = data_size; + + return ret_val; +} + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC) +static ret_code_t backend_mbedtls_cmac_finalize(void * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out, + size_t * p_data_out_size) +{ + int error; + + nrf_crypto_backend_mbedtls_aes_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_aes_context_t *)p_context; + + if (*p_data_out_size < NRF_CRYPTO_AES_BLOCK_SIZE) + { + return NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + } + + error = mbedtls_cipher_cmac_update(&p_ctx->cmac.context, p_data_in, data_size); + BACKEND_ERROR_CHECK(error); + + error = mbedtls_cipher_cmac_finish(&p_ctx->cmac.context, p_data_out); + BACKEND_ERROR_CHECK(error); + + *p_data_out_size = NRF_CRYPTO_AES_BLOCK_SIZE; + + return NRF_SUCCESS; +} +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC) || \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB) +static ret_code_t backend_mbedtls_padding_finalize(void * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out, + size_t * p_data_out_size) +{ + ret_code_t ret_val; + size_t buff_out_size; + uint8_t padding_buffer[NRF_CRYPTO_AES_BLOCK_SIZE] = {0}; + uint8_t msg_ending = (uint8_t)(data_size & (size_t)0x0F); + + nrf_crypto_backend_mbedtls_aes_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_aes_context_t *)p_context; + + if (p_ctx->any.backend.operation == NRF_CRYPTO_DECRYPT) + { + ret_val = backend_mbedtls_finalize(p_context, + p_data_in, + data_size, + p_data_out, + p_data_out_size); + VERIFY_SUCCESS(ret_val); + + ret_val = padding_pkcs7_remove(p_data_out, + p_data_out_size); + return ret_val; + } + + /* -------------- ENCRYPTION --------------*/ + data_size -= msg_ending; + + if (*p_data_out_size < (data_size + NRF_CRYPTO_AES_BLOCK_SIZE)) + { + /* no space for padding */ + return NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + } + + if (data_size > 0) + { + /* Encrypt 16 byte blocks */ + ret_val = backend_mbedtls_update(p_context, + p_data_in, + data_size, + p_data_out); + VERIFY_SUCCESS(ret_val); + } + + ret_val = padding_pkcs7_add(&padding_buffer[0], + p_data_in + data_size, + msg_ending); + VERIFY_SUCCESS(ret_val); + + buff_out_size = *p_data_out_size - data_size; + + ret_val = backend_mbedtls_finalize(p_context, + &padding_buffer[0], + NRF_CRYPTO_AES_BLOCK_SIZE, + p_data_out + data_size, + &buff_out_size); + VERIFY_SUCCESS(ret_val); + + *p_data_out_size = buff_out_size + data_size; + + return ret_val; +} +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC) +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_128_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_192_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC, + .key_size = NRF_CRYPTO_KEY_SIZE_192, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_256_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC, + .key_size = NRF_CRYPTO_KEY_SIZE_256, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_128_pad_pkcs7_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC_PAD_PCKS7, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_padding_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_192_pad_pkcs7_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC_PAD_PCKS7, + .key_size = NRF_CRYPTO_KEY_SIZE_192, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_padding_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_256_pad_pkcs7_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC_PAD_PCKS7, + .key_size = NRF_CRYPTO_KEY_SIZE_256, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_padding_finalize +}; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CTR) +nrf_crypto_aes_info_t const g_nrf_crypto_aes_ctr_128_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CTR, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_ctr_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_ctr_192_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CTR, + .key_size = NRF_CRYPTO_KEY_SIZE_192, + .context_size = sizeof(nrf_crypto_backend_aes_ctr_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_ctr_256_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CTR, + .key_size = NRF_CRYPTO_KEY_SIZE_256, + .context_size = sizeof(nrf_crypto_backend_aes_ctr_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_finalize +}; +#endif + +// CFB +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CFB) +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cfb_128_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CFB, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_cfb_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cfb_192_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CFB, + .key_size = NRF_CRYPTO_KEY_SIZE_192, + .context_size = sizeof(nrf_crypto_backend_aes_cfb_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cfb_256_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CFB, + .key_size = NRF_CRYPTO_KEY_SIZE_256, + .context_size = sizeof(nrf_crypto_backend_aes_cfb_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_finalize +}; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB) +nrf_crypto_aes_info_t const g_nrf_crypto_aes_ecb_128_info = +{ + .mode = NRF_CRYPTO_AES_MODE_ECB, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_ecb_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = NULL, + .iv_get_fn = NULL, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_ecb_192_info = +{ + .mode = NRF_CRYPTO_AES_MODE_ECB, + .key_size = NRF_CRYPTO_KEY_SIZE_192, + .context_size = sizeof(nrf_crypto_backend_aes_ecb_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = NULL, + .iv_get_fn = NULL, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_ecb_256_info = +{ + .mode = NRF_CRYPTO_AES_MODE_ECB, + .key_size = NRF_CRYPTO_KEY_SIZE_256, + .context_size = sizeof(nrf_crypto_backend_aes_ecb_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = NULL, + .iv_get_fn = NULL, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_ecb_128_pad_pkcs7_info = +{ + .mode = NRF_CRYPTO_AES_MODE_ECB_PAD_PCKS7, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_ecb_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = NULL, + .iv_get_fn = NULL, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_padding_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_ecb_192_pad_pkcs7_info = +{ + .mode = NRF_CRYPTO_AES_MODE_ECB_PAD_PCKS7, + .key_size = NRF_CRYPTO_KEY_SIZE_192, + .context_size = sizeof(nrf_crypto_backend_aes_ecb_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = NULL, + .iv_get_fn = NULL, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_padding_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_ecb_256_pad_pkcs7_info = +{ + .mode = NRF_CRYPTO_AES_MODE_ECB_PAD_PCKS7, + .key_size = NRF_CRYPTO_KEY_SIZE_256, + .context_size = sizeof(nrf_crypto_backend_aes_ecb_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = NULL, + .iv_get_fn = NULL, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_padding_finalize +}; +#endif + + +// CBC MAC +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC) +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_mac_128_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC_MAC, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_mac_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_cbc_mac_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_mac_192_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC_MAC, + .key_size = NRF_CRYPTO_KEY_SIZE_192, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_mac_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_cbc_mac_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_mac_256_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC_MAC, + .key_size = NRF_CRYPTO_KEY_SIZE_256, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_mac_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_cbc_mac_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_mac_128_pad_pkcs7_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC_MAC_PAD_PCKS7, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_mac_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_cbc_mac_padding_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_mac_192_pad_pkcs7_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC_MAC_PAD_PCKS7, + .key_size = NRF_CRYPTO_KEY_SIZE_192, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_mac_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_cbc_mac_padding_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cbc_mac_256_pad_pkcs7_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CBC_MAC_PAD_PCKS7, + .key_size = NRF_CRYPTO_KEY_SIZE_256, + .context_size = sizeof(nrf_crypto_backend_aes_cbc_mac_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = backend_mbedtls_iv_set, + .iv_get_fn = backend_mbedtls_iv_get, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_cbc_mac_padding_finalize +}; + +#endif + +// CMAC +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC) +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cmac_128_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CMAC, + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .context_size = sizeof(nrf_crypto_backend_aes_cmac_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = NULL, + .iv_get_fn = NULL, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_cmac_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cmac_192_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CMAC, + .key_size = NRF_CRYPTO_KEY_SIZE_192, + .context_size = sizeof(nrf_crypto_backend_aes_cmac_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = NULL, + .iv_get_fn = NULL, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_cmac_finalize +}; + +nrf_crypto_aes_info_t const g_nrf_crypto_aes_cmac_256_info = +{ + .mode = NRF_CRYPTO_AES_MODE_CMAC, + .key_size = NRF_CRYPTO_KEY_SIZE_256, + .context_size = sizeof(nrf_crypto_backend_aes_cmac_context_t), + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .key_set_fn = backend_mbedtls_key_set, + .iv_set_fn = NULL, + .iv_get_fn = NULL, + .update_fn = backend_mbedtls_update, + .finalize_fn = backend_mbedtls_cmac_finalize +}; +#endif + +#endif // #if NRF_MODULE_ENABLED(NRF_CRYPTO_MBEDTLS_AES) +#endif // MODULE_ENABLED(NRF_CRYPTO) + diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_aes.h b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_aes.h new file mode 100644 index 0000000..6ab63be --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_aes.h @@ -0,0 +1,227 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MBEDTLS_BACKEND_AES_H__ +#define MBEDTLS_BACKEND_AES_H__ + +/** @file + * + * @defgroup nrf_crypto_mbedtls_backend_aes nrf_crypto mbed TLS backend AES + * @{ + * @ingroup nrf_crypto_mbedtls_backend + * + * @brief AES functionality provided by the nrf_crypto mbed TLS backend. + */ + +#include "sdk_config.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +/*lint -save -e????*/ +#include "mbedtls/aes.h" +#include "mbedtls/cmac.h" +#include "mbedtls/platform.h" +/*lint -restore*/ +#include "nrf_crypto_error.h" +#include "nrf_crypto_types.h" +#include "nrf_crypto_aes_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* AES CBC */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CBC) +#error "Duplicate definition of AES CBC mode. More than one backend enabled"); +#endif +/* Flag that AES CBC is enabled in backend */ +#define NRF_CRYPTO_AES_CBC_ENABLED 1 +#undef NRF_CRYPTO_AES_ENABLED +#define NRF_CRYPTO_AES_ENABLED 1 // Flag that nrf_crypto_aes frontend can be compiled +#undef NRF_CRYPTO_MBEDTLS_AES_ENABLED +#define NRF_CRYPTO_MBEDTLS_AES_ENABLED 1 + +/* defines for test purposes */ +#define NRF_CRYPTO_AES_CBC_128_ENABLED 1 +#define NRF_CRYPTO_AES_CBC_192_ENABLED 1 +#define NRF_CRYPTO_AES_CBC_256_ENABLED 1 + +typedef struct +{ + nrf_crypto_aes_internal_context_t header; /**< Common header for context. */ + nrf_crypto_backend_aes_ctx_t backend; /**< Backend-specific internal context. */ + mbedtls_aes_context context; /**< AES context internal to mbed TLS. */ +} nrf_crypto_backend_aes_cbc_context_t; +#endif + + +/* AES CTR */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CTR) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CTR) +#error "Duplicate definition of AES CTR mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_AES_CTR_ENABLED 1 +#undef NRF_CRYPTO_AES_ENABLED +#define NRF_CRYPTO_AES_ENABLED 1 // Flag that nrf_crypto_aes frontend can be compiled +#undef NRF_CRYPTO_MBEDTLS_AES_ENABLED +#define NRF_CRYPTO_MBEDTLS_AES_ENABLED 1 + +/* defines for test purposes */ +#define NRF_CRYPTO_AES_CTR_128_ENABLED 1 +#define NRF_CRYPTO_AES_CTR_192_ENABLED 1 +#define NRF_CRYPTO_AES_CTR_256_ENABLED 1 + +typedef struct +{ + nrf_crypto_aes_internal_context_t header; /**< Common header for context. */ + nrf_crypto_backend_aes_ctx_t backend; /**< Backend-specific internal context. */ + mbedtls_aes_context context; /**< AES context internal to mbed TLS. */ +} nrf_crypto_backend_aes_ctr_context_t; +#endif + +/* AES CFB */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CFB) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CFB) +#error "Duplicate definition of AES CFB mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_AES_CFB_ENABLED 1 +#undef NRF_CRYPTO_AES_ENABLED +#define NRF_CRYPTO_AES_ENABLED 1 // Flag that nrf_crypto_aes frontend can be compiled +#undef NRF_CRYPTO_MBEDTLS_AES_ENABLED +#define NRF_CRYPTO_MBEDTLS_AES_ENABLED 1 + +/* defines for test purposes */ +#define NRF_CRYPTO_AES_CFB_128_ENABLED 1 +#define NRF_CRYPTO_AES_CFB_192_ENABLED 1 +#define NRF_CRYPTO_AES_CFB_256_ENABLED 1 + +typedef struct +{ + nrf_crypto_aes_internal_context_t header; /**< Common header for context. */ + nrf_crypto_backend_aes_ctx_t backend; /**< Backend-specific internal context. */ + mbedtls_aes_context context; /**< AES context internal to mbed TLS. */ +} nrf_crypto_backend_aes_cfb_context_t; +#endif + +/* AES ECB */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_ECB) +#error "Duplicate definition of AES ECB mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_AES_ECB_ENABLED 1 +#undef NRF_CRYPTO_AES_ENABLED +#define NRF_CRYPTO_AES_ENABLED 1 +#undef NRF_CRYPTO_MBEDTLS_AES_ENABLED +#define NRF_CRYPTO_MBEDTLS_AES_ENABLED 1 + +/* defines for test purposes */ +#define NRF_CRYPTO_AES_ECB_128_ENABLED 1 +#define NRF_CRYPTO_AES_ECB_192_ENABLED 1 +#define NRF_CRYPTO_AES_ECB_256_ENABLED 1 + +typedef struct +{ + nrf_crypto_aes_internal_context_t header; /**< Common header for context. */ + nrf_crypto_backend_no_iv_aes_ctx_t backend; /**< Backend-specific internal context. */ + mbedtls_aes_context context; /**< AES context internal to mbed TLS. */ +} nrf_crypto_backend_aes_ecb_context_t; +#endif + + +/* AES CBC MAC */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CBC_MAC) +#error "Duplicate definition of AES CBC MAC mode. More than one backend enabled"); +#endif +/* Flag that AES CBC MAC is enabled in backend */ +#define NRF_CRYPTO_AES_CBC_MAC_ENABLED 1 +#undef NRF_CRYPTO_AES_ENABLED +#define NRF_CRYPTO_AES_ENABLED 1 // Flag that nrf_crypto_aes frontend can be compiled +#undef NRF_CRYPTO_MBEDTLS_AES_ENABLED +#define NRF_CRYPTO_MBEDTLS_AES_ENABLED 1 + +/* defines for test purposes */ +#define NRF_CRYPTO_AES_CBC_MAC_128_ENABLED 1 +#define NRF_CRYPTO_AES_CBC_MAC_192_ENABLED 1 +#define NRF_CRYPTO_AES_CBC_MAC_256_ENABLED 1 + +typedef struct +{ + nrf_crypto_aes_internal_context_t header; /**< Common header for context. */ + nrf_crypto_backend_aes_ctx_t backend; /**< Backend-specific internal context. */ + mbedtls_aes_context context; /**< AES context internal to mbed TLS. */ +} nrf_crypto_backend_aes_cbc_mac_context_t; +#endif + + +/* AES CMAC */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CMAC) +#error "Duplicate definition of AES CMAC mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_AES_CMAC_ENABLED 1 +#undef NRF_CRYPTO_AES_ENABLED +#define NRF_CRYPTO_AES_ENABLED 1 // Flag that nrf_crypto_aes frontend can be compiled +#undef NRF_CRYPTO_MBEDTLS_AES_ENABLED +#define NRF_CRYPTO_MBEDTLS_AES_ENABLED 1 + +/* defines for test purposes */ +#define NRF_CRYPTO_AES_CMAC_128_ENABLED 1 +#define NRF_CRYPTO_AES_CMAC_192_ENABLED 1 +#define NRF_CRYPTO_AES_CMAC_256_ENABLED 1 + +typedef struct +{ + nrf_crypto_aes_internal_context_t header; /**< Common header for context. */ + nrf_crypto_backend_no_iv_aes_ctx_t backend; /**< Backend-specific internal context. */ + mbedtls_cipher_context_t context; /**< AES context internal to mbedtls. */ +} nrf_crypto_backend_aes_cmac_context_t; +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +/** @} */ + +#endif // MBEDTLS_BACKEND_AES_H__ diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_aes_aead.c b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_aes_aead.c new file mode 100644 index 0000000..b822484 --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_aes_aead.c @@ -0,0 +1,384 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#include +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include "nrf_crypto_error.h" +#include "mbedtls_backend_aes_aead.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_MBEDTLS_AES_AEAD) + +/**@internal @brief Type declaration of a template suiting all possible context sizes + * for this backend. + */ +typedef union +{ + nrf_crypto_aead_internal_context_t header; /**< Common header for context. */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CCM) + nrf_crypto_backend_aes_ccm_context_t ccm; +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_GCM) + nrf_crypto_backend_aes_gcm_context_t gcm; +#endif +} nrf_crypto_backend_mbedtls_aes_aead_context_t; + + +static ret_code_t result_get(int error) +{ + ret_code_t ret_val; + + switch (error) + { + case 0: + ret_val = NRF_SUCCESS; + break; + + case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA: + ret_val = NRF_ERROR_CRYPTO_INPUT_LENGTH; + break; + + case MBEDTLS_ERR_CIPHER_ALLOC_FAILED: + ret_val = NRF_ERROR_CRYPTO_ALLOC_FAILED; + break; + + case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE: + ret_val = NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + break; + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CCM) + case MBEDTLS_ERR_CCM_BAD_INPUT: + ret_val = NRF_ERROR_CRYPTO_INVALID_PARAM; + break; + + case MBEDTLS_ERR_CCM_AUTH_FAILED: + ret_val = NRF_ERROR_CRYPTO_AEAD_INVALID_MAC; + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_GCM) + case MBEDTLS_ERR_GCM_BAD_INPUT: + ret_val = NRF_ERROR_CRYPTO_INVALID_PARAM; + break; + + case MBEDTLS_ERR_GCM_AUTH_FAILED: + ret_val = NRF_ERROR_CRYPTO_AEAD_INVALID_MAC; + break; +#endif + + default: + ret_val = NRF_ERROR_CRYPTO_INTERNAL; + break; + } + return ret_val; +} + +static ret_code_t backend_mbedtls_init(void * const p_context, uint8_t * p_key) +{ + int result; + ret_code_t ret_val; + + nrf_crypto_backend_mbedtls_aes_aead_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_aes_aead_context_t *)p_context; + + if ((p_ctx->header.p_info->key_size != NRF_CRYPTO_KEY_SIZE_128) && + (p_ctx->header.p_info->key_size != NRF_CRYPTO_KEY_SIZE_192) && + (p_ctx->header.p_info->key_size != NRF_CRYPTO_KEY_SIZE_256)) + { + return NRF_ERROR_CRYPTO_KEY_SIZE; + } + + switch (p_ctx->header.p_info->mode) + { +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CCM) + case NRF_CRYPTO_AEAD_MODE_AES_CCM: + mbedtls_ccm_init(&p_ctx->ccm.context); + + result = mbedtls_ccm_setkey(&p_ctx->ccm.context, + MBEDTLS_CIPHER_ID_AES, + p_key, + p_ctx->header.p_info->key_size); + break; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_GCM) + case NRF_CRYPTO_AEAD_MODE_AES_GCM: + mbedtls_gcm_init(&p_ctx->gcm.context); + + result = mbedtls_gcm_setkey(&p_ctx->gcm.context, + MBEDTLS_CIPHER_ID_AES, + p_key, + p_ctx->header.p_info->key_size); + break; +#endif + + default: + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + } + + if (result != 0) + { + ret_val = result_get(result); + return ret_val; + } + + return NRF_SUCCESS; +} + +static ret_code_t backend_mbedtls_uninit(void * const p_context) +{ + nrf_crypto_backend_mbedtls_aes_aead_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_aes_aead_context_t *)p_context; + + if (p_ctx->header.p_info->mode == NRF_CRYPTO_AEAD_MODE_AES_CCM) + { +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CCM) + mbedtls_ccm_free(&p_ctx->ccm.context); +#endif + } + else + { +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_GCM) + mbedtls_gcm_free(&p_ctx->gcm.context); +#endif + } + + return NRF_SUCCESS; +} + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CCM) +static ret_code_t backend_mbedtls_ccm_crypt(void * const p_context, + nrf_crypto_operation_t operation, + uint8_t * p_nonce, + uint8_t nonce_size, + uint8_t * p_adata, + size_t adata_size, + uint8_t * p_data_in, + size_t data_in_size, + uint8_t * p_data_out, + uint8_t * p_mac, + uint8_t mac_size) +{ + int result; + ret_code_t ret_val; + + nrf_crypto_backend_mbedtls_aes_aead_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_aes_aead_context_t *)p_context; + + /* CCM mode allows following MAC sizes: [4, 6, 8, 10, 12, 14, 16] */ + if ((mac_size < NRF_CRYPTO_AES_CCM_MAC_MIN) || (mac_size > NRF_CRYPTO_AES_CCM_MAC_MAX) || + ((mac_size & 0x01) != 0)) + { + return NRF_ERROR_CRYPTO_AEAD_MAC_SIZE; + } + + if ((nonce_size < NRF_CRYPTO_AES_CCM_NONCE_SIZE_MIN) || + (nonce_size > NRF_CRYPTO_AES_CCM_NONCE_SIZE_MAX)) + { + return NRF_ERROR_CRYPTO_AEAD_NONCE_SIZE; + } + + if (operation == NRF_CRYPTO_ENCRYPT) + { + result = mbedtls_ccm_encrypt_and_tag(&p_ctx->ccm.context, + data_in_size, + p_nonce, + nonce_size, + p_adata, + adata_size, + p_data_in, + p_data_out, + p_mac, + (size_t)mac_size); + } + else if (operation == NRF_CRYPTO_DECRYPT) + { + result = mbedtls_ccm_auth_decrypt(&p_ctx->ccm.context, + data_in_size, + p_nonce, + nonce_size, + p_adata, + adata_size, + p_data_in, + p_data_out, + p_mac, + (size_t)mac_size); + } + else + { + return NRF_ERROR_CRYPTO_INVALID_PARAM; + } + + ret_val = result_get(result); + + return ret_val; +} +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_GCM) +static ret_code_t backend_mbedtls_gcm_crypt(void * const p_context, + nrf_crypto_operation_t operation, + uint8_t * p_nonce, + uint8_t nonce_size, + uint8_t * p_adata, + size_t adata_size, + uint8_t * p_data_in, + size_t data_in_size, + uint8_t * p_data_out, + uint8_t * p_mac, + uint8_t mac_size) +{ + int result; + ret_code_t ret_val; + + nrf_crypto_backend_mbedtls_aes_aead_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_aes_aead_context_t *)p_context; + + /* GCM allows following MAC size: [4 ... 16] */ + if ((mac_size < NRF_CRYPTO_AES_GCM_MAC_MIN) || (mac_size > NRF_CRYPTO_AES_GCM_MAC_MAX)) + { + return NRF_ERROR_CRYPTO_AEAD_MAC_SIZE; + } + + if (operation == NRF_CRYPTO_ENCRYPT) + { + result = mbedtls_gcm_crypt_and_tag(&p_ctx->gcm.context, + MBEDTLS_GCM_ENCRYPT, + data_in_size, + p_nonce, + nonce_size, + p_adata, + adata_size, + p_data_in, + p_data_out, + (size_t)mac_size, + p_mac); + ret_val = result_get(result); + } + else if (operation == NRF_CRYPTO_DECRYPT) + { + result = mbedtls_gcm_auth_decrypt(&p_ctx->gcm.context, + data_in_size, + p_nonce, + nonce_size, + p_adata, + adata_size, + p_mac, + (size_t)mac_size, + p_data_in, + p_data_out); + ret_val = result_get(result); + } + else + { + return NRF_ERROR_CRYPTO_INVALID_PARAM; + } + + return ret_val; +} +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CCM) +nrf_crypto_aead_info_t const g_nrf_crypto_aes_ccm_128_info = +{ + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .mode = NRF_CRYPTO_AEAD_MODE_AES_CCM, + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .crypt_fn = backend_mbedtls_ccm_crypt +}; + +nrf_crypto_aead_info_t const g_nrf_crypto_aes_ccm_192_info = +{ + .key_size = NRF_CRYPTO_KEY_SIZE_192, + .mode = NRF_CRYPTO_AEAD_MODE_AES_CCM, + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .crypt_fn = backend_mbedtls_ccm_crypt +}; + +nrf_crypto_aead_info_t const g_nrf_crypto_aes_ccm_256_info = +{ + .key_size = NRF_CRYPTO_KEY_SIZE_256, + .mode = NRF_CRYPTO_AEAD_MODE_AES_CCM, + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .crypt_fn = backend_mbedtls_ccm_crypt +}; +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_GCM) +nrf_crypto_aead_info_t const g_nrf_crypto_aes_gcm_128_info = +{ + .key_size = NRF_CRYPTO_KEY_SIZE_128, + .mode = NRF_CRYPTO_AEAD_MODE_AES_GCM, + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .crypt_fn = backend_mbedtls_gcm_crypt +}; + +nrf_crypto_aead_info_t const g_nrf_crypto_aes_gcm_192_info = +{ + .key_size = NRF_CRYPTO_KEY_SIZE_192, + .mode = NRF_CRYPTO_AEAD_MODE_AES_GCM, + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .crypt_fn = backend_mbedtls_gcm_crypt +}; + +nrf_crypto_aead_info_t const g_nrf_crypto_aes_gcm_256_info = +{ + .key_size = NRF_CRYPTO_KEY_SIZE_256, + .mode = NRF_CRYPTO_AEAD_MODE_AES_GCM, + + .init_fn = backend_mbedtls_init, + .uninit_fn = backend_mbedtls_uninit, + .crypt_fn = backend_mbedtls_gcm_crypt +}; +#endif + +#endif // MODULE_ENABLED(NRF_CRYPTO_MBEDTLS_AES_AEAD) +#endif // MODULE_ENABLED(NRF_CRYPTO) diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_aes_aead.h b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_aes_aead.h new file mode 100644 index 0000000..010bf93 --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_aes_aead.h @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MBEDTLS_BACKEND_AES_AEAD_H__ +#define MBEDTLS_BACKEND_AES_AEAD_H__ + +/** @file + * + * @defgroup nrf_crypto_mbedtls_backend_aes_aead nrf_crypto mbed TLS backend AES AEAD + * @{ + * @ingroup nrf_crypto_mbedtls_backend + * + * @brief AES AEAD functionality provided by the nrf_crypto mbed TLS backend. + */ + +#include "sdk_config.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) +/*lint -save -e????*/ +#include "mbedtls/ccm.h" +#include "mbedtls/gcm.h" +#include "mbedtls/platform.h" +/*lint -restore*/ +#include "nrf_crypto_error.h" +#include "nrf_crypto_aead_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* AES CCM */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_CCM) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CCM) +#error "Duplicate definition of AES CCM mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_AES_CCM_ENABLED 1 +#undef NRF_CRYPTO_AEAD_ENABLED +#define NRF_CRYPTO_AEAD_ENABLED 1 +#undef NRF_CRYPTO_MBEDTLS_AES_AEAD_ENABLED +#define NRF_CRYPTO_MBEDTLS_AES_AEAD_ENABLED 1 + +/* defines for test purposes */ +#define NRF_CRYPTO_AES_CCM_128_ENABLED 1 +#define NRF_CRYPTO_AES_CCM_192_ENABLED 1 +#define NRF_CRYPTO_AES_CCM_256_ENABLED 1 + +typedef struct +{ + nrf_crypto_aead_internal_context_t header; /**< Common header for context. */ + mbedtls_ccm_context context; /**< AES CCM context internal to mbed TLS. */ +} nrf_crypto_backend_aes_ccm_context_t; +#endif + +/* AES GCM */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_AES_GCM) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES_GCM) +#error "Duplicate definition of AES GCM mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_AES_GCM_ENABLED 1 +#undef NRF_CRYPTO_AEAD_ENABLED +#define NRF_CRYPTO_AEAD_ENABLED 1 +#undef NRF_CRYPTO_MBEDTLS_AES_AEAD_ENABLED +#define NRF_CRYPTO_MBEDTLS_AES_AEAD_ENABLED 1 + +/* defines for test purposes */ +#define NRF_CRYPTO_AES_GCM_128_ENABLED 1 +#define NRF_CRYPTO_AES_GCM_192_ENABLED 1 +#define NRF_CRYPTO_AES_GCM_256_ENABLED 1 + +typedef struct +{ + nrf_crypto_aead_internal_context_t header; /**< Common header for context. */ + mbedtls_gcm_context context; /**< AES GCM context internal to mbed TLS. */ +} nrf_crypto_backend_aes_gcm_context_t; +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +/** @} */ + +#endif // MBEDTLS_BACKEND_AES_AEAD_H__ + diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecc.c b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecc.c new file mode 100644 index 0000000..df043ce --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecc.c @@ -0,0 +1,585 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +#include +#include + +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdh.h" +#include "nrf_crypto_mem.h" +#include "nrf_crypto_rng.h" +#include "nrf_crypto_shared.h" +#include "nrf_assert.h" +#include "mbedtls_backend_ecc.h" + +/*lint -save -e????*/ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include "mbedtls/ecp.h" +#include "mbedtls/bignum.h" +/*lint -restore*/ + + +bool nrf_crypto_backend_mbedtls_ecc_group_load( + mbedtls_ecp_group * p_group, + struct nrf_crypto_ecc_curve_info_s const * p_info) +{ + int result; + + mbedtls_ecp_group_init(p_group); + result = mbedtls_ecp_group_load(p_group, + (mbedtls_ecp_group_id)(intptr_t)p_info->p_backend_data); + + if (result != 0) + { + return false; + } + return true; +} + + +int nrf_crypto_backend_mbedtls_ecc_mbedtls_rng(void * p_param, unsigned char * p_data, size_t size) +{ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) + + ret_code_t result; + + result = nrf_crypto_rng_vector_generate(p_data, size); + + if (result != NRF_SUCCESS) + { + return MBEDTLS_ERR_ECP_RANDOM_FAILED; + } + return 0; + +#else + return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; +#endif +} + + +ret_code_t nrf_crypto_backend_mbedtls_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key) +{ + int result; + mbedtls_ecp_group group; + + nrf_crypto_backend_mbedtls_ecc_private_key_t * p_prv = + (nrf_crypto_backend_mbedtls_ecc_private_key_t *)p_private_key; + + nrf_crypto_backend_mbedtls_ecc_public_key_t * p_pub = + (nrf_crypto_backend_mbedtls_ecc_public_key_t *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info; + + if (!nrf_crypto_backend_mbedtls_ecc_group_load(&group, p_info)) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + mbedtls_ecp_point_init(&p_pub->key); + mbedtls_mpi_init(&p_prv->key); + result = mbedtls_ecp_gen_keypair(&group, + &p_prv->key, + &p_pub->key, + nrf_crypto_backend_mbedtls_ecc_mbedtls_rng, + NULL); + + mbedtls_ecp_group_free(&group); + + if (result != 0) + { + mbedtls_mpi_free(&p_prv->key); + mbedtls_ecp_point_free(&p_pub->key); + return NRF_ERROR_CRYPTO_INTERNAL; + } + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_mbedtls_public_key_calculate( + void * p_context, + void const * p_private_key, + void * p_public_key) +{ + int result; + mbedtls_ecp_group group; + + nrf_crypto_backend_mbedtls_ecc_private_key_t const * p_prv = + (nrf_crypto_backend_mbedtls_ecc_private_key_t const *)p_private_key; + + nrf_crypto_backend_mbedtls_ecc_public_key_t * p_pub = + (nrf_crypto_backend_mbedtls_ecc_public_key_t *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info; + + if (!nrf_crypto_backend_mbedtls_ecc_group_load(&group, p_info)) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + mbedtls_ecp_point_init(&p_pub->key); + result = mbedtls_ecp_mul(&group, + &p_pub->key, + &p_prv->key, + &group.G, + nrf_crypto_backend_mbedtls_ecc_mbedtls_rng, + NULL); + + mbedtls_ecp_group_free(&group); + + if (result != 0) + { + mbedtls_ecp_point_free(&p_pub->key); + return NRF_ERROR_CRYPTO_INTERNAL; + } + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_mbedtls_private_key_from_raw( + void * p_private_key, + uint8_t const * p_raw_data) +{ + int result; + mbedtls_ecp_group group; + + nrf_crypto_backend_mbedtls_ecc_private_key_t * p_prv = + (nrf_crypto_backend_mbedtls_ecc_private_key_t *)p_private_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info; + + uint8_t const * p_input = p_raw_data; + +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED && !NRF_MODULE_ENABLED(NRF_CRYPTO_CURVE25519_BIG_ENDIAN) + + uint8_t temp[NRF_CRYPTO_ECC_CURVE25519_RAW_PRIVATE_KEY_SIZE]; + + if (p_info == &g_nrf_crypto_ecc_curve25519_curve_info) + { + nrf_crypto_internal_swap_endian(temp, + p_raw_data, + NRF_CRYPTO_ECC_CURVE25519_RAW_PRIVATE_KEY_SIZE); + p_input = temp; + } + +#endif + + if (!nrf_crypto_backend_mbedtls_ecc_group_load(&group, p_info)) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + mbedtls_mpi_init(&p_prv->key); + result = mbedtls_mpi_read_binary(&p_prv->key, p_input, p_info->raw_private_key_size); + + if (result == 0) + { +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_CURVE25519) + // Update bits in Curve25519 private key + if (p_prv->header.p_info->curve_type == NRF_CRYPTO_ECC_CURVE25519_CURVE_TYPE) + { + result = mbedtls_mpi_set_bit(&p_prv->key, 0, 0); + ASSERT(result == 0); + result = mbedtls_mpi_set_bit(&p_prv->key, 1, 0); + ASSERT(result == 0); + result = mbedtls_mpi_set_bit(&p_prv->key, 2, 0); + ASSERT(result == 0); + result = mbedtls_mpi_set_bit(&p_prv->key, 254, 1); + ASSERT(result == 0); + result = mbedtls_mpi_set_bit(&p_prv->key, 255, 0); + ASSERT(result == 0); + } +#endif + if (mbedtls_ecp_check_privkey(&group, &p_prv->key) != 0) + { + result = MBEDTLS_ERR_ECP_INVALID_KEY; + } + } + + mbedtls_ecp_group_free(&group); + + if (result != 0) + { + mbedtls_mpi_free(&p_prv->key); + return NRF_ERROR_CRYPTO_INTERNAL; + } + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_mbedtls_private_key_to_raw( + void const * p_private_key, + uint8_t * p_raw_data) +{ + int result; + + nrf_crypto_backend_mbedtls_ecc_private_key_t const * p_prv = + (nrf_crypto_backend_mbedtls_ecc_private_key_t const *)p_private_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info; + + result = mbedtls_mpi_write_binary(&p_prv->key, p_raw_data, p_info->raw_private_key_size); + +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED && !NRF_MODULE_ENABLED(NRF_CRYPTO_CURVE25519_BIG_ENDIAN) + + if (p_info == &g_nrf_crypto_ecc_curve25519_curve_info) + { + nrf_crypto_internal_swap_endian_in_place(p_raw_data, + NRF_CRYPTO_ECC_CURVE25519_RAW_PRIVATE_KEY_SIZE); + } + +#endif + + if (result != 0) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_mbedtls_public_key_from_raw( + void * p_public_key, + uint8_t const * p_raw_data) +{ + int result; + mbedtls_ecp_group group; + + nrf_crypto_backend_mbedtls_ecc_public_key_t * p_pub = + (nrf_crypto_backend_mbedtls_ecc_public_key_t *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info; + + uint8_t const * p_input = p_raw_data; + +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED && !NRF_MODULE_ENABLED(NRF_CRYPTO_CURVE25519_BIG_ENDIAN) + + uint8_t temp[NRF_CRYPTO_ECC_CURVE25519_RAW_PUBLIC_KEY_SIZE]; + + if (p_info == &g_nrf_crypto_ecc_curve25519_curve_info) + { + nrf_crypto_internal_swap_endian(temp, + p_raw_data, + NRF_CRYPTO_ECC_CURVE25519_RAW_PUBLIC_KEY_SIZE); + p_input = temp; + } + +#endif + + mbedtls_ecp_point_init(&p_pub->key); + + result = mbedtls_mpi_read_binary(&p_pub->key.X, + p_input, + p_info->raw_private_key_size); + + if (result != 0) + { + goto error_exit; + } + + if (p_info->raw_public_key_size > p_info->raw_private_key_size) + { + result = mbedtls_mpi_read_binary(&p_pub->key.Y, + &p_raw_data[p_info->raw_private_key_size], + p_info->raw_private_key_size); + } + + if (result != 0) + { + goto error_exit; + } + + result = mbedtls_mpi_lset(&p_pub->key.Z, 1); + + if (result == 0) + { + if (!nrf_crypto_backend_mbedtls_ecc_group_load(&group, p_info)) + { + goto error_exit; + } + result = mbedtls_ecp_check_pubkey(&group, &p_pub->key); + mbedtls_ecp_group_free(&group); + } + + if (result != 0) + { + goto error_exit; + } + return NRF_SUCCESS; + +error_exit: + mbedtls_ecp_point_free(&p_pub->key); + return NRF_ERROR_CRYPTO_INTERNAL; +} + + +ret_code_t nrf_crypto_backend_mbedtls_public_key_to_raw( + void const * p_public_key, + uint8_t * p_raw_data) +{ + int result; + + nrf_crypto_backend_mbedtls_ecc_public_key_t const * p_pub = + (nrf_crypto_backend_mbedtls_ecc_public_key_t const *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info; + + result = mbedtls_mpi_write_binary(&p_pub->key.X, + p_raw_data, + p_info->raw_private_key_size); + if (result != 0) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + if (p_info->raw_public_key_size > p_info->raw_private_key_size) + { + result = mbedtls_mpi_write_binary(&p_pub->key.Y, + &p_raw_data[p_info->raw_private_key_size], + p_info->raw_private_key_size); + } + +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED && !NRF_MODULE_ENABLED(NRF_CRYPTO_CURVE25519_BIG_ENDIAN) + + if (p_info == &g_nrf_crypto_ecc_curve25519_curve_info) + { + nrf_crypto_internal_swap_endian_in_place(p_raw_data, + NRF_CRYPTO_ECC_CURVE25519_RAW_PUBLIC_KEY_SIZE); + } + +#endif + + if (result != 0) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_mbedtls_private_key_free( + void * p_private_key) +{ + nrf_crypto_backend_mbedtls_ecc_private_key_t * p_prv = + (nrf_crypto_backend_mbedtls_ecc_private_key_t *)p_private_key; + + mbedtls_mpi_free(&p_prv->key); + return NRF_SUCCESS; +} + +ret_code_t nrf_crypto_backend_mbedtls_public_key_free( + void * p_public_key) +{ + nrf_crypto_backend_mbedtls_ecc_public_key_t * p_pub = + (nrf_crypto_backend_mbedtls_ecc_public_key_t *)p_public_key; + + mbedtls_ecp_point_free(&p_pub->key); + return NRF_SUCCESS; +} + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp192r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP192R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP192R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP192R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)MBEDTLS_ECP_DP_SECP192R1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp224r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP224R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP224R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)MBEDTLS_ECP_DP_SECP224R1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp256r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP256R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)MBEDTLS_ECP_DP_SECP256R1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP384R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp384r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP384R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP384R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP384R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)MBEDTLS_ECP_DP_SECP384R1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP521R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp521r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP521R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP521R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP521R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)MBEDTLS_ECP_DP_SECP521R1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192K1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp192k1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP192K1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP192K1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP192K1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)MBEDTLS_ECP_DP_SECP192K1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224K1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp224k1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP224K1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP224K1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP224K1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)MBEDTLS_ECP_DP_SECP224K1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256K1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp256k1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP256K1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP256K1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP256K1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)MBEDTLS_ECP_DP_SECP256K1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP256R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_bp256r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_BP256R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_BP256R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_BP256R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)MBEDTLS_ECP_DP_BP256R1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP384R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_bp384r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_BP384R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_BP384R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_BP384R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)MBEDTLS_ECP_DP_BP384R1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP512R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_bp512r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_BP512R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_BP512R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_BP512R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)MBEDTLS_ECP_DP_BP512R1, +}; +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_CURVE25519) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_curve25519_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_mbedtls_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_CURVE25519_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_CURVE25519_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_CURVE25519_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)MBEDTLS_ECP_DP_CURVE25519, +}; +#endif + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecc.h b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecc.h new file mode 100644 index 0000000..427eded --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecc.h @@ -0,0 +1,519 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MBEDTLS_BACKEND_ECC_H__ +#define MBEDTLS_BACKEND_ECC_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +#include +#include +#include "nrf_crypto_ecc_shared.h" + +/*lint -save -e????*/ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include "mbedtls/ecp.h" +/*lint -restore*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @internal @brief Common structure holding private key for mbed TLS. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + mbedtls_mpi key; /**< @internal @brief mbed TLS specific key representation */ +} nrf_crypto_backend_mbedtls_ecc_private_key_t; + + +/** @internal @brief Common structure holding public key for mbed TLS. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + mbedtls_ecp_point key; /**< @internal @brief mbed TLS specific key representation */ +} nrf_crypto_backend_mbedtls_ecc_public_key_t; + + +/** @internal See @ref nrf_crypto_backend_ecc_key_pair_generate_fn_t. + */ +ret_code_t nrf_crypto_backend_mbedtls_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_calculate_fn_t. +*/ +ret_code_t nrf_crypto_backend_mbedtls_public_key_calculate( + void * p_context, + void const * p_private_key, + void * p_public_key); + + +/** @internal See @ref nrf_crypto_backend_ecc_private_key_from_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_mbedtls_private_key_from_raw( + void * p_private_key, + uint8_t const * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_private_key_to_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_mbedtls_private_key_to_raw( + void const * p_private_key, + uint8_t * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_from_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_mbedtls_public_key_from_raw( + void * p_public_key, + uint8_t const * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_to_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_mbedtls_public_key_to_raw( + void const * p_public_key, + uint8_t * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_key_free_fn_t. +*/ +ret_code_t nrf_crypto_backend_mbedtls_private_key_free( + void * p_private_key); + + +/** @internal See @ref nrf_crypto_backend_ecc_key_free_fn_t. +*/ +ret_code_t nrf_crypto_backend_mbedtls_public_key_free( + void * p_public_key); + + +/** @internal @brief Loads mbed TLS ECC group of specified curve type. + * + * @param[out] p_group Pointer to place where to load a group. Data have to be later deallocated. + * @param[in] curve_type ECC curve type from enum @ref nrf_crypto_ecc_curve_type_t. + * @returns true on success, false if curve is not supported or no found in mbed TLS. + */ +bool nrf_crypto_backend_mbedtls_ecc_group_load( + mbedtls_ecp_group * p_group, + struct nrf_crypto_ecc_curve_info_s const * p_info); + + +/** @internal @brief Function that can be used as a parameter to mbed TLS functions requiring random + * number generator. + * + * It uses RNG from libary front end to generate random numbers. + * + * @param[in] p_param Opaque pointer passed by mbed TLS. Unused by this implementation. + * @param[out] p_data Pointer where to put random number. + * @returns 0 on success, mbed TLS error code on error. + */ +int nrf_crypto_backend_mbedtls_ecc_mbedtls_rng(void * p_param, unsigned char * p_data, size_t size); + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP192R1) +#error "More than one backend enabled for secp192r1 (NIST 192-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP192R1_ENABLED 1 + +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp192r1_key_pair_generate nrf_crypto_backend_mbedtls_key_pair_generate +#define nrf_crypto_backend_secp192r1_public_key_calculate nrf_crypto_backend_mbedtls_public_key_calculate +#define nrf_crypto_backend_secp192r1_private_key_from_raw nrf_crypto_backend_mbedtls_private_key_from_raw +#define nrf_crypto_backend_secp192r1_private_key_to_raw nrf_crypto_backend_mbedtls_private_key_to_raw +#define nrf_crypto_backend_secp192r1_public_key_from_raw nrf_crypto_backend_mbedtls_public_key_from_raw +#define nrf_crypto_backend_secp192r1_public_key_to_raw nrf_crypto_backend_mbedtls_public_key_to_raw +#define nrf_crypto_backend_secp192r1_private_key_free nrf_crypto_backend_mbedtls_private_key_free +#define nrf_crypto_backend_secp192r1_public_key_free nrf_crypto_backend_mbedtls_public_key_free +// mbed TLS does not require context, so its size is 0. +#define NRF_CRYPTO_BACKEND_SECP192R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP192R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 +// All MBEDTLS curve types share the same data structures +typedef nrf_crypto_backend_mbedtls_ecc_private_key_t nrf_crypto_backend_secp192r1_private_key_t; +typedef nrf_crypto_backend_mbedtls_ecc_public_key_t nrf_crypto_backend_secp192r1_public_key_t; +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp192r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp192r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP224R1) +#error "More than one backend enabled for secp224r1 (NIST 224-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP224R1_ENABLED 1 + +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp224r1_key_pair_generate nrf_crypto_backend_mbedtls_key_pair_generate +#define nrf_crypto_backend_secp224r1_public_key_calculate nrf_crypto_backend_mbedtls_public_key_calculate +#define nrf_crypto_backend_secp224r1_private_key_from_raw nrf_crypto_backend_mbedtls_private_key_from_raw +#define nrf_crypto_backend_secp224r1_private_key_to_raw nrf_crypto_backend_mbedtls_private_key_to_raw +#define nrf_crypto_backend_secp224r1_public_key_from_raw nrf_crypto_backend_mbedtls_public_key_from_raw +#define nrf_crypto_backend_secp224r1_public_key_to_raw nrf_crypto_backend_mbedtls_public_key_to_raw +#define nrf_crypto_backend_secp224r1_private_key_free nrf_crypto_backend_mbedtls_private_key_free +#define nrf_crypto_backend_secp224r1_public_key_free nrf_crypto_backend_mbedtls_public_key_free +// mbed TLS does not require context, so its size is 0. +#define NRF_CRYPTO_BACKEND_SECP224R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP224R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 +// All MBEDTLS curve types share the same data structures +typedef nrf_crypto_backend_mbedtls_ecc_private_key_t nrf_crypto_backend_secp224r1_private_key_t; +typedef nrf_crypto_backend_mbedtls_ecc_public_key_t nrf_crypto_backend_secp224r1_public_key_t; +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp224r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp224r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP256R1) +#error "More than one backend enabled for secp256r1 (NIST 256-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP256R1_ENABLED 1 + +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp256r1_key_pair_generate nrf_crypto_backend_mbedtls_key_pair_generate +#define nrf_crypto_backend_secp256r1_public_key_calculate nrf_crypto_backend_mbedtls_public_key_calculate +#define nrf_crypto_backend_secp256r1_private_key_from_raw nrf_crypto_backend_mbedtls_private_key_from_raw +#define nrf_crypto_backend_secp256r1_private_key_to_raw nrf_crypto_backend_mbedtls_private_key_to_raw +#define nrf_crypto_backend_secp256r1_public_key_from_raw nrf_crypto_backend_mbedtls_public_key_from_raw +#define nrf_crypto_backend_secp256r1_public_key_to_raw nrf_crypto_backend_mbedtls_public_key_to_raw +#define nrf_crypto_backend_secp256r1_private_key_free nrf_crypto_backend_mbedtls_private_key_free +#define nrf_crypto_backend_secp256r1_public_key_free nrf_crypto_backend_mbedtls_public_key_free +// mbed TLS does not require context, so its size is 0. +#define NRF_CRYPTO_BACKEND_SECP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 +// All MBEDTLS curve types share the same data structures +typedef nrf_crypto_backend_mbedtls_ecc_private_key_t nrf_crypto_backend_secp256r1_private_key_t; +typedef nrf_crypto_backend_mbedtls_ecc_public_key_t nrf_crypto_backend_secp256r1_public_key_t; +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp256r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp256r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP384R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP384R1) +#error "More than one backend enabled for secp384r1 (NIST 384-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP384R1_ENABLED 1 + +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp384r1_key_pair_generate nrf_crypto_backend_mbedtls_key_pair_generate +#define nrf_crypto_backend_secp384r1_public_key_calculate nrf_crypto_backend_mbedtls_public_key_calculate +#define nrf_crypto_backend_secp384r1_private_key_from_raw nrf_crypto_backend_mbedtls_private_key_from_raw +#define nrf_crypto_backend_secp384r1_private_key_to_raw nrf_crypto_backend_mbedtls_private_key_to_raw +#define nrf_crypto_backend_secp384r1_public_key_from_raw nrf_crypto_backend_mbedtls_public_key_from_raw +#define nrf_crypto_backend_secp384r1_public_key_to_raw nrf_crypto_backend_mbedtls_public_key_to_raw +#define nrf_crypto_backend_secp384r1_private_key_free nrf_crypto_backend_mbedtls_private_key_free +#define nrf_crypto_backend_secp384r1_public_key_free nrf_crypto_backend_mbedtls_public_key_free +// mbed TLS does not require context, so its size is 0. +#define NRF_CRYPTO_BACKEND_SECP384R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP384R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 +// All MBEDTLS curve types share the same data structures +typedef nrf_crypto_backend_mbedtls_ecc_private_key_t nrf_crypto_backend_secp384r1_private_key_t; +typedef nrf_crypto_backend_mbedtls_ecc_public_key_t nrf_crypto_backend_secp384r1_public_key_t; +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp384r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp384r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP384R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP521R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP521R1) +#error "More than one backend enabled for secp521r1 (NIST 521-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP521R1_ENABLED 1 + +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp521r1_key_pair_generate nrf_crypto_backend_mbedtls_key_pair_generate +#define nrf_crypto_backend_secp521r1_public_key_calculate nrf_crypto_backend_mbedtls_public_key_calculate +#define nrf_crypto_backend_secp521r1_private_key_from_raw nrf_crypto_backend_mbedtls_private_key_from_raw +#define nrf_crypto_backend_secp521r1_private_key_to_raw nrf_crypto_backend_mbedtls_private_key_to_raw +#define nrf_crypto_backend_secp521r1_public_key_from_raw nrf_crypto_backend_mbedtls_public_key_from_raw +#define nrf_crypto_backend_secp521r1_public_key_to_raw nrf_crypto_backend_mbedtls_public_key_to_raw +#define nrf_crypto_backend_secp521r1_private_key_free nrf_crypto_backend_mbedtls_private_key_free +#define nrf_crypto_backend_secp521r1_public_key_free nrf_crypto_backend_mbedtls_public_key_free +// mbed TLS does not require context, so its size is 0. +#define NRF_CRYPTO_BACKEND_SECP521R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP521R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 +// All MBEDTLS curve types share the same data structures +typedef nrf_crypto_backend_mbedtls_ecc_private_key_t nrf_crypto_backend_secp521r1_private_key_t; +typedef nrf_crypto_backend_mbedtls_ecc_public_key_t nrf_crypto_backend_secp521r1_public_key_t; +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp521r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp521r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP521R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192K1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP192K1) +#error "More than one backend enabled for secp192k1 (Koblitz 192-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP192K1_ENABLED 1 + +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp192k1_key_pair_generate nrf_crypto_backend_mbedtls_key_pair_generate +#define nrf_crypto_backend_secp192k1_public_key_calculate nrf_crypto_backend_mbedtls_public_key_calculate +#define nrf_crypto_backend_secp192k1_private_key_from_raw nrf_crypto_backend_mbedtls_private_key_from_raw +#define nrf_crypto_backend_secp192k1_private_key_to_raw nrf_crypto_backend_mbedtls_private_key_to_raw +#define nrf_crypto_backend_secp192k1_public_key_from_raw nrf_crypto_backend_mbedtls_public_key_from_raw +#define nrf_crypto_backend_secp192k1_public_key_to_raw nrf_crypto_backend_mbedtls_public_key_to_raw +#define nrf_crypto_backend_secp192k1_private_key_free nrf_crypto_backend_mbedtls_private_key_free +#define nrf_crypto_backend_secp192k1_public_key_free nrf_crypto_backend_mbedtls_public_key_free +// mbed TLS does not require context, so its size is 0. +#define NRF_CRYPTO_BACKEND_SECP192K1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP192K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 +// All MBEDTLS curve types share the same data structures +typedef nrf_crypto_backend_mbedtls_ecc_private_key_t nrf_crypto_backend_secp192k1_private_key_t; +typedef nrf_crypto_backend_mbedtls_ecc_public_key_t nrf_crypto_backend_secp192k1_public_key_t; +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp192k1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp192k1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192K1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224K1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP224K1) +#error "More than one backend enabled for secp224k1 (Koblitz 224-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP224K1_ENABLED 1 + +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp224k1_key_pair_generate nrf_crypto_backend_mbedtls_key_pair_generate +#define nrf_crypto_backend_secp224k1_public_key_calculate nrf_crypto_backend_mbedtls_public_key_calculate +#define nrf_crypto_backend_secp224k1_private_key_from_raw nrf_crypto_backend_mbedtls_private_key_from_raw +#define nrf_crypto_backend_secp224k1_private_key_to_raw nrf_crypto_backend_mbedtls_private_key_to_raw +#define nrf_crypto_backend_secp224k1_public_key_from_raw nrf_crypto_backend_mbedtls_public_key_from_raw +#define nrf_crypto_backend_secp224k1_public_key_to_raw nrf_crypto_backend_mbedtls_public_key_to_raw +#define nrf_crypto_backend_secp224k1_private_key_free nrf_crypto_backend_mbedtls_private_key_free +#define nrf_crypto_backend_secp224k1_public_key_free nrf_crypto_backend_mbedtls_public_key_free +// mbed TLS does not require context, so its size is 0. +#define NRF_CRYPTO_BACKEND_SECP224K1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP224K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 +// All MBEDTLS curve types share the same data structures +typedef nrf_crypto_backend_mbedtls_ecc_private_key_t nrf_crypto_backend_secp224k1_private_key_t; +typedef nrf_crypto_backend_mbedtls_ecc_public_key_t nrf_crypto_backend_secp224k1_public_key_t; +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp224k1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp224k1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224K1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256K1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP256K1) +#error "More than one backend enabled for secp256k1 (Koblitz 256-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP256K1_ENABLED 1 + +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp256k1_key_pair_generate nrf_crypto_backend_mbedtls_key_pair_generate +#define nrf_crypto_backend_secp256k1_public_key_calculate nrf_crypto_backend_mbedtls_public_key_calculate +#define nrf_crypto_backend_secp256k1_private_key_from_raw nrf_crypto_backend_mbedtls_private_key_from_raw +#define nrf_crypto_backend_secp256k1_private_key_to_raw nrf_crypto_backend_mbedtls_private_key_to_raw +#define nrf_crypto_backend_secp256k1_public_key_from_raw nrf_crypto_backend_mbedtls_public_key_from_raw +#define nrf_crypto_backend_secp256k1_public_key_to_raw nrf_crypto_backend_mbedtls_public_key_to_raw +#define nrf_crypto_backend_secp256k1_private_key_free nrf_crypto_backend_mbedtls_private_key_free +#define nrf_crypto_backend_secp256k1_public_key_free nrf_crypto_backend_mbedtls_public_key_free +// mbed TLS does not require context, so its size is 0. +#define NRF_CRYPTO_BACKEND_SECP256K1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 +// All MBEDTLS curve types share the same data structures +typedef nrf_crypto_backend_mbedtls_ecc_private_key_t nrf_crypto_backend_secp256k1_private_key_t; +typedef nrf_crypto_backend_mbedtls_ecc_public_key_t nrf_crypto_backend_secp256k1_public_key_t; +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp256k1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp256k1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256K1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP256R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_BP256R1) +#error "More than one backend enabled for bp256r1 (Brainpool 256-bit)."); +#endif +#define NRF_CRYPTO_ECC_BP256R1_ENABLED 1 + +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_bp256r1_key_pair_generate nrf_crypto_backend_mbedtls_key_pair_generate +#define nrf_crypto_backend_bp256r1_public_key_calculate nrf_crypto_backend_mbedtls_public_key_calculate +#define nrf_crypto_backend_bp256r1_private_key_from_raw nrf_crypto_backend_mbedtls_private_key_from_raw +#define nrf_crypto_backend_bp256r1_private_key_to_raw nrf_crypto_backend_mbedtls_private_key_to_raw +#define nrf_crypto_backend_bp256r1_public_key_from_raw nrf_crypto_backend_mbedtls_public_key_from_raw +#define nrf_crypto_backend_bp256r1_public_key_to_raw nrf_crypto_backend_mbedtls_public_key_to_raw +#define nrf_crypto_backend_bp256r1_private_key_free nrf_crypto_backend_mbedtls_private_key_free +#define nrf_crypto_backend_bp256r1_public_key_free nrf_crypto_backend_mbedtls_public_key_free +// mbed TLS does not require context, so its size is 0. +#define NRF_CRYPTO_BACKEND_BP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_BP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 +// All MBEDTLS curve types share the same data structures +typedef nrf_crypto_backend_mbedtls_ecc_private_key_t nrf_crypto_backend_bp256r1_private_key_t; +typedef nrf_crypto_backend_mbedtls_ecc_public_key_t nrf_crypto_backend_bp256r1_public_key_t; +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_bp256r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_bp256r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP256R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP384R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_BP384R1) +#error "More than one backend enabled for bp384r1 (Brainpool 384-bit)."); +#endif +#define NRF_CRYPTO_ECC_BP384R1_ENABLED 1 + +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_bp384r1_key_pair_generate nrf_crypto_backend_mbedtls_key_pair_generate +#define nrf_crypto_backend_bp384r1_public_key_calculate nrf_crypto_backend_mbedtls_public_key_calculate +#define nrf_crypto_backend_bp384r1_private_key_from_raw nrf_crypto_backend_mbedtls_private_key_from_raw +#define nrf_crypto_backend_bp384r1_private_key_to_raw nrf_crypto_backend_mbedtls_private_key_to_raw +#define nrf_crypto_backend_bp384r1_public_key_from_raw nrf_crypto_backend_mbedtls_public_key_from_raw +#define nrf_crypto_backend_bp384r1_public_key_to_raw nrf_crypto_backend_mbedtls_public_key_to_raw +#define nrf_crypto_backend_bp384r1_private_key_free nrf_crypto_backend_mbedtls_private_key_free +#define nrf_crypto_backend_bp384r1_public_key_free nrf_crypto_backend_mbedtls_public_key_free +// mbed TLS does not require context, so its size is 0. +#define NRF_CRYPTO_BACKEND_BP384R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_BP384R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 +// All MBEDTLS curve types share the same data structures +typedef nrf_crypto_backend_mbedtls_ecc_private_key_t nrf_crypto_backend_bp384r1_private_key_t; +typedef nrf_crypto_backend_mbedtls_ecc_public_key_t nrf_crypto_backend_bp384r1_public_key_t; +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_bp384r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_bp384r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP384R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP512R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_BP512R1) +#error "More than one backend enabled for bp512r1 (Brainpool 512-bit)."); +#endif +#define NRF_CRYPTO_ECC_BP512R1_ENABLED 1 + +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_bp512r1_key_pair_generate nrf_crypto_backend_mbedtls_key_pair_generate +#define nrf_crypto_backend_bp512r1_public_key_calculate nrf_crypto_backend_mbedtls_public_key_calculate +#define nrf_crypto_backend_bp512r1_private_key_from_raw nrf_crypto_backend_mbedtls_private_key_from_raw +#define nrf_crypto_backend_bp512r1_private_key_to_raw nrf_crypto_backend_mbedtls_private_key_to_raw +#define nrf_crypto_backend_bp512r1_public_key_from_raw nrf_crypto_backend_mbedtls_public_key_from_raw +#define nrf_crypto_backend_bp512r1_public_key_to_raw nrf_crypto_backend_mbedtls_public_key_to_raw +#define nrf_crypto_backend_bp512r1_private_key_free nrf_crypto_backend_mbedtls_private_key_free +#define nrf_crypto_backend_bp512r1_public_key_free nrf_crypto_backend_mbedtls_public_key_free +// mbed TLS does not require context, so its size is 0. +#define NRF_CRYPTO_BACKEND_BP512R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_BP512R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 +// All MBEDTLS curve types share the same data structures +typedef nrf_crypto_backend_mbedtls_ecc_private_key_t nrf_crypto_backend_bp512r1_private_key_t; +typedef nrf_crypto_backend_mbedtls_ecc_public_key_t nrf_crypto_backend_bp512r1_public_key_t; +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_bp512r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_bp512r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP512R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_CURVE25519) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_CURVE25519) +#error "More than one backend enabled for Curve25519."); +#endif +#define NRF_CRYPTO_ECC_CURVE25519_ENABLED 1 + +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_curve25519_key_pair_generate nrf_crypto_backend_mbedtls_key_pair_generate +#define nrf_crypto_backend_curve25519_public_key_calculate nrf_crypto_backend_mbedtls_public_key_calculate +#define nrf_crypto_backend_curve25519_private_key_from_raw nrf_crypto_backend_mbedtls_private_key_from_raw +#define nrf_crypto_backend_curve25519_private_key_to_raw nrf_crypto_backend_mbedtls_private_key_to_raw +#define nrf_crypto_backend_curve25519_public_key_from_raw nrf_crypto_backend_mbedtls_public_key_from_raw +#define nrf_crypto_backend_curve25519_public_key_to_raw nrf_crypto_backend_mbedtls_public_key_to_raw +#define nrf_crypto_backend_curve25519_private_key_free nrf_crypto_backend_mbedtls_private_key_free +#define nrf_crypto_backend_curve25519_public_key_free nrf_crypto_backend_mbedtls_public_key_free +// mbed TLS does not require context, so its size is 0. +#define NRF_CRYPTO_BACKEND_CURVE25519_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_CURVE25519_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 +// All MBEDTLS curve types share the same data structures +typedef nrf_crypto_backend_mbedtls_ecc_private_key_t nrf_crypto_backend_curve25519_private_key_t; +typedef nrf_crypto_backend_mbedtls_ecc_public_key_t nrf_crypto_backend_curve25519_public_key_t; +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_curve25519_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_curve25519_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_CURVE25519) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +#endif // MBEDTLS_BACKEND_ECC_H__ diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecdh.c b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecdh.c new file mode 100644 index 0000000..77fa69e --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecdh.c @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +#include + +#include "nrf_crypto_ecc_shared.h" +#include "nrf_crypto_ecdh_shared.h" +#include "nrf_crypto_shared.h" +#include "nrf_crypto_ecdh.h" + +/*lint -save -e????*/ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include "mbedtls/ecp.h" +#include "mbedtls/ecdh.h" +/*lint -restore*/ + + +ret_code_t nrf_crypto_backend_mbedtls_ecdh_compute( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret) +{ + int result; + mbedtls_mpi shared_secret_mpi; + mbedtls_ecp_group group; + + nrf_crypto_backend_mbedtls_ecc_private_key_t const * p_prv = + (nrf_crypto_backend_mbedtls_ecc_private_key_t const *)p_private_key; + + nrf_crypto_backend_mbedtls_ecc_public_key_t const * p_pub = + (nrf_crypto_backend_mbedtls_ecc_public_key_t const *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info; + + if (!nrf_crypto_backend_mbedtls_ecc_group_load(&group, p_info)) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + mbedtls_mpi_init(&shared_secret_mpi); + result = mbedtls_ecdh_compute_shared(&group, + &shared_secret_mpi, + &p_pub->key, + &p_prv->key, + nrf_crypto_backend_mbedtls_ecc_mbedtls_rng, + NULL); + + if (result == 0) + { + result = mbedtls_mpi_write_binary(&shared_secret_mpi, + p_shared_secret, + p_info->raw_private_key_size); + } + +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED && !NRF_MODULE_ENABLED(NRF_CRYPTO_CURVE25519_BIG_ENDIAN) + + if (p_info == &g_nrf_crypto_ecc_curve25519_curve_info) + { + nrf_crypto_internal_swap_endian_in_place(p_shared_secret, + NRF_CRYPTO_ECDH_CURVE25519_SHARED_SECRET_SIZE); + } + +#endif + + mbedtls_mpi_free(&shared_secret_mpi); + mbedtls_ecp_group_free(&group); + + if (result != 0) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + return NRF_SUCCESS; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecdh.h b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecdh.h new file mode 100644 index 0000000..125e8b3 --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecdh.h @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MBEDTLS_BACKEND_ECDH_H__ +#define MBEDTLS_BACKEND_ECDH_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdh_shared.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @internal See @ref nrf_crypto_backend_ecdh_compute_fn_t. + */ +ret_code_t nrf_crypto_backend_mbedtls_ecdh_compute( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret); + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192R1) +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp192r1_ecdh_compute nrf_crypto_backend_mbedtls_ecdh_compute +typedef uint32_t nrf_crypto_backend_secp192r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP192R1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224R1) +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp224r1_ecdh_compute nrf_crypto_backend_mbedtls_ecdh_compute +typedef uint32_t nrf_crypto_backend_secp224r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP224R1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256R1) +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp256r1_ecdh_compute nrf_crypto_backend_mbedtls_ecdh_compute +typedef uint32_t nrf_crypto_backend_secp256r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP256R1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP384R1) +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp384r1_ecdh_compute nrf_crypto_backend_mbedtls_ecdh_compute +typedef uint32_t nrf_crypto_backend_secp384r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP384R1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP384R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP521R1) +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp521r1_ecdh_compute nrf_crypto_backend_mbedtls_ecdh_compute +typedef uint32_t nrf_crypto_backend_secp521r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP521R1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP521R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192K1) +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp192k1_ecdh_compute nrf_crypto_backend_mbedtls_ecdh_compute +typedef uint32_t nrf_crypto_backend_secp192k1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP192K1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192K1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224K1) +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp224k1_ecdh_compute nrf_crypto_backend_mbedtls_ecdh_compute +typedef uint32_t nrf_crypto_backend_secp224k1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP224K1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224K1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256K1) +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_secp256k1_ecdh_compute nrf_crypto_backend_mbedtls_ecdh_compute +typedef uint32_t nrf_crypto_backend_secp256k1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP256K1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256K1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP256R1) +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_bp256r1_ecdh_compute nrf_crypto_backend_mbedtls_ecdh_compute +typedef uint32_t nrf_crypto_backend_bp256r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_BP256R1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP256R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP384R1) +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_bp384r1_ecdh_compute nrf_crypto_backend_mbedtls_ecdh_compute +typedef uint32_t nrf_crypto_backend_bp384r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_BP384R1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP384R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP512R1) +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_bp512r1_ecdh_compute nrf_crypto_backend_mbedtls_ecdh_compute +typedef uint32_t nrf_crypto_backend_bp512r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_BP512R1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP512R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_CURVE25519) +// Aliases for one common MBEDTLS implementation +#define nrf_crypto_backend_curve25519_ecdh_compute nrf_crypto_backend_mbedtls_ecdh_compute +typedef uint32_t nrf_crypto_backend_curve25519_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_CURVE25519_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_CURVE25519) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +#endif // MBEDTLS_BACKEND_ECDH_H__ diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecdsa.c b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecdsa.c new file mode 100644 index 0000000..9c612d8 --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecdsa.c @@ -0,0 +1,176 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +#include +#include +#include + +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdsa.h" + +/*lint -save -e????*/ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include "mbedtls/ecp.h" +#include "mbedtls/ecdsa.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +/*lint -restore*/ + + +ret_code_t nrf_crypto_backend_mbedtls_sign( + void * p_context, + void const * p_private_key, + uint8_t const * p_data, + size_t data_size, + uint8_t * p_signature) +{ + int result; + mbedtls_mpi r_mpi; + mbedtls_mpi s_mpi; + mbedtls_ecp_group group; + + nrf_crypto_backend_mbedtls_ecc_private_key_t const * p_prv = + (nrf_crypto_backend_mbedtls_ecc_private_key_t const *)p_private_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info; + + if (!nrf_crypto_backend_mbedtls_ecc_group_load(&group, p_info)) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + mbedtls_mpi_init(&r_mpi); + mbedtls_mpi_init(&s_mpi); + result = mbedtls_ecdsa_sign(&group, + &r_mpi, + &s_mpi, + &p_prv->key, + p_data, + data_size, + nrf_crypto_backend_mbedtls_ecc_mbedtls_rng, + NULL); + + mbedtls_ecp_group_free(&group); + + if (result == 0) + { + result = mbedtls_mpi_write_binary(&r_mpi, p_signature, p_info->raw_private_key_size); + if (result == 0) + { + result = mbedtls_mpi_write_binary(&s_mpi, + &p_signature[p_info->raw_private_key_size], + p_info->raw_private_key_size); + } + } + + mbedtls_mpi_free(&r_mpi); + mbedtls_mpi_free(&s_mpi); + + if (result != 0) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_mbedtls_verify( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature) +{ + int result; + mbedtls_mpi r_mpi; + mbedtls_mpi s_mpi; + mbedtls_ecp_group group; + + nrf_crypto_backend_mbedtls_ecc_public_key_t const * p_pub = + (nrf_crypto_backend_mbedtls_ecc_public_key_t const *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info; + + if (!nrf_crypto_backend_mbedtls_ecc_group_load(&group, p_info)) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + mbedtls_mpi_init(&r_mpi); + mbedtls_mpi_init(&s_mpi); + + result = mbedtls_mpi_read_binary(&r_mpi, p_signature, p_info->raw_private_key_size); + if (result == 0) + { + result = mbedtls_mpi_read_binary(&s_mpi, + &p_signature[p_info->raw_private_key_size], + p_info->raw_private_key_size); + if (result == 0) + { + result = mbedtls_ecdsa_verify(&group, p_data, data_size, &p_pub->key, &r_mpi, &s_mpi); + } + } + + mbedtls_ecp_group_free(&group); + mbedtls_mpi_free(&r_mpi); + mbedtls_mpi_free(&s_mpi); + + if (result == MBEDTLS_ERR_ECP_VERIFY_FAILED) + { + return NRF_ERROR_CRYPTO_ECDSA_INVALID_SIGNATURE; + } + else if (result != 0) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + return NRF_SUCCESS; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecdsa.h b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecdsa.h new file mode 100644 index 0000000..06f64fd --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_ecdsa.h @@ -0,0 +1,240 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MBEDTLS_BACKEND_ECDSA_H__ +#define MBEDTLS_BACKEND_ECDSA_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +#include "nrf_crypto_ecc_shared.h" +#include "nrf_crypto_ecdsa_shared.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @internal See @ref nrf_crypto_backend_ecdsa_sign_fn_t. + */ +ret_code_t nrf_crypto_backend_mbedtls_sign( + void * p_context, + void const * p_private_key, + uint8_t const * p_data, + size_t data_size, + uint8_t * p_signature); + + +/** @internal See @ref nrf_crypto_backend_ecdsa_verify_fn_t. + */ +ret_code_t nrf_crypto_backend_mbedtls_verify( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature); + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192R1) +// Context is not used by mbed TLS, so its size is 0 +#define NRF_CRYPTO_BACKEND_SECP192R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP192R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for unused contexts +typedef uint32_t nrf_crypto_backend_secp192r1_sign_context_t; +typedef uint32_t nrf_crypto_backend_secp192r1_verify_context_t; +// Alias for common mbed TLS +#define nrf_crypto_backend_secp192r1_sign nrf_crypto_backend_mbedtls_sign +#define nrf_crypto_backend_secp192r1_verify nrf_crypto_backend_mbedtls_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224R1) +// Context is not used by mbed TLS, so its size is 0 +#define NRF_CRYPTO_BACKEND_SECP224R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP224R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for unused contexts +typedef uint32_t nrf_crypto_backend_secp224r1_sign_context_t; +typedef uint32_t nrf_crypto_backend_secp224r1_verify_context_t; +// Alias for common mbed TLS +#define nrf_crypto_backend_secp224r1_sign nrf_crypto_backend_mbedtls_sign +#define nrf_crypto_backend_secp224r1_verify nrf_crypto_backend_mbedtls_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256R1) +// Context is not used by mbed TLS, so its size is 0 +#define NRF_CRYPTO_BACKEND_SECP256R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for unused contexts +typedef uint32_t nrf_crypto_backend_secp256r1_sign_context_t; +typedef uint32_t nrf_crypto_backend_secp256r1_verify_context_t; +// Alias for common mbed TLS +#define nrf_crypto_backend_secp256r1_sign nrf_crypto_backend_mbedtls_sign +#define nrf_crypto_backend_secp256r1_verify nrf_crypto_backend_mbedtls_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP384R1) +// Context is not used by mbed TLS, so its size is 0 +#define NRF_CRYPTO_BACKEND_SECP384R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP384R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for unused contexts +typedef uint32_t nrf_crypto_backend_secp384r1_sign_context_t; +typedef uint32_t nrf_crypto_backend_secp384r1_verify_context_t; +// Alias for common mbed TLS +#define nrf_crypto_backend_secp384r1_sign nrf_crypto_backend_mbedtls_sign +#define nrf_crypto_backend_secp384r1_verify nrf_crypto_backend_mbedtls_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP521R1) +// Context is not used by mbed TLS, so its size is 0 +#define NRF_CRYPTO_BACKEND_SECP521R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP521R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for unused contexts +typedef uint32_t nrf_crypto_backend_secp521r1_sign_context_t; +typedef uint32_t nrf_crypto_backend_secp521r1_verify_context_t; +// Alias for common mbed TLS +#define nrf_crypto_backend_secp521r1_sign nrf_crypto_backend_mbedtls_sign +#define nrf_crypto_backend_secp521r1_verify nrf_crypto_backend_mbedtls_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192K1) +// Context is not used by mbed TLS, so its size is 0 +#define NRF_CRYPTO_BACKEND_SECP192K1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP192K1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for unused contexts +typedef uint32_t nrf_crypto_backend_secp192k1_sign_context_t; +typedef uint32_t nrf_crypto_backend_secp192k1_verify_context_t; +// Alias for common mbed TLS +#define nrf_crypto_backend_secp192k1_sign nrf_crypto_backend_mbedtls_sign +#define nrf_crypto_backend_secp192k1_verify nrf_crypto_backend_mbedtls_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224K1) +// Context is not used by mbed TLS, so its size is 0 +#define NRF_CRYPTO_BACKEND_SECP224K1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP224K1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for unused contexts +typedef uint32_t nrf_crypto_backend_secp224k1_sign_context_t; +typedef uint32_t nrf_crypto_backend_secp224k1_verify_context_t; +// Alias for common mbed TLS +#define nrf_crypto_backend_secp224k1_sign nrf_crypto_backend_mbedtls_sign +#define nrf_crypto_backend_secp224k1_verify nrf_crypto_backend_mbedtls_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256K1) +// Context is not used by mbed TLS, so its size is 0 +#define NRF_CRYPTO_BACKEND_SECP256K1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256K1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for unused contexts +typedef uint32_t nrf_crypto_backend_secp256k1_sign_context_t; +typedef uint32_t nrf_crypto_backend_secp256k1_verify_context_t; +// Alias for common mbed TLS +#define nrf_crypto_backend_secp256k1_sign nrf_crypto_backend_mbedtls_sign +#define nrf_crypto_backend_secp256k1_verify nrf_crypto_backend_mbedtls_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP256R1) +// Context is not used by mbed TLS, so its size is 0 +#define NRF_CRYPTO_BACKEND_BP256R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_BP256R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for unused contexts +typedef uint32_t nrf_crypto_backend_bp256r1_sign_context_t; +typedef uint32_t nrf_crypto_backend_bp256r1_verify_context_t; +// Alias for common mbed TLS +#define nrf_crypto_backend_bp256r1_sign nrf_crypto_backend_mbedtls_sign +#define nrf_crypto_backend_bp256r1_verify nrf_crypto_backend_mbedtls_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP384R1) +// Context is not used by mbed TLS, so its size is 0 +#define NRF_CRYPTO_BACKEND_BP384R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_BP384R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for unused contexts +typedef uint32_t nrf_crypto_backend_bp384r1_sign_context_t; +typedef uint32_t nrf_crypto_backend_bp384r1_verify_context_t; +// Alias for common mbed TLS +#define nrf_crypto_backend_bp384r1_sign nrf_crypto_backend_mbedtls_sign +#define nrf_crypto_backend_bp384r1_verify nrf_crypto_backend_mbedtls_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP512R1) +// Context is not used by mbed TLS, so its size is 0 +#define NRF_CRYPTO_BACKEND_BP512R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_BP512R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for unused contexts +typedef uint32_t nrf_crypto_backend_bp512r1_sign_context_t; +typedef uint32_t nrf_crypto_backend_bp512r1_verify_context_t; +// Alias for common mbed TLS +#define nrf_crypto_backend_bp512r1_sign nrf_crypto_backend_mbedtls_sign +#define nrf_crypto_backend_bp512r1_verify nrf_crypto_backend_mbedtls_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_ECC_CURVE25519) +// Context is not used by mbed TLS, so its size is 0 +#define NRF_CRYPTO_BACKEND_CURVE25519_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_CURVE25519_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for unused contexts +typedef uint32_t nrf_crypto_backend_curve25519_sign_context_t; +typedef uint32_t nrf_crypto_backend_curve25519_verify_context_t; +// No ECDSA implementation for Curve25519 +#define nrf_crypto_backend_curve25519_sign NULL +#define nrf_crypto_backend_curve25519_verify NULL +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +#endif // MBEDTLS_BACKEND_ECDSA_H__ diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_hash.c b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_hash.c new file mode 100644 index 0000000..bf21243 --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_hash.c @@ -0,0 +1,196 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +#include "mbedtls_backend_hash.h" +#include "nrf_crypto_init.h" +#include "nrf_crypto_types.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_hash_shared.h" +#include "sdk_macros.h" +#include "nrf_log.h" +#include "nrf_assert.h" + +/*lint -save -e????*/ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +/*lint -restore*/ + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA256) + +static ret_code_t mbedtls_backend_hash_sha256_init(void * const p_context) +{ + // No parameter testing on this level. + // This has been done on upper level. + + mbedtls_sha256_context * p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t *)p_context)->context); + + mbedtls_sha256_init(p_backend_context); + + mbedtls_sha256_starts(p_backend_context, 0); + + return NRF_SUCCESS; +} + +static uint32_t mbedtls_backend_hash_sha256_update(void * const p_context, + uint8_t const * p_data, + size_t size) +{ + // Limited parameter testing on this level. + // This has been done on upper level. + + mbedtls_sha256_context * p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t *)p_context)->context); + + mbedtls_sha256_update(p_backend_context, p_data, size); + + return NRF_SUCCESS; +} + + +static uint32_t mbedtls_backend_hash_sha256_finalize(void * const p_context, + uint8_t * p_digest, + size_t * const p_digest_size) +{ + // Limited parameter testing on this level. + // This has been done on upper level. + + mbedtls_sha256_context * p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t *)p_context)->context); + + mbedtls_sha256_finish(p_backend_context, p_digest); + + *p_digest_size = NRF_CRYPTO_HASH_SIZE_SHA256; + + return NRF_SUCCESS; +} + + +const nrf_crypto_hash_info_t g_nrf_crypto_hash_sha256_info = +{ + .init_fn = mbedtls_backend_hash_sha256_init, + .update_fn = mbedtls_backend_hash_sha256_update, + .finalize_fn = mbedtls_backend_hash_sha256_finalize, + .digest_size = NRF_CRYPTO_HASH_SIZE_SHA256, + .context_size = sizeof(nrf_crypto_backend_hash_sha256_context_t), + .hash_mode = NRF_CRYPTO_HASH_MODE_SHA256 +}; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA256) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA512) + + +static ret_code_t mbedtls_backend_hash_sha512_init(void * p_context) +{ + // No parameter testing on this level. + // This has been done on upper level. + + mbedtls_sha512_context * p_backend_context + = &(((nrf_crypto_backend_hash_sha512_context_t *)p_context)->context); + + mbedtls_sha512_init(p_backend_context); + + mbedtls_sha512_starts(p_backend_context, 0); + + return NRF_SUCCESS; +} + + +static ret_code_t mbedtls_backend_hash_sha512_update(void * const p_context, + uint8_t const * p_data, + size_t size) +{ + // Limited parameter testing on this level. + // This has been done on upper level. + + mbedtls_sha512_context * p_backend_context + = &(((nrf_crypto_backend_hash_sha512_context_t *)p_context)->context); + + mbedtls_sha512_update(p_backend_context, p_data, size); + + return NRF_SUCCESS; +} + + +static ret_code_t mbedtls_backend_hash_sha512_finalize(void * const p_context, + uint8_t * p_digest, + size_t * const p_digest_size) +{ + // Limited parameter testing on this level. + // This has been done on upper level. + + mbedtls_sha512_context * p_backend_context + = &(((nrf_crypto_backend_hash_sha512_context_t *)p_context)->context); + + mbedtls_sha512_finish(p_backend_context, p_digest); + + *p_digest_size = NRF_CRYPTO_HASH_SIZE_SHA512; + + return NRF_SUCCESS; +} + + +const nrf_crypto_hash_info_t g_nrf_crypto_hash_sha512_info = +{ + .init_fn = mbedtls_backend_hash_sha512_init, + .update_fn = mbedtls_backend_hash_sha512_update, + .finalize_fn = mbedtls_backend_hash_sha512_finalize, + .digest_size = NRF_CRYPTO_HASH_SIZE_SHA512, + .context_size = sizeof(nrf_crypto_backend_hash_sha512_context_t), + .hash_mode = NRF_CRYPTO_HASH_MODE_SHA512 +}; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA512) + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_hash.h b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_hash.h new file mode 100644 index 0000000..cd9b8ef --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_hash.h @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MBEDTLS_BACKEND_HASH_H__ +#define MBEDTLS_BACKEND_HASH_H__ + +/** @file + * + * @defgroup nrf_crypto_mbedtls_backend_hash nrf_crypto mbedtls backend hash + * @{ + * @ingroup nrf_crypto_mbedtls_backend + * + * @brief Hash functionality provided by the nrf_crypto mbedtls backend. + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +#include "sdk_errors.h" +#include "nrf_crypto_hash_shared.h" + +/*lint -save -e????*/ +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +/*lint -restore*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA256) + +// Flag that nrf_crypto_hash frontend can be compiled +#undef NRF_CRYPTO_HASH_ENABLED +#define NRF_CRYPTO_HASH_ENABLED 1 + +// Duplicate backend enabled test for SHA-256 +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HASH_SHA256) +#error "Duplicate definition of SHA-256. More than one backend enabled"); +#endif + +// Flag that SHA-256 is enabled in backend +#define NRF_CRYPTO_HASH_SHA256_ENABLED 1 + + +/**brief nrf_crypto_hash context for SHA-256 in nrf_crypto mbedtls backend. */ +typedef struct +{ + nrf_crypto_hash_internal_context_t header; /**< Common header for context. */ + mbedtls_sha256_context context; /**< Hash context internal to mbedtls. */ +} nrf_crypto_backend_hash_sha256_context_t; + + +#endif // NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA256_ENABLED + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA512) + +// Flag that nrf_crypto_hash frontend can be compiled +#undef NRF_CRYPTO_HASH_ENABLED +#define NRF_CRYPTO_HASH_ENABLED 1 + +// Duplicate backend enabled test for SHA-512 +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HASH_SHA512) +#error "Duplicate definition of SHA-512. More than one backend enabled"); +#endif + +// Flag that SHA-512 is enabled in backend +#define NRF_CRYPTO_HASH_SHA512_ENABLED 1 + + +/**brief nrf_crypto_hash context for SHA-512 in nrf_crypto mbedtls backend. */ +typedef struct +{ + nrf_crypto_hash_internal_context_t header; /**< Common header for context. */ + mbedtls_sha512_context context; /**< Hash context internal to mbedtls. */ +} nrf_crypto_backend_hash_sha512_context_t; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA512) + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +/**@} */ + +#endif //MBEDTLS_BACKEND_HASH_H__ diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_hmac.c b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_hmac.c new file mode 100644 index 0000000..4399b54 --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_hmac.c @@ -0,0 +1,230 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +#include "nrf_log.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_types.h" +#include "mbedtls_backend_hmac.h" + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA256) + +static ret_code_t mbedtls_backend_hmac_init_sha256(void * const p_context, + uint8_t const * p_key, + size_t key_size) +{ + int err_code; + nrf_crypto_backend_mbedtls_hmac_sha256_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_hmac_sha256_context_t *)p_context; + + // Memset context to 0. This is equevalend with a call to mbedtls_md_init(). + memset(p_ctx->md_ctx_buffer, 0, sizeof(p_ctx->md_ctx_buffer)); + memset(p_ctx->hmac_ctx_buffer, 0, sizeof(p_ctx->hmac_ctx_buffer)); + + // Set info and context pointers to buffer allocated by user. + // This is Normally handled by mbedtls_md_setup(), but has to be done here in order + // to avoid dynamic allocation of memory inside mbed TLS. + p_ctx->mbedtls_ctx.md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + p_ctx->mbedtls_ctx.md_ctx = p_ctx->md_ctx_buffer; + p_ctx->mbedtls_ctx.hmac_ctx = p_ctx->hmac_ctx_buffer; + + // Enter key to start + err_code = mbedtls_md_hmac_starts(&p_ctx->mbedtls_ctx, + p_key, + key_size); + + if (err_code != 0) + { + NRF_LOG_ERROR("Error in mbedtls_md_hmac_starts: %u", err_code); + return NRF_ERROR_CRYPTO_INTERNAL; + } + + return NRF_SUCCESS; +} + + +static ret_code_t mbedtls_backend_hmac_update_sha256(void * const p_context, + uint8_t const * p_data, + size_t size) +{ + int err_code; + nrf_crypto_backend_mbedtls_hmac_sha256_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_hmac_sha256_context_t *)p_context; + + err_code = mbedtls_md_hmac_update(&p_ctx->mbedtls_ctx, p_data, size); + if (err_code != 0) + { + NRF_LOG_ERROR("Error in mbedtls_md_hmac_update: %u", err_code); + return NRF_ERROR_CRYPTO_INTERNAL; + } + + return NRF_SUCCESS; +} + + +static ret_code_t mbedtls_backend_hmac_finalize_sha256(void * const p_context, + uint8_t * p_digest, + size_t * const p_size) +{ + int err_code; + nrf_crypto_backend_mbedtls_hmac_sha256_context_t * const p_ctx = + (nrf_crypto_backend_mbedtls_hmac_sha256_context_t *)p_context; + + // Set the digest length to 0 so that this is used in case of any error. + *p_size = 0; + + err_code = mbedtls_md_hmac_finish(&p_ctx->mbedtls_ctx, p_digest); + if (err_code != 0) + { + NRF_LOG_ERROR("Error in mbedtls_md_hmac_finish: %u", err_code); + return NRF_ERROR_CRYPTO_INTERNAL; + } + + *p_size = p_ctx->header.p_info->digest_size; + + return NRF_SUCCESS; +} + + +// Information structure for HMAC SHA256 using mbed TLS backend. +const nrf_crypto_hmac_info_t g_nrf_crypto_hmac_sha256_info = +{ + .init_fn = mbedtls_backend_hmac_init_sha256, + .update_fn = mbedtls_backend_hmac_update_sha256, + .finalize_fn = mbedtls_backend_hmac_finalize_sha256, + .digest_size = NRF_CRYPTO_HASH_SIZE_SHA256, + .context_size = sizeof(nrf_crypto_backend_hmac_sha256_context_t), + .type = NRF_CRYPTO_HMAC_SHA256_TYPE +}; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA256) + + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA512) + +static ret_code_t mbedtls_backend_hmac_init_sha512(void * const p_context, + uint8_t const * p_key, + size_t key_size) +{ + int err_code; + nrf_crypto_backend_mbedtls_hmac_sha512_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_hmac_sha512_context_t *)p_context; + + // Memset context to 0. This is equevalend with a call to mbedtls_md_init(). + memset(p_ctx->md_ctx_buffer, 0, sizeof(p_ctx->md_ctx_buffer)); + memset(p_ctx->hmac_ctx_buffer, 0, sizeof(p_ctx->hmac_ctx_buffer)); + + // Set info and context pointers to buffer allocated by user. + // (Normally handled by mbedtls_md_setup()) + p_ctx->mbedtls_ctx.md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); + p_ctx->mbedtls_ctx.md_ctx = p_ctx->md_ctx_buffer; + p_ctx->mbedtls_ctx.hmac_ctx = p_ctx->hmac_ctx_buffer; + + // Enter key to start + err_code = mbedtls_md_hmac_starts(&p_ctx->mbedtls_ctx, p_key, key_size); + if (err_code != 0) + { + NRF_LOG_ERROR("Error in mbedtls_md_hmac_starts: %u", err_code); + return NRF_ERROR_CRYPTO_INTERNAL; + } + + return NRF_SUCCESS; +} + + +static ret_code_t mbedtls_backend_hmac_update_sha512(void * const p_context, + uint8_t const * p_data, + size_t size) +{ + int err_code; + nrf_crypto_backend_mbedtls_hmac_sha512_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_hmac_sha512_context_t *)p_context; + + err_code = mbedtls_md_hmac_update(&p_ctx->mbedtls_ctx, p_data, size); + if (err_code != 0) + { + NRF_LOG_ERROR("Error in mbedtls_md_hmac_update: %u", err_code); + return NRF_ERROR_CRYPTO_INTERNAL; + } + + return NRF_SUCCESS; +} + + +static ret_code_t mbedtls_backend_hmac_finalize_sha512(void * const p_context, + uint8_t * p_digest, + size_t * const p_size) +{ + int err_code; + nrf_crypto_backend_mbedtls_hmac_sha512_context_t * p_ctx = + (nrf_crypto_backend_mbedtls_hmac_sha512_context_t *)p_context; + + // Set the digest length to 0 so that this is used in case of any error. + *p_size = 0; + + err_code = mbedtls_md_hmac_finish(&p_ctx->mbedtls_ctx, p_digest); + if (err_code != 0) + { + NRF_LOG_ERROR("Error in mbedtls_md_hmac_finish: %u", err_code); + return NRF_ERROR_CRYPTO_INTERNAL; } + + *p_size = p_ctx->header.p_info->digest_size; + + return NRF_SUCCESS; +} + + +// Information structure for HMAC SHA512 using mbed TLS backend. +const nrf_crypto_hmac_info_t g_nrf_crypto_hmac_sha512_info = +{ + .init_fn = mbedtls_backend_hmac_init_sha512, + .update_fn = mbedtls_backend_hmac_update_sha512, + .finalize_fn = mbedtls_backend_hmac_finalize_sha512, + .digest_size = NRF_CRYPTO_HASH_SIZE_SHA512, + .context_size = sizeof(nrf_crypto_backend_hmac_sha512_context_t), + .type = NRF_CRYPTO_HMAC_SHA512_TYPE +}; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA512) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_hmac.h b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_hmac.h new file mode 100644 index 0000000..04feebf --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_hmac.h @@ -0,0 +1,140 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MBEDTLS_BACKEND_HMAC_H__ +#define MBEDTLS_BACKEND_HMAC_H__ + +/** @file + * + * @defgroup nrf_crypto_mbedtls_backend_hmac mbed TLS backend for HMAC + * @{ + * @ingroup nrf_crypto_mbedtls_backend + * + * @brief Backend wrapper for mbed TLS. None of these types should be used directly by the + * application. + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) && \ + ( NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA256) || \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA512) ) + +#include "nrf_crypto_hmac_shared.h" +/*lint -save -e????*/ +#include "mbedtls/md.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +/*lint -restore*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#undef NRF_CRYPTO_HMAC_ENABLED +#define NRF_CRYPTO_HMAC_ENABLED 1 + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA256) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HMAC_SHA256) +#error "Duplicate definition of HMAC SHA-256. More than one backend enabled" +#endif // NRF_CRYPTO_HMAC_SHA256_ENABLED +#define NRF_CRYPTO_HMAC_SHA256_ENABLED 1 + +/** + * @internal @brief Internal context object used by the mbed TLS backend wrapper for HMAC SHA256. + * + * @note This should never be used directly. Use @ref nrf_crypto_backend_hmac_sha256_context_t + * instead. + */ +typedef struct +{ + nrf_crypto_hmac_internal_context_t header; //!< Internal nrf_crypto_hmac context. + mbedtls_md_context_t mbedtls_ctx; //!< Mbed TLS context object. + uint8_t md_ctx_buffer[sizeof(mbedtls_sha256_context)]; //!< Message digest buffer for mbed TLS. + uint16_t hmac_ctx_buffer[64]; //!< Hash buffer for mbed TLS of size defined in mbedtls_sha256_info in md_internal.h. +} nrf_crypto_backend_mbedtls_hmac_sha256_context_t; + +/** + * @internal @brief Context for HMAC SHA256 using mbed TLS backend. + */ +typedef nrf_crypto_backend_mbedtls_hmac_sha256_context_t nrf_crypto_backend_hmac_sha256_context_t; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA256) + + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA512) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HMAC_SHA512) +#error "Duplicate definition of HMAC SHA-512. More than one backend enabled" +#endif // NRF_CRYPTO_HMAC_SHA512_ENABLED +#define NRF_CRYPTO_HMAC_SHA512_ENABLED 1 + +/** + * @internal @brief Internal context object used by the mbed TLS backend wrapper for HMAC SHA512. + * + * @note This should never be used directly. Use @ref nrf_crypto_backend_hmac_sha512_context_t + * instead. + */ +typedef struct +{ + nrf_crypto_hmac_internal_context_t header; //!< Internal nrf_crypto_hmac context header. + mbedtls_md_context_t mbedtls_ctx; //!< Mbed TLS context object. + uint8_t md_ctx_buffer[sizeof(mbedtls_sha512_context)]; //!< Message digest buffer for mbed TLS. + uint16_t hmac_ctx_buffer[128]; //!< Hash buffer for mbed TLS of size defined in mbedtls_sha512_info in md_internal.h. +} nrf_crypto_backend_mbedtls_hmac_sha512_context_t; + +/** + * @internal @brief Context for HMAC SHA512 using mbed TLS backend. + */ +typedef nrf_crypto_backend_mbedtls_hmac_sha512_context_t nrf_crypto_backend_hmac_sha512_context_t; + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA512) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) && ( NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA256) || NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA512) ) + +/**@} */ + +#endif // MBEDTLS_BACKEND_HMAC_H__ diff --git a/components/libraries/crypto/backend/mbedtls/mbedtls_backend_init.c b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_init.c new file mode 100644 index 0000000..4e6dcac --- /dev/null +++ b/components/libraries/crypto/backend/mbedtls/mbedtls_backend_init.c @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#include "sdk_config.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) + +#include +#include +#include "nrf_crypto_init.h" +#include "nrf_crypto_mem.h" +/*lint -save -e????*/ +#include "mbedtls/platform.h" +/*lint -restore*/ + + +#if NRF_CRYPTO_ALLOC_ON_STACK +#error "MBED TLS backend does not support memory allocation on stack. Use different allocator." +#endif + + +/** @internal @brief Function to use NRF_CRYPTO_ALLOC for MBED TLS memory allocation. + */ +static void * mbedtls_backend_calloc(size_t count, size_t size) +{ + size_t total_size = count * size; + void * p_data = NRF_CRYPTO_ALLOC(total_size); + if (p_data != NULL) + { + memset(p_data, 0, total_size); + } + return p_data; +} + + +/** @internal @brief Function to use NRF_CRYPTO_FREE for MBED TLS memory deallocation. + */ +static void mbedtls_backend_free(void * p_data) +{ + NRF_CRYPTO_FREE(p_data); +} + + +/** @internal @brief Function to initialize MBED TLS backend - setup memory management for. + */ +static ret_code_t mbedtls_backend_init(void) +{ + (void)mbedtls_platform_set_calloc_free(mbedtls_backend_calloc, mbedtls_backend_free); + return NRF_SUCCESS; +} + + +/** @internal @brief Function to uninitialize MBED TLS backend - currently no implementation is required. + */ +static ret_code_t mbedtls_backend_uninit(void) +{ + // Empty implementation + return NRF_SUCCESS; +} + + +CRYPTO_BACKEND_REGISTER(nrf_crypto_backend_info_t const mbedtls_backend) = +{ + .init_fn = mbedtls_backend_init, + .uninit_fn = mbedtls_backend_uninit, +}; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) diff --git a/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecc.c b/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecc.c new file mode 100644 index 0000000..c57dedc --- /dev/null +++ b/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecc.c @@ -0,0 +1,341 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC) + +#include +#include +#include + +#include "app_util.h" +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_rng.h" +#include "nrf_crypto_shared.h" +#include "micro_ecc_backend_ecc.h" +#include "micro_ecc_backend_shared.h" +#include "uECC.h" + + +typedef uECC_Curve (*micro_ecc_curve_fn_t)(void); + + +int nrf_crypto_backend_micro_ecc_rng_callback(uint8_t * dest, unsigned size) +{ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) + + ret_code_t result; + + result = nrf_crypto_rng_vector_generate(dest, size); + + // Return values compatible with mbed TLS + if (result != NRF_SUCCESS) + { + return 0; + } + return 1; + +#else + UNUSED_PARAMETER(dest); + UNUSED_PARAMETER(size); + return 0; +#endif +} + + +uECC_Curve nrf_crypto_backend_micro_ecc_curve_get( + nrf_crypto_backend_micro_ecc_common_key_t const * p_key) +{ + nrf_crypto_internal_ecc_key_header_t const * p_key_header = + (nrf_crypto_internal_ecc_key_header_t const *)p_key; + + //lint -save -e611 (Suspicious cast) + micro_ecc_curve_fn_t micro_ecc_curve_fn = + (micro_ecc_curve_fn_t)p_key_header->p_info->p_backend_data; + //lint -restore + + uECC_Curve p_micro_ecc_curve = micro_ecc_curve_fn(); + + return p_micro_ecc_curve; +} + + +ret_code_t nrf_crypto_backend_micro_ecc_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key) +{ + int result; + + nrf_crypto_backend_micro_ecc_common_key_t * p_prv = + (nrf_crypto_backend_micro_ecc_common_key_t *)p_private_key; + nrf_crypto_backend_micro_ecc_common_key_t * p_pub = + (nrf_crypto_backend_micro_ecc_common_key_t *)p_public_key; + + uECC_Curve p_micro_ecc_curve = nrf_crypto_backend_micro_ecc_curve_get(p_prv); + + uECC_set_rng(nrf_crypto_backend_micro_ecc_rng_callback); + + result = uECC_make_key((uint8_t *)(&p_pub->key[0]), + (uint8_t *)(&p_prv->key[0]), + p_micro_ecc_curve); + + if (result == 0) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_micro_ecc_public_key_calculate( + void * p_context, + void const * p_private_key, + void * p_public_key) +{ + int result; + + nrf_crypto_backend_micro_ecc_common_key_t const * p_prv = + (nrf_crypto_backend_micro_ecc_common_key_t const *)p_private_key; + nrf_crypto_backend_micro_ecc_common_key_t * p_pub = + (nrf_crypto_backend_micro_ecc_common_key_t *)p_public_key; + + uECC_Curve p_micro_ecc_curve = nrf_crypto_backend_micro_ecc_curve_get(p_prv); + + result = uECC_compute_public_key((uint8_t *)(&p_prv->key[0]), + (uint8_t *)(&p_pub->key[0]), + p_micro_ecc_curve); + + if (result == 0) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_micro_ecc_private_key_from_raw( + void * p_private_key, + uint8_t const * p_raw_data) +{ + nrf_crypto_backend_micro_ecc_common_key_t * p_prv = + (nrf_crypto_backend_micro_ecc_common_key_t *)p_private_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info; + +#if ECC_BACKEND_SWAP_BYTES + nrf_crypto_internal_swap_endian((uint8_t *)(&p_prv->key[0]), + p_raw_data, + p_info->raw_private_key_size); +#else + memcpy(&p_prv->key[0], p_raw_data, p_info->raw_private_key_size); +#endif + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_micro_ecc_private_key_to_raw( + void const * p_private_key, + uint8_t * p_raw_data) +{ + nrf_crypto_backend_micro_ecc_common_key_t const * p_prv = + (nrf_crypto_backend_micro_ecc_common_key_t const *)p_private_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info; + +#if ECC_BACKEND_SWAP_BYTES + nrf_crypto_internal_swap_endian(p_raw_data, + (uint8_t *)(&p_prv->key[0]), + p_info->raw_private_key_size); +#else + memcpy(p_raw_data, &p_prv->key[0], p_info->raw_private_key_size); +#endif + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_micro_ecc_public_key_from_raw( + void * p_public_key, + uint8_t const * p_raw_data) +{ + nrf_crypto_backend_micro_ecc_common_key_t * p_pub = + (nrf_crypto_backend_micro_ecc_common_key_t *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info; + +#if ECC_BACKEND_SWAP_BYTES + nrf_crypto_internal_double_swap_endian((uint8_t *)(&p_pub->key[0]), + p_raw_data, + p_info->raw_private_key_size); +#else + memcpy(&p_pub->key[0], p_raw_data, p_info->raw_public_key_size); +#endif + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_micro_ecc_public_key_to_raw( + void const * p_public_key, + uint8_t * p_raw_data) +{ + nrf_crypto_backend_micro_ecc_common_key_t const * p_pub = + (nrf_crypto_backend_micro_ecc_common_key_t const *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info; + +#if ECC_BACKEND_SWAP_BYTES + nrf_crypto_internal_double_swap_endian(p_raw_data, + (uint8_t *)(&p_pub->key[0]), + p_info->raw_private_key_size); +#else + memcpy(p_raw_data, &p_pub->key[0], p_info->raw_public_key_size); +#endif + + return NRF_SUCCESS; +} + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1) + +// Make sure that common key structure match secp192r1 (NIST 192-bit) key structure to safely cast types. +STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) == + offsetof(nrf_crypto_backend_secp192r1_private_key_t, key), + "Common uECC private key structure does not match secp192r1 (NIST 192-bit) one."); +STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) == + offsetof(nrf_crypto_backend_secp192r1_public_key_t, key), + "Common ECC public key structure does not match secp192r1 (NIST 192-bit) one."); + +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp192r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_secp192r1_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_secp192r1_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP192R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP192R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP192R1_RAW_PUBLIC_KEY_SIZE, + //lint -save -e611 -e546 (Suspicious cast, Suspicious use of &) + .p_backend_data = (void *)&uECC_secp192r1, + //lint -restore +}; + +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1) + +// Make sure that common key structure match secp224r1 (NIST 224-bit) key structure to safely cast types. +STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) == + offsetof(nrf_crypto_backend_secp224r1_private_key_t, key), + "Common uECC private key structure does not match secp224r1 (NIST 224-bit) one."); +STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) == + offsetof(nrf_crypto_backend_secp224r1_public_key_t, key), + "Common ECC public key structure does not match secp224r1 (NIST 224-bit) one."); + +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp224r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_secp224r1_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_secp224r1_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP224R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP224R1_RAW_PUBLIC_KEY_SIZE, + //lint -save -e611 -e546 (Suspicious cast, Suspicious use of &) + .p_backend_data = (void *)&uECC_secp224r1, + //lint -restore +}; + +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1) + +// Make sure that common key structure match secp256r1 (NIST 256-bit) key structure to safely cast types. +STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) == + offsetof(nrf_crypto_backend_secp256r1_private_key_t, key), + "Common uECC private key structure does not match secp256r1 (NIST 256-bit) one."); +STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) == + offsetof(nrf_crypto_backend_secp256r1_public_key_t, key), + "Common ECC public key structure does not match secp256r1 (NIST 256-bit) one."); + +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp256r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_secp256r1_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_secp256r1_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP256R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE, + //lint -save -e611 -e546 (Suspicious cast, Suspicious use of &) + .p_backend_data = (void *)&uECC_secp256r1, + //lint -restore +}; + +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1) + +// Make sure that common key structure match secp256k1 (Koblitz 256-bit) key structure to safely cast types. +STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) == + offsetof(nrf_crypto_backend_secp256k1_private_key_t, key), + "Common uECC private key structure does not match secp256k1 (Koblitz 256-bit) one."); +STATIC_ASSERT(offsetof(nrf_crypto_backend_micro_ecc_common_key_t, key) == + offsetof(nrf_crypto_backend_secp256k1_public_key_t, key), + "Common ECC public key structure does not match secp256k1 (Koblitz 256-bit) one."); + + +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp256k1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_secp256k1_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_secp256k1_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP256K1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP256K1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP256K1_RAW_PUBLIC_KEY_SIZE, + //lint -save -e611 -e546 (Suspicious cast, Suspicious use of &) + .p_backend_data = (void *)&uECC_secp256k1, + //lint -restore +}; + +#endif + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC) diff --git a/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecc.h b/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecc.h new file mode 100644 index 0000000..0a4aa65 --- /dev/null +++ b/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecc.h @@ -0,0 +1,303 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MICRO_ECC_BACKEND_ECC_H__ +#define MICRO_ECC_BACKEND_ECC_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC) + +#include +#include +#include "nrf_crypto_ecc_shared.h" +#include "uECC.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @internal See @ref nrf_crypto_backend_ecc_key_pair_generate_fn_t. + */ +ret_code_t nrf_crypto_backend_micro_ecc_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_calculate_fn_t. +*/ +ret_code_t nrf_crypto_backend_micro_ecc_public_key_calculate( + void * p_context, + void const * p_private_key, + void * p_public_key); + + +/** @internal See @ref nrf_crypto_backend_ecc_private_key_from_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_micro_ecc_private_key_from_raw( + void * p_private_key, + uint8_t const * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_private_key_to_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_micro_ecc_private_key_to_raw( + void const * p_private_key, + uint8_t * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_from_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_micro_ecc_public_key_from_raw( + void * p_public_key, + uint8_t const * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_to_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_micro_ecc_public_key_to_raw( + void const * p_public_key, + uint8_t * p_raw_data); + + +/** @internal @brief Represents common uECC backend key structure. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + uint32_t key[1]; /**< @internal @brief micro-ecc specific key representation */ +} nrf_crypto_backend_micro_ecc_common_key_t; + + +/** @internal @brief Callback RNG function that can be provided to uECC API. + * @param dest Destination buffer. + * @param size Size of the buffer. + * @return 1 on success, 0 on error. + */ +int nrf_crypto_backend_micro_ecc_rng_callback(uint8_t * dest, unsigned size); + + +/** @internal @brief Gets uECC type based on provided key. + * @param p_key uECC backend key (public or private). + * @return uECC specific value representing a curve. + */ +uECC_Curve nrf_crypto_backend_micro_ecc_curve_get( + nrf_crypto_backend_micro_ecc_common_key_t const * p_key); + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP192R1) +#error "More than one backend enabled for secp192r1 (NIST 192-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP192R1_ENABLED 1 + +/** @internal @brief Structure holding private key for secp192r1 (NIST 192-bit) in micro-ecc. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + uint32_t key[192 / 32]; /**< @internal @brief micro-ecc specific key representation */ +} nrf_crypto_backend_secp192r1_private_key_t; + +/** @internal @brief Structure holding public key for secp192r1 (NIST 192-bit) in micro-ecc. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + uint32_t key[2 * 192 / 32]; /**< @internal @brief micro-ecc specific key representation */ +} nrf_crypto_backend_secp192r1_public_key_t; + +// Aliases for one common micro-ecc implementation +#define nrf_crypto_backend_secp192r1_key_pair_generate nrf_crypto_backend_micro_ecc_key_pair_generate +#define nrf_crypto_backend_secp192r1_public_key_calculate nrf_crypto_backend_micro_ecc_public_key_calculate +#define nrf_crypto_backend_secp192r1_private_key_from_raw nrf_crypto_backend_micro_ecc_private_key_from_raw +#define nrf_crypto_backend_secp192r1_private_key_to_raw nrf_crypto_backend_micro_ecc_private_key_to_raw +#define nrf_crypto_backend_secp192r1_public_key_from_raw nrf_crypto_backend_micro_ecc_public_key_from_raw +#define nrf_crypto_backend_secp192r1_public_key_to_raw nrf_crypto_backend_micro_ecc_public_key_to_raw +#define nrf_crypto_backend_secp192r1_private_key_free NULL +#define nrf_crypto_backend_secp192r1_public_key_free NULL +#define NRF_CRYPTO_BACKEND_SECP192R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP192R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp192r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp192r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP224R1) +#error "More than one backend enabled for secp224r1 (NIST 224-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP224R1_ENABLED 1 + +/** @internal @brief Structure holding private key for secp224r1 (NIST 224-bit) in micro-ecc. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + uint32_t key[224 / 32]; /**< @internal @brief micro-ecc specific key representation */ +} nrf_crypto_backend_secp224r1_private_key_t; + +/** @internal @brief Structure holding public key for secp224r1 (NIST 224-bit) in micro-ecc. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + uint32_t key[2 * 224 / 32]; /**< @internal @brief micro-ecc specific key representation */ +} nrf_crypto_backend_secp224r1_public_key_t; + +// Aliases for one common micro-ecc implementation +#define nrf_crypto_backend_secp224r1_key_pair_generate nrf_crypto_backend_micro_ecc_key_pair_generate +#define nrf_crypto_backend_secp224r1_public_key_calculate nrf_crypto_backend_micro_ecc_public_key_calculate +#define nrf_crypto_backend_secp224r1_private_key_from_raw nrf_crypto_backend_micro_ecc_private_key_from_raw +#define nrf_crypto_backend_secp224r1_private_key_to_raw nrf_crypto_backend_micro_ecc_private_key_to_raw +#define nrf_crypto_backend_secp224r1_public_key_from_raw nrf_crypto_backend_micro_ecc_public_key_from_raw +#define nrf_crypto_backend_secp224r1_public_key_to_raw nrf_crypto_backend_micro_ecc_public_key_to_raw +#define nrf_crypto_backend_secp224r1_private_key_free NULL +#define nrf_crypto_backend_secp224r1_public_key_free NULL +#define NRF_CRYPTO_BACKEND_SECP224R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP224R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp224r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp224r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP256R1) +#error "More than one backend enabled for secp256r1 (NIST 256-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP256R1_ENABLED 1 + +/** @internal @brief Structure holding private key for secp256r1 (NIST 256-bit) in micro-ecc. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + uint32_t key[256 / 32]; /**< @internal @brief micro-ecc specific key representation */ +} nrf_crypto_backend_secp256r1_private_key_t; + +/** @internal @brief Structure holding public key for secp256r1 (NIST 256-bit) in micro-ecc. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + uint32_t key[2 * 256 / 32]; /**< @internal @brief micro-ecc specific key representation */ +} nrf_crypto_backend_secp256r1_public_key_t; + +// Aliases for one common micro-ecc implementation +#define nrf_crypto_backend_secp256r1_key_pair_generate nrf_crypto_backend_micro_ecc_key_pair_generate +#define nrf_crypto_backend_secp256r1_public_key_calculate nrf_crypto_backend_micro_ecc_public_key_calculate +#define nrf_crypto_backend_secp256r1_private_key_from_raw nrf_crypto_backend_micro_ecc_private_key_from_raw +#define nrf_crypto_backend_secp256r1_private_key_to_raw nrf_crypto_backend_micro_ecc_private_key_to_raw +#define nrf_crypto_backend_secp256r1_public_key_from_raw nrf_crypto_backend_micro_ecc_public_key_from_raw +#define nrf_crypto_backend_secp256r1_public_key_to_raw nrf_crypto_backend_micro_ecc_public_key_to_raw +#define nrf_crypto_backend_secp256r1_private_key_free NULL +#define nrf_crypto_backend_secp256r1_public_key_free NULL +#define NRF_CRYPTO_BACKEND_SECP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp256r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp256r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP256K1) +#error "More than one backend enabled for secp256k1 (Koblitz 256-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP256K1_ENABLED 1 + +/** @internal @brief Structure holding private key for secp256k1 (Koblitz 256-bit) in micro-ecc. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + uint32_t key[256 / 32]; /**< @internal @brief micro-ecc specific key representation */ +} nrf_crypto_backend_secp256k1_private_key_t; + +/** @internal @brief Structure holding public key for secp256k1 (Koblitz 256-bit) in micro-ecc. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + uint32_t key[2 * 256 / 32]; /**< @internal @brief micro-ecc specific key representation */ +} nrf_crypto_backend_secp256k1_public_key_t; + +// Aliases for one common micro-ecc implementation +#define nrf_crypto_backend_secp256k1_key_pair_generate nrf_crypto_backend_micro_ecc_key_pair_generate +#define nrf_crypto_backend_secp256k1_public_key_calculate nrf_crypto_backend_micro_ecc_public_key_calculate +#define nrf_crypto_backend_secp256k1_private_key_from_raw nrf_crypto_backend_micro_ecc_private_key_from_raw +#define nrf_crypto_backend_secp256k1_private_key_to_raw nrf_crypto_backend_micro_ecc_private_key_to_raw +#define nrf_crypto_backend_secp256k1_public_key_from_raw nrf_crypto_backend_micro_ecc_public_key_from_raw +#define nrf_crypto_backend_secp256k1_public_key_to_raw nrf_crypto_backend_micro_ecc_public_key_to_raw +#define nrf_crypto_backend_secp256k1_private_key_free NULL +#define nrf_crypto_backend_secp256k1_public_key_free NULL +#define NRF_CRYPTO_BACKEND_SECP256K1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp256k1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp256k1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC) + +#endif // MICRO_ECC_BACKEND_ECC_H__ diff --git a/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdh.c b/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdh.c new file mode 100644 index 0000000..1a97fb7 --- /dev/null +++ b/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdh.c @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC) + +#include + +#include "nrf_crypto_ecc_shared.h" +#include "nrf_crypto_ecdh_shared.h" +#include "nrf_crypto_ecdh.h" +#include "nrf_crypto_shared.h" +#include "micro_ecc_backend_ecc.h" +#include "micro_ecc_backend_shared.h" +#include "uECC.h" + + +ret_code_t nrf_crypto_backend_micro_ecc_ecdh_compute( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret) +{ + int result; + + nrf_crypto_backend_micro_ecc_common_key_t const * p_prv = + (nrf_crypto_backend_micro_ecc_common_key_t const *)p_private_key; + nrf_crypto_backend_micro_ecc_common_key_t const * p_pub = + (nrf_crypto_backend_micro_ecc_common_key_t const *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info; + + uECC_Curve p_micro_ecc_curve = nrf_crypto_backend_micro_ecc_curve_get(p_prv); + + // Check that the public key is valid + if (!uECC_valid_public_key((uint8_t *)(&p_pub->key[0]), p_micro_ecc_curve)) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + result = uECC_shared_secret((uint8_t const *)(&p_pub->key[0]), + (uint8_t const *)(&p_prv->key[0]), + p_shared_secret, + p_micro_ecc_curve); + +#if ECC_BACKEND_SWAP_BYTES + nrf_crypto_internal_swap_endian_in_place(p_shared_secret, p_info->raw_private_key_size); +#else + UNUSED_PARAMETER(p_info); +#endif + + if (result == 0) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + + + + return NRF_SUCCESS; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC) diff --git a/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdh.h b/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdh.h new file mode 100644 index 0000000..794cc6d --- /dev/null +++ b/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdh.h @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MICRO_ECC_BACKEND_ECDH_H__ +#define MICRO_ECC_BACKEND_ECDH_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC) + +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdh_shared.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @internal See @ref nrf_crypto_backend_ecdh_compute_fn_t. + */ +ret_code_t nrf_crypto_backend_micro_ecc_ecdh_compute( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret); + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1) +// Aliases for one common MICRO_ECC implementation +#define nrf_crypto_backend_secp192r1_ecdh_compute nrf_crypto_backend_micro_ecc_ecdh_compute +typedef uint32_t nrf_crypto_backend_secp192r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP192R1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1) +// Aliases for one common MICRO_ECC implementation +#define nrf_crypto_backend_secp224r1_ecdh_compute nrf_crypto_backend_micro_ecc_ecdh_compute +typedef uint32_t nrf_crypto_backend_secp224r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP224R1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1) +// Aliases for one common MICRO_ECC implementation +#define nrf_crypto_backend_secp256r1_ecdh_compute nrf_crypto_backend_micro_ecc_ecdh_compute +typedef uint32_t nrf_crypto_backend_secp256r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP256R1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1) +// Aliases for one common MICRO_ECC implementation +#define nrf_crypto_backend_secp256k1_ecdh_compute nrf_crypto_backend_micro_ecc_ecdh_compute +typedef uint32_t nrf_crypto_backend_secp256k1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP256K1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC) + +#endif // MICRO_ECC_BACKEND_ECDH_H__ diff --git a/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdsa.c b/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdsa.c new file mode 100644 index 0000000..b734591 --- /dev/null +++ b/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdsa.c @@ -0,0 +1,166 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC) + +#include +#include +#include + +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdsa.h" +#include "nrf_crypto_shared.h" +#include "nrf_crypto_mem.h" +#include "micro_ecc_backend_ecc.h" +#include "micro_ecc_backend_shared.h" +#include "uECC.h" + + +ret_code_t nrf_crypto_backend_micro_ecc_sign( + void * p_context, + void const * p_private_key, + uint8_t const * p_data, + size_t data_size, + uint8_t * p_signature) +{ + int result; + + nrf_crypto_backend_micro_ecc_common_key_t const * p_prv = + (nrf_crypto_backend_micro_ecc_common_key_t const *)p_private_key; + + uECC_Curve p_micro_ecc_curve = nrf_crypto_backend_micro_ecc_curve_get(p_prv); + +#if ECC_BACKEND_SWAP_BYTES + + nrf_crypto_ecc_curve_info_t const * p_info = p_prv->header.p_info; + + size_t hash_size = MIN(data_size, p_info->raw_private_key_size); + uint8_t hash_le[NRF_CRYPTO_ECC_RAW_PRIVATE_KEY_MAX_SIZE]; + + nrf_crypto_internal_swap_endian(hash_le, p_data, hash_size); + + uECC_set_rng(nrf_crypto_backend_micro_ecc_rng_callback); + + result = uECC_sign((uint8_t const *)(&p_prv->key[0]), + hash_le, + hash_size, + p_signature, + p_micro_ecc_curve); + + nrf_crypto_internal_double_swap_endian_in_place(p_signature, p_info->raw_private_key_size); + +#else + + uECC_set_rng(nrf_crypto_backend_micro_ecc_rng_callback); + + result = uECC_sign((uint8_t const *)(&p_prv->key[0]), + p_data, + data_size, + p_signature, + p_micro_ecc_curve); + +#endif + + if (result == 0) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_micro_ecc_verify( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature) +{ + int result; + + nrf_crypto_backend_micro_ecc_common_key_t const * p_pub = + (nrf_crypto_backend_micro_ecc_common_key_t const *)p_public_key; + + uECC_Curve p_micro_ecc_curve = nrf_crypto_backend_micro_ecc_curve_get(p_pub); + +#if ECC_BACKEND_SWAP_BYTES + + nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info; + + size_t hash_size = MIN(data_size, p_info->raw_private_key_size); + uint8_t hash_le [NRF_CRYPTO_ECC_RAW_PRIVATE_KEY_MAX_SIZE]; + uint8_t signature_le[NRF_CRYPTO_ECDSA_SIGNATURE_MAX_SIZE]; + + nrf_crypto_internal_swap_endian(hash_le, p_data, hash_size); + + nrf_crypto_internal_double_swap_endian(signature_le, + p_signature, + p_info->raw_private_key_size); + + result = uECC_verify((uint8_t const *)(&p_pub->key[0]), + hash_le, + hash_size, + signature_le, + p_micro_ecc_curve); + +#else + + result = uECC_verify((uint8_t const *)(&p_pub->key[0]), + p_data, + data_size, + p_signature, + p_micro_ecc_curve); + +#endif + + if (result == 0) + { + return NRF_ERROR_CRYPTO_ECDSA_INVALID_SIGNATURE; + } + + return NRF_SUCCESS; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC) + diff --git a/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdsa.h b/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdsa.h new file mode 100644 index 0000000..a1841d6 --- /dev/null +++ b/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdsa.h @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MICRO_ECC_BACKEND_ECDSA_H__ +#define MICRO_ECC_BACKEND_ECDSA_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC) + +#include "nrf_crypto_ecc_shared.h" +#include "nrf_crypto_ecdsa_shared.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @internal See @ref nrf_crypto_backend_ecdsa_sign_fn_t. + */ +ret_code_t nrf_crypto_backend_micro_ecc_sign( + void * p_context, + void const * p_private_key, + uint8_t const * p_data, + size_t data_size, + uint8_t * p_signature); + + +/** @internal See @ref nrf_crypto_backend_ecdsa_verify_fn_t. + */ +ret_code_t nrf_crypto_backend_micro_ecc_verify( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature); + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1) +#define NRF_CRYPTO_BACKEND_SECP192R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP192R1_VERIFY_CONTEXT_SIZE 0 +typedef uint32_t nrf_crypto_backend_secp192r1_sign_context_t; +typedef uint32_t nrf_crypto_backend_secp192r1_verify_context_t; +#define nrf_crypto_backend_secp192r1_sign nrf_crypto_backend_micro_ecc_sign +#define nrf_crypto_backend_secp192r1_verify nrf_crypto_backend_micro_ecc_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1) +#define NRF_CRYPTO_BACKEND_SECP224R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP224R1_VERIFY_CONTEXT_SIZE 0 +typedef uint32_t nrf_crypto_backend_secp224r1_sign_context_t; +typedef uint32_t nrf_crypto_backend_secp224r1_verify_context_t; +#define nrf_crypto_backend_secp224r1_sign nrf_crypto_backend_micro_ecc_sign +#define nrf_crypto_backend_secp224r1_verify nrf_crypto_backend_micro_ecc_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1) +#define NRF_CRYPTO_BACKEND_SECP256R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256R1_VERIFY_CONTEXT_SIZE 0 +typedef uint32_t nrf_crypto_backend_secp256r1_sign_context_t; +typedef uint32_t nrf_crypto_backend_secp256r1_verify_context_t; +#define nrf_crypto_backend_secp256r1_sign nrf_crypto_backend_micro_ecc_sign +#define nrf_crypto_backend_secp256r1_verify nrf_crypto_backend_micro_ecc_verify +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1) +#define NRF_CRYPTO_BACKEND_SECP256K1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256K1_VERIFY_CONTEXT_SIZE 0 +typedef uint32_t nrf_crypto_backend_secp256k1_sign_context_t; +typedef uint32_t nrf_crypto_backend_secp256k1_verify_context_t; +#define nrf_crypto_backend_secp256k1_sign nrf_crypto_backend_micro_ecc_sign +#define nrf_crypto_backend_secp256k1_verify nrf_crypto_backend_micro_ecc_verify +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC) + +#endif // MICRO_ECC_BACKEND_ECDSA_H__ diff --git a/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_shared.h b/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_shared.h new file mode 100644 index 0000000..2d62840 --- /dev/null +++ b/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_shared.h @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef MICRO_ECC_BACKEND_SHARED_H__ +#define MICRO_ECC_BACKEND_SHARED_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC) + +#include "uECC.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined(NRF_CRYPTO_BACKEND_MICRO_ECC_LITTLE_ENDIAN_ENABLED) + +#error The configuration NRF_CRYPTO_BACKEND_MICRO_ECC_LITTLE_ENDIAN_ENABLED was removed in SDK 15.1.0. Please see release notes for details on removing this error message. + +#endif + +#define ECC_BACKEND_SWAP_BYTES uECC_VLI_NATIVE_LITTLE_ENDIAN + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MICRO_ECC) + +#endif // MICRO_ECC_BACKEND_ECDSA_H__ diff --git a/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_init.c b/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_init.c new file mode 100644 index 0000000..81abace --- /dev/null +++ b/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_init.c @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG) + +#include "nrf.h" +#include "nrf_crypto_init.h" +#include "nrf_crypto_rng.h" + + +static ret_code_t nrf_hw_backend_init(void) +{ +#if defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 1) + + uint32_t ret_val; + ret_val = nrf_crypto_rng_init(NULL, NULL); + return ret_val; + +#elif defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 0) + + return NRF_SUCCESS; + +#else + + #warning NRF_CRYPTO_RNG_AUTO_INIT_ENABLED define not found in sdk_config.h (Is the sdk_config.h valid?). + +#endif // NRF_CRYPTO_RNG_AUTO_INIT_ENABLED +} + + +static ret_code_t nrf_hw_backend_uninit(void) +{ +#if defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 1) + + uint32_t ret_val; + ret_val = nrf_crypto_rng_uninit(); + return ret_val; + +#elif defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 0) + + return NRF_SUCCESS; + +#else + + #warning NRF_CRYPTO_RNG_AUTO_INIT_ENABLED define not found in sdk_config.h (Is the sdk_config.h valid?). + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_RNG_AUTO_INIT) +} + + +CRYPTO_BACKEND_REGISTER(nrf_crypto_backend_info_t const nrf_hw_backend) = +{ + .init_fn = nrf_hw_backend_init, + .uninit_fn = nrf_hw_backend_uninit +}; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG) diff --git a/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_rng.c b/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_rng.c new file mode 100644 index 0000000..647e4df --- /dev/null +++ b/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_rng.c @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG) && \ + !NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG) + +#include "nrf_crypto_rng.h" +#include "nrf_drv_rng.h" + + +ret_code_t nrf_crypto_rng_backend_init(void * const p_context, + void * const p_temp_buffer) +{ + ret_code_t ret_val; + + UNUSED_PARAMETER(p_context); + UNUSED_PARAMETER(p_temp_buffer); + + ret_val = nrf_drv_rng_init(NULL); + + return ret_val; +} + + +ret_code_t nrf_crypto_rng_backend_uninit(void * const p_context) +{ + UNUSED_PARAMETER(p_context); + + nrf_drv_rng_uninit(); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_rng_backend_vector_generate(void * const p_context, + uint8_t * const p_target, + size_t size, + bool use_mutex) +{ + UNUSED_PARAMETER(use_mutex); + UNUSED_PARAMETER(p_context); + + nrf_drv_rng_block_rand(p_target, size); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_rng_backend_reseed(void * const p_context, + void * p_temp_buffer, + uint8_t * p_input_data, + size_t size) +{ + UNUSED_PARAMETER(p_context); + UNUSED_PARAMETER(p_temp_buffer); + UNUSED_PARAMETER(p_input_data); + UNUSED_PARAMETER(size); + + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; +} + +#endif //NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG) && !NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG) diff --git a/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_rng.h b/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_rng.h new file mode 100644 index 0000000..e399d9f --- /dev/null +++ b/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_rng.h @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_HW_BACKEND_RNG_H__ +#define NRF_HW_BACKEND_RNG_H__ + +/** @file + * + * @defgroup nrf_crypto_nrf_hw_backend_rng nrf_crypto HW RNG backend + * @{ + * @ingroup nrf_crypto_backends + * + * @brief RNG functionality provided by the nrf_crypto nRF HW RNG backend. + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG) && \ + !NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG) + +#if !NRF_MODULE_ENABLED(RNG) +#error Enable RNG_ENABLED in sdk_config.h. +#endif + +#if !NRFX_RNG_CONFIG_ERROR_CORRECTION +#error Enable NRFX_RNG_CONFIG_ERROR_CORRECTION and RNG_CONFIG_ERROR_CORRECTION in sdk_config.h. +#endif + +#include "nrf_crypto_rng_shared.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) +#error "More than one RNG backend enabled." +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) +#define NRF_CRYPTO_RNG_ENABLED 1 + + +/** + * @internal @brief Context for nRF RNG peripheral. + */ +typedef struct +{ + nrf_crypto_rng_internal_context_t header; //!< Internal common context header. +} nrf_crypto_backend_rng_context_t; + +/** + * @internal @brief Dummy temp buffer for nRF RNG peripheral. + */ +typedef struct +{ + uint32_t reserved; +} nrf_crypto_backend_rng_temp_buffer_t; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG) && !NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG) + +/**@} */ + +#endif // NRF_HW_BACKEND_RNG_H__ diff --git a/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_rng_mbedtls.c b/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_rng_mbedtls.c new file mode 100644 index 0000000..a0382bd --- /dev/null +++ b/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_rng_mbedtls.c @@ -0,0 +1,168 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG) && \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG) + +#include "nrf_crypto_rng.h" +#include "nrf_drv_rng.h" +#include "nrf_hw_backend_rng_mbedtls.h" + + +// Function to convert mbedtls error codes to ret_code_t. +static ret_code_t result_get(int mbedtls_ret_val) +{ + ret_code_t ret_val; + switch (mbedtls_ret_val) + { + case 0: + ret_val = NRF_SUCCESS; + break; + + case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG: + ret_val = NRF_ERROR_CRYPTO_INPUT_LENGTH; + break; + + case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG: + ret_val = NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + break; + + case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED: + default: + ret_val = NRF_ERROR_CRYPTO_INTERNAL; + break; + } + + return ret_val; +} + + +// Callback function used by mbed TLS to seed and reseed. +static int entropy_callback(void * p_entropy, unsigned char * p_buffer, size_t size) +{ + UNUSED_PARAMETER(p_entropy); + + nrf_drv_rng_block_rand(p_buffer, size); + + return 0; +} + + +ret_code_t nrf_crypto_rng_backend_init(void * const p_context, void * const p_temp_buffer) +{ + ret_code_t ret_val; + int mbedtls_ret_val; + mbedtls_ctr_drbg_context * p_mbedtls_context = + &((nrf_crypto_backend_rng_context_t *)p_context)->mbedtls_context; + + UNUSED_PARAMETER(p_temp_buffer); + + ret_val = nrf_drv_rng_init(NULL); + + if (ret_val != NRF_SUCCESS) + { + return ret_val; + } + + mbedtls_ctr_drbg_init(p_mbedtls_context); + + // Initial seeding. The nrf_crypto_rng API does not support additional entropy in the initial + // seeding. Additional entropy can be provided using nrf_crypto_rng_backend_reseed(), + // which calls mbedtls_ctr_drbg_reseed(). + mbedtls_ret_val = mbedtls_ctr_drbg_seed(p_mbedtls_context, + entropy_callback, + NULL, + NULL, + 0); + + ret_val = result_get(mbedtls_ret_val); + + return ret_val; +} + + +ret_code_t nrf_crypto_rng_backend_uninit(void * const p_context) +{ + mbedtls_ctr_drbg_context * p_mbedtls_context = + &((nrf_crypto_backend_rng_context_t *)p_context)->mbedtls_context; + + mbedtls_ctr_drbg_free(p_mbedtls_context); + nrf_drv_rng_uninit(); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_rng_backend_vector_generate(void * const p_context, + uint8_t * const p_target, + size_t size, + bool use_mutex) +{ + int mbedtls_ret_val; + mbedtls_ctr_drbg_context * p_mbedtls_context = + &((nrf_crypto_backend_rng_context_t *)p_context)->mbedtls_context; + + UNUSED_PARAMETER(use_mutex); + + mbedtls_ret_val = mbedtls_ctr_drbg_random(p_mbedtls_context, p_target, size); + + return result_get(mbedtls_ret_val); +} + + +ret_code_t nrf_crypto_rng_backend_reseed(void * const p_context, + void * p_temp_buffer, + uint8_t * p_input_data, + size_t size) +{ + int mbedtls_ret_val; + mbedtls_ctr_drbg_context * p_mbedtls_context = + &((nrf_crypto_backend_rng_context_t *)p_context)->mbedtls_context; + + UNUSED_PARAMETER(p_temp_buffer); + + mbedtls_ret_val = mbedtls_ctr_drbg_reseed(p_mbedtls_context, p_input_data, size); + + return result_get(mbedtls_ret_val); +} + +#endif //NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG) diff --git a/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_rng_mbedtls.h b/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_rng_mbedtls.h new file mode 100644 index 0000000..ae80a8d --- /dev/null +++ b/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_rng_mbedtls.h @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_HW_BACKEND_RNG_MBEDTLS_H__ +#define NRF_HW_BACKEND_RNG_MBEDTLS_H__ + +/** @file + * + * @defgroup nrf_crypto_nrf_hw_backend_rng_mbedtls nrf_crypto HW RNG backend using mbedtls CTR-DRBG + * @{ + * @ingroup nrf_crypto_nrf_hw_backend_rng + * + * @brief RNG functionality provided by the nrf_crypto nRF HW RNG backend and mbedtls CTR-DRBG. + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG) && \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG) + +#if !NRF_MODULE_ENABLED(RNG) +#error Enable RNG_ENABLED in sdk_config.h. +#endif + +#if !NRFX_RNG_CONFIG_ERROR_CORRECTION +#error Enable NRFX_RNG_CONFIG_ERROR_CORRECTION and RNG_CONFIG_ERROR_CORRECTION in sdk_config.h. +#endif + +/*lint -save -e????*/ +#include "mbedtls/ctr_drbg.h" +/*lint -restore*/ +#include "nrf_crypto_rng_shared.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) +#error "More than one RNG backend enabled." +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) +#define NRF_CRYPTO_RNG_ENABLED 1 + + +/** + * @internal @brief Context for nRF RNG peripheral with mbed tls CTR-DRBG. + */ +typedef struct +{ + nrf_crypto_rng_internal_context_t header; //!< Internal common context header. + mbedtls_ctr_drbg_context mbedtls_context; //!< mbed TLS CTR-DRBG context. +} nrf_crypto_backend_rng_context_t; + +/** + * @internal @brief Dummy temp buffer for nRF RNG peripheral with mbed tls CTR-DRBG. + */ +typedef struct +{ + uint32_t reserved; +} nrf_crypto_backend_rng_temp_buffer_t; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG) + +/**@} */ + +#endif // NRF_HW_BACKEND_RNG_MBEDTLS_H__ diff --git a/components/libraries/crypto/backend/nrf_sw/nrf_sw_backend_hash.c b/components/libraries/crypto/backend/nrf_sw/nrf_sw_backend_hash.c new file mode 100644 index 0000000..ac90316 --- /dev/null +++ b/components/libraries/crypto/backend/nrf_sw/nrf_sw_backend_hash.c @@ -0,0 +1,139 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_SW) + +#include "nrf_sw_backend_hash.h" +#include "sha256.h" +#include "nrf_crypto_types.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_hash_shared.h" +#include "sdk_macros.h" +#include "nrf_log.h" +#include "nrf_assert.h" + + + +#if defined(NRF_CRYPTO_BACKEND_NRF_SW_HASH_LITTLE_ENDIAN_DIGEST_ENABLED) + +#error The configuration NRF_CRYPTO_BACKEND_NRF_SW_HASH_LITTLE_ENDIAN_DIGEST_ENABLED was removed in SDK 15.1.0. Please see release notes for details on removing this error message. + +#endif + +static ret_code_t nrf_sw_backend_hash_sha256_init(void * const p_context) +{ + ret_code_t ret_val; + + // No parameter testing on this level. + // This has been done on upper level. + + sha256_context_t * p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t *) p_context)->context); + + ret_val = sha256_init(p_backend_context); + + return ret_val; +} + +static uint32_t nrf_sw_backend_hash_sha256_update(void * const p_context, + uint8_t const * p_data, + size_t len) +{ + ret_code_t ret_val; + + // Limited parameter testing on this level. + // This has been done on upper level. + + sha256_context_t * p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t * ) p_context)->context); + + ret_val = sha256_update(p_backend_context, p_data, len); + + return ret_val; +} + + +static uint32_t nrf_sw_backend_hash_sha256_finalize(void * const p_context, + uint8_t * p_digest, + size_t * const p_digest_len) +{ + ret_code_t ret_val; + + // Limited parameter testing on this level. + // This has been done on upper level. + + sha256_context_t * p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t * )p_context)->context); + + if (NRF_CRYPTO_HASH_SIZE_SHA256 > *p_digest_len) + { + return NRF_ERROR_CRYPTO_OUTPUT_LENGTH; + } + + + ret_val = sha256_final(p_backend_context, p_digest, false); + + if (ret_val != NRF_SUCCESS) + { + return ret_val; + } + + *p_digest_len = NRF_CRYPTO_HASH_SIZE_SHA256; + + return NRF_SUCCESS; + +} + + +const nrf_crypto_hash_info_t g_nrf_crypto_hash_sha256_info = +{ + .init_fn = nrf_sw_backend_hash_sha256_init, + .update_fn = nrf_sw_backend_hash_sha256_update, + .finalize_fn = nrf_sw_backend_hash_sha256_finalize, + .digest_size = NRF_CRYPTO_HASH_SIZE_SHA256, + .context_size = sizeof(nrf_crypto_backend_hash_sha256_context_t), + .hash_mode = NRF_CRYPTO_HASH_MODE_SHA256 +}; + + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_SW) diff --git a/components/libraries/crypto/backend/nrf_sw/nrf_sw_backend_hash.h b/components/libraries/crypto/backend/nrf_sw/nrf_sw_backend_hash.h new file mode 100644 index 0000000..fd7c711 --- /dev/null +++ b/components/libraries/crypto/backend/nrf_sw/nrf_sw_backend_hash.h @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_SW_BACKEND_HASH_H__ +#define NRF_SW_BACKEND_HASH_H__ + +/** @file + * + * @defgroup nrf_crypto_nrf_sw_backend_hash nrf_crypto nRF SW backend hash + * @{ + * @ingroup nrf_crypto_nrf_sw_backend + * + * @brief Legacy hash functionality for bootloader use in nRFx devices + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_SW) + +#include "sha256.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_types.h" +#include "nrf_crypto_hash_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_SW_HASH_SHA256) + +// Flag that nrf_crypto_hash frontend can be compiled +#undef NRF_CRYPTO_HASH_ENABLED +#define NRF_CRYPTO_HASH_ENABLED 1 + +// Duplicate backend enabled test for SHA-256 +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HASH_SHA256) +#error "Duplicate definition of SHA-256. More than one backend enabled"); +#endif + +// Flag that SHA-256 is enabled in backend +#define NRF_CRYPTO_HASH_SHA256_ENABLED 1 + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_SW_HASH_SHA256) + + +/**@brief nrf_crypto_hash context for SHA-256 in nrf_crypto nrf_sw backend. */ +typedef struct +{ + nrf_crypto_hash_internal_context_t header; /**< Common header for context. */ + sha256_context_t context; /**< Hash context internal to nrf_sw. */ +} nrf_crypto_backend_hash_sha256_context_t; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_NRF_SW) + +/**@} */ + +#endif // NRF_SW_BACKEND_HASH_H__ diff --git a/components/libraries/crypto/backend/oberon/oberon_backend_chacha_poly_aead.c b/components/libraries/crypto/backend/oberon/oberon_backend_chacha_poly_aead.c new file mode 100644 index 0000000..6cf55ca --- /dev/null +++ b/components/libraries/crypto/backend/oberon/oberon_backend_chacha_poly_aead.c @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include +#include "oberon_backend_chacha_poly_aead.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_OBERON_CHACHA_POLY_AEAD) + +static ret_code_t backend_cc310_init(void * const p_context, uint8_t * p_key) +{ + nrf_crypto_backend_chacha_poly_context_t * p_ctx = + (nrf_crypto_backend_chacha_poly_context_t *)p_context; + + + if (p_ctx->header.p_info->key_size != NRF_CRYPTO_KEY_SIZE_256) + { + return NRF_ERROR_CRYPTO_KEY_SIZE; + } + + memcpy(p_ctx->key, p_key, sizeof(p_ctx->key)); + + return NRF_SUCCESS; +} + +static inline ret_code_t backend_cc310_uninit(void * const p_context) +{ + return NRF_SUCCESS; +} + +static ret_code_t backend_cc310_crypt(void * const p_context, + nrf_crypto_operation_t operation, + uint8_t * p_nonce, + uint8_t nonce_size, + uint8_t * p_adata, + size_t adata_size, + uint8_t * p_data_in, + size_t data_in_size, + uint8_t * p_data_out, + uint8_t * p_mac, + uint8_t mac_size) + +{ + int result; + + nrf_crypto_backend_chacha_poly_context_t * p_ctx = + (nrf_crypto_backend_chacha_poly_context_t *)p_context; + + if ((adata_size == 0) || (data_in_size == 0)) + { + return NRF_ERROR_CRYPTO_INPUT_LENGTH; + } + + if (mac_size != NRF_CRYPTO_CHACHA_POLY_MAC_SIZE) + { + return NRF_ERROR_CRYPTO_AEAD_MAC_SIZE; + } + + if (nonce_size != NRF_CRYPTO_CHACHA_POLY_NONCE_SIZE) + { + return NRF_ERROR_CRYPTO_AEAD_NONCE_SIZE; + } + + if (operation == NRF_CRYPTO_ENCRYPT) + { + ocrypto_chacha20_poly1305_encrypt_aad(p_mac, + p_data_out, + p_data_in, + data_in_size, + p_adata, + adata_size, + p_nonce, + (size_t)nonce_size, + p_ctx->key); + } + else if (operation == NRF_CRYPTO_DECRYPT) + { + result = ocrypto_chacha20_poly1305_decrypt_aad(p_mac, + p_data_out, + p_data_in, + data_in_size, + p_adata, + adata_size, + p_nonce, + (size_t)nonce_size, + p_ctx->key); + + if (result != 0) + { + return NRF_ERROR_CRYPTO_AEAD_INVALID_MAC; + } + } + else + { + return NRF_ERROR_CRYPTO_INVALID_PARAM; + } + + return NRF_SUCCESS; +} + +nrf_crypto_aead_info_t const g_nrf_crypto_chacha_poly_256_info = +{ + .key_size = NRF_CRYPTO_KEY_SIZE_256, + .mode = NRF_CRYPTO_AEAD_MODE_CHACHA_POLY, + + .init_fn = backend_cc310_init, + .uninit_fn = backend_cc310_uninit, + .crypt_fn = backend_cc310_crypt +}; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_CC310_CHACHA_POLY_AEAD) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) + diff --git a/components/libraries/crypto/backend/oberon/oberon_backend_chacha_poly_aead.h b/components/libraries/crypto/backend/oberon/oberon_backend_chacha_poly_aead.h new file mode 100644 index 0000000..81ff072 --- /dev/null +++ b/components/libraries/crypto/backend/oberon/oberon_backend_chacha_poly_aead.h @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef OBERON_BACKEND_CHACHA_POLY_AEAD_H__ +#define OBERON_BACKEND_CHACHA_POLY_AEAD_H__ + +/** @file + * + * @defgroup nrf_crypto_oberon_backend_chacha_poly_aead nrf_crypto Oberon backend CHACHA_POLY AEAD + * @{ + * @ingroup nrf_crypto_oberon_backend + * + * @brief AES AEAD functionality provided by the nrf_crypto Oberon backend. + */ + +#include "sdk_config.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) + +#include "nrf_crypto_aead_shared.h" +#include "ocrypto_chacha20_poly1305.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_types.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_CRYPTO_OBERON_CHACHA_POLY_BACKEND_KEY_SIZE (32) + +/* CHACHA-POLY */ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_CHACHA_POLY) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_CHACHA_POLY) +#error "Duplicate definition of CHACHA-POLY mode. More than one backend enabled"); +#endif +#define NRF_CRYPTO_CHACHA_POLY_ENABLED 1 +#undef NRF_CRYPTO_AEAD_ENABLED +#define NRF_CRYPTO_AEAD_ENABLED 1 // Flag that nrf_crypto_aead frontend can be compiled +#undef NRF_CRYPTO_OBERON_CHACHA_POLY_AEAD_ENABLED +#define NRF_CRYPTO_OBERON_CHACHA_POLY_AEAD_ENABLED 1 // aead backend for Oberon can be compiled + +/* defines for test purposes */ +#define NRF_CRYPTO_AES_CHACHA_POLY_256_ENABLED 1 + +typedef struct +{ + nrf_crypto_aead_internal_context_t header; /**< Common header for context. */ + + uint8_t key[NRF_CRYPTO_OBERON_CHACHA_POLY_BACKEND_KEY_SIZE]; +} nrf_crypto_backend_chacha_poly_context_t; +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) + +/** @} */ + +#endif // OBERON_BACKEND_CHACHA_POLY_AEAD_H__ + diff --git a/components/libraries/crypto/backend/oberon/oberon_backend_ecc.c b/components/libraries/crypto/backend/oberon/oberon_backend_ecc.c new file mode 100644 index 0000000..de0cf25 --- /dev/null +++ b/components/libraries/crypto/backend/oberon/oberon_backend_ecc.c @@ -0,0 +1,464 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) + +#include +#include +#include + +#include "app_util.h" +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_mem.h" +#include "nrf_crypto_rng.h" +#include "nrf_crypto_shared.h" +#include "oberon_backend_ecc.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) +#include "ocrypto_ecdh_p256.h" +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) +#include "ocrypto_curve25519.h" +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519) +#include "ocrypto_ed25519.h" +#endif + + +/** @internal @brief Structure holding private key common to all curves implemented by the Oberon. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header. */ + uint8_t key[32]; /**< @internal @brief Raw key. */ +} nrf_crypto_backend_oberon_private_key_t; + + +/** @internal @brief Structure holding public key common to all curves implemented by the Oberon. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header. */ + uint8_t key[64]; /**< @internal @brief Raw key. */ +} nrf_crypto_backend_oberon_public_key_t; + + +/** @internal @brief Function to hold copy function (can be simple mem copy or copy with endian swap). + */ +typedef void (*copy_fn_t)(void * p_dest, void const * p_src, size_t size); + + +ret_code_t nrf_crypto_backend_oberon_private_key_to_raw( + void const * p_private_key, + uint8_t * p_raw_data) +{ + nrf_crypto_backend_oberon_private_key_t const * p_prv = + (nrf_crypto_backend_oberon_private_key_t const *)p_private_key; + + //lint -save -e611 (Suspicious cast) + copy_fn_t copy_fn = (copy_fn_t)p_prv->header.p_info->p_backend_data; + //lint -restore + + copy_fn(p_raw_data, p_prv->key, p_prv->header.p_info->raw_private_key_size); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_oberon_public_key_from_raw( + void * p_public_key, + uint8_t const * p_raw_data) +{ + nrf_crypto_backend_oberon_public_key_t * p_pub = + (nrf_crypto_backend_oberon_public_key_t *)p_public_key; + + //lint -save -e611 (Suspicious cast) + copy_fn_t copy_fn = (copy_fn_t)p_pub->header.p_info->p_backend_data; + //lint -restore + + copy_fn(p_pub->key, p_raw_data, p_pub->header.p_info->raw_public_key_size); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_oberon_public_key_to_raw( + void const * p_public_key, + uint8_t * p_raw_data) +{ + nrf_crypto_backend_oberon_public_key_t const * p_pub = + (nrf_crypto_backend_oberon_public_key_t const *)p_public_key; + + //lint -save -e611 (Suspicious cast) + copy_fn_t copy_fn = (copy_fn_t)p_pub->header.p_info->p_backend_data; + //lint -restore + + copy_fn(p_raw_data, p_pub->key, p_pub->header.p_info->raw_public_key_size); + + return NRF_SUCCESS; +} + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) \ + || NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) + + +ret_code_t nrf_crypto_backend_oberon_private_key_from_raw( + void * p_private_key, + uint8_t const * p_raw_data) +{ + nrf_crypto_backend_oberon_private_key_t * p_prv = + (nrf_crypto_backend_oberon_private_key_t *)p_private_key; + + //lint -save -e611 (Suspicious cast) + copy_fn_t copy_fn = (copy_fn_t)p_prv->header.p_info->p_backend_data; + //lint -restore + + copy_fn(p_prv->key, p_raw_data, p_prv->header.p_info->raw_private_key_size); + + return NRF_SUCCESS; +} + + +#endif //NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) || NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) \ + || NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519) + + +static ret_code_t oberon_vector_generate(uint8_t * p_data, size_t size) +{ +#if defined(NRF_CRYPTO_RNG_ENABLED) && (NRF_CRYPTO_RNG_ENABLED == 1) + + return nrf_crypto_rng_vector_generate(p_data, size); + +#elif defined(NRF_CRYPTO_RNG_ENABLED) && (NRF_CRYPTO_RNG_ENABLED == 0) + + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; + +#else + + #warning NRF_CRYPTO_RNG_ENABLED define not found in sdk_config.h (Is the sdk_config.h valid?). + +#endif +} + + +#endif //NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) || NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) + + +// Make sure that common key structure match secp256r1 key structure to safely cast types. +STATIC_ASSERT(offsetof(nrf_crypto_backend_oberon_private_key_t, key) == + offsetof(nrf_crypto_backend_secp256r1_private_key_t, key), + "Common Oberon private key structure does not match secp256r1 one."); +STATIC_ASSERT(offsetof(nrf_crypto_backend_oberon_public_key_t, key) == + offsetof(nrf_crypto_backend_secp256r1_public_key_t, key), + "Common Oberon public key structure does not match secp256r1 one."); + + +ret_code_t nrf_crypto_backend_oberon_ecc_secp256r1_rng(uint8_t data[32]) +{ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) + + static const uint8_t min_value[32] = + { + 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, 0x01, + }; + static const uint8_t max_value[32] = + { + 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, 0x50, + }; + return nrf_crypto_rng_vector_generate_in_range(data, min_value, max_value, 32); + +#else + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; +#endif +} + + +ret_code_t nrf_crypto_backend_secp256r1_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key) +{ + int result; + + nrf_crypto_backend_secp256r1_private_key_t * p_prv = + (nrf_crypto_backend_secp256r1_private_key_t *)p_private_key; + + nrf_crypto_backend_secp256r1_public_key_t * p_pub = + (nrf_crypto_backend_secp256r1_public_key_t *)p_public_key; + + result = nrf_crypto_backend_oberon_ecc_secp256r1_rng(p_prv->key); + + if (result != NRF_SUCCESS) + { + return result; + } + + result = ocrypto_ecdh_p256_public_key(p_pub->key, p_prv->key); + + if (result != 0) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_secp256r1_public_key_calculate( + void * p_context, + void const * p_private_key, + void * p_public_key) +{ + int result; + + nrf_crypto_backend_secp256r1_private_key_t const * p_prv = + (nrf_crypto_backend_secp256r1_private_key_t const *)p_private_key; + + nrf_crypto_backend_secp256r1_public_key_t * p_pub = + (nrf_crypto_backend_secp256r1_public_key_t *)p_public_key; + + result = ocrypto_ecdh_p256_public_key(p_pub->key, p_prv->key); + + if (result != 0) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + return NRF_SUCCESS; +} + + +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp256r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_secp256r1_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_secp256r1_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP256R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE, + //lint -save -e611 -e546 (Suspicious cast, Suspicious use of &) + .p_backend_data = (void *)&memcpy, + //lint -restore +}; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) + + +// Make sure that common key structure match Curve25519 key structure to safely cast types. +STATIC_ASSERT(offsetof(nrf_crypto_backend_oberon_private_key_t, key) == + offsetof(nrf_crypto_backend_curve25519_private_key_t, key), + "Common Oberon private key structure does not match Curve25519 one."); +STATIC_ASSERT(offsetof(nrf_crypto_backend_oberon_public_key_t, key) == + offsetof(nrf_crypto_backend_curve25519_public_key_t, key), + "Common Oberon public key structure does not match Curve25519 one."); + + +ret_code_t nrf_crypto_backend_curve25519_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key) +{ + ret_code_t result; + + nrf_crypto_backend_curve25519_private_key_t * p_prv = + (nrf_crypto_backend_curve25519_private_key_t *)p_private_key; + + nrf_crypto_backend_curve25519_public_key_t * p_pub = + (nrf_crypto_backend_curve25519_public_key_t *)p_public_key; + + result = oberon_vector_generate(p_prv->key, sizeof(p_prv->key)); + + if (result != NRF_SUCCESS) + { + return result; + } + + p_prv->key[0] &= 0xF8; // Private key is multiply of 8 (by definition), so lower 3 bits are 0. + p_prv->key[31] &= 0x7F; // Highest bit has to be 0, because private key is 255-bit long. + p_prv->key[31] |= 0x40; // Bit 254 has to be 1 (by definition) + + ocrypto_curve25519_scalarmult_base(p_pub->key, p_prv->key); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_curve25519_public_key_calculate( + void * p_context, + void const * p_private_key, + void * p_public_key) +{ + nrf_crypto_backend_curve25519_private_key_t * p_prv = + (nrf_crypto_backend_curve25519_private_key_t *)p_private_key; + + nrf_crypto_backend_curve25519_public_key_t * p_pub = + (nrf_crypto_backend_curve25519_public_key_t *)p_public_key; + + // Private key bit fixing is done inside Oberon library. + ocrypto_curve25519_scalarmult_base(p_pub->key, p_prv->key); + + return NRF_SUCCESS; +} + + +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_curve25519_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_curve25519_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_curve25519_private_key_t), + .curve_type = NRF_CRYPTO_ECC_CURVE25519_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_CURVE25519_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_CURVE25519_RAW_PUBLIC_KEY_SIZE, +#if NRF_MODULE_ENABLED(NRF_CRYPTO_CURVE25519_BIG_ENDIAN) + //lint -save -e611 -e546 (Suspicious cast, Suspicious use of &) + .p_backend_data = (void *)&nrf_crypto_internal_swap_endian, + //lint -restore +#else + //lint -save -e611 -e546 (Suspicious cast, Suspicious use of &) + .p_backend_data = (void *)&memcpy, + //lint -restore +#endif +}; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519) + + +// Make sure that common key structure match Ed25519 key structure to safely cast types. +STATIC_ASSERT(offsetof(nrf_crypto_backend_oberon_private_key_t, key) == + offsetof(nrf_crypto_backend_ed25519_private_key_t, private_part), + "Common Oberon private key structure does not match Ed25519 one."); +STATIC_ASSERT(offsetof(nrf_crypto_backend_oberon_public_key_t, key) == + offsetof(nrf_crypto_backend_ed25519_public_key_t, key), + "Common Oberon public key structure does not match Ed25519 one."); + + +ret_code_t nrf_crypto_backend_ed25519_private_key_from_raw( + void * p_private_key, + uint8_t const * p_raw_data) +{ + nrf_crypto_backend_ed25519_private_key_t * p_prv = + (nrf_crypto_backend_ed25519_private_key_t *)p_private_key; + + memcpy(p_prv->private_part, p_raw_data, sizeof(p_prv->private_part)); + + ocrypto_ed25519_public_key(p_prv->public_part, p_prv->private_part); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_ed25519_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key) +{ + ret_code_t result; + + nrf_crypto_backend_ed25519_private_key_t * p_prv = + (nrf_crypto_backend_ed25519_private_key_t *)p_private_key; + + nrf_crypto_backend_ed25519_public_key_t * p_pub = + (nrf_crypto_backend_ed25519_public_key_t *)p_public_key; + + result = oberon_vector_generate(p_prv->private_part, sizeof(p_prv->private_part)); + + if (result != NRF_SUCCESS) + { + return result; + } + + ocrypto_ed25519_public_key(p_prv->public_part, p_prv->private_part); + + memcpy(p_pub->key, p_prv->public_part, sizeof(p_pub->key)); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_ed25519_public_key_calculate( + void * p_context, + void const * p_private_key, + void * p_public_key) +{ + nrf_crypto_backend_ed25519_private_key_t * p_prv = + (nrf_crypto_backend_ed25519_private_key_t *)p_private_key; + + nrf_crypto_backend_ed25519_public_key_t * p_pub = + (nrf_crypto_backend_ed25519_public_key_t *)p_public_key; + + memcpy(p_pub->key, p_prv->public_part, sizeof(p_pub->key)); + + return NRF_SUCCESS; +} + + +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_ed25519_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_ed25519_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_ed25519_private_key_t), + .curve_type = NRF_CRYPTO_ECC_ED25519_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_ED25519_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_ED25519_RAW_PUBLIC_KEY_SIZE, + //lint -save -e611 -e546 (Suspicious cast, Suspicious use of &) + .p_backend_data = (void *)&memcpy, + //lint -restore +}; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519) + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) diff --git a/components/libraries/crypto/backend/oberon/oberon_backend_ecc.h b/components/libraries/crypto/backend/oberon/oberon_backend_ecc.h new file mode 100644 index 0000000..ff2cec3 --- /dev/null +++ b/components/libraries/crypto/backend/oberon/oberon_backend_ecc.h @@ -0,0 +1,314 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef OBERON_BACKEND_ECC_H__ +#define OBERON_BACKEND_ECC_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) + +#include +#include +#include "nrf_crypto_ecc_shared.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @internal See @ref nrf_crypto_backend_ecc_private_key_from_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_oberon_private_key_from_raw( + void * p_private_key, + uint8_t const * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_private_key_to_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_oberon_private_key_to_raw( + void const * p_private_key, + uint8_t * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_from_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_oberon_public_key_from_raw( + void * p_public_key, + uint8_t const * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_to_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_oberon_public_key_to_raw( + void const * p_public_key, + uint8_t * p_raw_data); + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP256R1) +#error "More than one backend enabled for secp256r1 (NIST 256-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP256R1_ENABLED 1 + + +/** @internal @brief Generates random number that can be used as a private key for secp256r1. + * + * It uses RNG from libary frontend to generate random numbers. + * + * @param[out] data Array where generated random number will be placed. + * @returns NRF_SUCCESS or error code passed from RNG frontend. + */ +ret_code_t nrf_crypto_backend_oberon_ecc_secp256r1_rng(uint8_t data[32]); + + +/** @internal @brief Structure holding private key for Oberon's secp256r1. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header. */ + uint8_t key[32]; /**< @internal @brief Raw key. */ +} nrf_crypto_backend_secp256r1_private_key_t; + + +/** @internal @brief Structure holding public key for Oberon's secp256r1. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header. */ + uint8_t key[64]; /**< @internal @brief Raw key. */ +} nrf_crypto_backend_secp256r1_public_key_t; + + +/** @internal See @ref nrf_crypto_backend_ecc_key_pair_generate_fn_t. + */ +ret_code_t nrf_crypto_backend_secp256r1_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_calculate_fn_t. +*/ +ret_code_t nrf_crypto_backend_secp256r1_public_key_calculate( + void * p_context, + void const * p_private_key, + void * p_public_key); + + +// Common key conversion functions +#define nrf_crypto_backend_secp256r1_private_key_from_raw \ + nrf_crypto_backend_oberon_private_key_from_raw +#define nrf_crypto_backend_secp256r1_private_key_to_raw \ + nrf_crypto_backend_oberon_private_key_to_raw +#define nrf_crypto_backend_secp256r1_public_key_from_raw \ + nrf_crypto_backend_oberon_public_key_from_raw +#define nrf_crypto_backend_secp256r1_public_key_to_raw \ + nrf_crypto_backend_oberon_public_key_to_raw + +// Free is not required for oberon keys +#define nrf_crypto_backend_secp256r1_private_key_free NULL +#define nrf_crypto_backend_secp256r1_public_key_free NULL + +// Context is not used in oberon functions +#define NRF_CRYPTO_BACKEND_SECP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp256r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp256r1_public_key_calculate_context_t; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_CURVE25519) +#error "More than one backend enabled for Curve25519."); +#endif +#define NRF_CRYPTO_ECC_CURVE25519_ENABLED 1 + + +/** @internal @brief Structure holding private key for Oberon's Curve25519. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header. */ + uint8_t key[32]; /**< @internal @brief Raw key in little endian order. */ +} nrf_crypto_backend_curve25519_private_key_t; + + +/** @internal @brief Structure holding public key for Oberon's Curve25519. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header. */ + uint8_t key[32]; /**< @internal @brief Raw key in little endian order. */ +} nrf_crypto_backend_curve25519_public_key_t; + + +/** @internal See @ref nrf_crypto_backend_ecc_key_pair_generate_fn_t. + */ +ret_code_t nrf_crypto_backend_curve25519_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_calculate_fn_t. +*/ +ret_code_t nrf_crypto_backend_curve25519_public_key_calculate( + void * p_context, + void const * p_private_key, + void * p_public_key); + + +// Common key conversion functions +#define nrf_crypto_backend_curve25519_private_key_from_raw \ + nrf_crypto_backend_oberon_private_key_from_raw +#define nrf_crypto_backend_curve25519_private_key_to_raw \ + nrf_crypto_backend_oberon_private_key_to_raw +#define nrf_crypto_backend_curve25519_public_key_from_raw \ + nrf_crypto_backend_oberon_public_key_from_raw +#define nrf_crypto_backend_curve25519_public_key_to_raw \ + nrf_crypto_backend_oberon_public_key_to_raw + +// Free is not required for oberon keys +#define nrf_crypto_backend_curve25519_private_key_free NULL +#define nrf_crypto_backend_curve25519_public_key_free NULL + +// Context is not used in oberon functions +#define NRF_CRYPTO_BACKEND_CURVE25519_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_CURVE25519_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_curve25519_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_curve25519_public_key_calculate_context_t; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_ED25519) +#error "More than one backend enabled for Ed25519."); +#endif +#define NRF_CRYPTO_ECC_ED25519_ENABLED 1 + + + +/** @internal @brief Structure holding private key for Oberon's Ed25519. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header. */ + uint8_t private_part[32]; /**< @internal @brief Raw private key. */ + uint8_t public_part[32]; /**< @internal @brief Raw public key. It is also required for Ed25519 signing. */ +} nrf_crypto_backend_ed25519_private_key_t; + + +/** @internal @brief Structure holding private key for Oberon's Ed25519. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header. */ + uint8_t key[32]; /**< @internal @brief Raw key. */ +} nrf_crypto_backend_ed25519_public_key_t; + + +/** @internal See @ref nrf_crypto_backend_ecc_private_key_from_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_ed25519_private_key_from_raw( + void * p_private_key, + uint8_t const * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_key_pair_generate_fn_t. + */ +ret_code_t nrf_crypto_backend_ed25519_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_calculate_fn_t. +*/ +ret_code_t nrf_crypto_backend_ed25519_public_key_calculate( + void * p_context, + void const * p_private_key, + void * p_public_key); + + +// Common key conversion functions +#define nrf_crypto_backend_ed25519_private_key_to_raw \ + nrf_crypto_backend_oberon_private_key_to_raw +#define nrf_crypto_backend_ed25519_public_key_from_raw \ + nrf_crypto_backend_oberon_public_key_from_raw +#define nrf_crypto_backend_ed25519_public_key_to_raw \ + nrf_crypto_backend_oberon_public_key_to_raw + +// Free is not required for oberon keys +#define nrf_crypto_backend_ed25519_private_key_free NULL +#define nrf_crypto_backend_ed25519_public_key_free NULL + +// Context is not used in oberon functions +#define NRF_CRYPTO_BACKEND_ED25519_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_ED25519_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 + +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_ed25519_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_ed25519_public_key_calculate_context_t; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) + +#endif // OBERON_BACKEND_ECC_H__ diff --git a/components/libraries/crypto/backend/oberon/oberon_backend_ecdh.c b/components/libraries/crypto/backend/oberon/oberon_backend_ecdh.c new file mode 100644 index 0000000..1ec968e --- /dev/null +++ b/components/libraries/crypto/backend/oberon/oberon_backend_ecdh.c @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) + +#include + +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdh.h" +#include "nrf_crypto_shared.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) +#include "ocrypto_ecdh_p256.h" +#endif +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) +#include "ocrypto_curve25519.h" +#endif + + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) + +ret_code_t nrf_crypto_backend_secp256r1_ecdh_compute( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret) +{ + int result; + + nrf_crypto_backend_secp256r1_private_key_t const * p_prv = + (nrf_crypto_backend_secp256r1_private_key_t const *)p_private_key; + + nrf_crypto_backend_secp256r1_public_key_t const * p_pub = + (nrf_crypto_backend_secp256r1_public_key_t const *)p_public_key; + + result = ocrypto_ecdh_p256_common_secret(p_shared_secret, p_prv->key, p_pub->key); + + if (result != 0) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + return NRF_SUCCESS; +} + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) + +ret_code_t nrf_crypto_backend_curve25519_ecdh_compute( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret) +{ + nrf_crypto_backend_curve25519_private_key_t const * p_prv = + (nrf_crypto_backend_curve25519_private_key_t const *)p_private_key; + + nrf_crypto_backend_curve25519_public_key_t const * p_pub = + (nrf_crypto_backend_curve25519_public_key_t const *)p_public_key; + + // Private key can be completely random at this point. + // Oberon library updates bits in the key according to Curve25519 specification before use. + ocrypto_curve25519_scalarmult(p_shared_secret, p_prv->key, p_pub->key); + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_CURVE25519_BIG_ENDIAN) + nrf_crypto_internal_swap_endian_in_place(p_shared_secret, + NRF_CRYPTO_ECDH_CURVE25519_SHARED_SECRET_SIZE); +#endif + + return NRF_SUCCESS; +} + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) diff --git a/components/libraries/crypto/backend/oberon/oberon_backend_ecdh.h b/components/libraries/crypto/backend/oberon/oberon_backend_ecdh.h new file mode 100644 index 0000000..63abbf0 --- /dev/null +++ b/components/libraries/crypto/backend/oberon/oberon_backend_ecdh.h @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef OBERON_BACKEND_ECDH_H__ +#define OBERON_BACKEND_ECDH_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) + +#include +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdh_shared.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) + + +/** @internal See @ref nrf_crypto_backend_ecdh_compute_fn_t. + */ +ret_code_t nrf_crypto_backend_secp256r1_ecdh_compute( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret); + +// Context in not used in OBERON backend +typedef uint32_t nrf_crypto_backend_secp256r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP256R1_ECDH_CONTEXT_SIZE 0 + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) + +/** @internal See @ref nrf_crypto_backend_ecdh_compute_fn_t. + */ +ret_code_t nrf_crypto_backend_curve25519_ecdh_compute( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret); + +// Context in not used in OBERON backend +typedef uint32_t nrf_crypto_backend_curve25519_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_CURVE25519_ECDH_CONTEXT_SIZE 0 + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519) + +// ECDH is not possible for Ed25519 +#define nrf_crypto_backend_ed25519_ecdh_compute NULL +typedef uint32_t nrf_crypto_backend_ed25519_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_ED25519_ECDH_CONTEXT_SIZE 0 + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) + +#endif // OBERON_BACKEND_ECDH_H__ diff --git a/components/libraries/crypto/backend/oberon/oberon_backend_ecdsa.c b/components/libraries/crypto/backend/oberon/oberon_backend_ecdsa.c new file mode 100644 index 0000000..acbf49d --- /dev/null +++ b/components/libraries/crypto/backend/oberon/oberon_backend_ecdsa.c @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) && \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) + +#include +#include +#include + +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_rng.h" +#include "nrf_crypto_ecdsa.h" +#include "oberon_backend_eddsa.h" +#include "nrf_crypto_eddsa_shared.h" +#include "ocrypto_ecdsa_p256.h" + + +#define OBERON_HASH_SIZE_FOR_SECP256R1 (256 / 8) + + +ret_code_t nrf_crypto_backend_secp256r1_sign( + void * p_context, + void const * p_private_key, + uint8_t const * p_data, + size_t data_size, + uint8_t * p_signature) +{ + int result; + uint8_t session_key[32]; + + nrf_crypto_backend_secp256r1_private_key_t const * p_prv = + (nrf_crypto_backend_secp256r1_private_key_t const *)p_private_key; + + if (data_size < OBERON_HASH_SIZE_FOR_SECP256R1) + { + return NRF_ERROR_CRYPTO_INPUT_LENGTH; + } + + result = nrf_crypto_backend_oberon_ecc_secp256r1_rng(session_key); + if (result != NRF_SUCCESS) + { + return result; + } + + result = ocrypto_ecdsa_p256_sign_hash(p_signature, p_data, p_prv->key, session_key); + + return result == 0 ? NRF_SUCCESS : NRF_ERROR_CRYPTO_INTERNAL; +} + + +ret_code_t nrf_crypto_backend_secp256r1_verify( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature) +{ + int result; + + nrf_crypto_backend_secp256r1_public_key_t const * p_pub = + (nrf_crypto_backend_secp256r1_public_key_t const *)p_public_key; + + if (data_size < OBERON_HASH_SIZE_FOR_SECP256R1) + { + return NRF_ERROR_CRYPTO_INPUT_LENGTH; + } + + result = ocrypto_ecdsa_p256_verify_hash(p_signature, p_data, p_pub->key); + + if (result != 0) + { + return NRF_ERROR_CRYPTO_ECDSA_INVALID_SIGNATURE; + } + return NRF_SUCCESS; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) diff --git a/components/libraries/crypto/backend/oberon/oberon_backend_ecdsa.h b/components/libraries/crypto/backend/oberon/oberon_backend_ecdsa.h new file mode 100644 index 0000000..9a04d4a --- /dev/null +++ b/components/libraries/crypto/backend/oberon/oberon_backend_ecdsa.h @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef OBERON_BACKEND_ECDSA_H__ +#define OBERON_BACKEND_ECDSA_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) + +#include +#include "nrf_crypto_ecc_shared.h" +#include "nrf_crypto_ecdsa_shared.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1) + + +/** @internal See @ref nrf_crypto_backend_ecdsa_sign_fn_t. + */ +ret_code_t nrf_crypto_backend_secp256r1_sign( + void * p_context, + void const * p_private_key, + uint8_t const * p_data, + size_t data_size, + uint8_t * p_signature); + + +/** @internal See @ref nrf_crypto_backend_ecdsa_verify_fn_t. + */ +ret_code_t nrf_crypto_backend_secp256r1_verify( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature); + + +#define NRF_CRYPTO_BACKEND_SECP256R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256R1_VERIFY_CONTEXT_SIZE 0 +typedef uint32_t nrf_crypto_backend_secp256r1_sign_context_t; +typedef uint32_t nrf_crypto_backend_secp256r1_verify_context_t; + +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519) + +// Curve25519 is not designed for ECDSA +#define NRF_CRYPTO_BACKEND_CURVE25519_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_CURVE25519_VERIFY_CONTEXT_SIZE 0 +typedef uint32_t nrf_crypto_backend_curve25519_sign_context_t; +typedef uint32_t nrf_crypto_backend_curve25519_verify_context_t; +#define nrf_crypto_backend_curve25519_sign NULL +#define nrf_crypto_backend_curve25519_verify NULL + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) + +#endif // OBERON_BACKEND_ECDSA_H__ diff --git a/components/libraries/crypto/backend/oberon/oberon_backend_eddsa.c b/components/libraries/crypto/backend/oberon/oberon_backend_eddsa.c new file mode 100644 index 0000000..1c99daf --- /dev/null +++ b/components/libraries/crypto/backend/oberon/oberon_backend_eddsa.c @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) && \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519) + +#include +#include +#include + +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_rng.h" +#include "nrf_crypto_eddsa.h" +#include "ocrypto_ed25519.h" + + +ret_code_t nrf_crypto_backend_ed25519_sign( + void * p_context, + nrf_crypto_ecc_private_key_t const * p_private_key, + uint8_t const * p_message, + size_t message_size, + uint8_t * p_signature) +{ + ocrypto_ed25519_sign(p_signature, + p_message, + message_size, + p_private_key->key_ed25519.private_part, + p_private_key->key_ed25519.public_part); + + return NRF_SUCCESS; +} + +ret_code_t nrf_crypto_backend_ed25519_verify( + void * p_context, + nrf_crypto_ecc_public_key_t const * p_public_key, + uint8_t const * p_message, + size_t message_size, + uint8_t const * p_signature) +{ + int result; + + result = ocrypto_ed25519_verify(p_signature, + p_message, + message_size, + p_public_key->key_ed25519.key); + + if (result != 0) + { + return NRF_ERROR_CRYPTO_ECDSA_INVALID_SIGNATURE; + } + + return NRF_SUCCESS; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519) diff --git a/components/libraries/crypto/backend/oberon/oberon_backend_eddsa.h b/components/libraries/crypto/backend/oberon/oberon_backend_eddsa.h new file mode 100644 index 0000000..db4ca4d --- /dev/null +++ b/components/libraries/crypto/backend/oberon/oberon_backend_eddsa.h @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef OBERON_BACKEND_EDDSA_H__ +#define OBERON_BACKEND_EDDSA_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) && \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519) + +#include +#include "nrf_crypto_ecc_shared.h" +#include "nrf_crypto_eddsa_shared.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_CRYPTO_BACKEND_ED25519_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_ED25519_VERIFY_CONTEXT_SIZE 0 +typedef uint32_t nrf_crypto_backend_ed25519_sign_context_t; +typedef uint32_t nrf_crypto_backend_ed25519_verify_context_t; + +#ifdef __cplusplus +} +#endif + + +#endif // #if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519) + +#endif // OBERON_BACKEND_EDDSA_H__ diff --git a/components/libraries/crypto/backend/oberon/oberon_backend_hash.c b/components/libraries/crypto/backend/oberon/oberon_backend_hash.c new file mode 100644 index 0000000..bd9f627 --- /dev/null +++ b/components/libraries/crypto/backend/oberon/oberon_backend_hash.c @@ -0,0 +1,182 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) + +#include "oberon_backend_hash.h" +#include "nrf_crypto_init.h" +#include "nrf_crypto_types.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_hash_shared.h" +#include "sdk_macros.h" +#include "ocrypto_sha256.h" +#include "ocrypto_sha512.h" +#include "nrf_log.h" +#include "nrf_assert.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HASH_SHA256) + +static ret_code_t oberon_backend_hash_sha256_init(void * const p_context) +{ + // No parameter testing on this level. + // This has been done on upper level. + + ocrypto_sha256_ctx * p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t *)p_context)->context); + + ocrypto_sha256_init(p_backend_context); + + return NRF_SUCCESS; +} + + +static uint32_t oberon_backend_hash_sha256_update(void * const p_context, + uint8_t const * p_data, + size_t size) +{ + // Limited parameter testing on this level. + // This has been done on upper level. + + ocrypto_sha256_ctx * p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t *)p_context)->context); + + ocrypto_sha256_update(p_backend_context, p_data, size); + + return NRF_SUCCESS; +} + + +static uint32_t oberon_backend_hash_sha256_finalize(void * const p_context, + uint8_t * p_digest, + size_t * const p_digest_size) +{ + // Limited parameter testing on this level. + // This has been done on upper level. + + ocrypto_sha256_ctx * p_backend_context + = &(((nrf_crypto_backend_hash_sha256_context_t *)p_context)->context); + + ocrypto_sha256_final(p_backend_context, p_digest); + + *p_digest_size = NRF_CRYPTO_HASH_SIZE_SHA256; + + return NRF_SUCCESS; +} + + +const nrf_crypto_hash_info_t g_nrf_crypto_hash_sha256_info = +{ + .init_fn = oberon_backend_hash_sha256_init, + .update_fn = oberon_backend_hash_sha256_update, + .finalize_fn = oberon_backend_hash_sha256_finalize, + .digest_size = NRF_CRYPTO_HASH_SIZE_SHA256, + .context_size = sizeof(nrf_crypto_backend_hash_sha256_context_t), + .hash_mode = NRF_CRYPTO_HASH_MODE_SHA256 +}; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HASH_SHA256) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HASH_SHA512) + + +static ret_code_t oberon_backend_hash_sha512_init(void * p_context) +{ + // No parameter testing on this level. + // This has been done on upper level. + + ocrypto_sha512_ctx * p_backend_context + = &(((nrf_crypto_backend_hash_sha512_context_t *)p_context)->context); + + ocrypto_sha512_init(p_backend_context); + + return NRF_SUCCESS; +} + + +static ret_code_t oberon_backend_hash_sha512_update(void * const p_context, + uint8_t const * p_data, + size_t size) +{ + // Limited parameter testing on this level. + // This has been done on upper level. + + ocrypto_sha512_ctx * p_backend_context + = &(((nrf_crypto_backend_hash_sha512_context_t *)p_context)->context); + + ocrypto_sha512_update(p_backend_context, p_data, size); + + return NRF_SUCCESS; +} + + +static ret_code_t oberon_backend_hash_sha512_finalize(void * const p_context, + uint8_t * p_digest, + size_t * const p_digest_size) +{ + // Limited parameter testing on this level. + // This has been done on upper level. + + ocrypto_sha512_ctx * p_backend_context + = &(((nrf_crypto_backend_hash_sha512_context_t *)p_context)->context); + + ocrypto_sha512_final(p_backend_context, p_digest); + + *p_digest_size = NRF_CRYPTO_HASH_SIZE_SHA512; + + return NRF_SUCCESS; +} + + +const nrf_crypto_hash_info_t g_nrf_crypto_hash_sha512_info = +{ + .init_fn = oberon_backend_hash_sha512_init, + .update_fn = oberon_backend_hash_sha512_update, + .finalize_fn = oberon_backend_hash_sha512_finalize, + .digest_size = NRF_CRYPTO_HASH_SIZE_SHA512, + .context_size = sizeof(nrf_crypto_backend_hash_sha512_context_t), + .hash_mode = NRF_CRYPTO_HASH_MODE_SHA512 +}; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HASH_SHA512) + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) diff --git a/components/libraries/crypto/backend/oberon/oberon_backend_hash.h b/components/libraries/crypto/backend/oberon/oberon_backend_hash.h new file mode 100644 index 0000000..b6b3545 --- /dev/null +++ b/components/libraries/crypto/backend/oberon/oberon_backend_hash.h @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef OBERON_BACKEND_HASH_H__ +#define OBERON_BACKEND_HASH_H__ + +/** @file + * + * @defgroup nrf_crypto_oberon_backend_hash Oberon backend hash + * @{ + * @ingroup nrf_crypto_oberon_backend + * + * @brief Hash functionality provided by the Oberon nrf_crypto backend. + */ +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) + +#include "sdk_errors.h" +#include "nrf_crypto_hash_shared.h" +#include "ocrypto_sha256.h" +#include "ocrypto_sha512.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HASH_SHA256) + +// Flag that nrf_crypto_hash frontend can be compiled +#undef NRF_CRYPTO_HASH_ENABLED +#define NRF_CRYPTO_HASH_ENABLED 1 + +// Duplicate backend enabled test for SHA-256 +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HASH_SHA256) +#error "Duplicate definition of SHA-256. More than one backend enabled"); +#endif + +// Flag that SHA-256 is enabled in backend +#define NRF_CRYPTO_HASH_SHA256_ENABLED 1 + + +/**@brief nrf_crypto_hash context for SHA-256 in nrf_crypto Oberon backend. */ +typedef struct +{ + nrf_crypto_hash_internal_context_t header; /**< Common header for context. */ + ocrypto_sha256_ctx context; /**< Hash context internal to Oberon. */ +} nrf_crypto_backend_hash_sha256_context_t; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HASH_SHA256) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HASH_SHA512) + +// Flag that nrf_crypto_hash frontend can be compiled +#undef NRF_CRYPTO_HASH_ENABLED +#define NRF_CRYPTO_HASH_ENABLED 1 + +// Duplicate backend enabled test for SHA-512 +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HASH_SHA512) +#error "Duplicate definition of SHA-512. More than one backend enabled"); +#endif + +// Flag that SHA-512 is enabled in backend +#define NRF_CRYPTO_HASH_SHA512_ENABLED 1 + + +/**@brief nrf_crypto_hash context for SHA-512 in nrf_crypto Oberon backend. */ +typedef struct +{ + nrf_crypto_hash_internal_context_t header; /**< Common header for context. */ + ocrypto_sha512_ctx context; /**< Hash context internal to Oberon. */ +} nrf_crypto_backend_hash_sha512_context_t; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HASH_SHA512) + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) + +/**@} */ + +#endif // OBERON_BACKEND_HASH_H__ diff --git a/components/libraries/crypto/backend/oberon/oberon_backend_hmac.c b/components/libraries/crypto/backend/oberon/oberon_backend_hmac.c new file mode 100644 index 0000000..2e8e0ad --- /dev/null +++ b/components/libraries/crypto/backend/oberon/oberon_backend_hmac.c @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) + +#include "nrf_log.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_types.h" +#include "oberon_backend_hmac.h" + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA256) + +#define HMAC_SHA256_BLOCK_SIZE 64 + +static ret_code_t oberon_backend_hmac_init_sha256(void * const p_context, + uint8_t const * p_key, + size_t key_size) +{ + nrf_crypto_backend_oberon_hmac_sha256_context_t * p_ctx = + (nrf_crypto_backend_oberon_hmac_sha256_context_t *)p_context; + + ocrypto_hmac_sha256_init(&p_ctx->oberon_ctx, p_key, key_size); + + return NRF_SUCCESS; +} + + +static ret_code_t oberon_backend_hmac_update_sha256(void * const p_context, + uint8_t const * p_data, + size_t size) +{ + nrf_crypto_backend_oberon_hmac_sha256_context_t * p_ctx = + (nrf_crypto_backend_oberon_hmac_sha256_context_t *)p_context; + + ocrypto_hmac_sha256_update(&p_ctx->oberon_ctx, p_data, size); + + return NRF_SUCCESS; +} + + +static ret_code_t oberon_backend_hmac_finalize_sha256(void * const p_context, + uint8_t * p_digest, + size_t * const p_size) +{ + nrf_crypto_backend_oberon_hmac_sha256_context_t * const p_ctx = + (nrf_crypto_backend_oberon_hmac_sha256_context_t *)p_context; + + ocrypto_hmac_sha256_final(&p_ctx->oberon_ctx, p_digest); + + // Assume operation was successful and update the digest size accordingly. + *p_size = p_ctx->header.p_info->digest_size; + + return NRF_SUCCESS; +} + + +// Information structure for HMAC SHA256 using Oberon backend. +const nrf_crypto_hmac_info_t g_nrf_crypto_hmac_sha256_info = +{ + .init_fn = oberon_backend_hmac_init_sha256, + .update_fn = oberon_backend_hmac_update_sha256, + .finalize_fn = oberon_backend_hmac_finalize_sha256, + .digest_size = NRF_CRYPTO_HASH_SIZE_SHA256, + .context_size = sizeof(nrf_crypto_backend_oberon_hmac_sha256_context_t), + .type = NRF_CRYPTO_HMAC_SHA256_TYPE +}; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA256) + + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA512) + +#define HMAC_SHA512_BLOCK_SIZE 128 + +static ret_code_t oberon_backend_hmac_init_sha512(void * const p_context, + uint8_t const * p_key, + size_t key_size) +{ + nrf_crypto_backend_oberon_hmac_sha512_context_t * p_ctx = + (nrf_crypto_backend_oberon_hmac_sha512_context_t *)p_context; + + ocrypto_hmac_sha512_init(&p_ctx->oberon_ctx, p_key, key_size); + + return NRF_SUCCESS; +} + + +static ret_code_t oberon_backend_hmac_update_sha512(void * const p_context, + uint8_t const * p_data, + size_t size) +{ + nrf_crypto_backend_oberon_hmac_sha512_context_t * p_ctx = + (nrf_crypto_backend_oberon_hmac_sha512_context_t *)p_context; + + ocrypto_hmac_sha512_update(&p_ctx->oberon_ctx, p_data, size); + + return NRF_SUCCESS; +} + + +static ret_code_t oberon_backend_hmac_finalize_sha512(void * const p_context, + uint8_t * p_digest, + size_t * const p_size) +{ + nrf_crypto_backend_oberon_hmac_sha512_context_t * const p_ctx = + (nrf_crypto_backend_oberon_hmac_sha512_context_t *)p_context; + + ocrypto_hmac_sha512_final(&p_ctx->oberon_ctx, p_digest); + + // Assume operation was successful and update the digest size accordingly. + *p_size = p_ctx->header.p_info->digest_size; + + return NRF_SUCCESS; +} + + +// Information structure for HMAC SHA512 using Oberon backend. +const nrf_crypto_hmac_info_t g_nrf_crypto_hmac_sha512_info = +{ + .init_fn = oberon_backend_hmac_init_sha512, + .update_fn = oberon_backend_hmac_update_sha512, + .finalize_fn = oberon_backend_hmac_finalize_sha512, + .digest_size = NRF_CRYPTO_HASH_SIZE_SHA512, + .context_size = sizeof(nrf_crypto_backend_oberon_hmac_sha512_context_t), + .type = NRF_CRYPTO_HMAC_SHA512_TYPE +}; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA512) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) diff --git a/components/libraries/crypto/backend/oberon/oberon_backend_hmac.h b/components/libraries/crypto/backend/oberon/oberon_backend_hmac.h new file mode 100644 index 0000000..4adb044 --- /dev/null +++ b/components/libraries/crypto/backend/oberon/oberon_backend_hmac.h @@ -0,0 +1,136 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef OBERON_BACKEND_HMAC_H__ +#define OBERON_BACKEND_HMAC_H__ + +/** @file + * + * @defgroup nrf_crypto_oberon_backend_hmac Oberon backend for HMAC + * @{ + * @ingroup nrf_crypto_oberon_backend + * + * @brief Backend wrapper for Oberon. None of these types should be used directly by the + * application. + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON) && \ + ( NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA256) || \ + NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA512) ) + +#include "nrf_crypto_hmac_shared.h" +#include "ocrypto_hmac_sha256.h" +#include "ocrypto_hmac_sha512.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#undef NRF_CRYPTO_HMAC_ENABLED +#define NRF_CRYPTO_HMAC_ENABLED 1 + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA256) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HMAC_SHA256) +#error "Duplicate definition of HMAC SHA-256. More than one backend enabled" +#endif // NRF_CRYPTO_HMAC_SHA256_ENABLED +#define NRF_CRYPTO_HMAC_SHA256_ENABLED 1 + +/** + * @internal @brief Internal context object used by the Oberon backend wrapper for HMAC SHA256. + * + * @note This should never be used directly. Use @ref nrf_crypto_backend_hmac_sha256_context_t + * instead. + */ +typedef struct +{ + nrf_crypto_hmac_internal_context_t header; //!< Internal nrf_crypto_hmac context. + ocrypto_hmac_sha256_ctx oberon_ctx; //!< Oberon context object. +} nrf_crypto_backend_oberon_hmac_sha256_context_t; + + +/** + * @internal @brief Context for HMAC SHA256 using Oberon backend. + */ +typedef nrf_crypto_backend_oberon_hmac_sha256_context_t nrf_crypto_backend_hmac_sha256_context_t; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA256) + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA512) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HMAC_SHA512) +#error "Duplicate definition of HMAC SHA-512. More than one backend enabled" +#endif // NRF_CRYPTO_HMAC_SHA512_ENABLED +#define NRF_CRYPTO_HMAC_SHA512_ENABLED 1 + +/** + * @internal @brief Internal context object used by the Oberon backend wrapper for HMAC SHA512. + * + * @note This should never be used directly. Use @ref nrf_crypto_backend_hmac_sha512_context_t + * instead. + */ +typedef struct +{ + nrf_crypto_hmac_internal_context_t header; //!< Internal nrf_crypto_hmac context header. + ocrypto_hmac_sha512_ctx oberon_ctx; //!< Oberon context object. +} nrf_crypto_backend_oberon_hmac_sha512_context_t; + +/** + * @internal @brief Context for HMAC SHA512 using Oberon backend. + */ +typedef nrf_crypto_backend_oberon_hmac_sha512_context_t nrf_crypto_backend_hmac_sha512_context_t; + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA512) + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON && ( NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA256 || NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA512) ) + +/**@} */ + +#endif // OBERON_BACKEND_HMAC_H__ diff --git a/components/libraries/crypto/backend/optiga/optiga_backend_ecc.c b/components/libraries/crypto/backend/optiga/optiga_backend_ecc.c new file mode 100644 index 0000000..55c1da6 --- /dev/null +++ b/components/libraries/crypto/backend/optiga/optiga_backend_ecc.c @@ -0,0 +1,305 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) + +#include +#include + +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdh.h" +#include "nrf_crypto_mem.h" +#include "nrf_crypto_rng.h" +#include "nrf_crypto_shared.h" +#include "nrf_assert.h" +#include "optiga_backend_ecc.h" + +/*lint -save -e????*/ +#include "optiga/optiga_crypt.h" +/*lint -restore*/ + +int nrf_crypto_backend_optiga_ecc_optiga_rng(void * p_param, unsigned char * p_data, size_t size) +{ +#if NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) + return NRF_SUCCESS; + +#else + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; +#endif +} + +static const uint8_t der_pub_key_header[] = { + 0x03, // ASN.1 BITSTRING + 0x42, // bytes following + 0x00, // no unused bits + 0x04 // uncompressed key, see https://tools.ietf.org/html/rfc5480#section-2.2 +}; + +#define DER_PUB_KEY_HEADER_LEN (sizeof(der_pub_key_header)/sizeof(der_pub_key_header[0])) + +// for our purposes we always have 1 byte tag + 1 byte length +#define DER_OCTET_STRING_HEADER_LEN 2 + +// lengths for the ASN.1 DER encoded keys imported and exported by OPTIGA +#define OPTIGA_SECP256R1_PRIV_KEY_LEN (DER_OCTET_STRING_HEADER_LEN + NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE) +#define OPTIGA_SECP256R1_PUBL_KEY_LEN (DER_PUB_KEY_HEADER_LEN + NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE) + +ret_code_t nrf_crypto_backend_optiga_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key) +{ + optiga_lib_status_t res = OPTIGA_LIB_ERROR; + + nrf_crypto_backend_secp256r1_public_key_t * p_pub = + (nrf_crypto_backend_secp256r1_public_key_t *) p_public_key; + + nrf_crypto_backend_secp256r1_private_key_t * p_priv = + (nrf_crypto_backend_secp256r1_private_key_t *) p_private_key; + + bool export_private_key; + if (p_priv->oid == 0) + { + // OID=0 was implicitly specified when initializising, mostly due to Nordic internal code calling our API + p_priv->oid = (optiga_key_id_t)0xE100; + export_private_key = false; + } + else if (p_priv->oid == NRF_CRYPTO_INFINEON_PRIVKEY_HOST_OID) + { + export_private_key = true; + } + else // any other value for OID, we assume the OID was purposefully specified by caller + { + export_private_key = false; + } + + void * priv_key; + if (export_private_key) + { + //lint -save -e611 -e545 (Suspicious cast, Suspicious use of &) + priv_key = (void*) &p_priv->raw_privkey; + //lint -restore + p_priv->oid = (optiga_key_id_t)NRF_CRYPTO_INFINEON_PRIVKEY_HOST_OID; + } + else + { + //lint -save -e611 -e545 (Suspicious cast, Suspicious use of &) + priv_key = (void*) &p_priv->oid; + + memset(p_priv->raw_privkey, 0, OPTIGA_SECP256R1_PRIV_KEY_LEN); + //lint -restore + } + + // Set all flags because the nrf_crypto API does not allow to specify key use + const optiga_key_usage_t key_usage = (optiga_key_usage_t)(OPTIGA_KEY_USAGE_AUTHENTICATION | + OPTIGA_KEY_USAGE_SIGN | + OPTIGA_KEY_USAGE_KEY_AGREEMENT); + + uint16_t publ_key_len = OPTIGA_SECP256R1_PUBL_KEY_LEN; + res = optiga_crypt_ecc_generate_keypair(OPTIGA_ECC_NIST_P_256, + key_usage, + export_private_key, + priv_key, + p_pub->raw_pubkey, + &publ_key_len); + + if(res != OPTIGA_LIB_SUCCESS) + { + // error in the optiga library + return NRF_ERROR_CRYPTO_INTERNAL; + } + + if(publ_key_len != OPTIGA_SECP256R1_PUBL_KEY_LEN) + { + // unexpected length + return NRF_ERROR_CRYPTO_INTERNAL; + } + + // mark the public key as stored in host memory + p_pub->oid = (optiga_key_id_t)NRF_CRYPTO_INFINEON_PUBKEY_HOST_OID; + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_backend_optiga_public_key_calculate( + void * p_context, + void const * p_private_key, + void * p_public_key) +{ + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; +} + + +ret_code_t nrf_crypto_backend_optiga_private_key_from_raw( + void * p_private_key, + uint8_t const * p_raw_data) +{ + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; +} + +#define DER_TAG_OCTET_STRING 0x04 + +ret_code_t nrf_crypto_backend_optiga_private_key_to_raw( + void const * p_private_key, + uint8_t * p_raw_data) +{ + nrf_crypto_backend_secp256r1_private_key_t * p_priv = + (nrf_crypto_backend_secp256r1_private_key_t *)p_private_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_priv->header.p_info; + + if(p_priv->oid != NRF_CRYPTO_INFINEON_PRIVKEY_HOST_OID) + { + // must use magic OID for private key exported to host + return NRF_ERROR_CRYPTO_INTERNAL; + } + + uint8_t* p_key = p_priv->raw_privkey; + if(*p_key != DER_TAG_OCTET_STRING) + { + // private key must be encoded as DER OCTET STRING + return NRF_ERROR_CRYPTO_INTERNAL; + } + + p_key++; + + if(p_info == &g_nrf_crypto_ecc_secp256r1_curve_info) + { + if(*p_key != NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE) + { + // wrong length + return NRF_ERROR_CRYPTO_INTERNAL; + } + p_key++; + + memcpy(p_raw_data, p_key, NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE); + + return NRF_SUCCESS; + } + + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; +} + +ret_code_t nrf_crypto_backend_optiga_public_key_from_raw( + void * p_public_key, + uint8_t const * p_raw_data) +{ + nrf_crypto_backend_secp256r1_public_key_t * p_pub = + (nrf_crypto_backend_secp256r1_public_key_t *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info; + + if (p_info == &g_nrf_crypto_ecc_secp256r1_curve_info) + { + // copy header + memcpy(p_pub->raw_pubkey, der_pub_key_header, DER_PUB_KEY_HEADER_LEN); + // copy public key data + memcpy(p_pub->raw_pubkey + DER_PUB_KEY_HEADER_LEN, p_raw_data, NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE); + // Set OID to magic number for host-supplied public key + p_pub->oid = (optiga_key_id_t)NRF_CRYPTO_INFINEON_PUBKEY_HOST_OID; + + return NRF_SUCCESS; + } + + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; +} + + +ret_code_t nrf_crypto_backend_optiga_public_key_to_raw( + void const * p_public_key, + uint8_t * p_raw_data) +{ + nrf_crypto_backend_secp256r1_public_key_t * p_pub = + (nrf_crypto_backend_secp256r1_public_key_t *)p_public_key; + + nrf_crypto_ecc_curve_info_t const * p_info = p_pub->header.p_info; + + if(p_pub->oid != NRF_CRYPTO_INFINEON_PUBKEY_HOST_OID) + { + // must use magic OID for host supplied public key + return NRF_ERROR_CRYPTO_INTERNAL; + } + + if (p_info == &g_nrf_crypto_ecc_secp256r1_curve_info) + { + if(memcmp(p_pub->raw_pubkey, der_pub_key_header, DER_PUB_KEY_HEADER_LEN) != 0) { + // public key not correctly encoded + return NRF_ERROR_CRYPTO_INTERNAL; + } + + memcpy(p_raw_data, + p_pub->raw_pubkey + DER_PUB_KEY_HEADER_LEN, + NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE); + + return NRF_SUCCESS; + } + + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; +} + + +ret_code_t nrf_crypto_backend_optiga_private_key_free( + void * p_private_key) +{ + return NRF_ERROR_CRYPTO_INTERNAL; +} + +ret_code_t nrf_crypto_backend_optiga_public_key_free( + void * p_public_key) +{ + return NRF_ERROR_CRYPTO_INTERNAL; +} + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA_ECC_SECP256R1) +const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp256r1_curve_info = +{ + .public_key_size = sizeof(nrf_crypto_backend_secp256r1_public_key_t), + .private_key_size = sizeof(nrf_crypto_backend_optiga_ecc_private_key_t), + .curve_type = NRF_CRYPTO_ECC_SECP256R1_CURVE_TYPE, + .raw_private_key_size = NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE, + .raw_public_key_size = NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE, + .p_backend_data = (void *)OPTIGA_ECC_NIST_P_256, +}; +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) diff --git a/components/libraries/crypto/backend/optiga/optiga_backend_ecc.h b/components/libraries/crypto/backend/optiga/optiga_backend_ecc.h new file mode 100644 index 0000000..67a383d --- /dev/null +++ b/components/libraries/crypto/backend/optiga/optiga_backend_ecc.h @@ -0,0 +1,200 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef OPTIGA_BACKEND_ECC_H__ +#define OPTIGA_BACKEND_ECC_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) + +#include +#include +#include "nrf_crypto_ecc.h" + +/*lint -save -e????*/ +#include "optiga/optiga_crypt.h" +/*lint -restore*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** @internal Magic OID that indicates a host supplied public key +*/ +#define NRF_CRYPTO_INFINEON_PUBKEY_HOST_OID 0xFFFF + +/** @internal Magic OID that indicates to export the private key +*/ +#define NRF_CRYPTO_INFINEON_PRIVKEY_HOST_OID 0xFFFE + +/** @internal @brief Common structure holding private key for the OPTIGA backend. + */ +typedef struct nrf_crypto_backend_optiga_ecc_private_key_t +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + optiga_key_id_t oid; // OID where the private key is stored + uint8_t raw_privkey[64+2]; // Private Key encoded as DER OCTET STRING +} nrf_crypto_backend_optiga_ecc_private_key_t; + +#define NRF_CRYPTO_INFINEON_SECP256R1_PRIVATE_KEY_FROM_OID(oid_value) { \ + .key_secp256r1 = { \ + .header = { \ + .init_value = NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE, \ + .p_info = &g_nrf_crypto_ecc_secp256r1_curve_info \ + }, \ + .oid = (optiga_key_id_t)(oid_value) \ + } \ +} + +/** @internal @brief Common structure holding public key for the OPTIGA backend. + */ +typedef struct +{ + nrf_crypto_internal_ecc_key_header_t header; /**< @internal @brief Common ECC key header */ + optiga_key_id_t oid; // OID where the public key is stored + uint8_t raw_pubkey[64+4]; // Public Key encoded as DER BITSTRING with header +} nrf_crypto_backend_secp256r1_public_key_t; + +#define NRF_CRYPTO_INFINEON_SECP256R1_PUBLIC_KEY_FROM_OID(oid_value) { \ + .key_secp256r1 = { \ + .header = { \ + .init_value = NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE, \ + .p_info = &g_nrf_crypto_ecc_secp256r1_curve_info \ + }, \ + .oid = (optiga_key_id_t)(oid_value) \ + } \ +} + +#define NRF_CRYPTO_INFINEON_SECP256R1_PUBLIC_KEY_RAW \ + NRF_CRYPTO_INFINEON_SECP256R1_PUBLIC_KEY_FROM_OID(NRF_CRYPTO_INFINEON_PUBKEY_HOST_OID) + + +/** @internal See @ref nrf_crypto_backend_ecc_key_pair_generate_fn_t. + */ +ret_code_t nrf_crypto_backend_optiga_key_pair_generate( + void * p_context, + void * p_private_key, + void * p_public_key); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_calculate_fn_t. +*/ +ret_code_t nrf_crypto_backend_optiga_public_key_calculate( + void * p_context, + void const * p_private_key, + void * p_public_key); + + +/** @internal See @ref nrf_crypto_backend_ecc_private_key_from_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_optiga_private_key_from_raw( + void * p_private_key, + uint8_t const * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_private_key_to_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_optiga_private_key_to_raw( + void const * p_private_key, + uint8_t * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_from_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_optiga_public_key_from_raw( + void * p_public_key, + uint8_t const * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_public_key_to_raw_fn_t. +*/ +ret_code_t nrf_crypto_backend_optiga_public_key_to_raw( + void const * p_public_key, + uint8_t * p_raw_data); + + +/** @internal See @ref nrf_crypto_backend_ecc_key_free_fn_t. +*/ +ret_code_t nrf_crypto_backend_optiga_private_key_free( + void * p_private_key); + + +/** @internal See @ref nrf_crypto_backend_ecc_key_free_fn_t. +*/ +ret_code_t nrf_crypto_backend_optiga_public_key_free( + void * p_public_key); + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA_ECC_SECP256R1) + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_ECC_SECP256R1) +#error "More than one backend enabled for secp256r1 (NIST 256-bit)."); +#endif +#define NRF_CRYPTO_ECC_SECP256R1_ENABLED 1 + +// Aliases for one common OPTIGA implementation +#define nrf_crypto_backend_secp256r1_key_pair_generate nrf_crypto_backend_optiga_key_pair_generate +#define nrf_crypto_backend_secp256r1_public_key_calculate nrf_crypto_backend_optiga_public_key_calculate +#define nrf_crypto_backend_secp256r1_private_key_from_raw nrf_crypto_backend_optiga_private_key_from_raw +#define nrf_crypto_backend_secp256r1_private_key_to_raw nrf_crypto_backend_optiga_private_key_to_raw +#define nrf_crypto_backend_secp256r1_public_key_from_raw nrf_crypto_backend_optiga_public_key_from_raw +#define nrf_crypto_backend_secp256r1_public_key_to_raw nrf_crypto_backend_optiga_public_key_to_raw +#define nrf_crypto_backend_secp256r1_private_key_free nrf_crypto_backend_optiga_private_key_free +#define nrf_crypto_backend_secp256r1_public_key_free nrf_crypto_backend_optiga_public_key_free +// OPTIGA does not require context, so its size is 0. +#define NRF_CRYPTO_BACKEND_SECP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE 0 +// All OPTIGA curve types share the same private key data structures +typedef nrf_crypto_backend_optiga_ecc_private_key_t nrf_crypto_backend_secp256r1_private_key_t; +// Dummy typedef for unused context +typedef uint32_t nrf_crypto_backend_secp256r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp256r1_public_key_calculate_context_t; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA_ECC_SECP256R1) + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) + +#endif // OPTIGA_BACKEND_ECC_H__ diff --git a/components/libraries/crypto/backend/optiga/optiga_backend_ecdh.c b/components/libraries/crypto/backend/optiga/optiga_backend_ecdh.c new file mode 100644 index 0000000..9ee6cae --- /dev/null +++ b/components/libraries/crypto/backend/optiga/optiga_backend_ecdh.c @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) + +#include + +#include "nrf_crypto_ecc_shared.h" +#include "nrf_crypto_ecdh_shared.h" +#include "nrf_crypto_shared.h" +#include "nrf_crypto_ecdh.h" +#include "optiga_backend_ecc.h" + +/*lint -save -e????*/ +#include "optiga/optiga_crypt.h" +/*lint -restore*/ + + +ret_code_t nrf_crypto_backend_optiga_ecdh_compute( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret) +{ + optiga_lib_status_t res = OPTIGA_LIB_ERROR; + + // Prepare public key + nrf_crypto_backend_secp256r1_public_key_t * p_pub = + (nrf_crypto_backend_secp256r1_public_key_t *) p_public_key; + if (p_pub->oid != NRF_CRYPTO_INFINEON_PUBKEY_HOST_OID) + { + // OPTIGA requires the peer' public key to be host-supplied + return NRF_ERROR_CRYPTO_INTERNAL; + } + // magic OID for pubkey from host + public_key_from_host_t pub_key = { + .public_key = p_pub->raw_pubkey, + .length = 64+4, // public key + DER BITSTRING header + .curve = OPTIGA_ECC_NIST_P_256 + }; + + // Prepare private key + nrf_crypto_backend_secp256r1_private_key_t * p_priv = + (nrf_crypto_backend_secp256r1_private_key_t *) p_private_key; + optiga_key_id_t priv_oid = p_priv->oid; + if (priv_oid == NRF_CRYPTO_INFINEON_PRIVKEY_HOST_OID) + { + // OPTIGA Trust X can only compute ECDH with private key from inside OPTIGA + return NRF_ERROR_CRYPTO_INTERNAL; + } + + res = optiga_crypt_ecdh( + priv_oid, // private key OID + &pub_key, // peer public key details + true, // true: export shared secret to host + p_shared_secret // resulting shared secret + ); + + if (res != OPTIGA_LIB_SUCCESS) + { + // error in the optiga library + return NRF_ERROR_CRYPTO_INTERNAL; + } + + return NRF_SUCCESS; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) + diff --git a/components/libraries/crypto/backend/optiga/optiga_backend_ecdh.h b/components/libraries/crypto/backend/optiga/optiga_backend_ecdh.h new file mode 100644 index 0000000..e477a46 --- /dev/null +++ b/components/libraries/crypto/backend/optiga/optiga_backend_ecdh.h @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef OPTIGA_BACKEND_ECDH_H__ +#define OPTIGA_BACKEND_ECDH_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) + +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdh_shared.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +// This file is only needed to satisfy the nrf_crypto interface + + +/** @internal See @ref nrf_crypto_backend_ecdh_compute_fn_t. + */ +ret_code_t nrf_crypto_backend_optiga_ecdh_compute( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret); + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA_ECC_SECP256R1) +// Aliases for one common OPTIGA implementation +#define nrf_crypto_backend_secp256r1_ecdh_compute nrf_crypto_backend_optiga_ecdh_compute +typedef uint32_t nrf_crypto_backend_secp256r1_ecdh_context_t; +#define NRF_CRYPTO_BACKEND_SECP256R1_ECDH_CONTEXT_SIZE 0 +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA_ECC_SECP256R1) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) + +#endif // OPTIGA_BACKEND_ECDH_H__ diff --git a/components/libraries/crypto/backend/optiga/optiga_backend_ecdsa.c b/components/libraries/crypto/backend/optiga/optiga_backend_ecdsa.c new file mode 100644 index 0000000..d3027b4 --- /dev/null +++ b/components/libraries/crypto/backend/optiga/optiga_backend_ecdsa.c @@ -0,0 +1,155 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) + +#include +#include +#include + +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdsa.h" + +/*lint -save -e????*/ +#include "optiga/optiga_crypt.h" +#include "ecdsa_utils.h" +/*lint -restore*/ + +ret_code_t nrf_crypto_backend_optiga_sign( + void * p_context, + void const * p_private_key, + uint8_t const * p_data, + size_t data_size, + uint8_t * p_signature) +{ + optiga_lib_status_t res = OPTIGA_LIB_ERROR; + nrf_crypto_backend_optiga_ecc_private_key_t * p_prv = + (nrf_crypto_backend_optiga_ecc_private_key_t *)p_private_key; + + optiga_key_id_t oid = p_prv->oid; + + uint16_t der_sig_len = NRF_CRYPTO_ECDSA_SECP256R1_SIGNATURE_SIZE + ECDSA_RS_MAX_ASN1_OVERHEAD; + uint8_t der_sig[NRF_CRYPTO_ECDSA_SECP256R1_SIGNATURE_SIZE + ECDSA_RS_MAX_ASN1_OVERHEAD] = {0}; + + res = optiga_crypt_ecdsa_sign((uint8_t *)p_data, data_size, oid, der_sig, &der_sig_len); + if(res != OPTIGA_LIB_SUCCESS) { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + // convert signature to format suitable for nrf_crypto + if (!asn1_to_ecdsa_rs(der_sig, der_sig_len, + p_signature, NRF_CRYPTO_ECDSA_SECP256R1_SIGNATURE_SIZE)) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + return NRF_SUCCESS; +} + +ret_code_t nrf_crypto_backend_optiga_verify( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature) +{ + nrf_crypto_backend_secp256r1_public_key_t * p_pub = + (nrf_crypto_backend_secp256r1_public_key_t *)p_public_key; + + optiga_key_id_t oid = p_pub->oid; + + size_t der_sig_len = NRF_CRYPTO_ECDSA_SECP256R1_SIGNATURE_SIZE + ECDSA_RS_MAX_ASN1_OVERHEAD; + uint8_t der_sig[NRF_CRYPTO_ECDSA_SECP256R1_SIGNATURE_SIZE + ECDSA_RS_MAX_ASN1_OVERHEAD] = {0}; + + const size_t rs_size = NRF_CRYPTO_ECDSA_SECP256R1_SIGNATURE_SIZE/2; + + optiga_lib_status_t res = OPTIGA_LIB_ERROR; + + // Convert signature to DER format needed by OPTIGA + if (!ecdsa_rs_to_asn1_integers(p_signature, + p_signature + rs_size, + rs_size, + der_sig, + &der_sig_len)) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + if (oid == NRF_CRYPTO_INFINEON_PUBKEY_HOST_OID) + { + // Create magic OID for pubkey from host + public_key_from_host_t pub_key = { + .public_key = p_pub->raw_pubkey, + .length = NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE + 4, // public key + DER BITSTRING header + .curve = OPTIGA_ECC_NIST_P_256 + }; + + res = optiga_crypt_ecdsa_verify((uint8_t *)p_data, + data_size, + der_sig, + der_sig_len, + OPTIGA_CRYPT_HOST_DATA, + &pub_key); + } + else + { + // Public key is in OPTIGA, referenced by OID + res = optiga_crypt_ecdsa_verify((uint8_t *)p_data, + data_size, + der_sig, + der_sig_len, + OPTIGA_CRYPT_OID_DATA, + &oid); + } + + // consider everything that is not success a signature failure + if (res != OPTIGA_LIB_SUCCESS) + { + return NRF_ERROR_CRYPTO_ECDSA_INVALID_SIGNATURE; + } + + return NRF_SUCCESS; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) diff --git a/components/libraries/crypto/backend/optiga/optiga_backend_ecdsa.h b/components/libraries/crypto/backend/optiga/optiga_backend_ecdsa.h new file mode 100644 index 0000000..fb32147 --- /dev/null +++ b/components/libraries/crypto/backend/optiga/optiga_backend_ecdsa.h @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef OPTIGA_BACKEND_ECDSA_H__ +#define OPTIGA_BACKEND_ECDSA_H__ + +#include "sdk_config.h" +#include "nordic_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) + +#include +#include "nrf_crypto_ecc_shared.h" +#include "nrf_crypto_ecdsa_shared.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA_ECC_SECP256R1) + + +/** @internal See @ref nrf_crypto_backend_ecdsa_sign_fn_t. + */ +ret_code_t nrf_crypto_backend_optiga_sign( + void * p_context, + void const * p_private_key, + uint8_t const * p_data, + size_t data_size, + uint8_t * p_signature); + + +/** @internal See @ref nrf_crypto_backend_ecdsa_verify_fn_t. + */ +ret_code_t nrf_crypto_backend_optiga_verify( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature); + + +// Context is not used by OPTIGA, so its size is 0 +#define NRF_CRYPTO_BACKEND_SECP256R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for unused contexts +typedef uint32_t nrf_crypto_backend_secp256r1_sign_context_t; +typedef uint32_t nrf_crypto_backend_secp256r1_verify_context_t; +// Alias for common OPTIGA types +#define nrf_crypto_backend_secp256r1_sign nrf_crypto_backend_optiga_sign +#define nrf_crypto_backend_secp256r1_verify nrf_crypto_backend_optiga_verify +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) + +#endif // OPTIGA_BACKEND_ECDSA_H__ diff --git a/components/libraries/crypto/backend/optiga/optiga_backend_init.c b/components/libraries/crypto/backend/optiga/optiga_backend_init.c new file mode 100644 index 0000000..177bb23 --- /dev/null +++ b/components/libraries/crypto/backend/optiga/optiga_backend_init.c @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#include "sdk_config.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) + +#include "nrf_crypto_init.h" +#include "nrf_crypto_rng.h" +#include "nrf_log.h" + +/*lint -save -e????*/ +#include "optiga/optiga_util.h" +#include "optiga/ifx_i2c/ifx_i2c.h" +/*lint -restore*/ + +optiga_comms_t optiga_comms = {(void*)&ifx_i2c_context_0, NULL, NULL}; + +// need to forward declare these, because they are not exported through the PAL API +void pal_gpio_init(void); +void pal_os_event_init(void); + +/************************************************************************* +* functions +*************************************************************************/ + +static int32_t optiga_init(void) +{ + int32_t status = (int32_t) OPTIGA_LIB_ERROR; + + // Initialize PAL + pal_gpio_init(); + pal_os_event_init(); + + status = optiga_util_open_application(&optiga_comms); + if (OPTIGA_LIB_SUCCESS != status) + { + NRF_LOG_INFO("Failure: CmdLib_OpenApplication(): 0x%04X", status); + return status; + } + + NRF_LOG_INFO("Success: CmdLib_OpenApplication(): 0x%04X", status); + + return OPTIGA_LIB_SUCCESS; +} + +/** @internal @brief Function to initialize OPTIGA backend - open the application. + */ +static ret_code_t optiga_backend_init(void) +{ + if(optiga_init() != OPTIGA_LIB_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + +#if defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 1) + + ret_code_t ret_val; + ret_val = nrf_crypto_rng_init(NULL, NULL); + return ret_val; + +#elif defined(NRF_CRYPTO_RNG_AUTO_INIT_ENABLED) && (NRF_CRYPTO_RNG_AUTO_INIT_ENABLED == 0) + + return NRF_SUCCESS; + +#else + + #warning NRF_CRYPTO_RNG_AUTO_INIT_ENABLED define not found in sdk_config.h (Is the sdk_config.h valid?). + +#endif // NRF_CRYPTO_RNG_AUTO_INIT_ENABLED + +} + + +/** @internal @brief Function to uninitialize OPTIGA backend - currently no implementation is required. + */ +static ret_code_t optiga_backend_uninit(void) +{ + // Empty implementation + return NRF_SUCCESS; +} + + +CRYPTO_BACKEND_REGISTER(nrf_crypto_backend_info_t const optiga_backend) = +{ + .init_fn = optiga_backend_init, + .uninit_fn = optiga_backend_uninit, +}; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) && NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) diff --git a/components/libraries/crypto/backend/optiga/optiga_backend_rng.c b/components/libraries/crypto/backend/optiga/optiga_backend_rng.c new file mode 100644 index 0000000..ed2c654 --- /dev/null +++ b/components/libraries/crypto/backend/optiga/optiga_backend_rng.c @@ -0,0 +1,147 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA_RNG) + +#include "nrf_crypto_rng.h" +#include "optiga_backend_rng.h" +#include "optiga/optiga_crypt.h" + + +/** @brief Minimal size output of random data in OPTIGA Trust X + * + * @details See Solution Reference Manual v1.35, section 4.4.3.4 + */ +#define OPTIGA_RNG_MIN_SIZE (0x8) + + +/** @brief Maximum size output of random data in OPTIGA Trust X + * + * @details See Solution Reference Manual v1.35, section 4.4.3.4 + */ +#define OPTIGA_RNG_MAX_SIZE (0x100) + + +ret_code_t nrf_crypto_rng_backend_init(void * const p_context, + void * const p_temp_buffer) +{ + UNUSED_PARAMETER(p_context); + UNUSED_PARAMETER(p_temp_buffer); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_rng_backend_uninit(void * const p_context) +{ + UNUSED_PARAMETER(p_context); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_rng_backend_vector_generate(void * const p_context, + uint8_t * const p_target, + size_t size, + bool use_mutex) +{ + UNUSED_PARAMETER(use_mutex); + UNUSED_PARAMETER(p_context); + + uint8_t backup[OPTIGA_RNG_MIN_SIZE] = {0}; + optiga_lib_status_t err; + + uint8_t * out_cur = p_target; + + size_t size_left = size; + size_t cur_len = size_left; + + do + { + cur_len = size_left > OPTIGA_RNG_MAX_SIZE ? OPTIGA_RNG_MAX_SIZE : size_left; + + if (cur_len < OPTIGA_RNG_MIN_SIZE) + { + err = optiga_crypt_random(OPTIGA_RNG_TYPE_TRNG, backup, OPTIGA_RNG_MIN_SIZE); + if(err != OPTIGA_LIB_SUCCESS) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + memcpy(out_cur, backup, cur_len); + } + else + { + err = optiga_crypt_random(OPTIGA_RNG_TYPE_TRNG, out_cur, cur_len); + if (err != OPTIGA_LIB_SUCCESS) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + } + + out_cur += cur_len; + size_left -= cur_len; + + } while(size_left > 0); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_rng_backend_reseed(void * const p_context, + void * p_temp_buffer, + uint8_t * p_input_data, + size_t size) +{ + UNUSED_PARAMETER(p_context); + UNUSED_PARAMETER(p_temp_buffer); + UNUSED_PARAMETER(p_input_data); + UNUSED_PARAMETER(size); + + return NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE; +} + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA_RNG) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) diff --git a/components/libraries/crypto/backend/optiga/optiga_backend_rng.h b/components/libraries/crypto/backend/optiga/optiga_backend_rng.h new file mode 100644 index 0000000..24c20b0 --- /dev/null +++ b/components/libraries/crypto/backend/optiga/optiga_backend_rng.h @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef OPTIGA_BACKEND_RNG_H__ +#define OPTIGA_BACKEND_RNG_H__ + +/** @file + * + * @defgroup nrf_crypto_optiga_backend_rng nrf_crypto OPTIGA RNG backend + * @{ + * @ingroup nrf_crypto_backends + * + * @brief RNG functionality provided by the nrf_crypto OPTIGA RNG backend. + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) +#if NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA_RNG) + + +#include "nrf_crypto_rng_shared.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) +#error "More than one RNG backend enabled." +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) +#define NRF_CRYPTO_RNG_ENABLED 1 + +/** + * @internal @brief Context for nRF RNG peripheral. + */ +typedef struct +{ + nrf_crypto_rng_internal_context_t header; //!< Internal common context header. +} nrf_crypto_backend_rng_context_t; + +/** + * @internal @brief Dummy temp buffer for nRF RNG peripheral. + */ +typedef struct +{ + uint32_t reserved; +} nrf_crypto_backend_rng_temp_buffer_t; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA_RNG) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_OPTIGA) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) + +/**@} */ + +#endif // OPTIGA_BACKEND_RNG_H__ diff --git a/components/libraries/crypto/backend/optiga/optiga_backend_utils.c b/components/libraries/crypto/backend/optiga/optiga_backend_utils.c new file mode 100644 index 0000000..d43927e --- /dev/null +++ b/components/libraries/crypto/backend/optiga/optiga_backend_utils.c @@ -0,0 +1,265 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include +#include "optiga_backend_utils.h" +#include "nrf_crypto_error.h" + +/** + * @brief Decodes two ASN.1 integers to the R and S components of a ECC signature. + * + * @param[in] p_asn1 Pointer to buffer containing the ASN.1 encoded R and S values. + * @param[in] asn1_len Length of the asn1 buffer. + * @param[out] p_rs Pointer to buffer where to write the R and S values + * @param[in,out] p_rs_len pointer to variable containing length of the rs buffer, + * updated to actual length after the call. + * + * @returns NRF_SUCCESS on success, otherwise NRF_ERROR_CRYPTO_INTERNAL. + */ +ret_code_t asn1_to_ecdsa_rs(uint8_t const * p_asn1, + size_t asn1_len, + uint8_t * p_rs, + size_t * p_rs_len) +{ + + uint8_t const * p_cur = p_asn1; + uint8_t const * p_end = p_asn1 + asn1_len; // Points to first invalid mem-location + uint8_t r_len; + uint8_t s_len; + + if (p_asn1 == NULL || p_rs == NULL || p_rs_len == NULL) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + if (asn1_len == 0 || *p_rs_len == 0) + { + return NRF_ERROR_CRYPTO_INTERNAL; + } + + if (*p_cur != DER_TAG_INTEGER) + { + // Wrong tag type + return NRF_ERROR_CRYPTO_INTERNAL; + } + + if ((p_cur + 2) >= p_end) + { + // Prevented out-of-bounds read + return NRF_ERROR_CRYPTO_INTERNAL; + } + + // Move to length value + p_cur++; + r_len = *p_cur; + + if (r_len > DER_INTEGER_MAX_LEN) + { + // Unsupported length + return NRF_ERROR_CRYPTO_INTERNAL; + } + + // Move to first data value + p_cur++; + + // Check for stuffing bits + if (*p_cur == 0x00) + { + p_cur++; + r_len--; + } + + // Check for out-of-bounds read + if ((p_cur + r_len) >= p_end) + { + // prevented out-of-bounds read + return NRF_ERROR_CRYPTO_INTERNAL; + } + + // Check for out-of-bounds write + if ((p_rs + r_len) > (p_rs + *p_rs_len)) + { + // prevented out-of-bounds write + return NRF_ERROR_CRYPTO_INTERNAL; + } + + // Copy R component to output + memcpy(p_rs, p_cur, r_len); + + // Move to next tag + p_cur += r_len; + + if (*p_cur != DER_TAG_INTEGER) + { + // Wrong tag type + return NRF_ERROR_CRYPTO_INTERNAL; + } + + if ((p_cur + 2) >= p_end) + { + // Prevented out-of-bounds read + return NRF_ERROR_CRYPTO_INTERNAL; + } + p_cur++; + s_len = *p_cur; + + if (s_len > DER_INTEGER_MAX_LEN) + { + // Unsupported length + return NRF_ERROR_CRYPTO_INTERNAL; + } + p_cur++; + + if (*p_cur == 0x00) + { + p_cur++; + s_len--; + } + + // Check for out-of-bounds read + if ((p_cur + s_len) > p_end) + { + // prevented out-of-bounds read + return NRF_ERROR_CRYPTO_INTERNAL; + } + + // Check for out-of-bounds write + if ((p_rs + r_len + s_len) > (p_rs + *p_rs_len)) + { + // Prevented out-of-bounds write + return NRF_ERROR_CRYPTO_INTERNAL; + } + + memcpy(p_rs + r_len, p_cur, s_len); + + *p_rs_len = r_len + s_len; + + return NRF_SUCCESS; +} + + +/** + * @brief Encodes the ECDSA signature components (r, s) in ASN.1 format. + * + * @param[in] p_r Pointer to buffer containing component r of the ECDSA signature. + * @param[in] r_len Length of the r component of the ECDSA signature. + * @param[in] p_s Pointer to buffer containing component s of the ECDSA signature. + * @param[in] s_len Length of the s component of the ECDSA signature. + * @param[out] p_asn_sig Pointer to buffer to hold the resulting ASN.1-encoded ECDSA signature. + * @param[out] p_asn_sig_len Pointer to variable holding the length of the buffer for ASN.1-encoded + * ECDSA signature. This will be updated to the actual size when the + * function is called. + * + * @returns True on success, otherwise false. + */ +bool ecdsa_rs_to_asn1(uint8_t const * p_r, + size_t r_len, + uint8_t const * p_s, + size_t s_len, + uint8_t * p_asn_sig, + size_t * p_asn_sig_len) +{ + size_t index = 0; + // NULL checks + if (p_r == NULL || p_s == NULL || p_asn_sig_len == NULL) + { + return false; + } + + if (r_len == 0 || r_len > DER_INTEGER_MAX_LEN || s_len == 0 || s_len > DER_INTEGER_MAX_LEN) + { + return false; + } + + if (*p_asn_sig_len < (r_len + s_len + DER_OVERHEAD)) + { + // Not enough space in output buffer + return false; + } + + // R component + // DER TAG INTEGER + p_asn_sig[index] = DER_TAG_INTEGER; + index++; + + // Set length + p_asn_sig[index] = r_len; + + // check if extra byte needed + if (p_r[0] & 0x80) + { + // Update length value + p_asn_sig[index] += 1; + index++; + // Insert zero byte for padding + p_asn_sig[index] = 0; + } + + index++; + + memcpy(&p_asn_sig[index], p_r, r_len); + index += r_len; + + // S component + // DER TAG INTEGER + p_asn_sig[index] = DER_TAG_INTEGER; + index++; + // Set length + p_asn_sig[index] = s_len; + + if (p_s[0] & 0x80) + { + // Update length value + p_asn_sig[index] += 1; + index++; + // Insert zero byte for padding + p_asn_sig[index] = 0; + } + + index++; + + memcpy(&p_asn_sig[index], p_s, s_len); + index += s_len; + + // Return total length of ASN.1-encoded data structure + *p_asn_sig_len = index; + return true; +} diff --git a/components/libraries/crypto/backend/optiga/optiga_backend_utils.h b/components/libraries/crypto/backend/optiga/optiga_backend_utils.h new file mode 100644 index 0000000..2f5f764 --- /dev/null +++ b/components/libraries/crypto/backend/optiga/optiga_backend_utils.h @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef OPTIGA_BACKEND_UTILS_H__ +#define OPTIGA_BACKEND_UTILS_H__ + +#include +#include +#include +#include "sdk_config.h" +#include "nordic_common.h" +#include "sdk_errors.h" + +/** @brief Define for a integer tag in DER encoding. */ +#define DER_TAG_INTEGER 0x02 + + +/** @brief Max size of integer in DER encoding. + * + * @note This limit is for this implementation only, ASN.1 DER supports more + */ +#define DER_INTEGER_MAX_LEN 0x7F + + +/** @brief Define for overhead to encode a DER of two integers + * + * @details TAG + LENGTH needs 2 bytes if the highest bit of the integer is set + * we need an extra byte + */ +#define DER_OVERHEAD ((2 + 1) * 2) + + +/** + * @brief Decodes two ASN.1 integers to the R and S components of a ECC signature. + * + * @param[in] p_asn1 Pointer to buffer containing the ASN.1 encoded R and S values. + * @param[in] asn1_len Length of the asn1 buffer. + * @param[out] p_rs Pointer to buffer where to write the R and S values + * @param[in,out] p_rs_len pointer to variable containing length of the rs buffer, + * updated to actual length after the call. + * + * @returns NRF_SUCCESS on success, otherwise NRF_ERROR_CRYPTO_INTERNAL. + */ + +ret_code_t asn1_to_ecdsa_rs(uint8_t const * p_asn1, + size_t asn1_len, + uint8_t * p_rs, + size_t * p_rs_len); + + + +/** + * @brief Encodes the ECDSA signature components (r, s) in ASN.1 format. + * + * @param[in] p_r Pointer to buffer containing component r of the ECDSA signature. + * @param[in] r_len Length of the r component of the ECDSA signature. + * @param[in] p_s Pointer to buffer containing component s of the ECDSA signature. + * @param[in] s_len Length of the s component of the ECDSA signature. + * @param[out] p_asn_sig Pointer to buffer to hold the resulting ASN.1-encoded ECDSA signature. + * @param[out] p_asn_sig_len Pointer to variable holding the length of the buffer for ASN.1-encoded + * ECDSA signature. This will be updated to the actual size when the + * function is called. + * + * @returns True on success, otherwise false. + */ +bool ecdsa_rs_to_asn1(uint8_t const * p_r, + size_t r_len, + uint8_t const * p_s, + size_t s_len, + uint8_t * p_asn_sig, + size_t * p_asn_sig_len); + + +#endif // OPTIGA_BACKEND_UTILS_H__ + diff --git a/components/libraries/crypto/nrf_crypto.h b/components/libraries/crypto/nrf_crypto.h new file mode 100644 index 0000000..9823fe9 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto.h @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_H__ +#define NRF_CRYPTO_H__ + +/** + * @defgroup nrf_crypto Cryptography library + * @ingroup app_common + * @{ + * + * @brief Cryptography library (nrf_crypto). + * + * @details The cryptography library provides cryptographic functionality in a portable way. + * + * @note The functions in this API can run in software or hardware, depending on the supported features of your SoC and the configuration of nrf_crypto backend in the application. + * See @ref lib_crypto_config for details on changing the nrf_crypto backend. + * + * @} + * + */ + + + +#include +#include "nrf_crypto_init.h" +#include "nrf_crypto_types.h" +#include "nrf_crypto_mem.h" +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_hash.h" +#include "nrf_crypto_ecdsa.h" +#include "nrf_crypto_ecdh.h" +#include "nrf_crypto_rng.h" +#include "nrf_crypto_aes.h" +#include "nrf_crypto_aead.h" +#include "nrf_crypto_hmac.h" +#include "nrf_crypto_hkdf.h" +#include "nrf_crypto_eddsa.h" + + +#endif // NRF_CRYPTO_H__ diff --git a/components/libraries/crypto/nrf_crypto_aead.c b/components/libraries/crypto/nrf_crypto_aead.c new file mode 100644 index 0000000..865643b --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_aead.c @@ -0,0 +1,159 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include "nrf_crypto_error.h" +#include "nrf_crypto_aead.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AEAD) + +static ret_code_t context_verify(nrf_crypto_aead_internal_context_t const * p_context) +{ + VERIFY_TRUE((p_context != NULL), NRF_ERROR_CRYPTO_CONTEXT_NULL); + + VERIFY_TRUE((p_context->init_value == NRF_CRYPTO_AEAD_INIT_MAGIC_VALUE), + NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_aead_init(nrf_crypto_aead_context_t * const p_context, + nrf_crypto_aead_info_t const * const p_info, + uint8_t * p_key) +{ + ret_code_t ret_val; + + nrf_crypto_aead_internal_context_t * p_int_context = + (nrf_crypto_aead_internal_context_t *)p_context; + + VERIFY_TRUE((p_info != NULL), NRF_ERROR_CRYPTO_INPUT_NULL); + + VERIFY_TRUE((p_key != NULL), NRF_ERROR_CRYPTO_INPUT_NULL); + + ret_val = context_verify(p_int_context); + VERIFY_TRUE((ret_val == NRF_SUCCESS) || (ret_val == NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED), + ret_val); + + p_int_context->init_value = NRF_CRYPTO_AEAD_INIT_MAGIC_VALUE; + p_int_context->p_info = p_info; + + ret_val = p_info->init_fn(p_context, p_key); + + if (ret_val != NRF_SUCCESS) + { + p_int_context->init_value = 0; + } + + return ret_val; +} + +ret_code_t nrf_crypto_aead_uninit(void * const p_context) +{ + ret_code_t ret_val; + + nrf_crypto_aead_internal_context_t * p_int_context = + (nrf_crypto_aead_internal_context_t *)p_context; + + ret_val = context_verify(p_int_context); + VERIFY_SUCCESS(ret_val); + + ret_val = p_int_context->p_info->uninit_fn(p_context); + + p_int_context->init_value = 0; + + return ret_val; +} + +ret_code_t nrf_crypto_aead_crypt(nrf_crypto_aead_context_t * const p_context, + nrf_crypto_operation_t operation, + uint8_t * p_nonce, + uint8_t nonce_size, + uint8_t * p_adata, + size_t adata_size, + uint8_t * p_data_in, + size_t data_in_size, + uint8_t * p_data_out, + uint8_t * p_mac, + uint8_t mac_size) +{ + ret_code_t ret_val; + + nrf_crypto_aead_internal_context_t * p_int_context = + (nrf_crypto_aead_internal_context_t *)p_context; + + ret_val = context_verify(p_int_context); + VERIFY_SUCCESS(ret_val); + + VERIFY_FALSE(((p_nonce == NULL) && (nonce_size != 0)), + NRF_ERROR_CRYPTO_INPUT_NULL); + + /* If mac_size == 0 MAC is updated and not stored under p_mac */ + VERIFY_FALSE(((p_mac == NULL) && (mac_size != 0)), + NRF_ERROR_CRYPTO_INPUT_NULL); + + VERIFY_FALSE(((p_adata == NULL) && (adata_size != 0)), + NRF_ERROR_CRYPTO_INPUT_NULL); + + VERIFY_FALSE(((p_data_in == NULL) && (data_in_size != 0)), + NRF_ERROR_CRYPTO_INPUT_NULL); + + VERIFY_FALSE(((p_data_out == NULL) && (data_in_size != 0)), + NRF_ERROR_CRYPTO_OUTPUT_NULL); + + ret_val = p_int_context->p_info->crypt_fn(p_context, + operation, + p_nonce, + nonce_size, + p_adata, + adata_size, + p_data_in, + data_in_size, + p_data_out, + p_mac, + mac_size); + return ret_val; +} + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_AEAD) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) + diff --git a/components/libraries/crypto/nrf_crypto_aead.h b/components/libraries/crypto/nrf_crypto_aead.h new file mode 100644 index 0000000..43d3b4e --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_aead.h @@ -0,0 +1,235 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_AEAD_H__ +#define NRF_CRYPTO_AEAD_H__ + +/** @file + * + * @defgroup nrf_crypto_aead AEAD (Authenticated Encryption with Associated Data) related + * functions. + * @{ + * @ingroup nrf_crypto + * + * @brief Provides AEAD related functionality through nrf_crypto. + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) || defined(__SDK_DOXYGEN__) + +#include +#include "nrf_crypto_types.h" +#include "nrf_crypto_aead_shared.h" +#include "nrf_crypto_aead_backend.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief External variable declaration to the info structure for AES CCM mode with a 128-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aead_info_t g_nrf_crypto_aes_ccm_128_info; + +/**@brief External variable declaration to the info structure for AES CCM mode with a 192-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aead_info_t g_nrf_crypto_aes_ccm_192_info; + +/**@brief External variable declaration to the info structure for AES CCM mode with a 256-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aead_info_t g_nrf_crypto_aes_ccm_256_info; + +/**@brief External variable declaration to the info structure for AES CCM* mode with a 128-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aead_info_t g_nrf_crypto_aes_ccm_star_128_info; + +/**@brief External variable declaration to the info structure for AES EAX mode with a 128-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aead_info_t g_nrf_crypto_aes_eax_128_info; + +/**@brief External variable declaration to the info structure for AES EAX mode with a 192-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aead_info_t g_nrf_crypto_aes_eax_192_info; + +/**@brief External variable declaration to the info structure for AES EAX mode with a 256-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aead_info_t g_nrf_crypto_aes_eax_256_info; + +/**@brief External variable declaration to the info structure for AES GCM mode with a 128-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is enabled in the @ref sdk_config. +* +*/ +extern const nrf_crypto_aead_info_t g_nrf_crypto_aes_gcm_128_info; + +/**@brief External variable declaration to the info structure for AES GCM mode with a 192-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is enabled in the @ref sdk_config. +* +*/ +extern const nrf_crypto_aead_info_t g_nrf_crypto_aes_gcm_192_info; + +/**@brief External variable declaration to the info structure for AES GCM mode with a 256-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is enabled in the @ref sdk_config. +* +*/ +extern const nrf_crypto_aead_info_t g_nrf_crypto_aes_gcm_256_info; + +/**@brief External variable declaration to the info structure for CHACHA-POLY mode with a 256-bit +* key. +* +* @note The variable is defined in the nrf_crypto backend that is enabled in the @ref sdk_config. +* +*/ +extern const nrf_crypto_aead_info_t g_nrf_crypto_chacha_poly_256_info; + + +/** + * @brief Context type for AEAD. + * + * @note The size of this type is scaled for the largest AEAD backend context that is + * enabled in @ref sdk_config. + */ +typedef nrf_crypto_backend_aead_context_t nrf_crypto_aead_context_t; + + +/**@brief Function for initializing the AEAD calculation context. + * + * @param[in] p_context Pointer to the context object. It must be a context type associated with + * the object provided in the p_info parameter or other memory that can + * hold that context type. + * @param[in] p_info Pointer to structure holding information about: selected AES AEAD mode, + * and key size. + * @param[in] p_key Pointer to AEAD mode key. + * + * @retval NRF_SUCCESS Context was successfully initialized. + */ +ret_code_t nrf_crypto_aead_init(nrf_crypto_aead_context_t * const p_context, + nrf_crypto_aead_info_t const * const p_info, + uint8_t * p_key); + +/**@brief Function for uninitializing the AEAD calculation context. + * + * @param[in] p_context Pointer to the context object. It must be initialized before function call. + * + * @retval NRF_SUCCESS Context was successfully uninitialized. + */ +ret_code_t nrf_crypto_aead_uninit(void * const p_context); + +/**@brief Integrated encryption / decryption function. + * + * @param[in] p_context Context object. Must be initialized before the call. + * @param[in] operation Parameter indicating whether an encrypt (NRF_CRYPTO_ENCRYPT) or + * a decrypt (NRF_CRYPTO_DECRYPT) operation shall be performed. + * @param[in] p_nonce Pointer to nonce. For nonce_size == 0 p_nonce can be NULL. + * @param[in] nonce_size Nonce byte size. Valid values for supported modes: + * - CCM [7 ... 13] + * - CCM* [13] + * - EAX nonce size can be any length + * - GCM nonce size can be any length + * - CHACHA-POLY [12] + * @param[in] p_adata Pointer to additional authenticated data (adata). + * @param[in] adata_size Length of additional authenticated data in bytes. + * For CHACHA-POLY mode must be > 0. + * @param[in] p_data_in Pointer to the input data buffer for encryption or decryption. + * @param[in] data_in_size Length of the data in p_data_in buffer in bytes. Size of the + * p_data_out buffer must not be smaller than this value. + * When selecting CC310 backend data_in_size value shall be limited + * to 65535 bytes. Data out buffer must be at least the same length. + * @param[out] p_data_out Pointer to the output buffer where encrypted or decrypted data + * will be stored. Must be at least 'data_in_size' bytes wide. + * - GCM: On encryption, the p_data_out buffer can be the same as + * the p_data_in buffer. + * On decryption, the p_data_out buffer cannot be the same + * as p_data_in buffer. If buffers overlap, the p_data_out + * buffer must trail at least 8 bytes behind the p_data_in + * buffer. + * @param[out] p_mac Pointer to the MAC result buffer. Fo mac_size == 0 p_mac can be NULL. + * @param[in] mac_size MAC byte size. Valid values for supported modes: + * -CCM [4, 6, 8, 10, 12, 14, 16] + * -CCM* [0, 4, 8, 16] + * -EAX [1 ... 16] + * -GCM [4 ... 16] + * -CHACHA-POLY [16] + * + * @retval NRF_SUCCESS Message was successfully encrypted. + */ +ret_code_t nrf_crypto_aead_crypt(nrf_crypto_aead_context_t * const p_context, + nrf_crypto_operation_t operation, + uint8_t * p_nonce, + uint8_t nonce_size, + uint8_t * p_adata, + size_t adata_size, + uint8_t * p_data_in, + size_t data_in_size, + uint8_t * p_data_out, + uint8_t * p_mac, + uint8_t mac_size); + +#ifdef __cplusplus +} +#endif + +#endif // #if NRF_MODULE_ENABLED(NRF_CRYPTO) || defined(__SDK_DOXYGEN__) + +/** @} */ + +#endif // NRF_CRYPTO_AEAD_H__ diff --git a/components/libraries/crypto/nrf_crypto_aead_backend.h b/components/libraries/crypto/nrf_crypto_aead_backend.h new file mode 100644 index 0000000..a1ad862 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_aead_backend.h @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_AEAD_BACKEND_H__ +#define NRF_CRYPTO_AEAD_BACKEND_H__ + +#include "cc310_backend_aes_aead.h" +#include "cc310_backend_chacha_poly_aead.h" +#include "cifra_backend_aes_aead.h" +#include "mbedtls_backend_aes_aead.h" +#include "oberon_backend_chacha_poly_aead.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@internal @brief Fallback type for AES CCM context (if no backend is enabled). + */ +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CCM) +typedef nrf_crypto_aead_internal_context_t nrf_crypto_backend_aes_ccm_context_t; +#endif + +/**@internal @brief Fallback type for AES CCM* context (if no backend is enabled). + */ +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CCM_STAR) +typedef nrf_crypto_aead_internal_context_t nrf_crypto_backend_aes_ccm_star_context_t; +#endif + +/**@internal @brief Fallback type for AES EAX context (if no backend is enabled). + */ +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_AES_EAX) +typedef nrf_crypto_aead_internal_context_t nrf_crypto_backend_aes_eax_context_t; +#endif + +/**@internal @brief Fallback type for AES GCM context (if no backend is enabled). + */ +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_AES_GCM) +typedef nrf_crypto_aead_internal_context_t nrf_crypto_backend_aes_gcm_context_t; +#endif + +/**@internal @brief Fallback type for CHACHA-POLY context (if no backend is enabled). + */ +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_CHACHA_POLY) +typedef nrf_crypto_aead_internal_context_t nrf_crypto_backend_chacha_poly_context_t; +#endif + +/** @internal @brief Union holding a AEAD context. */ +typedef union +{ + nrf_crypto_backend_aes_ccm_context_t ccm_context; /**< @brief Holds context for AES CCM. */ + nrf_crypto_backend_aes_ccm_star_context_t ccm_star_context; /**< @brief Holds context for AES CCM*. */ + nrf_crypto_backend_aes_eax_context_t eax_context; /**< @brief Holds context for AES EAX. */ + nrf_crypto_backend_aes_gcm_context_t gcm_context; /**< @brief Holds context for AES GCM. */ + + nrf_crypto_backend_chacha_poly_context_t chacha_poly_context; /**< @brief Holds context for ChaCha-Poly. */ +} nrf_crypto_backend_aead_context_t; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_CRYPTO_AEAD_BACKEND_H__ diff --git a/components/libraries/crypto/nrf_crypto_aead_shared.h b/components/libraries/crypto/nrf_crypto_aead_shared.h new file mode 100644 index 0000000..4082fa6 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_aead_shared.h @@ -0,0 +1,147 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_AEAD_SHARED_H__ +#define NRF_CRYPTO_AEAD_SHARED_H__ + +/** @file + * + * @defgroup nrf_crypto_aead_shared AEAD related functions + * @{ + * @ingroup nrf_crypto + * + * @brief Provides AEAD related functionality through nrf_crypto. + */ + +#include +#include "nrf_crypto_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@internal @brief Magic value to signal that the nrf_crypto_hash context structure is initialized. + */ +#define NRF_CRYPTO_AEAD_INIT_MAGIC_VALUE (0x44414541) // ASCII "AEAD" + +#define NRF_CRYPTO_AES_CCM_STAR_MAC_BITMASK (0x1C) /* [0, 4, 8, 16] allowed MAC size in CCM mode */ +#define NRF_CRYPTO_AES_CCM_MAC_MIN (4u) /* MAC min value in CCM mode */ +#define NRF_CRYPTO_AES_CCM_MAC_MAX (16u) /* MAC max value in CCM mode */ +#define NRF_CRYPTO_AES_GCM_MAC_MIN (4u) /* MAC min value in GCM mode */ +#define NRF_CRYPTO_AES_GCM_MAC_MAX (16u) /* MAC max value in GCM mode */ +#define NRF_CRYPTO_AES_CCM_NONCE_SIZE_MIN (7u) /* [7...13] allowed nonce size in CCM mode */ +#define NRF_CRYPTO_AES_CCM_NONCE_SIZE_MAX (13u) /* [7...13] allowed nonce size in CCM mode */ +#define NRF_CRYPTO_AES_CCM_STAR_NONCE_SIZE (13u) /* [13] allowed nonce size in CCM* mode */ +#define NRF_CRYPTO_CHACHA_POLY_NONCE_SIZE (12u) /* [12] allowed nonce size in chacha-poly mode */ +#define NRF_CRYPTO_CHACHA_POLY_MAC_SIZE (16u) /* [16] allowed MAC size in chacha-poly mode */ + +/**@internal @brief Enumeration of supported modes of operation in nrf_crypto_aead. + */ +typedef enum +{ + NRF_CRYPTO_AEAD_MODE_AES_CCM, // supported by: MBEDTLS & CC310 + NRF_CRYPTO_AEAD_MODE_AES_CCM_STAR, // supported by: CC310 + NRF_CRYPTO_AEAD_MODE_AES_EAX, // supported by: CIFRA + NRF_CRYPTO_AEAD_MODE_AES_GCM, // supported by: MBEDTLS + NRF_CRYPTO_AEAD_MODE_CHACHA_POLY // supported by: CC310 & OBERON +} nrf_crypto_aead_mode_t; + + +/**@internal @brief Type declaration to perform AEAD initialization in the nrf_crypto backend. + * + * This is internal API. See @ref nrf_crypto_aead_init for documentation. + */ +typedef ret_code_t (*aead_init_fn_t)(void * const p_context, uint8_t * p_key); + +/**@internal @brief Type declaration to perform AEAD uninitialization in the nrf_crypto backend. + * + * This is internal API. See @ref nrf_crypto_aead_uninit for documentation. + */ +typedef ret_code_t (*aead_uninit_fn_t)(void * const p_context); + +/**@internal @brief Type declaration to perform AEAD encryption in nrf_crypto backend. + * + * This is internal API. See @ref nrf_crypto_aead_crypt for documentation. + */ +typedef ret_code_t (*aead_crypt_fn_t)(void * const p_context, + nrf_crypto_operation_t operation, + uint8_t * p_nonce, + uint8_t nonce_size, + uint8_t * p_adata, + size_t adata_size, + uint8_t * p_data_in, + size_t data_in_size, + uint8_t * p_data_out, + uint8_t * p_mac, + uint8_t mac_size); + +/**@internal @brief Type declaration for the nrf_crypto_aead info structure. + * + * @details This structure contains the calling interface and any metadata required + * to call the nrf_crypto_aead API functions. + */ +typedef struct +{ + nrf_crypto_aead_mode_t const mode; + nrf_crypto_key_size_id_t const key_size; + + aead_init_fn_t const init_fn; + aead_uninit_fn_t const uninit_fn; + aead_crypt_fn_t const crypt_fn; +} nrf_crypto_aead_info_t; + +/**@internal @brief Type declaration of internal representation of an AEAD context structure. + * + * @details This is an internal type that should not be used directly. + */ +typedef struct +{ + uint32_t init_value; + nrf_crypto_aead_info_t const * p_info; +} nrf_crypto_aead_internal_context_t; + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef NRF_CRYPTO_AEAD_SHARED_H__ + diff --git a/components/libraries/crypto/nrf_crypto_aes.c b/components/libraries/crypto/nrf_crypto_aes.c new file mode 100644 index 0000000..f2a2849 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_aes.c @@ -0,0 +1,319 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include "nrf_crypto_aes.h" +#include "nrf_crypto_mem.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_shared.h" +#include "nrf_crypto_aes_shared.h" +#include "nrf_crypto_aes_backend.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_AES) + +static ret_code_t context_verify(nrf_crypto_aes_internal_context_t const * p_context) +{ + if (p_context == NULL) + { + return NRF_ERROR_CRYPTO_CONTEXT_NULL; + } + + if (p_context->init_value != NRF_CRYPTO_AES_INIT_MAGIC_VALUE) + { + return NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED; + } + + return NRF_SUCCESS; +} + +ret_code_t nrf_crypto_aes_init(nrf_crypto_aes_context_t * const p_context, + nrf_crypto_aes_info_t const * const p_info, + nrf_crypto_operation_t operation) +{ + ret_code_t ret_val; + + nrf_crypto_aes_internal_context_t * p_int_context = + (nrf_crypto_aes_internal_context_t *)p_context; + + ret_val = context_verify(p_int_context); + VERIFY_TRUE((ret_val == NRF_SUCCESS) || (ret_val == NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED), + ret_val); + + VERIFY_TRUE(p_info != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + + p_int_context->p_info = p_info; + + ret_val = p_info->init_fn(p_context, operation); + + if (ret_val == NRF_SUCCESS) + { + p_int_context->init_value = NRF_CRYPTO_AES_INIT_MAGIC_VALUE; + } + + return ret_val; +} + +ret_code_t nrf_crypto_aes_uninit(nrf_crypto_aes_context_t * const p_context) +{ + ret_code_t ret_val; + + nrf_crypto_aes_internal_context_t * p_int_context = + (nrf_crypto_aes_internal_context_t *)p_context; + + ret_val = context_verify(p_int_context); + + if (ret_val == NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED) + { + /* If context was uninitialized with function nrf_crypto_aes_finalize it shall be still + possible to clear init_value */ + if (p_int_context->init_value == NRF_CRYPTO_AES_UNINIT_MAGIC_VALUE) + { + ret_val = NRF_SUCCESS; + } + } + VERIFY_SUCCESS(ret_val); + + ret_val = p_int_context->p_info->uninit_fn(p_context); + + p_int_context->init_value = 0; + + return ret_val; +} + +ret_code_t nrf_crypto_aes_key_set(nrf_crypto_aes_context_t * const p_context, uint8_t * p_key) +{ + ret_code_t ret_val; + + nrf_crypto_aes_internal_context_t * p_int_context = + (nrf_crypto_aes_internal_context_t *)p_context; + + ret_val = context_verify(p_int_context); + VERIFY_SUCCESS(ret_val); + + VERIFY_TRUE((p_key != NULL), NRF_ERROR_CRYPTO_INPUT_NULL); + + ret_val = p_int_context->p_info->key_set_fn(p_context, p_key); + + return ret_val; +} + +ret_code_t nrf_crypto_aes_iv_set(nrf_crypto_aes_context_t * const p_context, uint8_t * p_iv) +{ + ret_code_t ret_val; + + nrf_crypto_aes_internal_context_t * p_int_context = + (nrf_crypto_aes_internal_context_t *)p_context; + + ret_val = context_verify(p_int_context); + VERIFY_SUCCESS(ret_val); + + VERIFY_TRUE((p_int_context->p_info->iv_set_fn != NULL), NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE); + + VERIFY_TRUE((p_iv != NULL), NRF_ERROR_CRYPTO_INPUT_NULL); + + ret_val = p_int_context->p_info->iv_set_fn(p_context, p_iv); + + return ret_val; +} + +ret_code_t nrf_crypto_aes_iv_get(nrf_crypto_aes_context_t * const p_context, uint8_t * p_iv) +{ + ret_code_t ret_val; + + nrf_crypto_aes_internal_context_t * p_int_context = + (nrf_crypto_aes_internal_context_t *)p_context; + + ret_val = context_verify(p_int_context); + if (ret_val == NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED) + { + /* If context was uninitialized with function nrf_crypto_aes_finalize it shall be still + possible to read IV value */ + if (p_int_context->init_value == NRF_CRYPTO_AES_UNINIT_MAGIC_VALUE) + { + ret_val = NRF_SUCCESS; + } + } + VERIFY_SUCCESS(ret_val); + + VERIFY_TRUE((p_iv != NULL), NRF_ERROR_CRYPTO_INPUT_NULL); + + VERIFY_TRUE((p_int_context->p_info->iv_get_fn != NULL), NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE); + + ret_val = p_int_context->p_info->iv_get_fn(p_context, p_iv); + + return ret_val; +} + +ret_code_t nrf_crypto_aes_update(nrf_crypto_aes_context_t * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out) +{ + ret_code_t ret_val; + + nrf_crypto_aes_internal_context_t * p_int_context = + (nrf_crypto_aes_internal_context_t *)p_context; + + ret_val = context_verify(p_int_context); + VERIFY_SUCCESS(ret_val); + + VERIFY_TRUE((data_size != 0), NRF_ERROR_CRYPTO_INPUT_LENGTH); + + VERIFY_TRUE((p_data_in != NULL), NRF_ERROR_CRYPTO_INPUT_NULL); + + VERIFY_TRUE((p_data_out != NULL), NRF_ERROR_CRYPTO_OUTPUT_NULL); + + if ((data_size & 0xF) != 0) + { + VERIFY_TRUE((p_int_context->p_info->mode == NRF_CRYPTO_AES_MODE_CFB), + NRF_ERROR_CRYPTO_INPUT_LENGTH); + } + + ret_val = p_int_context->p_info->update_fn(p_context, + p_data_in, + data_size, + p_data_out); + + return ret_val; +} + +ret_code_t nrf_crypto_aes_finalize(nrf_crypto_aes_context_t * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out, + size_t * p_data_out_size) +{ + ret_code_t ret_val; + + nrf_crypto_aes_internal_context_t * p_int_context = + (nrf_crypto_aes_internal_context_t *)p_context; + + ret_val = context_verify(p_int_context); + VERIFY_SUCCESS(ret_val); + + VERIFY_TRUE((p_data_in != NULL), NRF_ERROR_CRYPTO_INPUT_NULL); + + VERIFY_TRUE((p_data_out != NULL), NRF_ERROR_CRYPTO_OUTPUT_NULL); + + VERIFY_TRUE((p_data_out_size != NULL), NRF_ERROR_CRYPTO_OUTPUT_NULL); + + ret_val = p_int_context->p_info->finalize_fn(p_context, + p_data_in, + data_size, + p_data_out, + p_data_out_size); + + VERIFY_TRUE((ret_val == NRF_SUCCESS), ret_val); + + ret_val = nrf_crypto_aes_uninit(p_context); + + if (ret_val == NRF_SUCCESS) + { + /* This line will allow to read IV for AES supporting IV get function. */ + p_int_context->init_value = NRF_CRYPTO_AES_UNINIT_MAGIC_VALUE; + } + + return ret_val; +} + +ret_code_t nrf_crypto_aes_crypt(nrf_crypto_aes_context_t * const p_context, + nrf_crypto_aes_info_t const * const p_info, + nrf_crypto_operation_t operation, + uint8_t * p_key, + uint8_t * p_iv, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out, + size_t * p_data_out_size) +{ + ret_code_t ret_val; + void * p_allocated_context = NULL; + + nrf_crypto_aes_context_t * p_ctx = p_context; + + VERIFY_TRUE(p_info != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + + if (p_ctx == NULL) + { + p_allocated_context = NRF_CRYPTO_ALLOC(p_info->context_size); + if (p_allocated_context == NULL) + { + return NRF_ERROR_CRYPTO_ALLOC_FAILED; + } + p_ctx = (nrf_crypto_aes_context_t *)p_allocated_context; + } + + ret_val = nrf_crypto_aes_init(p_ctx, p_info, operation); + NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(ret_val, p_allocated_context); + + ret_val = nrf_crypto_aes_key_set(p_ctx, p_key); + NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(ret_val, p_allocated_context); + + ret_val = nrf_crypto_aes_iv_set(p_ctx, p_iv); + /* not all AES modes support IV */ + if (ret_val != NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE) + { + NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(ret_val, p_allocated_context); + } + + ret_val = nrf_crypto_aes_finalize(p_ctx, + p_data_in, + data_size, + p_data_out, + p_data_out_size); + if (ret_val != NRF_SUCCESS) + { + /* Context was not successfully deinitialized in nrf_crypto_aes_finalize */ + UNUSED_RETURN_VALUE(nrf_crypto_aes_uninit(p_ctx)); + } + + if (p_allocated_context != NULL) + { + NRF_CRYPTO_FREE(p_allocated_context); + } + + return ret_val; +} + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_AES) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) + diff --git a/components/libraries/crypto/nrf_crypto_aes.h b/components/libraries/crypto/nrf_crypto_aes.h new file mode 100644 index 0000000..f3a62db --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_aes.h @@ -0,0 +1,481 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_AES_H__ +#define NRF_CRYPTO_AES_H__ + +/** @file + * + * @defgroup nrf_crypto_aes AES related functions + * @{ + * @ingroup nrf_crypto + * + * @brief Provides AES related functionality through nrf_crypto. + */ +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) || defined(__SDK_DOXYGEN__) + +#include +#include "nrf_crypto_types.h" +#include "nrf_crypto_aes_shared.h" +#include "nrf_crypto_aes_backend.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief External variable declaration to the info structure for AES CBC mode with a 128-bit key. +* No padding. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cbc_128_info; + +/**@brief External variable declaration to the info structure for AES CBC mode with a 192-bit key. +* No padding. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cbc_192_info; + +/**@brief External variable declaration to the info structure for AES CBC mode with a 256-bit key. +* No padding. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cbc_256_info; + +/**@brief External variable declaration to the info structure for AES CBC mode with a 128-bit key. +* Padding pkcs7 enabled. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cbc_128_pad_pkcs7_info; + +/**@brief External variable declaration to the info structure for AES CBC mode with a 192-bit key. +* Padding pkcs7 enabled. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cbc_192_pad_pkcs7_info; + +/**@brief External variable declaration to the info structure for AES CBC mode with a 256-bit key. +* Padding pkcs7 enabled. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cbc_256_pad_pkcs7_info; + +/**@brief External variable declaration to the info structure for AES CTR mode with a 128-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_ctr_128_info; + +/**@brief External variable declaration to the info structure for AES CTR mode with a 192-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_ctr_192_info; + +/**@brief External variable declaration to the info structure for AES CTR mode with a 256-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_ctr_256_info; + +/**@brief External variable declaration to the info structure for AES CFB mode with a 128-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cfb_128_info; + +/**@brief External variable declaration to the info structure for AES CFB mode with a 192-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cfb_192_info; + +/**@brief External variable declaration to the info structure for AES CFB mode with a 256-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cfb_256_info; + +/**@brief External variable declaration to the info structure for AES ECB mode with a 128-bit key. +* No padding. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_ecb_128_info; + +/**@brief External variable declaration to the info structure for AES ECB mode with a 192-bit key. +* No padding. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_ecb_192_info; + +/**@brief External variable declaration to the info structure for AES ECB mode with a 256-bit key. +* No padding. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_ecb_256_info; + +/**@brief External variable declaration to the info structure for AES ECB mode with a 128-bit key. +* Padding pkcs7 enabled. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_ecb_128_pad_pkcs7_info; + +/**@brief External variable declaration to the info structure for AES ECB mode with a 192-bit key. +* Padding pkcs7 enabled. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_ecb_192_pad_pkcs7_info; + +/**@brief External variable declaration to the info structure for AES ECB mode with a 256-bit key. +* Padding pkcs7 enabled. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_ecb_256_pad_pkcs7_info; + +/**@brief External variable declaration to the info structure for AES CBC MAC mode with a 128-bit +* key. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cbc_mac_128_info; + +/**@brief External variable declaration to the info structure for AES CBC MAC mode with a 192-bit +* key. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cbc_mac_192_info; + +/**@brief External variable declaration to the info structure for AES CBC MAC mode with a 256-bit +* key. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cbc_mac_256_info; + +/**@brief External variable declaration to the info structure for AES CBC MAC mode with a 128-bit +* key. +* Padding pkcs7 enabled. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cbc_mac_128_pad_pkcs7_info; + +/**@brief External variable declaration to the info structure for AES CBC MAC mode with a 192-bit +* key. +* Padding pkcs7 enabled. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cbc_mac_192_pad_pkcs7_info; + +/**@brief External variable declaration to the info structure for AES CBC MAC mode with a 256-bit +* key. +* Padding pkcs7 enabled. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cbc_mac_256_pad_pkcs7_info; + + +/**@brief External variable declaration to the info structure for AES CMAC mode with a 128-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cmac_128_info; + +/**@brief External variable declaration to the info structure for AES CMAC mode with a 192-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cmac_192_info; + +/**@brief External variable declaration to the info structure for AES CMAC mode with a 256-bit key. +* +* @note The variable is defined in the nrf_crypto backend that is +* enabled in the @c sdk_config file. +* +*/ +extern const nrf_crypto_aes_info_t g_nrf_crypto_aes_cmac_256_info; + +/** + * @brief Context type for AES. + * + * @note The size of this type is scaled for the largest AES backend context that is + * enabled in @ref sdk_config. + */ +typedef nrf_crypto_backend_aes_context_t nrf_crypto_aes_context_t; + +/**@brief Function for initializing the AES context. + * + * @param[in] p_context Pointer to the context object. It must be a context type associated + * with the object provided in the p_info parameter or other memory + * that can hold that context type. + * @param[in] p_info Pointer to structure holding information about: selected AES mode, + * key size, and padding. + * @param[in] operation Parameter indicating whether an encrypt (NRF_CRYPTO_ENCRYPT), + * a decrypt (NRF_CRYPTO_DECRYPT) or MAC calculation + * (NRF_CRYPTO_MAC_CALCULATE) operation shall be performed. + * + * @return NRF_SUCCESS on success. + */ +ret_code_t nrf_crypto_aes_init(nrf_crypto_aes_context_t * const p_context, + nrf_crypto_aes_info_t const * const p_info, + nrf_crypto_operation_t operation); + +/**@brief Internal function for uninitializing the AES context. + * + * @param[in] p_context Context object. Must be initialized before the call. + * + * @return NRF_SUCCESS on success. + */ +ret_code_t nrf_crypto_aes_uninit(nrf_crypto_aes_context_t * const p_context); + +/**@brief Function for setting the AES key. + * + * @param[in] p_context Context object. Must be initialized before the call. + * @param[in] p_key Pointer to the AES key. This buffer will be copied and there is no need + * to keep it by the user. + * + * @return NRF_SUCCESS on success. + */ +ret_code_t nrf_crypto_aes_key_set(nrf_crypto_aes_context_t * const p_context, uint8_t * p_key); + +/**@brief Function for setting an AES IV or a counter for AES modes which are using it. + * + * @param[in] p_context Context object. Must be initialized before the call. + * @param[in] p_iv Pointer to a buffer of the IV or a counter. This buffer will be copied + * and there is no need to keep it by the user. + * + * @return NRF_SUCCESS on success. + */ +ret_code_t nrf_crypto_aes_iv_set(nrf_crypto_aes_context_t * const p_context, uint8_t * p_iv); + +/**@brief Function for getting an AES IV or a counter for mode which is supporting it. + * + * @param[in] p_context Context object. Must be initialized before the call. + * @param[out] p_iv Pointer to a buffer of the IV or a counter. + * + * @return NRF_SUCCESS on success. + */ +ret_code_t nrf_crypto_aes_iv_get(nrf_crypto_aes_context_t * const p_context, uint8_t * p_iv); + +/**@brief AES update function for encryption, decryption and MAC calculation. It can be called once + * on the whole data block, or as many times as needed, until all the input data is processed. + * Functions: @ref nrf_crypto_aes_init, @ref nrf_crypto_aes_key_set, and, for some ciphers, + * @ref nrf_crypto_aes_iv_set, must be called before call to this API with the same context. + + * + * @param[in] p_context Context object. Must be initialized before the call. + * @param[in] p_data_in Pointer to the input buffer to the AES. + * @param[in] data_size Size of the data to be processed in bytes. + * For all modes except CFB it must be multiple of 16 bytes. + * @param[out] p_data_out Pointer to the output buffer. + * + * @return NRF_SUCCESS on success. + */ +ret_code_t nrf_crypto_aes_update(nrf_crypto_aes_context_t * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out); + + +/**@brief Function processes the last data block if needed and finalizes the AES operation (ie. adds + * padding) and produces operation results (for MAC operations). + * Functions: @ref nrf_crypto_aes_init, @ref nrf_crypto_aes_key_set, and, for some ciphers, + * @ref nrf_crypto_aes_iv_set, must be called before call to this API with the same context. + * + * Upon successful operation function will deinitialize the context but for some ciphers it will be + * possible to read IV. In order to fully deinitialize context you must call + * @ref nrf_crypto_aes_uninit. + * + * @param[in] p_context Context object. Must be initialized before the call. + * @param[in] p_data_in Pointer to the input buffer to the AES. + * @param[in] data_size Size of the data to be processed in bytes. + * @param[out] p_data_out Pointer to the output buffer. + * When padding is set: + * - The size of p_data_out buffer must have extra space for + * padding. Otherwise, the function will return an error: + * NRF_ERROR_CRYPTO_OUTPUT_LENGTH. + * - When text_size is multiple of 16 bytes, p_text_out must be + * allocated with size equal to text_size + an additional block + * (i.e 16 bytes for padding). + * - When text_size is not a multiple of 16 bytes, p_text_out + * must be allocated with size aligned to the next full 16 + * bytes block (i.e. 1 - 15 bytes for padding). + * @param[in,out] p_data_out_size IN: + * Size of the p_data_out buffer. + * OUT: + * Upon successfull function execution value will be updated + * with number of signifacnt bytes in p_data_out buffer. + * On decryption with padding function will result in a value + * without padded bytes. + * + * @return NRF_SUCCESS on success. + */ +ret_code_t nrf_crypto_aes_finalize(nrf_crypto_aes_context_t * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out, + size_t * p_data_out_size); + + + + +/**@brief AES integrated function for encryption, decryption and MAC calculation. + * It should be called once on the whole data block. + * + * @param[in] p_context Context object. If NULL, memory will be dynamically allocated. + * @param[in] p_info Pointer to structure holding information about: selected AES + * mode, key size, and padding. + * @param[in] operation Parameter indicating whether an encrypt (NRF_CRYPTO_ENCRYPT), + * a decrypt (NRF_CRYPTO_DECRYPT) or MAC calculation + * (NRF_CRYPTO_MAC_CALCULATE) operation shall be performed. + * @param[in] p_key Pointer to the AES key. This buffer will be copied and there is + * no need to keep it by the user. + * @param[in] p_iv Pointer to a buffer of the IV or a counter. This buffer will be + * copied and there is no need to keep it by the user. + * Can be NULL for ECB and CMAC. + * @param[in] p_data_in Pointer to the input buffer to the AES. + * @param[in] data_size Size of the data to be processed in bytes. + * @param[out] p_data_out Pointer to the output buffer. + * When padding is set: + * - The size of p_data_out buffer must have extra space for + * padding. Otherwise, the function will return an error: + * NRF_ERROR_CRYPTO_OUTPUT_LENGTH. + * - When text_size is multiple of 16 bytes, p_text_out must be + * allocated with size equal to text_size + an additional block + * (i.e 16 bytes for padding). + * - When text_size is not a multiple of 16 bytes, p_text_out + * must be allocated with size aligned to the next full 16 + * bytes block (i.e. 1 - 15 bytes for padding). + * @param[in,out] p_data_out_size IN: + * Size of the p_data_out buffer. + * OUT: + * Upon successfull function execution value will be updated + * with number of signifacnt bytes in p_data_out buffer. + * On decryption function will result in a value without padded + * bytes. + * + * @return NRF_SUCCESS on success. + */ +ret_code_t nrf_crypto_aes_crypt(nrf_crypto_aes_context_t * const p_context, + nrf_crypto_aes_info_t const * const p_info, + nrf_crypto_operation_t operation, + uint8_t * p_key, + uint8_t * p_iv, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out, + size_t * p_data_out_size); +#ifdef __cplusplus +} +#endif + +#endif // #if NRF_MODULE_ENABLED(NRF_CRYPTO) || defined(__SDK_DOXYGEN__) + +/** @} */ + +#endif // #ifndef NRF_CRYPTO_AES_H__ diff --git a/components/libraries/crypto/nrf_crypto_aes_backend.h b/components/libraries/crypto/nrf_crypto_aes_backend.h new file mode 100644 index 0000000..8daefa3 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_aes_backend.h @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_AES_BACKEND_H__ +#define NRF_CRYPTO_AES_BACKEND_H__ + +#include "cc310_backend_aes.h" +#include "mbedtls_backend_aes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@internal @brief Fallback type for AES CBC context (if no backend is enabled). + */ +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CBC) +typedef nrf_crypto_aes_internal_context_t nrf_crypto_backend_aes_cbc_context_t; +#endif + +/**@internal @brief Fallback type for AES CFB context (if no backend is enabled). + */ +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CFB) +typedef nrf_crypto_aes_internal_context_t nrf_crypto_backend_aes_cfb_context_t; +#endif + +/**@internal @brief Fallback type for AES CTR context (if no backend is enabled). + */ +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CTR) +typedef nrf_crypto_aes_internal_context_t nrf_crypto_backend_aes_ctr_context_t; +#endif + +/**@internal @brief Fallback type for AES ECB context (if no backend is enabled). + */ +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_AES_ECB) +typedef nrf_crypto_aes_internal_context_t nrf_crypto_backend_aes_ecb_context_t; +#endif + + +/**@internal @brief Fallback type for AES CBC_MAC context (if no backend is enabled). + */ +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CBC_MAC) +typedef nrf_crypto_aes_internal_context_t nrf_crypto_backend_aes_cbc_mac_context_t; +#endif + +/**@internal @brief Fallback type for AES CMAC context (if no backend is enabled). + */ +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CMAC) +typedef nrf_crypto_aes_internal_context_t nrf_crypto_backend_aes_cmac_context_t; +#endif + +/**@internal @brief Fallback type for AES CMAC_PRF128 context (if no backend is enabled). + */ +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_AES_CMAC_PRF128) +typedef nrf_crypto_aes_internal_context_t nrf_crypto_backend_aes_cmac_prf128_context_t; +#endif + + +/** @internal @brief Union holding a AES context. */ +typedef union +{ + nrf_crypto_backend_aes_cbc_context_t cbc_context; /**< @brief Holds context for AES CBC. */ + nrf_crypto_backend_aes_cfb_context_t cfb_context; /**< @brief Holds context for AES CFB. */ + nrf_crypto_backend_aes_ctr_context_t ctr_context; /**< @brief Holds context for AES CFB. */ + nrf_crypto_backend_aes_ecb_context_t ecb_context; /**< @brief Holds context for AES ECB. */ + + nrf_crypto_backend_aes_cbc_mac_context_t cbc_mac_context; /**< @brief Holds context for CBC-MAC. */ + nrf_crypto_backend_aes_cmac_context_t cmac_context; /**< @brief Holds context for CMAC. */ + nrf_crypto_backend_aes_cmac_prf128_context_t cmac_prf128_context; /**< @brief Holds context for CMAC_PRF128. */ +} nrf_crypto_backend_aes_context_t; + +#ifdef __cplusplus +} +#endif + +#endif // NRF_CRYPTO_AES_BACKEND_H__ diff --git a/components/libraries/crypto/nrf_crypto_aes_shared.c b/components/libraries/crypto/nrf_crypto_aes_shared.c new file mode 100644 index 0000000..3927780 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_aes_shared.c @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include "nrf_crypto_error.h" +#include "sdk_config.h" +#include "nrf_crypto_types.h" + + +ret_code_t padding_pkcs7_add(uint8_t * p_padding_buff, + uint8_t * p_message_buff, + uint8_t msg_ending_len) +{ + uint8_t padding_count; + + if ((p_padding_buff == NULL) || (p_message_buff == NULL)) + { + return NRF_ERROR_CRYPTO_INPUT_NULL; + } + + if (msg_ending_len >= NRF_CRYPTO_AES_BLOCK_SIZE) + { + return NRF_ERROR_CRYPTO_INVALID_PARAM; + } + + /* Creating padding buffer in two steps */ + /* step 1 add remaining message */ + memcpy(p_padding_buff, p_message_buff, msg_ending_len); + + /* step 2: add padding */ + padding_count = NRF_CRYPTO_AES_BLOCK_SIZE - msg_ending_len; + p_padding_buff += msg_ending_len; + + for (size_t i = 0; i < padding_count; i++) + { + p_padding_buff[i] = padding_count; + } + + return NRF_SUCCESS; +} + +ret_code_t padding_pkcs7_remove(uint8_t * p_padded_message, + size_t * p_message_len) +{ + if (p_padded_message == NULL) + { + return NRF_ERROR_CRYPTO_INPUT_NULL; + } + if (p_message_len == NULL) + { + return NRF_ERROR_CRYPTO_OUTPUT_NULL; + } + + /* padded_msg_len must be multiple of 16 */ + if ((*p_message_len == 0) || ((*p_message_len & 0x0F) != 0)) + { + return NRF_ERROR_CRYPTO_INVALID_PARAM; + } + + size_t padded_bytes = p_padded_message[*p_message_len - 1]; + + if ((padded_bytes == 0) || (padded_bytes > NRF_CRYPTO_AES_BLOCK_SIZE)) + { + return NRF_ERROR_CRYPTO_AES_INVALID_PADDING; + } + + /* i = 2: 1 for valid string and 1 for already checked *p_message_len - 1 */ + for (size_t i = 2; i < padded_bytes; i++) + { + if (p_padded_message[*p_message_len - i] != padded_bytes) + { + return NRF_ERROR_CRYPTO_AES_INVALID_PADDING; + } + } + + *p_message_len -= padded_bytes; + + return NRF_SUCCESS; +} + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) + diff --git a/components/libraries/crypto/nrf_crypto_aes_shared.h b/components/libraries/crypto/nrf_crypto_aes_shared.h new file mode 100644 index 0000000..83d7456 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_aes_shared.h @@ -0,0 +1,218 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_AES_SHARED_H__ +#define NRF_CRYPTO_AES_SHARED_H__ + +/** @file + * + * @defgroup nrf_crypto_aes AES related functions + * @{ + * @ingroup nrf_crypto + * + * @brief Provides AES related functionality through nrf_crypto. + */ + +#include +#include "nrf_crypto_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@internal @brief Magic value to signal that the nrf_crypto_hash context structure is initialized. + */ +#define NRF_CRYPTO_AES_INIT_MAGIC_VALUE (0x53454163) // ASCII "cAES" +#define NRF_CRYPTO_AES_UNINIT_MAGIC_VALUE (0x63414553) // ASCII "SEAc" + +#define NRF_CRYPTO_MBEDTLS_AES_IV_SIZE (16) + + +/** @internal @brief Enumeration of supported modes of operation in nrf_crypto_aes. + */ +typedef enum +{ + NRF_CRYPTO_AES_MODE_CBC, // supported by: MBEDTLS & CC310 + NRF_CRYPTO_AES_MODE_CBC_PAD_PCKS7, // supported by: MBEDTLS & CC310 + NRF_CRYPTO_AES_MODE_CFB, // supported by: MBEDTLS + NRF_CRYPTO_AES_MODE_CTR, // supported by: MBEDTLS & CC310 + NRF_CRYPTO_AES_MODE_ECB, // supported by: MBEDTLS & CC310 + NRF_CRYPTO_AES_MODE_ECB_PAD_PCKS7, // supported by: MBEDTLS & CC310 + + // Authentication modes + NRF_CRYPTO_AES_MODE_CBC_MAC, // supported by: MBEDTLS & CC310 + NRF_CRYPTO_AES_MODE_CBC_MAC_PAD_PCKS7, // supported by: MBEDTLS & CC310 + NRF_CRYPTO_AES_MODE_CMAC, // supported by: MBEDTLS & CC310 +} nrf_crypto_aes_mode_t; + +/**@internal @brief Type declaration to perform AES initialization in the nrf_crypto backend. + * + * This is internal API. See @ref nrf_crypto_aes_init for documentation. + */ +typedef ret_code_t (*aes_init_fn_t)(void * const p_context, nrf_crypto_operation_t operation); + +/**@internal @brief Type declaration to perform AES uninitialization in the nrf_crypto backend. + * + * This is internal API. See @ref nrf_crypto_aes_uninit for documentation. + */ +typedef ret_code_t (*aes_uninit_fn_t)(void * const p_context); + +/**@internal @brief Type declaration to set an AES key in the nrf_crypto backend. + * + * This is internal API. See @ref nrf_crypto_aes_key_set for documentation. + */ +typedef ret_code_t (*aes_key_set_fn_t)(void * const p_context, uint8_t * p_key); + +/**@internal @brief Type declaration to set an AES IV in the nrf_crypto backend. + * + * This is internal API. See @ref nrf_crypto_aes_iv_set for documentation. + */ +typedef ret_code_t (*aes_iv_set_fn_t)(void * const p_context, uint8_t * p_iv); + +/**@internal @brief Type declaration to get an AES IV in the nrf_crypto backend. + * + * This is internal API. See @ref nrf_crypto_aes_iv_get for documentation. + */ +typedef ret_code_t (*aes_iv_get_fn_t)(void * const p_context, uint8_t * p_iv); + +/**@internal @brief Type declaration to perform AES block operation in the nrf_crypto backend. + * + * This is internal API. See @ref nrf_crypto_aes_update for documentation. + */ +typedef ret_code_t (*aes_update_fn_t)(void * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out); + +/**@internal @brief Type declaration to finalize AES operation in the nrf_crypto backend. + * + * This is internal API. See @ref nrf_crypto_aes_finalize for documentation. + */ +typedef ret_code_t (*aes_finalize_fn_t)(void * const p_context, + uint8_t * p_data_in, + size_t data_size, + uint8_t * p_data_out, + size_t * p_data_out_size); + +/**@internal @brief Type declaration for an nrf_crypto_aes info structure. + * + * @details This structure contains the calling interface and any metadata required + * to call the nrf_crypto_aes API functions. + */ +typedef struct +{ + nrf_crypto_aes_mode_t const mode; + nrf_crypto_key_size_id_t const key_size; + size_t const context_size; + + aes_init_fn_t const init_fn; + aes_uninit_fn_t const uninit_fn; + aes_key_set_fn_t const key_set_fn; + aes_iv_set_fn_t const iv_set_fn; + aes_iv_get_fn_t const iv_get_fn; + aes_update_fn_t const update_fn; + aes_finalize_fn_t const finalize_fn; +} nrf_crypto_aes_info_t; + +/**@internal @brief Type declaration of internal representation of an AES context structure. + * + * @details This is an internal type that should not be used directly. + */ +typedef struct +{ + uint32_t init_value; + nrf_crypto_aes_info_t const * p_info; +} nrf_crypto_aes_internal_context_t; + + +/**@internal @brief Type declaration of internal representation of an AES backend context structure. + * with initialization vector. + * + * @details This is an internal type that should not be used directly. + */ +typedef struct +{ + nrf_crypto_operation_t operation; + + uint8_t iv[NRF_CRYPTO_MBEDTLS_AES_IV_SIZE]; // space for 128-bit initialization vector +} nrf_crypto_backend_aes_ctx_t; + +/**@internal @brief Type declaration of internal representation of an AES backend context structure + * without initialization vector. + * + * @details This is an internal type that should not be used directly. + */ +typedef struct +{ + nrf_crypto_operation_t operation; +} nrf_crypto_backend_no_iv_aes_ctx_t; + + +/**@internal @brief Function copies remainders (msg_ending_len) from p_message_buff to the + * p_padding_buff. Next it adds pkcs7-padding to have a 16 bytes p_padding_buff. + * + * @param[in] p_padding_buff Pointer the buffer with padded message. + * @param[in] p_message_buff Pointer to the buffer with message that must be padded. + * @param[in] msg_ending_len Message remainders length. + * + */ +ret_code_t padding_pkcs7_add(uint8_t * p_padding_buff, + uint8_t * p_message_buff, + uint8_t msg_ending_len); + + +/**@internal @brief Function calculate message length without padding. + * + * @param[in] p_padded_message Pointer the buffer with padded message. + * @param[in/out] p_message_len IN: padded message length + * OUT: message length without padding + */ +ret_code_t padding_pkcs7_remove(uint8_t * p_padded_message, + size_t * p_message_len); + + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif // #ifndef NRF_CRYPTO_AES_SHARED_H__ diff --git a/components/libraries/crypto/nrf_crypto_ecc.c b/components/libraries/crypto/nrf_crypto_ecc.c new file mode 100644 index 0000000..e6cf486 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_ecc.c @@ -0,0 +1,1315 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include + +#include "nordic_common.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_mem.h" +#include "nrf_crypto_ecc.h" +#include "app_util.h" +#include "sdk_macros.h" + + +#if NRF_CRYPTO_ECC_ENABLED + + +#if NRF_CRYPTO_ECC_IMPLEMENTED_CURVES_COUNT > 1 + + +static const nrf_crypto_backend_ecc_key_pair_generate_fn_t key_pair_generate_impl[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + nrf_crypto_backend_secp160r1_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + nrf_crypto_backend_secp160r2_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + nrf_crypto_backend_secp192r1_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + nrf_crypto_backend_secp224r1_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + nrf_crypto_backend_secp256r1_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + nrf_crypto_backend_secp384r1_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + nrf_crypto_backend_secp521r1_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + nrf_crypto_backend_secp160k1_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + nrf_crypto_backend_secp192k1_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + nrf_crypto_backend_secp224k1_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + nrf_crypto_backend_secp256k1_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + nrf_crypto_backend_bp256r1_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + nrf_crypto_backend_bp384r1_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + nrf_crypto_backend_bp512r1_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + nrf_crypto_backend_curve25519_key_pair_generate, +#endif +#if NRF_CRYPTO_ECC_ED25519_ENABLED + nrf_crypto_backend_ed25519_key_pair_generate, +#endif +}; + + +static const uint16_t key_pair_generate_context_size[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + NRF_CRYPTO_BACKEND_SECP160R1_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + NRF_CRYPTO_BACKEND_SECP160R2_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + NRF_CRYPTO_BACKEND_SECP192R1_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + NRF_CRYPTO_BACKEND_SECP224R1_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + NRF_CRYPTO_BACKEND_SECP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + NRF_CRYPTO_BACKEND_SECP384R1_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + NRF_CRYPTO_BACKEND_SECP521R1_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + NRF_CRYPTO_BACKEND_SECP160K1_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + NRF_CRYPTO_BACKEND_SECP192K1_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + NRF_CRYPTO_BACKEND_SECP224K1_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + NRF_CRYPTO_BACKEND_SECP256K1_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + NRF_CRYPTO_BACKEND_BP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + NRF_CRYPTO_BACKEND_BP384R1_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + NRF_CRYPTO_BACKEND_BP512R1_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + NRF_CRYPTO_BACKEND_CURVE25519_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_ED25519_ENABLED + NRF_CRYPTO_BACKEND_ED25519_KEY_PAIR_GENERATE_CONTEXT_SIZE, +#endif +}; + + +static const nrf_crypto_backend_ecc_public_key_calculate_fn_t public_key_calculate_impl[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + nrf_crypto_backend_secp160r1_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + nrf_crypto_backend_secp160r2_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + nrf_crypto_backend_secp192r1_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + nrf_crypto_backend_secp224r1_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + nrf_crypto_backend_secp256r1_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + nrf_crypto_backend_secp384r1_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + nrf_crypto_backend_secp521r1_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + nrf_crypto_backend_secp160k1_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + nrf_crypto_backend_secp192k1_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + nrf_crypto_backend_secp224k1_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + nrf_crypto_backend_secp256k1_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + nrf_crypto_backend_bp256r1_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + nrf_crypto_backend_bp384r1_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + nrf_crypto_backend_bp512r1_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + nrf_crypto_backend_curve25519_public_key_calculate, +#endif +#if NRF_CRYPTO_ECC_ED25519_ENABLED + nrf_crypto_backend_ed25519_public_key_calculate, +#endif +}; + + +static const uint16_t public_key_calculate_context_size[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + NRF_CRYPTO_BACKEND_SECP160R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + NRF_CRYPTO_BACKEND_SECP160R2_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + NRF_CRYPTO_BACKEND_SECP192R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + NRF_CRYPTO_BACKEND_SECP224R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + NRF_CRYPTO_BACKEND_SECP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + NRF_CRYPTO_BACKEND_SECP384R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + NRF_CRYPTO_BACKEND_SECP521R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + NRF_CRYPTO_BACKEND_SECP160K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + NRF_CRYPTO_BACKEND_SECP192K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + NRF_CRYPTO_BACKEND_SECP224K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + NRF_CRYPTO_BACKEND_SECP256K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + NRF_CRYPTO_BACKEND_BP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + NRF_CRYPTO_BACKEND_BP384R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + NRF_CRYPTO_BACKEND_BP512R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + NRF_CRYPTO_BACKEND_CURVE25519_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_ED25519_ENABLED + NRF_CRYPTO_BACKEND_ED25519_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE, +#endif +}; + + +static const nrf_crypto_backend_ecc_private_key_from_raw_fn_t private_key_from_raw_impl[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + nrf_crypto_backend_secp160r1_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + nrf_crypto_backend_secp160r2_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + nrf_crypto_backend_secp192r1_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + nrf_crypto_backend_secp224r1_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + nrf_crypto_backend_secp256r1_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + nrf_crypto_backend_secp384r1_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + nrf_crypto_backend_secp521r1_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + nrf_crypto_backend_secp160k1_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + nrf_crypto_backend_secp192k1_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + nrf_crypto_backend_secp224k1_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + nrf_crypto_backend_secp256k1_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + nrf_crypto_backend_bp256r1_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + nrf_crypto_backend_bp384r1_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + nrf_crypto_backend_bp512r1_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + nrf_crypto_backend_curve25519_private_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_ED25519_ENABLED + nrf_crypto_backend_ed25519_private_key_from_raw, +#endif +}; + + +static const nrf_crypto_backend_ecc_private_key_to_raw_fn_t private_key_to_raw_impl[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + nrf_crypto_backend_secp160r1_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + nrf_crypto_backend_secp160r2_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + nrf_crypto_backend_secp192r1_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + nrf_crypto_backend_secp224r1_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + nrf_crypto_backend_secp256r1_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + nrf_crypto_backend_secp384r1_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + nrf_crypto_backend_secp521r1_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + nrf_crypto_backend_secp160k1_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + nrf_crypto_backend_secp192k1_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + nrf_crypto_backend_secp224k1_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + nrf_crypto_backend_secp256k1_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + nrf_crypto_backend_bp256r1_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + nrf_crypto_backend_bp384r1_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + nrf_crypto_backend_bp512r1_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + nrf_crypto_backend_curve25519_private_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_ED25519_ENABLED + nrf_crypto_backend_ed25519_private_key_to_raw, +#endif +}; + + +static const nrf_crypto_backend_ecc_public_key_from_raw_fn_t public_key_from_raw_impl[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + nrf_crypto_backend_secp160r1_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + nrf_crypto_backend_secp160r2_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + nrf_crypto_backend_secp192r1_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + nrf_crypto_backend_secp224r1_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + nrf_crypto_backend_secp256r1_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + nrf_crypto_backend_secp384r1_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + nrf_crypto_backend_secp521r1_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + nrf_crypto_backend_secp160k1_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + nrf_crypto_backend_secp192k1_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + nrf_crypto_backend_secp224k1_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + nrf_crypto_backend_secp256k1_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + nrf_crypto_backend_bp256r1_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + nrf_crypto_backend_bp384r1_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + nrf_crypto_backend_bp512r1_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + nrf_crypto_backend_curve25519_public_key_from_raw, +#endif +#if NRF_CRYPTO_ECC_ED25519_ENABLED + nrf_crypto_backend_ed25519_public_key_from_raw, +#endif +}; + + +static const nrf_crypto_backend_ecc_public_key_to_raw_fn_t public_key_to_raw_impl[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + nrf_crypto_backend_secp160r1_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + nrf_crypto_backend_secp160r2_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + nrf_crypto_backend_secp192r1_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + nrf_crypto_backend_secp224r1_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + nrf_crypto_backend_secp256r1_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + nrf_crypto_backend_secp384r1_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + nrf_crypto_backend_secp521r1_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + nrf_crypto_backend_secp160k1_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + nrf_crypto_backend_secp192k1_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + nrf_crypto_backend_secp224k1_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + nrf_crypto_backend_secp256k1_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + nrf_crypto_backend_bp256r1_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + nrf_crypto_backend_bp384r1_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + nrf_crypto_backend_bp512r1_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + nrf_crypto_backend_curve25519_public_key_to_raw, +#endif +#if NRF_CRYPTO_ECC_ED25519_ENABLED + nrf_crypto_backend_ed25519_public_key_to_raw, +#endif +}; + + +static const nrf_crypto_backend_ecc_key_free_fn_t private_key_free_impl[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + nrf_crypto_backend_secp160r1_private_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + nrf_crypto_backend_secp160r2_private_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + nrf_crypto_backend_secp192r1_private_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + nrf_crypto_backend_secp224r1_private_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + nrf_crypto_backend_secp256r1_private_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + nrf_crypto_backend_secp384r1_private_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + nrf_crypto_backend_secp521r1_private_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + nrf_crypto_backend_secp160k1_private_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + nrf_crypto_backend_secp192k1_private_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + nrf_crypto_backend_secp224k1_private_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + nrf_crypto_backend_secp256k1_private_key_free, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + nrf_crypto_backend_bp256r1_private_key_free, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + nrf_crypto_backend_bp384r1_private_key_free, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + nrf_crypto_backend_bp512r1_private_key_free, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + nrf_crypto_backend_curve25519_private_key_free, +#endif +#if NRF_CRYPTO_ECC_ED25519_ENABLED + nrf_crypto_backend_ed25519_private_key_free, +#endif +}; + + +static const nrf_crypto_backend_ecc_key_free_fn_t public_key_free_impl[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + nrf_crypto_backend_secp160r1_public_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + nrf_crypto_backend_secp160r2_public_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + nrf_crypto_backend_secp192r1_public_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + nrf_crypto_backend_secp224r1_public_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + nrf_crypto_backend_secp256r1_public_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + nrf_crypto_backend_secp384r1_public_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + nrf_crypto_backend_secp521r1_public_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + nrf_crypto_backend_secp160k1_public_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + nrf_crypto_backend_secp192k1_public_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + nrf_crypto_backend_secp224k1_public_key_free, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + nrf_crypto_backend_secp256k1_public_key_free, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + nrf_crypto_backend_bp256r1_public_key_free, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + nrf_crypto_backend_bp384r1_public_key_free, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + nrf_crypto_backend_bp512r1_public_key_free, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + nrf_crypto_backend_curve25519_public_key_free, +#endif +#if NRF_CRYPTO_ECC_ED25519_ENABLED + nrf_crypto_backend_ed25519_public_key_free, +#endif +}; + + +#define BACKEND_IMPL_GET(table, curve_type) (table)[(uint32_t)(curve_type)] + + +#else + + +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_secp160r1_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_secp160r1_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_secp160r1_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_secp160r1_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_secp160r1_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_secp160r1_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_secp160r1_private_key_free +#define public_key_free_impl nrf_crypto_backend_secp160r1_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_SECP160R1_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_SECP160R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP160R2_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_secp160r2_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_secp160r2_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_secp160r2_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_secp160r2_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_secp160r2_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_secp160r2_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_secp160r2_private_key_free +#define public_key_free_impl nrf_crypto_backend_secp160r2_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_SECP160R2_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_SECP160R2_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP192R1_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_secp192r1_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_secp192r1_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_secp192r1_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_secp192r1_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_secp192r1_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_secp192r1_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_secp192r1_private_key_free +#define public_key_free_impl nrf_crypto_backend_secp192r1_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_SECP192R1_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_SECP192R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP224R1_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_secp224r1_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_secp224r1_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_secp224r1_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_secp224r1_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_secp224r1_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_secp224r1_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_secp224r1_private_key_free +#define public_key_free_impl nrf_crypto_backend_secp224r1_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_SECP224R1_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_SECP224R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP256R1_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_secp256r1_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_secp256r1_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_secp256r1_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_secp256r1_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_secp256r1_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_secp256r1_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_secp256r1_private_key_free +#define public_key_free_impl nrf_crypto_backend_secp256r1_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_SECP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_SECP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP384R1_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_secp384r1_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_secp384r1_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_secp384r1_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_secp384r1_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_secp384r1_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_secp384r1_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_secp384r1_private_key_free +#define public_key_free_impl nrf_crypto_backend_secp384r1_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_SECP384R1_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_SECP384R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP521R1_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_secp521r1_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_secp521r1_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_secp521r1_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_secp521r1_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_secp521r1_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_secp521r1_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_secp521r1_private_key_free +#define public_key_free_impl nrf_crypto_backend_secp521r1_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_SECP521R1_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_SECP521R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP160K1_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_secp160k1_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_secp160k1_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_secp160k1_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_secp160k1_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_secp160k1_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_secp160k1_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_secp160k1_private_key_free +#define public_key_free_impl nrf_crypto_backend_secp160k1_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_SECP160K1_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_SECP160K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP192K1_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_secp192k1_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_secp192k1_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_secp192k1_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_secp192k1_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_secp192k1_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_secp192k1_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_secp192k1_private_key_free +#define public_key_free_impl nrf_crypto_backend_secp192k1_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_SECP192K1_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_SECP192K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP224K1_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_secp224k1_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_secp224k1_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_secp224k1_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_secp224k1_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_secp224k1_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_secp224k1_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_secp224k1_private_key_free +#define public_key_free_impl nrf_crypto_backend_secp224k1_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_SECP224K1_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_SECP224K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP256K1_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_secp256k1_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_secp256k1_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_secp256k1_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_secp256k1_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_secp256k1_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_secp256k1_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_secp256k1_private_key_free +#define public_key_free_impl nrf_crypto_backend_secp256k1_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_SECP256K1_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_SECP256K1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_BP256R1_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_bp256r1_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_bp256r1_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_bp256r1_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_bp256r1_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_bp256r1_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_bp256r1_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_bp256r1_private_key_free +#define public_key_free_impl nrf_crypto_backend_bp256r1_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_BP256R1_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_BP256R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_BP384R1_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_bp384r1_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_bp384r1_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_bp384r1_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_bp384r1_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_bp384r1_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_bp384r1_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_bp384r1_private_key_free +#define public_key_free_impl nrf_crypto_backend_bp384r1_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_BP384R1_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_BP384R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_BP512R1_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_bp512r1_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_bp512r1_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_bp512r1_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_bp512r1_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_bp512r1_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_bp512r1_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_bp512r1_private_key_free +#define public_key_free_impl nrf_crypto_backend_bp512r1_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_BP512R1_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_BP512R1_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_CURVE25519_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_curve25519_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_curve25519_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_curve25519_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_curve25519_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_curve25519_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_curve25519_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_curve25519_private_key_free +#define public_key_free_impl nrf_crypto_backend_curve25519_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_CURVE25519_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_CURVE25519_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_ED25519_ENABLED +#define key_pair_generate_impl nrf_crypto_backend_ed25519_key_pair_generate +#define public_key_calculate_impl nrf_crypto_backend_ed25519_public_key_calculate +#define private_key_from_raw_impl nrf_crypto_backend_ed25519_private_key_from_raw +#define private_key_to_raw_impl nrf_crypto_backend_ed25519_private_key_to_raw +#define public_key_from_raw_impl nrf_crypto_backend_ed25519_public_key_from_raw +#define public_key_to_raw_impl nrf_crypto_backend_ed25519_public_key_to_raw +#define private_key_free_impl nrf_crypto_backend_ed25519_private_key_free +#define public_key_free_impl nrf_crypto_backend_ed25519_public_key_free +#define key_pair_generate_context_size \ + NRF_CRYPTO_BACKEND_ED25519_KEY_PAIR_GENERATE_CONTEXT_SIZE +#define public_key_calculate_context_size \ + NRF_CRYPTO_BACKEND_ED25519_PUBLIC_KEY_CALCULATE_CONTEXT_SIZE +#else +#define key_pair_generate_impl NULL +#define public_key_calculate_impl NULL +#define private_key_from_raw_impl NULL +#define private_key_to_raw_impl NULL +#define public_key_from_raw_impl NULL +#define public_key_to_raw_impl NULL +#define private_key_free_impl NULL +#define public_key_free_impl NULL +#define key_pair_generate_context_size 0 +#define public_key_calculate_context_size 0 +#endif + + +#define BACKEND_IMPL_GET(function, curve_type) (function) + + +#endif + + +ret_code_t nrf_crypto_internal_ecc_key_output_prepare( + nrf_crypto_ecc_curve_info_t const * p_curve_info, + nrf_crypto_internal_ecc_key_header_t * p_key_header) +{ + // Check NULL pointers + VERIFY_TRUE(p_curve_info != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + VERIFY_TRUE(p_key_header != NULL, NRF_ERROR_CRYPTO_OUTPUT_NULL); + + // Clear init value to indicate that this key is not valid yet. + p_key_header->init_value = 0; + // Save curve info inside the header + p_key_header->p_info = p_curve_info; + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_internal_ecc_key_input_check( + nrf_crypto_internal_ecc_key_header_t const * p_key_header, + uint32_t init_value) +{ + // Check NULL pointer + VERIFY_TRUE(p_key_header != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + // Check init value + VERIFY_TRUE(p_key_header->init_value == init_value, NRF_ERROR_CRYPTO_ECC_KEY_NOT_INITIALIZED); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_internal_ecc_raw_output_prepare( + uint8_t * p_raw_data, + size_t * p_raw_data_size, + size_t expected_size) +{ + // Check NULL pointer + VERIFY_TRUE(p_raw_data != NULL, NRF_ERROR_CRYPTO_OUTPUT_NULL); + + if (p_raw_data_size != NULL) // User can provide NULL as p_raw_data_size to skip size checking + { + // Check if data fits into buffer + VERIFY_TRUE(*p_raw_data_size >= expected_size, NRF_ERROR_CRYPTO_OUTPUT_LENGTH); + // Provide actual data size + *p_raw_data_size = expected_size; + } + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_internal_ecc_raw_input_check( + uint8_t const * p_raw_data, + size_t raw_data_size, + size_t expected_size) +{ + VERIFY_TRUE(p_raw_data != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + VERIFY_TRUE(raw_data_size == expected_size, NRF_ERROR_CRYPTO_INPUT_LENGTH); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_ecc_key_pair_generate( + nrf_crypto_ecc_key_pair_generate_context_t * p_context, + nrf_crypto_ecc_curve_info_t const * p_curve_info, + nrf_crypto_ecc_private_key_t * p_private_key, + nrf_crypto_ecc_public_key_t * p_public_key) +{ + ret_code_t result; + void * p_allocated_context = NULL; + nrf_crypto_backend_ecc_key_pair_generate_fn_t backend_implementation; + size_t context_size; + + // Get pointer to header for each key + nrf_crypto_internal_ecc_key_header_t * p_private_key_header = + (nrf_crypto_internal_ecc_key_header_t *)p_private_key; + nrf_crypto_internal_ecc_key_header_t * p_public_key_header = + (nrf_crypto_internal_ecc_key_header_t *)p_public_key; + + // Check and prepare parameters + result = nrf_crypto_internal_ecc_key_output_prepare(p_curve_info, p_private_key_header); + VERIFY_SUCCESS(result); + result = nrf_crypto_internal_ecc_key_output_prepare(p_curve_info, p_public_key_header); + VERIFY_SUCCESS(result); + + // Get backend specific information + backend_implementation = BACKEND_IMPL_GET(key_pair_generate_impl, p_curve_info->curve_type); + context_size = BACKEND_IMPL_GET(key_pair_generate_context_size, p_curve_info->curve_type); + VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE); + + // Allocate context if not provided + if (p_context == NULL && context_size > 0) + { + p_allocated_context = NRF_CRYPTO_ALLOC(context_size); + VERIFY_TRUE(p_allocated_context != NULL, NRF_ERROR_CRYPTO_ALLOC_FAILED); + p_context = p_allocated_context; + } + + // Execute backend implementation + result = backend_implementation(p_context, p_private_key, p_public_key); + + // Set init values to indicate valid key + if (result == NRF_SUCCESS) + { + p_private_key_header->init_value = NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE; + p_public_key_header->init_value = NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE; + } + + // Deallocate context if allocated + if (p_allocated_context != NULL) + { + NRF_CRYPTO_FREE(p_allocated_context); + } + + return result; +} + + +ret_code_t nrf_crypto_ecc_public_key_calculate( + nrf_crypto_ecc_public_key_calculate_context_t * p_context, + nrf_crypto_ecc_private_key_t const * p_private_key, + nrf_crypto_ecc_public_key_t * p_public_key) +{ + ret_code_t result; + void * p_allocated_context = NULL; + nrf_crypto_backend_ecc_public_key_calculate_fn_t backend_implementation; + size_t context_size; + nrf_crypto_ecc_curve_info_t const * p_info; + + // Get pointer to header for each key + nrf_crypto_internal_ecc_key_header_t const * p_private_key_header = + (nrf_crypto_internal_ecc_key_header_t const *)p_private_key; + nrf_crypto_internal_ecc_key_header_t * p_public_key_header = + (nrf_crypto_internal_ecc_key_header_t *)p_public_key; + + // Check and prepare parameters + result = nrf_crypto_internal_ecc_key_input_check( + p_private_key_header, + NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE); + VERIFY_SUCCESS(result); + p_info = p_private_key_header->p_info; + result = nrf_crypto_internal_ecc_key_output_prepare(p_info, p_public_key_header); + VERIFY_SUCCESS(result); + + // Get backend specific information + backend_implementation = BACKEND_IMPL_GET(public_key_calculate_impl, p_info->curve_type); + context_size = BACKEND_IMPL_GET(public_key_calculate_context_size, p_info->curve_type); + VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE); + + // Allocate context if not provided + if (p_context == NULL && context_size > 0) + { + p_allocated_context = NRF_CRYPTO_ALLOC(context_size); + VERIFY_TRUE(p_allocated_context != NULL, NRF_ERROR_CRYPTO_ALLOC_FAILED); + p_context = p_allocated_context; + } + + // Execute backend implementation + result = backend_implementation(p_context, p_private_key, p_public_key); + + // Set init values to indicate valid key + if (result == NRF_SUCCESS) + { + p_public_key_header->init_value = NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE; + } + + // Deallocate context if allocated + if (p_allocated_context != NULL) + { + NRF_CRYPTO_FREE(p_allocated_context); + } + + return result; +} + + +ret_code_t nrf_crypto_ecc_private_key_from_raw( + nrf_crypto_ecc_curve_info_t const * p_curve_info, + nrf_crypto_ecc_private_key_t * p_private_key, + uint8_t const * p_raw_data, + size_t raw_data_size) +{ + ret_code_t result; + nrf_crypto_backend_ecc_private_key_from_raw_fn_t backend_implementation; + + // Get pointer to header + nrf_crypto_internal_ecc_key_header_t * p_private_key_header = + (nrf_crypto_internal_ecc_key_header_t *)p_private_key; + + // Check and prepare parameters + result = nrf_crypto_internal_ecc_key_output_prepare(p_curve_info, + p_private_key_header); + VERIFY_SUCCESS(result); + result = nrf_crypto_internal_ecc_raw_input_check(p_raw_data, + raw_data_size, + p_curve_info->raw_private_key_size); + VERIFY_SUCCESS(result); + + // Get backend specific information + backend_implementation = BACKEND_IMPL_GET(private_key_from_raw_impl, p_curve_info->curve_type); + VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE); + + // Execute backend implementation + result = backend_implementation(p_private_key, p_raw_data); + + // Set init value to indicate valid key + if (result == NRF_SUCCESS) + { + p_private_key_header->init_value = NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE; + } + + return result; +} + + +ret_code_t nrf_crypto_ecc_private_key_to_raw( + nrf_crypto_ecc_private_key_t const * p_private_key, + uint8_t * p_raw_data, + size_t * p_raw_data_size) +{ + ret_code_t result; + nrf_crypto_ecc_curve_info_t const * p_info; + nrf_crypto_backend_ecc_private_key_to_raw_fn_t backend_implementation; + + // Get pointer to header + nrf_crypto_internal_ecc_key_header_t const * p_private_key_header = + (nrf_crypto_internal_ecc_key_header_t const *)p_private_key; + + // Check and prepare parameters + result = nrf_crypto_internal_ecc_key_input_check( + p_private_key_header, + NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE); + VERIFY_SUCCESS(result); + p_info = p_private_key_header->p_info; + result = nrf_crypto_internal_ecc_raw_output_prepare(p_raw_data, + p_raw_data_size, + p_info->raw_private_key_size); + VERIFY_SUCCESS(result); + + // Get backend specific information + backend_implementation = BACKEND_IMPL_GET(private_key_to_raw_impl, p_info->curve_type); + VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE); + + // Execute backend implementation + result = backend_implementation(p_private_key, p_raw_data); + + return result; +} + + +ret_code_t nrf_crypto_ecc_public_key_from_raw( + nrf_crypto_ecc_curve_info_t const * p_curve_info, + nrf_crypto_ecc_public_key_t * p_public_key, + uint8_t const * p_raw_data, + size_t raw_data_size) +{ + ret_code_t result; + nrf_crypto_backend_ecc_private_key_from_raw_fn_t backend_implementation; + + // Get pointer to header + nrf_crypto_internal_ecc_key_header_t * p_public_key_header = + (nrf_crypto_internal_ecc_key_header_t *)p_public_key; + + // Check and prepare parameters + result = nrf_crypto_internal_ecc_key_output_prepare(p_curve_info, + p_public_key_header); + VERIFY_SUCCESS(result); + result = nrf_crypto_internal_ecc_raw_input_check(p_raw_data, + raw_data_size, + p_curve_info->raw_public_key_size); + VERIFY_SUCCESS(result); + + // Get backend specific information + backend_implementation = BACKEND_IMPL_GET(public_key_from_raw_impl, p_curve_info->curve_type); + VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE); + + // Execute backend implementation + result = backend_implementation(p_public_key, p_raw_data); + + // Set init value to indicate valid key + if (result == NRF_SUCCESS) + { + p_public_key_header->init_value = NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE; + } + + return result; +} + + +ret_code_t nrf_crypto_ecc_public_key_to_raw( + nrf_crypto_ecc_public_key_t const * p_public_key, + uint8_t * p_raw_data, + size_t * p_raw_data_size) +{ + ret_code_t result; + nrf_crypto_ecc_curve_info_t const * p_info; + nrf_crypto_backend_ecc_public_key_to_raw_fn_t backend_implementation; + + // Get pointer to header + nrf_crypto_internal_ecc_key_header_t const * p_public_key_header = + (nrf_crypto_internal_ecc_key_header_t const *)p_public_key; + + // Check and prepare parameters + result = nrf_crypto_internal_ecc_key_input_check( + p_public_key_header, + NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE); + VERIFY_SUCCESS(result); + p_info = p_public_key_header->p_info; + result = nrf_crypto_internal_ecc_raw_output_prepare(p_raw_data, + p_raw_data_size, + p_info->raw_public_key_size); + VERIFY_SUCCESS(result); + + // Get backend specific information + backend_implementation = BACKEND_IMPL_GET(public_key_to_raw_impl, p_info->curve_type); + VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE); + + // Execute backend implementation + result = backend_implementation(p_public_key, p_raw_data); + + return result; +} + + +ret_code_t nrf_crypto_ecc_private_key_free( + nrf_crypto_ecc_private_key_t * p_private_key) +{ + ret_code_t result; + nrf_crypto_ecc_curve_info_t const * p_info; + nrf_crypto_backend_ecc_key_free_fn_t backend_implementation; + + // Get pointer to header + nrf_crypto_internal_ecc_key_header_t * p_private_key_header = + (nrf_crypto_internal_ecc_key_header_t *)p_private_key; + + // Check and prepare parameters + result = nrf_crypto_internal_ecc_key_input_check( + p_private_key_header, + NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE); + VERIFY_SUCCESS(result); + p_info = p_private_key_header->p_info; + + UNUSED_PARAMETER(p_info); // Is some situations BACKEND_IMPL_GET() macro may not use second parameter + + // Get backend specific information + backend_implementation = BACKEND_IMPL_GET(private_key_free_impl, p_info->curve_type); + + if (backend_implementation != NULL) + { + // Execute backend implementation + result = backend_implementation(p_private_key); + } + else + { + // Free is not implemented by the backend, so nothing have to deallocated. + result = NRF_SUCCESS; + } + + // Clear init value to indicate invalid key + p_private_key_header->init_value = 0; + + return result; +} + + +ret_code_t nrf_crypto_ecc_public_key_free( + nrf_crypto_ecc_public_key_t * p_public_key) +{ + ret_code_t result; + nrf_crypto_ecc_curve_info_t const * p_info; + nrf_crypto_backend_ecc_key_free_fn_t backend_implementation; + + // Get pointer to header + nrf_crypto_internal_ecc_key_header_t * p_public_key_header = + (nrf_crypto_internal_ecc_key_header_t *)p_public_key; + + // Check and prepare parameters + result = nrf_crypto_internal_ecc_key_input_check( + p_public_key_header, + NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE); + VERIFY_SUCCESS(result); + p_info = p_public_key_header->p_info; + + UNUSED_PARAMETER(p_info); // Is some situations BACKEND_IMPL_GET() macro may not use second parameter + + // Get backend specific information + backend_implementation = BACKEND_IMPL_GET(public_key_free_impl, p_info->curve_type); + + if (backend_implementation != NULL) + { + // Execute backend implementation + result = backend_implementation(p_public_key); + } + else + { + // Free is not implemented by the backend, so nothing have to deallocated. + result = NRF_SUCCESS; + } + + // Clear init value to indicate invalid key + p_public_key_header->init_value = 0; + + return result; +} + + +ret_code_t nrf_crypto_ecc_curve_info_get( + void const * p_key, + nrf_crypto_ecc_curve_info_t const ** pp_curve_info) +{ + ret_code_t result; + + // Get pointer to header + nrf_crypto_internal_ecc_key_header_t const * p_key_header = + (nrf_crypto_internal_ecc_key_header_t const *)p_key; + + // Check and prepare parameters + VERIFY_TRUE(pp_curve_info != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + result = nrf_crypto_internal_ecc_key_input_check( + p_key_header, + NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE); + if (result != NRF_SUCCESS) + { + // p_key can be private or public key, so check second case here + result = nrf_crypto_internal_ecc_key_input_check( + p_key_header, + NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE); + } + VERIFY_SUCCESS(result); + + // Write output parameter + *pp_curve_info = p_key_header->p_info; + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_ecc_byte_order_invert( + nrf_crypto_ecc_curve_info_t const * p_curve_info, + uint8_t const * p_raw_input, + uint8_t * p_raw_output, + size_t raw_data_size) +{ + uint8_t temp; + size_t from_index; + size_t to_index; + size_t integer_size; + + if (p_curve_info == NULL) + { + integer_size = raw_data_size; + } + else + { + integer_size = p_curve_info->raw_private_key_size; + } + + VERIFY_TRUE(raw_data_size > 0, NRF_ERROR_CRYPTO_INPUT_LENGTH); + VERIFY_TRUE(p_raw_input != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + VERIFY_TRUE(p_raw_output != NULL, NRF_ERROR_CRYPTO_OUTPUT_NULL); + + // Loop over each big integer of the input + while (raw_data_size >= integer_size) + { + // Swap byte by byte in current integer + from_index = 0; + to_index = integer_size - 1; + while (from_index <= to_index) + { + // Swap bytes from source to destination, this may be the same buffer, so use temporary variable + temp = p_raw_input[from_index]; + p_raw_output[from_index] = p_raw_input[to_index]; + p_raw_output[to_index] = temp; + // Go to next pair of bytes + from_index++; + to_index--; + } + // Go to next integer + raw_data_size -= integer_size; + p_raw_input += integer_size; + p_raw_output += integer_size; + } + + if (raw_data_size != 0) + { + // Input size is not a multiple of big integer size, so it is invalid + return NRF_ERROR_CRYPTO_INPUT_LENGTH; + } + + return NRF_SUCCESS; +} + + +#endif // NRF_CRYPTO_ECC_ENABLED diff --git a/components/libraries/crypto/nrf_crypto_ecc.h b/components/libraries/crypto/nrf_crypto_ecc.h new file mode 100644 index 0000000..177aea0 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_ecc.h @@ -0,0 +1,969 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_ECC_H__ +#define NRF_CRYPTO_ECC_H__ + +/** @addtogroup nrf_crypto + * @{ + * @addtogroup nrf_crypto_ecc Elliptic Curve Cryptography Key Management + * @{ + * @brief Provides elliptic curve cryptography API for public and private key management. + * + * @addtogroup nrf_crypto_ecc_secp160r1 Definitions specific to secp160r1 (NIST 160-bit) + * @addtogroup nrf_crypto_ecc_secp160r2 Definitions specific to secp160r2 (NIST 160-bit) + * @addtogroup nrf_crypto_ecc_secp192r1 Definitions specific to secp192r1 (NIST 192-bit) + * @addtogroup nrf_crypto_ecc_secp224r1 Definitions specific to secp224r1 (NIST 224-bit) + * @addtogroup nrf_crypto_ecc_secp256r1 Definitions specific to secp256r1 (NIST 256-bit) + * @addtogroup nrf_crypto_ecc_secp384r1 Definitions specific to secp384r1 (NIST 384-bit) + * @addtogroup nrf_crypto_ecc_secp521r1 Definitions specific to secp521r1 (NIST 521-bit) + * @addtogroup nrf_crypto_ecc_secp160k1 Definitions specific to secp160k1 (Koblitz 160-bit) + * @addtogroup nrf_crypto_ecc_secp192k1 Definitions specific to secp192k1 (Koblitz 192-bit) + * @addtogroup nrf_crypto_ecc_secp224k1 Definitions specific to secp224k1 (Koblitz 224-bit) + * @addtogroup nrf_crypto_ecc_secp256k1 Definitions specific to secp256k1 (Koblitz 256-bit) + * @addtogroup nrf_crypto_ecc_bp256r1 Definitions specific to bp256r1 (Brainpool 256-bit) + * @addtogroup nrf_crypto_ecc_bp384r1 Definitions specific to bp384r1 (Brainpool 384-bit) + * @addtogroup nrf_crypto_ecc_bp512r1 Definitions specific to bp512r1 (Brainpool 512-bit) + * @addtogroup nrf_crypto_ecc_curve25519 Definitions specific to Curve25519 + * @addtogroup nrf_crypto_ecc_ed25519 Definitions specific to Ed25519 + */ + +#include +#include + +#include "nrf_crypto_error.h" +#include "nrf_crypto_ecc_shared.h" +#include "nrf_crypto_ecc_backend.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined(__SDK_DOXYGEN__) +#define NRF_CRYPTO_ECC_SECP160R1_ENABLED 1 /**< @brief Defined as 1 if secp160r1 (NIST 160-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp160r1 */ +#define NRF_CRYPTO_ECC_SECP160R2_ENABLED 1 /**< @brief Defined as 1 if secp160r2 (NIST 160-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp160r2 */ +#define NRF_CRYPTO_ECC_SECP192R1_ENABLED 1 /**< @brief Defined as 1 if secp192r1 (NIST 192-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp192r1 */ +#define NRF_CRYPTO_ECC_SECP224R1_ENABLED 1 /**< @brief Defined as 1 if secp224r1 (NIST 224-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp224r1 */ +#define NRF_CRYPTO_ECC_SECP256R1_ENABLED 1 /**< @brief Defined as 1 if secp256r1 (NIST 256-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp256r1 */ +#define NRF_CRYPTO_ECC_SECP384R1_ENABLED 1 /**< @brief Defined as 1 if secp384r1 (NIST 384-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp384r1 */ +#define NRF_CRYPTO_ECC_SECP521R1_ENABLED 1 /**< @brief Defined as 1 if secp521r1 (NIST 521-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp521r1 */ +#define NRF_CRYPTO_ECC_SECP160K1_ENABLED 1 /**< @brief Defined as 1 if secp160k1 (Koblitz 160-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp160k1 */ +#define NRF_CRYPTO_ECC_SECP192K1_ENABLED 1 /**< @brief Defined as 1 if secp192k1 (Koblitz 192-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp192k1 */ +#define NRF_CRYPTO_ECC_SECP224K1_ENABLED 1 /**< @brief Defined as 1 if secp224k1 (Koblitz 224-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp224k1 */ +#define NRF_CRYPTO_ECC_SECP256K1_ENABLED 1 /**< @brief Defined as 1 if secp256k1 (Koblitz 256-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_secp256k1 */ +#define NRF_CRYPTO_ECC_BP256R1_ENABLED 1 /**< @brief Defined as 1 if bp256r1 (Brainpool 256-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_bp256r1 */ +#define NRF_CRYPTO_ECC_BP384R1_ENABLED 1 /**< @brief Defined as 1 if bp384r1 (Brainpool 384-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_bp384r1 */ +#define NRF_CRYPTO_ECC_BP512R1_ENABLED 1 /**< @brief Defined as 1 if bp512r1 (Brainpool 512-bit) is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_bp512r1 */ +#define NRF_CRYPTO_ECC_CURVE25519_ENABLED 1 /**< @brief Defined as 1 if Curve25519 is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_curve25519 */ +#define NRF_CRYPTO_ECC_ED25519_ENABLED 1 /**< @brief Defined as 1 if Ed25519 is enabled in any of the backends and it is usable in the API, 0 otherwise. @ingroup nrf_crypto_ecc_ed25519 */ +#endif + + +#define NRF_CRYPTO_ECC_SECP160R1_RAW_PRIVATE_KEY_SIZE (160 / 8) /**< @brief Raw private key size for secp160r1 (NIST 160-bit). @ingroup nrf_crypto_ecc_secp160r1 */ +#define NRF_CRYPTO_ECC_SECP160R2_RAW_PRIVATE_KEY_SIZE (160 / 8) /**< @brief Raw private key size for secp160r2 (NIST 160-bit). @ingroup nrf_crypto_ecc_secp160r2 */ +#define NRF_CRYPTO_ECC_SECP192R1_RAW_PRIVATE_KEY_SIZE (192 / 8) /**< @brief Raw private key size for secp192r1 (NIST 192-bit). @ingroup nrf_crypto_ecc_secp192r1 */ +#define NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE (224 / 8) /**< @brief Raw private key size for secp224r1 (NIST 224-bit). @ingroup nrf_crypto_ecc_secp224r1 */ +#define NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE (256 / 8) /**< @brief Raw private key size for secp256r1 (NIST 256-bit). @ingroup nrf_crypto_ecc_secp256r1 */ +#define NRF_CRYPTO_ECC_SECP384R1_RAW_PRIVATE_KEY_SIZE (384 / 8) /**< @brief Raw private key size for secp384r1 (NIST 384-bit). @ingroup nrf_crypto_ecc_secp384r1 */ +#define NRF_CRYPTO_ECC_SECP521R1_RAW_PRIVATE_KEY_SIZE (528 / 8) /**< @brief Raw private key size for secp521r1 (NIST 521-bit). @ingroup nrf_crypto_ecc_secp521r1 */ +#define NRF_CRYPTO_ECC_SECP160K1_RAW_PRIVATE_KEY_SIZE (160 / 8) /**< @brief Raw private key size for secp160k1 (Koblitz 160-bit). @ingroup nrf_crypto_ecc_secp160k1 */ +#define NRF_CRYPTO_ECC_SECP192K1_RAW_PRIVATE_KEY_SIZE (192 / 8) /**< @brief Raw private key size for secp192k1 (Koblitz 192-bit). @ingroup nrf_crypto_ecc_secp192k1 */ +#define NRF_CRYPTO_ECC_SECP224K1_RAW_PRIVATE_KEY_SIZE (224 / 8) /**< @brief Raw private key size for secp224k1 (Koblitz 224-bit). @ingroup nrf_crypto_ecc_secp224k1 */ +#define NRF_CRYPTO_ECC_SECP256K1_RAW_PRIVATE_KEY_SIZE (256 / 8) /**< @brief Raw private key size for secp256k1 (Koblitz 256-bit). @ingroup nrf_crypto_ecc_secp256k1 */ +#define NRF_CRYPTO_ECC_BP256R1_RAW_PRIVATE_KEY_SIZE (256 / 8) /**< @brief Raw private key size for bp256r1 (Brainpool 256-bit). @ingroup nrf_crypto_ecc_bp256r1 */ +#define NRF_CRYPTO_ECC_BP384R1_RAW_PRIVATE_KEY_SIZE (384 / 8) /**< @brief Raw private key size for bp384r1 (Brainpool 384-bit). @ingroup nrf_crypto_ecc_bp384r1 */ +#define NRF_CRYPTO_ECC_BP512R1_RAW_PRIVATE_KEY_SIZE (512 / 8) /**< @brief Raw private key size for bp512r1 (Brainpool 512-bit). @ingroup nrf_crypto_ecc_bp512r1 */ +#define NRF_CRYPTO_ECC_CURVE25519_RAW_PRIVATE_KEY_SIZE (256 / 8) /**< @brief Raw private key size for Curve25519. @ingroup nrf_crypto_ecc_curve25519 */ +#define NRF_CRYPTO_ECC_ED25519_RAW_PRIVATE_KEY_SIZE (256 / 8) /**< @brief Raw private key size for Ed25519. @ingroup nrf_crypto_ecc_ed25519 */ + + +#define NRF_CRYPTO_ECC_SECP160R1_RAW_PUBLIC_KEY_SIZE (2 * 160 / 8) /**< @brief Raw public key size for curve secp160r1 (NIST 160-bit). @ingroup nrf_crypto_ecc_secp160r1 */ +#define NRF_CRYPTO_ECC_SECP160R2_RAW_PUBLIC_KEY_SIZE (2 * 160 / 8) /**< @brief Raw public key size for curve secp160r2 (NIST 160-bit). @ingroup nrf_crypto_ecc_secp160r2 */ +#define NRF_CRYPTO_ECC_SECP192R1_RAW_PUBLIC_KEY_SIZE (2 * 192 / 8) /**< @brief Raw public key size for curve secp192r1 (NIST 192-bit). @ingroup nrf_crypto_ecc_secp192r1 */ +#define NRF_CRYPTO_ECC_SECP224R1_RAW_PUBLIC_KEY_SIZE (2 * 224 / 8) /**< @brief Raw public key size for curve secp224r1 (NIST 224-bit). @ingroup nrf_crypto_ecc_secp224r1 */ +#define NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE (2 * 256 / 8) /**< @brief Raw public key size for curve secp256r1 (NIST 256-bit). @ingroup nrf_crypto_ecc_secp256r1 */ +#define NRF_CRYPTO_ECC_SECP384R1_RAW_PUBLIC_KEY_SIZE (2 * 384 / 8) /**< @brief Raw public key size for curve secp384r1 (NIST 384-bit). @ingroup nrf_crypto_ecc_secp384r1 */ +#define NRF_CRYPTO_ECC_SECP521R1_RAW_PUBLIC_KEY_SIZE (2 * 528 / 8) /**< @brief Raw public key size for curve secp521r1 (NIST 521-bit). @ingroup nrf_crypto_ecc_secp521r1 */ +#define NRF_CRYPTO_ECC_SECP160K1_RAW_PUBLIC_KEY_SIZE (2 * 160 / 8) /**< @brief Raw public key size for curve secp160k1 (Koblitz 160-bit). @ingroup nrf_crypto_ecc_secp160k1 */ +#define NRF_CRYPTO_ECC_SECP192K1_RAW_PUBLIC_KEY_SIZE (2 * 192 / 8) /**< @brief Raw public key size for curve secp192k1 (Koblitz 192-bit). @ingroup nrf_crypto_ecc_secp192k1 */ +#define NRF_CRYPTO_ECC_SECP224K1_RAW_PUBLIC_KEY_SIZE (2 * 224 / 8) /**< @brief Raw public key size for curve secp224k1 (Koblitz 224-bit). @ingroup nrf_crypto_ecc_secp224k1 */ +#define NRF_CRYPTO_ECC_SECP256K1_RAW_PUBLIC_KEY_SIZE (2 * 256 / 8) /**< @brief Raw public key size for curve secp256k1 (Koblitz 256-bit). @ingroup nrf_crypto_ecc_secp256k1 */ +#define NRF_CRYPTO_ECC_BP256R1_RAW_PUBLIC_KEY_SIZE (2 * 256 / 8) /**< @brief Raw public key size for curve bp256r1 (Brainpool 256-bit). @ingroup nrf_crypto_ecc_bp256r1 */ +#define NRF_CRYPTO_ECC_BP384R1_RAW_PUBLIC_KEY_SIZE (2 * 384 / 8) /**< @brief Raw public key size for curve bp384r1 (Brainpool 384-bit). @ingroup nrf_crypto_ecc_bp384r1 */ +#define NRF_CRYPTO_ECC_BP512R1_RAW_PUBLIC_KEY_SIZE (2 * 512 / 8) /**< @brief Raw public key size for curve bp512r1 (Brainpool 512-bit). @ingroup nrf_crypto_ecc_bp512r1 */ +#define NRF_CRYPTO_ECC_CURVE25519_RAW_PUBLIC_KEY_SIZE (256 / 8) /**< @brief Raw public key size for curve Curve25519. @ingroup nrf_crypto_ecc_curve25519 */ +#define NRF_CRYPTO_ECC_ED25519_RAW_PUBLIC_KEY_SIZE (256 / 8) /**< @brief Raw public key size for curve Ed25519. @ingroup nrf_crypto_ecc_ed25519 */ + + +#define NRF_CRYPTO_ECC_RAW_PRIVATE_KEY_MAX_SIZE NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE /**< @brief Maximum size of a raw private key for all enabled curves. */ +#define NRF_CRYPTO_ECC_RAW_PUBLIC_KEY_MAX_SIZE NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE /**< @brief Maximum size of a raw public key for all enabled curves. */ + + +/** @brief Defines type of ECC curve. + */ +typedef enum +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + NRF_CRYPTO_ECC_SECP160R1_CURVE_TYPE, /**< secp160r1 (NIST 160-bit) */ +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + NRF_CRYPTO_ECC_SECP160R2_CURVE_TYPE, /**< secp160r2 (NIST 160-bit) */ +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + NRF_CRYPTO_ECC_SECP192R1_CURVE_TYPE, /**< secp192r1 (NIST 192-bit) */ +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + NRF_CRYPTO_ECC_SECP224R1_CURVE_TYPE, /**< secp224r1 (NIST 224-bit) */ +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + NRF_CRYPTO_ECC_SECP256R1_CURVE_TYPE, /**< secp256r1 (NIST 256-bit) */ +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + NRF_CRYPTO_ECC_SECP384R1_CURVE_TYPE, /**< secp384r1 (NIST 384-bit) */ +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + NRF_CRYPTO_ECC_SECP521R1_CURVE_TYPE, /**< secp521r1 (NIST 521-bit) */ +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + NRF_CRYPTO_ECC_SECP160K1_CURVE_TYPE, /**< secp160k1 (Koblitz 160-bit) */ +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + NRF_CRYPTO_ECC_SECP192K1_CURVE_TYPE, /**< secp192k1 (Koblitz 192-bit) */ +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + NRF_CRYPTO_ECC_SECP224K1_CURVE_TYPE, /**< secp224k1 (Koblitz 224-bit) */ +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + NRF_CRYPTO_ECC_SECP256K1_CURVE_TYPE, /**< secp256k1 (Koblitz 256-bit) */ +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + NRF_CRYPTO_ECC_BP256R1_CURVE_TYPE, /**< bp256r1 (Brainpool 256-bit) */ +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + NRF_CRYPTO_ECC_BP384R1_CURVE_TYPE, /**< bp384r1 (Brainpool 384-bit) */ +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + NRF_CRYPTO_ECC_BP512R1_CURVE_TYPE, /**< bp512r1 (Brainpool 512-bit) */ +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + NRF_CRYPTO_ECC_CURVE25519_CURVE_TYPE, /**< Curve25519 */ +#endif +#if NRF_CRYPTO_ECC_ED25519_ENABLED + NRF_CRYPTO_ECC_ED25519_CURVE_TYPE, /**< Ed25519 */ +#endif +#if !NRF_CRYPTO_ECC_SECP160R1_ENABLED + NRF_CRYPTO_ECC_SECP160R1_CURVE_TYPE, /**< secp160r1 (NIST 160-bit) */ +#endif +#if !NRF_CRYPTO_ECC_SECP160R2_ENABLED + NRF_CRYPTO_ECC_SECP160R2_CURVE_TYPE, /**< secp160r2 (NIST 160-bit) */ +#endif +#if !NRF_CRYPTO_ECC_SECP192R1_ENABLED + NRF_CRYPTO_ECC_SECP192R1_CURVE_TYPE, /**< secp192r1 (NIST 192-bit) */ +#endif +#if !NRF_CRYPTO_ECC_SECP224R1_ENABLED + NRF_CRYPTO_ECC_SECP224R1_CURVE_TYPE, /**< secp224r1 (NIST 224-bit) */ +#endif +#if !NRF_CRYPTO_ECC_SECP256R1_ENABLED + NRF_CRYPTO_ECC_SECP256R1_CURVE_TYPE, /**< secp256r1 (NIST 256-bit) */ +#endif +#if !NRF_CRYPTO_ECC_SECP384R1_ENABLED + NRF_CRYPTO_ECC_SECP384R1_CURVE_TYPE, /**< secp384r1 (NIST 384-bit) */ +#endif +#if !NRF_CRYPTO_ECC_SECP521R1_ENABLED + NRF_CRYPTO_ECC_SECP521R1_CURVE_TYPE, /**< secp521r1 (NIST 521-bit) */ +#endif +#if !NRF_CRYPTO_ECC_SECP160K1_ENABLED + NRF_CRYPTO_ECC_SECP160K1_CURVE_TYPE, /**< secp160k1 (Koblitz 160-bit) */ +#endif +#if !NRF_CRYPTO_ECC_SECP192K1_ENABLED + NRF_CRYPTO_ECC_SECP192K1_CURVE_TYPE, /**< secp192k1 (Koblitz 192-bit) */ +#endif +#if !NRF_CRYPTO_ECC_SECP224K1_ENABLED + NRF_CRYPTO_ECC_SECP224K1_CURVE_TYPE, /**< secp224k1 (Koblitz 224-bit) */ +#endif +#if !NRF_CRYPTO_ECC_SECP256K1_ENABLED + NRF_CRYPTO_ECC_SECP256K1_CURVE_TYPE, /**< secp256k1 (Koblitz 256-bit) */ +#endif +#if !NRF_CRYPTO_ECC_BP256R1_ENABLED + NRF_CRYPTO_ECC_BP256R1_CURVE_TYPE, /**< bp256r1 (Brainpool 256-bit) */ +#endif +#if !NRF_CRYPTO_ECC_BP384R1_ENABLED + NRF_CRYPTO_ECC_BP384R1_CURVE_TYPE, /**< bp384r1 (Brainpool 384-bit) */ +#endif +#if !NRF_CRYPTO_ECC_BP512R1_ENABLED + NRF_CRYPTO_ECC_BP512R1_CURVE_TYPE, /**< bp512r1 (Brainpool 512-bit) */ +#endif +#if !NRF_CRYPTO_ECC_CURVE25519_ENABLED + NRF_CRYPTO_ECC_CURVE25519_CURVE_TYPE, /**< Curve25519 */ +#endif +#if !NRF_CRYPTO_ECC_ED25519_ENABLED + NRF_CRYPTO_ECC_ED25519_CURVE_TYPE, /**< Ed25519 */ +#endif +} nrf_crypto_ecc_curve_type_t; + + +/** @brief Structure holding information on a specific curve. + * + * @note This structure cannot be used to create a new variable. Only the variables defined by this + * library can be used, e.g. @ref g_nrf_crypto_ecc_secp256r1_curve_info. + */ +typedef struct nrf_crypto_ecc_curve_info_s +{ + uint16_t public_key_size; /**< @brief Size of a structure holding internal public key. */ + uint16_t private_key_size; /**< @brief Size of a structure holding internal private key. */ + nrf_crypto_ecc_curve_type_t curve_type; /**< @brief Type of the curve. */ + uint8_t raw_private_key_size; /**< @brief Size of a buffer containing raw private key. */ + uint8_t raw_public_key_size; /**< @brief Size of a buffer containing raw public key. */ + void * p_backend_data; /**< @brief Field to hold backend specific internal data. */ +} nrf_crypto_ecc_curve_info_t; + + +/** @addtogroup nrf_crypto_ecc_secp160r1 + * @{ */ + +typedef nrf_crypto_backend_secp160r1_key_pair_generate_context_t + nrf_crypto_ecc_secp160r1_key_pair_generate_context_t; /**< @brief Context structure for key generation using secp160r1 (NIST 160-bit). */ +typedef nrf_crypto_backend_secp160r1_public_key_calculate_context_t + nrf_crypto_ecc_secp160r1_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using secp160r1 (NIST 160-bit). */ +typedef nrf_crypto_backend_secp160r1_private_key_t + nrf_crypto_ecc_secp160r1_private_key_t; /**< @brief Structure holding internal representation of a private key for secp160r1 (NIST 160-bit) */ +typedef nrf_crypto_backend_secp160r1_public_key_t + nrf_crypto_ecc_secp160r1_public_key_t; /**< @brief Structure holding internal representation of a public key for secp160r1 (NIST 160-bit) */ +typedef uint8_t nrf_crypto_ecc_secp160r1_raw_private_key_t + [NRF_CRYPTO_ECC_SECP160R1_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for secp160r1 (NIST 160-bit) */ +typedef uint8_t nrf_crypto_ecc_secp160r1_raw_public_key_t + [NRF_CRYPTO_ECC_SECP160R1_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for secp160r1 (NIST 160-bit) */ + + + +/** @brief Variable containing information on secp160r1 (NIST 160-bit). + * + * It can be used as a parameter for the functions creating secp160r1 (NIST 160-bit) keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp160r1_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_secp160r2 + * @{ */ + +typedef nrf_crypto_backend_secp160r2_key_pair_generate_context_t + nrf_crypto_ecc_secp160r2_key_pair_generate_context_t; /**< @brief Context structure for key generation using secp160r2 (NIST 160-bit). */ +typedef nrf_crypto_backend_secp160r2_public_key_calculate_context_t + nrf_crypto_ecc_secp160r2_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using secp160r2 (NIST 160-bit). */ +typedef nrf_crypto_backend_secp160r2_private_key_t + nrf_crypto_ecc_secp160r2_private_key_t; /**< @brief Structure holding internal representation of a private key for secp160r2 (NIST 160-bit) */ +typedef nrf_crypto_backend_secp160r2_public_key_t + nrf_crypto_ecc_secp160r2_public_key_t; /**< @brief Structure holding internal representation of a public key for secp160r2 (NIST 160-bit) */ +typedef uint8_t nrf_crypto_ecc_secp160r2_raw_private_key_t + [NRF_CRYPTO_ECC_SECP160R2_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for secp160r2 (NIST 160-bit) */ +typedef uint8_t nrf_crypto_ecc_secp160r2_raw_public_key_t + [NRF_CRYPTO_ECC_SECP160R2_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for secp160r2 (NIST 160-bit) */ + + + +/** @brief Variable containing information on secp160r2 (NIST 160-bit). + * + * It can be used as a parameter for the functions creating secp160r2 (NIST 160-bit) keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp160r2_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_secp192r1 + * @{ */ + +typedef nrf_crypto_backend_secp192r1_key_pair_generate_context_t + nrf_crypto_ecc_secp192r1_key_pair_generate_context_t; /**< @brief Context structure for key generation using secp192r1 (NIST 192-bit). */ +typedef nrf_crypto_backend_secp192r1_public_key_calculate_context_t + nrf_crypto_ecc_secp192r1_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using secp192r1 (NIST 192-bit). */ +typedef nrf_crypto_backend_secp192r1_private_key_t + nrf_crypto_ecc_secp192r1_private_key_t; /**< @brief Structure holding internal representation of a private key for secp192r1 (NIST 192-bit) */ +typedef nrf_crypto_backend_secp192r1_public_key_t + nrf_crypto_ecc_secp192r1_public_key_t; /**< @brief Structure holding internal representation of a public key for secp192r1 (NIST 192-bit) */ +typedef uint8_t nrf_crypto_ecc_secp192r1_raw_private_key_t + [NRF_CRYPTO_ECC_SECP192R1_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for secp192r1 (NIST 192-bit) */ +typedef uint8_t nrf_crypto_ecc_secp192r1_raw_public_key_t + [NRF_CRYPTO_ECC_SECP192R1_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for secp192r1 (NIST 192-bit) */ + + + +/** @brief Variable containing information on secp192r1 (NIST 192-bit). + * + * It can be used as a parameter for the functions creating secp192r1 (NIST 192-bit) keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp192r1_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_secp224r1 + * @{ */ + +typedef nrf_crypto_backend_secp224r1_key_pair_generate_context_t + nrf_crypto_ecc_secp224r1_key_pair_generate_context_t; /**< @brief Context structure for key generation using secp224r1 (NIST 224-bit). */ +typedef nrf_crypto_backend_secp224r1_public_key_calculate_context_t + nrf_crypto_ecc_secp224r1_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using secp224r1 (NIST 224-bit). */ +typedef nrf_crypto_backend_secp224r1_private_key_t + nrf_crypto_ecc_secp224r1_private_key_t; /**< @brief Structure holding internal representation of a private key for secp224r1 (NIST 224-bit) */ +typedef nrf_crypto_backend_secp224r1_public_key_t + nrf_crypto_ecc_secp224r1_public_key_t; /**< @brief Structure holding internal representation of a public key for secp224r1 (NIST 224-bit) */ +typedef uint8_t nrf_crypto_ecc_secp224r1_raw_private_key_t + [NRF_CRYPTO_ECC_SECP224R1_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for secp224r1 (NIST 224-bit) */ +typedef uint8_t nrf_crypto_ecc_secp224r1_raw_public_key_t + [NRF_CRYPTO_ECC_SECP224R1_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for secp224r1 (NIST 224-bit) */ + + + +/** @brief Variable containing information on secp224r1 (NIST 224-bit). + * + * It can be used as a parameter for the functions creating secp224r1 (NIST 224-bit) keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp224r1_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_secp256r1 + * @{ */ + +typedef nrf_crypto_backend_secp256r1_key_pair_generate_context_t + nrf_crypto_ecc_secp256r1_key_pair_generate_context_t; /**< @brief Context structure for key generation using secp256r1 (NIST 256-bit). */ +typedef nrf_crypto_backend_secp256r1_public_key_calculate_context_t + nrf_crypto_ecc_secp256r1_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using secp256r1 (NIST 256-bit). */ +typedef nrf_crypto_backend_secp256r1_private_key_t + nrf_crypto_ecc_secp256r1_private_key_t; /**< @brief Structure holding internal representation of a private key for secp256r1 (NIST 256-bit) */ +typedef nrf_crypto_backend_secp256r1_public_key_t + nrf_crypto_ecc_secp256r1_public_key_t; /**< @brief Structure holding internal representation of a public key for secp256r1 (NIST 256-bit) */ +typedef uint8_t nrf_crypto_ecc_secp256r1_raw_private_key_t + [NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for secp256r1 (NIST 256-bit) */ +typedef uint8_t nrf_crypto_ecc_secp256r1_raw_public_key_t + [NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for secp256r1 (NIST 256-bit) */ + + + +/** @brief Variable containing information on secp256r1 (NIST 256-bit). + * + * It can be used as a parameter for the functions creating secp256r1 (NIST 256-bit) keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp256r1_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_secp384r1 + * @{ */ + +typedef nrf_crypto_backend_secp384r1_key_pair_generate_context_t + nrf_crypto_ecc_secp384r1_key_pair_generate_context_t; /**< @brief Context structure for key generation using secp384r1 (NIST 384-bit). */ +typedef nrf_crypto_backend_secp384r1_public_key_calculate_context_t + nrf_crypto_ecc_secp384r1_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using secp384r1 (NIST 384-bit). */ +typedef nrf_crypto_backend_secp384r1_private_key_t + nrf_crypto_ecc_secp384r1_private_key_t; /**< @brief Structure holding internal representation of a private key for secp384r1 (NIST 384-bit) */ +typedef nrf_crypto_backend_secp384r1_public_key_t + nrf_crypto_ecc_secp384r1_public_key_t; /**< @brief Structure holding internal representation of a public key for secp384r1 (NIST 384-bit) */ +typedef uint8_t nrf_crypto_ecc_secp384r1_raw_private_key_t + [NRF_CRYPTO_ECC_SECP384R1_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for secp384r1 (NIST 384-bit) */ +typedef uint8_t nrf_crypto_ecc_secp384r1_raw_public_key_t + [NRF_CRYPTO_ECC_SECP384R1_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for secp384r1 (NIST 384-bit) */ + + + +/** @brief Variable containing information on secp384r1 (NIST 384-bit). + * + * It can be used as a parameter for the functions creating secp384r1 (NIST 384-bit) keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp384r1_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_secp521r1 + * @{ */ + +typedef nrf_crypto_backend_secp521r1_key_pair_generate_context_t + nrf_crypto_ecc_secp521r1_key_pair_generate_context_t; /**< @brief Context structure for key generation using secp521r1 (NIST 521-bit). */ +typedef nrf_crypto_backend_secp521r1_public_key_calculate_context_t + nrf_crypto_ecc_secp521r1_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using secp521r1 (NIST 521-bit). */ +typedef nrf_crypto_backend_secp521r1_private_key_t + nrf_crypto_ecc_secp521r1_private_key_t; /**< @brief Structure holding internal representation of a private key for secp521r1 (NIST 521-bit) */ +typedef nrf_crypto_backend_secp521r1_public_key_t + nrf_crypto_ecc_secp521r1_public_key_t; /**< @brief Structure holding internal representation of a public key for secp521r1 (NIST 521-bit) */ +typedef uint8_t nrf_crypto_ecc_secp521r1_raw_private_key_t + [NRF_CRYPTO_ECC_SECP521R1_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for secp521r1 (NIST 521-bit) */ +typedef uint8_t nrf_crypto_ecc_secp521r1_raw_public_key_t + [NRF_CRYPTO_ECC_SECP521R1_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for secp521r1 (NIST 521-bit) */ + + + +/** @brief Variable containing information on secp521r1 (NIST 521-bit). + * + * It can be used as a parameter for the functions creating secp521r1 (NIST 521-bit) keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp521r1_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_secp160k1 + * @{ */ + +typedef nrf_crypto_backend_secp160k1_key_pair_generate_context_t + nrf_crypto_ecc_secp160k1_key_pair_generate_context_t; /**< @brief Context structure for key generation using secp160k1 (Koblitz 160-bit). */ +typedef nrf_crypto_backend_secp160k1_public_key_calculate_context_t + nrf_crypto_ecc_secp160k1_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using secp160k1 (Koblitz 160-bit). */ +typedef nrf_crypto_backend_secp160k1_private_key_t + nrf_crypto_ecc_secp160k1_private_key_t; /**< @brief Structure holding internal representation of a private key for secp160k1 (Koblitz 160-bit) */ +typedef nrf_crypto_backend_secp160k1_public_key_t + nrf_crypto_ecc_secp160k1_public_key_t; /**< @brief Structure holding internal representation of a public key for secp160k1 (Koblitz 160-bit) */ +typedef uint8_t nrf_crypto_ecc_secp160k1_raw_private_key_t + [NRF_CRYPTO_ECC_SECP160K1_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for secp160k1 (Koblitz 160-bit) */ +typedef uint8_t nrf_crypto_ecc_secp160k1_raw_public_key_t + [NRF_CRYPTO_ECC_SECP160K1_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for secp160k1 (Koblitz 160-bit) */ + + + +/** @brief Variable containing information on secp160k1 (Koblitz 160-bit). + * + * It can be used as a parameter for the functions creating secp160k1 (Koblitz 160-bit) keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp160k1_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_secp192k1 + * @{ */ + +typedef nrf_crypto_backend_secp192k1_key_pair_generate_context_t + nrf_crypto_ecc_secp192k1_key_pair_generate_context_t; /**< @brief Context structure for key generation using secp192k1 (Koblitz 192-bit). */ +typedef nrf_crypto_backend_secp192k1_public_key_calculate_context_t + nrf_crypto_ecc_secp192k1_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using secp192k1 (Koblitz 192-bit). */ +typedef nrf_crypto_backend_secp192k1_private_key_t + nrf_crypto_ecc_secp192k1_private_key_t; /**< @brief Structure holding internal representation of a private key for secp192k1 (Koblitz 192-bit) */ +typedef nrf_crypto_backend_secp192k1_public_key_t + nrf_crypto_ecc_secp192k1_public_key_t; /**< @brief Structure holding internal representation of a public key for secp192k1 (Koblitz 192-bit) */ +typedef uint8_t nrf_crypto_ecc_secp192k1_raw_private_key_t + [NRF_CRYPTO_ECC_SECP192K1_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for secp192k1 (Koblitz 192-bit) */ +typedef uint8_t nrf_crypto_ecc_secp192k1_raw_public_key_t + [NRF_CRYPTO_ECC_SECP192K1_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for secp192k1 (Koblitz 192-bit) */ + + + +/** @brief Variable containing information on secp192k1 (Koblitz 192-bit). + * + * It can be used as a parameter for the functions creating secp192k1 (Koblitz 192-bit) keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp192k1_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_secp224k1 + * @{ */ + +typedef nrf_crypto_backend_secp224k1_key_pair_generate_context_t + nrf_crypto_ecc_secp224k1_key_pair_generate_context_t; /**< @brief Context structure for key generation using secp224k1 (Koblitz 224-bit). */ +typedef nrf_crypto_backend_secp224k1_public_key_calculate_context_t + nrf_crypto_ecc_secp224k1_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using secp224k1 (Koblitz 224-bit). */ +typedef nrf_crypto_backend_secp224k1_private_key_t + nrf_crypto_ecc_secp224k1_private_key_t; /**< @brief Structure holding internal representation of a private key for secp224k1 (Koblitz 224-bit) */ +typedef nrf_crypto_backend_secp224k1_public_key_t + nrf_crypto_ecc_secp224k1_public_key_t; /**< @brief Structure holding internal representation of a public key for secp224k1 (Koblitz 224-bit) */ +typedef uint8_t nrf_crypto_ecc_secp224k1_raw_private_key_t + [NRF_CRYPTO_ECC_SECP224K1_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for secp224k1 (Koblitz 224-bit) */ +typedef uint8_t nrf_crypto_ecc_secp224k1_raw_public_key_t + [NRF_CRYPTO_ECC_SECP224K1_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for secp224k1 (Koblitz 224-bit) */ + + + +/** @brief Variable containing information on secp224k1 (Koblitz 224-bit). + * + * It can be used as a parameter for the functions creating secp224k1 (Koblitz 224-bit) keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp224k1_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_secp256k1 + * @{ */ + +typedef nrf_crypto_backend_secp256k1_key_pair_generate_context_t + nrf_crypto_ecc_secp256k1_key_pair_generate_context_t; /**< @brief Context structure for key generation using secp256k1 (Koblitz 256-bit). */ +typedef nrf_crypto_backend_secp256k1_public_key_calculate_context_t + nrf_crypto_ecc_secp256k1_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using secp256k1 (Koblitz 256-bit). */ +typedef nrf_crypto_backend_secp256k1_private_key_t + nrf_crypto_ecc_secp256k1_private_key_t; /**< @brief Structure holding internal representation of a private key for secp256k1 (Koblitz 256-bit) */ +typedef nrf_crypto_backend_secp256k1_public_key_t + nrf_crypto_ecc_secp256k1_public_key_t; /**< @brief Structure holding internal representation of a public key for secp256k1 (Koblitz 256-bit) */ +typedef uint8_t nrf_crypto_ecc_secp256k1_raw_private_key_t + [NRF_CRYPTO_ECC_SECP256K1_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for secp256k1 (Koblitz 256-bit) */ +typedef uint8_t nrf_crypto_ecc_secp256k1_raw_public_key_t + [NRF_CRYPTO_ECC_SECP256K1_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for secp256k1 (Koblitz 256-bit) */ + + + +/** @brief Variable containing information on secp256k1 (Koblitz 256-bit). + * + * It can be used as a parameter for the functions creating secp256k1 (Koblitz 256-bit) keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_secp256k1_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_bp256r1 + * @{ */ + +typedef nrf_crypto_backend_bp256r1_key_pair_generate_context_t + nrf_crypto_ecc_bp256r1_key_pair_generate_context_t; /**< @brief Context structure for key generation using bp256r1 (Brainpool 256-bit). */ +typedef nrf_crypto_backend_bp256r1_public_key_calculate_context_t + nrf_crypto_ecc_bp256r1_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using bp256r1 (Brainpool 256-bit). */ +typedef nrf_crypto_backend_bp256r1_private_key_t + nrf_crypto_ecc_bp256r1_private_key_t; /**< @brief Structure holding internal representation of a private key for bp256r1 (Brainpool 256-bit) */ +typedef nrf_crypto_backend_bp256r1_public_key_t + nrf_crypto_ecc_bp256r1_public_key_t; /**< @brief Structure holding internal representation of a public key for bp256r1 (Brainpool 256-bit) */ +typedef uint8_t nrf_crypto_ecc_bp256r1_raw_private_key_t + [NRF_CRYPTO_ECC_BP256R1_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for bp256r1 (Brainpool 256-bit) */ +typedef uint8_t nrf_crypto_ecc_bp256r1_raw_public_key_t + [NRF_CRYPTO_ECC_BP256R1_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for bp256r1 (Brainpool 256-bit) */ + + + +/** @brief Variable containing information on bp256r1 (Brainpool 256-bit). + * + * It can be used as a parameter for the functions creating bp256r1 (Brainpool 256-bit) keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_bp256r1_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_bp384r1 + * @{ */ + +typedef nrf_crypto_backend_bp384r1_key_pair_generate_context_t + nrf_crypto_ecc_bp384r1_key_pair_generate_context_t; /**< @brief Context structure for key generation using bp384r1 (Brainpool 384-bit). */ +typedef nrf_crypto_backend_bp384r1_public_key_calculate_context_t + nrf_crypto_ecc_bp384r1_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using bp384r1 (Brainpool 384-bit). */ +typedef nrf_crypto_backend_bp384r1_private_key_t + nrf_crypto_ecc_bp384r1_private_key_t; /**< @brief Structure holding internal representation of a private key for bp384r1 (Brainpool 384-bit) */ +typedef nrf_crypto_backend_bp384r1_public_key_t + nrf_crypto_ecc_bp384r1_public_key_t; /**< @brief Structure holding internal representation of a public key for bp384r1 (Brainpool 384-bit) */ +typedef uint8_t nrf_crypto_ecc_bp384r1_raw_private_key_t + [NRF_CRYPTO_ECC_BP384R1_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for bp384r1 (Brainpool 384-bit) */ +typedef uint8_t nrf_crypto_ecc_bp384r1_raw_public_key_t + [NRF_CRYPTO_ECC_BP384R1_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for bp384r1 (Brainpool 384-bit) */ + + + +/** @brief Variable containing information on bp384r1 (Brainpool 384-bit). + * + * It can be used as a parameter for the functions creating bp384r1 (Brainpool 384-bit) keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_bp384r1_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_bp512r1 + * @{ */ + +typedef nrf_crypto_backend_bp512r1_key_pair_generate_context_t + nrf_crypto_ecc_bp512r1_key_pair_generate_context_t; /**< @brief Context structure for key generation using bp512r1 (Brainpool 512-bit). */ +typedef nrf_crypto_backend_bp512r1_public_key_calculate_context_t + nrf_crypto_ecc_bp512r1_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using bp512r1 (Brainpool 512-bit). */ +typedef nrf_crypto_backend_bp512r1_private_key_t + nrf_crypto_ecc_bp512r1_private_key_t; /**< @brief Structure holding internal representation of a private key for bp512r1 (Brainpool 512-bit) */ +typedef nrf_crypto_backend_bp512r1_public_key_t + nrf_crypto_ecc_bp512r1_public_key_t; /**< @brief Structure holding internal representation of a public key for bp512r1 (Brainpool 512-bit) */ +typedef uint8_t nrf_crypto_ecc_bp512r1_raw_private_key_t + [NRF_CRYPTO_ECC_BP512R1_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for bp512r1 (Brainpool 512-bit) */ +typedef uint8_t nrf_crypto_ecc_bp512r1_raw_public_key_t + [NRF_CRYPTO_ECC_BP512R1_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for bp512r1 (Brainpool 512-bit) */ + + + +/** @brief Variable containing information on bp512r1 (Brainpool 512-bit). + * + * It can be used as a parameter for the functions creating bp512r1 (Brainpool 512-bit) keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_bp512r1_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_curve25519 + * @{ */ + +typedef nrf_crypto_backend_curve25519_key_pair_generate_context_t + nrf_crypto_ecc_curve25519_key_pair_generate_context_t; /**< @brief Context structure for key generation using Curve25519. */ +typedef nrf_crypto_backend_curve25519_public_key_calculate_context_t + nrf_crypto_ecc_curve25519_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using Curve25519. */ +typedef nrf_crypto_backend_curve25519_private_key_t + nrf_crypto_ecc_curve25519_private_key_t; /**< @brief Structure holding internal representation of a private key for Curve25519 */ +typedef nrf_crypto_backend_curve25519_public_key_t + nrf_crypto_ecc_curve25519_public_key_t; /**< @brief Structure holding internal representation of a public key for Curve25519 */ +typedef uint8_t nrf_crypto_ecc_curve25519_raw_private_key_t + [NRF_CRYPTO_ECC_CURVE25519_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for Curve25519 */ +typedef uint8_t nrf_crypto_ecc_curve25519_raw_public_key_t + [NRF_CRYPTO_ECC_CURVE25519_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for Curve25519 */ + + +/** @brief Variable containing information on Curve25519. + * + * It can be used as a parameter for the functions creating Curve25519 keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_curve25519_curve_info; + + +/** @} */ + + +/** @addtogroup nrf_crypto_ecc_ed25519 + * @{ */ + +typedef nrf_crypto_backend_ed25519_key_pair_generate_context_t + nrf_crypto_ecc_ed25519_key_pair_generate_context_t; /**< @brief Context structure for key generation using Ed25519. */ +typedef nrf_crypto_backend_ed25519_public_key_calculate_context_t + nrf_crypto_ecc_ed25519_public_key_calculate_context_t; /**< @brief Context structure for public key calculation using Ed25519. */ +typedef nrf_crypto_backend_ed25519_private_key_t + nrf_crypto_ecc_ed25519_private_key_t; /**< @brief Structure holding internal representation of a private key for Ed25519 */ +typedef nrf_crypto_backend_ed25519_public_key_t + nrf_crypto_ecc_ed25519_public_key_t; /**< @brief Structure holding internal representation of a public key for Ed25519 */ +typedef uint8_t nrf_crypto_ecc_ed25519_raw_private_key_t + [NRF_CRYPTO_ECC_ED25519_RAW_PRIVATE_KEY_SIZE]; /**< @brief Array holding raw private key for Ed25519 */ +typedef uint8_t nrf_crypto_ecc_ed25519_raw_public_key_t + [NRF_CRYPTO_ECC_ED25519_RAW_PUBLIC_KEY_SIZE]; /**< @brief Array holding raw public key for Ed25519 */ + + + +/** @brief Variable containing information on Ed25519. + * + * It can be used as a parameter for the functions creating Ed25519 keys. + */ +extern const nrf_crypto_ecc_curve_info_t g_nrf_crypto_ecc_ed25519_curve_info; + + +/** @} */ + + +typedef uint8_t nrf_crypto_ecc_raw_private_key_t[NRF_CRYPTO_ECC_RAW_PRIVATE_KEY_MAX_SIZE]; /**< @brief Type big enough to hold a raw private key for any the enabled curves. */ +typedef uint8_t nrf_crypto_ecc_raw_public_key_t [NRF_CRYPTO_ECC_RAW_PUBLIC_KEY_MAX_SIZE]; /**< @brief Type big enough to hold a raw public key for any the enabled curves. */ + + +/** @brief Union holding a context for a key pair generation. + */ +typedef union +{ + nrf_crypto_ecc_secp160r1_key_pair_generate_context_t context_secp160r1; /**< @brief Holds context for secp160r1 (NIST 160-bit). */ + nrf_crypto_ecc_secp160r2_key_pair_generate_context_t context_secp160r2; /**< @brief Holds context for secp160r2 (NIST 160-bit). */ + nrf_crypto_ecc_secp192r1_key_pair_generate_context_t context_secp192r1; /**< @brief Holds context for secp192r1 (NIST 192-bit). */ + nrf_crypto_ecc_secp224r1_key_pair_generate_context_t context_secp224r1; /**< @brief Holds context for secp224r1 (NIST 224-bit). */ + nrf_crypto_ecc_secp256r1_key_pair_generate_context_t context_secp256r1; /**< @brief Holds context for secp256r1 (NIST 256-bit). */ + nrf_crypto_ecc_secp384r1_key_pair_generate_context_t context_secp384r1; /**< @brief Holds context for secp384r1 (NIST 384-bit). */ + nrf_crypto_ecc_secp521r1_key_pair_generate_context_t context_secp521r1; /**< @brief Holds context for secp521r1 (NIST 521-bit). */ + nrf_crypto_ecc_secp160k1_key_pair_generate_context_t context_secp160k1; /**< @brief Holds context for secp160k1 (Koblitz 160-bit). */ + nrf_crypto_ecc_secp192k1_key_pair_generate_context_t context_secp192k1; /**< @brief Holds context for secp192k1 (Koblitz 192-bit). */ + nrf_crypto_ecc_secp224k1_key_pair_generate_context_t context_secp224k1; /**< @brief Holds context for secp224k1 (Koblitz 224-bit). */ + nrf_crypto_ecc_secp256k1_key_pair_generate_context_t context_secp256k1; /**< @brief Holds context for secp256k1 (Koblitz 256-bit). */ + nrf_crypto_ecc_bp256r1_key_pair_generate_context_t context_bp256r1; /**< @brief Holds context for bp256r1 (Brainpool 256-bit). */ + nrf_crypto_ecc_bp384r1_key_pair_generate_context_t context_bp384r1; /**< @brief Holds context for bp384r1 (Brainpool 384-bit). */ + nrf_crypto_ecc_bp512r1_key_pair_generate_context_t context_bp512r1; /**< @brief Holds context for bp512r1 (Brainpool 512-bit). */ + nrf_crypto_ecc_curve25519_key_pair_generate_context_t context_curve25519; /**< @brief Holds context for Curve25519. */ + nrf_crypto_ecc_ed25519_key_pair_generate_context_t context_ed25519; /**< @brief Holds context for Ed25519. */ +} nrf_crypto_ecc_key_pair_generate_context_t; + + +/** @brief Union holding a context for a public key calculation. + */ +typedef union +{ + nrf_crypto_ecc_secp160r1_public_key_calculate_context_t context_secp160r1; /**< @brief Holds context for secp160r1 (NIST 160-bit). */ + nrf_crypto_ecc_secp160r2_public_key_calculate_context_t context_secp160r2; /**< @brief Holds context for secp160r2 (NIST 160-bit). */ + nrf_crypto_ecc_secp192r1_public_key_calculate_context_t context_secp192r1; /**< @brief Holds context for secp192r1 (NIST 192-bit). */ + nrf_crypto_ecc_secp224r1_public_key_calculate_context_t context_secp224r1; /**< @brief Holds context for secp224r1 (NIST 224-bit). */ + nrf_crypto_ecc_secp256r1_public_key_calculate_context_t context_secp256r1; /**< @brief Holds context for secp256r1 (NIST 256-bit). */ + nrf_crypto_ecc_secp384r1_public_key_calculate_context_t context_secp384r1; /**< @brief Holds context for secp384r1 (NIST 384-bit). */ + nrf_crypto_ecc_secp521r1_public_key_calculate_context_t context_secp521r1; /**< @brief Holds context for secp521r1 (NIST 521-bit). */ + nrf_crypto_ecc_secp160k1_public_key_calculate_context_t context_secp160k1; /**< @brief Holds context for secp160k1 (Koblitz 160-bit). */ + nrf_crypto_ecc_secp192k1_public_key_calculate_context_t context_secp192k1; /**< @brief Holds context for secp192k1 (Koblitz 192-bit). */ + nrf_crypto_ecc_secp224k1_public_key_calculate_context_t context_secp224k1; /**< @brief Holds context for secp224k1 (Koblitz 224-bit). */ + nrf_crypto_ecc_secp256k1_public_key_calculate_context_t context_secp256k1; /**< @brief Holds context for secp256k1 (Koblitz 256-bit). */ + nrf_crypto_ecc_bp256r1_public_key_calculate_context_t context_bp256r1; /**< @brief Holds context for bp256r1 (Brainpool 256-bit). */ + nrf_crypto_ecc_bp384r1_public_key_calculate_context_t context_bp384r1; /**< @brief Holds context for bp384r1 (Brainpool 384-bit). */ + nrf_crypto_ecc_bp512r1_public_key_calculate_context_t context_bp512r1; /**< @brief Holds context for bp512r1 (Brainpool 512-bit). */ + nrf_crypto_ecc_curve25519_public_key_calculate_context_t context_curve25519; /**< @brief Holds context for Curve25519. */ + nrf_crypto_ecc_ed25519_public_key_calculate_context_t context_ed25519; /**< @brief Holds context for Ed25519. */ +} nrf_crypto_ecc_public_key_calculate_context_t; + + +/** @brief Union holding representation of a private key for any curve type. + */ +typedef union +{ + nrf_crypto_ecc_secp160r1_private_key_t key_secp160r1; /**< @brief Holds internal representation of a private key for secp160r1 (NIST 160-bit). */ + nrf_crypto_ecc_secp160r2_private_key_t key_secp160r2; /**< @brief Holds internal representation of a private key for secp160r2 (NIST 160-bit). */ + nrf_crypto_ecc_secp192r1_private_key_t key_secp192r1; /**< @brief Holds internal representation of a private key for secp192r1 (NIST 192-bit). */ + nrf_crypto_ecc_secp224r1_private_key_t key_secp224r1; /**< @brief Holds internal representation of a private key for secp224r1 (NIST 224-bit). */ + nrf_crypto_ecc_secp256r1_private_key_t key_secp256r1; /**< @brief Holds internal representation of a private key for secp256r1 (NIST 256-bit). */ + nrf_crypto_ecc_secp384r1_private_key_t key_secp384r1; /**< @brief Holds internal representation of a private key for secp384r1 (NIST 384-bit). */ + nrf_crypto_ecc_secp521r1_private_key_t key_secp521r1; /**< @brief Holds internal representation of a private key for secp521r1 (NIST 521-bit). */ + nrf_crypto_ecc_secp160k1_private_key_t key_secp160k1; /**< @brief Holds internal representation of a private key for secp160k1 (Koblitz 160-bit). */ + nrf_crypto_ecc_secp192k1_private_key_t key_secp192k1; /**< @brief Holds internal representation of a private key for secp192k1 (Koblitz 192-bit). */ + nrf_crypto_ecc_secp224k1_private_key_t key_secp224k1; /**< @brief Holds internal representation of a private key for secp224k1 (Koblitz 224-bit). */ + nrf_crypto_ecc_secp256k1_private_key_t key_secp256k1; /**< @brief Holds internal representation of a private key for secp256k1 (Koblitz 256-bit). */ + nrf_crypto_ecc_bp256r1_private_key_t key_bp256r1; /**< @brief Holds internal representation of a private key for bp256r1 (Brainpool 256-bit). */ + nrf_crypto_ecc_bp384r1_private_key_t key_bp384r1; /**< @brief Holds internal representation of a private key for bp384r1 (Brainpool 384-bit). */ + nrf_crypto_ecc_bp512r1_private_key_t key_bp512r1; /**< @brief Holds internal representation of a private key for bp512r1 (Brainpool 512-bit). */ + nrf_crypto_ecc_curve25519_private_key_t key_curve25519; /**< @brief Holds internal representation of a private key for Curve25519. */ + nrf_crypto_ecc_ed25519_private_key_t key_ed25519; /**< @brief Holds internal representation of a private key for Ed25519. */ +} nrf_crypto_ecc_private_key_t; + + +/** @brief Union holding representation of a public key for any curve type. + */ +typedef union +{ + nrf_crypto_ecc_secp160r1_public_key_t key_secp160r1; /**< @brief Holds internal representation of a public key for secp160r1 (NIST 160-bit). */ + nrf_crypto_ecc_secp160r2_public_key_t key_secp160r2; /**< @brief Holds internal representation of a public key for secp160r2 (NIST 160-bit). */ + nrf_crypto_ecc_secp192r1_public_key_t key_secp192r1; /**< @brief Holds internal representation of a public key for secp192r1 (NIST 192-bit). */ + nrf_crypto_ecc_secp224r1_public_key_t key_secp224r1; /**< @brief Holds internal representation of a public key for secp224r1 (NIST 224-bit). */ + nrf_crypto_ecc_secp256r1_public_key_t key_secp256r1; /**< @brief Holds internal representation of a public key for secp256r1 (NIST 256-bit). */ + nrf_crypto_ecc_secp384r1_public_key_t key_secp384r1; /**< @brief Holds internal representation of a public key for secp384r1 (NIST 384-bit). */ + nrf_crypto_ecc_secp521r1_public_key_t key_secp521r1; /**< @brief Holds internal representation of a public key for secp521r1 (NIST 521-bit). */ + nrf_crypto_ecc_secp160k1_public_key_t key_secp160k1; /**< @brief Holds internal representation of a public key for secp160k1 (Koblitz 160-bit). */ + nrf_crypto_ecc_secp192k1_public_key_t key_secp192k1; /**< @brief Holds internal representation of a public key for secp192k1 (Koblitz 192-bit). */ + nrf_crypto_ecc_secp224k1_public_key_t key_secp224k1; /**< @brief Holds internal representation of a public key for secp224k1 (Koblitz 224-bit). */ + nrf_crypto_ecc_secp256k1_public_key_t key_secp256k1; /**< @brief Holds internal representation of a public key for secp256k1 (Koblitz 256-bit). */ + nrf_crypto_ecc_bp256r1_public_key_t key_bp256r1; /**< @brief Holds internal representation of a public key for bp256r1 (Brainpool 256-bit). */ + nrf_crypto_ecc_bp384r1_public_key_t key_bp384r1; /**< @brief Holds internal representation of a public key for bp384r1 (Brainpool 384-bit). */ + nrf_crypto_ecc_bp512r1_public_key_t key_bp512r1; /**< @brief Holds internal representation of a public key for bp512r1 (Brainpool 512-bit). */ + nrf_crypto_ecc_curve25519_public_key_t key_curve25519; /**< @brief Holds internal representation of a public key for Curve25519. */ + nrf_crypto_ecc_ed25519_public_key_t key_ed25519; /**< @brief Holds internal representation of a public key for Ed25519. */ +} nrf_crypto_ecc_public_key_t; + + +/** @brief Generate a new pair of a public key and a private key. + * + * Generated keys have to deallocated using @ref nrf_crypto_ecc_private_key_free and + * @ref nrf_crypto_ecc_public_key_free. + * @param[in] p_context Pointer to temporary structure holding context information. + * If it is NULL, necessary data will be allocated with + * @ref NRF_CRYPTO_ALLOC and freed at the end of the function. + * @param[in] p_curve_info Pointer to information on selected curve. Use only global variables + * defined by nrf_crypto, e.g. @ref g_nrf_crypto_ecc_secp256r1_curve_info. + * @param[out] p_private_key Pointer to structure where newly generated private key will be put. + * @param[out] p_public_key Pointer to structure where newly generated public key will be put. + */ +ret_code_t nrf_crypto_ecc_key_pair_generate( + nrf_crypto_ecc_key_pair_generate_context_t * p_context, + nrf_crypto_ecc_curve_info_t const * p_curve_info, + nrf_crypto_ecc_private_key_t * p_private_key, + nrf_crypto_ecc_public_key_t * p_public_key); + + +/** @brief Calculate public key associated with provided private key. + * + * Calculated public key has to be deallocated using @ref nrf_crypto_ecc_public_key_free. + * @param[in] p_context Pointer to temporary structure holding context information. + * If it is NULL, necessary data will be allocated with + * @ref NRF_CRYPTO_ALLOC and freed at the end of the function. + * @param[in] p_private_key Pointer to structure holding a private key that will be used for computation. + * @param[out] p_public_key Pointer to structure where newly generated public key will be put. + */ +ret_code_t nrf_crypto_ecc_public_key_calculate( + nrf_crypto_ecc_public_key_calculate_context_t * p_context, + nrf_crypto_ecc_private_key_t const * p_private_key, + nrf_crypto_ecc_public_key_t * p_public_key); + + +/** @brief Create a private key from a raw data. + * + * Generated private key has to be deallocated using @ref nrf_crypto_ecc_private_key_free. + * + * @note Ed25519 only: Memory is allocated internally using @ref nrf_crypto_mem. + * + * @param[in] p_curve_info Pointer to information on selected curve. Use only global variables + * defined by nrf_crypto, e.g. @ref g_nrf_crypto_ecc_secp256r1_curve_info. + * @param[out] p_private_key Pointer to structure where newly converted private key will be put. + * @param[in] p_raw_data Pointer to buffer containing a big endian raw data. + * @param[in] raw_data_size Number of bytes of a raw data. Correct size for selected curve can be found in + * @p p_curve_info and it is also defined by the preprocessor definitions, e.g. + * @ref NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE. + */ +ret_code_t nrf_crypto_ecc_private_key_from_raw( + nrf_crypto_ecc_curve_info_t const * p_curve_info, + nrf_crypto_ecc_private_key_t * p_private_key, + uint8_t const * p_raw_data, + size_t raw_data_size); + + +/** @brief Convert a private key to a raw data. + * + * @param[in] p_private_key Pointer to structure holding private key that will be convert. + * @param[out] p_raw_data Pointer to buffer containing a big endian raw data. + * @param[in,out] p_raw_data_size Maximum number of bytes that @p p_raw_data buffer can hold on input + * and the actual number of bytes used by the raw data on output. + * Actual size for selected curve can be found in + * @ref nrf_crypto_ecc_curve_info_t and it is also defined by + * the preprocessor definitions, e.g. + * @ref NRF_CRYPTO_ECC_SECP256R1_RAW_PRIVATE_KEY_SIZE. + */ +ret_code_t nrf_crypto_ecc_private_key_to_raw( + nrf_crypto_ecc_private_key_t const * p_private_key, + uint8_t * p_raw_data, + size_t * p_raw_data_size); + + +/** @brief Create a public key from a raw data. + * + * Generated public key has to be deallocated using @ref nrf_crypto_ecc_public_key_free. + * @param[in] p_curve_info Pointer to information on selected curve. Use only global variables + * defined by nrf_crypto, e.g. @ref g_nrf_crypto_ecc_secp256r1_curve_info. + * @param[out] p_public_key Pointer to structure where newly converted public key will be put. + * @param[in] p_raw_data Pointer to buffer containing a big endian raw data. + * @param[in] raw_data_size Number of bytes of a raw data. Correct size for selected curve can be found in + * @p p_curve_info and it is also defined by the preprocessor definitions, e.g. + * @ref NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE. + */ +ret_code_t nrf_crypto_ecc_public_key_from_raw( + nrf_crypto_ecc_curve_info_t const * p_curve_info, + nrf_crypto_ecc_public_key_t * p_public_key, + uint8_t const * p_raw_data, + size_t raw_data_size); + + +/** @brief Convert a public key to a raw data. + * + * @param[in] p_public_key Pointer to structure holding public key that will be convert. + * @param[out] p_raw_data Pointer to buffer containing a big endian raw data. + * @param[in,out] p_raw_data_size Maximum number of bytes that @p p_raw_data buffer can hold on input + * and the actual number of bytes used by the raw data on output. + * Actual size for selected curve can be found in + * @ref nrf_crypto_ecc_curve_info_t and it is also defined by + * the preprocessor definitions, e.g. + * @ref NRF_CRYPTO_ECC_SECP256R1_RAW_PUBLIC_KEY_SIZE. + */ +ret_code_t nrf_crypto_ecc_public_key_to_raw( + nrf_crypto_ecc_public_key_t const * p_public_key, + uint8_t * p_raw_data, + size_t * p_raw_data_size); + + +/** @brief Release resources taken by a private key. + * + * @param[in] p_private_key Pointer to structure holding private key to release. + */ +ret_code_t nrf_crypto_ecc_private_key_free( + nrf_crypto_ecc_private_key_t * p_private_key); + + +/** @brief Release resources taken by a public key. + * + * @param[in] p_public_key Pointer to structure holding public key to release. + */ +ret_code_t nrf_crypto_ecc_public_key_free( + nrf_crypto_ecc_public_key_t * p_public_key); + + +/** @brief Gets curve information structure from provided key (private or public). + * + * @param[in] p_key Pointer to structure holding private or public key. + * @param[out] pp_curve_info Pointer to location where put retrieved pointer to curve information structure. + */ +ret_code_t nrf_crypto_ecc_curve_info_get( + void const * p_key, + nrf_crypto_ecc_curve_info_t const ** pp_curve_info); + + +/** @brief Inverts byte order of a big integers contained in a raw data. + * + * All the ECC API accepts only data with big endian integers, so this function have to be used + * if little endian is required. If input is in little endian byte order it will be converted + * to big endian. If input is in big endian byte order it will be converted to little endian. + * It works for ECC raw private key, raw public key, signature and shared secret. If raw data + * contains two big integers (e.g. R, S, or X, Y) each integer is inverted separately. + * If @p p_curve_info is NULL then all bytes in buffer will be inverted regardless what is the + * content of the buffer. + * + * @param[in] p_curve_info Pointer to information on selected curve. Use only global variables + * defined by nrf_crypto, e.g. @ref g_nrf_crypto_ecc_secp256r1_curve_info. + * @param[in] p_raw_input Pointer to buffer holding source data. + * @param[out] p_raw_output Pointer to buffer that will be filled with inverted byte order. + * This parameter can be the same as @p p_raw_input, otherwise the + * buffers cannot overlap. + * @param[in] raw_data_size Size of input and output buffer. + */ +ret_code_t nrf_crypto_ecc_byte_order_invert( + nrf_crypto_ecc_curve_info_t const * p_curve_info, + uint8_t const * p_raw_input, + uint8_t * p_raw_output, + size_t raw_data_size); + + +#ifdef __cplusplus +} +#endif + +/** @} + * @} + */ + +#endif // NRF_CRYPTO_ECC_H__ diff --git a/components/libraries/crypto/nrf_crypto_ecc_backend.h b/components/libraries/crypto/nrf_crypto_ecc_backend.h new file mode 100644 index 0000000..4f2d366 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_ecc_backend.h @@ -0,0 +1,356 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_ECC_BACKEND_H__ +#define NRF_CRYPTO_ECC_BACKEND_H__ +#if !defined(__SDK_DOXYGEN__) + +#include +#include + +#include "sdk_config.h" +#include "nordic_common.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_ecc_shared.h" + +// Include all backends +#include "cc310_backend_ecc.h" +#include "cc310_bl_backend_ecc.h" +#include "mbedtls_backend_ecc.h" +#include "oberon_backend_ecc.h" +#include "micro_ecc_backend_ecc.h" +#include "optiga_backend_ecc.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +// Make sure that all required defines are defined +#if !defined(NRF_CRYPTO_ECC_SECP160R1_ENABLED) +#define NRF_CRYPTO_ECC_SECP160R1_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_SECP160R2_ENABLED) +#define NRF_CRYPTO_ECC_SECP160R2_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_SECP192R1_ENABLED) +#define NRF_CRYPTO_ECC_SECP192R1_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_SECP224R1_ENABLED) +#define NRF_CRYPTO_ECC_SECP224R1_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_SECP256R1_ENABLED) +#define NRF_CRYPTO_ECC_SECP256R1_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_SECP384R1_ENABLED) +#define NRF_CRYPTO_ECC_SECP384R1_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_SECP521R1_ENABLED) +#define NRF_CRYPTO_ECC_SECP521R1_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_SECP160K1_ENABLED) +#define NRF_CRYPTO_ECC_SECP160K1_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_SECP192K1_ENABLED) +#define NRF_CRYPTO_ECC_SECP192K1_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_SECP224K1_ENABLED) +#define NRF_CRYPTO_ECC_SECP224K1_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_SECP256K1_ENABLED) +#define NRF_CRYPTO_ECC_SECP256K1_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_BP256R1_ENABLED) +#define NRF_CRYPTO_ECC_BP256R1_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_BP384R1_ENABLED) +#define NRF_CRYPTO_ECC_BP384R1_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_BP512R1_ENABLED) +#define NRF_CRYPTO_ECC_BP512R1_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_CURVE25519_ENABLED) +#define NRF_CRYPTO_ECC_CURVE25519_ENABLED 0 +#endif +#if !defined(NRF_CRYPTO_ECC_ED25519_ENABLED) +#define NRF_CRYPTO_ECC_ED25519_ENABLED 0 +#endif + + +/** @internal @brief Definition to detect if ECC submodule is enabled. It will be enabled if any + * curve of any of the backends is enabled. + */ +#define NRF_CRYPTO_ECC_ENABLED ( \ + NRF_MODULE_ENABLED(NRF_CRYPTO) && ( \ + NRF_CRYPTO_ECC_SECP160R1_ENABLED | \ + NRF_CRYPTO_ECC_SECP160R2_ENABLED | \ + NRF_CRYPTO_ECC_SECP192R1_ENABLED | \ + NRF_CRYPTO_ECC_SECP224R1_ENABLED | \ + NRF_CRYPTO_ECC_SECP256R1_ENABLED | \ + NRF_CRYPTO_ECC_SECP384R1_ENABLED | \ + NRF_CRYPTO_ECC_SECP521R1_ENABLED | \ + NRF_CRYPTO_ECC_SECP160K1_ENABLED | \ + NRF_CRYPTO_ECC_SECP192K1_ENABLED | \ + NRF_CRYPTO_ECC_SECP224K1_ENABLED | \ + NRF_CRYPTO_ECC_SECP256K1_ENABLED | \ + NRF_CRYPTO_ECC_BP256R1_ENABLED | \ + NRF_CRYPTO_ECC_BP384R1_ENABLED | \ + NRF_CRYPTO_ECC_BP512R1_ENABLED | \ + NRF_CRYPTO_ECC_CURVE25519_ENABLED | \ + NRF_CRYPTO_ECC_ED25519_ENABLED)) + + +/** @internal @brief Definition containing number of enabled curves. + */ +#define NRF_CRYPTO_ECC_IMPLEMENTED_CURVES_COUNT ( \ + NRF_CRYPTO_ECC_SECP160R1_ENABLED + \ + NRF_CRYPTO_ECC_SECP160R2_ENABLED + \ + NRF_CRYPTO_ECC_SECP192R1_ENABLED + \ + NRF_CRYPTO_ECC_SECP224R1_ENABLED + \ + NRF_CRYPTO_ECC_SECP256R1_ENABLED + \ + NRF_CRYPTO_ECC_SECP384R1_ENABLED + \ + NRF_CRYPTO_ECC_SECP521R1_ENABLED + \ + NRF_CRYPTO_ECC_SECP160K1_ENABLED + \ + NRF_CRYPTO_ECC_SECP192K1_ENABLED + \ + NRF_CRYPTO_ECC_SECP224K1_ENABLED + \ + NRF_CRYPTO_ECC_SECP256K1_ENABLED + \ + NRF_CRYPTO_ECC_BP256R1_ENABLED + \ + NRF_CRYPTO_ECC_BP384R1_ENABLED + \ + NRF_CRYPTO_ECC_BP512R1_ENABLED + \ + NRF_CRYPTO_ECC_CURVE25519_ENABLED + \ + NRF_CRYPTO_ECC_ED25519_ENABLED) + + +#if !NRF_CRYPTO_ECC_SECP160R1_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_secp160r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp160r1_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp160r1_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp160r1_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_SECP160R2_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_secp160r2_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp160r2_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp160r2_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp160r2_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_SECP192R1_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_secp192r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp192r1_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp192r1_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp192r1_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_SECP224R1_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_secp224r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp224r1_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp224r1_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp224r1_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_SECP256R1_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_secp256r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp256r1_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp256r1_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp256r1_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_SECP384R1_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_secp384r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp384r1_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp384r1_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp384r1_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_SECP521R1_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_secp521r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp521r1_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp521r1_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp521r1_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_SECP160K1_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_secp160k1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp160k1_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp160k1_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp160k1_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_SECP192K1_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_secp192k1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp192k1_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp192k1_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp192k1_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_SECP224K1_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_secp224k1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp224k1_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp224k1_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp224k1_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_SECP256K1_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_secp256k1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_secp256k1_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp256k1_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_secp256k1_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_BP256R1_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_bp256r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_bp256r1_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_bp256r1_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_bp256r1_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_BP384R1_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_bp384r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_bp384r1_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_bp384r1_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_bp384r1_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_BP512R1_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_bp512r1_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_bp512r1_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_bp512r1_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_bp512r1_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_CURVE25519_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_curve25519_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_curve25519_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_curve25519_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_curve25519_public_key_t; +#endif + +#if !NRF_CRYPTO_ECC_ED25519_ENABLED +// Dummy typedefs for disabled contexts +typedef uint32_t nrf_crypto_backend_ed25519_key_pair_generate_context_t; +typedef uint32_t nrf_crypto_backend_ed25519_public_key_calculate_context_t; +// Dummy typedefs for disabled keys +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_ed25519_private_key_t; +typedef nrf_crypto_internal_ecc_key_header_t nrf_crypto_backend_ed25519_public_key_t; +#endif + + +// Find biggest raw private and public key size that is currently enabled +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (66) +#elif NRF_CRYPTO_ECC_BP512R1_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (64) +#elif NRF_CRYPTO_ECC_BP384R1_ENABLED || NRF_CRYPTO_ECC_SECP384R1_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (48) +#elif NRF_CRYPTO_ECC_BP256R1_ENABLED || NRF_CRYPTO_ECC_SECP256K1_ENABLED || NRF_CRYPTO_ECC_CURVE25519_ENABLED || NRF_CRYPTO_ECC_ED25519_ENABLED || NRF_CRYPTO_ECC_SECP256R1_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (32) +#elif NRF_CRYPTO_ECC_SECP224K1_ENABLED || NRF_CRYPTO_ECC_SECP224R1_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (28) +#elif NRF_CRYPTO_ECC_SECP192K1_ENABLED || NRF_CRYPTO_ECC_SECP192R1_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (24) +#elif NRF_CRYPTO_ECC_SECP160K1_ENABLED || NRF_CRYPTO_ECC_SECP160R1_ENABLED || NRF_CRYPTO_ECC_SECP160R2_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (20) +#else +# define NRF_CRYPTO_BACKEND_ECC_RAW_PRIVATE_KEY_MAX_SIZE (1) +#endif + +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (2 * 66) +#elif NRF_CRYPTO_ECC_BP512R1_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (2 * 64) +#elif NRF_CRYPTO_ECC_BP384R1_ENABLED || NRF_CRYPTO_ECC_SECP384R1_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (2 * 48) +#elif NRF_CRYPTO_ECC_BP256R1_ENABLED || NRF_CRYPTO_ECC_SECP256K1_ENABLED || NRF_CRYPTO_ECC_SECP256R1_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (2 * 32) +#elif NRF_CRYPTO_ECC_SECP224K1_ENABLED || NRF_CRYPTO_ECC_SECP224R1_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (2 * 28) +#elif NRF_CRYPTO_ECC_SECP192K1_ENABLED || NRF_CRYPTO_ECC_SECP192R1_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (2 * 24) +#elif NRF_CRYPTO_ECC_SECP160K1_ENABLED || NRF_CRYPTO_ECC_SECP160R1_ENABLED || NRF_CRYPTO_ECC_SECP160R2_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (2 * 20) +#elif NRF_CRYPTO_ECC_CURVE25519_ENABLED || NRF_CRYPTO_ECC_ED25519_ENABLED +# define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (32) +#else +# define NRF_CRYPTO_BACKEND_ECC_RAW_PUBLIC_KEY_MAX_SIZE (1) +#endif + +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED && !defined(NRF_CRYPTO_CURVE25519_BIG_ENDIAN_ENABLED) +#warning "NRF_CRYPTO_CURVE25519_BIG_ENDIAN_ENABLED not defined. Please define it to choose the endianness of Curve25519 parameters." +#endif + +#ifdef __cplusplus +} +#endif + + +#endif // !defined(__SDK_DOXYGEN__) +#endif // NRF_CRYPTO_ECC_BACKEND_H__ diff --git a/components/libraries/crypto/nrf_crypto_ecc_shared.h b/components/libraries/crypto/nrf_crypto_ecc_shared.h new file mode 100644 index 0000000..401cb84 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_ecc_shared.h @@ -0,0 +1,229 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_ECC_SHARED_H__ +#define NRF_CRYPTO_ECC_SHARED_H__ +#if !defined(__SDK_DOXYGEN__) + +#include +#include +#include + +#include "sdk_errors.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE (0x4D465276) /**< @internal @brief Init value for all ECC private keys. ASCII "nRFv". */ +#define NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE (0x4D465270) /**< @internal @brief Init value for all ECC public keys. ASCII "nRFp". */ + + +// Forward declaration only +struct nrf_crypto_ecc_curve_info_s; + + +/** @brief Header structure at the beginning of each key structure. + */ +typedef struct +{ + uint32_t init_value; /**< @internal @brief Init value to check if key was correctly initialized. */ + struct nrf_crypto_ecc_curve_info_s const * p_info; /**< @internal @brief Points to information structure of an associated curve type. */ +} nrf_crypto_internal_ecc_key_header_t; + + +/** @internal @brief Function pointer for backend implementation of a key pair garatarion. + * + * @note All parameters provided to the backend are vefified in frontend. Verification includes + * checking of NULL pointers, buffer size, initialization values. Front end also take full care of + * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t. + * + * @param[in] p_context Pointer to context. + * @param[out] p_private_key Pointer where to put new private key. + * @param[out] p_public_key Pointer where to put new public key. + */ +typedef ret_code_t (*nrf_crypto_backend_ecc_key_pair_generate_fn_t)( + void * p_context, + void * p_private_key, + void * p_public_key); + + +/** @internal @brief Function pointer for backend implementation of a public key calculation. + * + * @note All parameters provided to the backend are vefified in frontend. Verification includes + * checking of NULL pointers, buffer size, initialization values. Front end also take full care of + * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t. + * + * @param[in] p_context Pointer to context. + * @param[in] p_private_key Pointer to private key. + * @param[out] p_public_key Pointer where to put new public key. + */ +typedef ret_code_t (*nrf_crypto_backend_ecc_public_key_calculate_fn_t)( + void * p_context, + void const * p_private_key, + void * p_public_key); + + +/** @internal @brief Function pointer for backend implementation of raw to private key conversion. + * + * @note All parameters provided to the backend are vefified in frontend. Verification includes + * checking of NULL pointers, buffer size, initialization values. Front end also take full care of + * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t. + * + * @param[out] p_private_key Pointer where to put new private key. + * @param[in] p_raw_data Pointer to raw data. + */ +typedef ret_code_t (*nrf_crypto_backend_ecc_private_key_from_raw_fn_t)( + void * p_private_key, + uint8_t const * p_raw_data); + + +/** @internal @brief Function pointer for backend implementation of private key to raw conversion. + * + * @note All parameters provided to the backend are vefified in frontend. Verification includes + * checking of NULL pointers, buffer size, initialization values. Front end also take full care of + * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t. + * + * @param[in] p_private_key Pointer to private key. + * @param[out] p_raw_data Pointer where to put raw data. + */ +typedef ret_code_t (*nrf_crypto_backend_ecc_private_key_to_raw_fn_t)( + void const * p_private_key, + uint8_t * p_raw_data); + + +/** @internal @brief Function pointer for backend implementation of raw to public key conversion. + * + * @note All parameters provided to the backend are vefified in frontend. Verification includes + * checking of NULL pointers, buffer size, initialization values. Front end also take full care of + * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t. + * + * @param[out] p_public_key Pointer where to put new public key. + * @param[in] p_raw_data Pointer to raw data. + */ +typedef ret_code_t (*nrf_crypto_backend_ecc_public_key_from_raw_fn_t)( + void * p_public_key, + uint8_t const * p_raw_data); + + +/** @internal @brief Function pointer for backend implementation of public key to raw conversion. + * + * @note All parameters provided to the backend are vefified in frontend. Verification includes + * checking of NULL pointers, buffer size, initialization values. Front end also take full care of + * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t. + * + * @param[in] p_public_key Pointer to public key. + * @param[out] p_raw_data Pointer where to put raw data. + */ +typedef ret_code_t (*nrf_crypto_backend_ecc_public_key_to_raw_fn_t)( + void const * p_public_key, + uint8_t * p_raw_data); + + +/** @internal @brief Function pointer for backend implementation of key (public or private) deallocation. + * + * @note All parameters provided to the backend are vefified in frontend. Verification includes + * checking of NULL pointers, buffer size, initialization values. Front end also take full care of + * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t. + * + * @param[in] p_key Pointer to public or private key. + */ +typedef ret_code_t (*nrf_crypto_backend_ecc_key_free_fn_t)( + void * p_key); + + +/** @internal @brief Function for checking and preparing ECC key output parameter. + * + * @param[in] p_curve_info Curve info provided by user that will be used to create a new key. + * @param[out] p_key_header Key header that have to be prepared. + * @return NRF_SUCCESS if parameters are valid, error otherwise. + */ +ret_code_t nrf_crypto_internal_ecc_key_output_prepare( + struct nrf_crypto_ecc_curve_info_s const * p_curve_info, + nrf_crypto_internal_ecc_key_header_t * p_key_header); + + +/** @internal @brief Function for checking ECC key input parameter. + * + * @param[in] p_key_header Key header that have to be checked. + * @param[in] init_value Expected init value in this key. + * @return NRF_SUCCESS if parameter is valid, error otherwise. + */ +ret_code_t nrf_crypto_internal_ecc_key_input_check( + nrf_crypto_internal_ecc_key_header_t const * p_key_header, + uint32_t init_value); + + +/** @internal @brief Function for checking and preparing raw data output parameter. + * + * @param[out] p_raw_data Buffer where output will be written. + * @param[in,out] p_raw_data_size Pointer to size of the data. On input this is size of provided by + * the user buffer. On output is equal @p expected_size. This pointer + * can be NULL if used does not want to do size checking. + * @param[in] expected_size Size of output data that will be written to the buffer. + * @return NRF_SUCCESS if parameters are valid, error otherwise. + */ +ret_code_t nrf_crypto_internal_ecc_raw_output_prepare( + uint8_t * p_raw_data, + size_t * p_raw_data_size, + size_t expected_size); + + +/** @internal @brief Function for checking raw data input parameter. + * + * @param[in] p_raw_data Buffer where data is located. + * @param[in] raw_data_size Size of the data.Function will fail if it is different than @p expected_size. + * @param[in] expected_size Expected size of the data. + * @return NRF_SUCCESS if parameters are valid, error otherwise. + */ +ret_code_t nrf_crypto_internal_ecc_raw_input_check( + uint8_t const * p_raw_data, + size_t raw_data_size, + size_t expected_size); + + +#ifdef __cplusplus +} +#endif + +#endif // !defined(__SDK_DOXYGEN__) +#endif // NRF_CRYPTO_ECC_SHARED_H__ diff --git a/components/libraries/crypto/nrf_crypto_ecdh.c b/components/libraries/crypto/nrf_crypto_ecdh.c new file mode 100644 index 0000000..3f0977b --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_ecdh.c @@ -0,0 +1,277 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_crypto_error.h" +#include "nrf_crypto_mem.h" +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdh.h" +#include "app_util.h" +#include "sdk_macros.h" + + +#if NRF_CRYPTO_ECC_ENABLED + + +#if NRF_CRYPTO_ECC_IMPLEMENTED_CURVES_COUNT > 1 + + +static const nrf_crypto_backend_ecdh_compute_fn_t compute_impl[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + nrf_crypto_backend_secp160r1_ecdh_compute, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + nrf_crypto_backend_secp160r2_ecdh_compute, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + nrf_crypto_backend_secp192r1_ecdh_compute, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + nrf_crypto_backend_secp224r1_ecdh_compute, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + nrf_crypto_backend_secp256r1_ecdh_compute, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + nrf_crypto_backend_secp384r1_ecdh_compute, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + nrf_crypto_backend_secp521r1_ecdh_compute, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + nrf_crypto_backend_secp160k1_ecdh_compute, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + nrf_crypto_backend_secp192k1_ecdh_compute, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + nrf_crypto_backend_secp224k1_ecdh_compute, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + nrf_crypto_backend_secp256k1_ecdh_compute, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + nrf_crypto_backend_bp256r1_ecdh_compute, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + nrf_crypto_backend_bp384r1_ecdh_compute, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + nrf_crypto_backend_bp512r1_ecdh_compute, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + nrf_crypto_backend_curve25519_ecdh_compute, +#endif +}; + + +static const uint16_t compute_impl_context_size[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + NRF_CRYPTO_BACKEND_SECP160R1_ECDH_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + NRF_CRYPTO_BACKEND_SECP160R2_ECDH_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + NRF_CRYPTO_BACKEND_SECP192R1_ECDH_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + NRF_CRYPTO_BACKEND_SECP224R1_ECDH_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + NRF_CRYPTO_BACKEND_SECP256R1_ECDH_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + NRF_CRYPTO_BACKEND_SECP384R1_ECDH_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + NRF_CRYPTO_BACKEND_SECP521R1_ECDH_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + NRF_CRYPTO_BACKEND_SECP160K1_ECDH_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + NRF_CRYPTO_BACKEND_SECP192K1_ECDH_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + NRF_CRYPTO_BACKEND_SECP224K1_ECDH_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + NRF_CRYPTO_BACKEND_SECP256K1_ECDH_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + NRF_CRYPTO_BACKEND_BP256R1_ECDH_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + NRF_CRYPTO_BACKEND_BP384R1_ECDH_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + NRF_CRYPTO_BACKEND_BP512R1_ECDH_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + NRF_CRYPTO_BACKEND_CURVE25519_ECDH_CONTEXT_SIZE, +#endif +}; + +#define BACKEND_IMPL_GET(table, curve_type) (table)[(uint32_t)(curve_type)] + +#else + + +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED +#define compute_impl nrf_crypto_backend_secp160r1_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP160R1_ECDH_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP160R2_ENABLED +#define compute_impl nrf_crypto_backend_secp160r2_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP160R2_ECDH_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP192R1_ENABLED +#define compute_impl nrf_crypto_backend_secp192r1_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP192R1_ECDH_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP224R1_ENABLED +#define compute_impl nrf_crypto_backend_secp224r1_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP224R1_ECDH_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP256R1_ENABLED +#define compute_impl nrf_crypto_backend_secp256r1_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP256R1_ECDH_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP384R1_ENABLED +#define compute_impl nrf_crypto_backend_secp384r1_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP384R1_ECDH_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP521R1_ENABLED +#define compute_impl nrf_crypto_backend_secp521r1_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP521R1_ECDH_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP160K1_ENABLED +#define compute_impl nrf_crypto_backend_secp160k1_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP160K1_ECDH_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP192K1_ENABLED +#define compute_impl nrf_crypto_backend_secp192k1_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP192K1_ECDH_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP224K1_ENABLED +#define compute_impl nrf_crypto_backend_secp224k1_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP224K1_ECDH_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP256K1_ENABLED +#define compute_impl nrf_crypto_backend_secp256k1_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_SECP256K1_ECDH_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_BP256R1_ENABLED +#define compute_impl nrf_crypto_backend_bp256r1_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_BP256R1_ECDH_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_BP384R1_ENABLED +#define compute_impl nrf_crypto_backend_bp384r1_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_BP384R1_ECDH_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_BP512R1_ENABLED +#define compute_impl nrf_crypto_backend_bp512r1_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_BP512R1_ECDH_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_CURVE25519_ENABLED +#define compute_impl nrf_crypto_backend_curve25519_ecdh_compute +#define compute_impl_context_size NRF_CRYPTO_BACKEND_CURVE25519_ECDH_CONTEXT_SIZE +#else +#define compute_impl NULL +#define compute_impl_context_size 0 +#endif + +#define BACKEND_IMPL_GET(function, curve_type) (function) + +#endif + + +ret_code_t nrf_crypto_ecdh_compute( + nrf_crypto_ecdh_context_t * p_context, + nrf_crypto_ecc_private_key_t const * p_private_key, + nrf_crypto_ecc_public_key_t const * p_public_key, + uint8_t * p_shared_secret, + size_t * p_shared_secret_size) +{ + ret_code_t result; + void * p_allocated_context = NULL; + nrf_crypto_backend_ecdh_compute_fn_t backend_implementation; + size_t context_size; + nrf_crypto_ecc_curve_info_t const * p_info; + + // Get pointer to header for each key + nrf_crypto_internal_ecc_key_header_t const * p_private_key_header = + (nrf_crypto_internal_ecc_key_header_t const *)p_private_key; + nrf_crypto_internal_ecc_key_header_t const * p_public_key_header = + (nrf_crypto_internal_ecc_key_header_t const *)p_public_key; + + // Check and prepare parameters + result = nrf_crypto_internal_ecc_key_input_check( + p_private_key_header, + NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE); + VERIFY_SUCCESS(result); + result = nrf_crypto_internal_ecc_key_input_check( + p_public_key_header, + NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE); + VERIFY_SUCCESS(result); + VERIFY_TRUE(p_private_key_header->p_info == p_public_key_header->p_info, + NRF_ERROR_CRYPTO_ECDH_CURVE_MISMATCH); + p_info = p_private_key_header->p_info; + result = nrf_crypto_internal_ecc_raw_output_prepare( + p_shared_secret, + p_shared_secret_size, + p_info->raw_private_key_size); + VERIFY_SUCCESS(result); + + // Get backend specific information + backend_implementation = BACKEND_IMPL_GET(compute_impl, p_info->curve_type); + context_size = BACKEND_IMPL_GET(compute_impl_context_size, p_info->curve_type); + VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE); + + // Allocate context if not provided + if (p_context == NULL && context_size > 0) + { + p_allocated_context = NRF_CRYPTO_ALLOC(context_size); + VERIFY_TRUE(p_allocated_context != NULL, NRF_ERROR_CRYPTO_ALLOC_FAILED); + p_context = p_allocated_context; + } + + // Execute backend implementation + result = backend_implementation(p_context, p_private_key, p_public_key, p_shared_secret); + + // Deallocate context if allocated + if (p_allocated_context != NULL) + { + NRF_CRYPTO_FREE(p_allocated_context); + } + + return result; +} + + +#endif // NRF_CRYPTO_ECC_ENABLED diff --git a/components/libraries/crypto/nrf_crypto_ecdh.h b/components/libraries/crypto/nrf_crypto_ecdh.h new file mode 100644 index 0000000..12e2527 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_ecdh.h @@ -0,0 +1,201 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_ECDH_H__ +#define NRF_CRYPTO_ECDH_H__ + +/** @addtogroup nrf_crypto + * @{ + * @addtogroup nrf_crypto_ecdh Elliptic Curve Diffie-Hellman (ECDH) + * @{ + * @brief Provides elliptic curve cryptography functions for Diffie-Hellman shared secret exchange. + * + * @addtogroup nrf_crypto_ecdh_secp160r1 Definitions specific to secp160r1 (NIST 160-bit) + * @addtogroup nrf_crypto_ecdh_secp160r2 Definitions specific to secp160r2 (NIST 160-bit) + * @addtogroup nrf_crypto_ecdh_secp192r1 Definitions specific to secp192r1 (NIST 192-bit) + * @addtogroup nrf_crypto_ecdh_secp224r1 Definitions specific to secp224r1 (NIST 224-bit) + * @addtogroup nrf_crypto_ecdh_secp256r1 Definitions specific to secp256r1 (NIST 256-bit) + * @addtogroup nrf_crypto_ecdh_secp384r1 Definitions specific to secp384r1 (NIST 384-bit) + * @addtogroup nrf_crypto_ecdh_secp521r1 Definitions specific to secp521r1 (NIST 521-bit) + * @addtogroup nrf_crypto_ecdh_secp160k1 Definitions specific to secp160k1 (Koblitz 160-bit) + * @addtogroup nrf_crypto_ecdh_secp192k1 Definitions specific to secp192k1 (Koblitz 192-bit) + * @addtogroup nrf_crypto_ecdh_secp224k1 Definitions specific to secp224k1 (Koblitz 224-bit) + * @addtogroup nrf_crypto_ecdh_secp256k1 Definitions specific to secp256k1 (Koblitz 256-bit) + * @addtogroup nrf_crypto_ecdh_bp256r1 Definitions specific to bp256r1 (Brainpool 256-bit) + * @addtogroup nrf_crypto_ecdh_bp384r1 Definitions specific to bp384r1 (Brainpool 384-bit) + * @addtogroup nrf_crypto_ecdh_bp512r1 Definitions specific to bp512r1 (Brainpool 512-bit) + * @addtogroup nrf_crypto_ecdh_curve25519 Definitions specific to Curve25519 + */ + +#include +#include + +#include "nrf_crypto_error.h" +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdh_shared.h" +#include "nrf_crypto_ecdh_backend.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define NRF_CRYPTO_ECDH_SECP160R1_SHARED_SECRET_SIZE (160 / 8) /**< @brief Number of bytes in a shared secret using secp160r1 (NIST 160-bit). @ingroup nrf_crypto_ecdh_secp160r1 */ +#define NRF_CRYPTO_ECDH_SECP160R2_SHARED_SECRET_SIZE (160 / 8) /**< @brief Number of bytes in a shared secret using secp160r2 (NIST 160-bit). @ingroup nrf_crypto_ecdh_secp160r2 */ +#define NRF_CRYPTO_ECDH_SECP192R1_SHARED_SECRET_SIZE (192 / 8) /**< @brief Number of bytes in a shared secret using secp192r1 (NIST 192-bit). @ingroup nrf_crypto_ecdh_secp192r1 */ +#define NRF_CRYPTO_ECDH_SECP224R1_SHARED_SECRET_SIZE (224 / 8) /**< @brief Number of bytes in a shared secret using secp224r1 (NIST 224-bit). @ingroup nrf_crypto_ecdh_secp224r1 */ +#define NRF_CRYPTO_ECDH_SECP256R1_SHARED_SECRET_SIZE (256 / 8) /**< @brief Number of bytes in a shared secret using secp256r1 (NIST 256-bit). @ingroup nrf_crypto_ecdh_secp256r1 */ +#define NRF_CRYPTO_ECDH_SECP384R1_SHARED_SECRET_SIZE (384 / 8) /**< @brief Number of bytes in a shared secret using secp384r1 (NIST 384-bit). @ingroup nrf_crypto_ecdh_secp384r1 */ +#define NRF_CRYPTO_ECDH_SECP521R1_SHARED_SECRET_SIZE (528 / 8) /**< @brief Number of bytes in a shared secret using secp521r1 (NIST 521-bit). @ingroup nrf_crypto_ecdh_secp521r1 */ +#define NRF_CRYPTO_ECDH_SECP160K1_SHARED_SECRET_SIZE (160 / 8) /**< @brief Number of bytes in a shared secret using secp160k1 (Koblitz 160-bit). @ingroup nrf_crypto_ecdh_secp160k1 */ +#define NRF_CRYPTO_ECDH_SECP192K1_SHARED_SECRET_SIZE (192 / 8) /**< @brief Number of bytes in a shared secret using secp192k1 (Koblitz 192-bit). @ingroup nrf_crypto_ecdh_secp192k1 */ +#define NRF_CRYPTO_ECDH_SECP224K1_SHARED_SECRET_SIZE (224 / 8) /**< @brief Number of bytes in a shared secret using secp224k1 (Koblitz 224-bit). @ingroup nrf_crypto_ecdh_secp224k1 */ +#define NRF_CRYPTO_ECDH_SECP256K1_SHARED_SECRET_SIZE (256 / 8) /**< @brief Number of bytes in a shared secret using secp256k1 (Koblitz 256-bit). @ingroup nrf_crypto_ecdh_secp256k1 */ +#define NRF_CRYPTO_ECDH_BP256R1_SHARED_SECRET_SIZE (256 / 8) /**< @brief Number of bytes in a shared secret using bp256r1 (Brainpool 256-bit). @ingroup nrf_crypto_ecdh_bp256r1 */ +#define NRF_CRYPTO_ECDH_BP384R1_SHARED_SECRET_SIZE (384 / 8) /**< @brief Number of bytes in a shared secret using bp384r1 (Brainpool 384-bit). @ingroup nrf_crypto_ecdh_bp384r1 */ +#define NRF_CRYPTO_ECDH_BP512R1_SHARED_SECRET_SIZE (512 / 8) /**< @brief Number of bytes in a shared secret using bp512r1 (Brainpool 512-bit). @ingroup nrf_crypto_ecdh_bp512r1 */ +#define NRF_CRYPTO_ECDH_CURVE25519_SHARED_SECRET_SIZE (256 / 8) /**< @brief Number of bytes in a shared secret using Curve25519. @ingroup nrf_crypto_ecdh_curve25519 */ +#define NRF_CRYPTO_ECDH_SHARED_SECRET_MAX_SIZE NRF_CRYPTO_ECC_RAW_PRIVATE_KEY_MAX_SIZE /**< @brief Maximum size of a shared secret in bytes for all enabled curves. */ + + +typedef nrf_crypto_backend_secp160r1_ecdh_context_t nrf_crypto_ecdh_secp160r1_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve secp160r1 (NIST 160-bit). @ingroup nrf_crypto_ecdh_secp160r1 */ +typedef nrf_crypto_backend_secp160r2_ecdh_context_t nrf_crypto_ecdh_secp160r2_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve secp160r2 (NIST 160-bit). @ingroup nrf_crypto_ecdh_secp160r2 */ +typedef nrf_crypto_backend_secp192r1_ecdh_context_t nrf_crypto_ecdh_secp192r1_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve secp192r1 (NIST 192-bit). @ingroup nrf_crypto_ecdh_secp192r1 */ +typedef nrf_crypto_backend_secp224r1_ecdh_context_t nrf_crypto_ecdh_secp224r1_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve secp224r1 (NIST 224-bit). @ingroup nrf_crypto_ecdh_secp224r1 */ +typedef nrf_crypto_backend_secp256r1_ecdh_context_t nrf_crypto_ecdh_secp256r1_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve secp256r1 (NIST 256-bit). @ingroup nrf_crypto_ecdh_secp256r1 */ +typedef nrf_crypto_backend_secp384r1_ecdh_context_t nrf_crypto_ecdh_secp384r1_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve secp384r1 (NIST 384-bit). @ingroup nrf_crypto_ecdh_secp384r1 */ +typedef nrf_crypto_backend_secp521r1_ecdh_context_t nrf_crypto_ecdh_secp521r1_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve secp521r1 (NIST 521-bit). @ingroup nrf_crypto_ecdh_secp521r1 */ +typedef nrf_crypto_backend_secp160k1_ecdh_context_t nrf_crypto_ecdh_secp160k1_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve secp160k1 (Koblitz 160-bit). @ingroup nrf_crypto_ecdh_secp160k1 */ +typedef nrf_crypto_backend_secp192k1_ecdh_context_t nrf_crypto_ecdh_secp192k1_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve secp192k1 (Koblitz 192-bit). @ingroup nrf_crypto_ecdh_secp192k1 */ +typedef nrf_crypto_backend_secp224k1_ecdh_context_t nrf_crypto_ecdh_secp224k1_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve secp224k1 (Koblitz 224-bit). @ingroup nrf_crypto_ecdh_secp224k1 */ +typedef nrf_crypto_backend_secp256k1_ecdh_context_t nrf_crypto_ecdh_secp256k1_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve secp256k1 (Koblitz 256-bit). @ingroup nrf_crypto_ecdh_secp256k1 */ +typedef nrf_crypto_backend_bp256r1_ecdh_context_t nrf_crypto_ecdh_bp256r1_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve bp256r1 (Brainpool 256-bit). @ingroup nrf_crypto_ecdh_bp256r1 */ +typedef nrf_crypto_backend_bp384r1_ecdh_context_t nrf_crypto_ecdh_bp384r1_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve bp384r1 (Brainpool 384-bit). @ingroup nrf_crypto_ecdh_bp384r1 */ +typedef nrf_crypto_backend_bp512r1_ecdh_context_t nrf_crypto_ecdh_bp512r1_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve bp512r1 (Brainpool 512-bit). @ingroup nrf_crypto_ecdh_bp512r1 */ +typedef nrf_crypto_backend_curve25519_ecdh_context_t nrf_crypto_ecdh_curve25519_context_t; /**< @brief Context used to store temporary data during computing ECDH for curve Curve25519. @ingroup nrf_crypto_ecdh_curve25519 */ + + +typedef uint8_t nrf_crypto_ecdh_secp160r1_shared_secret_t + [NRF_CRYPTO_ECDH_SECP160R1_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve secp160r1 (NIST 160-bit). @ingroup nrf_crypto_ecdh_secp160r1 */ +typedef uint8_t nrf_crypto_ecdh_secp160r2_shared_secret_t + [NRF_CRYPTO_ECDH_SECP160R2_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve secp160r2 (NIST 160-bit). @ingroup nrf_crypto_ecdh_secp160r2 */ +typedef uint8_t nrf_crypto_ecdh_secp192r1_shared_secret_t + [NRF_CRYPTO_ECDH_SECP192R1_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve secp192r1 (NIST 192-bit). @ingroup nrf_crypto_ecdh_secp192r1 */ +typedef uint8_t nrf_crypto_ecdh_secp224r1_shared_secret_t + [NRF_CRYPTO_ECDH_SECP224R1_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve secp224r1 (NIST 224-bit). @ingroup nrf_crypto_ecdh_secp224r1 */ +typedef uint8_t nrf_crypto_ecdh_secp256r1_shared_secret_t + [NRF_CRYPTO_ECDH_SECP256R1_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve secp256r1 (NIST 256-bit). @ingroup nrf_crypto_ecdh_secp256r1 */ +typedef uint8_t nrf_crypto_ecdh_secp384r1_shared_secret_t + [NRF_CRYPTO_ECDH_SECP384R1_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve secp384r1 (NIST 384-bit). @ingroup nrf_crypto_ecdh_secp384r1 */ +typedef uint8_t nrf_crypto_ecdh_secp521r1_shared_secret_t + [NRF_CRYPTO_ECDH_SECP521R1_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve secp521r1 (NIST 521-bit). @ingroup nrf_crypto_ecdh_secp521r1 */ +typedef uint8_t nrf_crypto_ecdh_secp160k1_shared_secret_t + [NRF_CRYPTO_ECDH_SECP160K1_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve secp160k1 (Koblitz 160-bit). @ingroup nrf_crypto_ecdh_secp160k1 */ +typedef uint8_t nrf_crypto_ecdh_secp192k1_shared_secret_t + [NRF_CRYPTO_ECDH_SECP192K1_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve secp192k1 (Koblitz 192-bit). @ingroup nrf_crypto_ecdh_secp192k1 */ +typedef uint8_t nrf_crypto_ecdh_secp224k1_shared_secret_t + [NRF_CRYPTO_ECDH_SECP224K1_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve secp224k1 (Koblitz 224-bit). @ingroup nrf_crypto_ecdh_secp224k1 */ +typedef uint8_t nrf_crypto_ecdh_secp256k1_shared_secret_t + [NRF_CRYPTO_ECDH_SECP256K1_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve secp256k1 (Koblitz 256-bit). @ingroup nrf_crypto_ecdh_secp256k1 */ +typedef uint8_t nrf_crypto_ecdh_bp256r1_shared_secret_t + [NRF_CRYPTO_ECDH_BP256R1_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve bp256r1 (Brainpool 256-bit). @ingroup nrf_crypto_ecdh_bp256r1 */ +typedef uint8_t nrf_crypto_ecdh_bp384r1_shared_secret_t + [NRF_CRYPTO_ECDH_BP384R1_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve bp384r1 (Brainpool 384-bit). @ingroup nrf_crypto_ecdh_bp384r1 */ +typedef uint8_t nrf_crypto_ecdh_bp512r1_shared_secret_t + [NRF_CRYPTO_ECDH_BP512R1_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve bp512r1 (Brainpool 512-bit). @ingroup nrf_crypto_ecdh_bp512r1 */ +typedef uint8_t nrf_crypto_ecdh_curve25519_shared_secret_t + [NRF_CRYPTO_ECDH_CURVE25519_SHARED_SECRET_SIZE]; /**< @brief Array type of a shared secret for curve Curve25519. @ingroup nrf_crypto_ecdh_curve25519 */ +typedef uint8_t nrf_crypto_ecdh_shared_secret_t + [NRF_CRYPTO_ECDH_SHARED_SECRET_MAX_SIZE]; /**< @brief Array type of a shared secret for any of the enabled curves. */ + + +/** @brief Union holding a context for ECDH computation. + */ +typedef union +{ + nrf_crypto_ecdh_secp160r1_context_t context_secp160r1; /**< @brief Occupies space for secp160r1 (NIST 160-bit). */ + nrf_crypto_ecdh_secp160r2_context_t context_secp160r2; /**< @brief Occupies space for secp160r2 (NIST 160-bit). */ + nrf_crypto_ecdh_secp192r1_context_t context_secp192r1; /**< @brief Occupies space for secp192r1 (NIST 192-bit). */ + nrf_crypto_ecdh_secp224r1_context_t context_secp224r1; /**< @brief Occupies space for secp224r1 (NIST 224-bit). */ + nrf_crypto_ecdh_secp256r1_context_t context_secp256r1; /**< @brief Occupies space for secp256r1 (NIST 256-bit). */ + nrf_crypto_ecdh_secp384r1_context_t context_secp384r1; /**< @brief Occupies space for secp384r1 (NIST 384-bit). */ + nrf_crypto_ecdh_secp521r1_context_t context_secp521r1; /**< @brief Occupies space for secp521r1 (NIST 521-bit). */ + nrf_crypto_ecdh_secp160k1_context_t context_secp160k1; /**< @brief Occupies space for secp160k1 (Koblitz 160-bit). */ + nrf_crypto_ecdh_secp192k1_context_t context_secp192k1; /**< @brief Occupies space for secp192k1 (Koblitz 192-bit). */ + nrf_crypto_ecdh_secp224k1_context_t context_secp224k1; /**< @brief Occupies space for secp224k1 (Koblitz 224-bit). */ + nrf_crypto_ecdh_secp256k1_context_t context_secp256k1; /**< @brief Occupies space for secp256k1 (Koblitz 256-bit). */ + nrf_crypto_ecdh_bp256r1_context_t context_bp256r1; /**< @brief Occupies space for bp256r1 (Brainpool 256-bit). */ + nrf_crypto_ecdh_bp384r1_context_t context_bp384r1; /**< @brief Occupies space for bp384r1 (Brainpool 384-bit). */ + nrf_crypto_ecdh_bp512r1_context_t context_bp512r1; /**< @brief Occupies space for bp512r1 (Brainpool 512-bit). */ + nrf_crypto_ecdh_curve25519_context_t context_curve25519; /**< @brief Occupies space for Curve25519. */ +} nrf_crypto_ecdh_context_t; + + +/** @brief Computes shared secret using ECC Diffie-Hellman. + * + * @param[in] p_context Pointer to temporary structure holding context information. + * If it is NULL, necessary data will be allocated with + * @ref NRF_CRYPTO_ALLOC and freed at the end of the function. + * @param[in] p_private_key Pointer to structure holding a private key. + * @param[in] p_public_key Pointer to structure holding a public key received from the other party. + * @param[out] p_shared_secret Pointer to buffer where shared secret will be put. + * @param[in,out] p_shared_secret_size Maximum number of bytes that @p p_shared_secret buffer can hold on input + * and the actual number of bytes used by the data on output. + * Actual size for selected curve is defined by + * the preprocessor definitions, e.g. + * @ref NRF_CRYPTO_ECDH_SECP256R1_SHARED_SECRET_SIZE. + */ +ret_code_t nrf_crypto_ecdh_compute( + nrf_crypto_ecdh_context_t * p_context, + nrf_crypto_ecc_private_key_t const * p_private_key, + nrf_crypto_ecc_public_key_t const * p_public_key, + uint8_t * p_shared_secret, + size_t * p_shared_secret_size); + + +#ifdef __cplusplus +} +#endif + +/** @} + * @} + */ + +#endif // NRF_CRYPTO_ECDH_H__ diff --git a/components/libraries/crypto/nrf_crypto_ecdh_backend.h b/components/libraries/crypto/nrf_crypto_ecdh_backend.h new file mode 100644 index 0000000..713d941 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_ecdh_backend.h @@ -0,0 +1,185 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_ECDH_BACKEND_H__ +#define NRF_CRYPTO_ECDH_BACKEND_H__ +#if !defined(__SDK_DOXYGEN__) + +#include +#include + +#include "sdk_errors.h" +#include "sdk_config.h" +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdh_shared.h" + +// Include all backends +#include "cc310_backend_ecdh.h" +#include "cc310_bl_backend_ecdh.h" +#include "mbedtls_backend_ecdh.h" +#include "oberon_backend_ecdh.h" +#include "micro_ecc_backend_ecdh.h" +#include "optiga_backend_ecdh.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if !NRF_CRYPTO_ECC_SECP160R1_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_secp160r1_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp160r1_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP160R2_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_secp160r2_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp160r2_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP192R1_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_secp192r1_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp192r1_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP224R1_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_secp224r1_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp224r1_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP256R1_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_secp256r1_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp256r1_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP384R1_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_secp384r1_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp384r1_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP521R1_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_secp521r1_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp521r1_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP160K1_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_secp160k1_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp160k1_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP192K1_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_secp192k1_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp192k1_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP224K1_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_secp224k1_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp224k1_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP256K1_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_secp256k1_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp256k1_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_BP256R1_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_bp256r1_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_bp256r1_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_BP384R1_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_bp384r1_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_bp384r1_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_BP512R1_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_bp512r1_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_bp512r1_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_CURVE25519_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_curve25519_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_curve25519_ecdh_compute NULL +#endif + +#if !NRF_CRYPTO_ECC_ED25519_ENABLED +// Dummy typedef for disabled context +typedef uint32_t nrf_crypto_backend_ed25519_ecdh_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_ed25519_ecdh_compute NULL +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // !defined(__SDK_DOXYGEN__) +#endif // NRF_CRYPTO_ECDH_BACKEND_H__ diff --git a/components/libraries/crypto/nrf_crypto_ecdh_shared.h b/components/libraries/crypto/nrf_crypto_ecdh_shared.h new file mode 100644 index 0000000..087e45b --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_ecdh_shared.h @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_ECDH_SHARED_H__ +#define NRF_CRYPTO_ECDH_SHARED_H__ +#if !defined(__SDK_DOXYGEN__) + +#include +#include + +#include "sdk_errors.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @internal @brief Function pointer for backend implementation of ECDH. + * + * @note All parameters provided to the backend are vefified in frontend. Verification includes + * checking of NULL pointers, buffer size, initialization values. Front end also take full care of + * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t. + * + * @param[in] p_context Pointer to context. + * @param[in] p_private_key Pointer to private key. + * @param[in] p_public_key Pointer to public key. + * @param[out] p_shared_secret Pointer where to put generated shared secret. + */ +typedef ret_code_t (*nrf_crypto_backend_ecdh_compute_fn_t)( + void * p_context, + void const * p_private_key, + void const * p_public_key, + uint8_t * p_shared_secret); + + +#ifdef __cplusplus +} +#endif + +#endif // !defined(__SDK_DOXYGEN__) +#endif // NRF_CRYPTO_ECDH_SHARED_H__ diff --git a/components/libraries/crypto/nrf_crypto_ecdsa.c b/components/libraries/crypto/nrf_crypto_ecdsa.c new file mode 100644 index 0000000..3ed51c6 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_ecdsa.c @@ -0,0 +1,454 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_crypto_error.h" +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdsa.h" +#include "nrf_crypto_mem.h" +#include "app_util.h" +#include "sdk_macros.h" + + +#if NRF_CRYPTO_ECC_ENABLED + + +#if NRF_CRYPTO_ECC_IMPLEMENTED_CURVES_COUNT > 1 + + +static const nrf_crypto_backend_ecdsa_sign_fn_t sign_impl[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + nrf_crypto_backend_secp160r1_sign, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + nrf_crypto_backend_secp160r2_sign, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + nrf_crypto_backend_secp192r1_sign, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + nrf_crypto_backend_secp224r1_sign, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + nrf_crypto_backend_secp256r1_sign, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + nrf_crypto_backend_secp384r1_sign, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + nrf_crypto_backend_secp521r1_sign, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + nrf_crypto_backend_secp160k1_sign, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + nrf_crypto_backend_secp192k1_sign, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + nrf_crypto_backend_secp224k1_sign, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + nrf_crypto_backend_secp256k1_sign, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + nrf_crypto_backend_bp256r1_sign, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + nrf_crypto_backend_bp384r1_sign, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + nrf_crypto_backend_bp512r1_sign, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + nrf_crypto_backend_curve25519_sign, +#endif +}; + +static const uint16_t sign_impl_context_size[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + NRF_CRYPTO_BACKEND_SECP160R1_SIGN_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + NRF_CRYPTO_BACKEND_SECP160R2_SIGN_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + NRF_CRYPTO_BACKEND_SECP192R1_SIGN_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + NRF_CRYPTO_BACKEND_SECP224R1_SIGN_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + NRF_CRYPTO_BACKEND_SECP256R1_SIGN_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + NRF_CRYPTO_BACKEND_SECP384R1_SIGN_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + NRF_CRYPTO_BACKEND_SECP521R1_SIGN_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + NRF_CRYPTO_BACKEND_SECP160K1_SIGN_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + NRF_CRYPTO_BACKEND_SECP192K1_SIGN_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + NRF_CRYPTO_BACKEND_SECP224K1_SIGN_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + NRF_CRYPTO_BACKEND_SECP256K1_SIGN_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + NRF_CRYPTO_BACKEND_BP256R1_SIGN_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + NRF_CRYPTO_BACKEND_BP384R1_SIGN_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + NRF_CRYPTO_BACKEND_BP512R1_SIGN_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + NRF_CRYPTO_BACKEND_CURVE25519_SIGN_CONTEXT_SIZE, +#endif +}; + +static const nrf_crypto_backend_ecdsa_verify_fn_t verify_impl[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + nrf_crypto_backend_secp160r1_verify, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + nrf_crypto_backend_secp160r2_verify, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + nrf_crypto_backend_secp192r1_verify, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + nrf_crypto_backend_secp224r1_verify, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + nrf_crypto_backend_secp256r1_verify, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + nrf_crypto_backend_secp384r1_verify, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + nrf_crypto_backend_secp521r1_verify, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + nrf_crypto_backend_secp160k1_verify, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + nrf_crypto_backend_secp192k1_verify, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + nrf_crypto_backend_secp224k1_verify, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + nrf_crypto_backend_secp256k1_verify, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + nrf_crypto_backend_bp256r1_verify, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + nrf_crypto_backend_bp384r1_verify, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + nrf_crypto_backend_bp512r1_verify, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + nrf_crypto_backend_curve25519_verify, +#endif +}; + +static const uint16_t verify_impl_context_size[] = +{ +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED + NRF_CRYPTO_BACKEND_SECP160R1_VERIFY_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP160R2_ENABLED + NRF_CRYPTO_BACKEND_SECP160R2_VERIFY_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP192R1_ENABLED + NRF_CRYPTO_BACKEND_SECP192R1_VERIFY_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP224R1_ENABLED + NRF_CRYPTO_BACKEND_SECP224R1_VERIFY_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP256R1_ENABLED + NRF_CRYPTO_BACKEND_SECP256R1_VERIFY_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP384R1_ENABLED + NRF_CRYPTO_BACKEND_SECP384R1_VERIFY_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP521R1_ENABLED + NRF_CRYPTO_BACKEND_SECP521R1_VERIFY_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP160K1_ENABLED + NRF_CRYPTO_BACKEND_SECP160K1_VERIFY_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP192K1_ENABLED + NRF_CRYPTO_BACKEND_SECP192K1_VERIFY_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP224K1_ENABLED + NRF_CRYPTO_BACKEND_SECP224K1_VERIFY_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_SECP256K1_ENABLED + NRF_CRYPTO_BACKEND_SECP256K1_VERIFY_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP256R1_ENABLED + NRF_CRYPTO_BACKEND_BP256R1_VERIFY_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP384R1_ENABLED + NRF_CRYPTO_BACKEND_BP384R1_VERIFY_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_BP512R1_ENABLED + NRF_CRYPTO_BACKEND_BP512R1_VERIFY_CONTEXT_SIZE, +#endif +#if NRF_CRYPTO_ECC_CURVE25519_ENABLED + NRF_CRYPTO_BACKEND_CURVE25519_VERIFY_CONTEXT_SIZE, +#endif +}; + +#define BACKEND_IMPL_GET(table, curve_type) (table)[(uint32_t)(curve_type)] + +#else + +#if NRF_CRYPTO_ECC_SECP160R1_ENABLED +#define sign_impl nrf_crypto_backend_secp160r1_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_SECP160R1_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_secp160r1_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_SECP160R1_VERIFY_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP160R2_ENABLED +#define sign_impl nrf_crypto_backend_secp160r2_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_SECP160R2_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_secp160r2_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_SECP160R2_VERIFY_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP192R1_ENABLED +#define sign_impl nrf_crypto_backend_secp192r1_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_SECP192R1_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_secp192r1_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_SECP192R1_VERIFY_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP224R1_ENABLED +#define sign_impl nrf_crypto_backend_secp224r1_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_SECP224R1_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_secp224r1_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_SECP224R1_VERIFY_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP256R1_ENABLED +#define sign_impl nrf_crypto_backend_secp256r1_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_SECP256R1_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_secp256r1_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_SECP256R1_VERIFY_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP384R1_ENABLED +#define sign_impl nrf_crypto_backend_secp384r1_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_SECP384R1_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_secp384r1_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_SECP384R1_VERIFY_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP521R1_ENABLED +#define sign_impl nrf_crypto_backend_secp521r1_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_SECP521R1_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_secp521r1_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_SECP521R1_VERIFY_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP160K1_ENABLED +#define sign_impl nrf_crypto_backend_secp160k1_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_SECP160K1_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_secp160k1_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_SECP160K1_VERIFY_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP192K1_ENABLED +#define sign_impl nrf_crypto_backend_secp192k1_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_SECP192K1_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_secp192k1_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_SECP192K1_VERIFY_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP224K1_ENABLED +#define sign_impl nrf_crypto_backend_secp224k1_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_SECP224K1_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_secp224k1_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_SECP224K1_VERIFY_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_SECP256K1_ENABLED +#define sign_impl nrf_crypto_backend_secp256k1_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_SECP256K1_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_secp256k1_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_SECP256K1_VERIFY_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_BP256R1_ENABLED +#define sign_impl nrf_crypto_backend_bp256r1_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_BP256R1_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_bp256r1_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_BP256R1_VERIFY_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_BP384R1_ENABLED +#define sign_impl nrf_crypto_backend_bp384r1_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_BP384R1_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_bp384r1_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_BP384R1_VERIFY_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_BP512R1_ENABLED +#define sign_impl nrf_crypto_backend_bp512r1_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_BP512R1_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_bp512r1_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_BP512R1_VERIFY_CONTEXT_SIZE +#elif NRF_CRYPTO_ECC_CURVE25519_ENABLED +#define sign_impl nrf_crypto_backend_curve25519_sign +#define sign_impl_context_size NRF_CRYPTO_BACKEND_CURVE25519_SIGN_CONTEXT_SIZE +#define verify_impl nrf_crypto_backend_curve25519_verify +#define verify_impl_context_size NRF_CRYPTO_BACKEND_CURVE25519_VERIFY_CONTEXT_SIZE +#else +#define sign_impl NULL +#define sign_impl_context_size 0 +#define verify_impl NULL +#define verify_impl_context_size 0 +#endif + +#define BACKEND_IMPL_GET(function, curve_type) (function) + +#endif + + +ret_code_t nrf_crypto_ecdsa_sign( + nrf_crypto_ecdsa_sign_context_t * p_context, + nrf_crypto_ecc_private_key_t const * p_private_key, + uint8_t const * p_hash, + size_t hash_size, + uint8_t * p_signature, + size_t * p_signature_size) +{ + ret_code_t result; + void * p_allocated_context = NULL; + nrf_crypto_backend_ecdsa_sign_fn_t backend_implementation; + size_t context_size; + nrf_crypto_ecc_curve_info_t const * p_info; + + // Get pointer to header + nrf_crypto_internal_ecc_key_header_t const * p_private_key_header = + (nrf_crypto_internal_ecc_key_header_t const *)p_private_key; + + // Check and prepare parameters + VERIFY_TRUE(p_hash != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + result = nrf_crypto_internal_ecc_key_input_check( + p_private_key_header, + NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE); + VERIFY_SUCCESS(result); + p_info = p_private_key_header->p_info; + result = nrf_crypto_internal_ecc_raw_output_prepare(p_signature, + p_signature_size, + 2 * p_info->raw_private_key_size); + VERIFY_SUCCESS(result); + + // Get backend specific information + backend_implementation = BACKEND_IMPL_GET(sign_impl, p_info->curve_type); + context_size = BACKEND_IMPL_GET(sign_impl_context_size, p_info->curve_type); + VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE); + + // Allocate context if not provided + if (p_context == NULL && context_size > 0) + { + p_allocated_context = NRF_CRYPTO_ALLOC(context_size); + VERIFY_TRUE(p_allocated_context != NULL, NRF_ERROR_CRYPTO_ALLOC_FAILED); + p_context = p_allocated_context; + } + + // Execute backend implementation + result = backend_implementation(p_context, p_private_key, p_hash, hash_size, p_signature); + + // Deallocate context if allocated + if (p_allocated_context != NULL) + { + NRF_CRYPTO_FREE(p_allocated_context); + } + + return result; +} + + +ret_code_t nrf_crypto_ecdsa_verify( + nrf_crypto_ecdsa_verify_context_t * p_context, + nrf_crypto_ecc_public_key_t const * p_public_key, + uint8_t const * p_hash, + size_t hash_size, + uint8_t const * p_signature, + size_t signature_size) +{ + ret_code_t result; + void * p_allocated_context = NULL; + nrf_crypto_backend_ecdsa_verify_fn_t backend_implementation; + size_t context_size; + nrf_crypto_ecc_curve_info_t const * p_info; + + // Get pointer to header + nrf_crypto_internal_ecc_key_header_t const * p_public_key_header = + (nrf_crypto_internal_ecc_key_header_t const *)p_public_key; + + // Check and prepare parameters + result = nrf_crypto_internal_ecc_key_input_check( + p_public_key_header, + NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE); + VERIFY_SUCCESS(result); + p_info = p_public_key_header->p_info; + result = nrf_crypto_internal_ecc_raw_input_check(p_signature, + signature_size, + 2 * p_info->raw_private_key_size); + VERIFY_SUCCESS(result); + VERIFY_TRUE(p_hash != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + + // Get backend specific information + backend_implementation = BACKEND_IMPL_GET(verify_impl, p_info->curve_type); + context_size = BACKEND_IMPL_GET(verify_impl_context_size, p_info->curve_type); + VERIFY_TRUE(backend_implementation != NULL, NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE); + + // Allocate context if not provided + if (p_context == NULL && context_size > 0) + { + p_allocated_context = NRF_CRYPTO_ALLOC(context_size); + VERIFY_TRUE(p_allocated_context != NULL, NRF_ERROR_CRYPTO_ALLOC_FAILED); + p_context = p_allocated_context; + } + + // Execute backend implementation + result = backend_implementation(p_context, p_public_key, p_hash, hash_size, p_signature); + + // Deallocate context if allocated + if (p_allocated_context != NULL) + { + NRF_CRYPTO_FREE(p_allocated_context); + } + + return result; +} + + +#endif // NRF_CRYPTO_ECC_ENABLED diff --git a/components/libraries/crypto/nrf_crypto_ecdsa.h b/components/libraries/crypto/nrf_crypto_ecdsa.h new file mode 100644 index 0000000..ad635e2 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_ecdsa.h @@ -0,0 +1,245 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_ECDSA_H__ +#define NRF_CRYPTO_ECDSA_H__ + +/** @addtogroup nrf_crypto + * @{ + * @addtogroup nrf_crypto_ecdsa Elliptic Curve Digital Signature (ECDSA) + * @{ + * @brief Provides elliptic curve cryptography functions for digital signature. + * + * @addtogroup nrf_crypto_ecdsa_secp160r1 Definitions specific to secp160r1 (NIST 160-bit) + * @addtogroup nrf_crypto_ecdsa_secp160r2 Definitions specific to secp160r2 (NIST 160-bit) + * @addtogroup nrf_crypto_ecdsa_secp192r1 Definitions specific to secp192r1 (NIST 192-bit) + * @addtogroup nrf_crypto_ecdsa_secp224r1 Definitions specific to secp224r1 (NIST 224-bit) + * @addtogroup nrf_crypto_ecdsa_secp256r1 Definitions specific to secp256r1 (NIST 256-bit) + * @addtogroup nrf_crypto_ecdsa_secp384r1 Definitions specific to secp384r1 (NIST 384-bit) + * @addtogroup nrf_crypto_ecdsa_secp521r1 Definitions specific to secp521r1 (NIST 521-bit) + * @addtogroup nrf_crypto_ecdsa_secp160k1 Definitions specific to secp160k1 (Koblitz 160-bit) + * @addtogroup nrf_crypto_ecdsa_secp192k1 Definitions specific to secp192k1 (Koblitz 192-bit) + * @addtogroup nrf_crypto_ecdsa_secp224k1 Definitions specific to secp224k1 (Koblitz 224-bit) + * @addtogroup nrf_crypto_ecdsa_secp256k1 Definitions specific to secp256k1 (Koblitz 256-bit) + * @addtogroup nrf_crypto_ecdsa_bp256r1 Definitions specific to bp256r1 (Brainpool 256-bit) + * @addtogroup nrf_crypto_ecdsa_bp384r1 Definitions specific to bp384r1 (Brainpool 384-bit) + * @addtogroup nrf_crypto_ecdsa_bp512r1 Definitions specific to bp512r1 (Brainpool 512-bit) + * @addtogroup nrf_crypto_ecdsa_curve25519 Definitions specific to Curve25519 + */ + +#include +#include + +#include "nrf_crypto_error.h" +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_ecdsa_shared.h" +#include "nrf_crypto_ecdsa_backend.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_CRYPTO_ECDSA_SECP160R1_SIGNATURE_SIZE (2 * 160 / 8) /**< @brief Size of a signature for secp160r1 (NIST 160-bit) curve. @ingroup nrf_crypto_ecdsa_secp160r1 */ +#define NRF_CRYPTO_ECDSA_SECP160R2_SIGNATURE_SIZE (2 * 160 / 8) /**< @brief Size of a signature for secp160r2 (NIST 160-bit) curve. @ingroup nrf_crypto_ecdsa_secp160r2 */ +#define NRF_CRYPTO_ECDSA_SECP192R1_SIGNATURE_SIZE (2 * 192 / 8) /**< @brief Size of a signature for secp192r1 (NIST 192-bit) curve. @ingroup nrf_crypto_ecdsa_secp192r1 */ +#define NRF_CRYPTO_ECDSA_SECP224R1_SIGNATURE_SIZE (2 * 224 / 8) /**< @brief Size of a signature for secp224r1 (NIST 224-bit) curve. @ingroup nrf_crypto_ecdsa_secp224r1 */ +#define NRF_CRYPTO_ECDSA_SECP256R1_SIGNATURE_SIZE (2 * 256 / 8) /**< @brief Size of a signature for secp256r1 (NIST 256-bit) curve. @ingroup nrf_crypto_ecdsa_secp256r1 */ +#define NRF_CRYPTO_ECDSA_SECP384R1_SIGNATURE_SIZE (2 * 384 / 8) /**< @brief Size of a signature for secp384r1 (NIST 384-bit) curve. @ingroup nrf_crypto_ecdsa_secp384r1 */ +#define NRF_CRYPTO_ECDSA_SECP521R1_SIGNATURE_SIZE (2 * 528 / 8) /**< @brief Size of a signature for secp521r1 (NIST 521-bit) curve. @ingroup nrf_crypto_ecdsa_secp521r1 */ +#define NRF_CRYPTO_ECDSA_SECP160K1_SIGNATURE_SIZE (2 * 160 / 8) /**< @brief Size of a signature for secp160k1 (Koblitz 160-bit) curve. @ingroup nrf_crypto_ecdsa_secp160k1 */ +#define NRF_CRYPTO_ECDSA_SECP192K1_SIGNATURE_SIZE (2 * 192 / 8) /**< @brief Size of a signature for secp192k1 (Koblitz 192-bit) curve. @ingroup nrf_crypto_ecdsa_secp192k1 */ +#define NRF_CRYPTO_ECDSA_SECP224K1_SIGNATURE_SIZE (2 * 224 / 8) /**< @brief Size of a signature for secp224k1 (Koblitz 224-bit) curve. @ingroup nrf_crypto_ecdsa_secp224k1 */ +#define NRF_CRYPTO_ECDSA_SECP256K1_SIGNATURE_SIZE (2 * 256 / 8) /**< @brief Size of a signature for secp256k1 (Koblitz 256-bit) curve. @ingroup nrf_crypto_ecdsa_secp256k1 */ +#define NRF_CRYPTO_ECDSA_BP256R1_SIGNATURE_SIZE (2 * 256 / 8) /**< @brief Size of a signature for bp256r1 (Brainpool 256-bit) curve. @ingroup nrf_crypto_ecdsa_bp256r1 */ +#define NRF_CRYPTO_ECDSA_BP384R1_SIGNATURE_SIZE (2 * 384 / 8) /**< @brief Size of a signature for bp384r1 (Brainpool 384-bit) curve. @ingroup nrf_crypto_ecdsa_bp384r1 */ +#define NRF_CRYPTO_ECDSA_BP512R1_SIGNATURE_SIZE (2 * 512 / 8) /**< @brief Size of a signature for bp512r1 (Brainpool 512-bit) curve. @ingroup nrf_crypto_ecdsa_bp512r1 */ +#define NRF_CRYPTO_ECDSA_CURVE25519_SIGNATURE_SIZE (2 * 256 / 8) /**< @brief Size of a signature for Curve25519 curve. @ingroup nrf_crypto_ecdsa_curve25519 */ +#define NRF_CRYPTO_ECDSA_SIGNATURE_MAX_SIZE (2 * NRF_CRYPTO_ECC_RAW_PRIVATE_KEY_MAX_SIZE) /**< @brief Maximum size of a signature for all enabled curves. */ + + +typedef uint8_t nrf_crypto_ecdsa_secp160r1_signature_t [NRF_CRYPTO_ECDSA_SECP160R1_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for secp160r1 (NIST 160-bit) curve. @ingroup nrf_crypto_ecdsa_secp160r1 */ +typedef uint8_t nrf_crypto_ecdsa_secp160r2_signature_t [NRF_CRYPTO_ECDSA_SECP160R2_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for secp160r2 (NIST 160-bit) curve. @ingroup nrf_crypto_ecdsa_secp160r2 */ +typedef uint8_t nrf_crypto_ecdsa_secp192r1_signature_t [NRF_CRYPTO_ECDSA_SECP192R1_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for secp192r1 (NIST 192-bit) curve. @ingroup nrf_crypto_ecdsa_secp192r1 */ +typedef uint8_t nrf_crypto_ecdsa_secp224r1_signature_t [NRF_CRYPTO_ECDSA_SECP224R1_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for secp224r1 (NIST 224-bit) curve. @ingroup nrf_crypto_ecdsa_secp224r1 */ +typedef uint8_t nrf_crypto_ecdsa_secp256r1_signature_t [NRF_CRYPTO_ECDSA_SECP256R1_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for secp256r1 (NIST 256-bit) curve. @ingroup nrf_crypto_ecdsa_secp256r1 */ +typedef uint8_t nrf_crypto_ecdsa_secp384r1_signature_t [NRF_CRYPTO_ECDSA_SECP384R1_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for secp384r1 (NIST 384-bit) curve. @ingroup nrf_crypto_ecdsa_secp384r1 */ +typedef uint8_t nrf_crypto_ecdsa_secp521r1_signature_t [NRF_CRYPTO_ECDSA_SECP521R1_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for secp521r1 (NIST 521-bit) curve. @ingroup nrf_crypto_ecdsa_secp521r1 */ +typedef uint8_t nrf_crypto_ecdsa_secp160k1_signature_t [NRF_CRYPTO_ECDSA_SECP160K1_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for secp160k1 (Koblitz 160-bit) curve. @ingroup nrf_crypto_ecdsa_secp160k1 */ +typedef uint8_t nrf_crypto_ecdsa_secp192k1_signature_t [NRF_CRYPTO_ECDSA_SECP192K1_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for secp192k1 (Koblitz 192-bit) curve. @ingroup nrf_crypto_ecdsa_secp192k1 */ +typedef uint8_t nrf_crypto_ecdsa_secp224k1_signature_t [NRF_CRYPTO_ECDSA_SECP224K1_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for secp224k1 (Koblitz 224-bit) curve. @ingroup nrf_crypto_ecdsa_secp224k1 */ +typedef uint8_t nrf_crypto_ecdsa_secp256k1_signature_t [NRF_CRYPTO_ECDSA_SECP256K1_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for secp256k1 (Koblitz 256-bit) curve. @ingroup nrf_crypto_ecdsa_secp256k1 */ +typedef uint8_t nrf_crypto_ecdsa_bp256r1_signature_t [NRF_CRYPTO_ECDSA_BP256R1_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for bp256r1 (Brainpool 256-bit) curve. @ingroup nrf_crypto_ecdsa_bp256r1 */ +typedef uint8_t nrf_crypto_ecdsa_bp384r1_signature_t [NRF_CRYPTO_ECDSA_BP384R1_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for bp384r1 (Brainpool 384-bit) curve. @ingroup nrf_crypto_ecdsa_bp384r1 */ +typedef uint8_t nrf_crypto_ecdsa_bp512r1_signature_t [NRF_CRYPTO_ECDSA_BP512R1_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for bp512r1 (Brainpool 512-bit) curve. @ingroup nrf_crypto_ecdsa_bp512r1 */ +typedef uint8_t nrf_crypto_ecdsa_curve25519_signature_t [NRF_CRYPTO_ECDSA_CURVE25519_SIGNATURE_SIZE]; /**< @brief Type to hold signature output for Curve25519 curve. @ingroup nrf_crypto_ecdsa_curve25519 */ +typedef uint8_t nrf_crypto_ecdsa_signature_t [NRF_CRYPTO_ECDSA_SIGNATURE_MAX_SIZE]; /**< @brief Type big enough to hold signature output for any curve type. */ + + +typedef nrf_crypto_backend_secp160r1_sign_context_t nrf_crypto_ecdsa_secp160r1_sign_context_t; /**< @brief Context used to store temporary data during signing with curve secp160r1 (NIST 160-bit). @ingroup nrf_crypto_ecdsa_secp160r1 */ +typedef nrf_crypto_backend_secp160r2_sign_context_t nrf_crypto_ecdsa_secp160r2_sign_context_t; /**< @brief Context used to store temporary data during signing with curve secp160r2 (NIST 160-bit). @ingroup nrf_crypto_ecdsa_secp160r2 */ +typedef nrf_crypto_backend_secp192r1_sign_context_t nrf_crypto_ecdsa_secp192r1_sign_context_t; /**< @brief Context used to store temporary data during signing with curve secp192r1 (NIST 192-bit). @ingroup nrf_crypto_ecdsa_secp192r1 */ +typedef nrf_crypto_backend_secp224r1_sign_context_t nrf_crypto_ecdsa_secp224r1_sign_context_t; /**< @brief Context used to store temporary data during signing with curve secp224r1 (NIST 224-bit). @ingroup nrf_crypto_ecdsa_secp224r1 */ +typedef nrf_crypto_backend_secp256r1_sign_context_t nrf_crypto_ecdsa_secp256r1_sign_context_t; /**< @brief Context used to store temporary data during signing with curve secp256r1 (NIST 256-bit). @ingroup nrf_crypto_ecdsa_secp256r1 */ +typedef nrf_crypto_backend_secp384r1_sign_context_t nrf_crypto_ecdsa_secp384r1_sign_context_t; /**< @brief Context used to store temporary data during signing with curve secp384r1 (NIST 384-bit). @ingroup nrf_crypto_ecdsa_secp384r1 */ +typedef nrf_crypto_backend_secp521r1_sign_context_t nrf_crypto_ecdsa_secp521r1_sign_context_t; /**< @brief Context used to store temporary data during signing with curve secp521r1 (NIST 521-bit). @ingroup nrf_crypto_ecdsa_secp521r1 */ +typedef nrf_crypto_backend_secp160k1_sign_context_t nrf_crypto_ecdsa_secp160k1_sign_context_t; /**< @brief Context used to store temporary data during signing with curve secp160k1 (Koblitz 160-bit). @ingroup nrf_crypto_ecdsa_secp160k1 */ +typedef nrf_crypto_backend_secp192k1_sign_context_t nrf_crypto_ecdsa_secp192k1_sign_context_t; /**< @brief Context used to store temporary data during signing with curve secp192k1 (Koblitz 192-bit). @ingroup nrf_crypto_ecdsa_secp192k1 */ +typedef nrf_crypto_backend_secp224k1_sign_context_t nrf_crypto_ecdsa_secp224k1_sign_context_t; /**< @brief Context used to store temporary data during signing with curve secp224k1 (Koblitz 224-bit). @ingroup nrf_crypto_ecdsa_secp224k1 */ +typedef nrf_crypto_backend_secp256k1_sign_context_t nrf_crypto_ecdsa_secp256k1_sign_context_t; /**< @brief Context used to store temporary data during signing with curve secp256k1 (Koblitz 256-bit). @ingroup nrf_crypto_ecdsa_secp256k1 */ +typedef nrf_crypto_backend_bp256r1_sign_context_t nrf_crypto_ecdsa_bp256r1_sign_context_t; /**< @brief Context used to store temporary data during signing with curve bp256r1 (Brainpool 256-bit). @ingroup nrf_crypto_ecdsa_bp256r1 */ +typedef nrf_crypto_backend_bp384r1_sign_context_t nrf_crypto_ecdsa_bp384r1_sign_context_t; /**< @brief Context used to store temporary data during signing with curve bp384r1 (Brainpool 384-bit). @ingroup nrf_crypto_ecdsa_bp384r1 */ +typedef nrf_crypto_backend_bp512r1_sign_context_t nrf_crypto_ecdsa_bp512r1_sign_context_t; /**< @brief Context used to store temporary data during signing with curve bp512r1 (Brainpool 512-bit). @ingroup nrf_crypto_ecdsa_bp512r1 */ +typedef nrf_crypto_backend_curve25519_sign_context_t nrf_crypto_ecdsa_curve25519_sign_context_t; /**< @brief Context used to store temporary data during signing with curve Curve25519. @ingroup nrf_crypto_ecdsa_curve25519 */ + + +typedef nrf_crypto_backend_secp160r1_verify_context_t nrf_crypto_ecdsa_secp160r1_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve secp160r1 (NIST 160-bit). @ingroup nrf_crypto_ecdsa_secp160r1 */ +typedef nrf_crypto_backend_secp160r2_verify_context_t nrf_crypto_ecdsa_secp160r2_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve secp160r2 (NIST 160-bit). @ingroup nrf_crypto_ecdsa_secp160r2 */ +typedef nrf_crypto_backend_secp192r1_verify_context_t nrf_crypto_ecdsa_secp192r1_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve secp192r1 (NIST 192-bit). @ingroup nrf_crypto_ecdsa_secp192r1 */ +typedef nrf_crypto_backend_secp224r1_verify_context_t nrf_crypto_ecdsa_secp224r1_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve secp224r1 (NIST 224-bit). @ingroup nrf_crypto_ecdsa_secp224r1 */ +typedef nrf_crypto_backend_secp256r1_verify_context_t nrf_crypto_ecdsa_secp256r1_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve secp256r1 (NIST 256-bit). @ingroup nrf_crypto_ecdsa_secp256r1 */ +typedef nrf_crypto_backend_secp384r1_verify_context_t nrf_crypto_ecdsa_secp384r1_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve secp384r1 (NIST 384-bit). @ingroup nrf_crypto_ecdsa_secp384r1 */ +typedef nrf_crypto_backend_secp521r1_verify_context_t nrf_crypto_ecdsa_secp521r1_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve secp521r1 (NIST 521-bit). @ingroup nrf_crypto_ecdsa_secp521r1 */ +typedef nrf_crypto_backend_secp160k1_verify_context_t nrf_crypto_ecdsa_secp160k1_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve secp160k1 (Koblitz 160-bit). @ingroup nrf_crypto_ecdsa_secp160k1 */ +typedef nrf_crypto_backend_secp192k1_verify_context_t nrf_crypto_ecdsa_secp192k1_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve secp192k1 (Koblitz 192-bit). @ingroup nrf_crypto_ecdsa_secp192k1 */ +typedef nrf_crypto_backend_secp224k1_verify_context_t nrf_crypto_ecdsa_secp224k1_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve secp224k1 (Koblitz 224-bit). @ingroup nrf_crypto_ecdsa_secp224k1 */ +typedef nrf_crypto_backend_secp256k1_verify_context_t nrf_crypto_ecdsa_secp256k1_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve secp256k1 (Koblitz 256-bit). @ingroup nrf_crypto_ecdsa_secp256k1 */ +typedef nrf_crypto_backend_bp256r1_verify_context_t nrf_crypto_ecdsa_bp256r1_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve bp256r1 (Brainpool 256-bit). @ingroup nrf_crypto_ecdsa_bp256r1 */ +typedef nrf_crypto_backend_bp384r1_verify_context_t nrf_crypto_ecdsa_bp384r1_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve bp384r1 (Brainpool 384-bit). @ingroup nrf_crypto_ecdsa_bp384r1 */ +typedef nrf_crypto_backend_bp512r1_verify_context_t nrf_crypto_ecdsa_bp512r1_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve bp512r1 (Brainpool 512-bit). @ingroup nrf_crypto_ecdsa_bp512r1 */ +typedef nrf_crypto_backend_curve25519_verify_context_t nrf_crypto_ecdsa_curve25519_verify_context_t; /**< @brief Context used to store temporary data during verifying with curve Curve25519. @ingroup nrf_crypto_ecdsa_curve25519 */ + + +/** @brief Union holding a context for ECDSA hash sign. + */ +typedef union +{ + nrf_crypto_ecdsa_secp160r1_sign_context_t context_secp160r1; /**< @brief Occupies space for secp160r1 (NIST 160-bit). */ + nrf_crypto_ecdsa_secp160r2_sign_context_t context_secp160r2; /**< @brief Occupies space for secp160r2 (NIST 160-bit). */ + nrf_crypto_ecdsa_secp192r1_sign_context_t context_secp192r1; /**< @brief Occupies space for secp192r1 (NIST 192-bit). */ + nrf_crypto_ecdsa_secp224r1_sign_context_t context_secp224r1; /**< @brief Occupies space for secp224r1 (NIST 224-bit). */ + nrf_crypto_ecdsa_secp256r1_sign_context_t context_secp256r1; /**< @brief Occupies space for secp256r1 (NIST 256-bit). */ + nrf_crypto_ecdsa_secp384r1_sign_context_t context_secp384r1; /**< @brief Occupies space for secp384r1 (NIST 384-bit). */ + nrf_crypto_ecdsa_secp521r1_sign_context_t context_secp521r1; /**< @brief Occupies space for secp521r1 (NIST 521-bit). */ + nrf_crypto_ecdsa_secp160k1_sign_context_t context_secp160k1; /**< @brief Occupies space for secp160k1 (Koblitz 160-bit). */ + nrf_crypto_ecdsa_secp192k1_sign_context_t context_secp192k1; /**< @brief Occupies space for secp192k1 (Koblitz 192-bit). */ + nrf_crypto_ecdsa_secp224k1_sign_context_t context_secp224k1; /**< @brief Occupies space for secp224k1 (Koblitz 224-bit). */ + nrf_crypto_ecdsa_secp256k1_sign_context_t context_secp256k1; /**< @brief Occupies space for secp256k1 (Koblitz 256-bit). */ + nrf_crypto_ecdsa_bp256r1_sign_context_t context_bp256r1; /**< @brief Occupies space for bp256r1 (Brainpool 256-bit). */ + nrf_crypto_ecdsa_bp384r1_sign_context_t context_bp384r1; /**< @brief Occupies space for bp384r1 (Brainpool 384-bit). */ + nrf_crypto_ecdsa_bp512r1_sign_context_t context_bp512r1; /**< @brief Occupies space for bp512r1 (Brainpool 512-bit). */ + nrf_crypto_ecdsa_curve25519_sign_context_t context_curve25519; /**< @brief Occupies space for Curve25519. */ +} nrf_crypto_ecdsa_sign_context_t; + + +/** @brief Union holding a context for ECDSA hash verify. + */ +typedef union +{ + nrf_crypto_ecdsa_secp160r1_verify_context_t context_secp160r1; /**< @brief Occupies spece for secp160r1 (NIST 160-bit). */ + nrf_crypto_ecdsa_secp160r2_verify_context_t context_secp160r2; /**< @brief Occupies spece for secp160r2 (NIST 160-bit). */ + nrf_crypto_ecdsa_secp192r1_verify_context_t context_secp192r1; /**< @brief Occupies spece for secp192r1 (NIST 192-bit). */ + nrf_crypto_ecdsa_secp224r1_verify_context_t context_secp224r1; /**< @brief Occupies spece for secp224r1 (NIST 224-bit). */ + nrf_crypto_ecdsa_secp256r1_verify_context_t context_secp256r1; /**< @brief Occupies spece for secp256r1 (NIST 256-bit). */ + nrf_crypto_ecdsa_secp384r1_verify_context_t context_secp384r1; /**< @brief Occupies spece for secp384r1 (NIST 384-bit). */ + nrf_crypto_ecdsa_secp521r1_verify_context_t context_secp521r1; /**< @brief Occupies spece for secp521r1 (NIST 521-bit). */ + nrf_crypto_ecdsa_secp160k1_verify_context_t context_secp160k1; /**< @brief Occupies spece for secp160k1 (Koblitz 160-bit). */ + nrf_crypto_ecdsa_secp192k1_verify_context_t context_secp192k1; /**< @brief Occupies spece for secp192k1 (Koblitz 192-bit). */ + nrf_crypto_ecdsa_secp224k1_verify_context_t context_secp224k1; /**< @brief Occupies spece for secp224k1 (Koblitz 224-bit). */ + nrf_crypto_ecdsa_secp256k1_verify_context_t context_secp256k1; /**< @brief Occupies spece for secp256k1 (Koblitz 256-bit). */ + nrf_crypto_ecdsa_bp256r1_verify_context_t context_bp256r1; /**< @brief Occupies spece for bp256r1 (Brainpool 256-bit). */ + nrf_crypto_ecdsa_bp384r1_verify_context_t context_bp384r1; /**< @brief Occupies spece for bp384r1 (Brainpool 384-bit). */ + nrf_crypto_ecdsa_bp512r1_verify_context_t context_bp512r1; /**< @brief Occupies spece for bp512r1 (Brainpool 512-bit). */ + nrf_crypto_ecdsa_curve25519_verify_context_t context_curve25519; /**< @brief Occupies spece for Curve25519. */ +} nrf_crypto_ecdsa_verify_context_t; + + +/** @brief Sign a hash of a message. + * + * @param[in] p_context Pointer to temporary structure holding context information. + * If it is NULL, necessary data will be allocated with + * @ref NRF_CRYPTO_ALLOC and freed at the end of the function. + * @param[in] p_private_key Pointer to structure holding a private key. + * @param[in] p_hash Pointer to hash to sign. + * @param[in] hash_size Number of bytes in p_hash. + * @param[out] p_signature Pointer to buffer where digital signature will be put. + * @param[in,out] p_signature_size Maximum number of bytes that @p p_signature buffer can hold on input + * and the actual number of bytes used by the data on output. + * Actual size for selected curve is defined by + * the preprocessor definitions, e.g. + * @ref NRF_CRYPTO_ECDSA_SECP256R1_SIGNATURE_SIZE. + */ +ret_code_t nrf_crypto_ecdsa_sign( + nrf_crypto_ecdsa_sign_context_t * p_context, + nrf_crypto_ecc_private_key_t const * p_private_key, + uint8_t const * p_hash, + size_t hash_size, + uint8_t * p_signature, + size_t * p_signature_size); + + +/** @brief Verify a signature using a hash of a message. + * + * @param[in] p_context Pointer to temporary structure holding context information. + * If it is NULL, necessary data will be allocated with + * @ref NRF_CRYPTO_ALLOC and freed at the end of the function. + * @param[in] p_public_key Pointer to structure holding a public key. + * @param[in] p_hash Pointer to hash to verify. + * @param[in] hash_size Number of bytes in p_hash. + * @param[in] p_signature Pointer to buffer containing digital signature. + * @param[in,out] signature_size Number of bytes in p_signature. + */ +ret_code_t nrf_crypto_ecdsa_verify( + nrf_crypto_ecdsa_verify_context_t * p_context, + nrf_crypto_ecc_public_key_t const * p_public_key, + uint8_t const * p_hash, + size_t hash_size, + uint8_t const * p_signature, + size_t signature_size); + +#ifdef __cplusplus +} +#endif + +/** @} + * @} + */ + +#endif // NRF_CRYPTO_ECDSA_H__ diff --git a/components/libraries/crypto/nrf_crypto_ecdsa_backend.h b/components/libraries/crypto/nrf_crypto_ecdsa_backend.h new file mode 100644 index 0000000..08f50e1 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_ecdsa_backend.h @@ -0,0 +1,251 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_ECDSA_BACKEND_H__ +#define NRF_CRYPTO_ECDSA_BACKEND_H__ +#if !defined(__SDK_DOXYGEN__) + +#include +#include + +#include "sdk_config.h" +#include "nrf_crypto_ecdsa_shared.h" + +// Include all backends +#include "cc310_backend_ecdsa.h" +#include "cc310_bl_backend_ecdsa.h" +#include "mbedtls_backend_ecdsa.h" +#include "oberon_backend_ecdsa.h" +#include "micro_ecc_backend_ecdsa.h" +#include "optiga_backend_ecdsa.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if !NRF_CRYPTO_ECC_SECP160R1_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_SECP160R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP160R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_secp160r1_sign_context_t; +typedef uint8_t nrf_crypto_backend_secp160r1_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp160r1_sign NULL +#define nrf_crypto_backend_secp160r1_verify NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP160R2_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_SECP160R2_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP160R2_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_secp160r2_sign_context_t; +typedef uint8_t nrf_crypto_backend_secp160r2_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp160r2_sign NULL +#define nrf_crypto_backend_secp160r2_verify NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP192R1_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_SECP192R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP192R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_secp192r1_sign_context_t; +typedef uint8_t nrf_crypto_backend_secp192r1_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp192r1_sign NULL +#define nrf_crypto_backend_secp192r1_verify NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP224R1_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_SECP224R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP224R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_secp224r1_sign_context_t; +typedef uint8_t nrf_crypto_backend_secp224r1_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp224r1_sign NULL +#define nrf_crypto_backend_secp224r1_verify NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP256R1_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_SECP256R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_secp256r1_sign_context_t; +typedef uint8_t nrf_crypto_backend_secp256r1_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp256r1_sign NULL +#define nrf_crypto_backend_secp256r1_verify NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP384R1_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_SECP384R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP384R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_secp384r1_sign_context_t; +typedef uint8_t nrf_crypto_backend_secp384r1_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp384r1_sign NULL +#define nrf_crypto_backend_secp384r1_verify NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP521R1_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_SECP521R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP521R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_secp521r1_sign_context_t; +typedef uint8_t nrf_crypto_backend_secp521r1_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp521r1_sign NULL +#define nrf_crypto_backend_secp521r1_verify NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP160K1_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_SECP160K1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP160K1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_secp160k1_sign_context_t; +typedef uint8_t nrf_crypto_backend_secp160k1_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp160k1_sign NULL +#define nrf_crypto_backend_secp160k1_verify NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP192K1_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_SECP192K1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP192K1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_secp192k1_sign_context_t; +typedef uint8_t nrf_crypto_backend_secp192k1_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp192k1_sign NULL +#define nrf_crypto_backend_secp192k1_verify NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP224K1_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_SECP224K1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP224K1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_secp224k1_sign_context_t; +typedef uint8_t nrf_crypto_backend_secp224k1_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp224k1_sign NULL +#define nrf_crypto_backend_secp224k1_verify NULL +#endif + +#if !NRF_CRYPTO_ECC_SECP256K1_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_SECP256K1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_SECP256K1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_secp256k1_sign_context_t; +typedef uint8_t nrf_crypto_backend_secp256k1_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_secp256k1_sign NULL +#define nrf_crypto_backend_secp256k1_verify NULL +#endif + +#if !NRF_CRYPTO_ECC_BP256R1_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_BP256R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_BP256R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_bp256r1_sign_context_t; +typedef uint8_t nrf_crypto_backend_bp256r1_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_bp256r1_sign NULL +#define nrf_crypto_backend_bp256r1_verify NULL +#endif + +#if !NRF_CRYPTO_ECC_BP384R1_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_BP384R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_BP384R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_bp384r1_sign_context_t; +typedef uint8_t nrf_crypto_backend_bp384r1_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_bp384r1_sign NULL +#define nrf_crypto_backend_bp384r1_verify NULL +#endif + +#if !NRF_CRYPTO_ECC_BP512R1_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_BP512R1_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_BP512R1_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_bp512r1_sign_context_t; +typedef uint8_t nrf_crypto_backend_bp512r1_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_bp512r1_sign NULL +#define nrf_crypto_backend_bp512r1_verify NULL +#endif + +#if !NRF_CRYPTO_ECC_CURVE25519_ENABLED +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_CURVE25519_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_CURVE25519_VERIFY_CONTEXT_SIZE 0 +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_curve25519_sign_context_t; +typedef uint8_t nrf_crypto_backend_curve25519_verify_context_t; +// Backend implementation is NULL to indicate feature not supported +#define nrf_crypto_backend_curve25519_sign NULL +#define nrf_crypto_backend_curve25519_verify NULL +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // !defined(__SDK_DOXYGEN__) +#endif // NRF_CRYPTO_ECDSA_BACKEND_H__ diff --git a/components/libraries/crypto/nrf_crypto_ecdsa_shared.h b/components/libraries/crypto/nrf_crypto_ecdsa_shared.h new file mode 100644 index 0000000..44e11af --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_ecdsa_shared.h @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_ECDSA_SHARED_H__ +#define NRF_CRYPTO_ECDSA_SHARED_H__ + +#include + +#include "nordic_common.h" +#include "nrf_crypto_ecc.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @internal @brief Function pointer for backend implementation of ECDSA sign. + * + * @note All parameters provided to the backend are vefified in frontend. Verification includes + * checking of NULL pointers, buffer size, initialization values. Front end also take full care of + * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t. + * + * @param[in] p_context Pointer to context. + * @param[in] p_private_key Pointer to private key. + * @param[in] p_data Pointer to data to sign. Data can be a message or a hash. It depends + * on which version of signing functions is pointed by this function + * pointer. + * @param[in] data_size Size of @p p_data. + * @param[out] p_signature Pointer where to put generated signature. + */ +typedef ret_code_t (*nrf_crypto_backend_ecdsa_sign_fn_t)( + void * p_context, + void const * p_private_key, + uint8_t const * p_data, + size_t data_size, + uint8_t * p_signature); + + +/** @internal @brief Function pointer for backend implementation of ECDSA verify. + * + * @note All parameters provided to the backend are vefified in frontend. Verification includes + * checking of NULL pointers, buffer size, initialization values. Front end also take full care of + * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t. + * + * @param[in] p_context Pointer to context. + * @param[in] p_public_key Pointer to public key. + * @param[in] p_data Pointer to data to verify. Data can be a message or a hash. It depends + * on which version of signing functions is pointed by this function + * pointer. + * @param[in] data_size Size of @p p_data. + * @param[in] p_signature Pointer to signature to verify. + */ +typedef ret_code_t (*nrf_crypto_backend_ecdsa_verify_fn_t)( + void * p_context, + void const * p_public_key, + uint8_t const * p_data, + size_t data_size, + uint8_t const * p_signature); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_CRYPTO_ECDSA_SHARED_H__ diff --git a/components/libraries/crypto/nrf_crypto_eddsa.c b/components/libraries/crypto/nrf_crypto_eddsa.c new file mode 100644 index 0000000..a9106d3 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_eddsa.c @@ -0,0 +1,162 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_crypto_error.h" +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_eddsa.h" +#include "nrf_crypto_mem.h" +#include "app_util.h" +#include "sdk_macros.h" + + +#if NRF_CRYPTO_ECC_ENABLED && NRF_CRYPTO_ECC_ED25519_ENABLED + + + +ret_code_t nrf_crypto_eddsa_sign(nrf_crypto_eddsa_sign_context_t * p_context, + nrf_crypto_ecc_private_key_t const * p_private_key, + uint8_t const * p_message, + size_t message_size, + uint8_t * p_signature, + size_t * p_signature_size) +{ + ret_code_t result = NRF_SUCCESS; + void * p_allocated_context = NULL; + + // Get pointer to header + nrf_crypto_internal_ecc_key_header_t const * p_private_key_header = + (nrf_crypto_internal_ecc_key_header_t const *)p_private_key; + + // Verify parameters (zero-length message is valid per RFC 8032) + if (message_size > 0) + { + VERIFY_TRUE(p_message != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + } + + result = nrf_crypto_internal_ecc_key_input_check( + p_private_key_header, + NRF_CRYPTO_INTERNAL_ECC_PRIVATE_KEY_INIT_VALUE); + VERIFY_SUCCESS(result); + + result = nrf_crypto_internal_ecc_raw_output_prepare(p_signature, + p_signature_size, + NRF_CRYPTO_EDDSA_ED25519_SIGNATURE_SIZE); + VERIFY_SUCCESS(result); + + // Allocate context if not provided + if (p_context == NULL && NRF_CRYPTO_BACKEND_ED25519_SIGN_CONTEXT_SIZE > 0) + { + p_allocated_context = NRF_CRYPTO_ALLOC(NRF_CRYPTO_BACKEND_ED25519_SIGN_CONTEXT_SIZE); + VERIFY_TRUE(p_allocated_context != NULL, NRF_ERROR_CRYPTO_ALLOC_FAILED); + p_context = p_allocated_context; + } + + // Execute backend implementation + result = nrf_crypto_backend_ed25519_sign(p_context, + p_private_key, + p_message, + message_size, + p_signature); + + // Deallocate context if allocated + if (p_allocated_context != NULL) + { + NRF_CRYPTO_FREE(p_allocated_context); + } + + return result; +} + + +ret_code_t nrf_crypto_eddsa_verify(nrf_crypto_eddsa_verify_context_t * p_context, + nrf_crypto_ecc_public_key_t const * p_public_key, + uint8_t const * p_message, + size_t message_size, + uint8_t const * p_signature, + size_t signature_size) +{ + ret_code_t result = NRF_SUCCESS; + void * p_allocated_context = NULL; + + // Get pointer to header + nrf_crypto_internal_ecc_key_header_t const * p_public_key_header = + (nrf_crypto_internal_ecc_key_header_t const *)p_public_key; + + // Verify parameters (zero-length message is valid per RFC 8032) + if (message_size > 0) + { + VERIFY_TRUE(p_message != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + } + + result = nrf_crypto_internal_ecc_key_input_check( + p_public_key_header, + NRF_CRYPTO_INTERNAL_ECC_PUBLIC_KEY_INIT_VALUE); + VERIFY_SUCCESS(result); + + result = nrf_crypto_internal_ecc_raw_input_check(p_signature, + signature_size, + NRF_CRYPTO_EDDSA_ED25519_SIGNATURE_SIZE); + VERIFY_SUCCESS(result); + + // Allocate context if not provided + if (p_context == NULL && NRF_CRYPTO_BACKEND_ED25519_VERIFY_CONTEXT_SIZE > 0) + { + p_allocated_context = NRF_CRYPTO_ALLOC(NRF_CRYPTO_BACKEND_ED25519_VERIFY_CONTEXT_SIZE); + VERIFY_TRUE(p_allocated_context != NULL, NRF_ERROR_CRYPTO_ALLOC_FAILED); + p_context = p_allocated_context; + } + + // Execute backend implementation + result = nrf_crypto_backend_ed25519_verify(p_context, + p_public_key, + p_message, + message_size, + p_signature); + + // Deallocate context if allocated + if (p_allocated_context != NULL) + { + NRF_CRYPTO_FREE(p_allocated_context); + } + + return result; +} + +#endif // NRF_CRYPTO_ECC_ENABLED && NRF_CRYPTO_ECC_ED25519_ENABLED diff --git a/components/libraries/crypto/nrf_crypto_eddsa.h b/components/libraries/crypto/nrf_crypto_eddsa.h new file mode 100644 index 0000000..f1d4209 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_eddsa.h @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_EDDSA_H__ +#define NRF_CRYPTO_EDDSA_H__ + +/** @file + * + * @defgroup nrf_crypto_eddsa Edwards-curve Digital Signature Algorithm (EdDSA) + * @{ + * @ingroup nrf_crypto + * + * @brief Provides functionality related to Edwards-curve Digital Signature Algorithm (EdDSA). + */ + +#include +#include + +#include "nrf_crypto_error.h" +#include "nrf_crypto_ecc.h" +#include "nrf_crypto_eddsa_shared.h" +#include "nrf_crypto_eddsa_backend.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**< @brief Size of the EdDSA Ed25519 signature. */ +#define NRF_CRYPTO_EDDSA_ED25519_SIGNATURE_SIZE (2 * 256 / 8) + +/**< @brief Context used to store temporary data during the signing with EdDSA Ed25519. */ +typedef nrf_crypto_backend_ed25519_sign_context_t nrf_crypto_eddsa_sign_context_t; + +/**< @brief Context used to store temporary data during the verification with EdDSA Ed25519. */ +typedef nrf_crypto_backend_ed25519_verify_context_t nrf_crypto_eddsa_verify_context_t; + + +/** @brief Sign a message using Edwards-curve Digital Signature Algorithm (EdDSA). + * + * @param[in] p_context Pointer to the temporary structure that holds context information. + * If it is NULL, the required data is allocated with + * @ref NRF_CRYPTO_ALLOC and freed at the end of the function. + * @param[in] p_private_key Pointer to the structure that holds a private key. + * @param[in] p_message Pointer to the message to sign. + * @param[in] message_size Number of bytes in p_message. + * @param[out] p_signature Pointer to the array where EdDSA signature is to be put. Minimum bytes required: @ref NRF_CRYPTO_EDDSA_ED25519_SIGNATURE_SIZE. + * @param[in,out] p_signature_size Pointer to the maximum number of bytes that @p p_signature buffer + * can hold on input, and to the actual number of bytes used by the + * data on output (@ref NRF_CRYPTO_EDDSA_ED25519_SIGNATURE_SIZE). + * + * @return NRF_SUCCESS on success. + */ +ret_code_t nrf_crypto_eddsa_sign(nrf_crypto_eddsa_sign_context_t * p_context, + nrf_crypto_ecc_private_key_t const * p_private_key, + uint8_t const * p_message, + size_t message_size, + uint8_t * p_signature, + size_t * p_signature_size); + + +/** @brief Verify a message using Edwards-curve Digital Signature Algorithm (EdDSA). + * + * @param[in] p_context Pointer to the temporary structure that holds context information. + * If it is NULL, necessary data is allocated with + * @ref NRF_CRYPTO_ALLOC and freed at the end of the function. + * @param[in] p_public_key Pointer to the structure that holds a public key. + * @param[in] p_message Pointer to the message to verify. + * @param[in] message_size Number of bytes in p_message. + * @param[in] p_signature Pointer to the array that contains EdDSA signature. + * @param[in] signature_size Number of bytes in p_signature. + * + * @return NRF_SUCCESS on success. + */ +ret_code_t nrf_crypto_eddsa_verify(nrf_crypto_eddsa_verify_context_t * p_context, + nrf_crypto_ecc_public_key_t const * p_public_key, + uint8_t const * p_message, + size_t message_size, + uint8_t const * p_signature, + size_t signature_size); + + +#ifdef __cplusplus +} +#endif + +/** @} + */ + +#endif // NRF_CRYPTO_EDDSA_H__ diff --git a/components/libraries/crypto/nrf_crypto_eddsa_backend.h b/components/libraries/crypto/nrf_crypto_eddsa_backend.h new file mode 100644 index 0000000..9a1cc4a --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_eddsa_backend.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_EDDSA_BACKEND_H__ +#define NRF_CRYPTO_EDDSA_BACKEND_H__ +#if !defined(__SDK_DOXYGEN__) + +#include +#include + +#include "sdk_config.h" +#include "nrf_crypto_ecdsa_shared.h" + +// Include all backends +#include "cc310_backend_eddsa.h" +#include "oberon_backend_eddsa.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#if !NRF_CRYPTO_ECC_ED25519_ENABLED + +// Context sizes are zero for disabled functionality +#define NRF_CRYPTO_BACKEND_ED25519_SIGN_CONTEXT_SIZE 0 +#define NRF_CRYPTO_BACKEND_ED25519_VERIFY_CONTEXT_SIZE 0 + +// Dummy typedefs for disabled contexts +typedef uint8_t nrf_crypto_backend_ed25519_sign_context_t; +typedef uint8_t nrf_crypto_backend_ed25519_verify_context_t; + +#endif + +#ifdef __cplusplus +} +#endif + +#endif // !defined(__SDK_DOXYGEN__) +#endif // NRF_CRYPTO_EDDSA_BACKEND_H__ diff --git a/components/libraries/crypto/nrf_crypto_eddsa_shared.h b/components/libraries/crypto/nrf_crypto_eddsa_shared.h new file mode 100644 index 0000000..69bb1b3 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_eddsa_shared.h @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_EDDSA_SHARED_H__ +#define NRF_CRYPTO_EDDSA_SHARED_H__ + +#include + +#include "nordic_common.h" +#include "nrf_crypto_ecc.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @internal @brief Sign a message using Edwards-curve Digital Signature Algorithm (EdDSA). + * + * @note All parameters provided to the backend are vefified in frontend. Verification includes + * checking of NULL pointers, buffer size, initialization values. Front end also take full care of + * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t. + * + * @param[in] p_context Pointer to temporary structure holding context information. + * If it is NULL, necessary data will be allocated with + * @ref NRF_CRYPTO_ALLOC and freed at the end of the function. + * @param[in] p_private_key Pointer to structure holding a private Ed25519 key. + * (Buffer size @ref NRF_CRYPTO_ECC_ED25519_RAW_PRIVATE_KEY_SIZE). + * @param[in] p_message Pointer to message to sign. + * @param[in] message_size Number of bytes in p_message. + * @param[out] p_signature Pointer to buffer where EdDSA signature will be put. Must be + * @ref NRF_CRYPTO_EDDSA_ED25519_SIGNATURE_SIZE bytes. + * + * @return NRF_SUCCESS on success. + */ +ret_code_t nrf_crypto_backend_ed25519_sign( + void * p_context, + nrf_crypto_ecc_private_key_t const * p_private_key, + uint8_t const * p_message, + size_t message_size, + uint8_t * p_signature); + + +/** @internal @brief Verify a message using Edwards-curve Digital Signature Algorithm (EdDSA). + * + * @note All parameters provided to the backend are vefified in frontend. Verification includes + * checking of NULL pointers, buffer size, initialization values. Front end also take full care of + * common ECC key hearder @ref nrf_crypto_internal_ecc_key_header_t. + * + * @param[in] p_context Pointer to temporary structure holding context information. + * If it is NULL, necessary data will be allocated with + * @ref NRF_CRYPTO_ALLOC and freed at the end of the function. + * @param[in] p_public_key Pointer to structure holding a public Ed25519 key. + * (Buffer size @ref NRF_CRYPTO_ECC_ED25519_RAW_PUBLIC_KEY_SIZE). + * @param[in] p_message Pointer to message to verify. + * @param[in] message_size Number of bytes in p_message. + * @param[in] p_signature Pointer to buffer containing EdDSA signature + * (@ref NRF_CRYPTO_EDDSA_ED25519_SIGNATURE_SIZE bytes). + * + * @return NRF_SUCCESS on success. + */ +ret_code_t nrf_crypto_backend_ed25519_verify( + void * p_context, + nrf_crypto_ecc_public_key_t const * p_public_key, + uint8_t const * p_message, + size_t message_size, + uint8_t const * p_signature); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_CRYPTO_EDDSA_SHARED_H__ diff --git a/components/libraries/crypto/nrf_crypto_error.c b/components/libraries/crypto/nrf_crypto_error.c new file mode 100644 index 0000000..d36a487 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_error.c @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include "nordic_common.h" +#include "nrf_crypto_error.h" + +typedef struct +{ + ret_code_t error; + const char * p_text; +} error_code_pair; + +static const error_code_pair m_crypto_error[] = +{ + { NRF_ERROR_CRYPTO_NOT_INITIALIZED, "nrf_crypto_init was not called prior to this crypto function" }, + { NRF_ERROR_CRYPTO_CONTEXT_NULL, "A null pointer was provided for the context structure" }, + { NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED, "The context was not initialized prior to this call or it was corrupted. Please call the corresponding init function for the algorithm to initialize it" }, + { NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE, "The function was called with a feature that is unavailable" }, + { NRF_ERROR_CRYPTO_BUSY, "The function could not be called because the crypto backend was busy. Please rerun the cryptographic routine at a later time" }, + { NRF_ERROR_CRYPTO_INPUT_NULL, "One or more of the input arguments for this function was NULL" }, + { NRF_ERROR_CRYPTO_INPUT_LENGTH, "The length of one or more of the input arguments was invalid" }, + { NRF_ERROR_CRYPTO_INPUT_LOCATION, "Input data not in RAM" }, + { NRF_ERROR_CRYPTO_OUTPUT_NULL, "One or more of the output arguments for this function was NULL" }, + { NRF_ERROR_CRYPTO_OUTPUT_LENGTH, "The length of the one or more output arguments was too small" }, + { NRF_ERROR_CRYPTO_ALLOC_FAILED, "A required memory allocation failed" }, + { NRF_ERROR_CRYPTO_INTERNAL, "An internal error occurred when calling this function" }, + { NRF_ERROR_CRYPTO_INVALID_PARAM, "Invalid combination of input parameters" }, + { NRF_ERROR_CRYPTO_KEY_SIZE, "Size of the key is not supported by choosen backend" }, + { NRF_ERROR_CRYPTO_STACK_OVERFLOW, "Stack overflow detected" }, + { NRF_ERROR_CRYPTO_ECC_KEY_NOT_INITIALIZED, "ECC key was not initialized" }, + { NRF_ERROR_CRYPTO_ECDH_CURVE_MISMATCH, "Public and private key provided to ECDH have different types of curves" }, + { NRF_ERROR_CRYPTO_ECDSA_INVALID_SIGNATURE, "Signature verification check reported invalid signature" }, + { NRF_ERROR_CRYPTO_ECC_INVALID_KEY, "Provided key is invalid" }, + { NRF_ERROR_CRYPTO_AES_INVALID_PADDING, "Message padding is corrupted." }, + { NRF_ERROR_CRYPTO_AEAD_INVALID_MAC, "MAC not matching encrypted text" }, + { NRF_ERROR_CRYPTO_AEAD_NONCE_SIZE, "Size of the nonce is not supported in this AEAD mode" }, + { NRF_ERROR_CRYPTO_AEAD_MAC_SIZE, "Size of the MAC (tag) is not supported in this AEAD mode" }, + { NRF_ERROR_CRYPTO_RNG_INIT_FAILED, "Initialization or startup of RNG failed" }, + { NRF_ERROR_CRYPTO_RNG_RESEED_REQUIRED, "Reseed required (reseed counter overflowed)" }, +}; + +char const * nrf_crypto_error_string_get(ret_code_t error) +{ + if (error == NRF_SUCCESS) + { + return "No error"; + } + else + { + uint32_t i; + for (i = 0; i < ARRAY_SIZE(m_crypto_error); i++) + { + if (m_crypto_error[i].error == error) + { + return m_crypto_error[i].p_text; + } + } + } + return "Error not related to nrf_crypto library"; +} + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) diff --git a/components/libraries/crypto/nrf_crypto_error.h b/components/libraries/crypto/nrf_crypto_error.h new file mode 100644 index 0000000..933189a --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_error.h @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_ERROR_H__ +#define NRF_CRYPTO_ERROR_H__ + +/**@file + * + * @defgroup nrf_crypto_error nrf_crypto error codes + * @{ + * @ingroup nrf_crypto + * + * @details This is the standardized error codes provided when calling nrf_crypto APIs. + * The error codes provided here are enumerated based on @ref NRF_ERROR_CRYPTO_ERR_BASE. + * + * @note Success code, NRF_SUCCESS, is used if the nrf_crypto operation was successful. + * + */ + +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_ERROR_CRYPTO_NOT_INITIALIZED (NRF_ERROR_CRYPTO_ERR_BASE + 0x00) /**< @ref nrf_crypto_init was not called prior to this crypto function. */ +#define NRF_ERROR_CRYPTO_CONTEXT_NULL (NRF_ERROR_CRYPTO_ERR_BASE + 0x01) /**< A null pointer was provided for the context structure. */ +#define NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED (NRF_ERROR_CRYPTO_ERR_BASE + 0x02) /**< The context was not initialized prior to this call or it was corrupted. Call the corresponding init function for the algorithm to initialize it. */ +#define NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE (NRF_ERROR_CRYPTO_ERR_BASE + 0x03) /**< The function was called with a feature that is unavailable. */ +#define NRF_ERROR_CRYPTO_BUSY (NRF_ERROR_CRYPTO_ERR_BASE + 0x04) /**< The function could not be called because the crypto backend was busy. Rerun the cryptographic routine at a later time. */ + +#define NRF_ERROR_CRYPTO_INPUT_NULL (NRF_ERROR_CRYPTO_ERR_BASE + 0x10) /**< One or more of the input arguments for this function were NULL. */ +#define NRF_ERROR_CRYPTO_INPUT_LENGTH (NRF_ERROR_CRYPTO_ERR_BASE + 0x11) /**< The length of one or more of the input arguments was invalid. */ +#define NRF_ERROR_CRYPTO_INPUT_LOCATION (NRF_ERROR_CRYPTO_ERR_BASE + 0x12) /**< Input data not in RAM. */ +#define NRF_ERROR_CRYPTO_OUTPUT_NULL (NRF_ERROR_CRYPTO_ERR_BASE + 0x13) /**< One or more of the output arguments for this function were NULL. */ +#define NRF_ERROR_CRYPTO_OUTPUT_LENGTH (NRF_ERROR_CRYPTO_ERR_BASE + 0x14) /**< The length of one or more output arguments was too small. */ +#define NRF_ERROR_CRYPTO_ALLOC_FAILED (NRF_ERROR_CRYPTO_ERR_BASE + 0x15) /**< A required memory allocation failed. */ +#define NRF_ERROR_CRYPTO_INTERNAL (NRF_ERROR_CRYPTO_ERR_BASE + 0x16) /**< An internal error occurred when calling this function. */ +#define NRF_ERROR_CRYPTO_INVALID_PARAM (NRF_ERROR_CRYPTO_ERR_BASE + 0x17) /**< Invalid combination of input parameters. */ +#define NRF_ERROR_CRYPTO_KEY_SIZE (NRF_ERROR_CRYPTO_ERR_BASE + 0x18) /**< Size of the key is not supported by choosen backend. */ +#define NRF_ERROR_CRYPTO_STACK_OVERFLOW (NRF_ERROR_CRYPTO_ERR_BASE + 0x19) /**< Stack overflow detected. */ + +#define NRF_ERROR_CRYPTO_ECC_ERR_BASE (NRF_ERROR_CRYPTO_ERR_BASE + 0x40) /**< Base error code for ECC. */ +#define NRF_ERROR_CRYPTO_ECC_KEY_NOT_INITIALIZED (NRF_ERROR_CRYPTO_ECC_ERR_BASE + 0x00) /**< The key was not initialized. */ +#define NRF_ERROR_CRYPTO_ECDH_CURVE_MISMATCH (NRF_ERROR_CRYPTO_ECC_ERR_BASE + 0x01) /**< Public and private key provided to ECDH have different types of curves. */ +#define NRF_ERROR_CRYPTO_ECDSA_INVALID_SIGNATURE (NRF_ERROR_CRYPTO_ECC_ERR_BASE + 0x02) /**< Signature verification check reported invalid signature. */ +#define NRF_ERROR_CRYPTO_ECC_INVALID_KEY (NRF_ERROR_CRYPTO_ECC_ERR_BASE + 0x03) /**< Provided key is invalid. */ + +#define NRF_ERROR_CRYPTO_AES_ERR_BASE (NRF_ERROR_CRYPTO_ERR_BASE + 0x50) /**< Base error code for all AES modes. */ +#define NRF_ERROR_CRYPTO_AES_INVALID_PADDING (NRF_ERROR_CRYPTO_AES_ERR_BASE + 0x00) /**< Message padding is corrupted. */ + +#define NRF_ERROR_CRYPTO_AEAD_ERR_BASE (NRF_ERROR_CRYPTO_ERR_BASE + 0x60) /**< Base error code for all AEAD modes. */ +#define NRF_ERROR_CRYPTO_AEAD_INVALID_MAC (NRF_ERROR_CRYPTO_AEAD_ERR_BASE + 0x00) /**< MAC not matching encrypted text. */ +#define NRF_ERROR_CRYPTO_AEAD_NONCE_SIZE (NRF_ERROR_CRYPTO_AEAD_ERR_BASE + 0x01) /**< Size of the nonce is not supported in this AEAD mode. */ +#define NRF_ERROR_CRYPTO_AEAD_MAC_SIZE (NRF_ERROR_CRYPTO_AEAD_ERR_BASE + 0x02) /**< Size of the MAC (tag) is not supported in this AEAD mode. */ + +#define NRF_ERROR_CRYPTO_RNG_ERR_BASE (NRF_ERROR_CRYPTO_ERR_BASE + 0x70) /**< Base error code for all RNG modes. */ +#define NRF_ERROR_CRYPTO_RNG_INIT_FAILED (NRF_ERROR_CRYPTO_RNG_ERR_BASE + 0x00) /**< Initialization or startup of RNG failed. */ +#define NRF_ERROR_CRYPTO_RNG_RESEED_REQUIRED (NRF_ERROR_CRYPTO_RNG_ERR_BASE + 0x01) /**< Reseed required (reseed counter overflowed). */ + +/** + * @brief Function for converting an nrf_crypto error to a printable string pointer. + * + * @param[in] error Error code. + * + * @return Pointer to string explaining nrf_crypto error. + * */ +char const * nrf_crypto_error_string_get(ret_code_t error); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif // NRF_CRYPTO_ERROR_H__ diff --git a/components/libraries/crypto/nrf_crypto_hash.c b/components/libraries/crypto/nrf_crypto_hash.c new file mode 100644 index 0000000..1609a1b --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_hash.c @@ -0,0 +1,205 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include "nrf_crypto_error.h" +#include "nrf_crypto_hash.h" +#include "nrf_crypto_mem.h" +#include "nrf_crypto_hash_backend.h" +#include "nrf_crypto_hash_shared.h" +#include "nrf_crypto_shared.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HASH) + +static ret_code_t verify_context(nrf_crypto_hash_internal_context_t * const p_context) +{ + if (p_context == NULL) + { + return NRF_ERROR_CRYPTO_CONTEXT_NULL; + } + + if (p_context->init_val != NRF_CRYPTO_HASH_INIT_VALUE) + { + return NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED; + } + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_hash_init(nrf_crypto_hash_context_t * const p_context, + nrf_crypto_hash_info_t const * p_info) +{ + ret_code_t ret_val; + nrf_crypto_hash_internal_context_t * p_int_context; + + VERIFY_TRUE(p_context != NULL, NRF_ERROR_CRYPTO_CONTEXT_NULL); + VERIFY_TRUE(p_info != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + + p_int_context = (nrf_crypto_hash_internal_context_t *) p_context; + p_int_context->p_info = p_info; + + ret_val = p_info->init_fn(p_context); + if (ret_val != NRF_SUCCESS) + { + return ret_val; + } + + p_int_context->init_val = NRF_CRYPTO_HASH_INIT_VALUE; + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_hash_update(nrf_crypto_hash_context_t * const p_context, + uint8_t const * p_data, + size_t data_size) +{ + ret_code_t ret_val; + nrf_crypto_hash_internal_context_t * p_int_context + = (nrf_crypto_hash_internal_context_t *) p_context; + + ret_val = verify_context(p_int_context); + if (ret_val != NRF_SUCCESS) + { + return ret_val; + } + + VERIFY_TRUE(p_data != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + + // Allow zero size input + if (data_size == 0) + { + return NRF_SUCCESS; + } + + ret_val = p_int_context->p_info->update_fn(p_context, p_data, data_size); + + return ret_val; +} + + +ret_code_t nrf_crypto_hash_finalize(nrf_crypto_hash_context_t * const p_context, + uint8_t * p_digest, + size_t * const p_digest_size) +{ + ret_code_t ret_val; + nrf_crypto_hash_internal_context_t * p_int_context + = (nrf_crypto_hash_internal_context_t *) p_context; + + ret_val = verify_context(p_int_context); + if (ret_val != NRF_SUCCESS) + { + return ret_val; + } + + VERIFY_TRUE(p_digest != NULL, NRF_ERROR_CRYPTO_OUTPUT_NULL); + VERIFY_TRUE(*p_digest_size >= p_int_context->p_info->digest_size, NRF_ERROR_CRYPTO_OUTPUT_LENGTH); + + ret_val = p_int_context->p_info->finalize_fn(p_context, p_digest, p_digest_size); + + return ret_val; +} + + +ret_code_t nrf_crypto_hash_calculate(nrf_crypto_hash_context_t * const p_context, + nrf_crypto_hash_info_t const * p_info, + uint8_t const * p_data, + size_t data_size, + uint8_t * p_digest, + size_t * const p_digest_size) +{ + ret_code_t ret_val; + nrf_crypto_hash_context_t * p_ctx = (nrf_crypto_hash_context_t *)p_context; + void * p_allocated_context = NULL; + +// Internal allocation of context not available for CC310_BL in order to save code size. +#if defined(NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED) && (NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED == 1) + + // Do nothing + +#elif defined(NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED) && (NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED == 0) + + // Validate input. Only validate input parameters that are used locally, others are validated + // in the init, update and/or finalize functions. + VERIFY_TRUE(p_info != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + + // Allocate context if needed (not provided by the user). + if (p_context == NULL) + { + p_allocated_context = NRF_CRYPTO_ALLOC(p_info->context_size); + if (p_allocated_context == NULL) + { + return NRF_ERROR_CRYPTO_ALLOC_FAILED; + } + p_ctx = (nrf_crypto_hash_context_t *)p_allocated_context; + } + +#else + + #warning NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED define not found in sdk_config.h (Is the sdk_config.h valid?). + +#endif // NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED + + ret_val = nrf_crypto_hash_init(p_ctx, p_info); + NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(ret_val, p_allocated_context); + + ret_val = nrf_crypto_hash_update(p_ctx, p_data, data_size); + NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(ret_val, p_allocated_context); + + ret_val = nrf_crypto_hash_finalize(p_ctx, p_digest, p_digest_size); + NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(ret_val, p_allocated_context); + +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256) + // Free context if allocated internally + if (p_allocated_context != NULL) + { + NRF_CRYPTO_FREE(p_allocated_context); + } +#endif // !NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256) + + return NRF_SUCCESS; +} + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_HASH) + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) diff --git a/components/libraries/crypto/nrf_crypto_hash.h b/components/libraries/crypto/nrf_crypto_hash.h new file mode 100644 index 0000000..d7849de --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_hash.h @@ -0,0 +1,268 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_HASH_H__ +#define NRF_CRYPTO_HASH_H__ + +/** @file + * + * @defgroup nrf_crypto_hash Cryptographic hash related functions + * @{ + * @ingroup nrf_crypto + * + * @brief Provides cryptographic hash related functionality through nrf_crypto. + */ + +#include +#include "nrf_crypto_types.h" +#include "nrf_crypto_hash_shared.h" +#include "nrf_crypto_hash_backend.h" +#include "app_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief External variable declaration to info structure for SHA-256 + * + * @note The variable is defined in the nrf_crypto backend that is + * enabled in the @ref sdk_config. + * + */ +extern const nrf_crypto_hash_info_t g_nrf_crypto_hash_sha256_info; + + + /**@brief External variable declaration to info structure for SHA-512 + * + * @note The variable is defined in the nrf_crypto backend that is + * enabled in the @ref sdk_config. + * + */ +extern const nrf_crypto_hash_info_t g_nrf_crypto_hash_sha512_info; + + +/** + * @brief Context type for Hash. + * + * @note The size of this type is scaled for the largest Hash backend context that is + * enabled in @ref sdk_config. + */ +typedef nrf_crypto_backend_hash_context_t nrf_crypto_hash_context_t; + + +/** @brief Type definition for an array holding a SHA-256 hash digest. */ +typedef uint8_t nrf_crypto_hash_sha256_digest_t[NRF_CRYPTO_HASH_SIZE_SHA256]; + + +/** @brief Type definition for an array holding a SHA-512 hash digest. */ +typedef uint8_t nrf_crypto_hash_sha512_digest_t[NRF_CRYPTO_HASH_SIZE_SHA512]; + + +/**@brief Function for initializing the context structure required to compute a hash digest from + * arbitrary input data. + * + * @note The context structure is assumed to be an opaque type defined by the + * nrf_crypto backend. + * + * @note The return codes @ref NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE and + * NRF_ERROR_CRYPTO_INTERNAL only happens in cc310 backend. + * + * @param[in,out] p_context Pointer to structure holding context information for + * the hash calculation. + * @param[in] p_info Pointer to structure holding info about the hash algorithm + * used to do the computed hash. + * + * @retval NRF_SUCCESS The hash initialization was successful. + * @retval NRF_ERROR_CRYPTO_NOT_INITIALIZED @ref nrf_crypto_init was not called prior to + * this crypto function. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NULL A NULL pointer was provided for the context + * structure. + * @retval NRF_ERROR_CRYPTO_INPUT_NULL The pointer to the info structure was NULL. + * @retval NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE The function was called with a hash mode that + * is unavailable. + * @retval NRF_ERROR_CRYPTO_INTERNAL An internal error occurred when initializing + * the constext in the nrf_crypto backend. + */ +ret_code_t nrf_crypto_hash_init(nrf_crypto_hash_context_t * const p_context, + nrf_crypto_hash_info_t const * p_info); + + +/**@brief Function for updating the hash calculation with partial arbitrary data. + * + * @details This function should be called one or more times until all arbituary input data + * required for the hash calcuation is provided. + * + * @note @ref nrf_crypto_hash_init must be called prior to this function to configure the + * context structure used as input parameter to this function. + * + * @note @ref nrf_crypto_hash_finalize must be called after all arbitruary input data + * has been provided to get the calculated hash digest. + * + * @note The context object is assumed to be an opaque type defined by the + * nrf_crypto backend. + * + * @note The return values @ref NRF_ERROR_CRYPTO_BUSY, @ref NRF_ERROR_CRYPTO_INPUT_LOCATION + * and @ref NRF_ERROR_CRYPTO_INPUT_LOCATION can only occur in CC310 backend. + * + * @param[in,out] p_context Pointer to structure holding context information for + * the hash calculation. + * @param[in] p_data Pointer to data to be hashed. + * @param[in] data_size Length of the data to be hashed. + * + * @retval NRF_SUCCESS The hash digest was computed successfully. + * @retval NRF_ERROR_CRYPTO_NOT_INITIALIZED @ref nrf_crypto_init was not called prior to + * this crypto function. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED The context was not initialized prior to + * this call or it was corrupted. Please call + * @ref nrf_crypto_hash_init to initialize it. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NULL A NULL pointer was provided for the context + * structure. + * @retval NRF_ERROR_CRYPTO_INPUT_NULL p_data was NULL. + * @retval NRF_ERROR_CRYPTO_INPUT_LOCATION Input data not in RAM. + * @retval NRF_ERROR_CRYPTO_BUSY The function could not be called because the + * nrf_crypto backend was busy. Please rerun the + * cryptographic routine at a later time. + * @retval NRF_ERROR_CRYPTO_INTERNAL An internal error occurred in the nrf_crypto + * backend. + */ +ret_code_t nrf_crypto_hash_update(nrf_crypto_hash_context_t * const p_context, + uint8_t const * p_data, + size_t data_size); + +/**@brief Function for finalizing computation of a hash digest from arbitrary data. + * + * @details This function is called to get the calculated + * + * @note @ref nrf_crypto_hash_init must be called prior to this function to configure the + * context structure used as input parameter to this function. + * + * @note The input data for the calculated hash digest must be provided by calling + * @ref nrf_crypto_hash_update one or more times. + * + * @note The context object is assumed to be an opaque type defined by the + * nrf_crypto backend. + * + * @note The return values @ref NRF_ERROR_CRYPTO_BUSY and @ref NRF_ERROR_CRYPTO_INPUT_LOCATION + * can only occur in CC310 backend. + * + * + * @param[in] p_context Pointer to structure holding context information for + * the hash calculation. + * @param[out] p_digest Pointer to buffer holding the calculated hash digest. + * @param[in,out] p_digest_size Pointer to a variable holding the length of the calculated hash. + * Set this to the length of buffer that p_digest is pointing to. + * + * @retval NRF_SUCCESS The hash digest was computed successfully. + * @retval NRF_ERROR_CRYPTO_NOT_INITIALIZED @ref nrf_crypto_init was not called prior to + * this crypto function. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED The context was not initialized prior to + * this call or it was corrupted. Please call + * @ref nrf_crypto_hash_init to initialize it. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NULL A NULL pointer was provided for the context + * structure. + * @retval NRF_ERROR_CRYPTO_OUTPUT_NULL p_digest or p_digest_size was NULL. + * @retval NRF_ERROR_CRYPTO_OUTPUT_LENGTH The length of p_digest was too small for + * the hash digest result. + * @retval NRF_ERROR_CRYPTO_BUSY The function could not be called because the + * nrf_crypto backend was busy. Please rerun the + * cryptographic routine at a later time. + * @retval NRF_ERROR_CRYPTO_INTERNAL An internal error occurred in the nrf_crypto + * backend. + */ +ret_code_t nrf_crypto_hash_finalize(nrf_crypto_hash_context_t * const p_context, + uint8_t * p_digest, + size_t * const p_digest_size); + + +/**@brief Function for computing a hash from arbitrary data in a single integrated step. + * + * @details This function calculates the hash digest from arbitruary data in a single integrated step. + * This means calling init, update and finalize in one step. + * + * @note The context object is assumed to be an opaque type defined by the + * nrf_crypto backend. + * + * @note The return values @ref NRF_ERROR_CRYPTO_BUSY, @ref NRF_ERROR_CRYPTO_INPUT_LOCATION + * and @ref NRF_ERROR_CRYPTO_INPUT_LOCATION can only occur in CC310 backend. + * + * @param[in,out] p_context Pointer to structure holding context information for + * the hash calculation. If this + * is set to NULL, it will be allocated by the user configurable + * allocate/free function @ref NRF_CRYPTO_ALLOC and + * @ref NRF_CRYPTO_FREE. + * @param[in] p_info Pointer to structure holding info about hash algorithm + * for the computed hash. + * @param[in] p_data Pointer to data to be hashed. + * @param[in] data_size Length of the data to be hashed. + * @param[out] p_digest Pointer to buffer holding the calculated hash digest. + * @param[in,out] p_digest_size Pointer to a variable holding the length of the calculated hash. + * Set this to the length of buffer that p_digest is pointing to. + * + * @retval NRF_SUCCESS The hash initialization was successful. + * @retval NRF_ERROR_CRYPTO_NOT_INITIALIZED @ref nrf_crypto_init was not called prior to + * this crypto function. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NULL A NULL pointer was provided for the context + * structure. + * @retval NRF_ERROR_CRYPTO_INPUT_NULL p_info or p_data was NULL. + * @retval NRF_ERROR_CRYPTO_INPUT_LOCATION Input data not in RAM. + * @retval NRF_ERROR_CRYPTO_OUTPUT_NULL p_digest or p_digest_size was NULL. + * @retval NRF_ERROR_CRYPTO_OUTPUT_LENGTH The length of p_digest was too small for + * the hash digest result. + * @retval NRF_ERROR_CRYPTO_BUSY The function could not be called because the + * nrf_crypto backend was busy. Please rerun the + * cryptographic routine at a later time. + * @retval NRF_ERROR_CRYPTO_ALLOC_FAILED Unable to allocate memory for the context. + * @retval NRF_ERROR_CRYPTO_INTERNAL An internal error occurred in the nrf_crypto + * backend. + */ +ret_code_t nrf_crypto_hash_calculate(nrf_crypto_hash_context_t * const p_context, + nrf_crypto_hash_info_t const * p_info, + uint8_t const * p_data, + size_t data_size, + uint8_t * p_digest, + size_t * const p_digest_size); + +#ifdef __cplusplus +} +#endif + +/**@} */ + +#endif // NRF_CRYPTO_HASH_H__ diff --git a/components/libraries/crypto/nrf_crypto_hash_backend.h b/components/libraries/crypto/nrf_crypto_hash_backend.h new file mode 100644 index 0000000..be70874 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_hash_backend.h @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_HASH_BACKEND_H__ +#define NRF_CRYPTO_HASH_BACKEND_H__ + +#include "sdk_common.h" +#include "cc310_backend_hash.h" +#include "mbedtls_backend_hash.h" +#include "oberon_backend_hash.h" +#include "cc310_bl_backend_hash.h" +#include "nrf_sw_backend_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_HASH_SHA256) + +/**@internal @brief Fallback type for SHA-256 hash context (if no backend is enabled). + */ +typedef nrf_crypto_hash_internal_context_t nrf_crypto_backend_hash_sha256_context_t; + +#endif + +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_HASH_SHA512) + +/**@internal @brief Fallback type for SHA-512 hash context (if no backend is enabled). + */ +typedef nrf_crypto_hash_internal_context_t nrf_crypto_backend_hash_sha512_context_t; + +#endif + + +/** @internal @brief Union holding a hash context. */ +typedef union +{ + nrf_crypto_backend_hash_sha256_context_t hash_sha256_context; /**< @brief Holds context for SHA-256. */ + nrf_crypto_backend_hash_sha512_context_t hash_sha512_context; /**< @brief Holds context for SHA-512. */ +} nrf_crypto_backend_hash_context_t; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_CRYPTO_HASH_BACKEND_H__ diff --git a/components/libraries/crypto/nrf_crypto_hash_shared.h b/components/libraries/crypto/nrf_crypto_hash_shared.h new file mode 100644 index 0000000..f1ebeeb --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_hash_shared.h @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_HASH_SHARED_H__ +#define NRF_CRYPTO_HASH_SHARED_H__ + +#include "stdint.h" +#include "stddef.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_CRYPTO_HASH_INIT_VALUE (0x4846526E) //!< Magic value to signal that the nrf_crypto_hash context structure is initialized. + +/**@brief Enumeration of supported modes of operation in nrf_crypto_hash + */ +typedef enum +{ + NRF_CRYPTO_HASH_MODE_SHA256, + NRF_CRYPTO_HASH_MODE_SHA512 +} nrf_crypto_hash_mode_t; + + +/**@internal @brief Type declaration to do hash initialization in nrf_crypto backend. + * + * This is an internal API. See @ref nrf_crypto_hash_init for documentation. + */ +typedef ret_code_t (*nrf_crypto_hash_init_fn_t)(void * const p_context); + + +/**@internal @brief Type declaration to do hash update in nrf_crypto backend. + * + * This is an internal API. See @ref nrf_crypto_hash_init for documentation. + */ +typedef ret_code_t (*nrf_crypto_hash_update_fn_t)(void * const p_context, + uint8_t const * p_data, + size_t size); + + +/**@internal @brief Type declaration to do hash finalize in nrf_crypto backend. + * + * This is an internal API. See @ref nrf_crypto_hash_finalize for documentation. + */ +typedef ret_code_t (*nrf_crypto_hash_finalize_fn_t)(void * const p_context, + uint8_t * p_digest, + size_t * const p_digest_size); + + +/**@internal @brief Type declaration to for a nrf_crypto_hash info strucure + * + * @details This structure contains the calling interface and any meta data required + * to call the nrf_crypto_hash API functions. + */ +typedef struct +{ + nrf_crypto_hash_init_fn_t const init_fn; /**< Function pointer to call to initialize nrf_crypto_hash context in backend. */ + nrf_crypto_hash_update_fn_t const update_fn; /**< Function pointer to call to add data in the hash calculation. */ + nrf_crypto_hash_finalize_fn_t const finalize_fn; /**< Function pointer to call to finalize the hash calculation and return the result. */ + size_t const digest_size; /**< Size of the digest. */ + size_t const context_size; /**< Size of the context type. */ + nrf_crypto_hash_mode_t const hash_mode; /**< Mode of hash operation. */ +} nrf_crypto_hash_info_t; + + +/**@internal @brief Type declaration of internal representation of a hash context structure. + * + * @details This is an internal type that should not be used directly. + */ +typedef struct +{ + uint32_t init_val; /**< Value that is set to NRF_CRYPTO_HASH_INIT_VALUE when context has been initialized. */ + nrf_crypto_hash_info_t const * p_info; /**< Pointer to an nrf_crypto_hash info structure. */ + +} nrf_crypto_hash_internal_context_t; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_CRYPTO_HASH_SHARED_H__ diff --git a/components/libraries/crypto/nrf_crypto_hkdf.c b/components/libraries/crypto/nrf_crypto_hkdf.c new file mode 100644 index 0000000..bc361f3 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_hkdf.c @@ -0,0 +1,225 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include "stddef.h" +#include "nrf_assert.h" +#include "nrf_crypto_hmac.h" +#include "nrf_crypto_hkdf.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_mem.h" +#include "nrf_crypto_shared.h" +#include "nrf_crypto_hmac_shared.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HMAC) + +static ret_code_t hkdf_expand(nrf_crypto_hmac_context_t * const p_context, + nrf_crypto_hmac_info_t const * p_info, + uint8_t * const p_output_key, + size_t output_key_size, + uint8_t const * const p_ainfo, + size_t ainfo_size, + uint8_t * const p_temp, + uint8_t const * const p_prk, + size_t prk_size) +{ + size_t const hash_digest_size = p_info->digest_size; + uint32_t const n_iterations = (output_key_size + hash_digest_size - 1) / hash_digest_size; + ret_code_t err_code = NRF_SUCCESS; + size_t temp_size; + uint8_t n_current; + int write_offset; + + VERIFY_TRUE(n_iterations <= 255, NRF_ERROR_CRYPTO_OUTPUT_LENGTH); + + write_offset = 0; + for (uint32_t i = 0; i < n_iterations; i++) + { + n_current = i + 1; + + err_code = nrf_crypto_hmac_init(p_context, p_info, p_prk, prk_size); + VERIFY_SUCCESS(err_code); + + if (i != 0) + { + err_code = nrf_crypto_hmac_update(p_context, p_temp, hash_digest_size); + VERIFY_SUCCESS(err_code); + } + + if (p_ainfo != NULL) + { + err_code = nrf_crypto_hmac_update(p_context, p_ainfo, ainfo_size); + VERIFY_SUCCESS(err_code); + } + + err_code = nrf_crypto_hmac_update(p_context, &n_current, 1); + VERIFY_SUCCESS(err_code); + + temp_size = hash_digest_size; + err_code = nrf_crypto_hmac_finalize(p_context, p_temp, &temp_size); + VERIFY_SUCCESS(err_code); + + memcpy(p_output_key + write_offset, + p_temp, + (n_current != n_iterations) ? hash_digest_size : (output_key_size - write_offset)); + + write_offset += hash_digest_size; + } + + return err_code; +} + + +ret_code_t nrf_crypto_hkdf_calculate(nrf_crypto_hmac_context_t * const p_context, + nrf_crypto_hmac_info_t const * p_info, + uint8_t * const p_output_key, + size_t * const p_output_key_size, + uint8_t const * const p_input_key, + size_t input_key_size, + uint8_t const * p_salt, + size_t salt_size, + uint8_t const * const p_ainfo, + size_t ainfo_size, + nrf_crypto_hkdf_mode_t mode) +{ + uint8_t prk[NRF_CRYPTO_HASH_SIZE_SHA512]; // Scaled for the largest supported hash size. + uint8_t temp[NRF_CRYPTO_HASH_SIZE_SHA512]; // Scaled for the largest supported hash size. + void * p_ctx = NULL; + void * p_allocated_context = NULL; + size_t prk_size = sizeof(prk); + size_t output_key_size = *p_output_key_size; + ret_code_t err_code; + + VERIFY_TRUE(p_info != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + VERIFY_TRUE(p_output_key != NULL, NRF_ERROR_CRYPTO_OUTPUT_NULL); + VERIFY_TRUE(*p_output_key_size > 0, NRF_ERROR_CRYPTO_OUTPUT_LENGTH); + VERIFY_TRUE(p_input_key != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + VERIFY_TRUE(input_key_size > 0, NRF_ERROR_CRYPTO_INPUT_LENGTH); + + if (p_salt != NULL) + { + VERIFY_TRUE(salt_size > 0, NRF_ERROR_CRYPTO_INPUT_LENGTH); + } + + if (p_ainfo != NULL) + { + VERIFY_TRUE(ainfo_size > 0, NRF_ERROR_CRYPTO_INPUT_LENGTH); + } + + *p_output_key_size = 0; // Set output length to 0 as default value (in case of error). + + // Allocate context internally if p_context is NULL + if (p_context == NULL) + { + p_allocated_context = NRF_CRYPTO_ALLOC(p_info->context_size); + if (p_allocated_context == NULL) + { + return NRF_ERROR_CRYPTO_ALLOC_FAILED; + } + p_ctx = p_allocated_context; + } + else + { + p_ctx = p_context; + } + + if (mode == NRF_CRYPTO_HKDF_EXTRACT_AND_EXPAND) + { + if (p_salt == NULL) + { + // Use default salt defined in RFC 5869: String of zeros of hash length. + salt_size = p_info->digest_size; + ASSERT(sizeof(temp) >= salt_size); + memset(temp, 0, salt_size); + p_salt = temp; + } + + // Step 1: Extract + err_code = nrf_crypto_hmac_calculate(p_context, + p_info, + prk, + &prk_size, + p_salt, + salt_size, + p_input_key, + input_key_size); + NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(err_code, p_allocated_context); + + // Step 2: Expand + err_code = hkdf_expand(p_ctx, + p_info, + p_output_key, + output_key_size, + p_ainfo, + ainfo_size, + temp, + prk, + prk_size); + NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(err_code, p_allocated_context); + } + else // NRF_CRYPTO_HKDF_EXPAND_ONLY + { + err_code = hkdf_expand(p_ctx, + p_info, + p_output_key, + output_key_size, + p_ainfo, + ainfo_size, + temp, + p_input_key, + input_key_size); + NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(err_code, p_allocated_context); + } + + if (p_allocated_context != NULL) + { + NRF_CRYPTO_FREE(p_allocated_context); + } + + *p_output_key_size = output_key_size; + + return NRF_SUCCESS; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_HMAC) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) diff --git a/components/libraries/crypto/nrf_crypto_hkdf.h b/components/libraries/crypto/nrf_crypto_hkdf.h new file mode 100644 index 0000000..6ae5d00 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_hkdf.h @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_HKDF_H__ +#define NRF_CRYPTO_HKDF_H__ + +/** @file + * + * @defgroup nrf_crypto_hkdf HMAC based Key Derivation Function (HKDF) related functions + * @{ + * @ingroup nrf_crypto + * + * @brief Provides functions to generate HMAC based Key Derivation Function (HKDF). + * + * @details Provides functions to generate HMAC based Key Derivation Function (HKDF) using + * one of the supported hash algorithms. This layer is independent of backend crypto library. + * The HKDF module does not have a backend configuration, as it uses the nrf_crypto_hmac API, + * including the backend configured for HMAC in @ref sdk_config. + */ + + +#include +#include "sdk_common.h" +#include "nrf_crypto_hmac.h" +#include "nrf_crypto_hkdf.h" +#include "nrf_crypto_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Enumeration of HKDF modes. + */ +typedef enum +{ + NRF_CRYPTO_HKDF_EXTRACT_AND_EXPAND, //!< HKDF Extract and expand mode (normal). + NRF_CRYPTO_HKDF_EXPAND_ONLY //!< HKDF Expand only mode. +} nrf_crypto_hkdf_mode_t; + + +/** + * @brief Integrated HKDF calculation function + * + * @details This HKDF calculation function uses the nrf_crypto HMAC frontend directly. + * The backend is selected by configuring the HMAC backend in @ref sdk_config. + * + * @param[in,out] p_context Pointer to context structure. Context memory will be + * allocated internally if the context pointer is NULL. + * @param[in] p_info Pointer to static info structure. This defines the algorithm. + * This should be either @ref g_nrf_crypto_hmac_sha256_info or + * @ref g_nrf_crypto_hmac_sha512_info. + * @param[out] p_output_key Pointer to buffer to hold the output key material. + * @param[in,out] p_output_key_size Pointer to the length of the wanted output key material as input + * and actual length of the output material as output. Can be any + * number between 1 and the hash digest size multiplied by 255 + * (65280 for SHA-256 or 130560 for SHA-512). The p_output_key + * buffer must be large enough to hold this value. + * @param[in] p_input_key Pointer to buffer holding the input key material. + * @param[in] input_key_size Length of the input key material. + * @param[in] p_salt Pointer to buffer of nonsecret random salt data. Set to NULL in + * order to use the default salt defined by RFC 5869 (all zero + * array of hash digest size) or if salt is not used (expand only). + * @param[in] salt_size Length of the salt. Must be > 0 unless default salt is used, or + * in case mode is set to @ref NRF_CRYPTO_HKDF_EXPAND_ONLY. + * @param[in] p_ainfo Pointer to optional application specific information. + * (set to NULL and set ainfo_size to 0 if unused). + * @param[in] ainfo_size Length of the additional information. + * @param[in] mode Set to @ref NRF_CRYPTO_HKDF_EXTRACT_AND_EXPAND for normal mode. + * Alternatively, set to @ref NRF_CRYPTO_HKDF_EXPAND_ONLY to skip + * the extraction step. + * + * @retval NRF_SUCCESS Output key material hash was successfully calculated. + * @retval NRF_ERROR_CRYPTO_INPUT_NULL If p_input_key was NULL. + * @retval NRF_ERROR_CRYPTO_INPUT_LENGTH If input_key_size or salt_size was invalid. + * @retval NRF_ERROR_CRYPTO_OUTPUT_NULL If p_output_key_sizen was NULL. + * @retval NRF_ERROR_CRYPTO_OUTPUT_LENGTH If *p_output_key_size is 0. + * @retval NRF_ERROR_CRYPTO_ALLOC_FAILED Unable to allocate memory for the context. + * @retval NRF_ERROR_CRYPTO_INTERNAL An error occurred in the crypto backend. + * @retval NRF_ERROR_CRYPTO_BUSY The function could not be called because the + * nrf_crypto backend was busy. Please rerun the + * cryptographic routine at a later time. CC310 only. + */ +ret_code_t nrf_crypto_hkdf_calculate(nrf_crypto_hmac_context_t * const p_context, + nrf_crypto_hmac_info_t const * p_info, + uint8_t * const p_output_key, + size_t * const p_output_key_size, + uint8_t const * const p_input_key, + size_t input_key_size, + uint8_t const * p_salt, + size_t salt_size, + uint8_t const * const p_ainfo, + size_t ainfo_size, + nrf_crypto_hkdf_mode_t mode); + + +#ifdef __cplusplus +} +#endif + +/**@} */ + +#endif // #ifndef NRF_CRYPTO_HKDF_H__ diff --git a/components/libraries/crypto/nrf_crypto_hmac.c b/components/libraries/crypto/nrf_crypto_hmac.c new file mode 100644 index 0000000..6e76597 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_hmac.c @@ -0,0 +1,203 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include "stddef.h" +#include "nrf_log.h" +#include "nrf_crypto_hmac.h" +#include "nrf_crypto_hmac_shared.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_init.h" +#include "nrf_crypto_mem.h" +#include "nrf_crypto_shared.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_HMAC) + +// Magic word that is set when initializing the context and checked by functions that use it. +#define NRF_CRYPTO_HMAC_INIT_MAGIC_VALUE 0xBADEBA11 + + +static ret_code_t verify_context_valid(nrf_crypto_hmac_internal_context_t * const p_context) +{ + if (p_context == NULL) + { + return NRF_ERROR_CRYPTO_CONTEXT_NULL; + } + else if (p_context->init_value != NRF_CRYPTO_HMAC_INIT_MAGIC_VALUE) + { + return NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED; + } + else + { + return NRF_SUCCESS; + } +} + + +ret_code_t nrf_crypto_hmac_init(nrf_crypto_hmac_context_t * const p_context, + nrf_crypto_hmac_info_t const * p_info, + uint8_t const * p_key, + size_t key_size) +{ + ret_code_t err_code; + nrf_crypto_hmac_internal_context_t * p_ctx = (nrf_crypto_hmac_internal_context_t *)p_context; + + VERIFY_TRUE(nrf_crypto_is_initialized(), NRF_ERROR_CRYPTO_NOT_INITIALIZED); + + // Validate input + VERIFY_TRUE(p_ctx != NULL, NRF_ERROR_CRYPTO_CONTEXT_NULL); + VERIFY_TRUE(p_info != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + VERIFY_TRUE(p_key != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + VERIFY_TRUE(key_size > 0, NRF_ERROR_CRYPTO_INPUT_LENGTH); + + // Initialize generic part of the context + p_ctx->p_info = p_info; + + // Do backend specific initialization by calling the backend init function pointed + // to in the configuration struct in the context (nrf_crypto_hmac_config_t) + err_code = p_ctx->p_info->init_fn(p_context, p_key, key_size); + if (err_code == NRF_SUCCESS) + { + p_ctx->init_value = NRF_CRYPTO_HMAC_INIT_MAGIC_VALUE; + } + + return err_code; +} + + +ret_code_t nrf_crypto_hmac_update(nrf_crypto_hmac_context_t * const p_context, + uint8_t const * p_data, + size_t data_size) +{ + ret_code_t err_code; + + // The context header by definition has to be the first element of the context struct. + nrf_crypto_hmac_internal_context_t * p_ctx = (nrf_crypto_hmac_internal_context_t *)p_context; + + // Validate input + err_code = verify_context_valid(p_ctx); + VERIFY_SUCCESS(err_code); + VERIFY_TRUE(p_data != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + VERIFY_TRUE(data_size > 0, NRF_ERROR_CRYPTO_INPUT_LENGTH); + + // Call backend specific update function (pointed to by config struct in context) + err_code = p_ctx->p_info->update_fn(p_context, p_data, data_size); + + return err_code; +} + + +ret_code_t nrf_crypto_hmac_finalize(nrf_crypto_hmac_context_t * const p_context, + uint8_t * p_digest, + size_t * const p_digest_size) +{ + ret_code_t err_code; + + // The context header by definition has to be the first element of the context struct. + nrf_crypto_hmac_internal_context_t * p_ctx = (nrf_crypto_hmac_internal_context_t *)p_context; + + // Validate input + err_code = verify_context_valid(p_ctx); + VERIFY_SUCCESS(err_code); + VERIFY_TRUE(p_digest != NULL, NRF_ERROR_CRYPTO_OUTPUT_NULL); + VERIFY_TRUE(*p_digest_size >= p_ctx->p_info->digest_size, NRF_ERROR_CRYPTO_OUTPUT_LENGTH); + + // Call backend specific finish function (pointed to by config struct in context) + err_code = p_ctx->p_info->finalize_fn(p_context, p_digest, p_digest_size); + + return err_code; +} + + +ret_code_t nrf_crypto_hmac_calculate(nrf_crypto_hmac_context_t * const p_context, + nrf_crypto_hmac_info_t const * p_info, + uint8_t * p_digest, + size_t * const p_digest_size, + uint8_t const * p_key, + size_t key_size, + uint8_t const * p_data, + size_t data_size) +{ + ret_code_t err_code; + nrf_crypto_hmac_context_t * p_ctx; + void * p_allocated_context = NULL; + + // Validate input. Only validate input parameters that are used locally, others are validated + // in the init, update and/or finalize functions. + VERIFY_TRUE(p_info != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + + // Allocate context if needed (not provided by the user). + if (p_context == NULL) + { + p_allocated_context = NRF_CRYPTO_ALLOC(p_info->context_size); + if (p_allocated_context == NULL) + { + return NRF_ERROR_CRYPTO_ALLOC_FAILED; + } + p_ctx = (nrf_crypto_hmac_context_t *)p_allocated_context; + } + else + { + p_ctx = (nrf_crypto_hmac_context_t *)p_context; + } + + // Perform integrated HMAC calculation by caling the frontend functions defined in this file + err_code = nrf_crypto_hmac_init(p_ctx, p_info, p_key, key_size); + NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(err_code, p_allocated_context); + + err_code = nrf_crypto_hmac_update(p_ctx, p_data, data_size); + NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(err_code, p_allocated_context); + + err_code = nrf_crypto_hmac_finalize(p_ctx, p_digest, p_digest_size); + NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(err_code, p_allocated_context); + + // Free context if allocated internally + if (p_allocated_context != NULL) + { + NRF_CRYPTO_FREE(p_allocated_context); + } + + return err_code; +} + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_HMAC) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) diff --git a/components/libraries/crypto/nrf_crypto_hmac.h b/components/libraries/crypto/nrf_crypto_hmac.h new file mode 100644 index 0000000..f6516b8 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_hmac.h @@ -0,0 +1,226 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_HMAC_H__ +#define NRF_CRYPTO_HMAC_H__ + +/** @file + * + * @defgroup nrf_crypto_hmac Hash-based message authentication code (HMAC) related functions + * @{ + * @ingroup nrf_crypto + * + * @brief Provides functions to generate Hash-based message authentication code (HMAC). + * + * @details Provides functions to generate Hash-based message authentication code (HMAC) using + * one of the supported hash algorithms. This layer is independent of backend crypto library. + */ + +#include +#include "sdk_common.h" +#include "nrf_crypto_types.h" +#include "nrf_crypto_hmac_backend.h" +#include "nrf_crypto_hmac_shared.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Information structures used to select the specific algorithm (SHA-256) + * + * @details The information structure is used in a generic way but is populated by the backend, + * and contains backend specific data. */ +extern const nrf_crypto_hmac_info_t g_nrf_crypto_hmac_sha256_info; + + +/** + * @brief Information structures used to select the specific algorithm (SHA-512) + * + * @details The information structure is used in a generic way but is populated by the backend, + * and contains backend specific data. + */ +extern const nrf_crypto_hmac_info_t g_nrf_crypto_hmac_sha512_info; + + +/** + * @brief Context type for HMAC. + * + * @note The size of this type is scaled for the largest HMAC backend context that is + * enabled in @ref sdk_config. + */ +typedef nrf_crypto_backend_hmac_context_t nrf_crypto_hmac_context_t; + +/** + * @brief Initialize context object for HMAC + * + * @details Use to initialize a context once it has been allocated. + * + * @note Must be called before @ref nrf_crypto_hmac_update. Can also be called after + * @ref nrf_crypto_hmac_finalize order to start a new HMAC calculation re-using an + * existing context object. + * + * @param[in,out] p_context Pointer to context structure. + * @param[in] p_info Pointer to static info structure. This defines the algorithm. + * This should be either @ref g_nrf_crypto_hmac_sha256_info or + * @ref g_nrf_crypto_hmac_sha512_info. + * @param[in] p_key HMAC key. + * @param[in] key_size Length of the HMAC key in bytes. + * + * @retval NRF_SUCCESS Data successfully consumed. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NULL If p_context has not been initialized. + * @retval NRF_ERROR_CRYPTO_INPUT_NULL If p_info or p_key was NULL. + * @retval NRF_ERROR_CRYPTO_INPUT_LENGTH If key_size was invalid. + * @retval NRF_ERROR_CRYPTO_INPUT_LOCATION Input data not in RAM (CC310 only). + * @retval NRF_ERROR_CRYPTO_INTERNAL An error occurred in the crypto backend. + * @retval NRF_ERROR_CRYPTO_BUSY The function could not be called because the + * nrf_crypto backend was busy. Please rerun + * the cryptographic routine at a later time. + * CC310 only. + */ +ret_code_t nrf_crypto_hmac_init(nrf_crypto_hmac_context_t * const p_context, + nrf_crypto_hmac_info_t const * p_info, + uint8_t const * p_key, + size_t key_size); + + +/** + * @brief Feed data to HMAC algorithm. + * + * @note Must be called after @ref nrf_crypto_hmac_init and before @ref nrf_crypto_hmac_finalize. + * Can be called repeatedly to consume data as it arrives. + * + * @param[in,out] p_context Context pointer. + * @param[in] p_data Pointer to input data buffer. + * @param[in] data_size Length of input data. + * + * @retval NRF_SUCCESS Data successfully consumed. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NULL If p_context has not been initialized. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED If p_data was NULL. + * @retval NRF_ERROR_CRYPTO_INPUT_NULL If p_data was NULL. + * @retval NRF_ERROR_CRYPTO_INPUT_LENGTH If size was invalid. + * @retval NRF_ERROR_CRYPTO_INPUT_LOCATION Input data not in RAM (CC310 only). + * @retval NRF_ERROR_CRYPTO_INTERNAL An error occurred in the crypto backend. + * @retval NRF_ERROR_CRYPTO_BUSY The function could not be called because the + * nrf_crypto backend was busy. Please rerun + * the cryptographic routine at a later time. + * CC310 only. + */ +ret_code_t nrf_crypto_hmac_update(nrf_crypto_hmac_context_t * const p_context, + uint8_t const * p_data, + size_t data_size); + + +/** + * @brief Calculate HMAC + * + * @note @ref nrf_crypto_hmac_update must be called at least once before calling this. + * + * @param[in,out] p_context Context pointer. + * @param[out] p_digest Pointer to HMAC digest (result) buffer. Must be large enough to + * hold the digest (32 byte for SHA-256 and 64 byte for SHA-512). + * @param[in,out] p_digest_size Length of buffer as input. Length of digest as output. + * + * @retval NRF_SUCCESS HMAC hash was successfully calculated. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NULL If p_context was NULL. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED If p_context has not been initialized. + * @retval NRF_ERROR_CRYPTO_OUTPUT_NULL If p_digest was NULL. + * @retval NRF_ERROR_CRYPTO_OUTPUT_LENGTH If p_size is not enough to hold the digest. + * @retval NRF_ERROR_CRYPTO_INTERNAL An error occurred in the crypto backend. + * @retval NRF_ERROR_CRYPTO_BUSY The function could not be called because the + * nrf_crypto backend was busy. Please rerun + * the cryptographic routine at a later time. + * CC310 only. + */ +ret_code_t nrf_crypto_hmac_finalize(nrf_crypto_hmac_context_t * const p_context, + uint8_t * p_digest, + size_t * const p_digest_size); + + +/** + * @brief Integrated HMAC wrapper function + * + * @note This is an integrated wrapper functions that can be used instead of calling other HMAC + * functions individually. + * + * @param[in,out] p_context Optional pointer to context structure. + * Context memory will be allocated internally if the pointer is NULL. + * @param[in] p_info Pointer to static info structure. This defines the algorithm. + * This should be either @ref g_nrf_crypto_hmac_sha256_info or + * @ref g_nrf_crypto_hmac_sha512_info. + * @param[out] p_digest Pointer to HMAC digest. + * Buffer must be large enough to hold the digest. + * @param[in,out] p_digest_size Length of digest (result) buffer as input. + * Length of digest as output. + * @param[in] p_key Pointer to HMAC key. + * @param[in] key_size Lenth of the HMAC key in bytes. + * @param[in] p_data Pointer to input data. + * @param[in] data_size Length of input data. + * + * @retval NRF_SUCCESS HMAC hash was successfully calculated. + * @retval NRF_ERROR_CRYPTO_INPUT_NULL If p_key or p_data was NULL. + * @retval NRF_ERROR_CRYPTO_INPUT_LOCATION Input data not in RAM (CC310 only). + * @retval NRF_ERROR_CRYPTO_INPUT_LENGTH If key_size or data_size was invalid. + * @retval NRF_ERROR_CRYPTO_OUTPUT_NULL If data_size was NULL. + * @retval NRF_ERROR_CRYPTO_OUTPUT_LENGTH If data_size is not enough to hold the digest. + * @retval NRF_ERROR_CRYPTO_ALLOC_FAILED Unable to allocate memory for the context. + * @retval NRF_ERROR_CRYPTO_INTERNAL An error occurred in the crypto backend. + * @retval NRF_ERROR_CRYPTO_BUSY The function could not be called because the + * nrf_crypto backend was busy. Please rerun the + * cryptographic routine at a later time. CC310 only. + */ +ret_code_t nrf_crypto_hmac_calculate(nrf_crypto_hmac_context_t * const p_context, + nrf_crypto_hmac_info_t const * p_info, + uint8_t * p_digest, + size_t * const p_digest_size, + uint8_t const * p_key, + size_t key_size, + uint8_t const * p_data, + size_t data_size); + + +#ifdef __cplusplus +} +#endif + +/**@} */ + +#endif // #ifndef NRF_CRYPTO_HMAC_H__ diff --git a/components/libraries/crypto/nrf_crypto_hmac_backend.h b/components/libraries/crypto/nrf_crypto_hmac_backend.h new file mode 100644 index 0000000..4ad4884 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_hmac_backend.h @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_HMAC_BACKEND_H__ +#define NRF_CRYPTO_HMAC_BACKEND_H__ + +/** @file + * + * @defgroup nrf_crypto_hmac_backend Meta backend. + * @{ + * @ingroup nrf_crypto_hmac + * + * @brief Includes all backends definitions. + * + * @details This file includes all backend definitions, and provide a dummy context in case no + * backend is enabled. This is needed so that any project including HMAC headers will still + * compile when HMAC is not used/enabled. + */ + +#include "sdk_common.h" +#include "nrf_crypto_hmac_shared.h" +#include "mbedtls_backend_hmac.h" +#include "cc310_backend_hmac.h" +#include "oberon_backend_hmac.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifndef NRF_CRYPTO_HMAC_SHA256_ENABLED +// /** @internal @brief Fallback context type for HMAC SHA256 in case no backend is selected. */ +typedef nrf_crypto_hmac_internal_context_t nrf_crypto_backend_hmac_sha256_context_t; +#endif // #ifndef NRF_CRYPTO_HMAC_SHA256_ENABLED + +#ifndef NRF_CRYPTO_HMAC_SHA512_ENABLED +/** @internal @brief Fallback context type for HMAC SHA512 in case no backend is selected. */ +typedef nrf_crypto_hmac_internal_context_t nrf_crypto_backend_hmac_sha512_context_t; +#endif // #ifndef NRF_CRYPTO_HMAC_SHA512_ENABLED + + +/** @internal @brief Union holding a HMAC context. */ +typedef union +{ + nrf_crypto_backend_hmac_sha256_context_t hmac_sha256_context; /**< @brief Holds context for HMAC SHA-256. */ + nrf_crypto_backend_hmac_sha512_context_t hmac_sha512_context; /**< @brief Holds context for HMAC SHA-512. */ +} nrf_crypto_backend_hmac_context_t; + + +#ifdef __cplusplus +} +#endif + +/**@} */ + +#endif // NRF_CRYPTO_HMAC_BACKEND_H__ diff --git a/components/libraries/crypto/nrf_crypto_hmac_shared.h b/components/libraries/crypto/nrf_crypto_hmac_shared.h new file mode 100644 index 0000000..85e918c --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_hmac_shared.h @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_HMAC_SHARED_H__ +#define NRF_CRYPTO_HMAC_SHARED_H__ + +/** @file + * + * @defgroup nrf_crypto_hmac_shared Types shared between all @ref nrf_crypto_hmac backends. + * @{ + * @ingroup nrf_crypto_hmac + * + * @brief Types shared between all @ref nrf_crypto_hmac backends. + * + * @details These types should not be used directly by the application. + */ + +#include +#include "sdk_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @internal @brief HMAC algorithm type. + */ +typedef enum { + NRF_CRYPTO_HMAC_SHA256_TYPE, //!< HMAC using hash algorithm SHA256 + NRF_CRYPTO_HMAC_SHA512_TYPE, //!< HMAC using hash algorithm SHA512 +} nrf_crypto_hmac_type_t; + + +/** + * @internal @brief Function pointer type for HMAC backend init function. + * + * @note The backend function should never be called directly. + * Use @ref nrf_crypto_hmac_init instead. + * + * @param[in,out] p_context Context pointer. + * @param[in] p_key HMAC key. + * @param[in] key_size Length of the HMAC key in bytes. +*/ +typedef ret_code_t (*nrf_crypto_hmac_init_fn_t)(void * const p_context, + uint8_t const * p_key, + size_t key_size); + + +/** + * @internal @brief Function pointer type for HMAC backend update function. + * + * @note The backend function should never be called directly. + * Use @ref nrf_crypto_hmac_update instead. + * + * @param[in,out] p_context Context pointer. + * @param[in] p_data Pointer to input data buffer. + * @param[in] size Length of input data. +*/ +typedef ret_code_t (*nrf_crypto_hmac_update_fn_t)(void * const p_context, + uint8_t const * p_data, + size_t size); + + +/** + * @internal @brief Function pointer type for HMAC backend finalize function. + * + * @note The backend function should never be called directly. + * Use @ref nrf_crypto_hmac_finalize instead. + * + * @param[in,out] p_context Context pointer. + * @param[out] p_digest HMAC digest (result) buffer. + * @param[in,out] p_size Length of buffer as input. Length of digest as output. +*/ +typedef ret_code_t (*nrf_crypto_hmac_finalize_fn_t)(void * const p_context, + uint8_t * const p_digest, + size_t * p_size); + + +/** + * @internal @brief structure holding the configuration of each particular algorithm. + * + * @details This is an internal type that should not be used directly. + */ +typedef struct +{ + nrf_crypto_hmac_init_fn_t const init_fn; //!< Pointer to update function for specific backend. + nrf_crypto_hmac_update_fn_t const update_fn; //!< Pointer to update function for specific backend. + nrf_crypto_hmac_finalize_fn_t const finalize_fn; //!< Pointer to finalize function for specific backend. + size_t const digest_size; //!< Size of the digest of the HMAC operation. + size_t const context_size; //!< Size of the context type. + nrf_crypto_hmac_type_t const type; //!< HMAC algorithm type. +} nrf_crypto_hmac_info_t; + + +/** + * @internal @brief Common header for each HMAC context structures + * + * @details This is an internal type that should not be used directly. + */ +typedef struct +{ + uint32_t init_value; //!< Contains NRF_CRYPTO_HMAC_INIT_MAGIC_VALUE if it is correctly initialized. + nrf_crypto_hmac_info_t const * p_info; //!< Points to information object related to selected algorithm. +} nrf_crypto_hmac_internal_context_t; + + +#ifdef __cplusplus +} +#endif + +/**@} */ + +#endif // NRF_CRYPTO_HMAC_SHARED_H__ diff --git a/components/libraries/crypto/nrf_crypto_init.c b/components/libraries/crypto/nrf_crypto_init.c new file mode 100644 index 0000000..26c813f --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_init.c @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include "nrf_crypto_init.h" +#include "nrf_section.h" + + +// Create a named section for crypto backend data +NRF_SECTION_DEF(crypto_data, const nrf_crypto_backend_info_t); + + +#define NRF_CRYPTO_BACKEND_SECTION_ITEM_GET(i) NRF_SECTION_ITEM_GET(crypto_data, nrf_crypto_backend_info_t, (i)) +#define NRF_CRYPTO_BACKEND_SECTION_ITEM_COUNT NRF_SECTION_ITEM_COUNT(crypto_data, nrf_crypto_backend_info_t) + +typedef enum +{ + UNINITIALIZED, + INITIALIZING, + INITIALIZED, +} nrf_crypto_state_t; + +static volatile nrf_crypto_state_t m_state = UNINITIALIZED; + + +ret_code_t nrf_crypto_init(void) +{ + ret_code_t ret_val; + size_t const num_backends = NRF_CRYPTO_BACKEND_SECTION_ITEM_COUNT; + + m_state = INITIALIZING; + + // Iterate through each backends to call the init function + for (size_t i = 0; i < num_backends; i++) + { + nrf_crypto_backend_info_t const * p_backend = NRF_CRYPTO_BACKEND_SECTION_ITEM_GET(i); + ret_val = p_backend->init_fn(); + if (ret_val != NRF_SUCCESS) + { + return ret_val; + } + } + + // Set nrf_crypto to initialized + m_state = INITIALIZED; + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_uninit(void) +{ + ret_code_t ret_val; + size_t const num_backends = NRF_CRYPTO_BACKEND_SECTION_ITEM_COUNT; + + // Iterate through each backends to call the uninit function + for (size_t i = 0; i < num_backends; i++) + { + nrf_crypto_backend_info_t const * p_backend = NRF_CRYPTO_BACKEND_SECTION_ITEM_GET(i); + ret_val = p_backend->uninit_fn(); + if (ret_val != NRF_SUCCESS) + { + return ret_val; + } + } + + // Set nrf_crypto to uninitialized + m_state = UNINITIALIZED; + return NRF_SUCCESS; +} + + +bool nrf_crypto_is_initialized(void) +{ + return (m_state == INITIALIZED); +} + + +bool nrf_crypto_is_initializing(void) +{ + return ((m_state == INITIALIZED) || m_state == INITIALIZING); +} + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) diff --git a/components/libraries/crypto/nrf_crypto_init.h b/components/libraries/crypto/nrf_crypto_init.h new file mode 100644 index 0000000..6462766 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_init.h @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_INIT_H__ +#define NRF_CRYPTO_INIT_H__ + +/** @file + * + * @defgroup nrf_crypto_initialization Initialization + * @{ + * @ingroup nrf_crypto + * + * @brief Initialization related functions for nrf_crypto . + * + * @details @ref lib_crypto is responsible for global initialization of the nrf_crypto + * frontend and backends that are enabled in @ref sdk_config. + */ + +#include +#include +#include "nrf_section.h" +#include "sdk_errors.h" +#include "nrf_crypto_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@internal @brief Macro for registering a nrf_crypto backend for initialization by using + * nrf_section. + * + * @details This macro places a variable in a section named "crypto_data", which + * is initialized by @ref nrf_crypto_init. + * + * @note This macro is used internally based on sdk_config.h configurations for nrf_crypto + */ +#define CRYPTO_BACKEND_REGISTER(crypto_var) NRF_SECTION_ITEM_REGISTER(crypto_data, crypto_var) + +/**@internal @brief Type definition of function pointer to initialize the nrf_crypto backend. + * + * This function type is used internally. See @nrf_crypto_init for documentation. + */ +typedef ret_code_t (*nrf_crypto_backend_init_fn_t)(void); + + +/**@internal @brief Type definition of function pointer to uninitialize the nrf_crypto backend. + * + * This function type is used internally. Please see @nrf_crypto_uninit for documentation. + */ +typedef ret_code_t (*nrf_crypto_backend_uninit_fn_t)(void); + + + +/**@internal @brief Type definition for structure holding the calling interface to + * init, uninit, enable, or disable an nrf_crypto_backend + * + * @note Some backends require no expressive init, uninit, enable, or disable. + * In this case, the backend will not use this structure type or only select + * to implement + */ +typedef struct +{ + nrf_crypto_backend_init_fn_t const init_fn; + nrf_crypto_backend_uninit_fn_t const uninit_fn; +} nrf_crypto_backend_info_t; + + +/**@brief Function for initializing nrf_crypto and all registered backends. + * + * @details Must always be called before any other @ref nrf_crypto function. + * + * @retval NRF_SUCCESS The initialization was successful. + * @retval NRF_ERROR_INTERNAL An internal error occured in the nrf_crypt backend init. + */ +ret_code_t nrf_crypto_init(void); + + +/**@brief Function for uninitializing nrf_crypto and all registered backends. + * + * @retval NRF_SUCCESS If unititialization was successful. + * @retval NRF_ERROR_INTERNAL If an internal error occured in the nrf_crypt backend init. + */ +ret_code_t nrf_crypto_uninit(void); + + +/**@brief Function reporting if nrf_crypto has been initialized. + * + * @retval True If cryptographic library is initialized. + * @retval False If cryptographic library is not initialized. + */ +bool nrf_crypto_is_initialized(void); + + +/**@brief Function reporting if nrf_crypto is initialized or is in the process of being initialized. + * + * @retval True If cryptographic library is initializing or already initialized. + * @retval False If cryptographic library is not initialized. + */ +bool nrf_crypto_is_initializing(void); + +#ifdef __cplusplus +} +#endif + +/**@} */ + +#endif // NRF_CRYPTO_INIT_H__ diff --git a/components/libraries/crypto/nrf_crypto_mem.h b/components/libraries/crypto/nrf_crypto_mem.h new file mode 100644 index 0000000..5421315 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_mem.h @@ -0,0 +1,185 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_MEM_H__ +#define NRF_CRYPTO_MEM_H__ + +/** @file + * + * @defgroup nrf_crypto_mem Dynamic memory management module + * @{ + * @ingroup nrf_crypto + * + * @brief Module to manage dynamically allocated memory used by nrf_crypto APIs. + * + * @ref NRF_CRYPTO_ALLOCATOR definition is used to configure this module. + */ + +#include +#include "sdk_common.h" +#include "sdk_config.h" +#include "nrf_crypto_types.h" +#include "sdk_alloca.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifndef __SDK_DOXYGEN__ + + +#define NRF_CRYPTO_ALLOCATOR_DEFAULT 0 /**< @internal @brief Value for NRF_CRYPTO_ALLOCATOR to select default memory allocation. */ +#define NRF_CRYPTO_ALLOCATOR_USER 1 /**< @internal @brief Value for NRF_CRYPTO_ALLOCATOR to select user defined memory allocation. */ +#define NRF_CRYPTO_ALLOCATOR_ALLOCA 2 /**< @internal @brief Value for NRF_CRYPTO_ALLOCATOR to select stack based memory allocation. */ +#define NRF_CRYPTO_ALLOCATOR_MALLOC 3 /**< @internal @brief Value for NRF_CRYPTO_ALLOCATOR to select stdlib's dynamic memory allocation. */ +#define NRF_CRYPTO_ALLOCATOR_NRF_MALLOC 4 /**< @internal @brief Value for NRF_CRYPTO_ALLOCATOR to select mem_manager for memory allocation. */ + + +#ifndef NRF_CRYPTO_ALLOCATOR +#define NRF_CRYPTO_ALLOCATOR NRF_CRYPTO_ALLOCATOR_DEFAULT +#endif + + +#if NRF_CRYPTO_ALLOCATOR == NRF_CRYPTO_ALLOCATOR_DEFAULT +#undef NRF_CRYPTO_ALLOCATOR +#if SDK_ALLOCA_DEFINED && !NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_MBEDTLS) +#define NRF_CRYPTO_ALLOCATOR NRF_CRYPTO_ALLOCATOR_ALLOCA +#else +#define NRF_CRYPTO_ALLOCATOR NRF_CRYPTO_ALLOCATOR_NRF_MALLOC +#endif +#endif + + +#if NRF_CRYPTO_ALLOCATOR == NRF_CRYPTO_ALLOCATOR_USER + +#include "nrf_crypto_allocator.h" +#ifndef NRF_CRYPTO_ALLOC +#error "User defined allocator for nrf_crypto does not define NRF_CRYPTO_ALLOC" +#endif +#ifndef NRF_CRYPTO_FREE +#error "User defined allocator for nrf_crypto does not define NRF_CRYPTO_FREE" +#endif +#ifndef NRF_CRYPTO_ALLOC_ON_STACK +#error "User defined allocator for nrf_crypto does not define NRF_CRYPTO_ALLOC_ON_STACK" +#endif + +#elif NRF_CRYPTO_ALLOCATOR == NRF_CRYPTO_ALLOCATOR_ALLOCA + +#if !SDK_ALLOCA_DEFINED +#warning "Stack based allocation is selected, but alloca() is not supported on this platform" +#endif +#define NRF_CRYPTO_ALLOC(size) (alloca((size_t)(size))) +#define NRF_CRYPTO_FREE(p_buffer) // Empty +#define NRF_CRYPTO_ALLOC_ON_STACK 1 + +#elif NRF_CRYPTO_ALLOCATOR == NRF_CRYPTO_ALLOCATOR_MALLOC + +#include "stdlib.h" +#define NRF_CRYPTO_ALLOC(size) (malloc((size_t)(size))) +#define NRF_CRYPTO_FREE(p_buffer) (free((void *)(p_buffer))) +#define NRF_CRYPTO_ALLOC_ON_STACK 0 + +#elif NRF_CRYPTO_ALLOCATOR == NRF_CRYPTO_ALLOCATOR_NRF_MALLOC + +#include "mem_manager.h" +#define NRF_CRYPTO_ALLOC(size) (nrf_malloc((uint32_t)(size))) +#define NRF_CRYPTO_FREE(p_buffer) (nrf_free((void *)(p_buffer))) +#define NRF_CRYPTO_ALLOC_ON_STACK 0 + +#else + +#error "Invalid NRF_CRYPTO_ALLOCATOR configuration value" + +#endif + + +#else // __SDK_DOXYGEN__ + + +/** @brief Defines memory allocation function for nrf_crypto. + * + * This macro is used internally by nrf_crypto library to allocate temporary memory. It is not + * intended to be used outside nrf_crypto library. How memory is actually allocated is configured + * by @ref NRF_CRYPTO_ALLOCATOR definition. + * + * If user macros are selected by @ref NRF_CRYPTO_ALLOCATOR then this macro have to be defined by + * the user in "nrf_crypto_allocator.h" file. The file will be included into "nrf_crypto_mem.h". + * + * If @ref NRF_CRYPTO_ALLOC_ON_STACK is 1 then this function will allocate data on stack, + * so make sure that returned pointer is not used outside the caller function. + * + * @param size Number of bytes to allocate. + * @returns Pointer to newly allocated memory or NULL on error. + */ +#define NRF_CRYPTO_ALLOC(size) + +/** @brief Defines memory deallocation function for nrf_crypto. + * + * This macro is used internally by nrf_crypto library to deallocate temporary memory. It is not + * intended to be used outside nrf_crypto library. + * + * If user macros are selected by @ref NRF_CRYPTO_ALLOCATOR then this macro have to be defined by + * the user in "nrf_crypto_allocator.h" file. The file will be included into "nrf_crypto_mem.h". + * + * @param p_buffer Pointer to memory buffer for deallocation. + */ +#define NRF_CRYPTO_FREE(p_buffer) + +/** @brief Contains 1 if memory allocated by @ref NRF_CRYPTO_ALLOC is on stack or 0 otherwise. + * + * This definition is used internally by nrf_crypto library. It is not intended to be used outside + * nrf_crypto library. + * + * If user macros are selected by @ref NRF_CRYPTO_ALLOCATOR then this macro have to be defined by + * the user in "nrf_crypto_allocator.h" file. The file will be included into "nrf_crypto_mem.h". + */ +#define NRF_CRYPTO_ALLOC_ON_STACK + + +#endif // __SDK_DOXYGEN__ + +#ifdef __cplusplus +} +#endif + +/**@} */ + + #endif // NRF_CRYPTO_MEM_H__ diff --git a/components/libraries/crypto/nrf_crypto_rng.c b/components/libraries/crypto/nrf_crypto_rng.c new file mode 100644 index 0000000..8e1e806 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_rng.c @@ -0,0 +1,430 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + +#include "nrf_crypto_init.h" +#include "nrf_log.h" +#include "nrf_crypto_mem.h" +#include "nrf_crypto_rng.h" +#include "nrf_crypto_rng_shared.h" +#include "nrf_crypto_rng_backend.h" +#include "nrf_stack_info.h" + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) + +#define NRF_CRYPTO_RNG_MODULE_INIT_MAGIC_VALUE (0x4be57265) + +static nrf_crypto_backend_rng_context_t * mp_allocated_context = NULL; +static nrf_crypto_backend_rng_context_t * mp_context = NULL; +static uint32_t m_initialized = 0; + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS) +static nrf_crypto_backend_rng_context_t m_context; +static nrf_crypto_rng_temp_buffer_t m_temp_buffer; +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS) + + +static bool is_vector_greater_or_equal(uint8_t const * const p_vector, + uint8_t const * const p_min, + size_t size) +{ + for (size_t i = 0; i < size; i++) + { + if (p_vector[i] != p_min[i]) + { + if (p_vector[i] > p_min[i]) + { + return true; + } + else + { + return false; + } + } + } + + return true; +} + + +// Return true if value p_vector is between (including) p_min and p_max. +static bool is_vector_in_range(uint8_t const * const p_vector, + uint8_t const * const p_min, + uint8_t const * const p_max, + size_t size) +{ + if (!is_vector_greater_or_equal(p_vector, p_min, size)) + { + return false; + } + + if (!is_vector_greater_or_equal(p_max, p_vector, size)) + { + return false; + } + + return true; +} + + +static uint32_t count_leading_zeros(uint8_t const * const p_vector, size_t size) +{ + uint32_t leading_zeros = 0; + uint32_t nonzero_byte = 0xFF; + + // Find leading all-zero elements. + for (uint32_t i = 0; i < size; i++) + { + if (p_vector[i] == 0) + { + leading_zeros += 8; + } + else + { + nonzero_byte = p_vector[i]; + break; + } + } + + // Find leading zeros in non-zero element. + for (uint32_t i = 0; i < 8; i++) + { + nonzero_byte <<= 1; + + if ((nonzero_byte & ~0xff) > 0) + { + break; + } + + leading_zeros ++; + } + + return leading_zeros; +} + + +static ret_code_t generate(uint8_t * const p_target, size_t size, bool use_mutex) +{ + ret_code_t ret_code; + + VERIFY_TRUE(p_target != NULL, NRF_ERROR_CRYPTO_OUTPUT_NULL); + VERIFY_TRUE(size > 0, NRF_ERROR_CRYPTO_OUTPUT_LENGTH); + + VERIFY_TRUE(m_initialized == NRF_CRYPTO_RNG_MODULE_INIT_MAGIC_VALUE, + NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED); + + ret_code = nrf_crypto_rng_backend_vector_generate(mp_context, p_target, size, use_mutex); + + // Reseed internally and try again if reseed is required by the backend. + // (CC310 only as mbed TLS handles reseeding internally.) + if (ret_code == NRF_ERROR_CRYPTO_RNG_RESEED_REQUIRED) + { + ret_code = nrf_crypto_rng_reseed(NULL, NULL, 0); + + if (ret_code != NRF_SUCCESS) + { + return ret_code; + } + + ret_code = nrf_crypto_rng_backend_vector_generate(mp_context, p_target, size, use_mutex); + } + + return ret_code; +} + + +static ret_code_t generate_in_range(uint8_t * const p_target, + uint8_t const * const p_min, + uint8_t const * const p_max, + size_t size, + bool use_mutex) +{ + uint32_t const max_leading_zeros = count_leading_zeros(p_max, size); + ret_code_t ret_code; + + VERIFY_TRUE(p_target != NULL, NRF_ERROR_CRYPTO_OUTPUT_NULL); + VERIFY_TRUE(size > 0, NRF_ERROR_CRYPTO_OUTPUT_LENGTH); + VERIFY_TRUE(p_min != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + VERIFY_TRUE(p_max != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + VERIFY_TRUE(is_vector_greater_or_equal(p_max, p_min, size), NRF_ERROR_CRYPTO_INVALID_PARAM); + + do + { + ret_code = nrf_crypto_rng_backend_vector_generate(mp_context, p_target, size, use_mutex); + + if (ret_code != NRF_SUCCESS) + { + return ret_code; + } + + // Mask leading zeros in generated vector instead of always discarding a too large vectors. + memset(p_target, 0, max_leading_zeros / 8); + if ((max_leading_zeros & 0x07) > 0) + { + p_target[max_leading_zeros / 8] = + p_target[max_leading_zeros / 8] & (0xff >> (max_leading_zeros & 0x07)); + } + } while (!is_vector_in_range(p_target, p_min, p_max, size)); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_crypto_rng_vector_generate(uint8_t * const p_target, size_t size) +{ + ret_code_t ret_code; + + ret_code = generate(p_target, size, true); + + return ret_code; +} + + +ret_code_t nrf_crypto_rng_vector_generate_in_range(uint8_t * const p_target, + uint8_t const * const p_min, + uint8_t const * const p_max, + size_t size) +{ + ret_code_t ret_code; + + ret_code = generate_in_range(p_target, p_min, p_max, size, true); + + return ret_code; +} + + +ret_code_t nrf_crypto_rng_vector_generate_no_mutex(uint8_t * const p_target, size_t size) +{ + ret_code_t ret_code; + + ret_code = generate(p_target, size, false); + + return ret_code; +} + + +ret_code_t nrf_crypto_rng_vector_generate_in_range_no_mutex(uint8_t * const p_target, + uint8_t const * const p_min, + uint8_t const * const p_max, + size_t size) +{ + ret_code_t ret_code; + + ret_code = generate_in_range(p_target, p_min, p_max, size, false); + + return ret_code; +} + + +ret_code_t nrf_crypto_rng_init(nrf_crypto_rng_context_t * p_context, + nrf_crypto_rng_temp_buffer_t * p_temp_buffer) +{ + ret_code_t ret_code; + nrf_crypto_rng_temp_buffer_t * p_allocated_temp_buffer = NULL; + + // Check if the stack has overflowed. This can typically happen if the application has put the + // ~6 kB large temp buffer for CC310 on the stack. + if (nrf_stack_info_overflowed()) + { + NRF_LOG_ERROR("Stack overflow detected."); + return NRF_ERROR_CRYPTO_STACK_OVERFLOW; + } + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_RNG_AUTO_INIT) + VERIFY_TRUE(nrf_crypto_is_initializing(), NRF_ERROR_CRYPTO_NOT_INITIALIZED); +#else + VERIFY_TRUE(nrf_crypto_is_initialized(), NRF_ERROR_CRYPTO_NOT_INITIALIZED); +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_RNG_AUTO_INIT) + + // Do nothing if RNG module is already initialized. + if (mp_context != 0 && (m_initialized == NRF_CRYPTO_RNG_MODULE_INIT_MAGIC_VALUE)) + { + return NRF_SUCCESS; + } + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS) + + VERIFY_TRUE(p_context == NULL, NRF_ERROR_CRYPTO_INVALID_PARAM); + VERIFY_TRUE(p_temp_buffer == NULL, NRF_ERROR_CRYPTO_INVALID_PARAM); + + mp_context = &m_context; + p_temp_buffer = &m_temp_buffer; + +#else // !NRF_MODULE_ENABLED(NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS) + + if (p_context == NULL) + { + if (NRF_CRYPTO_ALLOC_ON_STACK) + { + NRF_LOG_ERROR("RNG context cannot be allocated on the stack."); + return NRF_ERROR_CRYPTO_ALLOC_FAILED; + } + else + { + mp_allocated_context = NRF_CRYPTO_ALLOC(sizeof(nrf_crypto_backend_rng_context_t)); + if (mp_allocated_context == NULL) + { + return NRF_ERROR_CRYPTO_ALLOC_FAILED; + } + mp_context = mp_allocated_context; + } + } + else + { + mp_context = p_context; + } + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS) + + // Allocate temporary buffer internally if not statically allocated or provided by the user. + if (p_temp_buffer == NULL) + { + p_allocated_temp_buffer = NRF_CRYPTO_ALLOC(sizeof(nrf_crypto_rng_temp_buffer_t)); + + if (p_allocated_temp_buffer == NULL) + { + if (mp_allocated_context != NULL) + { + NRF_CRYPTO_FREE(mp_allocated_context); + } + + return NRF_ERROR_CRYPTO_ALLOC_FAILED; + } + + p_temp_buffer = p_allocated_temp_buffer; + } + + ret_code = nrf_crypto_rng_backend_init(mp_context, p_temp_buffer); + if (ret_code == NRF_SUCCESS) + { + m_initialized = NRF_CRYPTO_RNG_MODULE_INIT_MAGIC_VALUE; + mp_context->header.init_value = NRF_CRYPTO_RNG_CONTEXT_INIT_MAGIC_VALUE; + } + + if (p_allocated_temp_buffer != NULL) + { + NRF_CRYPTO_FREE(p_allocated_temp_buffer); + } + + return ret_code; +} + + +ret_code_t nrf_crypto_rng_uninit(void) +{ + ret_code_t ret_code; + + VERIFY_TRUE(m_initialized == NRF_CRYPTO_RNG_MODULE_INIT_MAGIC_VALUE, + NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED); + + VERIFY_TRUE(mp_context->header.init_value == NRF_CRYPTO_RNG_CONTEXT_INIT_MAGIC_VALUE, + NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED); + + mp_context->header.init_value = 0; + m_initialized = 0; + + ret_code = nrf_crypto_rng_backend_uninit(mp_context); + + if (mp_allocated_context != NULL) + { + NRF_CRYPTO_FREE(mp_allocated_context); + } + + return ret_code; +} + + +ret_code_t nrf_crypto_rng_reseed(nrf_crypto_rng_temp_buffer_t * p_temp_buffer, + uint8_t * p_input_data, + size_t size) +{ + ret_code_t ret_code; + void * p_allocated_temp_buffer = NULL; + + // Check if the stack has overflowed. This can typically happen if the application has put the + // ~6 kB large temp buffer for CC310 on the stack. + if (nrf_stack_info_overflowed()) + { + NRF_LOG_ERROR("Stack overflow detected."); + return NRF_ERROR_CRYPTO_STACK_OVERFLOW; + } + + if (size > 0) + { + VERIFY_TRUE(p_input_data != NULL, NRF_ERROR_CRYPTO_INPUT_NULL); + } + + VERIFY_TRUE(m_initialized == NRF_CRYPTO_RNG_MODULE_INIT_MAGIC_VALUE, + NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED); + +#if NRF_MODULE_ENABLED(NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS) + + VERIFY_TRUE(p_temp_buffer == NULL, NRF_ERROR_CRYPTO_INVALID_PARAM); + p_temp_buffer = &m_temp_buffer; + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS) + + // Allocate temporary buffer internally if not statically allocated or provided by the user. + if (p_temp_buffer == NULL) + { + p_allocated_temp_buffer = NRF_CRYPTO_ALLOC(sizeof(nrf_crypto_rng_temp_buffer_t)); + if (p_allocated_temp_buffer == NULL) + { + return NRF_ERROR_CRYPTO_ALLOC_FAILED; + } + p_temp_buffer = (nrf_crypto_rng_temp_buffer_t *)p_allocated_temp_buffer; + } + + ret_code = nrf_crypto_rng_backend_reseed(mp_context, p_temp_buffer, p_input_data, size); + + if (p_allocated_temp_buffer != NULL) + { + NRF_CRYPTO_FREE(p_allocated_temp_buffer); + } + + return ret_code; +} + + +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) +#endif // NRF_MODULE_ENABLED(NRF_CRYPTO) diff --git a/components/libraries/crypto/nrf_crypto_rng.h b/components/libraries/crypto/nrf_crypto_rng.h new file mode 100644 index 0000000..e795506 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_rng.h @@ -0,0 +1,285 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_RNG_H__ +#define NRF_CRYPTO_RNG_H__ + +/** @file + * + * @defgroup nrf_crypto_rng RNG related functions + * @{ + * @ingroup nrf_crypto + * + * @brief RNG related functions + * + * @details There are two available RNG backends: + * - ARM CryptoCell CC310 (default for devices with CC310). + * - nRF HW RNG peripheral. + * * CTR-DRBG mode - nRF HW RNG used for seeding mbed TLS CTR-DRBG (default for + * devices without CC310). + * * Raw mode - all data is generated by the nRF HW RNG. + * + * The CC310 backend meets the standards NIST 800-90B3 and AIS-31 (Class “P2 High”), and + * should be preferred in most cases on devices that includes the CC310 core. Devices that + * do not include CC310 should normally use the nRF HW RNG with mbed TLS CTR-DRBG. The + * mbed TLS CTR-DRBG code is standardized by NIST (SP 800-90A Rev. 1). + */ + +#include "sdk_common.h" +#include "nrf_crypto_error.h" +#include "nrf_crypto_rng_shared.h" +#include "nrf_crypto_rng_backend.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Context type for RNG. + * + * @note The actual type depend on the backend in use. + */ +typedef nrf_crypto_backend_rng_context_t nrf_crypto_rng_context_t; + + +/** + * @brief Temporary work buffer type for RNG. + * + * @details Only needed during initializing. Can be freed when @ref nrf_crypto_rng_init has + * returned. Not needed if @ref NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS_ENABLED is enabled + * in @ref sdk_config. + * + * @note The actual type depend on the backend in use. + */ +typedef nrf_crypto_backend_rng_temp_buffer_t nrf_crypto_rng_temp_buffer_t; + + +/**@brief Initialize the random number generator. + * + * @details This function has no effect when @ref NRF_CRYPTO_RNG_AUTO_INIT_ENABLED is enabled. + * + * @warning The p_temp_buffer is 6112 bytes when using the CC310 backend. Ensure that stack size + * is sufficient if allocated on stack. Applications that use nRF HW RNG as backend or are + * not RAM constrained can use internal static allocation of context and temporary buffers + * (@ref NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS_ENABLED). + * + * @note The context object can be reused without the need for a full reinitialization of the + * backend in case of for example wakeup from system OFF, provided that the context is + * located in a memory block that is retained. This only apply to the CC310 backend, and when + * the context is allocated manually (NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS_ENABLED disabled). + * + * @param[in] p_context Pointer to context memory. The context will be managed + * internally, and the pointer is not used for subsequent calls to + * the nrf_crypto_rng API. The context memory is needed until + * @ref nrf_crypto_rng_uninit is called, so it should normally not + * be on the stack. Use NULL if + * @ref NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS_ENABLED is enabled + * in @ref sdk_config (recommended for most applications). + * + * @param[in,out] p_temp_buffer Temporary buffer needed during initialization of the backend. It + * is not used after the return of this function, and can be freed + * at that point. Buffer is allocated internally if the pointer is + * NULL, using the allocated defined by @ref NRF_CRYPTO_ALLOCATOR + * in @c sdk_config.h. Use NULL if + * @ref NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS_ENABLED is enabled + * in @ref sdk_config (recommended for most applications). + * + * @retval NRF_SUCCESS If random number generator was initialized + * successfully. + * @retval NRF_ERROR_CRYPTO_NOT_INITIALIZED @ref nrf_crypto_init was not called prior to this + * function. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NULL p_context was NULL. + * @retval NRF_ERROR_CRYPTO_INTERNAL If an internal error occurred in the nrf_crypto + * backend. + * @retval NRF_ERROR_CRYPTO_ALLOC_FAILED Unable to allocate memory for the context or work + * buffer. + * @retval NRF_ERROR_CRYPTO_STACK_OVERFLOW Stack overflow detected. Typically caused by + * allocating an instance of + * @ref nrf_crypto_rng_temp_buffer_t + * on the stack when using CC310 backend. + * @retval NRF_ERROR_CRYPTO_BUSY RNG is busy. Rerun at a later time. + */ +ret_code_t nrf_crypto_rng_init(nrf_crypto_rng_context_t * p_context, + nrf_crypto_rng_temp_buffer_t * p_temp_buffer); + + +/**@brief Uninitialize the random number generator. + * + * @retval NRF_SUCCESS If RNG was uninitialized successfully. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED RNG has not been initialized. + * @retval NRF_ERROR_CRYPTO_INTERNAL If an internal error occurred in the + * nrf_crypto backend. + * @retval NRF_ERROR_CRYPTO_BUSY RNG is busy. Rerun at a later time. + */ +ret_code_t nrf_crypto_rng_uninit(void); + + +/**@brief Generate random data of given size. + * + * @details @ref nrf_crypto_rng_init must be called prior to this function unless + * @ref NRF_CRYPTO_RNG_AUTO_INIT_ENABLED is enabled in @ref sdk_config. + * + * @param[in,out] p_target Buffer to hold the random generated data. + * This buffer must be at least as large as the size parameter. + * @param[in] size Length (in bytes) to generate random data for. + * + * @retval NRF_SUCCESS Data was generated successfully. + * @retval NRF_ERROR_CRYPTO_NOT_INITIALIZED @ref nrf_crypto_init was not called prior to + * this function. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED @ref nrf_crypto_rng_init was not called + * prior to this function and + * @ref NRF_CRYPTO_RNG_AUTO_INIT_ENABLED is + * disabled. + * @retval NRF_ERROR_CRYPTO_OUTPUT_NULL p_target was NULL. + * @retval NRF_ERROR_CRYPTO_OUTPUT_LENGTH Size was 0 or larger than the backend + * supports. + * @retval NRF_ERROR_CRYPTO_INTERNAL If an internal error occurred in the + * backend. + * @retval NRF_ERROR_CRYPTO_STACK_OVERFLOW Stack overflow detected in + * @ref nrf_crypto_rng_init when using auto + * initialization. Typically caused by + * allocating an instance of + * @ref nrf_crypto_rng_temp_buffer_t + * on the stack when using CC310 backend. + * @retval NRF_ERROR_CRYPTO_BUSY RNG is busy. Rerun at a later time. + */ +ret_code_t nrf_crypto_rng_vector_generate(uint8_t * const p_target, size_t size); + + +/**@brief Generate a vector of constrained random data of given size, between the specified min + * and max values. + * + * @details @ref nrf_crypto_rng_init must be called prior to this function unless + * @ref NRF_CRYPTO_RNG_AUTO_INIT_ENABLED is enabled in @ref sdk_config. + * + * All vectors are in big-endian format, with the most significant byte as the first + * element / lowest address. + * + * @note This function may execute for a long time if the window between p_min and p_max is small. + * + * @param[in,out] p_target Buffer to hold the random generated data. + * This buffer must be at least as large as the size parameter. + * @param[in] p_min Byte array defining the lower limit of the random vector. + * @param[in] p_max Byte array defining the upper limit of the random vector. + * @param[in] size Length (in bytes) to generate random data for. Note that all three + * buffers (p_target, p_min and p_max) must be of this size. + * + * @retval NRF_SUCCESS Data was generated successfully. + * @retval NRF_ERROR_CRYPTO_NOT_INITIALIZED @ref nrf_crypto_init was not called prior to + * this function. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED @ref nrf_crypto_rng_init was not called + * prior to this function and + * @ref NRF_CRYPTO_RNG_AUTO_INIT_ENABLED is + * disabled. + * @retval NRF_ERROR_CRYPTO_OUTPUT_NULL p_target was NULL. + * @retval NRF_ERROR_CRYPTO_INPUT_NULL p_min or p_max was NULL. + * @retval NRF_ERROR_CRYPTO_OUTPUT_LENGTH Size was 0 or larger than the backend + * supports. + * @retval NRF_ERROR_CRYPTO_INTERNAL If an internal error occurred in the + * backend. + * @retval NRF_ERROR_CRYPTO_STACK_OVERFLOW Stack overflow detected in + * @ref nrf_crypto_rng_init when using auto + * initialization. Typically caused by + * allocating an instance of + * @ref nrf_crypto_rng_temp_buffer_t + * on the stack when using CC310 backend. + * @retval NRF_ERROR_CRYPTO_BUSY RNG is busy. Rerun at a later time. + */ +ret_code_t nrf_crypto_rng_vector_generate_in_range(uint8_t * const p_target, + uint8_t const * const p_min, + uint8_t const * const p_max, + size_t size); + + +/** + * @brief This function is used for reseeding the RNG with additional entropy. + * + * @details The backends will reseed automatically when required. This function can be used to + * reseed at specific times and to provide additional data that is used to add personalized + * randomness. + * + * @note Reseeding is not supported if using the nRF HW RNG backend without mbed TLS CTR-DRBG + * (NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG_ENABLED disabled in sdk_config.h). + * + * @warning The p_temp_buffer is 6112 bytes when the CC310 backend is used. Ensure that stack size + * is sufficient if allocated on stack. + * + * @param[in,out] p_temp_buffer Temporary buffer needed during reseeding. It + * is not used after the return of this function, and can be freed + * at that point. Buffer is allocated internally if the pointer is + * NULL, using the allocated defined by @ref NRF_CRYPTO_ALLOCATOR + * in @c sdk_config.h. Use NULL if + * @ref NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS_ENABLED is enabled + * in @ref sdk_config (recommended for most applications). + * @param[in] p_input_data Optional input data used to increase the entropy. + * @param[in] size Length of input data. Must be 0, 4, 8 or 12 for CC310. + * + * @retval NRF_SUCCESS Data was generated successfully. + * @retval NRF_ERROR_CRYPTO_NOT_INITIALIZED @ref nrf_crypto_init was not called prior to + * this function. + * @retval NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED @ref nrf_crypto_rng_init was not called + * prior to this function and + * @ref NRF_CRYPTO_RNG_AUTO_INIT_ENABLED is + * disabled. + * @retval NRF_ERROR_CRYPTO_INPUT_NULL p_temp_buffer was NULL or p_input_data was + * NULL and size > 0 . + * @retval NRF_ERROR_CRYPTO_INPUT_LENGTH Invalid input data size. + * @retval NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE Reseeding not supported by backend. + * @retval NRF_ERROR_CRYPTO_INTERNAL If an internal error occurred in the + * backend. + * @retval NRF_ERROR_CRYPTO_STACK_OVERFLOW Stack overflow detected. Typically caused by + * allocating an instance of + * @ref nrf_crypto_rng_temp_buffer_t + * on the stack when using CC310 backend. + * @retval NRF_ERROR_CRYPTO_BUSY RNG is busy. Rerun at a later time. + */ +ret_code_t nrf_crypto_rng_reseed(nrf_crypto_rng_temp_buffer_t * p_temp_buffer, + uint8_t * p_input_data, + size_t size); + + +#ifdef __cplusplus +} +#endif + +/**@} */ + +#endif // NRF_CRYPTO_RNG_H__ diff --git a/components/libraries/crypto/nrf_crypto_rng_backend.h b/components/libraries/crypto/nrf_crypto_rng_backend.h new file mode 100644 index 0000000..34c389a --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_rng_backend.h @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_RNG_BACKEND_H__ +#define NRF_CRYPTO_RNG_BACKEND_H__ + +/** @file + * + * @defgroup nrf_crypto_rng_backend Meta RNG backend. + * @{ + * @ingroup nrf_crypto_rng + * + * @brief Includes all backends definitions. + * + * @details This file includes all backend definitions. + */ + +#include "cc310_backend_rng.h" +#include "nrf_hw_backend_rng.h" +#include "nrf_hw_backend_rng_mbedtls.h" +#include "optiga_backend_rng.h" + +#if !NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) + +#ifdef __cplusplus +extern "C" { +#endif + +/** @internal @brief Fallback dummy context type in case no backend is selected */ +typedef nrf_crypto_rng_internal_context_t nrf_crypto_backend_rng_context_t; + +/** @internal @brief Fallback dummy temp buffer type in case no backend is selected . */ +typedef struct +{ + uint32_t reserved; +} nrf_crypto_backend_rng_temp_buffer_t; + +#ifdef __cplusplus +} +#endif + +#endif // !NRF_MODULE_ENABLED(NRF_CRYPTO_RNG) + +/**@} */ + +#endif // NRF_CRYPTO_RNG_BACKEND_H__ diff --git a/components/libraries/crypto/nrf_crypto_rng_shared.h b/components/libraries/crypto/nrf_crypto_rng_shared.h new file mode 100644 index 0000000..9a1d5e7 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_rng_shared.h @@ -0,0 +1,142 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_RNG_SHARED_H__ +#define NRF_CRYPTO_RNG_SHARED_H__ + +/** @file + * + * @defgroup nrf_crypto_rng_shared Types shared between all @ref nrf_crypto_rng backends. + * @{ + * @ingroup nrf_crypto_rng + * + * @brief Types shared between all @ref nrf_crypto_rng backends. + * + * @details These types should not be used directly by the application. + */ + +#include "sdk_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define NRF_CRYPTO_RNG_CONTEXT_INIT_MAGIC_VALUE (0x4d616961) + + +/** + * @internal @brief Common header for each RNG backend context. + * + * @details This is an internal type that should not be used directly. + */ +typedef struct +{ + uint32_t init_value; //!< Contains NRF_CRYPTO_RNG_CONTEXT_INIT_MAGIC_VALUE if initialized. +} nrf_crypto_rng_internal_context_t; + + +/** + * @internal @brief Function for initializing the RNG backend. + * + * @note The backend function should never be called directly. + * Use @ref nrf_crypto_rng_init instead. + * + * @param[in,out] p_context Pointer to context structure. + * @param[in,out] p_temp_buffer Temporary buffer needed during initialization of the backend. + * @param[in] use_mutex Use mutex to prevent simultanious usage of backend resources. + */ +ret_code_t nrf_crypto_rng_backend_init(void * const p_context, + void * const p_temp_buffer); + + +/** + * @internal @brief Function for uninitializing the RNG backend. + * + * @note The backend function should never be called directly. + * Use @ref nrf_crypto_rng_uninit instead. + * + * @param[in,out] p_context Pointer to context structure. + * @param[in] use_mutex Use mutex to prevent simultanious usage of backend resources. + */ +ret_code_t nrf_crypto_rng_backend_uninit(void * const p_context); + + +/** + * @internal @brief Function for retrieving a random vector from the RNG backend. + * + * @note The backend function should never be called directly. + * Use @ref nrf_crypto_rng_vector_generate instead. + * + * @param[in,out] p_context Pointer to context structure. + * @param[out] p_target Buffer to hold the random generated data. + * @param[in] size Length (in bytes) to generate random data for. + * @param[in] use_mutex Use mutex to prevent simultanious usage of backend resources. + */ +ret_code_t nrf_crypto_rng_backend_vector_generate(void * const p_context, + uint8_t * const p_target, + size_t size, + bool use_mutex); + + +/** + * @internal @brief This function is used for reseeding the RNG with additional entropy. + * + * @note The backend function should never be called directly. + * Use @ref nrf_crypto_rng_reseed instead. + * + * @param[in,out] p_context Pointer to context structure. + * @param[in,out] p_temp_buffer Temporary buffer needed during initialization of the backend. + * @param[in] p_input_data Input data used to increase the entropy. + * @param[in] size Length of input data. + */ +ret_code_t nrf_crypto_rng_backend_reseed(void * const p_context, + void * p_temp_buffer, + uint8_t * p_input_data, + size_t size); + + +#ifdef __cplusplus +} +#endif + +/**@} */ + +#endif // NRF_CRYPTO_RNG_SHARED_H__ diff --git a/components/libraries/crypto/nrf_crypto_shared.c b/components/libraries/crypto/nrf_crypto_shared.c new file mode 100644 index 0000000..db5dc48 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_shared.c @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_config.h" +#include "nordic_common.h" +#include "nrf_crypto_shared.h" + + +#if NRF_MODULE_ENABLED(NRF_CRYPTO) + + +void nrf_crypto_internal_swap_endian_in_place(uint8_t * p_buffer, size_t size) +{ + ASSERT(p_buffer != NULL); + + uint8_t temp; + uint8_t * p_first = p_buffer; + uint8_t * p_last = p_buffer + size - 1; + while (p_last >= p_first) + { + temp = *p_first; + *p_first = *p_last; + *p_last = temp; + p_first++; + p_last--; + } +} + + +void nrf_crypto_internal_swap_endian(uint8_t * p_out, uint8_t const * p_in, size_t size) +{ + ASSERT(p_out != NULL); + ASSERT(p_in != NULL); + + uint8_t const * p_first = p_in; + uint8_t * p_last = p_out + size - 1; + while (p_last >= p_out) + { + *p_last = *p_first; + p_first++; + p_last--; + } +} + + +void nrf_crypto_internal_double_swap_endian(uint8_t * p_out, uint8_t const * p_in, size_t part_size) +{ + nrf_crypto_internal_swap_endian(p_out, p_in, part_size); + nrf_crypto_internal_swap_endian(&p_out[part_size], &p_in[part_size], part_size); +} + + +void nrf_crypto_internal_double_swap_endian_in_place(uint8_t * p_buffer, size_t part_size) +{ + nrf_crypto_internal_swap_endian_in_place(p_buffer, part_size); + nrf_crypto_internal_swap_endian_in_place(&p_buffer[part_size], part_size); +} + + +#endif diff --git a/components/libraries/crypto/nrf_crypto_shared.h b/components/libraries/crypto/nrf_crypto_shared.h new file mode 100644 index 0000000..e069432 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_shared.h @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_SHARED_H__ +#define NRF_CRYPTO_SHARED_H__ + +/** @internal @file + * + * @defgroup nrf_crypto_shared Shared macros for nrf_crypto + * @{ + * @ingroup nrf_crypto + * + * @brief Module containing shared macros for nrf_crypto. + */ + +#include "sdk_macros.h" +#include "nrf_crypto_mem.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @internal @brief Macro for verifying statement to be true. It will cause the exterior function + * to return err_code if the statement is not true, but only after freeing the + * memory pointed to by p_memory if p_memory is not NULL. + * + * @param[in] statement Statement to test. + * @param[in] err_code Error value to return if test was invalid. + * @param[in] p_memory The memory block to be freed in case of error. + * + * @retval nothing, but will cause the exterior function to return @p err_code if @p statement + * is false. + */ +#define NRF_CRYPTO_VERIFY_TRUE_DEALLOCATE(statement, err_code, p_memory) \ +do \ +{ \ + if (!(statement)) \ + { \ + if (p_memory != NULL) \ + { \ + NRF_CRYPTO_FREE(p_memory); \ + } \ + return err_code; \ + } \ +} while (0) + + +/** + * @internal @brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the + * exterior function to return err_code if the err_code is not @ref NRF_SUCCESS, + * but only after freeing the memory pointed to by p_memory if p_memory is not + * NULL. + * + * @param[in] err_code The error code to check. + * @param[in] p_memory The memory block to be freed in case of error. + */ +#ifdef DISABLE_PARAM_CHECK +#define NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE() +#else +#define NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(err_code, p_memory) \ + NRF_CRYPTO_VERIFY_TRUE_DEALLOCATE((err_code) == NRF_SUCCESS, (err_code), p_memory) +#endif /* DISABLE_PARAM_CHECK */ + + +/** + * @internal @brief Generate a vector with random data of given size. + * + * @details This function does not check or lock the CC310 mutex, and should only be used + * + * @note Only for internal use in nrf_crypto. + * + * @param[in,out] p_target Buffer to hold the random generated data. + * This buffer must be at least as large as the size parameter. + * @param[in] size Length (in bytes) to generate random data for. + * + * @retval See return values for @ref nrf_crypto_rng_vector_generate. + */ +ret_code_t nrf_crypto_rng_vector_generate_no_mutex(uint8_t * const p_target, size_t size); + + +/** + * @internal @brief Generate a vector of constrained random data of given size, between the + * specified min and max values. + * + * @details This function does not check or lock the CC310 mutex, and should only be used + * + * @note Only for internal use in nrf_crypto. + * + * @param[in,out] p_target Buffer to hold the random generated data. + * This buffer must be at least as large as the size parameter. + * @param[in] p_min Byte array defining the lower limit of the random vector. + * @param[in] p_max Byte array defining the upper limit of the random vector. + * @param[in] size Length (in bytes) to generate random data for. Note that all three + * buffers (p_target, p_min and p_max) must be of this size. + * + * @retval See return values for @ref nrf_crypto_rng_vector_generate_in_range. + */ +ret_code_t nrf_crypto_rng_vector_generate_in_range_no_mutex(uint8_t * const p_target, + uint8_t const * const p_min, + uint8_t const * const p_max, + size_t size); + + +/** @internal @brief Swap bytes order inside provided buffer (in place). + * + * @note Only for internal use in nrf_crypto. + * + * @param[in,out] p_buffer Buffer with data to swap. + * @param[in] size Number of bytes in @p p_buffer. + */ +void nrf_crypto_internal_swap_endian_in_place(uint8_t * p_buffer, size_t size); + + +/** @internal @brief Copy from one buffer to another and swap byte order. + * + * @note Only for internal use in nrf_crypto. + * + * @param[out] p_out Buffer with source data. + * @param[in] p_in Destination buffer with swapped bytes. + * @param[in] size Number of bytes in @p p_out and @p p_in. + */ +void nrf_crypto_internal_swap_endian(uint8_t * p_out, uint8_t const * p_in, size_t size); + + +/** @internal @brief Swap bytes order inside buffer containing two integers (in place). + * + * @note Only for internal use in nrf_crypto. + * + * @param[in,out] p_buffer Buffer with data to swap. + * @param[in] part_size Number of bytes in single integer which is half of size of @p p_buffer. + */ +void nrf_crypto_internal_double_swap_endian_in_place(uint8_t * p_buffer, size_t part_size); + + +/** @internal @brief Copy from one buffer containing two integers to another and swap byte order of each integer. + * + * @note Only for internal use in nrf_crypto. + * + * @param[out] p_out Buffer with source data. + * @param[in] p_in Destination buffer with swapped bytes. + * @param[in] part_size Number of bytes in single integer which is half of size of @p p_out and @p p_in. + */ +void nrf_crypto_internal_double_swap_endian(uint8_t * p_out, uint8_t const * p_in, size_t part_size); + + +#ifdef __cplusplus +} +#endif + +/**@} */ + +#endif // NRF_CRYPTO_SHARED_H__ diff --git a/components/libraries/crypto/nrf_crypto_types.h b/components/libraries/crypto/nrf_crypto_types.h new file mode 100644 index 0000000..5482816 --- /dev/null +++ b/components/libraries/crypto/nrf_crypto_types.h @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_CRYPTO_TYPES_H__ +#define NRF_CRYPTO_TYPES_H__ + +/** @file + * + * @defgroup nrf_crypto_types Commonly shared types + * @{ + * @ingroup nrf_crypto + * + * @brief Provides definitions of commonly shared cryptographic types like hashes and curves used in the nrf_crypto APIs. + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Hashing algorithms that are available through nrf_crypto. + * + * @note All cryptographic hash types may not be available through the nrf_crypto backend. + */ +typedef enum +{ + NRF_CRYPTO_HASH_TYPE_INVALID = 0x00, //!< Invalid hashing algorithm. + NRF_CRYPTO_HASH_TYPE_MD5 = 0x01, //!< MD5. + NRF_CRYPTO_HASH_TYPE_SHA1 = 0x03, //!< SHA-1. + NRF_CRYPTO_HASH_TYPE_SHA224 = 0x04, //!< SHA-224 (SHA-2). + NRF_CRYPTO_HASH_TYPE_SHA256 = 0x05, //!< SHA-256 (SHA-2). + NRF_CRYPTO_HASH_TYPE_SHA384 = 0x06, //!< SHA-384 (SHA-2). + NRF_CRYPTO_HASH_TYPE_SHA512 = 0x07, //!< SHA-512 (SHA-2). + +} nrf_hash_type_t; + +/**@defgroup NRF_CRYPTO_HASH_SIZES Cryptographic hash sizes + * @brief Sizes of different cryptographic hashes. + * @{ */ +#define NRF_CRYPTO_HASH_SIZE_MD5 (20) +#define NRF_CRYPTO_HASH_SIZE_SHA1 (20) +#define NRF_CRYPTO_HASH_SIZE_SHA224 (28) +#define NRF_CRYPTO_HASH_SIZE_SHA256 (32) +#define NRF_CRYPTO_HASH_SIZE_SHA384 (48) +#define NRF_CRYPTO_HASH_SIZE_SHA512 (64) +/** @} */ + + +/**@brief Type definition for key size. + */ +typedef enum +{ + NRF_CRYPTO_KEY_SIZE_128 = 128, + NRF_CRYPTO_KEY_SIZE_192 = 192, + NRF_CRYPTO_KEY_SIZE_256 = 256 +} nrf_crypto_key_size_id_t; + +/**@brief Type specifying whether decrypt or encrypt operation shall be performed. + */ +typedef enum +{ + NRF_CRYPTO_DECRYPT = 0, + NRF_CRYPTO_ENCRYPT = 1, + NRF_CRYPTO_MAC_CALCULATE = 2 +} nrf_crypto_operation_t; + +#define NRF_CRYPTO_AES_BLOCK_SIZE (16u) // 16 bytes + +#ifdef __cplusplus +} +#endif + +/**@} */ + +#endif // #ifndef NRF_CRYPTO_TYPES_H__ diff --git a/components/libraries/delay/nrf_delay.h b/components/libraries/delay/nrf_delay.h new file mode 100644 index 0000000..4e5931b --- /dev/null +++ b/components/libraries/delay/nrf_delay.h @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2011 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _NRF_DELAY_H +#define _NRF_DELAY_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for delaying execution for a number of microseconds. + * + * @param us_time Number of microseconds to wait. + */ +#define nrf_delay_us(us_time) NRFX_DELAY_US(us_time) + + +/** + * @brief Function for delaying execution for a number of milliseconds. + * + * @param ms_time Number of milliseconds to wait. + */ + +__STATIC_INLINE void nrf_delay_ms(uint32_t ms_time) +{ + if (ms_time == 0) + { + return; + } + + do { + nrf_delay_us(1000); + } while (--ms_time); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/libraries/experimental_section_vars/nrf_section.h b/components/libraries/experimental_section_vars/nrf_section.h new file mode 100644 index 0000000..1549930 --- /dev/null +++ b/components/libraries/experimental_section_vars/nrf_section.h @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_SECTION_H__ +#define NRF_SECTION_H__ + +#include "nordic_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup section_vars Section variables + * @ingroup app_common + * @{ + * + * @brief Section variables. + */ + +//lint -save -e27 -esym(526,*) + +#if defined(__ICCARM__) +// Enable IAR language extensions +#pragma language=extended +#endif + +/**@brief Macro for obtaining the address of the beginning of a section. + * + * param[in] section_name Name of the section. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_START_ADDR(section_name) &CONCAT_2(section_name, $$Base) + +#elif defined(__GNUC__) +#define NRF_SECTION_START_ADDR(section_name) &CONCAT_2(__start_, section_name) + +#elif defined(__ICCARM__) +#define NRF_SECTION_START_ADDR(section_name) __section_begin(STRINGIFY(section_name)) +#endif + + +/**@brief Macro for obtaining the address of the end of a section. + * + * @param[in] section_name Name of the section. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_END_ADDR(section_name) &CONCAT_2(section_name, $$Limit) + +#elif defined(__GNUC__) +#define NRF_SECTION_END_ADDR(section_name) &CONCAT_2(__stop_, section_name) + +#elif defined(__ICCARM__) +#define NRF_SECTION_END_ADDR(section_name) __section_end(STRINGIFY(section_name)) +#endif + + +/**@brief Macro for retrieving the length of a given section, in bytes. + * + * @param[in] section_name Name of the section. + * @hideinitializer + */ +#define NRF_SECTION_LENGTH(section_name) \ + ((size_t)NRF_SECTION_END_ADDR(section_name) - \ + (size_t)NRF_SECTION_START_ADDR(section_name)) + + +/**@brief Macro for creating a section. + * + * @param[in] section_name Name of the section. + * @param[in] data_type Data type of the variables to be registered in the section. + * + * @warning Data type must be word aligned to prevent padding. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_DEF(section_name, data_type) \ + extern data_type * CONCAT_2(section_name, $$Base); \ + extern void * CONCAT_2(section_name, $$Limit) + +#elif defined(__GNUC__) +#define NRF_SECTION_DEF(section_name, data_type) \ + extern data_type * CONCAT_2(__start_, section_name); \ + extern void * CONCAT_2(__stop_, section_name) + +#elif defined(__ICCARM__) +#define NRF_SECTION_DEF(section_name, data_type) \ + _Pragma(STRINGIFY(section = STRINGIFY(section_name))); + +#endif + + +/**@brief Macro for declaring a variable and registering it in a section. + * + * @details Declares a variable and registers it in a named section. This macro ensures that the + * variable is not stripped away when using optimizations. + * + * @note The order in which variables are placed in a section is dependent on the order in + * which the linker script encounters the variables during linking. + * + * @param[in] section_name Name of the section. + * @param[in] section_var Variable to register in the given section. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \ + section_var __attribute__ ((section(STRINGIFY(section_name)))) __attribute__((used)) + +#elif defined(__GNUC__) +#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \ + section_var __attribute__ ((section("." STRINGIFY(section_name)))) __attribute__((used)) + +#elif defined(__ICCARM__) +#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \ + __root section_var @ STRINGIFY(section_name) +#endif + + +/**@brief Macro for retrieving a variable from a section. + * + * @warning The stored symbol can only be resolved using this macro if the + * type of the data is word aligned. The operation of acquiring + * the stored symbol relies on the size of the stored type. No + * padding can exist in the named section in between individual + * stored items or this macro will fail. + * + * @param[in] section_name Name of the section. + * @param[in] data_type Data type of the variable. + * @param[in] i Index of the variable in section. + * @hideinitializer + */ +#define NRF_SECTION_ITEM_GET(section_name, data_type, i) \ + ((data_type*)NRF_SECTION_START_ADDR(section_name) + (i)) + + +/**@brief Macro for getting the number of variables in a section. + * + * @param[in] section_name Name of the section. + * @param[in] data_type Data type of the variables in the section. + * @hideinitializer + */ +#define NRF_SECTION_ITEM_COUNT(section_name, data_type) \ + NRF_SECTION_LENGTH(section_name) / sizeof(data_type) + +/** @} */ + +//lint -restore + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SECTION_H__ diff --git a/components/libraries/experimental_section_vars/nrf_section_iter.c b/components/libraries/experimental_section_vars/nrf_section_iter.c new file mode 100644 index 0000000..39e93a7 --- /dev/null +++ b/components/libraries/experimental_section_vars/nrf_section_iter.c @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_SECTION_ITER) + +#include "nrf_section_iter.h" + + +#if !defined(__GNUC__) +static void nrf_section_iter_item_set(nrf_section_iter_t * p_iter) +{ + ASSERT(p_iter != NULL); + ASSERT(p_iter->p_set != NULL); + ASSERT(p_iter->p_section != NULL); + + while (true) + { + if (p_iter->p_section == p_iter->p_set->p_last) + { + // End of the section set. + p_iter->p_item = NULL; + return; + } + + if (p_iter->p_section->p_start != p_iter->p_section->p_end) + { + // Not empty section. + p_iter->p_item = p_iter->p_section->p_start; + return; + } + + // Next section. + p_iter->p_section++; + } +} +#endif + + +void nrf_section_iter_init(nrf_section_iter_t * p_iter, nrf_section_set_t const * p_set) +{ + ASSERT(p_iter != NULL); + ASSERT(p_set != NULL); + + p_iter->p_set = p_set; + +#if defined(__GNUC__) + p_iter->p_item = p_iter->p_set->section.p_start; + if (p_iter->p_item == p_iter->p_set->section.p_end) + { + p_iter->p_item = NULL; + } +#else + p_iter->p_section = p_set->p_first; + nrf_section_iter_item_set(p_iter); +#endif +} + +void nrf_section_iter_next(nrf_section_iter_t * p_iter) +{ + ASSERT(p_iter != NULL); + ASSERT(p_iter->p_set != NULL); + + if (p_iter->p_item == NULL) + { + return; + } + + p_iter->p_item = (void *)((size_t)(p_iter->p_item) + p_iter->p_set->item_size); + +#if defined(__GNUC__) + if (p_iter->p_item == p_iter->p_set->section.p_end) + { + p_iter->p_item = NULL; + } +#else + ASSERT(p_iter->p_section != NULL); + // End of current section reached? + if (p_iter->p_item == p_iter->p_section->p_end) + { + p_iter->p_section++; + nrf_section_iter_item_set(p_iter); + } +#endif +} + +#endif // NRF_MODULE_ENABLED(NRF_SECTION_ITER) diff --git a/components/libraries/experimental_section_vars/nrf_section_iter.h b/components/libraries/experimental_section_vars/nrf_section_iter.h new file mode 100644 index 0000000..aa5651b --- /dev/null +++ b/components/libraries/experimental_section_vars/nrf_section_iter.h @@ -0,0 +1,206 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_SECTION_ITER_H__ +#define NRF_SECTION_ITER_H__ + +#include +#include "nrf_section.h" +#include "nrf_assert.h" +#include "app_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @defgroup nrf_section_iter Section variables iterator + * @ingroup app_common + * @{ + */ + +/**@brief Single section description structure. */ +typedef struct +{ + void * p_start; //!< Pointer to the start of section. + void * p_end; //!< Pointer to the end of section. +} nrf_section_t; + + +/**@brief Set of the sections description structure. */ +typedef struct +{ +#if defined(__GNUC__) + nrf_section_t section; //!< Description of the set of sections. + /**< + * In case of GCC all sections in the set are sorted and + * placed in contiguous area, because they are treated as + * one section. + */ +#else + nrf_section_t const * p_first; //!< Pointer to the first section in the set. + nrf_section_t const * p_last; //!< Pointer to the last section in the set. +#endif + size_t item_size; //!< Size of the single item in the section. +} nrf_section_set_t; + + +/**@brief Section iterator structure. */ +typedef struct +{ + nrf_section_set_t const * p_set; //!< Pointer to the appropriate section set. +#if !defined(__GNUC__) + nrf_section_t const * p_section; //!< Pointer to the selected section. + /**< + * In case of GCC all sections in the set are sorted and + * placed in contiguous area, because they are treated + * as one section. + */ +#endif + void * p_item; //!< Pointer to the selected item in the section. +} nrf_section_iter_t; + + +/**@brief Create a set of sections. + * + * @note This macro reserves memory for the given set of sections. + * + * @details A set of sections, is an ordered collections of sections. + * + * @param[in] _name Name of the set. + * @param[in] _type Type of the elements stored in the sections. + * @param[in] _count Number of the sections in the set. This parameter is ignored in case of GCC. + * @hideinitializer + */ +#if defined(__GNUC__) + +#define NRF_SECTION_SET_DEF(_name, _type, _count) \ + \ + NRF_SECTION_DEF(_name, _type); \ + static nrf_section_set_t const _name = \ + { \ + .section = \ + { \ + .p_start = NRF_SECTION_START_ADDR(_name), \ + .p_end = NRF_SECTION_END_ADDR(_name), \ + }, \ + .item_size = sizeof(_type), \ + } + +#else + +#define NRF_SECTION_SET_DEF(_name, _type, _count) \ +/*lint -save -emacro(14, MACRO_REPEAT_FOR*) */ \ +MACRO_REPEAT_FOR(_count, NRF_SECTION_DEF_, _name, _type) \ +static nrf_section_t const CONCAT_2(_name, _array)[] = \ +{ \ + MACRO_REPEAT_FOR(_count, NRF_SECTION_SET_DEF_, _name) \ +}; \ +/*lint -restore */ \ +static nrf_section_set_t const _name = \ +{ \ + .p_first = CONCAT_2(_name, _array), \ + .p_last = CONCAT_2(_name, _array) + ARRAY_SIZE(CONCAT_2(_name, _array)), \ + .item_size = sizeof(_type), \ +} + +#ifndef DOXYGEN +#define NRF_SECTION_DEF_(_priority, _name, _type) \ +NRF_SECTION_DEF(CONCAT_2(_name, _priority), _type); + +#define NRF_SECTION_SET_DEF_(_priority, _name) \ +{ \ + .p_start = NRF_SECTION_START_ADDR(CONCAT_2(_name, _priority)), \ + .p_end = NRF_SECTION_END_ADDR(CONCAT_2(_name, _priority)), \ +}, +#endif // DOXYGEN +#endif // __GNUC__ + + +/**@brief Macro to declare a variable and register it in the section set. + * + * @note The order of the section in the set is based on the priority. The order with which + * variables are placed in a section is dependant on the order with which the linker + * encouters the variables during linking. + * + * @param[in] _name Name of the section set. + * @param[in] _priority Priority of the desired section. + * @param[in] _var The variable to register in the given section. + * @hideinitializer + */ +#define NRF_SECTION_SET_ITEM_REGISTER(_name, _priority, _var) \ + NRF_SECTION_ITEM_REGISTER(CONCAT_2(_name, _priority), _var) + + +/**@brief Function for initializing the section set iterator. + * + * @param[in] p_iter Pointer to the iterator. + * @param[in] p_set Pointer to the sections set. + */ +void nrf_section_iter_init(nrf_section_iter_t * p_iter, nrf_section_set_t const * p_set); + + +/**@brief Function for incrementing iterator. + * + * @param[in] p_iter Pointer to the iterator. + */ +void nrf_section_iter_next(nrf_section_iter_t * p_iter); + + +/**@brief Function for getting the element pointed to by the iterator. + * + * @param[in] p_iter Pointer to the iterator. + * + * @retval Pointer to the element or NULL if iterator points end of the set. + */ +static inline void * nrf_section_iter_get(nrf_section_iter_t const * p_iter) +{ + ASSERT(p_iter); + return p_iter->p_item; +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SECTION_ITER_H__ diff --git a/components/libraries/fds/fds.c b/components/libraries/fds/fds.c new file mode 100644 index 0000000..b271757 --- /dev/null +++ b/components/libraries/fds/fds.c @@ -0,0 +1,2201 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(FDS) +#include "fds.h" +#include "fds_internal_defs.h" + +#include +#include +#include +#include "nrf_error.h" +#include "nrf_atomic.h" +#include "nrf_atfifo.h" + +#include "nrf_fstorage.h" +#if (FDS_BACKEND == NRF_FSTORAGE_SD) +#include "nrf_fstorage_sd.h" +#elif (FDS_BACKEND == NRF_FSTORAGE_NVMC) +#include "nrf_fstorage_nvmc.h" +#else +#error Invalid FDS backend. +#endif + +#if (FDS_CRC_CHECK_ON_READ) +#include "crc16.h" +#endif + + +static void fs_event_handler(nrf_fstorage_evt_t * evt); + +NRF_FSTORAGE_DEF(nrf_fstorage_t m_fs) = +{ + // The flash area boundaries are set in fds_init(). + .evt_handler = fs_event_handler, +}; + +// Internal status flags. +static struct +{ + bool volatile initialized; + nrf_atomic_flag_t initializing; +} m_flags; + +// The number of queued operations. +// Incremented by queue_start() and decremented by queue_has_next(). +static nrf_atomic_u32_t m_queued_op_cnt; + +// The number of registered users and their callback functions. +static nrf_atomic_u32_t m_users; +static fds_cb_t m_cb_table[FDS_MAX_USERS]; + +// The latest (largest) record ID written so far. +static nrf_atomic_u32_t m_latest_rec_id; + +// Queue of fds operations. +NRF_ATFIFO_DEF(m_queue, fds_op_t, FDS_OP_QUEUE_SIZE); + +// Structures used to hold informations about virtual pages. +static fds_page_t m_pages[FDS_DATA_PAGES]; +static fds_swap_page_t m_swap_page; + +// Garbage collection data. +static fds_gc_data_t m_gc; + + +static void event_send(fds_evt_t const * const p_evt) +{ + for (uint32_t user = 0; user < FDS_MAX_USERS; user++) + { + if (m_cb_table[user] != NULL) + { + m_cb_table[user](p_evt); + } + } +} + + +static void event_prepare(fds_op_t const * const p_op, fds_evt_t * const p_evt) +{ + switch (p_op->op_code) + { + case FDS_OP_INIT: + p_evt->id = FDS_EVT_INIT; + break; + + case FDS_OP_WRITE: + p_evt->id = FDS_EVT_WRITE; + p_evt->write.file_id = p_op->write.header.file_id; + p_evt->write.record_key = p_op->write.header.record_key; + p_evt->write.record_id = p_op->write.header.record_id; + p_evt->write.is_record_updated = 0; + break; + + case FDS_OP_UPDATE: + p_evt->id = FDS_EVT_UPDATE; + p_evt->write.file_id = p_op->write.header.file_id; + p_evt->write.record_key = p_op->write.header.record_key; + p_evt->write.record_id = p_op->write.header.record_id; + p_evt->write.is_record_updated = (p_op->write.step == FDS_OP_WRITE_DONE); + break; + + case FDS_OP_DEL_RECORD: + p_evt->id = FDS_EVT_DEL_RECORD; + p_evt->del.file_id = p_op->del.file_id; + p_evt->del.record_key = p_op->del.record_key; + p_evt->del.record_id = p_op->del.record_to_delete; + break; + + case FDS_OP_DEL_FILE: + p_evt->id = FDS_EVT_DEL_FILE; + p_evt->del.file_id = p_op->del.file_id; + p_evt->del.record_key = FDS_RECORD_KEY_DIRTY; + p_evt->del.record_id = 0; + break; + + case FDS_OP_GC: + p_evt->id = FDS_EVT_GC; + break; + + default: + // Should not happen. + break; + } +} + + +static bool header_has_next(fds_header_t const * p_hdr, uint32_t const * p_page_end) +{ + uint32_t const * const p_hdr32 = (uint32_t*)p_hdr; + return ( ( p_hdr32 < p_page_end) + && (*p_hdr32 != FDS_ERASED_WORD)); // Check last to be on the safe side (dereference) +} + + +// Jump to the next header. +static fds_header_t const * header_jump(fds_header_t const * const p_hdr) +{ + return (fds_header_t*)((uint32_t*)p_hdr + FDS_HEADER_SIZE + p_hdr->length_words); +} + + +static fds_header_status_t header_check(fds_header_t const * p_hdr, uint32_t const * p_page_end) +{ + if (((uint32_t*)header_jump(p_hdr) > p_page_end)) + { + // The length field would jump across the page boundary. + // FDS won't allow writing such a header, therefore it has been corrupted. + return FDS_HEADER_CORRUPT; + } + + // It is important to also check for the record ID to be non-erased. + // It might happen that during GC, when records are copied in one operation, + // the device powers off after writing the first two words of the header. + // In that case the record would be considered valid, but its ID would + // corrupt the file system. + if ( (p_hdr->file_id == FDS_FILE_ID_INVALID) + || (p_hdr->record_key == FDS_RECORD_KEY_DIRTY) + || (p_hdr->record_id == FDS_ERASED_WORD)) + { + return FDS_HEADER_DIRTY; + } + + return FDS_HEADER_VALID; +} + + +static bool address_is_valid(uint32_t const * const p_addr) +{ + return ((p_addr != NULL) && + (p_addr >= (uint32_t*)m_fs.start_addr) && + (p_addr <= (uint32_t*)m_fs.end_addr) && + (is_word_aligned(p_addr))); +} + + +// Reads a page tag, and determines if the page is used to store data or as swap. +static fds_page_type_t page_identify(uint32_t const * const p_page_addr) +{ + if ( (p_page_addr == NULL) // Should never happen. + || (p_page_addr[FDS_PAGE_TAG_WORD_0] != FDS_PAGE_TAG_MAGIC)) + { + return FDS_PAGE_UNDEFINED; + } + + switch (p_page_addr[FDS_PAGE_TAG_WORD_1]) + { + case FDS_PAGE_TAG_SWAP: + return FDS_PAGE_SWAP; + + case FDS_PAGE_TAG_DATA: + return FDS_PAGE_DATA; + + default: + return FDS_PAGE_UNDEFINED; + } +} + +// A page can be tagged if it is entirely erased, or +// of the first word is fds magic word and the rest of it is erased. +static bool page_can_tag(uint32_t const * const p_page_addr) +{ + // This function should consider pages that have only the first half + // of the fds page tag written as erased (taggable). + // That is because the tag is two words long, and if the device + // has rebooted after writing the first word, that would cause + // the page to be unusable (since undefined and not fully erased). + // By considering the first word as erased if it contains fds page tag, + // the page can be re-tagged as necessary. + + if ((p_page_addr[FDS_PAGE_TAG_WORD_0] != FDS_ERASED_WORD) && + (p_page_addr[FDS_PAGE_TAG_WORD_0] != FDS_PAGE_TAG_MAGIC)) + { + return false; + } + + // Ignore the first word of the tag, we already checked that it is either erased or fds's. + for (uint32_t i = FDS_PAGE_TAG_WORD_1; i < FDS_PAGE_SIZE; i++) + { + if (*(p_page_addr + i) != FDS_ERASED_WORD) + { + return false; + } + } + + return true; +} + + +// NOTE: Must be called from within a critical section. +static bool page_has_space(uint16_t page, uint16_t length_words) +{ + length_words += m_pages[page].write_offset; + length_words += m_pages[page].words_reserved; + return (length_words <= FDS_PAGE_SIZE); +} + + +// Given a pointer to a record, find the index of the page on which it is stored. +// Returns NRF_SUCCESS if the page is found, FDS_ERR_NOT_FOUND otherwise. +static ret_code_t page_from_record(uint16_t * const p_page, uint32_t const * const p_rec) +{ + ret_code_t ret = FDS_ERR_NOT_FOUND; + + CRITICAL_SECTION_ENTER(); + for (uint16_t i = 0; i < FDS_DATA_PAGES; i++) + { + if ((p_rec > m_pages[i].p_addr) && + (p_rec < m_pages[i].p_addr + FDS_PAGE_SIZE)) + { + ret = NRF_SUCCESS; + *p_page = i; + break; + } + } + CRITICAL_SECTION_EXIT(); + + return ret; +} + + +// Scan a page to determine how many words have been written to it. +// This information is used to set the page write offset during initialization. +// Additionally, this function updates the latest record ID as it proceeds. +// If an invalid record header is found, the can_gc argument is set to true. +static void page_scan(uint32_t const * p_addr, + uint16_t * const words_written, + bool * const can_gc) +{ + uint32_t const * const p_page_end = p_addr + FDS_PAGE_SIZE; + + p_addr += FDS_PAGE_TAG_SIZE; + *words_written = FDS_PAGE_TAG_SIZE; + + fds_header_t const * p_header = (fds_header_t*)p_addr; + + while (header_has_next(p_header, p_page_end)) + { + fds_header_status_t hdr = header_check(p_header, p_page_end); + + if (hdr == FDS_HEADER_VALID) + { + // Update the latest (largest) record ID. + if (p_header->record_id > m_latest_rec_id) + { + m_latest_rec_id = p_header->record_id; + } + } + else + { + if (can_gc != NULL) + { + *can_gc = true; + } + + if (hdr == FDS_HEADER_CORRUPT) + { + // It could happen that a record has a corrupt header which would set a + // wrong offset for this page. In such cases, update this value to its maximum, + // to ensure that no new records will be written to this page and to enable + // correct statistics reporting by fds_stat(). + *words_written = FDS_PAGE_SIZE; + + // We can't continue to scan this page. + return; + } + } + + *words_written += (FDS_HEADER_SIZE + p_header->length_words); + p_header = header_jump(p_header); + } +} + + +static void page_offsets_update(fds_page_t * const p_page, fds_op_t const * p_op) +{ + // If the first part of the header has been written correctly, update the offset as normal. + // Even if the record has not been written completely, fds is still able to continue normal + // operation. Incomplete records will be deleted the next time garbage collection is run. + // If we failed at the very beginning of the write operation, restore the offset + // to the previous value so that no holes will be left in the flash. + if (p_op->write.step > FDS_OP_WRITE_RECORD_ID) + { + p_page->write_offset += (FDS_HEADER_SIZE + p_op->write.header.length_words); + } + + p_page->words_reserved -= (FDS_HEADER_SIZE + p_op->write.header.length_words); +} + + +// Tags a page as swap, i.e., reserved for GC. +static ret_code_t page_tag_write_swap(void) +{ + // The tag needs to be statically allocated since it is not buffered by fstorage. + static uint32_t const page_tag_swap[] = {FDS_PAGE_TAG_MAGIC, FDS_PAGE_TAG_SWAP}; + return nrf_fstorage_write(&m_fs, (uint32_t)m_swap_page.p_addr, page_tag_swap, FDS_PAGE_TAG_SIZE * sizeof(uint32_t), NULL); +} + + +// Tags a page as data, i.e, ready for storage. +static ret_code_t page_tag_write_data(uint32_t const * const p_page_addr) +{ + // The tag needs to be statically allocated since it is not buffered by fstorage. + static uint32_t const page_tag_data[] = {FDS_PAGE_TAG_MAGIC, FDS_PAGE_TAG_DATA}; + return nrf_fstorage_write(&m_fs, (uint32_t)p_page_addr, page_tag_data, FDS_PAGE_TAG_SIZE * sizeof(uint32_t), NULL); +} + + +// Reserve space on a page. +// NOTE: this function takes into the account the space required for the record header. +static ret_code_t write_space_reserve(uint16_t length_words, uint16_t * p_page) +{ + bool space_reserved = false; + uint16_t const total_len_words = length_words + FDS_HEADER_SIZE; + + if (total_len_words > FDS_PAGE_SIZE - FDS_PAGE_TAG_SIZE) + { + return FDS_ERR_RECORD_TOO_LARGE; + } + + CRITICAL_SECTION_ENTER(); + for (uint16_t page = 0; page < FDS_DATA_PAGES; page++) + { + if ((m_pages[page].page_type == FDS_PAGE_DATA) && + (page_has_space(page, total_len_words))) + { + space_reserved = true; + *p_page = page; + + m_pages[page].words_reserved += total_len_words; + break; + } + } + CRITICAL_SECTION_EXIT(); + + return (space_reserved) ? NRF_SUCCESS : FDS_ERR_NO_SPACE_IN_FLASH; +} + + +// Undo a write_space_reserve() call. +// NOTE: Must be called within a critical section. +static void write_space_free(uint16_t length_words, uint16_t page) +{ + m_pages[page].words_reserved -= (length_words + FDS_HEADER_SIZE); +} + + +static uint32_t record_id_new(void) +{ + return nrf_atomic_u32_add(&m_latest_rec_id, 1); +} + + +// Given a page and a record, find the next valid record on that page. +// If p_record is NULL, search from the beginning of the page, +// otherwise, resume searching from p_record. +// Return true if a record is found, false otherwise. +// If no record is found, p_record is unchanged. +static bool record_find_next(uint16_t page, uint32_t const ** p_record) +{ + uint32_t const * p_page_end = (m_pages[page].p_addr + FDS_PAGE_SIZE); + + // If this is the first call on this page, start searching from its beginning. + // Otherwise, jump to the next record. + fds_header_t const * p_header = (fds_header_t*)(*p_record); + + if (p_header != NULL) + { + p_header = header_jump(p_header); + } + else + { + p_header = (fds_header_t*)(m_pages[page].p_addr + FDS_PAGE_TAG_SIZE); + } + + // Read records from the page until: + // - a valid record is found or + // - the last record on a page is found + + while (header_has_next(p_header, p_page_end)) + { + switch (header_check(p_header, p_page_end)) + { + case FDS_HEADER_VALID: + *p_record = (uint32_t*)p_header; + return true; + + case FDS_HEADER_DIRTY: + p_header = header_jump(p_header); + break; + + case FDS_HEADER_CORRUPT: + // We can't reliably jump over this record. + // There is nothing more we can do on this page. + return false; + } + } + + // No more valid records on this page. + return false; +} + + +// Find a record given its descriptor and retrive the page in which the record is stored. +// NOTE: Do not pass NULL as an argument for p_page. +static bool record_find_by_desc(fds_record_desc_t * const p_desc, uint16_t * const p_page) +{ + // If the gc_run_count field in the descriptor matches our counter, then the record has + // not been moved. If the address is valid, and the record ID matches, there is no need + // to find the record again. Only lookup the page in which the record is stored. + + if ((address_is_valid(p_desc->p_record)) && + (p_desc->gc_run_count == m_gc.run_count) && + (p_desc->record_id == ((fds_header_t*)p_desc->p_record)->record_id)) + { + return (page_from_record(p_page, p_desc->p_record) == NRF_SUCCESS); + } + + // Otherwise, find the record in flash. + for (*p_page = 0; *p_page < FDS_DATA_PAGES; (*p_page)++) + { + // Set p_record to NULL to make record_find_next() search from the beginning of the page. + uint32_t const * p_record = NULL; + + while (record_find_next(*p_page, &p_record)) + { + fds_header_t const * const p_header = (fds_header_t*)p_record; + if (p_header->record_id == p_desc->record_id) + { + p_desc->p_record = p_record; + p_desc->gc_run_count = m_gc.run_count; + return true; + } + } + } + + return false; +} + + +// Search for a record and return its descriptor. +// If p_file_id is NULL, only the record key will be used for matching. +// If p_record_key is NULL, only the file ID will be used for matching. +// If both are NULL, it will iterate through all records. +static ret_code_t record_find(uint16_t const * p_file_id, + uint16_t const * p_record_key, + fds_record_desc_t * p_desc, + fds_find_token_t * p_token) +{ + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + if (p_desc == NULL || p_token == NULL) + { + return FDS_ERR_NULL_ARG; + } + + // Begin (or resume) searching for a record. + for (; p_token->page < FDS_DATA_PAGES; p_token->page++) + { + if (m_pages[p_token->page].page_type != FDS_PAGE_DATA) + { + // It might be that the page is FDS_PAGE_UNDEFINED. + // Skip this page. + continue; + } + + while (record_find_next(p_token->page, &p_token->p_addr)) + { + fds_header_t const * p_header = (fds_header_t*)p_token->p_addr; + + // A valid record was found, check its header for a match. + if ((p_file_id != NULL) && + (p_header->file_id != *p_file_id)) + { + continue; + } + + if ((p_record_key != NULL) && + (p_header->record_key != *p_record_key)) + { + continue; + } + + // Record found; update the descriptor. + p_desc->record_id = p_header->record_id; + p_desc->p_record = p_token->p_addr; + p_desc->gc_run_count = m_gc.run_count; + + return NRF_SUCCESS; + } + + // We have scanned an entire page. Set the address in the token to NULL + // so that it will be updated in the next iteration. + p_token->p_addr = NULL; + } + + return FDS_ERR_NOT_FOUND; +} + + +// Retrieve statistics about dirty records on a page. +static void records_stat(uint16_t page, + uint16_t * p_valid_records, + uint16_t * p_dirty_records, + uint16_t * p_freeable_words, + bool * p_corruption) +{ + fds_header_t const * p_header = (fds_header_t*)(m_pages[page].p_addr + FDS_PAGE_TAG_SIZE); + uint32_t const * const p_page_end = (m_pages[page].p_addr + FDS_PAGE_SIZE); + + while (header_has_next(p_header, p_page_end)) + { + switch (header_check(p_header, p_page_end)) + { + case FDS_HEADER_DIRTY: + *p_dirty_records += 1; + *p_freeable_words += FDS_HEADER_SIZE + p_header->length_words; + p_header = header_jump(p_header); + break; + + case FDS_HEADER_VALID: + *p_valid_records += 1; + p_header = header_jump(p_header); + break; + + case FDS_HEADER_CORRUPT: + { + *p_dirty_records += 1; + *p_freeable_words += (p_page_end - (uint32_t*)p_header); + *p_corruption = true; + // We can't continue on this page. + return; + } + + default: + break; + } + } +} + + +// Get a buffer on the queue of operations. +static fds_op_t * queue_buf_get(nrf_atfifo_item_put_t * p_iput_ctx) +{ + fds_op_t * const p_op = (fds_op_t*) nrf_atfifo_item_alloc(m_queue, p_iput_ctx); + + memset(p_op, 0x00, sizeof(fds_op_t)); + return p_op; +} + + +// Commit a buffer to the queue of operations. +static void queue_buf_store(nrf_atfifo_item_put_t * p_iput_ctx) +{ + (void) nrf_atfifo_item_put(m_queue, p_iput_ctx); +} + + +// Load the next operation from the queue. +static fds_op_t * queue_load(nrf_atfifo_item_get_t * p_iget_ctx) +{ + return (fds_op_t*) nrf_atfifo_item_get(m_queue, p_iget_ctx); +} + + +// Free the currently loaded operation. +static void queue_free(nrf_atfifo_item_get_t * p_iget_ctx) +{ + // Free the current queue element. + (void) nrf_atfifo_item_free(m_queue, p_iget_ctx); +} + + +static bool queue_has_next(void) +{ + // Decrement the number of queued operations. + ASSERT(m_queued_op_cnt != 0); + return nrf_atomic_u32_sub(&m_queued_op_cnt, 1); +} + + +// This function is called during initialization to setup the page structure (m_pages) and +// provide additional information regarding eventual further initialization steps. +static fds_init_opts_t pages_init(void) +{ + uint32_t ret = NO_PAGES; + uint16_t page = 0; + uint16_t total_pages_available = FDS_VIRTUAL_PAGES; + bool swap_set_but_not_found = false; + + for (uint16_t i = 0; i < FDS_VIRTUAL_PAGES; i++) + { + uint32_t const * const p_page_addr = (uint32_t*)m_fs.start_addr + (i * FDS_PAGE_SIZE); + fds_page_type_t const page_type = page_identify(p_page_addr); + + switch (page_type) + { + case FDS_PAGE_UNDEFINED: + { + if (page_can_tag(p_page_addr)) + { + if (m_swap_page.p_addr != NULL) + { + // If a swap page is already set, flag the page as erased (in m_pages) + // and try to tag it as data (in flash) later on during initialization. + m_pages[page].page_type = FDS_PAGE_ERASED; + m_pages[page].p_addr = p_page_addr; + m_pages[page].write_offset = FDS_PAGE_TAG_SIZE; + + // This is a candidate for a potential new swap page, in case the + // current swap is going to be promoted to complete a GC instance. + m_gc.cur_page = page; + page++; + } + else + { + // If there is no swap page yet, use this one. + m_swap_page.p_addr = p_page_addr; + m_swap_page.write_offset = FDS_PAGE_TAG_SIZE; + swap_set_but_not_found = true; + } + + ret |= PAGE_ERASED; + } + else + { + // The page contains non-FDS data. + // Do not initialize or use this page. + total_pages_available--; + m_pages[page].p_addr = p_page_addr; + m_pages[page].page_type = FDS_PAGE_UNDEFINED; + page++; + } + } break; + + case FDS_PAGE_DATA: + { + m_pages[page].page_type = FDS_PAGE_DATA; + m_pages[page].p_addr = p_page_addr; + + // Scan the page to compute its write offset and determine whether or not the page + // can be garbage collected. Additionally, update the latest kwown record ID. + page_scan(p_page_addr, &m_pages[page].write_offset, &m_pages[page].can_gc); + + ret |= PAGE_DATA; + page++; + } break; + + case FDS_PAGE_SWAP: + { + if (swap_set_but_not_found) + { + m_pages[page].page_type = FDS_PAGE_ERASED; + m_pages[page].p_addr = m_swap_page.p_addr; + m_pages[page].write_offset = FDS_PAGE_TAG_SIZE; + + // This is a candidate for a potential new swap page, in case the + // current swap is going to be promoted to complete a GC instance. + m_gc.cur_page = page; + page++; + } + + m_swap_page.p_addr = p_page_addr; + // If the swap is promoted, this offset should be kept, otherwise, + // it should be set to FDS_PAGE_TAG_SIZE. + page_scan(p_page_addr, &m_swap_page.write_offset, NULL); + + ret |= (m_swap_page.write_offset == FDS_PAGE_TAG_SIZE) ? + PAGE_SWAP_CLEAN : PAGE_SWAP_DIRTY; + } break; + + default: + // Shouldn't happen. + break; + } + } + + if (total_pages_available < 2) + { + ret &= NO_PAGES; + } + + return (fds_init_opts_t)ret; +} + + +// Write the first part of a record header (the key and length). +static ret_code_t record_header_write_begin(fds_op_t * const p_op, uint32_t * const p_addr) +{ + ret_code_t ret; + + // Write the record ID next. + p_op->write.step = FDS_OP_WRITE_RECORD_ID; + + ret = nrf_fstorage_write(&m_fs, (uint32_t)(p_addr + FDS_OFFSET_TL), + &p_op->write.header.record_key, FDS_HEADER_SIZE_TL * sizeof(uint32_t), NULL); + + return (ret == NRF_SUCCESS) ? NRF_SUCCESS : FDS_ERR_BUSY; +} + + +static ret_code_t record_header_write_id(fds_op_t * const p_op, uint32_t * const p_addr) +{ + ret_code_t ret; + + // If this record has no data, write the last part of the header directly. + // Otherwise, write the record data next. + p_op->write.step = (p_op->write.p_data != NULL) ? + FDS_OP_WRITE_DATA : FDS_OP_WRITE_HEADER_FINALIZE; + + ret = nrf_fstorage_write(&m_fs, (uint32_t)(p_addr + FDS_OFFSET_ID), + &p_op->write.header.record_id, FDS_HEADER_SIZE_ID * sizeof(uint32_t), NULL); + + return (ret == NRF_SUCCESS) ? NRF_SUCCESS : FDS_ERR_BUSY; +} + + +static ret_code_t record_header_write_finalize(fds_op_t * const p_op, uint32_t * const p_addr) +{ + ret_code_t ret; + + // If this is a simple write operation, then this is the last step. + // If this is an update instead, delete the old record next. + p_op->write.step = (p_op->op_code == FDS_OP_UPDATE) ? + FDS_OP_WRITE_FLAG_DIRTY : FDS_OP_WRITE_DONE; + + ret = nrf_fstorage_write(&m_fs, (uint32_t)(p_addr + FDS_OFFSET_IC), + &p_op->write.header.file_id, FDS_HEADER_SIZE_IC * sizeof(uint32_t), NULL); + + return (ret == NRF_SUCCESS) ? NRF_SUCCESS : FDS_ERR_BUSY; +} + + +static ret_code_t record_header_flag_dirty(uint32_t * const p_record, uint16_t page_to_gc) +{ + // Used to flag a record as dirty, i.e. ready for garbage collection. + // Must be statically allocated since it will be written to flash. + __ALIGN(4) static uint32_t const dirty_header = {0xFFFF0000}; + + // Flag the record as dirty. + ret_code_t ret; + + ret = nrf_fstorage_write(&m_fs, (uint32_t)p_record, + &dirty_header, FDS_HEADER_SIZE_TL * sizeof(uint32_t), NULL); + + if (ret != NRF_SUCCESS) + { + return FDS_ERR_BUSY; + } + + m_pages[page_to_gc].can_gc = true; + + return NRF_SUCCESS; +} + + +static ret_code_t record_find_and_delete(fds_op_t * const p_op) +{ + ret_code_t ret; + uint16_t page; + fds_record_desc_t desc = {0}; + + desc.record_id = p_op->del.record_to_delete; + + if (record_find_by_desc(&desc, &page)) + { + fds_header_t const * const p_header = (fds_header_t const *)desc.p_record; + + // Copy the record key and file ID, so that they can be returned in the event. + // In case this function is run as part of an update, there is no need to copy + // the file ID and record key since they are present in the header stored + // in the queue element. + + p_op->del.file_id = p_header->file_id; + p_op->del.record_key = p_header->record_key; + + // Flag the record as dirty. + ret = record_header_flag_dirty((uint32_t*)desc.p_record, page); + } + else + { + // The record never existed, or it has already been deleted. + ret = FDS_ERR_NOT_FOUND; + } + + return ret; +} + + +// Finds a record within a file and flags it as dirty. +static ret_code_t file_find_and_delete(fds_op_t * const p_op) +{ + ret_code_t ret; + fds_record_desc_t desc; + + // This token must persist across calls. + static fds_find_token_t tok = {0}; + + // Pass NULL to ignore the record key. + ret = record_find(&p_op->del.file_id, NULL, &desc, &tok); + + if (ret == NRF_SUCCESS) + { + // A record was found: flag it as dirty. + ret = record_header_flag_dirty((uint32_t*)desc.p_record, tok.page); + } + else // FDS_ERR_NOT_FOUND + { + // No more records were found. Zero the token, so that it can be reused. + memset(&tok, 0x00, sizeof(fds_find_token_t)); + } + + return ret; +} + + +// Writes record data to flash. +static ret_code_t record_write_data(fds_op_t * const p_op, uint32_t * const p_addr) +{ + ret_code_t ret; + + p_op->write.step = FDS_OP_WRITE_HEADER_FINALIZE; + + ret = nrf_fstorage_write(&m_fs, (uint32_t)(p_addr + FDS_OFFSET_DATA), + p_op->write.p_data, p_op->write.header.length_words * sizeof(uint32_t), NULL); + + return (ret == NRF_SUCCESS) ? NRF_SUCCESS : FDS_ERR_BUSY; +} + + +#if (FDS_CRC_CHECK_ON_READ) +static bool crc_verify_success(uint16_t crc, uint16_t len_words, uint32_t const * const p_data) +{ + uint16_t computed_crc; + + // The CRC is computed on the entire record, except the CRC field itself. + // The record header is 12 bytes, out of these we have to skip bytes 6 to 8 where the + // CRC itself is stored. Then we compute the CRC for the rest of the record, from byte 8 of + // the header (where the record ID begins) to the end of the record data. + computed_crc = crc16_compute((uint8_t const *)p_data, 6, NULL); + computed_crc = crc16_compute((uint8_t const *)p_data + 8, + (FDS_HEADER_SIZE_ID + len_words) * sizeof(uint32_t), + &computed_crc); + + return (computed_crc == crc); +} +#endif + + +static void gc_init(void) +{ + m_gc.run_count++; + m_gc.cur_page = 0; + m_gc.resume = false; + + // Setup which pages to GC. Defer checking for open records and the can_gc flag, + // as other operations might change those while GC is running. + for (uint16_t i = 0; i < FDS_DATA_PAGES; i++) + { + m_gc.do_gc_page[i] = (m_pages[i].page_type == FDS_PAGE_DATA); + } +} + + +// Obtain the next page to be garbage collected. +// Returns true if there are pages left to garbage collect, returns false otherwise. +static bool gc_page_next(uint16_t * const p_next_page) +{ + bool ret = false; + + for (uint16_t i = 0; i < FDS_DATA_PAGES; i++) + { + if (m_gc.do_gc_page[i]) + { + // Do not attempt to GC this page again. + m_gc.do_gc_page[i] = false; + + // Only GC pages with no open records and with some records which have been deleted. + if ((m_pages[i].records_open == 0) && (m_pages[i].can_gc == true)) + { + *p_next_page = i; + ret = true; + break; + } + } + } + + return ret; +} + + +static ret_code_t gc_swap_erase(void) +{ + m_gc.state = GC_DISCARD_SWAP; + m_swap_page.write_offset = FDS_PAGE_TAG_SIZE; + + return nrf_fstorage_erase(&m_fs, (uint32_t)m_swap_page.p_addr, FDS_PHY_PAGES_IN_VPAGE, NULL); +} + + +// Erase the page being garbage collected, or erase the swap in case there are any open +// records on the page being garbage collected. +static ret_code_t gc_page_erase(void) +{ + uint32_t ret; + uint16_t const gc = m_gc.cur_page; + + if (m_pages[gc].records_open == 0) + { + m_gc.state = GC_ERASE_PAGE; + + ret = nrf_fstorage_erase(&m_fs, (uint32_t)m_pages[gc].p_addr, FDS_PHY_PAGES_IN_VPAGE, NULL); + } + else + { + // If there are open records, stop garbage collection on this page. + // Discard the swap and try to garbage collect another page. + ret = gc_swap_erase(); + } + + return ret; +} + + +// Copy the current record to swap. +static ret_code_t gc_record_copy(void) +{ + fds_header_t const * const p_header = (fds_header_t*)m_gc.p_record_src; + uint32_t const * const p_dest = m_swap_page.p_addr + m_swap_page.write_offset; + uint16_t const record_len = FDS_HEADER_SIZE + p_header->length_words; + + m_gc.state = GC_COPY_RECORD; + + // Copy the record to swap; it is guaranteed to fit in the destination page, + // so there is no need to check its size. This will either succeed or timeout. + return nrf_fstorage_write(&m_fs, (uint32_t)p_dest, m_gc.p_record_src, + record_len * sizeof(uint32_t), + NULL); +} + + +static ret_code_t gc_record_find_next(void) +{ + ret_code_t ret; + + // Find the next valid record to copy. + if (record_find_next(m_gc.cur_page, &m_gc.p_record_src)) + { + ret = gc_record_copy(); + } + else + { + // No more records left to copy on this page; swap pages. + ret = gc_page_erase(); + } + + return ret; +} + + +// Promote the swap by tagging it as a data page. +static ret_code_t gc_swap_promote(void) +{ + m_gc.state = GC_PROMOTE_SWAP; + return page_tag_write_data(m_pages[m_gc.cur_page].p_addr); +} + + +// Tag the page just garbage collected as swap. +static ret_code_t gc_tag_new_swap(void) +{ + m_gc.state = GC_TAG_NEW_SWAP; + m_gc.p_record_src = NULL; + return page_tag_write_swap(); +} + + +static ret_code_t gc_next_page(void) +{ + if (!gc_page_next(&m_gc.cur_page)) + { + // No pages left to GC; GC has terminated. Reset the state. + m_gc.state = GC_BEGIN; + m_gc.cur_page = 0; + m_gc.p_record_src = NULL; + + return FDS_OP_COMPLETED; + } + + return gc_record_find_next(); +} + + +// Update the swap page offeset after a record has been successfully copied to it. +static void gc_update_swap_offset(void) +{ + fds_header_t const * const p_header = (fds_header_t*)m_gc.p_record_src; + uint16_t const record_len = FDS_HEADER_SIZE + p_header->length_words; + + m_swap_page.write_offset += record_len; +} + + +static void gc_swap_pages(void) +{ + // The page being garbage collected will be the new swap page, + // and the current swap will be used as a data page (promoted). + uint32_t const * const p_addr = m_swap_page.p_addr; + + m_swap_page.p_addr = m_pages[m_gc.cur_page].p_addr; + m_pages[m_gc.cur_page].p_addr = p_addr; + + // Keep the offset for this page, but reset it for the swap. + m_pages[m_gc.cur_page].write_offset = m_swap_page.write_offset; + m_swap_page.write_offset = FDS_PAGE_TAG_SIZE; + + // Page has been garbage collected + m_pages[m_gc.cur_page].can_gc = false; +} + + +static void gc_state_advance(void) +{ + switch (m_gc.state) + { + case GC_BEGIN: + gc_init(); + m_gc.state = GC_NEXT_PAGE; + break; + + // A record was successfully copied. + case GC_COPY_RECORD: + gc_update_swap_offset(); + m_gc.state = GC_FIND_NEXT_RECORD; + break; + + // A page was successfully erased. Prepare to promote the swap. + case GC_ERASE_PAGE: + gc_swap_pages(); + m_gc.state = GC_PROMOTE_SWAP; + break; + + // Swap was discarded because the page being GC'ed had open records. + case GC_DISCARD_SWAP: + // Swap was successfully promoted. + case GC_PROMOTE_SWAP: + // Prepare to tag the page just GC'ed as swap. + m_gc.state = GC_TAG_NEW_SWAP; + break; + + case GC_TAG_NEW_SWAP: + m_gc.state = GC_NEXT_PAGE; + break; + + default: + // Should not happen. + break; + } +} + + +// Initialize the filesystem. +static ret_code_t init_execute(uint32_t prev_ret, fds_op_t * const p_op) +{ + ret_code_t ret = FDS_ERR_INTERNAL; + + if (prev_ret != NRF_SUCCESS) + { + // A previous operation has timed out. + m_flags.initializing = false; + return FDS_ERR_OPERATION_TIMEOUT; + } + + switch (p_op->init.step) + { + case FDS_OP_INIT_TAG_SWAP: + { + // The page write offset was determined previously by pages_init(). + p_op->init.step = FDS_OP_INIT_TAG_DATA; + ret = page_tag_write_swap(); + } break; + + case FDS_OP_INIT_TAG_DATA: + { + // Tag remaining erased pages as data. + bool write_reqd = false; + for (uint16_t i = 0; i < FDS_DATA_PAGES; i++) + { + if (m_pages[i].page_type == FDS_PAGE_ERASED) + { + m_pages[i].page_type = FDS_PAGE_DATA; + write_reqd = true; + ret = page_tag_write_data(m_pages[i].p_addr); + break; + } + } + if (!write_reqd) + { + m_flags.initialized = true; + m_flags.initializing = false; + return FDS_OP_COMPLETED; + } + } break; + + case FDS_OP_INIT_ERASE_SWAP: + { + // If the swap is going to be discarded then reset its write_offset. + p_op->init.step = FDS_OP_INIT_TAG_SWAP; + m_swap_page.write_offset = FDS_PAGE_TAG_SIZE; + + ret = nrf_fstorage_erase(&m_fs, (uint32_t)m_swap_page.p_addr, FDS_PHY_PAGES_IN_VPAGE, NULL); + } break; + + case FDS_OP_INIT_PROMOTE_SWAP: + { + p_op->init.step = FDS_OP_INIT_TAG_SWAP; + + uint16_t const gc = m_gc.cur_page; + uint32_t const * const p_old_swap = m_swap_page.p_addr; + + // Execute the swap. + m_swap_page.p_addr = m_pages[gc].p_addr; + m_pages[gc].p_addr = p_old_swap; + + // Copy the offset from the swap to the new page. + m_pages[gc].write_offset = m_swap_page.write_offset; + m_swap_page.write_offset = FDS_PAGE_TAG_SIZE; + + m_pages[gc].page_type = FDS_PAGE_DATA; + + // Promote the old swap page to data, but do this at the end + // because we can re-enter this function; we must update have + // updated the page in RAM before that. + ret = page_tag_write_data(p_old_swap); + } break; + + default: + // Should not happen. + break; + } + + if (ret != NRF_SUCCESS) + { + // fstorage queue was full. + m_flags.initializing = false; + return FDS_ERR_BUSY; + } + + return FDS_OP_EXECUTING; +} + + +// Executes write and update operations. +static ret_code_t write_execute(uint32_t prev_ret, fds_op_t * const p_op) +{ + ret_code_t ret; + uint32_t * p_write_addr; + fds_page_t * const p_page = &m_pages[p_op->write.page]; + + // This must persist across calls. + static fds_record_desc_t desc = {0}; + // When a record is updated, this variable will hold the page where the old + // copy was stored. This will be used to set the can_gc flag when the header is + // invalidated (FDS_OP_WRITE_FLAG_DIRTY). + static uint16_t page; + + if (prev_ret != NRF_SUCCESS) + { + // The previous operation has timed out, update offsets. + page_offsets_update(p_page, p_op); + return FDS_ERR_OPERATION_TIMEOUT; + } + + // Compute the address where to write data. + p_write_addr = (uint32_t*)(p_page->p_addr + p_page->write_offset); + + // Execute the current step of the operation, and set one to be executed next. + switch (p_op->write.step) + { + case FDS_OP_WRITE_FIND_RECORD: + { + // The first step of updating a record constists of locating the copy to be deleted. + // If the old copy couldn't be found for any reason then the update should fail. + // This prevents duplicates when queuing multiple updates of the same record. + desc.p_record = NULL; + desc.record_id = p_op->write.record_to_delete; + + if (!record_find_by_desc(&desc, &page)) + { + return FDS_ERR_NOT_FOUND; + } + // Setting the step is redundant since we are falling through. + } + // Fallthrough to FDS_OP_WRITE_HEADER_BEGIN. + + case FDS_OP_WRITE_HEADER_BEGIN: + ret = record_header_write_begin(p_op, p_write_addr); + break; + + case FDS_OP_WRITE_RECORD_ID: + ret = record_header_write_id(p_op, p_write_addr); + break; + + case FDS_OP_WRITE_DATA: + ret = record_write_data(p_op, p_write_addr); + break; + + case FDS_OP_WRITE_HEADER_FINALIZE: + ret = record_header_write_finalize(p_op, p_write_addr); + break; + + case FDS_OP_WRITE_FLAG_DIRTY: + p_op->write.step = FDS_OP_WRITE_DONE; + ret = record_header_flag_dirty((uint32_t*)desc.p_record, page); + break; + + case FDS_OP_WRITE_DONE: + ret = FDS_OP_COMPLETED; + +#if (FDS_CRC_CHECK_ON_WRITE) + if (!crc_verify_success(p_op->write.header.crc16, + p_op->write.header.length_words, + p_write_addr)) + { + ret = FDS_ERR_CRC_CHECK_FAILED; + } +#endif + break; + + default: + ret = FDS_ERR_INTERNAL; + break; + } + + // An operation has either completed or failed. It may have failed because fstorage + // ran out of memory, or because the user tried to delete a record which did not exist. + if (ret != FDS_OP_EXECUTING) + { + // There won't be another callback for this operation, so update the page offset now. + page_offsets_update(p_page, p_op); + } + + return ret; +} + + +static ret_code_t delete_execute(uint32_t prev_ret, fds_op_t * const p_op) +{ + ret_code_t ret; + + if (prev_ret != NRF_SUCCESS) + { + return FDS_ERR_OPERATION_TIMEOUT; + } + + switch (p_op->del.step) + { + case FDS_OP_DEL_RECORD_FLAG_DIRTY: + p_op->del.step = FDS_OP_DEL_DONE; + ret = record_find_and_delete(p_op); + break; + + case FDS_OP_DEL_FILE_FLAG_DIRTY: + ret = file_find_and_delete(p_op); + if (ret == FDS_ERR_NOT_FOUND) + { + // No more records could be found. + // There won't be another callback for this operation, so return now. + ret = FDS_OP_COMPLETED; + } + break; + + case FDS_OP_DEL_DONE: + ret = FDS_OP_COMPLETED; + break; + + default: + ret = FDS_ERR_INTERNAL; + break; + } + + return ret; +} + + +static ret_code_t gc_execute(uint32_t prev_ret) +{ + ret_code_t ret; + + if (prev_ret != NRF_SUCCESS) + { + return FDS_ERR_OPERATION_TIMEOUT; + } + + if (m_gc.resume) + { + m_gc.resume = false; + } + else + { + gc_state_advance(); + } + + switch (m_gc.state) + { + case GC_NEXT_PAGE: + ret = gc_next_page(); + break; + + case GC_FIND_NEXT_RECORD: + ret = gc_record_find_next(); + break; + + case GC_COPY_RECORD: + ret = gc_record_copy(); + break; + + case GC_ERASE_PAGE: + ret = gc_page_erase(); + break; + + case GC_PROMOTE_SWAP: + ret = gc_swap_promote(); + break; + + case GC_TAG_NEW_SWAP: + ret = gc_tag_new_swap(); + break; + + default: + // Should not happen. + ret = FDS_ERR_INTERNAL; + break; + } + + // Either FDS_OP_EXECUTING, FDS_OP_COMPLETED, FDS_ERR_BUSY or FDS_ERR_INTERNAL. + return ret; +} + + +static void queue_process(ret_code_t result) +{ + static fds_op_t * m_p_cur_op; // Current fds operation. + static nrf_atfifo_item_get_t m_iget_ctx; // Queue context for the current operation. + + while (true) + { + if (m_p_cur_op == NULL) + { + // Load the next from the queue if no operation is being executed. + m_p_cur_op = queue_load(&m_iget_ctx); + } + + /* We can reach here in three ways: + * from queue_start(): something was just queued + * from the fstorage event handler: an operation is being executed + * looping: we only loop if there are operations still in the queue + * + * In all these three cases, m_p_cur_op != NULL. + */ + ASSERT(m_p_cur_op != NULL); + + switch (m_p_cur_op->op_code) + { + case FDS_OP_INIT: + result = init_execute(result, m_p_cur_op); + break; + + case FDS_OP_WRITE: + case FDS_OP_UPDATE: + result = write_execute(result, m_p_cur_op); + break; + + case FDS_OP_DEL_RECORD: + case FDS_OP_DEL_FILE: + result = delete_execute(result, m_p_cur_op); + break; + + case FDS_OP_GC: + result = gc_execute(result); + break; + + default: + result = FDS_ERR_INTERNAL; + break; + } + + if (result == FDS_OP_EXECUTING) + { + // The operation has not completed yet. Wait for the next system event. + break; + } + + // The operation has completed (either successfully or with an error). + // - send an event to the user + // - free the operation buffer + // - execute any other queued operations + + fds_evt_t evt = + { + // The operation might have failed for one of the following reasons: + // FDS_ERR_BUSY - flash subsystem can't accept the operation + // FDS_ERR_OPERATION_TIMEOUT - flash subsystem timed out + // FDS_ERR_CRC_CHECK_FAILED - a CRC check failed + // FDS_ERR_NOT_FOUND - no record found (delete/update) + .result = (result == FDS_OP_COMPLETED) ? NRF_SUCCESS : result, + }; + + event_prepare(m_p_cur_op, &evt); + event_send(&evt); + + // Zero the pointer to the current operation so that this function + // will fetch a new one from the queue next time it is run. + m_p_cur_op = NULL; + + // The result of the operation must be reset upon re-entering the loop to ensure + // the next operation won't be affected by eventual errors in previous operations. + result = NRF_SUCCESS; + + // Free the queue element used by the current operation. + queue_free(&m_iget_ctx); + + if (!queue_has_next()) + { + // No more elements left. Nothing to do. + break; + } + } +} + + +static void queue_start(void) +{ + if (!nrf_atomic_u32_fetch_add(&m_queued_op_cnt, 1)) + { + queue_process(NRF_SUCCESS); + } +} + + +static void fs_event_handler(nrf_fstorage_evt_t * p_evt) +{ + queue_process(p_evt->result); +} + + +// Enqueues write and update operations. +static ret_code_t write_enqueue(fds_record_desc_t * const p_desc, + fds_record_t const * const p_record, + fds_reserve_token_t const * const p_tok, + fds_op_code_t op_code) +{ + ret_code_t ret; + uint16_t page; + uint16_t crc = 0; + uint16_t length_words = 0; + fds_op_t * p_op; + nrf_atfifo_item_put_t iput_ctx; + + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + if (p_record == NULL) + { + return FDS_ERR_NULL_ARG; + } + + if ((p_record->file_id == FDS_FILE_ID_INVALID) || + (p_record->key == FDS_RECORD_KEY_DIRTY)) + { + return FDS_ERR_INVALID_ARG; + } + + if (!is_word_aligned(p_record->data.p_data)) + { + return FDS_ERR_UNALIGNED_ADDR; + } + + // No space was previously reserved in flash for this operation. + if (p_tok == NULL) + { + // Find a page where to write data. + length_words = p_record->data.length_words; + ret = write_space_reserve(length_words, &page); + + if (ret != NRF_SUCCESS) + { + // There is either not enough space in flash (FDS_ERR_NO_SPACE_IN_FLASH) or + // the record exceeds the size of virtual page (FDS_ERR_RECORD_TOO_LARGE). + return ret; + } + } + else + { + page = p_tok->page; + length_words = p_tok->length_words; + } + + // Get a buffer on the queue of operations. + p_op = queue_buf_get(&iput_ctx); + if (p_op == NULL) + { + CRITICAL_SECTION_ENTER(); + write_space_free(length_words, page); + CRITICAL_SECTION_EXIT(); + return FDS_ERR_NO_SPACE_IN_QUEUES; + } + + // Initialize the operation. + p_op->op_code = op_code; + p_op->write.step = FDS_OP_WRITE_HEADER_BEGIN; + p_op->write.page = page; + p_op->write.p_data = p_record->data.p_data; + p_op->write.header.record_id = record_id_new(); + p_op->write.header.file_id = p_record->file_id; + p_op->write.header.record_key = p_record->key; + p_op->write.header.length_words = length_words; + + if (op_code == FDS_OP_UPDATE) + { + p_op->write.step = FDS_OP_WRITE_FIND_RECORD; + // Save the record ID of the record to be updated. + p_op->write.record_to_delete = p_desc->record_id; + } + +#if (FDS_CRC_CHECK_ON_READ) + // First, compute the CRC for the first 6 bytes of the header which contain the + // record key, length and file ID, then, compute the CRC of the record ID (4 bytes). + crc = crc16_compute((uint8_t*)&p_op->write.header, 6, NULL); + crc = crc16_compute((uint8_t*)&p_op->write.header.record_id, 4, &crc); + + // Compute the CRC for the record data. + crc = crc16_compute((uint8_t*)p_record->data.p_data, + p_record->data.length_words * sizeof(uint32_t), &crc); +#endif + + p_op->write.header.crc16 = crc; + + queue_buf_store(&iput_ctx); + + // Initialize the record descriptor, if provided. + if (p_desc != NULL) + { + p_desc->p_record = NULL; + // Don't invoke record_id_new() again ! + p_desc->record_id = p_op->write.header.record_id; + p_desc->record_is_open = false; + p_desc->gc_run_count = m_gc.run_count; + } + + // Start processing the queue, if necessary. + queue_start(); + + return NRF_SUCCESS; +} + + +ret_code_t fds_register(fds_cb_t cb) +{ + ret_code_t ret; + + if (m_users == FDS_MAX_USERS) + { + ret = FDS_ERR_USER_LIMIT_REACHED; + } + else + { + m_cb_table[m_users] = cb; + (void) nrf_atomic_u32_add(&m_users, 1); + + ret = NRF_SUCCESS; + } + + return ret; +} + + +static uint32_t flash_end_addr(void) +{ + uint32_t const bootloader_addr = BOOTLOADER_ADDRESS; + uint32_t const page_sz = NRF_FICR->CODEPAGESIZE; + +#if defined(NRF52810_XXAA) || defined(NRF52811_XXAA) + // Hardcode the number of flash pages, necessary for SoC emulation. + // nRF52810 on nRF52832 and + // nRF52811 on nRF52840 + uint32_t const code_sz = 48; +#else + uint32_t const code_sz = NRF_FICR->CODESIZE; +#endif + + uint32_t end_addr = (bootloader_addr != 0xFFFFFFFF) ? bootloader_addr : (code_sz * page_sz); + + return end_addr - (FDS_PHY_PAGES_RESERVED * FDS_PHY_PAGE_SIZE * sizeof(uint32_t)); +} + + +static void flash_bounds_set(void) +{ + uint32_t flash_size = (FDS_PHY_PAGES * FDS_PHY_PAGE_SIZE * sizeof(uint32_t)); + m_fs.end_addr = flash_end_addr(); + m_fs.start_addr = m_fs.end_addr - flash_size; +} + + +static ret_code_t flash_subsystem_init(void) +{ + flash_bounds_set(); + + #if (FDS_BACKEND == NRF_FSTORAGE_SD) + return nrf_fstorage_init(&m_fs, &nrf_fstorage_sd, NULL); + #elif (FDS_BACKEND == NRF_FSTORAGE_NVMC) + return nrf_fstorage_init(&m_fs, &nrf_fstorage_nvmc, NULL); + #else + #error Invalid FDS_BACKEND. + #endif +} + + +static void queue_init(void) +{ + (void) NRF_ATFIFO_INIT(m_queue); +} + + +ret_code_t fds_init(void) +{ + ret_code_t ret; + fds_evt_t const evt_success = + { + .id = FDS_EVT_INIT, + .result = NRF_SUCCESS, + }; + + if (m_flags.initialized) + { + // No initialization is necessary. Notify the application immediately. + event_send(&evt_success); + return NRF_SUCCESS; + } + + if (nrf_atomic_flag_set_fetch(&m_flags.initializing)) + { + // If we were already initializing, return. + return NRF_SUCCESS; + } + + // Otherwise, the flag is set and we proceed to initialization. + + ret = flash_subsystem_init(); + if (ret != NRF_SUCCESS) + { + return ret; + } + + queue_init(); + + // Initialize the page structure (m_pages), and determine which + // initialization steps are required given the current state of the filesystem. + + fds_init_opts_t init_opts = pages_init(); + + switch (init_opts) + { + case NO_PAGES: + case NO_SWAP: + m_flags.initialized = false; + m_flags.initializing = false; + return FDS_ERR_NO_PAGES; + + case ALREADY_INSTALLED: + { + // No initialization is necessary. Notify the application immediately. + m_flags.initialized = true; + m_flags.initializing = false; + event_send(&evt_success); + return NRF_SUCCESS; + } + + default: + break; + } + + // A write operation is necessary to initialize the fileystem. + + nrf_atfifo_item_put_t iput_ctx; + + fds_op_t * p_op = queue_buf_get(&iput_ctx); + if (p_op == NULL) + { + return FDS_ERR_NO_SPACE_IN_QUEUES; + } + + p_op->op_code = FDS_OP_INIT; + + switch (init_opts) + { + case FRESH_INSTALL: + case TAG_SWAP: + p_op->init.step = FDS_OP_INIT_TAG_SWAP; + break; + + case PROMOTE_SWAP: + case PROMOTE_SWAP_INST: + p_op->init.step = FDS_OP_INIT_PROMOTE_SWAP; + break; + + case DISCARD_SWAP: + p_op->init.step = FDS_OP_INIT_ERASE_SWAP; + break; + + case TAG_DATA: + case TAG_DATA_INST: + p_op->init.step = FDS_OP_INIT_TAG_DATA; + break; + + default: + // Should not happen. + break; + } + + queue_buf_store(&iput_ctx); + queue_start(); + + return NRF_SUCCESS; +} + + +ret_code_t fds_record_open(fds_record_desc_t * const p_desc, + fds_flash_record_t * const p_flash_rec) +{ + uint16_t page; + + if ((p_desc == NULL) || (p_flash_rec == NULL)) + { + return FDS_ERR_NULL_ARG; + } + + // Find the record if necessary. + if (record_find_by_desc(p_desc, &page)) + { + fds_header_t const * const p_header = (fds_header_t*)p_desc->p_record; + +#if (FDS_CRC_CHECK_ON_READ) + if (!crc_verify_success(p_header->crc16, + p_header->length_words, + p_desc->p_record)) + { + return FDS_ERR_CRC_CHECK_FAILED; + } +#endif + + (void) nrf_atomic_u32_add(&m_pages[page].records_open, 1); + + // Initialize p_flash_rec. + p_flash_rec->p_header = p_header; + p_flash_rec->p_data = (p_desc->p_record + FDS_HEADER_SIZE); + + // Set the record as open in the descriptor. + p_desc->record_is_open = true; + + return NRF_SUCCESS; + } + + // The record could not be found. + // It either never existed or it has been deleted. + return FDS_ERR_NOT_FOUND; +} + + +ret_code_t fds_record_close(fds_record_desc_t * const p_desc) +{ + ret_code_t ret; + uint16_t page; + + if (p_desc == NULL) + { + return FDS_ERR_NULL_ARG; + } + + if (record_find_by_desc((fds_record_desc_t*)p_desc, &page)) + { + CRITICAL_SECTION_ENTER(); + if ((m_pages[page].records_open > 0) && (p_desc->record_is_open)) + { + + m_pages[page].records_open--; + p_desc->record_is_open = false; + + ret = NRF_SUCCESS; + } + else + { + ret = FDS_ERR_NO_OPEN_RECORDS; + } + CRITICAL_SECTION_EXIT(); + } + else + { + ret = FDS_ERR_NOT_FOUND; + } + + return ret; +} + + +ret_code_t fds_reserve(fds_reserve_token_t * const p_tok, uint16_t length_words) +{ + ret_code_t ret; + uint16_t page; + + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + if (p_tok == NULL) + { + return FDS_ERR_NULL_ARG; + } + + ret = write_space_reserve(length_words, &page); + + if (ret == NRF_SUCCESS) + { + p_tok->page = page; + p_tok->length_words = length_words; + } + + return ret; +} + + +ret_code_t fds_reserve_cancel(fds_reserve_token_t * const p_tok) +{ + ret_code_t ret; + + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + if (p_tok == NULL) + { + return FDS_ERR_NULL_ARG; + } + + if (p_tok->page > FDS_DATA_PAGES) + { + // The page does not exist. This shouldn't happen. + return FDS_ERR_INVALID_ARG; + } + + fds_page_t const * const p_page = &m_pages[p_tok->page]; + + CRITICAL_SECTION_ENTER(); + if ((FDS_HEADER_SIZE + p_tok->length_words) <= p_page->words_reserved) + { + // Free reserved space. + write_space_free(p_tok->length_words, p_tok->page); + + // Clean the token. + p_tok->page = 0; + p_tok->length_words = 0; + ret = NRF_SUCCESS; + } + else + { + // We are trying to cancel a reservation of more words than how many are + // currently reserved on the page. Clearly, this shouldn't happen. + ret = FDS_ERR_INVALID_ARG; + } + CRITICAL_SECTION_EXIT(); + + return ret; +} + + +ret_code_t fds_record_write(fds_record_desc_t * const p_desc, + fds_record_t const * const p_record) +{ + return write_enqueue(p_desc, p_record, NULL, FDS_OP_WRITE); +} + + +ret_code_t fds_record_write_reserved(fds_record_desc_t * const p_desc, + fds_record_t const * const p_record, + fds_reserve_token_t const * const p_tok) +{ + // A NULL token is not allowed when writing to a reserved space. + if (p_tok == NULL) + { + return FDS_ERR_NULL_ARG; + } + + return write_enqueue(p_desc, p_record, p_tok, FDS_OP_WRITE); +} + + +ret_code_t fds_record_update(fds_record_desc_t * const p_desc, + fds_record_t const * const p_record) +{ + // A NULL descriptor is not allowed when updating a record. + if (p_desc == NULL) + { + return FDS_ERR_NULL_ARG; + } + + return write_enqueue(p_desc, p_record, NULL, FDS_OP_UPDATE); +} + + +ret_code_t fds_record_delete(fds_record_desc_t * const p_desc) +{ + fds_op_t * p_op; + nrf_atfifo_item_put_t iput_ctx; + + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + if (p_desc == NULL) + { + return FDS_ERR_NULL_ARG; + } + + p_op = queue_buf_get(&iput_ctx); + if (p_op == NULL) + { + return FDS_ERR_NO_SPACE_IN_QUEUES; + } + + p_op->op_code = FDS_OP_DEL_RECORD; + p_op->del.step = FDS_OP_DEL_RECORD_FLAG_DIRTY; + p_op->del.record_to_delete = p_desc->record_id; + + queue_buf_store(&iput_ctx); + queue_start(); + + return NRF_SUCCESS; +} + + +ret_code_t fds_file_delete(uint16_t file_id) +{ + fds_op_t * p_op; + nrf_atfifo_item_put_t iput_ctx; + + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + if (file_id == FDS_FILE_ID_INVALID) + { + return FDS_ERR_INVALID_ARG; + } + + p_op = queue_buf_get(&iput_ctx); + if (p_op == NULL) + { + return FDS_ERR_NO_SPACE_IN_QUEUES; + } + + p_op->op_code = FDS_OP_DEL_FILE; + p_op->del.step = FDS_OP_DEL_FILE_FLAG_DIRTY; + p_op->del.file_id = file_id; + + queue_buf_store(&iput_ctx); + queue_start(); + + return NRF_SUCCESS; +} + + +ret_code_t fds_gc(void) +{ + fds_op_t * p_op; + nrf_atfifo_item_put_t iput_ctx; + + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + p_op = queue_buf_get(&iput_ctx); + if (p_op == NULL) + { + return FDS_ERR_NO_SPACE_IN_QUEUES; + } + + p_op->op_code = FDS_OP_GC; + + queue_buf_store(&iput_ctx); + + if (m_gc.state != GC_BEGIN) + { + // Resume GC by retrying the last step. + m_gc.resume = true; + } + + queue_start(); + + return NRF_SUCCESS; +} + + +ret_code_t fds_record_iterate(fds_record_desc_t * const p_desc, + fds_find_token_t * const p_token) +{ + return record_find(NULL, NULL, p_desc, p_token); +} + + +ret_code_t fds_record_find(uint16_t file_id, + uint16_t record_key, + fds_record_desc_t * const p_desc, + fds_find_token_t * const p_token) +{ + return record_find(&file_id, &record_key, p_desc, p_token); +} + + +ret_code_t fds_record_find_by_key(uint16_t record_key, + fds_record_desc_t * const p_desc, + fds_find_token_t * const p_token) +{ + return record_find(NULL, &record_key, p_desc, p_token); +} + + +ret_code_t fds_record_find_in_file(uint16_t file_id, + fds_record_desc_t * const p_desc, + fds_find_token_t * const p_token) +{ + return record_find(&file_id, NULL, p_desc, p_token); +} + + +ret_code_t fds_descriptor_from_rec_id(fds_record_desc_t * const p_desc, + uint32_t record_id) +{ + if (p_desc == NULL) + { + return FDS_ERR_NULL_ARG; + } + + // Zero the descriptor and set the record_id field. + memset(p_desc, 0x00, sizeof(fds_record_desc_t)); + p_desc->record_id = record_id; + + return NRF_SUCCESS; +} + + +ret_code_t fds_record_id_from_desc(fds_record_desc_t const * const p_desc, + uint32_t * const p_record_id) +{ + if ((p_desc == NULL) || (p_record_id == NULL)) + { + return FDS_ERR_NULL_ARG; + } + + *p_record_id = p_desc->record_id; + + return NRF_SUCCESS; +} + + +ret_code_t fds_stat(fds_stat_t * const p_stat) +{ + uint16_t const words_in_page = FDS_PAGE_SIZE; + // The largest number of free contiguous words on any page. + uint16_t contig_words = 0; + + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + if (p_stat == NULL) + { + return FDS_ERR_NULL_ARG; + } + + memset(p_stat, 0x00, sizeof(fds_stat_t)); + + p_stat->pages_available = FDS_VIRTUAL_PAGES; + + for (uint16_t page = 0; page < FDS_DATA_PAGES; page++) + { + uint16_t const words_used = m_pages[page].write_offset + m_pages[page].words_reserved; + + if (page_identify(m_pages[page].p_addr) == FDS_PAGE_UNDEFINED) + { + p_stat->pages_available--; + } + + p_stat->open_records += m_pages[page].records_open; + p_stat->words_reserved += m_pages[page].words_reserved; + p_stat->words_used += words_used; + + contig_words = (words_in_page - words_used); + if (contig_words > p_stat->largest_contig) + { + p_stat->largest_contig = contig_words; + } + + records_stat(page, + &p_stat->valid_records, + &p_stat->dirty_records, + &p_stat->freeable_words, + &p_stat->corruption); + } + + return NRF_SUCCESS; +} + +#endif //NRF_MODULE_ENABLED(FDS) diff --git a/components/libraries/fds/fds.h b/components/libraries/fds/fds.h new file mode 100644 index 0000000..054e1e1 --- /dev/null +++ b/components/libraries/fds/fds.h @@ -0,0 +1,703 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef FDS_H__ +#define FDS_H__ + +/** + * @defgroup fds Flash Data Storage + * @ingroup app_common + * @{ + * + * @brief Flash Data Storage (FDS). + * + * @details Flash Data Storage is a minimalistic, record-oriented file system for the on-chip + * flash. Files are stored as a collection of records of variable length. FDS supports + * synchronous read operations and asynchronous write operations (write, update, + * and delete). FDS can be used from multiple threads. + */ + +#include +#include +#include "sdk_errors.h" +#include "app_util_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Invalid file ID. + * + * This value must not be used as a file ID by the application. + */ +#define FDS_FILE_ID_INVALID (0xFFFF) + + +/**@brief Record key for deleted records. + * + * This key is used to flag a record as "dirty", which means that it should be removed during + * the next garbage collection. This value must not be used as a record key by the application. + */ +#define FDS_RECORD_KEY_DIRTY (0x0000) + + +/**@brief FDS return values. + */ +enum +{ + FDS_ERR_OPERATION_TIMEOUT = NRF_ERROR_FDS_ERR_BASE, //!< Error. The operation timed out. + FDS_ERR_NOT_INITIALIZED, //!< Error. The module has not been initialized. + FDS_ERR_UNALIGNED_ADDR, //!< Error. The input data is not aligned to a word boundary. + FDS_ERR_INVALID_ARG, //!< Error. The parameter contains invalid data. + FDS_ERR_NULL_ARG, //!< Error. The parameter is NULL. + FDS_ERR_NO_OPEN_RECORDS, //!< Error. The record is not open, so it cannot be closed. + FDS_ERR_NO_SPACE_IN_FLASH, //!< Error. There is no space in flash memory. + FDS_ERR_NO_SPACE_IN_QUEUES, //!< Error. There is no space in the internal queues. + FDS_ERR_RECORD_TOO_LARGE, //!< Error. The record exceeds the maximum allowed size. + FDS_ERR_NOT_FOUND, //!< Error. The record was not found. + FDS_ERR_NO_PAGES, //!< Error. No flash pages are available. + FDS_ERR_USER_LIMIT_REACHED, //!< Error. The maximum number of users has been reached. + FDS_ERR_CRC_CHECK_FAILED, //!< Error. The CRC check failed. + FDS_ERR_BUSY, //!< Error. The underlying flash subsystem was busy. + FDS_ERR_INTERNAL, //!< Error. An internal error occurred. +}; + + +/**@brief The record metadata as stored in flash. + * @warning Do not edit or reorder the fields in this structure. + */ +typedef struct +{ + uint16_t record_key; //!< The record key. + uint16_t length_words; //!< The length of the record data (in 4-byte words). + uint16_t file_id; //!< The ID of the file that the record belongs to. + uint16_t crc16; //!< CRC16-CCITT check value. + /* The CRC is calculated over the entire record as stored in flash, + * including the record metadata except the CRC field itself. + */ + uint32_t record_id; //!< The unique record ID (32 bits). +} fds_header_t; + + +/**@brief The record descriptor structure that is used to manipulate records. + * + * This structure is used by the FDS module. You must provide the descriptor to the module when + * you manipulate existing records. However, you should never modify it or use any of its fields. + * + * @note Never reuse the same descriptor for different records. + */ +typedef struct +{ + uint32_t record_id; //!< The unique record ID. + uint32_t const * p_record; //!< The last known location of the record in flash. + uint16_t gc_run_count; //!< Number of times garbage collection has been run. + bool record_is_open; //!< Whether the record is currently open. +} fds_record_desc_t; + + +/**@brief Structure that can be used to read the contents of a record stored in flash. + * + * This structure does not reflect the physical layout of a record in flash, but it points + * to the locations where the record header (metadata) and the record data are stored. + */ +typedef struct +{ + fds_header_t const * p_header; //!< Location of the record header in flash. + void const * p_data; //!< Location of the record data in flash. +} fds_flash_record_t; + + +/**@brief A record to be written to flash. */ +typedef struct +{ + uint16_t file_id; //!< The ID of the file that the record belongs to. + uint16_t key; //!< The record key. + struct + { + void const * p_data; + uint32_t length_words; + } data; +} fds_record_t; + + +/**@brief A token to a reserved space in flash, created by @ref fds_reserve. + * + * This token can be used to write the record in the reserved space (@ref fds_record_write_reserved) + * or to cancel the reservation (@ref fds_reserve_cancel). + */ +typedef struct +{ + uint16_t page; //!< The logical ID of the page where space was reserved. + uint16_t length_words; //!< The amount of space reserved (in 4-byte words). +} fds_reserve_token_t; + + +/**@brief A token to keep information about the progress of @ref fds_record_find, + * @ref fds_record_find_by_key, and @ref fds_record_find_in_file. + * + * @note Always zero-initialize the token before using it for the first time. + * @note Never reuse the same token to search for different records. + */ +typedef struct +{ + uint32_t const * p_addr; + uint16_t page; +} fds_find_token_t; + + +/**@brief FDS event IDs. + */ +typedef enum +{ + FDS_EVT_INIT, //!< Event for @ref fds_init. + FDS_EVT_WRITE, //!< Event for @ref fds_record_write and @ref fds_record_write_reserved. + FDS_EVT_UPDATE, //!< Event for @ref fds_record_update. + FDS_EVT_DEL_RECORD, //!< Event for @ref fds_record_delete. + FDS_EVT_DEL_FILE, //!< Event for @ref fds_file_delete. + FDS_EVT_GC //!< Event for @ref fds_gc. +} fds_evt_id_t; + + +ANON_UNIONS_ENABLE; + +/**@brief An FDS event. */ +typedef struct +{ + fds_evt_id_t id; //!< The event ID. See @ref fds_evt_id_t. + ret_code_t result; //!< The result of the operation related to this event. + union + { + struct + { + uint32_t record_id; + uint16_t file_id; + uint16_t record_key; + bool is_record_updated; + } write; //!< Information for @ref FDS_EVT_WRITE and @ref FDS_EVT_UPDATE events. + struct + { + uint32_t record_id; + uint16_t file_id; + uint16_t record_key; + } del; //!< Information for @ref FDS_EVT_DEL_RECORD and @ref FDS_EVT_DEL_FILE events. + }; +} fds_evt_t; + +ANON_UNIONS_DISABLE; + + +/**@brief File system statistics. */ +typedef struct +{ + uint16_t pages_available; //!< The number of pages available. + uint16_t open_records; //!< The number of open records. + uint16_t valid_records; //!< The number of valid records. + uint16_t dirty_records; //!< The number of deleted ("dirty") records. + uint16_t words_reserved; //!< The number of words reserved by @ref fds_reserve(). + + /**@brief The number of words written to flash, including those reserved for future writes. */ + uint16_t words_used; + + /**@brief The largest number of free contiguous words in the file system. + * + * This number indicates the largest record that can be stored by FDS. + * It takes into account all reservations for future writes. + */ + uint16_t largest_contig; + + /**@brief The largest number of words that can be reclaimed by garbage collection. + * + * The actual amount of space freed by garbage collection might be less than this value if + * records are open while garbage collection is run. + */ + uint16_t freeable_words; + + /**@brief Filesystem corruption has been detected. + * + * One or more corrupted records were detected. FDS will heal the filesystem automatically + * next time garbage collection is run, but some data may be lost. + * + * @note: This flag is unrelated to CRC failures. + */ + bool corruption; +} fds_stat_t; + + +/**@brief FDS event handler function prototype. + * + * @param p_evt The event. + */ +typedef void (*fds_cb_t)(fds_evt_t const * p_evt); + + +/**@brief Function for registering an FDS event handler. + * + * The maximum amount of handlers that can be registered can be configured by changing the value + * of @ref FDS_MAX_USERS in fds_config.h. + * + * @param[in] cb The event handler function. + * + * @retval NRF_SUCCESS If the event handler was registered successfully. + * @retval FDS_ERR_USER_LIMIT_REACHED If the maximum number of registered callbacks is reached. + */ +ret_code_t fds_register(fds_cb_t cb); + + +/**@brief Function for initializing the module. + * + * This function initializes the module and installs the file system (unless it is installed + * already). + * + * This function is asynchronous. Completion is reported through the @ref FDS_EVT_INIT event. + * Make sure to call @ref fds_register before calling @ref fds_init so that you receive + * @ref FDS_EVT_INIT. + * + * @retval NRF_SUCCESS If the operation was queued successfully. + * @retval FDS_ERR_NO_PAGES If there is no space available in flash memory to install the + * file system. + */ +ret_code_t fds_init(void); + + +/**@brief Function for writing a record to flash. + * + * There are no restrictions on the file ID and the record key, except that the record key must be + * different from @ref FDS_RECORD_KEY_DIRTY and the file ID must be different from + * @ref FDS_FILE_ID_INVALID. In particular, no restrictions are made regarding the uniqueness of + * the file ID or the record key. All records with the same file ID are grouped into one file. + * If no file with the specified ID exists, it is created. There can be multiple records with the + * same record key in a file. + * + * Some modules need exclusive use of certain file IDs and record keys. + * See @ref lib_fds_functionality_keys for details. + * + * Record data can consist of multiple chunks. The data must be aligned to a 4 byte boundary, and + * because it is not buffered internally, it must be kept in memory until the callback for the + * operation has been received. The length of the data must not exceed @ref FDS_VIRTUAL_PAGE_SIZE + * words minus 14 bytes. + * + * This function is asynchronous. Completion is reported through @ref FDS_EVT_WRITE event that is + * sent to the registered event handler function. + * + * @param[out] p_desc The descriptor of the record that was written. Pass NULL if you do not + * need the descriptor. + * @param[in] p_record The record to be written to flash. The record is required to be word + * aligned. + * + * @retval NRF_SUCCESS If the operation was queued successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_record is NULL. + * @retval FDS_ERR_INVALID_ARG If the file ID or the record key is invalid. + * @retval FDS_ERR_UNALIGNED_ADDR If the record data is not aligned to a 4 byte boundary. + * @retval FDS_ERR_RECORD_TOO_LARGE If the record data exceeds the maximum length. + * @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full or there are more record + * chunks than can be buffered. + * @retval FDS_ERR_NO_SPACE_IN_FLASH If there is not enough free space in flash to store the + * record. + */ +ret_code_t fds_record_write(fds_record_desc_t * p_desc, + fds_record_t const * p_record); + + +/**@brief Function for reserving space in flash. + * + * This function can be used to reserve space in flash memory. To write a record into the reserved + * space, use @ref fds_record_write_reserved. Alternatively, use @ref fds_reserve_cancel to cancel + * a reservation. + * + * Note that this function does not write any data to flash. + * + * @param[out] p_token A token that can be used to write a record in the reserved space or + * cancel the reservation. + * @param[in] length_words The length of the record data (in 4-byte words). + * + * @retval NRF_SUCCESS If the flash space was reserved successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_token is NULL instead of a valid token address. + * @retval FDS_ERR_RECORD_TOO_LARGE If the record length exceeds the maximum length. + * @retval FDS_ERR_NO_SPACE_IN_FLASH If there is not enough free space in flash to store the + * record. + */ +ret_code_t fds_reserve(fds_reserve_token_t * p_token, uint16_t length_words); + + +/**@brief Function for canceling an @ref fds_reserve operation. + * + * @param[in] p_token The token that identifies the reservation, produced by @ref fds_reserve. + * + * @retval NRF_SUCCESS If the reservation was canceled. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_token is NULL instead of a valid token address. + * @retval FDS_ERR_INVALID_ARG If @p p_token contains invalid data. + */ +ret_code_t fds_reserve_cancel(fds_reserve_token_t * p_token); + + +/**@brief Function for writing a record to a space in flash that was reserved using + * @ref fds_reserve. + * + * There are no restrictions on the file ID and the record key, except that the record key must be + * different from @ref FDS_RECORD_KEY_DIRTY and the file ID must be different from + * @ref FDS_FILE_ID_INVALID. In particular, no restrictions are made regarding the uniqueness of + * the file ID or the record key. All records with the same file ID are grouped into one file. + * If no file with the specified ID exists, it is created. There can be multiple records with the + * same record key in a file. + * + * Record data can consist of multiple chunks. The data must be aligned to a 4 byte boundary, and + * because it is not buffered internally, it must be kept in memory until the callback for the + * operation has been received. The length of the data must not exceed @ref FDS_VIRTUAL_PAGE_SIZE + * words minus 14 bytes. + * + * This function is asynchronous. Completion is reported through an event that is sent to the + * registered event handler function. + * + * @note + * This function behaves similarly to @ref fds_record_write, with the exception that it never + * fails with the error @ref FDS_ERR_NO_SPACE_IN_FLASH. + * + * @param[out] p_desc The descriptor of the record that was written. Pass NULL if you do not + * need the descriptor. + * @param[in] p_record The record to be written to flash. The record is required + * to be word aligned. + * @param[in] p_token The token that identifies the space reserved in flash. + * + * @retval NRF_SUCCESS If the operation was queued successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_token is NULL instead of a valid token address. + * @retval FDS_ERR_INVALID_ARG If the file ID or the record key is invalid. + * @retval FDS_ERR_UNALIGNED_ADDR If the record data is not aligned to a 4 byte boundary. + * @retval FDS_ERR_RECORD_TOO_LARGE If the record data exceeds the maximum length. + * @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full or there are more record + * chunks than can be buffered. + */ +ret_code_t fds_record_write_reserved(fds_record_desc_t * p_desc, + fds_record_t const * p_record, + fds_reserve_token_t const * p_token); + + +/**@brief Function for deleting a record. + * + * Deleted records cannot be located using @ref fds_record_find, @ref fds_record_find_by_key, or + * @ref fds_record_find_in_file. Additionally, they can no longer be opened using + * @ref fds_record_open. + * + * Note that deleting a record does not free the space it occupies in flash memory. + * To reclaim flash space used by deleted records, call @ref fds_gc to run garbage collection. + * + * This function is asynchronous. Completion is reported through the @ref FDS_EVT_DEL_RECORD event + * that is sent to the registered event handler function. + * + * @param[in] p_desc The descriptor of the record that should be deleted. + * + * @retval NRF_SUCCESS If the operation was queued successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If the specified record descriptor @p p_desc is NULL. + * @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full. + */ +ret_code_t fds_record_delete(fds_record_desc_t * p_desc); + + +/**@brief Function for deleting all records in a file. + * + * This function deletes a file, including all its records. Deleted records cannot be located + * using @ref fds_record_find, @ref fds_record_find_by_key, or @ref fds_record_find_in_file. + * Additionally, they can no longer be opened using @ref fds_record_open. + * + * Note that deleting records does not free the space they occupy in flash memory. + * To reclaim flash space used by deleted records, call @ref fds_gc to run garbage collection. + * + * This function is asynchronous. Completion is reported through the @ref FDS_EVT_DEL_FILE event + * that is sent to the registered event handler function. + * + * @param[in] file_id The ID of the file to be deleted. + * + * @retval NRF_SUCCESS If the operation was queued successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_INVALID_ARG If the specified @p file_id is invalid. + * @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full. + */ +ret_code_t fds_file_delete(uint16_t file_id); + + +/**@brief Function for updating a record. + * + * Updating a record first writes a new record (@p p_record) to flash and then deletes the + * old record (identified by @p p_desc). + * + * There are no restrictions on the file ID and the record key, except that the record key must be + * different from @ref FDS_RECORD_KEY_DIRTY and the file ID must be different from + * @ref FDS_FILE_ID_INVALID. In particular, no restrictions are made regarding the uniqueness of + * the file ID or the record key. All records with the same file ID are grouped into one file. + * If no file with the specified ID exists, it is created. There can be multiple records with the + * same record key in a file. + * + * Record data can consist of multiple chunks. The data must be aligned to a 4 byte boundary, and + * because it is not buffered internally, it must be kept in memory until the callback for the + * operation has been received. The length of the data must not exceed @ref FDS_VIRTUAL_PAGE_SIZE + * words minus 14 bytes. + * + * This function is asynchronous. Completion is reported through the @ref FDS_EVT_UPDATE event + * that is sent to the registered event handler function. + * + * @param[in, out] p_desc The descriptor of the record to update. When the function + * returns with NRF_SUCCESS, this parameter contains the + * descriptor of the newly written record. + * @param[in] p_record The updated record to be written to flash. The record is required + * to be word aligned. + * + * @retval NRF_SUCCESS If the operation was queued successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_INVALID_ARG If the file ID or the record key is invalid. + * @retval FDS_ERR_UNALIGNED_ADDR If the record data is not aligned to a 4 byte boundary. + * @retval FDS_ERR_RECORD_TOO_LARGE If the record data exceeds the maximum length. + * @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full or there are more record + * chunks than can be buffered. + * @retval FDS_ERR_NO_SPACE_IN_FLASH If there is not enough free space in flash to store the + * updated record. + */ +ret_code_t fds_record_update(fds_record_desc_t * p_desc, + fds_record_t const * p_record); + + +/**@brief Function for iterating through all records in flash. + * + * To search for the next record, call the function again and supply the same @ref fds_find_token_t + * structure to resume searching from the last record that was found. + * + * Note that the order with which records are iterated is not defined. + * + * @param[out] p_desc The descriptor of the record that was found. + * @param[out] p_token A token containing information about the progress of the operation. + * + * @retval NRF_SUCCESS If a record was found. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_token is NULL. + * @retval FDS_ERR_NOT_FOUND If no matching record was found. + */ +ret_code_t fds_record_iterate(fds_record_desc_t * p_desc, + fds_find_token_t * p_token); + + +/**@brief Function for searching for records with a given record key in a file. + * + * This function finds the first record in a file that has the given record key. To search for the + * next record with the same key in the file, call the function again and supply the same + * @ref fds_find_token_t structure to resume searching from the last record that was found. + * + * @param[in] file_id The file ID. + * @param[in] record_key The record key. + * @param[out] p_desc The descriptor of the record that was found. + * @param[out] p_token A token containing information about the progress of the operation. + * + * @retval NRF_SUCCESS If a record was found. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_token is NULL. + * @retval FDS_ERR_NOT_FOUND If no matching record was found. + */ +ret_code_t fds_record_find(uint16_t file_id, + uint16_t record_key, + fds_record_desc_t * p_desc, + fds_find_token_t * p_token); + + +/**@brief Function for searching for records with a given record key. + * + * This function finds the first record with a given record key, independent of the file it + * belongs to. To search for the next record with the same key, call the function again and supply + * the same @ref fds_find_token_t structure to resume searching from the last record that was found. + * + * @param[in] record_key The record key. + * @param[out] p_desc The descriptor of the record that was found. + * @param[out] p_token A token containing information about the progress of the operation. + * + * @retval NRF_SUCCESS If a record was found. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_token is NULL. + * @retval FDS_ERR_NOT_FOUND If no record with the given key was found. + */ +ret_code_t fds_record_find_by_key(uint16_t record_key, + fds_record_desc_t * p_desc, + fds_find_token_t * p_token); + + +/**@brief Function for searching for any record in a file. + * + * This function finds the first record in a file, independent of its record key. + * To search for the next record in the same file, call the function again and supply the same + * @ref fds_find_token_t structure to resume searching from the last record that was found. + * + * @param[in] file_id The file ID. + * @param[out] p_desc The descriptor of the record that was found. + * @param[out] p_token A token containing information about the progress of the operation. + * + * @retval NRF_SUCCESS If a record was found. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_token is NULL. + * @retval FDS_ERR_NOT_FOUND If no matching record was found. + */ +ret_code_t fds_record_find_in_file(uint16_t file_id, + fds_record_desc_t * p_desc, + fds_find_token_t * p_token); + + +/**@brief Function for opening a record for reading. + * + * This function opens a record that is stored in flash, so that it can be read. The function + * initializes an @ref fds_flash_record_t structure, which can be used to access the record data as + * well as its associated metadata. The pointers provided in the @ref fds_flash_record_t structure + * are pointers to flash memory. + * + * Opening a record with @ref fds_record_open prevents garbage collection to run on the virtual + * flash page in which record is stored, so that the contents of the memory pointed by fields in + * @ref fds_flash_record_t are guaranteed to remain unmodified as long as the record is kept open. + * + * When you are done reading a record, call @ref fds_record_close to close it. Garbage collection + * can then reclaim space on the virtual page where the record is stored. Note that you must + * provide the same descriptor for @ref fds_record_close as you did for this function. + * + * @param[in] p_desc The descriptor of the record to open. + * @param[out] p_flash_record The record, as stored in flash. + * + * @retval NRF_SUCCESS If the record was opened successfully. + * @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_flash_record is NULL. + * @retval FDS_ERR_NOT_FOUND If the record was not found. It might have been deleted, or + * it might not have been written yet. + * @retval FDS_ERR_CRC_CHECK_FAILED If the CRC check for the record failed. + */ +ret_code_t fds_record_open(fds_record_desc_t * p_desc, + fds_flash_record_t * p_flash_record); + + +/**@brief Function for closing a record. + * + * Closing a record allows garbage collection to run on the virtual page in which the record is + * stored (if no other records remain open on that page). The descriptor passed as an argument + * must be the same as the one used to open the record using @ref fds_record_open. + * + * Note that closing a record does not invalidate its descriptor. You can still supply the + * descriptor to all functions that accept a record descriptor as a parameter. + * + * @param[in] p_desc The descriptor of the record to close. + * + * @retval NRF_SUCCESS If the record was closed successfully. + * @retval FDS_ERR_NULL_ARG If @p p_desc is NULL. + * @retval FDS_ERR_NO_OPEN_RECORDS If the record is not open. + * @retval FDS_ERR_NOT_FOUND If the record could not be found. + */ +ret_code_t fds_record_close(fds_record_desc_t * p_desc); + + +/**@brief Function for running garbage collection. + * + * Garbage collection reclaims the flash space that is occupied by records that have been deleted, + * or that failed to be completely written due to, for example, a power loss. + * + * This function is asynchronous. Completion is reported through the @ref FDS_EVT_GC event that + * is sent to the registered event handler function. + * + * @retval NRF_SUCCESS If the operation was queued successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full. + */ +ret_code_t fds_gc(void); + + +/**@brief Function for obtaining a descriptor from a record ID. + * + * This function can be used to reconstruct a descriptor from a record ID, like the one that is + * passed to the callback function. + * + * @note + * This function does not check whether a record with the given record ID exists. + * If a non-existing record ID is supplied, the resulting descriptor is invalid and will cause + * other functions to fail when it is supplied as parameter. + * + * @param[out] p_desc The descriptor of the record with the given record ID. + * @param[in] record_id The record ID for which a descriptor should be returned. + * + * @retval NRF_SUCCESS If a descriptor was returned. + * @retval FDS_ERR_NULL_ARG If @p p_desc is NULL. + */ +ret_code_t fds_descriptor_from_rec_id(fds_record_desc_t * p_desc, + uint32_t record_id); + + +/**@brief Function for obtaining a record ID from a record descriptor. + * + * This function can be used to extract a record ID from a descriptor. For example, you could use + * it in the callback function to compare the record ID of an event to the record IDs of the + * records for which you have a descriptor. + * + * @warning + * This function does not check whether the record descriptor is valid. If the descriptor is not + * initialized or has been tampered with, the resulting record ID might be invalid. + * + * @param[in] p_desc The descriptor from which the record ID should be extracted. + * @param[out] p_record_id The record ID that is contained in the given descriptor. + * + * @retval NRF_SUCCESS If a record ID was returned. + * @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_record_id is NULL. + */ +ret_code_t fds_record_id_from_desc(fds_record_desc_t const * p_desc, + uint32_t * p_record_id); + + +/**@brief Function for retrieving file system statistics. + * + * This function retrieves file system statistics, such as the number of open records, the space + * that can be reclaimed by garbage collection, and others. + * + * @param[out] p_stat File system statistics. + * + * @retval NRF_SUCCESS If the statistics were returned successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_stat is NULL. + */ +ret_code_t fds_stat(fds_stat_t * p_stat); + + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif // FDS_H__ diff --git a/components/libraries/fds/fds_internal_defs.h b/components/libraries/fds/fds_internal_defs.h new file mode 100644 index 0000000..8793431 --- /dev/null +++ b/components/libraries/fds/fds_internal_defs.h @@ -0,0 +1,329 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef FDS_INTERNAL_DEFS_H__ +#define FDS_INTERNAL_DEFS_H__ +#include "sdk_config.h" +#include +#include + +#if defined (FDS_THREADS) + #include "nrf_soc.h" + #include "app_util_platform.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define FDS_PAGE_TAG_SIZE (2) // Page tag size, in 4-byte words. +#define FDS_PAGE_TAG_WORD_0 (0) // Offset of the first word in the page tag from the page address. +#define FDS_PAGE_TAG_WORD_1 (1) // Offset of the second word in the page tag from the page address. + +// Page tag constants +#define FDS_PAGE_TAG_MAGIC (0xDEADC0DE) +#define FDS_PAGE_TAG_SWAP (0xF11E01FF) +#define FDS_PAGE_TAG_DATA (0xF11E01FE) + +#define FDS_ERASED_WORD (0xFFFFFFFF) + +#define FDS_OFFSET_TL (0) // Offset of TL from the record base address, in 4-byte words. +#define FDS_OFFSET_IC (1) // Offset of IC from the record base address, in 4-byte words. +#define FDS_OFFSET_ID (2) // Offset of ID from the record base address, in 4-byte words. +#define FDS_OFFSET_DATA (3) // Offset of the data from the record base address, in 4-byte words. + +#define FDS_HEADER_SIZE_TL (1) // Size of the TL part of the header, in 4-byte words. +#define FDS_HEADER_SIZE_IC (1) // Size of the IC part of the header, in 4-byte words. +#define FDS_HEADER_SIZE_ID (1) // Size of the record ID in the header, in 4-byte words. +#define FDS_HEADER_SIZE (3) // Size of the whole header, in 4-byte words. + +#define FDS_OP_EXECUTING (NRF_SUCCESS) +#define FDS_OP_COMPLETED (0x1D1D) + +#define NRF_FSTORAGE_NVMC 1 +#define NRF_FSTORAGE_SD 2 + +// The size of a physical page, in 4-byte words. +#if defined(NRF51) + #define FDS_PHY_PAGE_SIZE (256) +#else + #define FDS_PHY_PAGE_SIZE (1024) +#endif + +// The number of physical pages to be used. This value is configured indirectly. +#define FDS_PHY_PAGES ((FDS_VIRTUAL_PAGES * FDS_VIRTUAL_PAGE_SIZE) / FDS_PHY_PAGE_SIZE) + +// The number of physical pages at the end of the flash that are reserved by other modules. +#define FDS_PHY_PAGES_RESERVED ((FDS_VIRTUAL_PAGES_RESERVED * FDS_VIRTUAL_PAGE_SIZE) / FDS_PHY_PAGE_SIZE) + +// The size of a virtual page, in number of physical pages. +#define FDS_PHY_PAGES_IN_VPAGE (FDS_VIRTUAL_PAGE_SIZE / FDS_PHY_PAGE_SIZE) + +// The number of pages available to store data; which is the total minus one (the swap). +#define FDS_DATA_PAGES (FDS_VIRTUAL_PAGES - 1) + + // Just a shorter name for the size, in words, of a virtual page. +#define FDS_PAGE_SIZE (FDS_VIRTUAL_PAGE_SIZE) + +#if (FDS_VIRTUAL_PAGE_SIZE % FDS_PHY_PAGE_SIZE != 0) + #error "FDS_VIRTUAL_PAGE_SIZE must be a multiple of the size of a physical page." +#endif + +#if (FDS_VIRTUAL_PAGES < 2) + #error "FDS requires at least two virtual pages." +#endif + + +// Page types. +typedef enum +{ + FDS_PAGE_DATA, // Page is ready for storage. + FDS_PAGE_SWAP, // Page is reserved for garbage collection. + FDS_PAGE_ERASED, // Page is erased. + FDS_PAGE_UNDEFINED, // Undefined page type. +} fds_page_type_t; + + +typedef enum +{ + FDS_HEADER_VALID, // Valid header. + FDS_HEADER_DIRTY, // Header is incomplete, or record has been deleted. + FDS_HEADER_CORRUPT // Header contains corrupt information, not related to CRC. +} fds_header_status_t; + + +typedef struct +{ + fds_page_type_t page_type; // The page type. + uint32_t const * p_addr; // The address of the page. + uint16_t write_offset; // The page write offset, in 4-byte words. + uint16_t words_reserved; // The amount of words reserved. + uint32_t volatile records_open; // The number of open records. + bool can_gc; // Indicates that there are some records that have been deleted. +} fds_page_t; + + +typedef struct +{ + uint32_t const * p_addr; + uint16_t write_offset; +} fds_swap_page_t; + + +// FDS op-codes. +typedef enum +{ + FDS_OP_NONE, + FDS_OP_INIT, // Initialize the module. + FDS_OP_WRITE, // Write a record to flash. + FDS_OP_UPDATE, // Update a record. + FDS_OP_DEL_RECORD, // Delete a record. + FDS_OP_DEL_FILE, // Delete a file. + FDS_OP_GC // Run garbage collection. +} fds_op_code_t; + + +typedef enum +{ + FDS_OP_INIT_TAG_SWAP, + FDS_OP_INIT_TAG_DATA, + FDS_OP_INIT_ERASE_SWAP, + FDS_OP_INIT_PROMOTE_SWAP, +} fds_init_step_t; + + +typedef enum +{ + FDS_OP_WRITE_HEADER_BEGIN, // Write the record key and length. + FDS_OP_WRITE_HEADER_FINALIZE, // Write the file ID and CRC. + FDS_OP_WRITE_RECORD_ID, // Write the record ID. + FDS_OP_WRITE_DATA, // Write the record data. + FDS_OP_WRITE_FIND_RECORD, + FDS_OP_WRITE_FLAG_DIRTY, // Flag a record as dirty (as part of an update operation). + FDS_OP_WRITE_DONE, +} fds_write_step_t; + + +typedef enum +{ + FDS_OP_DEL_RECORD_FLAG_DIRTY, // Flag a record as dirty. + FDS_OP_DEL_FILE_FLAG_DIRTY, // Flag multiple records as dirty. + FDS_OP_DEL_DONE, +} fds_delete_step_t; + + +#if defined(__CC_ARM) + #pragma push + #pragma anon_unions +#elif defined(__ICCARM__) + #pragma language=extended +#elif defined(__GNUC__) + // anonymous unions are enabled by default +#endif + +typedef struct +{ + fds_op_code_t op_code; // The opcode for the operation. + union + { + struct + { + fds_init_step_t step; // The current step the operation is at. + } init; + struct + { + fds_header_t header; + void const * p_data; + uint16_t page; // The page the flash space for this command was reserved. + fds_write_step_t step; // The current step the operation is at. + uint32_t record_to_delete; // The record to delete in case this is an update. + } write; + struct + { + fds_delete_step_t step; + uint16_t file_id; + uint16_t record_key; + uint32_t record_to_delete; + } del; + }; +} fds_op_t; + +#if defined(__CC_ARM) + #pragma pop +#elif defined(__ICCARM__) + // leave anonymous unions enabled +#elif defined(__GNUC__) + // anonymous unions are enabled by default +#endif + + +enum +{ + PAGE_ERASED = 0x1, // One or more erased pages found. + PAGE_DATA = 0x2, // One or more data pages found. + PAGE_SWAP_CLEAN = 0x4, // A clean (empty) swap page was found. + PAGE_SWAP_DIRTY = 0x8, // A dirty (non-empty) swap page was found. +}; + + +typedef enum +{ + // No erased pages or FDS pages found. + // This is a fatal error. + NO_PAGES, + + // The filesystem can not be garbage collected. + // This is a fatal error. + NO_SWAP = (PAGE_DATA), + + // Perform a fresh installation. + FRESH_INSTALL = (PAGE_ERASED), + + // Tag an erased page as swap. + TAG_SWAP = (PAGE_ERASED | PAGE_DATA), + + // Tag all erased pages as data. + TAG_DATA = (PAGE_ERASED | PAGE_SWAP_CLEAN), + + // Tag all remaining erased pages as data. + TAG_DATA_INST = (PAGE_ERASED | PAGE_DATA | PAGE_SWAP_CLEAN), + + // The swap is dirty, likely because the device powered off during GC. + // Because there is also an erased page, assume that that page has been garbage collected. + // Hence, tag the swap as data (promote), an erased page as swap and remaining pages as data. + PROMOTE_SWAP = (PAGE_ERASED | PAGE_SWAP_DIRTY), + + // Tag the swap as data (promote), an erased page as swap and remaining pages as data. + PROMOTE_SWAP_INST = (PAGE_ERASED | PAGE_DATA | PAGE_SWAP_DIRTY), + + // The swap is dirty (written) and there are no erased pages. It is likely that the device + // powered off during GC. It is safe to discard (erase) the swap, since data that was + // swapped out still lies in one of the valid pages. + DISCARD_SWAP = (PAGE_DATA | PAGE_SWAP_DIRTY), + + // Do nothing. + ALREADY_INSTALLED = (PAGE_DATA | PAGE_SWAP_CLEAN), + +} fds_init_opts_t; + + +typedef enum +{ + GC_BEGIN, // Begin GC. + GC_NEXT_PAGE, // GC a page. + GC_FIND_NEXT_RECORD, // Find a valid record to copy. + GC_COPY_RECORD, // Copy a valid record to swap. + GC_ERASE_PAGE, // Erase the page being garbage collected. + GC_DISCARD_SWAP, // Erase (discard) the swap page. + GC_PROMOTE_SWAP, // Tag the swap as valid. + GC_TAG_NEW_SWAP // Tag a freshly erased (GCed) page as swap. +} fds_gc_state_t; + + +// Holds garbage collection status and related data. +typedef struct +{ + fds_gc_state_t state; // The current GC step. + uint16_t cur_page; // The current page being garbage collected. + uint32_t const * p_record_src; // The current record being copied to swap. + uint16_t run_count; // Total number of times GC was run. + bool do_gc_page[FDS_DATA_PAGES]; // Controls which pages to garbage collect. + bool resume; // Whether or not GC should be resumed. +} fds_gc_data_t; + + +// Macros to enable and disable application interrupts. +#if defined (FDS_THREADS) + + #define CRITICAL_SECTION_ENTER() CRITICAL_REGION_ENTER() + #define CRITICAL_SECTION_EXIT() CRITICAL_REGION_EXIT() + +#else + + #define CRITICAL_SECTION_ENTER() + #define CRITICAL_SECTION_EXIT() + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // FDS_INTERNAL_DEFS_H__ diff --git a/components/libraries/fifo/app_fifo.c b/components/libraries/fifo/app_fifo.c new file mode 100644 index 0000000..b0634a9 --- /dev/null +++ b/components/libraries/fifo/app_fifo.c @@ -0,0 +1,214 @@ +/** + * Copyright (c) 2013 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(APP_FIFO) +#include "app_fifo.h" + +static __INLINE uint32_t fifo_length(app_fifo_t * p_fifo) +{ + uint32_t tmp = p_fifo->read_pos; + return p_fifo->write_pos - tmp; +} + + +#define FIFO_LENGTH() fifo_length(p_fifo) /**< Macro for calculating the FIFO length. */ + + +/**@brief Put one byte to the FIFO. */ +static __INLINE void fifo_put(app_fifo_t * p_fifo, uint8_t byte) +{ + p_fifo->p_buf[p_fifo->write_pos & p_fifo->buf_size_mask] = byte; + p_fifo->write_pos++; +} + + +/**@brief Look at one byte in the FIFO. */ +static __INLINE void fifo_peek(app_fifo_t * p_fifo, uint16_t index, uint8_t * p_byte) +{ + *p_byte = p_fifo->p_buf[(p_fifo->read_pos + index) & p_fifo->buf_size_mask]; +} + + +/**@brief Get one byte from the FIFO. */ +static __INLINE void fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte) +{ + fifo_peek(p_fifo, 0, p_byte); + p_fifo->read_pos++; +} + + +uint32_t app_fifo_init(app_fifo_t * p_fifo, uint8_t * p_buf, uint16_t buf_size) +{ + // Check buffer for null pointer. + if (p_buf == NULL) + { + return NRF_ERROR_NULL; + } + + // Check that the buffer size is a power of two. + if (!IS_POWER_OF_TWO(buf_size)) + { + return NRF_ERROR_INVALID_LENGTH; + } + + p_fifo->p_buf = p_buf; + p_fifo->buf_size_mask = buf_size - 1; + p_fifo->read_pos = 0; + p_fifo->write_pos = 0; + + return NRF_SUCCESS; +} + + +uint32_t app_fifo_put(app_fifo_t * p_fifo, uint8_t byte) +{ + if (FIFO_LENGTH() <= p_fifo->buf_size_mask) + { + fifo_put(p_fifo, byte); + return NRF_SUCCESS; + } + + return NRF_ERROR_NO_MEM; +} + + +uint32_t app_fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte) +{ + if (FIFO_LENGTH() != 0) + { + fifo_get(p_fifo, p_byte); + return NRF_SUCCESS; + } + + return NRF_ERROR_NOT_FOUND; + +} + + +uint32_t app_fifo_peek(app_fifo_t * p_fifo, uint16_t index, uint8_t * p_byte) +{ + if (FIFO_LENGTH() > index) + { + fifo_peek(p_fifo, index, p_byte); + return NRF_SUCCESS; + } + + return NRF_ERROR_NOT_FOUND; +} + + +uint32_t app_fifo_flush(app_fifo_t * p_fifo) +{ + p_fifo->read_pos = p_fifo->write_pos; + return NRF_SUCCESS; +} + + +uint32_t app_fifo_read(app_fifo_t * p_fifo, uint8_t * p_byte_array, uint32_t * p_size) +{ + VERIFY_PARAM_NOT_NULL(p_fifo); + VERIFY_PARAM_NOT_NULL(p_size); + + const uint32_t byte_count = fifo_length(p_fifo); + const uint32_t requested_len = (*p_size); + uint32_t index = 0; + uint32_t read_size = MIN(requested_len, byte_count); + + (*p_size) = byte_count; + + // Check if the FIFO is empty. + if (byte_count == 0) + { + return NRF_ERROR_NOT_FOUND; + } + + // Check if application has requested only the size. + if (p_byte_array == NULL) + { + return NRF_SUCCESS; + } + + // Fetch bytes from the FIFO. + while (index < read_size) + { + fifo_get(p_fifo, &p_byte_array[index++]); + } + + (*p_size) = read_size; + + return NRF_SUCCESS; +} + + +uint32_t app_fifo_write(app_fifo_t * p_fifo, uint8_t const * p_byte_array, uint32_t * p_size) +{ + VERIFY_PARAM_NOT_NULL(p_fifo); + VERIFY_PARAM_NOT_NULL(p_size); + + const uint32_t available_count = p_fifo->buf_size_mask - fifo_length(p_fifo) + 1; + const uint32_t requested_len = (*p_size); + uint32_t index = 0; + uint32_t write_size = MIN(requested_len, available_count); + + (*p_size) = available_count; + + // Check if the FIFO is FULL. + if (available_count == 0) + { + return NRF_ERROR_NO_MEM; + } + + // Check if application has requested only the size. + if (p_byte_array == NULL) + { + return NRF_SUCCESS; + } + + //Fetch bytes from the FIFO. + while (index < write_size) + { + fifo_put(p_fifo, p_byte_array[index++]); + } + + (*p_size) = write_size; + + return NRF_SUCCESS; +} +#endif //NRF_MODULE_ENABLED(APP_FIFO) diff --git a/components/libraries/fifo/app_fifo.h b/components/libraries/fifo/app_fifo.h new file mode 100644 index 0000000..00cd4d6 --- /dev/null +++ b/components/libraries/fifo/app_fifo.h @@ -0,0 +1,181 @@ +/** + * Copyright (c) 2013 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup app_fifo FIFO implementation + * @{ + * @ingroup app_common + * + * @brief FIFO implementation. + */ + +#ifndef APP_FIFO_H__ +#define APP_FIFO_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief A FIFO instance structure. + * @details Keeps track of which bytes to read and write next. + * Also, it keeps the information about which memory is allocated for the buffer + * and its size. This structure must be initialized by app_fifo_init() before use. + */ +typedef struct +{ + uint8_t * p_buf; /**< Pointer to FIFO buffer memory. */ + uint16_t buf_size_mask; /**< Read/write index mask. Also used for size checking. */ + volatile uint32_t read_pos; /**< Next read position in the FIFO buffer. */ + volatile uint32_t write_pos; /**< Next write position in the FIFO buffer. */ +} app_fifo_t; + +/**@brief Function for initializing the FIFO. + * + * @param[out] p_fifo FIFO object. + * @param[in] p_buf FIFO buffer for storing data. The buffer size must be a power of two. + * @param[in] buf_size Size of the FIFO buffer provided. This size must be a power of two. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_NULL If a NULL pointer is provided as buffer. + * @retval NRF_ERROR_INVALID_LENGTH If size of buffer provided is not a power of two. + */ +uint32_t app_fifo_init(app_fifo_t * p_fifo, uint8_t * p_buf, uint16_t buf_size); + +/**@brief Function for adding an element to the FIFO. + * + * @param[in] p_fifo Pointer to the FIFO. + * @param[in] byte Data byte to add to the FIFO. + * + * @retval NRF_SUCCESS If an element has been successfully added to the FIFO. + * @retval NRF_ERROR_NO_MEM If the FIFO is full. + */ +uint32_t app_fifo_put(app_fifo_t * p_fifo, uint8_t byte); + +/**@brief Function for getting the next element from the FIFO. + * + * @param[in] p_fifo Pointer to the FIFO. + * @param[out] p_byte Byte fetched from the FIFO. + * + * @retval NRF_SUCCESS If an element was returned. + * @retval NRF_ERROR_NOT_FOUND If there are no more elements in the queue. + */ +uint32_t app_fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte); + +/**@brief Function for looking at an element in the FIFO, without consuming it. + * + * @param[in] p_fifo Pointer to the FIFO. + * @param[in] index Which element to look at. The lower the index, the earlier it was put. + * @param[out] p_byte Byte fetched from the FIFO. + * + * @retval NRF_SUCCESS If an element was returned. + * @retval NRF_ERROR_NOT_FOUND If there are no more elements in the queue, or the index was + * too large. + */ +uint32_t app_fifo_peek(app_fifo_t * p_fifo, uint16_t index, uint8_t * p_byte); + +/**@brief Function for flushing the FIFO. + * + * @param[in] p_fifo Pointer to the FIFO. + * + * @retval NRF_SUCCESS If the FIFO was flushed successfully. + */ +uint32_t app_fifo_flush(app_fifo_t * p_fifo); + +/**@brief Function for reading bytes from the FIFO. + * + * This function can also be used to get the number of bytes in the FIFO. + * + * @param[in] p_fifo Pointer to the FIFO. Must not be NULL. + * @param[out] p_byte_array Memory pointer where the read bytes are fetched from the FIFO. + * Can be NULL. If NULL, the number of bytes that can be read in the FIFO + * are returned in the p_size parameter. + * @param[inout] p_size Address to memory indicating the maximum number of bytes to be read. + * The provided memory is overwritten with the actual number of bytes + * read if the procedure was successful. This field must not be NULL. + * If p_byte_array is set to NULL by the application, this parameter + * returns the number of bytes in the FIFO. + * + * @retval NRF_SUCCESS If the procedure is successful. The actual number of bytes read might + * be less than the requested maximum, depending on how many elements exist + * in the FIFO. Even if less bytes are returned, the procedure is considered + * successful. + * @retval NRF_ERROR_NULL If a NULL parameter was passed for a parameter that must not + * be NULL. + * @retval NRF_ERROR_NOT_FOUND If the FIFO is empty. + */ +uint32_t app_fifo_read(app_fifo_t * p_fifo, uint8_t * p_byte_array, uint32_t * p_size); + +/**@brief Function for writing bytes to the FIFO. + * + * This function can also be used to get the available size on the FIFO. + * + * @param[in] p_fifo Pointer to the FIFO. Must not be NULL. + * @param[in] p_byte_array Memory pointer containing the bytes to be written to the FIFO. + * Can be NULL. If NULL, this function returns the number of bytes + * that can be written to the FIFO. + * @param[inout] p_size Address to memory indicating the maximum number of bytes to be written. + * The provided memory is overwritten with the number of bytes that were actually + * written if the procedure is successful. This field must not be NULL. + * If p_byte_array is set to NULL by the application, this parameter + * returns the number of bytes available in the FIFO. + * + * @retval NRF_SUCCESS If the procedure is successful. The actual number of bytes written might + * be less than the requested maximum, depending on how much room there is in + * the FIFO. Even if less bytes are written, the procedure is considered + * successful. If the write was partial, the application should use + * subsequent calls to attempt writing the data again. + * @retval NRF_ERROR_NULL If a NULL parameter was passed for a parameter that must not + * be NULL. + * @retval NRF_ERROR_NO_MEM If the FIFO is full. + * + */ +uint32_t app_fifo_write(app_fifo_t * p_fifo, uint8_t const * p_byte_array, uint32_t * p_size); + + +#ifdef __cplusplus +} +#endif + +#endif // APP_FIFO_H__ + +/** @} */ diff --git a/components/libraries/fstorage/nrf_fstorage.c b/components/libraries/fstorage/nrf_fstorage.c new file mode 100644 index 0000000..2e235eb --- /dev/null +++ b/components/libraries/fstorage/nrf_fstorage.c @@ -0,0 +1,244 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_config.h" + +#if NRF_FSTORAGE_ENABLED + +#include "nrf_fstorage.h" +#include +#include +#include "sdk_errors.h" +#include "sdk_macros.h" +#include "nrf_section.h" + +#define NRF_LOG_MODULE_NAME nrf_fstorage +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +/* Create the section "fs_data". */ +NRF_SECTION_DEF(fs_data, nrf_fstorage_t); + + +/**@brief Macro to handle user input validation. + * + * If @p _cond evaluates to true, does nothing. Otherwise, + * if the NRF_FSTORAGE_PARAM_CHECK_DISABLED is not set, logs an error message and returns @p _err. + * If the NRF_FSTORAGE_PARAM_CHECK_DISABLED is set, behaves like the @ref ASSERT macro. + * + * Parameter checking implemented using this macro can be optionally turned off for release code. + * Only disable runtime parameter checks if size if a major concern. + * + * @param _cond The condition to be evaluated. + * @param _err The error code to be returned. + */ +#define NRF_FSTORAGE_PARAM_CHECK(_cond, _err) \ + NRF_PARAM_CHECK(NRF_FSTORAGE, _cond, _err, NRF_LOG_ERROR) + + +static bool addr_is_aligned32(uint32_t addr); +static bool addr_is_page_aligned(nrf_fstorage_t const * p_fs, uint32_t addr); +static bool addr_is_within_bounds(nrf_fstorage_t const * p_fs, uint32_t addr, uint32_t len); + + +ret_code_t nrf_fstorage_init(nrf_fstorage_t * p_fs, + nrf_fstorage_api_t * p_api, + void * p_param) +{ + NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL); + NRF_FSTORAGE_PARAM_CHECK(p_api, NRF_ERROR_NULL); + + p_fs->p_api = p_api; + + return (p_fs->p_api)->init(p_fs, p_param); +} + + +ret_code_t nrf_fstorage_uninit(nrf_fstorage_t * p_fs, + void * p_param) +{ + ret_code_t rc; + + NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL); + NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE); + + rc = (p_fs->p_api)->uninit(p_fs, p_param); + + /* Uninitialize the API. */ + p_fs->p_api = NULL; + p_fs->p_flash_info = NULL; + + return rc; +} + + +ret_code_t nrf_fstorage_read(nrf_fstorage_t const * p_fs, + uint32_t src, + void * p_dest, + uint32_t len) +{ + NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL); + NRF_FSTORAGE_PARAM_CHECK(p_dest, NRF_ERROR_NULL); + NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE); + NRF_FSTORAGE_PARAM_CHECK(len, NRF_ERROR_INVALID_LENGTH); + + /* Source addres must be word-aligned. */ + NRF_FSTORAGE_PARAM_CHECK(addr_is_aligned32(src), NRF_ERROR_INVALID_ADDR); + NRF_FSTORAGE_PARAM_CHECK(addr_is_within_bounds(p_fs, src, len), NRF_ERROR_INVALID_ADDR); + + return (p_fs->p_api)->read(p_fs, src, p_dest, len); +} + + +ret_code_t nrf_fstorage_write(nrf_fstorage_t const * p_fs, + uint32_t dest, + void const * p_src, + uint32_t len, + void * p_context) +{ + NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL); + NRF_FSTORAGE_PARAM_CHECK(p_src, NRF_ERROR_NULL); + NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE); + NRF_FSTORAGE_PARAM_CHECK(len, NRF_ERROR_INVALID_LENGTH); + + /* Length must be a multiple of the program unit. */ + NRF_FSTORAGE_PARAM_CHECK(!(len % p_fs->p_flash_info->program_unit), NRF_ERROR_INVALID_LENGTH); + + /* Source and destination addresses must be word-aligned. */ + NRF_FSTORAGE_PARAM_CHECK(addr_is_aligned32(dest), NRF_ERROR_INVALID_ADDR); + NRF_FSTORAGE_PARAM_CHECK(addr_is_aligned32((uint32_t)p_src), NRF_ERROR_INVALID_ADDR); + NRF_FSTORAGE_PARAM_CHECK(addr_is_within_bounds(p_fs, dest, len), NRF_ERROR_INVALID_ADDR); + + return (p_fs->p_api)->write(p_fs, dest, p_src, len, p_context); +} + + +ret_code_t nrf_fstorage_erase(nrf_fstorage_t const * p_fs, + uint32_t page_addr, + uint32_t len, + void * p_context) +{ + NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL); + NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE); + NRF_FSTORAGE_PARAM_CHECK(len, NRF_ERROR_INVALID_LENGTH); + + /* Address must be aligned to a page boundary. */ + NRF_FSTORAGE_PARAM_CHECK(addr_is_page_aligned(p_fs, page_addr), NRF_ERROR_INVALID_ADDR); + + NRF_FSTORAGE_PARAM_CHECK( + addr_is_within_bounds(p_fs, page_addr, (len * p_fs->p_flash_info->erase_unit)), + NRF_ERROR_INVALID_ADDR + ); + + return (p_fs->p_api)->erase(p_fs, page_addr, len, p_context); +} + + +uint8_t const * nrf_fstorage_rmap(nrf_fstorage_t const * p_fs, uint32_t addr) +{ + if ((p_fs == NULL) || (p_fs->p_api == NULL)) + { + return NULL; + } + + return (p_fs->p_api)->rmap(p_fs, addr); +} + + +uint8_t * nrf_fstorage_wmap(nrf_fstorage_t const * p_fs, uint32_t addr) +{ + if ((p_fs == NULL) || (p_fs->p_api == NULL)) + { + return NULL; + } + + return (p_fs->p_api)->wmap(p_fs, addr); +} + + +bool nrf_fstorage_is_busy(nrf_fstorage_t const * p_fs) +{ + /* If a NULL instance is provided, return true if any instance is busy. + * Uninitialized instances are considered not busy. */ + if ((p_fs == NULL) || (p_fs->p_api == NULL)) + { + for (uint32_t i = 0; i < NRF_FSTORAGE_INSTANCE_CNT; i++) + { + p_fs = NRF_FSTORAGE_INSTANCE_GET(i); /* cannot be NULL. */ + if (p_fs->p_api != NULL) + { + /* p_api->is_busy() cannot be NULL. */ + if (p_fs->p_api->is_busy(p_fs)) + { + return true; + } + } + } + + return false; + } + + return p_fs->p_api->is_busy(p_fs); +} + + +static bool addr_is_within_bounds(nrf_fstorage_t const * p_fs, + uint32_t addr, + uint32_t len) +{ + return ( (addr >= p_fs->start_addr) + && (addr + len - 1 <= p_fs->end_addr)); +} + + +static bool addr_is_aligned32(uint32_t addr) +{ + return !(addr & 0x03); +} + + +static bool addr_is_page_aligned(nrf_fstorage_t const * p_fs, + uint32_t addr) +{ + return (addr & (p_fs->p_flash_info->erase_unit - 1)) == 0; +} + + +#endif // NRF_FSTORAGE_ENABLED diff --git a/components/libraries/fstorage/nrf_fstorage.h b/components/libraries/fstorage/nrf_fstorage.h new file mode 100644 index 0000000..a6e95a5 --- /dev/null +++ b/components/libraries/fstorage/nrf_fstorage.h @@ -0,0 +1,341 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_FSTORAGE_H__ +#define NRF_FSTORAGE_H__ + +/** + * @file + * + * @defgroup nrf_fstorage Flash storage (fstorage) + * @ingroup app_common + * @{ + * + * @brief Flash abstraction library that provides basic read, write, and erase operations. + * + * @details The fstorage library can be implemented in different ways. Two implementations are provided: + * - The @ref nrf_fstorage_sd implements flash access through the SoftDevice. + * - The @ref nrf_fstorage_nvmc implements flash access through the non-volatile memory controller. + * + * You can select the implementation that should be used independently for each instance of fstorage. + */ + +#include +#include +#include "sdk_errors.h" +#include "nrf_section.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Macro for defining an fstorage instance. + * + * Users of fstorage must define an instance variable by using this macro. + * Each instance is tied to an API implementation and contains information such + * as the program and erase units for the target flash peripheral. + * Instance variables are placed in the "fs_data" section of the binary. + * + * @param[in] inst A definition of an @ref nrf_fstorage_t variable. + */ +#define NRF_FSTORAGE_DEF(inst) NRF_SECTION_ITEM_REGISTER(fs_data, inst) + +/**@brief Macro for retrieving an fstorage instance. */ +#define NRF_FSTORAGE_INSTANCE_GET(i) NRF_SECTION_ITEM_GET(fs_data, nrf_fstorage_t, (i)) + +/**@brief Macro for retrieving the total number of fstorage instances. */ +#define NRF_FSTORAGE_INSTANCE_CNT NRF_SECTION_ITEM_COUNT(fs_data, nrf_fstorage_t) + + +/**@brief Event IDs. */ +typedef enum +{ + NRF_FSTORAGE_EVT_READ_RESULT, //!< Unused event reserved for a possible future feature. + NRF_FSTORAGE_EVT_WRITE_RESULT, //!< Event for @ref nrf_fstorage_write. + NRF_FSTORAGE_EVT_ERASE_RESULT //!< Event for @ref nrf_fstorage_erase. +} nrf_fstorage_evt_id_t; + + +/**@brief An fstorage event. */ +typedef struct +{ + nrf_fstorage_evt_id_t id; //!< The event ID. + ret_code_t result; //!< Result of the operation. + uint32_t addr; //!< Address at which the operation was performed. + void const * p_src; //!< Buffer written to flash. + uint32_t len; //!< Length of the operation. + void * p_param; //!< User-defined parameter passed to the event handler. +} nrf_fstorage_evt_t; + + +/**@brief Event handler function prototype. + * + * @param[in] p_evt The event. + */ +typedef void (*nrf_fstorage_evt_handler_t)(nrf_fstorage_evt_t * p_evt); + + +/**@brief Information about the implementation and the flash peripheral. */ +typedef struct +{ + uint32_t erase_unit; //!< Size of a flash page (in bytes). A flash page is the smallest unit that can be erased. + uint32_t program_unit; //!< Size of the smallest programmable unit (in bytes). + bool rmap; //!< The device address space is memory mapped to the MCU address space. + bool wmap; //!< The device address space is memory mapped to a writable MCU address space. +} const nrf_fstorage_info_t; + + +/* Necessary forward declaration. */ +struct nrf_fstorage_api_s; + + +/**@brief An fstorage instance. + * + * @details Use the @ref NRF_FSTORAGE_DEF macro to define an fstorage instance. + * + * An instance is tied to an API implementation and contains information about the flash device, + * such as the program and erase units as well and implementation-specific functionality. + */ +typedef struct +{ + /**@brief The API implementation used by this instance. */ + struct nrf_fstorage_api_s const * p_api; + + /**@brief Information about the implementation functionality and the flash peripheral. */ + nrf_fstorage_info_t * p_flash_info; + + /**@brief The event handler function. + * + * If set to NULL, no events will be sent. + */ + nrf_fstorage_evt_handler_t evt_handler; + + /**@brief The beginning of the flash space on which this fstorage instance should operate. + * All flash operations must be within the address specified in + * this field and @ref end_addr. + * + * This field must be set manually. + */ + uint32_t start_addr; + + /**@brief The last address (exclusive) of flash on which this fstorage instance should operate. + * All flash operations must be within the address specified in + * this field and @ref start_addr. + * + * This field must be set manually. + */ + uint32_t end_addr; +} nrf_fstorage_t; + + +/**@brief Functions provided by the API implementation. */ +typedef struct nrf_fstorage_api_s +{ + /**@brief Initialize the flash peripheral. */ + ret_code_t (*init)(nrf_fstorage_t * p_fs, void * p_param); + /**@brief Uninitialize the flash peripheral. */ + ret_code_t (*uninit)(nrf_fstorage_t * p_fs, void * p_param); + /**@brief Read data from flash. */ + ret_code_t (*read)(nrf_fstorage_t const * p_fs, uint32_t src, void * p_dest, uint32_t len); + /**@brief Write bytes to flash. */ + ret_code_t (*write)(nrf_fstorage_t const * p_fs, uint32_t dest, void const * p_src, uint32_t len, void * p_param); + /**@brief Erase flash pages. */ + ret_code_t (*erase)(nrf_fstorage_t const * p_fs, uint32_t addr, uint32_t len, void * p_param); + /**@brief Map a device address to a readable address within the MCU address space. */ + uint8_t const * (*rmap)(nrf_fstorage_t const * p_fs, uint32_t addr); + /**@brief Map a device address to a writable address within the MCU address space. */ + uint8_t * (*wmap)(nrf_fstorage_t const * p_fs, uint32_t addr); + /**@brief Check if there are any pending flash operations. */ + bool (*is_busy)(nrf_fstorage_t const * p_fs); +} const nrf_fstorage_api_t; + + +/**@brief Function for initializing fstorage. + * + * @param[in] p_fs The fstorage instance to initialize. + * @param[in] p_api The API implementation to use. + * @param[in] p_param An optional parameter to pass to the implementation-specific API call. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_NULL If @p p_fs or @p p_api field in @p p_fs is NULL. + * @retval NRF_ERROR_INTERNAL If another error occurred. + */ +ret_code_t nrf_fstorage_init(nrf_fstorage_t * p_fs, + nrf_fstorage_api_t * p_api, + void * p_param); + + +/**@brief Function for uninitializing an fstorage instance. + * + * @param[in] p_fs The fstorage instance to uninitialize. + * @param[in] p_param An optional parameter to pass to the implementation-specific API call. + * + * @retval NRF_SUCCESS If uninitialization was successful. + * @retval NRF_ERROR_NULL If @p p_fs is NULL. + * @retval NRF_ERROR_INVALID_STATE If the module is not initialized. + * @retval NRF_ERROR_INTERNAL If another error occurred. + */ +ret_code_t nrf_fstorage_uninit(nrf_fstorage_t * p_fs, void * p_param); + + +/**@brief Function for reading data from flash. + * + * Copy @p len bytes from @p addr to @p p_dest. + * + * @param[in] p_fs The fstorage instance. + * @param[in] addr Address in flash where to read from. + * @param[in] p_dest Buffer where the data should be copied. + * @param[in] len Length of the data to be copied (in bytes). + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If @p p_fs or @p p_dest is NULL. + * @retval NRF_ERROR_INVALID_STATE If the module is not initialized. + * @retval NRF_ERROR_INVALID_LENGTH If @p len is zero or otherwise invalid. + * @retval NRF_ERROR_INVALID_ADDR If the address @p addr is outside the flash memory + * boundaries specified in @p p_fs, or if it is unaligned. + */ +ret_code_t nrf_fstorage_read(nrf_fstorage_t const * p_fs, + uint32_t addr, + void * p_dest, + uint32_t len); + + +/**@brief Function for writing data to flash. + * + * Write @p len bytes from @p p_src to @p dest. + * + * When using @ref nrf_fstorage_sd, the data is written by several calls to @ref sd_flash_write if + * the length of the data exceeds @ref NRF_FSTORAGE_SD_MAX_WRITE_SIZE bytes. + * Only one event is sent upon completion. + * + * @note The data to be written to flash must be kept in memory until the operation has + * terminated and an event is received. + * + * @param[in] p_fs The fstorage instance. + * @param[in] dest Address in flash memory where to write the data. + * @param[in] p_src Data to be written. + * @param[in] len Length of the data (in bytes). + * @param[in] p_param User-defined parameter passed to the event handler (may be NULL). + * + * @retval NRF_SUCCESS If the operation was accepted. + * @retval NRF_ERROR_NULL If @p p_fs or @p p_src is NULL. + * @retval NRF_ERROR_INVALID_STATE If the module is not initialized. + * @retval NRF_ERROR_INVALID_LENGTH If @p len is zero or not a multiple of the program unit, + * or if it is otherwise invalid. + * @retval NRF_ERROR_INVALID_ADDR If the address @p dest is outside the flash memory + * boundaries specified in @p p_fs, or if it is unaligned. + * @retval NRF_ERROR_NO_MEM If no memory is available to accept the operation. + * When using the @ref nrf_fstorage_sd, this error + * indicates that the internal queue of operations is full. + */ +ret_code_t nrf_fstorage_write(nrf_fstorage_t const * p_fs, + uint32_t dest, + void const * p_src, + uint32_t len, + void * p_param); + + +/**@brief Function for erasing flash pages. + * + * @details This function erases @p len pages starting from the page at address @p page_addr. + * The erase operation must be initiated on a page boundary. + * + * @param[in] p_fs The fstorage instance. + * @param[in] page_addr Address of the page to erase. + * @param[in] len Number of pages to erase. + * @param[in] p_param User-defined parameter passed to the event handler (may be NULL). + * + * @retval NRF_SUCCESS If the operation was accepted. + * @retval NRF_ERROR_NULL If @p p_fs is NULL. + * @retval NRF_ERROR_INVALID_STATE If the module is not initialized. + * @retval NRF_ERROR_INVALID_LENGTH If @p len is zero. + * @retval NRF_ERROR_INVALID_ADDR If the address @p page_addr is outside the flash memory + * boundaries specified in @p p_fs, or if it is unaligned. + * @retval NRF_ERROR_NO_MEM If no memory is available to accept the operation. + * When using the @ref nrf_fstorage_sd, this error + * indicates that the internal queue of operations is full. + */ +ret_code_t nrf_fstorage_erase(nrf_fstorage_t const * p_fs, + uint32_t page_addr, + uint32_t len, + void * p_param); + + +/**@brief Map a flash address to a pointer in the MCU address space that can be dereferenced. + * + * @param p_fs The fstorage instance. + * @param addr The address to map. + * + * @retval A pointer to the specified address, + * or @c NULL if the address cannot be mapped or if @p p_fs is @c NULL. + */ +uint8_t const * nrf_fstorage_rmap(nrf_fstorage_t const * p_fs, uint32_t addr); + + +/**@brief Map a flash address to a pointer in the MCU address space that can be written to. + * + * @param p_fs The fstorage instance. + * @param addr The address to map. + * + * @retval A pointer to the specified address, + * or @c NULL if the address cannot be mapped or if @p p_fs is @c NULL. + */ +uint8_t * nrf_fstorage_wmap(nrf_fstorage_t const * p_fs, uint32_t addr); + + +/**@brief Function for querying the status of fstorage. + * + * @details An uninitialized instance of fstorage is treated as not busy. + * + * @param[in] p_fs The fstorage instance. Pass NULL to query all instances. + * + * @returns If @p p_fs is @c NULL, this function returns true if any fstorage instance is busy or false otherwise. + * @returns If @p p_fs is not @c NULL, this function returns true if the fstorage instance is busy or false otherwise. + */ + bool nrf_fstorage_is_busy(nrf_fstorage_t const * p_fs); + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_FSTORAGE_H__ diff --git a/components/libraries/fstorage/nrf_fstorage_nvmc.c b/components/libraries/fstorage/nrf_fstorage_nvmc.c new file mode 100644 index 0000000..199797c --- /dev/null +++ b/components/libraries/fstorage/nrf_fstorage_nvmc.c @@ -0,0 +1,217 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_FSTORAGE) + +#include "nrf_fstorage_nvmc.h" +#include +#include +#include +#include "nrf_nvmc.h" +#include "nrf_atomic.h" + + +static nrf_fstorage_info_t m_flash_info = +{ +#if defined(NRF51) + .erase_unit = 1024, +#elif defined(NRF52_SERIES) + .erase_unit = 4096, +#endif + .program_unit = 4, + .rmap = true, + .wmap = false, +}; + + + /* An operation initiated by fstorage is ongoing. */ +static nrf_atomic_flag_t m_flash_operation_ongoing; + + +/* Send event to the event handler. */ +static void event_send(nrf_fstorage_t const * p_fs, + nrf_fstorage_evt_id_t evt_id, + void const * p_src, + uint32_t addr, + uint32_t len, + void * p_param) +{ + if (p_fs->evt_handler == NULL) + { + /* Nothing to do. */ + return; + } + + nrf_fstorage_evt_t evt = + { + .result = NRF_SUCCESS, + .id = evt_id, + .addr = addr, + .p_src = p_src, + .len = len, + .p_param = p_param, + }; + + p_fs->evt_handler(&evt); +} + + +static ret_code_t init(nrf_fstorage_t * p_fs, void * p_param) +{ + UNUSED_PARAMETER(p_param); + + p_fs->p_flash_info = &m_flash_info; + + return NRF_SUCCESS; +} + + +static ret_code_t uninit(nrf_fstorage_t * p_fs, void * p_param) +{ + UNUSED_PARAMETER(p_fs); + UNUSED_PARAMETER(p_param); + + (void) nrf_atomic_flag_clear(&m_flash_operation_ongoing); + + return NRF_SUCCESS; +} + + +static ret_code_t read(nrf_fstorage_t const * p_fs, uint32_t src, void * p_dest, uint32_t len) +{ + UNUSED_PARAMETER(p_fs); + + memcpy(p_dest, (uint32_t*)src, len); + + return NRF_SUCCESS; +} + + +static ret_code_t write(nrf_fstorage_t const * p_fs, + uint32_t dest, + void const * p_src, + uint32_t len, + void * p_param) +{ + if (nrf_atomic_flag_set_fetch(&m_flash_operation_ongoing)) + { + return NRF_ERROR_BUSY; + } + + nrf_nvmc_write_words(dest, (uint32_t*)p_src, (len / m_flash_info.program_unit)); + + /* Clear the flag before sending the event, to allow API calls in the event context. */ + (void) nrf_atomic_flag_clear(&m_flash_operation_ongoing); + + event_send(p_fs, NRF_FSTORAGE_EVT_WRITE_RESULT, p_src, dest, len, p_param); + + return NRF_SUCCESS; +} + + +static ret_code_t erase(nrf_fstorage_t const * p_fs, + uint32_t page_addr, + uint32_t len, + void * p_param) +{ + uint32_t progress = 0; + + if (nrf_atomic_flag_set_fetch(&m_flash_operation_ongoing)) + { + return NRF_ERROR_BUSY; + } + + while (progress != len) + { + nrf_nvmc_page_erase(page_addr + (progress * m_flash_info.erase_unit)); + progress++; + } + + /* Clear the flag before sending the event, to allow API calls in the event context. */ + (void) nrf_atomic_flag_clear(&m_flash_operation_ongoing); + + event_send(p_fs, NRF_FSTORAGE_EVT_ERASE_RESULT, NULL, page_addr, len, p_param); + + return NRF_SUCCESS; +} + + +static uint8_t const * rmap(nrf_fstorage_t const * p_fs, uint32_t addr) +{ + UNUSED_PARAMETER(p_fs); + + return (uint8_t*)addr; +} + + +static uint8_t * wmap(nrf_fstorage_t const * p_fs, uint32_t addr) +{ + UNUSED_PARAMETER(p_fs); + UNUSED_PARAMETER(addr); + + /* Not supported. */ + return NULL; +} + + +static bool is_busy(nrf_fstorage_t const * p_fs) +{ + UNUSED_PARAMETER(p_fs); + + return m_flash_operation_ongoing; +} + + +/* The exported API. */ +nrf_fstorage_api_t nrf_fstorage_nvmc = +{ + .init = init, + .uninit = uninit, + .read = read, + .write = write, + .erase = erase, + .rmap = rmap, + .wmap = wmap, + .is_busy = is_busy +}; + + +#endif // NRF_FSTORAGE_ENABLED diff --git a/components/libraries/fstorage/nrf_fstorage_nvmc.h b/components/libraries/fstorage/nrf_fstorage_nvmc.h new file mode 100644 index 0000000..412c02e --- /dev/null +++ b/components/libraries/fstorage/nrf_fstorage_nvmc.h @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * + * @defgroup nrf_fstorage_nvmc NVMC implementation + * @ingroup nrf_fstorage + * @{ + * + * @brief API implementation of fstorage that uses the non-volatile memory controller (NVMC). +*/ + +#ifndef NRF_FSTORAGE_NVMC_H__ +#define NRF_FSTORAGE_NVMC_H__ + +#include "nrf_fstorage.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief API implementation that uses the non-volatile memory controller. + * + * @details An fstorage instance with this API implementation can be initialized by providing + * this structure as a parameter to @ref nrf_fstorage_init. + * The structure is defined in @c nrf_fstorage_nvmc.c. + */ +extern nrf_fstorage_api_t nrf_fstorage_nvmc; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_FSTORAGE_NVMC_H__ +/** @} */ diff --git a/components/libraries/fstorage/nrf_fstorage_sd.c b/components/libraries/fstorage/nrf_fstorage_sd.c new file mode 100644 index 0000000..bcc9bf7 --- /dev/null +++ b/components/libraries/fstorage/nrf_fstorage_sd.c @@ -0,0 +1,624 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" + +#if NRF_MODULE_ENABLED(NRF_FSTORAGE) + +#include "nrf_fstorage_sd.h" +#include +#include +#include +#include "nordic_common.h" +#include "nrf_soc.h" +#include "nrf_sdh.h" +#include "nrf_sdh_soc.h" +#include "nrf_atomic.h" +#include "nrf_atfifo.h" +#include "app_util_platform.h" + + +#if (NRF_FSTORAGE_SD_MAX_WRITE_SIZE % 4) +#error NRF_FSTORAGE_SD_MAX_WRITE_SIZE must be a multiple of the word size. +#endif + + +/**@brief fstorage operation codes. */ +typedef enum +{ + NRF_FSTORAGE_OP_WRITE, //!< Write bytes to flash. + NRF_FSTORAGE_OP_ERASE //!< Erase flash pages. +} nrf_fstorage_sd_opcode_t; + +ANON_UNIONS_ENABLE; +/**@brief fstorage operation queue element. */ +typedef struct +{ + nrf_fstorage_t const * p_fs; //!< The fstorage instance that requested the operation. + nrf_fstorage_sd_opcode_t op_code; //!< Requested operation. + void * p_param; //!< User-defined parameter passed to the event handler. + union + { + struct + { + void const * p_src; //!< Data to be written to flash. + uint32_t dest; //!< Destination of the data in flash. + uint32_t len; //!< Length of the data to be written (in bytes). + uint32_t offset; //!< Write offset. + } write; + struct + { + uint32_t page; //!< Physical page number. + uint32_t progress; //!< Number of pages erased. + uint32_t pages_to_erase; //!< Total number of pages to erase. + } erase; + }; +} nrf_fstorage_sd_op_t; +ANON_UNIONS_DISABLE; + +typedef enum +{ + NRF_FSTORAGE_STATE_IDLE, //!< No operations requested to the SoftDevice. + NRF_FSTORAGE_STATE_OP_PENDING, //!< A non-fstorage operation is pending. + NRF_FSTORAGE_STATE_OP_EXECUTING, //!< An fstorage operation is executing. +} nrf_fstorage_sd_state_t; + +/**@brief Internal state. */ +typedef struct +{ + nrf_atomic_flag_t initialized; //!< fstorage is initalized. + nrf_atomic_flag_t queue_running; //!< The queue is running. + /** Prevent API calls from entering queue_process(). */ + nrf_fstorage_sd_state_t state; //!< Internal fstorage state. + uint32_t retries; //!< Number of times an operation has been retried on timeout. + bool sd_enabled; //!< The SoftDevice is enabled. + bool paused; //!< A SoftDevice state change is impending. + /** Do not load a new operation when the last one completes. */ +} nrf_fstorage_sd_work_t; + + +void nrf_fstorage_sys_evt_handler(uint32_t, void *); +bool nrf_fstorage_sdh_req_handler(nrf_sdh_req_evt_t, void *); +void nrf_fstorage_sdh_state_handler(nrf_sdh_state_evt_t, void *); + + +/* Flash device information. */ +static nrf_fstorage_info_t m_flash_info = +{ +#if defined(NRF51) + .erase_unit = 1024, +#elif defined(NRF52_SERIES) + .erase_unit = 4096, +#endif + .program_unit = 4, + .rmap = true, + .wmap = false, +}; + +/* Queue of fstorage operations. */ +NRF_ATFIFO_DEF(m_fifo, nrf_fstorage_sd_op_t, NRF_FSTORAGE_SD_QUEUE_SIZE); + +/* Define a nrf_sdh_soc event observer to receive SoftDevice system events. */ +NRF_SDH_SOC_OBSERVER(m_sys_obs, 0, nrf_fstorage_sys_evt_handler, NULL); + +/* nrf_sdh request observer. */ +NRF_SDH_REQUEST_OBSERVER(m_req_obs, 0) = +{ + .handler = nrf_fstorage_sdh_req_handler, +}; + +/* nrf_sdh state observer. */ +NRF_SDH_STATE_OBSERVER(m_state_obs, 0) = +{ + .handler = nrf_fstorage_sdh_state_handler, +}; + +static nrf_fstorage_sd_work_t m_flags; /* Internal status. */ +static nrf_fstorage_sd_op_t * m_p_cur_op; /* The current operation being executed. */ +static nrf_atfifo_item_get_t m_iget_ctx; /* Context for nrf_atfifo_item_get() and nrf_atfifo_item_free(). */ + + +/* Send events to the application. */ +static void event_send(nrf_fstorage_sd_op_t const * p_op, ret_code_t result) +{ + if (p_op->p_fs->evt_handler == NULL) + { + /* Nothing to do. */ + return; + } + + nrf_fstorage_evt_t evt = + { + .result = result, + .p_param = p_op->p_param, + }; + + switch (p_op->op_code) + { + case NRF_FSTORAGE_OP_WRITE: + evt.id = NRF_FSTORAGE_EVT_WRITE_RESULT; + evt.addr = p_op->write.dest; + evt.p_src = p_op->write.p_src; + evt.len = p_op->write.len; + break; + + case NRF_FSTORAGE_OP_ERASE: + evt.id = NRF_FSTORAGE_EVT_ERASE_RESULT; + evt.addr = (p_op->erase.page * m_flash_info.erase_unit); + evt.len = p_op->erase.pages_to_erase; + break; + + default: + /* Should not happen. */ + break; + } + + p_op->p_fs->evt_handler(&evt); +} + + +/* Write to flash. */ +static uint32_t write_execute(nrf_fstorage_sd_op_t const * p_op) +{ + uint32_t chunk_len; + + chunk_len = MIN(p_op->write.len - p_op->write.offset, NRF_FSTORAGE_SD_MAX_WRITE_SIZE); + chunk_len = MAX(1, chunk_len / m_flash_info.program_unit); + + /* Cast to p_src to uint32_t to perform arithmetic. */ + uint32_t * p_dest = (uint32_t*)(p_op->write.dest + p_op->write.offset); + uint32_t const * p_src = (uint32_t*)((uint32_t)p_op->write.p_src + p_op->write.offset); + + return sd_flash_write(p_dest, p_src, chunk_len); +} + + +/* Erase flash page(s). */ +static uint32_t erase_execute(nrf_fstorage_sd_op_t const * p_op) +{ + return sd_flash_page_erase(p_op->erase.page + p_op->erase.progress); +} + + +/* Free the current queue element. */ +static void queue_free(void) +{ + (void) nrf_atfifo_item_free(m_fifo, &m_iget_ctx); +} + + +/* Load a new operation from the queue. */ +static bool queue_load_next(void) +{ + m_p_cur_op = nrf_atfifo_item_get(m_fifo, &m_iget_ctx); + + return (m_p_cur_op != NULL); +} + + +/* Execute an operation in the queue. */ +static void queue_process(void) +{ + uint32_t rc; + + if (m_flags.state == NRF_FSTORAGE_STATE_IDLE) + { + if (!queue_load_next()) + { + /* No more operations, nothing to do. */ + m_flags.queue_running = false; + return; + } + } + + m_flags.state = NRF_FSTORAGE_STATE_OP_EXECUTING; + + switch (m_p_cur_op->op_code) + { + case NRF_FSTORAGE_OP_WRITE: + rc = write_execute(m_p_cur_op); + break; + + case NRF_FSTORAGE_OP_ERASE: + rc = erase_execute(m_p_cur_op); + break; + + default: + rc = NRF_ERROR_INTERNAL; + break; + } + + switch (rc) + { + case NRF_SUCCESS: + { + /* The operation was accepted by the SoftDevice. + * If the SoftDevice is enabled, wait for a system event. Otherwise, + * the SoftDevice call is synchronous and will not send an event so we simulate it. */ + if (!m_flags.sd_enabled) + { + nrf_fstorage_sys_evt_handler(NRF_EVT_FLASH_OPERATION_SUCCESS, NULL); + } + } break; + + case NRF_ERROR_BUSY: + { + /* The SoftDevice is executing a flash operation that was not requested by fstorage. + * Stop processing the queue until a system event is received. */ + m_flags.state = NRF_FSTORAGE_STATE_OP_PENDING; + } break; + + default: + { + /* An error has occurred. We cannot proceed further with this operation. */ + event_send(m_p_cur_op, NRF_ERROR_INTERNAL); + /* Reset the internal state so we can accept other operations. */ + m_flags.state = NRF_FSTORAGE_STATE_IDLE; + m_flags.queue_running = false; + /* Free the current queue element. */ + queue_free(); + } break; + } +} + + +/* Start processing the queue if it is not running and fstorage is not paused. */ +static void queue_start(void) +{ + if ( (!nrf_atomic_flag_set_fetch(&m_flags.queue_running)) + && (!m_flags.paused)) + { + queue_process(); + } +} + + +/* Flash operation success callback. Keeps track of the progress of an operation. */ +static bool on_operation_success(nrf_fstorage_sd_op_t * const p_op) +{ + /* Reset the retry counter on success. */ + m_flags.retries = 0; + + switch (p_op->op_code) + { + case NRF_FSTORAGE_OP_WRITE: + { + /* Update the offset only if the operation is successful + * so that it can be retried in case it times out. */ + uint32_t const chunk_len = MIN(p_op->write.len - p_op->write.offset, + NRF_FSTORAGE_SD_MAX_WRITE_SIZE); + + p_op->write.offset += chunk_len; + + if (p_op->write.offset == p_op->write.len) + { + return true; + } + } break; + + case NRF_FSTORAGE_OP_ERASE: + { + p_op->erase.progress++; + + if (p_op->erase.progress == p_op->erase.pages_to_erase) + { + return true; + } + } break; + + default: + /* Should not happen. */ + break; + } + + return false; +} + + +/* Flash operation failure callback. */ +static bool on_operation_failure(nrf_fstorage_sd_op_t const * p_op) +{ + UNUSED_PARAMETER(p_op); + + m_flags.retries++; + + if (m_flags.retries > NRF_FSTORAGE_SD_MAX_RETRIES) + { + /* Maximum amount of retries reached. Give up. */ + m_flags.retries = 0; + return true; + } + + return false; +} + + +static ret_code_t init(nrf_fstorage_t * p_fs, void * p_param) +{ + UNUSED_PARAMETER(p_param); + + p_fs->p_flash_info = &m_flash_info; + + if (!nrf_atomic_flag_set_fetch(&m_flags.initialized)) + { +#if NRF_SDH_ENABLED + m_flags.sd_enabled = nrf_sdh_is_enabled(); +#endif + (void) NRF_ATFIFO_INIT(m_fifo); + } + + return NRF_SUCCESS; +} + + +static ret_code_t uninit(nrf_fstorage_t * p_fs, void * p_param) +{ + UNUSED_PARAMETER(p_fs); + UNUSED_PARAMETER(p_param); + + /* The state is re-initialized upon init(). + * The common uninitialization code is run by the caller. */ + + memset(&m_flags, 0x00, sizeof(m_flags)); + + (void) nrf_atfifo_clear(m_fifo); + + return NRF_SUCCESS; +} + + +static ret_code_t write(nrf_fstorage_t const * p_fs, + uint32_t dest, + void const * p_src, + uint32_t len, + void * p_param) +{ + nrf_fstorage_sd_op_t * p_op; + nrf_atfifo_item_put_t iput_ctx; + + /* Get a free queue element. */ + p_op = nrf_atfifo_item_alloc(m_fifo, &iput_ctx); + + if (p_op == NULL) + { + return NRF_ERROR_NO_MEM; + } + + /* Initialize the operation. */ + memset(p_op, 0x00, sizeof(nrf_fstorage_sd_op_t)); + + p_op->op_code = NRF_FSTORAGE_OP_WRITE; + p_op->p_fs = p_fs; + p_op->p_param = p_param; + p_op->write.dest = dest; + p_op->write.p_src = p_src; + p_op->write.len = len; + + /* Put the operation on the queue. */ + (void) nrf_atfifo_item_put(m_fifo, &iput_ctx); + + queue_start(); + + return NRF_SUCCESS; +} + + +static ret_code_t read(nrf_fstorage_t const * p_fs, uint32_t src, void * p_dest, uint32_t len) +{ + memcpy(p_dest, (uint32_t*)src, len); + + return NRF_SUCCESS; +} + + +static ret_code_t erase(nrf_fstorage_t const * p_fs, + uint32_t page_addr, + uint32_t len, + void * p_param) +{ + nrf_fstorage_sd_op_t * p_op; + nrf_atfifo_item_put_t iput_ctx; + + /* Get a free queue element. */ + p_op = nrf_atfifo_item_alloc(m_fifo, &iput_ctx); + + if (p_op == NULL) + { + return NRF_ERROR_NO_MEM; + } + + /* Initialize the operation. */ + memset(p_op, 0x00, sizeof(nrf_fstorage_sd_op_t)); + + p_op->op_code = NRF_FSTORAGE_OP_ERASE; + p_op->p_fs = p_fs; + p_op->p_param = p_param; + p_op->erase.page = (page_addr / m_flash_info.erase_unit); + p_op->erase.pages_to_erase = len; + + /* Put the operation on the queue. */ + (void) nrf_atfifo_item_put(m_fifo, &iput_ctx); + + queue_start(); + + return NRF_SUCCESS; +} + + +static uint8_t const * rmap(nrf_fstorage_t const * p_fs, uint32_t addr) +{ + UNUSED_PARAMETER(p_fs); + + return (uint8_t*)addr; +} + + +static uint8_t * wmap(nrf_fstorage_t const * p_fs, uint32_t addr) +{ + UNUSED_PARAMETER(p_fs); + UNUSED_PARAMETER(addr); + + /* Not supported. */ + return NULL; +} + + +static bool is_busy(nrf_fstorage_t const * p_fs) +{ + UNUSED_PARAMETER(p_fs); + + return (m_flags.state != NRF_FSTORAGE_STATE_IDLE); +} + + +void nrf_fstorage_sys_evt_handler(uint32_t sys_evt, void * p_context) +{ + UNUSED_PARAMETER(p_context); + + if ( (sys_evt != NRF_EVT_FLASH_OPERATION_SUCCESS) + && (sys_evt != NRF_EVT_FLASH_OPERATION_ERROR)) + { + /* Ignore any non-flash events. */ + return; + } + + switch (m_flags.state) + { + case NRF_FSTORAGE_STATE_IDLE: + /* Ignore flash events if no flash operation was requested. */ + return; + + case NRF_FSTORAGE_STATE_OP_PENDING: + /* The SoftDevice has completed a flash operation that was not requested by fstorage. + * It should be possible to request an operation now. + * Process the queue at the end of this function. */ + break; + + case NRF_FSTORAGE_STATE_OP_EXECUTING: + { + /* Handle the result of a flash operation initiated by this module. */ + bool operation_finished = false; + + switch (sys_evt) + { + case NRF_EVT_FLASH_OPERATION_SUCCESS: + operation_finished = on_operation_success(m_p_cur_op); + break; + + case NRF_EVT_FLASH_OPERATION_ERROR: + operation_finished = on_operation_failure(m_p_cur_op); + break; + + default: + break; + } + + if (operation_finished) + { + /* The operation has finished. Change state to NRF_FSTORAGE_STATE_IDLE + * so that queue_process() will fetch a new operation from the queue. */ + m_flags.state = NRF_FSTORAGE_STATE_IDLE; + + event_send(m_p_cur_op, (sys_evt == NRF_EVT_FLASH_OPERATION_SUCCESS) ? + NRF_SUCCESS : NRF_ERROR_TIMEOUT); + + /* Free the queue element after sending out the event to prevent API calls made + * in the event context to queue elements indefinitely, without this function + * ever returning in case the SoftDevice calls are synchronous. */ + queue_free(); + } + } break; + } + + if (!m_flags.paused) + { + queue_process(); + } + else + { + /* A flash operation has completed. Let the SoftDevice change state. */ + (void) nrf_sdh_request_continue(); + } +} + + +bool nrf_fstorage_sdh_req_handler(nrf_sdh_req_evt_t req, void * p_context) +{ + UNUSED_PARAMETER(req); + UNUSED_PARAMETER(p_context); + + m_flags.paused = true; + + /* If there are any operations ongoing, pause the SoftDevice state change. */ + return (m_flags.state == NRF_FSTORAGE_STATE_IDLE); +} + + +void nrf_fstorage_sdh_state_handler(nrf_sdh_state_evt_t state, void * p_context) +{ + UNUSED_PARAMETER(p_context); + + if ( (state == NRF_SDH_EVT_STATE_ENABLED) + || (state == NRF_SDH_EVT_STATE_DISABLED)) + { + m_flags.paused = false; + m_flags.sd_enabled = (state == NRF_SDH_EVT_STATE_ENABLED); + + /* Execute any operations still in the queue. */ + queue_process(); + } +} + + +/* Exported API implementation. */ +nrf_fstorage_api_t nrf_fstorage_sd = +{ + .init = init, + .uninit = uninit, + .read = read, + .write = write, + .erase = erase, + .rmap = rmap, + .wmap = wmap, + .is_busy = is_busy +}; + + +#endif // NRF_FSTORAGE_ENABLED diff --git a/components/libraries/fstorage/nrf_fstorage_sd.h b/components/libraries/fstorage/nrf_fstorage_sd.h new file mode 100644 index 0000000..d441a98 --- /dev/null +++ b/components/libraries/fstorage/nrf_fstorage_sd.h @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * + * @defgroup nrf_fstorage_sd SoftDevice implementation + * @ingroup nrf_fstorage + * @{ + * + * @brief API implementation of fstorage that uses the SoftDevice. +*/ + +#ifndef NRF_FSTORAGE_SD_H__ +#define NRF_FSTORAGE_SD_H__ + +#include "nrf_fstorage.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief API implementation that uses the SoftDevice. + * + * @details An fstorage instance with this API implementation can be initialized by providing + * this structure as a parameter to @ref nrf_fstorage_init. + * The structure is defined in @c nrf_fstorage_sd.c. + */ +extern nrf_fstorage_api_t nrf_fstorage_sd; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_FSTORAGE_SD_H__ +/** @} */ diff --git a/components/libraries/hardfault/hardfault.h b/components/libraries/hardfault/hardfault.h new file mode 100644 index 0000000..b831f13 --- /dev/null +++ b/components/libraries/hardfault/hardfault.h @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef HARDFAULT_H__ +#define HARDFAULT_H__ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @defgroup hardfault_default HardFault exception + * @{ + * @brief Default HardFault exception implementation. + * @ingroup app_common + */ + +/** + * @brief Contents of the stack. + * + * This structure is used to re-create the stack layout after a HardFault exception was raised. + */ +typedef struct HardFault_stack +{ + uint32_t r0; ///< R0 register. + uint32_t r1; ///< R1 register. + uint32_t r2; ///< R2 register. + uint32_t r3; ///< R3 register. + uint32_t r12; ///< R12 register. + uint32_t lr; ///< Link register. + uint32_t pc; ///< Program counter. + uint32_t psr; ///< Program status register. +} HardFault_stack_t; + +/** + * @brief Function for processing HardFault exceptions. + * + * An application that needs to process HardFault exceptions should provide an implementation of this function. + * It will be called from the HardFault handler. + * If no implementation is provided, the library uses a default one, which just restarts the MCU. + * + * @note If the DEBUG_NRF macro is defined, the software breakpoint is set just before the call + * to this function. + * + * @param p_stack Pointer to the stack bottom. + * This pointer might be NULL if the HardFault was called when the main stack was + * the active stack and a stack overrun is detected. + * In such a situation, the stack pointer is reinitialized to the default position, + * and the stack content is lost. + */ +void HardFault_process(HardFault_stack_t * p_stack); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* HARDFAULT_H__ */ diff --git a/components/libraries/hardfault/hardfault_genhf.h b/components/libraries/hardfault/hardfault_genhf.h new file mode 100644 index 0000000..b3b019d --- /dev/null +++ b/components/libraries/hardfault/hardfault_genhf.h @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef HARDFAULT_GENHF_H__ +#define HARDFAULT_GENHF_H__ + +#include "compiler_abstraction.h" + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @defgroup hardfault_genhf Generating HardFaults for testing + * @{ + * @brief Macros and functions used to generate a HardFault in a selected place. + * @ingroup hardfault_default + * + * This functionality is meant to be used while testing the @ref hardfault_default library functionality. + */ + +/** + * @brief Function for generating an invalid function pointer HardFault. + * + * Function tries to jump into illegal address. + */ +static inline void hardfault_genhf_invalid_fp(void); + +/** + * @brief Function for generating an undefined instruction HardFault. + * + * This function places the value in the code area that is not the legal instruction. + */ +static inline void hardfault_genhf_undefined_instr(void); + +/** + * @brief Function for generating an unaligned LDM access HardFault. + * + * This function generates fault exception loading values from an unaligned address. + */ +static inline void hardfault_genhf_ldm_align(void); + +#if defined( __CC_ARM ) + +static inline __ASM void hardfault_genhf_invalid_fp(void) +{ + MOVS r0, #0 + BLX r0 +} + +static inline __ASM void hardfault_genhf_undefined_instr(void) +{ + DCI 0xf123 + DCI 0x4567 +} + +static inline __ASM void hardfault_genhf_ldm_align(void) +{ + MOVS r0, #1 + LDM r0!, {r1-r2} +} + +#elif defined( __ICCARM__ ) + +#pragma inline=forced +static inline void hardfault_genhf_invalid_fp(void) +{ + __ASM volatile( + " movs r0, #0 \n" + " blx r0 \n" + ); +} + +#pragma inline=forced +static inline void hardfault_genhf_undefined_instr(void) +{ + __ASM volatile( + "DATA \n" + " DC16 0xf123 \n" + " DC16 0x4567 \n" + ); +} + +#pragma inline=forced +static inline void hardfault_genhf_ldm_align(void) +{ + __ASM volatile( + " movs r0, #1 \n" + " ldm r0!, {r1-r2} \n" + ); +} + +#elif defined( __GNUC__ ) + +static inline void hardfault_genhf_invalid_fp(void) +{ + __ASM volatile( + " .syntax unified \n" + " movs r0, #0 \n" + " blx r0 \n" + ); +} + +static inline void hardfault_genhf_undefined_instr(void) +{ + __ASM volatile( + " .hword 0xf123 \n" + " .hword 0x4567 \n" + ); +} + +static inline void hardfault_genhf_ldm_align(void) +{ + __ASM volatile( + " .syntax unified \n" + " movs r0, #1 \n" + " ldm r0!, {r1-r2} \n" + ); +} + +#else +#error "Unsupported compiler" +#endif + +/** @} */ +#ifdef __cplusplus +} +#endif + +#endif /* HARDFAULT_GENHF_H__ */ diff --git a/components/libraries/hardfault/hardfault_implementation.c b/components/libraries/hardfault/hardfault_implementation.c new file mode 100644 index 0000000..e1228b3 --- /dev/null +++ b/components/libraries/hardfault/hardfault_implementation.c @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(HARDFAULT_HANDLER) +#include "hardfault.h" +#include "nrf.h" +#include "compiler_abstraction.h" +#include "app_util_platform.h" +#ifdef SOFTDEVICE_PRESENT +#include "nrf_soc.h" +#endif +#define NRF_LOG_MODULE_NAME hardfault +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +NRF_LOG_MODULE_REGISTER(); + + +/*lint -save -e14 */ +__WEAK void HardFault_process(HardFault_stack_t * p_stack) +{ + // Restart the system by default + NVIC_SystemReset(); +} +/*lint -restore */ + +void HardFault_c_handler(uint32_t * p_stack_address) +{ + NRF_LOG_FINAL_FLUSH(); + +#if (__CORTEX_M == 0x04) + +#ifndef CFSR_MMARVALID + #define CFSR_MMARVALID (1 << (0 + 7)) +#endif + +#ifndef CFSR_BFARVALID + #define CFSR_BFARVALID (1 << (8 + 7)) +#endif + + HardFault_stack_t * p_stack = (HardFault_stack_t *)p_stack_address; + static const char *cfsr_msgs[] = { + [0] = "The processor has attempted to execute an undefined instruction", + [1] = "The processor attempted a load or store at a location that does not permit the operation", + [2] = NULL, + [3] = "Unstack for an exception return has caused one or more access violations", + [4] = "Stacking for an exception entry has caused one or more access violations", + [5] = "A MemManage fault occurred during floating-point lazy state preservation", + [6] = NULL, + [7] = NULL, + [8] = "Instruction bus error", + [9] = "Data bus error (PC value stacked for the exception return points to the instruction that caused the fault)", + [10] = "Data bus error (return address in the stack frame is not related to the instruction that caused the error)", + [11] = "Unstack for an exception return has caused one or more BusFaults", + [12] = "Stacking for an exception entry has caused one or more BusFaults", + [13] = "A bus fault occurred during floating-point lazy state preservation", + [14] = NULL, + [15] = NULL, + [16] = "The processor has attempted to execute an undefined instruction", + [17] = "The processor has attempted to execute an instruction that makes illegal use of the EPSR", + [18] = "The processor has attempted an illegal load of EXC_RETURN to the PC, as a result of an invalid context, or an invalid EXC_RETURN value", + [19] = "The processor has attempted to access a coprocessor", + [20] = NULL, + [21] = NULL, + [22] = NULL, + [23] = NULL, + [24] = "The processor has made an unaligned memory access", + [25] = "The processor has executed an SDIV or UDIV instruction with a divisor of 0", + }; + + uint32_t cfsr = SCB->CFSR; + + if (p_stack != NULL) + { + // Print information about error. + NRF_LOG_ERROR("HARD FAULT at 0x%08X", p_stack->pc); + NRF_LOG_ERROR(" R0: 0x%08X R1: 0x%08X R2: 0x%08X R3: 0x%08X", + p_stack->r0, p_stack->r1, p_stack->r2, p_stack->r3); + NRF_LOG_ERROR(" R12: 0x%08X LR: 0x%08X PSR: 0x%08X", + p_stack->r12, p_stack->lr, p_stack->psr); + } + else + { + NRF_LOG_ERROR("Stack violation: stack pointer outside stack area."); + } + + if (SCB->HFSR & SCB_HFSR_VECTTBL_Msk) + { + NRF_LOG_ERROR("Cause: BusFault on a vector table read during exception processing."); + } + + for (uint32_t i = 0; i < sizeof(cfsr_msgs) / sizeof(cfsr_msgs[0]); i++) + { + if (((cfsr & (1 << i)) != 0) && (cfsr_msgs[i] != NULL)) + { + NRF_LOG_ERROR("Cause: %s.", (uint32_t)cfsr_msgs[i]); + } + } + + if (cfsr & CFSR_MMARVALID) + { + NRF_LOG_ERROR("MemManage Fault Address: 0x%08X", SCB->MMFAR); + } + + if (cfsr & CFSR_BFARVALID) + { + NRF_LOG_ERROR("Bus Fault Address: 0x%08X", SCB->BFAR); + } + +#if defined(DEBUG) + + NRF_BREAKPOINT_COND; + + #endif // defined (DEBUG) + +#endif // __CORTEX_M == 0x04 + + HardFault_process((HardFault_stack_t *)p_stack_address); +} +#endif //NRF_MODULE_ENABLED(HARDFAULT_HANDLER) diff --git a/components/libraries/hardfault/nrf51/handler/hardfault_handler_gcc.c b/components/libraries/hardfault/nrf51/handler/hardfault_handler_gcc.c new file mode 100644 index 0000000..bddaff4 --- /dev/null +++ b/components/libraries/hardfault/nrf51/handler/hardfault_handler_gcc.c @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(HARDFAULT_HANDLER) +#include +#include "compiler_abstraction.h" + +extern void HardFault_c_handler(uint32_t *); + +void HardFault_Handler(void) __attribute__(( naked )); + +void HardFault_Handler(void) +{ + __ASM volatile( + " .syntax unified \n" + + " ldr r0, =0xFFFFFFFD \n" + " cmp r0, lr \n" + " bne HardFault_Handler_ChooseMSP \n" + /* Reading PSP into R0 */ + " mrs r0, PSP \n" + " b HardFault_Handler_Continue \n" + "HardFault_Handler_ChooseMSP: \n" + /* Reading MSP into R0 */ + " mrs r0, MSP \n" + /* ----------------------------------------------------------------- + * If we have selected MSP check if we may use stack safetly. + * If not - reset the stack to the initial value. */ + " ldr r1, =__StackTop \n" + " ldr r2, =__StackLimit \n" + + /* MSP is in the range of the stack area */ + " cmp r0, r1 \n" + " bhi HardFault_MoveSP \n" + " cmp r0, r2 \n" + " bhi HardFault_Handler_Continue \n" + /* ----------------------------------------------------------------- */ + "HardFault_MoveSP: \n" + " mov SP, r1 \n" + " movs r0, #0 \n" + + "HardFault_Handler_Continue: \n" + " ldr r3, =%0 \n" + " bx r3 \n" + + " .ltorg \n" + : : "X"(HardFault_c_handler) + ); +} +#endif //NRF_MODULE_ENABLED(HARDFAULT_HANDLER) diff --git a/components/libraries/hardfault/nrf51/handler/hardfault_handler_iar.c b/components/libraries/hardfault/nrf51/handler/hardfault_handler_iar.c new file mode 100644 index 0000000..31d21af --- /dev/null +++ b/components/libraries/hardfault/nrf51/handler/hardfault_handler_iar.c @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(HARDFAULT_HANDLER) +#include +#include "compiler_abstraction.h" + +#pragma section = "CSTACK" +extern void HardFault_c_handler( uint32_t * ); + +__stackless void HardFault_Handler(void); + +__stackless void HardFault_Handler(void) +{ + __ASM volatile( + " ldr r0, 100f \n" + " cmp r0, lr \n" + " bne 1f \n" + /* Reading PSP into R0 */ + " mrs r0, PSP \n" + " b 3f \n" + "1: \n" + /* Reading MSP into R0 */ + " mrs r0, MSP \n" + /* ----------------------------------------------------------------- + * If we have selected MSP check if we may use stack safetly. + * If not - reset the stack to the initial value. */ + " ldr r1, 101f \n" + " ldr r2, 102f \n" + + /* MSP is in the range of the stack area */ + " cmp r0, r1 \n" + " bhi 2f \n" + " cmp r0, r2 \n" + " bhi 3f \n" + /* ----------------------------------------------------------------- */ + "2: \n" + " mov SP, r1 \n" + " movs r0, #0 \n" + + "3: \n" + " ldr r3, 103f \n" + " bx r3 \n" + + "DATA \n" + "100: \n" + " DC32 0xFFFFFFFD \n" + "101: \n" + " DC32 %c0 \n" + "102: \n" + " DC32 %c1 \n" + "103: \n" + " DC32 %c2 \n" + : /* Outputs */ + : /* Inputs */ + "i"(__section_end("CSTACK")), + "i"(__section_begin("CSTACK")), + "i"(&HardFault_c_handler) + ); +} +#endif //NRF_MODULE_ENABLED(HARDFAULT_HANDLER) diff --git a/components/libraries/hardfault/nrf51/handler/hardfault_handler_keil.c b/components/libraries/hardfault/nrf51/handler/hardfault_handler_keil.c new file mode 100644 index 0000000..ff8f51e --- /dev/null +++ b/components/libraries/hardfault/nrf51/handler/hardfault_handler_keil.c @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(HARDFAULT_HANDLER) +#include +#include "compiler_abstraction.h" + + +//lint -save -e27 + +__ASM void HardFault_Handler(void) +{ + PRESERVE8 + EXTERN HardFault_c_handler + EXTERN |STACK$$Base| + EXTERN |STACK$$Limit| + + ldr r0, =0xFFFFFFFD + cmp r0, lr + bne HardFault_Handler_ChooseMSP + /* Reading PSP into R0 */ + mrs r0, PSP + b HardFault_Handler_Continue +HardFault_Handler_ChooseMSP + /* Reading MSP into R0 */ + mrs r0, MSP + /* ----------------------------------------------------------------- + * If we have selected MSP, check if we may use stack safely. + * If not - reset the stack to the initial value. */ + ldr r1, =|STACK$$Limit| + ldr r2, =|STACK$$Base| + + /* MSP is in the range of the stack area */ + cmp r0, r1 + bhi HardFault_MoveSP + cmp r0, r2 + bhi HardFault_Handler_Continue + /* ----------------------------------------------------------------- */ +HardFault_MoveSP + mov SP, r1 + movs r0, #0 + +HardFault_Handler_Continue + ldr r3, =HardFault_c_handler + bx r3 + + ALIGN +} + +//lint -restore +#endif //NRF_MODULE_ENABLED(HARDFAULT_HANDLER) diff --git a/components/libraries/hardfault/nrf52/handler/hardfault_handler_gcc.c b/components/libraries/hardfault/nrf52/handler/hardfault_handler_gcc.c new file mode 100644 index 0000000..955905e --- /dev/null +++ b/components/libraries/hardfault/nrf52/handler/hardfault_handler_gcc.c @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(HARDFAULT_HANDLER) +#include +#include "compiler_abstraction.h" + +extern void HardFault_c_handler(uint32_t *); + +void HardFault_Handler(void) __attribute__(( naked )); + +void HardFault_Handler(void) +{ + __ASM volatile( + " tst lr, #4 \n" + + /* PSP is quite simple and does not require additional handler */ + " itt ne \n" + " mrsne r0, psp \n" + /* Jump to the handler, do not store LR - returning from handler just exits exception */ + " bne HardFault_Handler_Continue \n" + + /* Processing MSP requires stack checking */ + " mrs r0, msp \n" + + " ldr r1, =__StackTop \n" + " ldr r2, =__StackLimit \n" + + /* MSP is in the range of the stack area */ + " cmp r0, r1 \n" + " bhi HardFault_MoveSP \n" + " cmp r0, r2 \n" + " bhi HardFault_Handler_Continue \n" + + "HardFault_MoveSP: \n" + " mov sp, r1 \n" + " mov r0, #0 \n" + + "HardFault_Handler_Continue: \n" + " ldr r3, =%0 \n" + " bx r3 \n" + " .ltorg \n" + : : "X"(HardFault_c_handler) + ); +} +#endif //NRF_MODULE_ENABLED(HARDFAULT_HANDLER) diff --git a/components/libraries/hardfault/nrf52/handler/hardfault_handler_iar.c b/components/libraries/hardfault/nrf52/handler/hardfault_handler_iar.c new file mode 100644 index 0000000..72c9a1d --- /dev/null +++ b/components/libraries/hardfault/nrf52/handler/hardfault_handler_iar.c @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(HARDFAULT_HANDLER) +#include +#include "compiler_abstraction.h" + +#pragma section = "CSTACK" +extern void HardFault_c_handler( uint32_t * ); + +__stackless void HardFault_Handler(void); + +__stackless void HardFault_Handler(void) +{ + __ASM volatile( + " ldr.n r3, 103f \n" + " tst lr, #4 \n" + + /* PSP is quite simple and does not require additional handler */ + " itt ne \n" + " mrsne r0, psp \n" + /* Jump to the handler, do not store LR - returning from handler just exits exception */ + " bxne r3 \n" + + /* Processing MSP requires stack checking */ + " mrs r0, msp \n" + + " ldr.n r1, 101f \n" + " ldr.n r2, 102f \n" + + /* MSP is in the range of the stack area */ + " cmp r0, r1 \n" + " bhi.n 1f \n" + " cmp r0, r2 \n" + " bhi.n 2f \n" + + "1: \n" + " mov sp, r1 \n" + " mov r0, #0 \n" + + "2: \n" + " bx r3 \n" + /* Data alignment if required */ + " nop \n" + + "DATA \n" + "101: \n" + " DC32 %c0 \n" + "102: \n" + " DC32 %c1 \n" + "103: \n" + " DC32 %c2 \n" + : /* Outputs */ + : /* Inputs */ + "i"(__section_end("CSTACK")), + "i"(__section_begin("CSTACK")), + "i"(&HardFault_c_handler) + ); +} +#endif //NRF_MODULE_ENABLED(HARDFAULT_HANDLER) diff --git a/components/libraries/hardfault/nrf52/handler/hardfault_handler_keil.c b/components/libraries/hardfault/nrf52/handler/hardfault_handler_keil.c new file mode 100644 index 0000000..54e70d7 --- /dev/null +++ b/components/libraries/hardfault/nrf52/handler/hardfault_handler_keil.c @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(HARDFAULT_HANDLER) +#include +#include "compiler_abstraction.h" + + +//lint -save -e27 + +__ASM void HardFault_Handler(void) +{ + PRESERVE8 + EXTERN HardFault_c_handler + EXTERN |STACK$$Base| + EXTERN |STACK$$Limit| + + ldr r3, =HardFault_c_handler + tst lr, #4 + + /* PSP is quite simple and does not require additional handler */ + itt ne + mrsne r0, psp + /* Jump to the handler, do not store LR - returning from handler just exits exception */ + bxne r3 + + /* Processing MSP requires stack checking */ + mrs r0, msp + + ldr r1, =|STACK$$Limit| + ldr r2, =|STACK$$Base| + + /* MSP is in the range of the stack area */ + cmp r0, r1 + bhi HardFault_MoveSP + cmp r0, r2 + bhi HardFault_Handler_Continue + +HardFault_MoveSP + mov sp, r1 + mov r0, #0 + +HardFault_Handler_Continue + bx r3 + + ALIGN +} + +//lint -restore +#endif //NRF_MODULE_ENABLED(HARDFAULT_HANDLER) diff --git a/components/libraries/log/nrf_log.h b/components/libraries/log/nrf_log.h new file mode 100644 index 0000000..a3afcea --- /dev/null +++ b/components/libraries/log/nrf_log.h @@ -0,0 +1,296 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_log Logger module + * @{ + * @ingroup app_common + * + * @brief The nrf_log module interface. + */ + +#ifndef NRF_LOG_H_ +#define NRF_LOG_H_ + +#include "sdk_common.h" +#include "nrf_section.h" +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "nrf_strerror.h" +#define NRF_LOG_ERROR_STRING_GET(code) nrf_strerror_get(code) +#else +#define NRF_LOG_ERROR_STRING_GET(code) "" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Severity level for the module. + * + * The severity level can be defined in a module to override the default. + */ +#ifndef NRF_LOG_LEVEL + #define NRF_LOG_LEVEL NRF_LOG_DEFAULT_LEVEL +#endif + +/** @brief Initial severity if filtering is enabled. + */ +#ifndef NRF_LOG_INITIAL_LEVEL + #define NRF_LOG_INITIAL_LEVEL NRF_LOG_LEVEL +#endif + + +#include "nrf_log_internal.h" + +/** @def NRF_LOG_ERROR + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ + +/** @def NRF_LOG_WARNING + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs. + */ + +/** @def NRF_LOG_INFO + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs. + */ + +/** @def NRF_LOG_DEBUG + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs. + */ + +#define NRF_LOG_ERROR(...) NRF_LOG_INTERNAL_ERROR(__VA_ARGS__) +#define NRF_LOG_WARNING(...) NRF_LOG_INTERNAL_WARNING( __VA_ARGS__) +#define NRF_LOG_INFO(...) NRF_LOG_INTERNAL_INFO( __VA_ARGS__) +#define NRF_LOG_DEBUG(...) NRF_LOG_INTERNAL_DEBUG( __VA_ARGS__) + +/** @def NRF_LOG_INST_ERROR + * @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @param p_inst Pointer to the instance with logging support. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ + +/** @def NRF_LOG_INST_WARNING + * @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @param p_inst Pointer to the instance with logging support. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ + +/** @def NRF_LOG_INST_INFO + * @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @param p_inst Pointer to the instance with logging support. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ + +/** @def NRF_LOG_INST_DEBUG + * @brief Macro for logging error messages for given module instance. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @param p_inst Pointer to the instance with logging support. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ +#define NRF_LOG_INST_ERROR(p_inst,...) NRF_LOG_INTERNAL_INST_ERROR(p_inst,__VA_ARGS__) +#define NRF_LOG_INST_WARNING(p_inst,...) NRF_LOG_INTERNAL_INST_WARNING(p_inst,__VA_ARGS__) +#define NRF_LOG_INST_INFO(p_inst,...) NRF_LOG_INTERNAL_INST_INFO(p_inst, __VA_ARGS__) +#define NRF_LOG_INST_DEBUG(p_inst,...) NRF_LOG_INTERNAL_INST_DEBUG(p_inst, __VA_ARGS__) + +/** + * @brief Macro for logging a formatted string without any prefix or timestamp. + */ +#define NRF_LOG_RAW_INFO(...) NRF_LOG_INTERNAL_RAW_INFO( __VA_ARGS__) + +/** @def NRF_LOG_HEXDUMP_ERROR + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_WARNING + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_INFO + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_DEBUG + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +#define NRF_LOG_HEXDUMP_ERROR(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) +#define NRF_LOG_HEXDUMP_WARNING(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) +#define NRF_LOG_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) +#define NRF_LOG_HEXDUMP_DEBUG(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) + +/** @def NRF_LOG_HEXDUMP_INST_ERROR + * @brief Macro for logging raw bytes for a specific module instance. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_inst Pointer to the instance with logging support. + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_INST_WARNING + * @brief Macro for logging raw bytes for a specific module instance. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_inst Pointer to the instance with logging support. + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_INST_INFO + * @brief Macro for logging raw bytes for a specific module instance. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_inst Pointer to the instance with logging support. + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_INST_DEBUG + * @brief Macro for logging raw bytes for a specific module instance. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_inst Pointer to the instance with logging support. + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +#define NRF_LOG_HEXDUMP_INST_ERROR(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_ERROR(p_inst, p_data, len) +#define NRF_LOG_HEXDUMP_INST_WARNING(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_WARNING(p_inst, p_data, len) +#define NRF_LOG_HEXDUMP_INST_INFO(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_INFO(p_inst, p_data, len) +#define NRF_LOG_HEXDUMP_INST_DEBUG(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_DEBUG(p_inst, p_data, len) + +/** + * @brief Macro for logging hexdump without any prefix or timestamp. + */ +#define NRF_LOG_RAW_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) + + +/** + * @brief Macro for copying a string to internal logger buffer if logs are deferred. + * + * @param _str String. + */ +#define NRF_LOG_PUSH(_str) NRF_LOG_INTERNAL_LOG_PUSH(_str) + +/** + * @brief Function for copying a string to the internal logger buffer if logs are deferred. + * + * Use this function to store a string that is volatile (for example allocated + * on stack) or that may change before the deferred logs are processed. Such string is copied + * into the internal logger buffer (see @ref NRF_LOG_STR_PUSH_BUFFER_SIZE). + * + * @note String storing is not reliable. It means that string is copied to the buffer but there is + * no indication when it was used and could be freed. String may be overwritten by another + * @ref nrf_log_push call before being processed. For reliable data dumping use + * hexdump macros (e.g. @ref NRF_LOG_HEXDUMP_INFO). + * + * @note If the logs are not deferred, then this function returns the input parameter. + * + * @param p_str Pointer to the user string. + * + * @return Address to the location where the string is stored in the internal logger buffer. + */ +char const * nrf_log_push(char * const p_str); + +/** + * @brief Macro to be used in a formatted string to a pass float number to the log. + * + * Use this macro in a formatted string instead of the %f specifier together with + * @ref NRF_LOG_FLOAT macro. + * Example: NRF_LOG_INFO("My float number" NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(f))) + */ +#define NRF_LOG_FLOAT_MARKER "%s%d.%02d" + +/** + * @brief Macro for dissecting a float number into two numbers (integer and residuum). + */ +#define NRF_LOG_FLOAT(val) (uint32_t)(((val) < 0 && (val) > -1.0) ? "-" : ""), \ + (int32_t)(val), \ + (int32_t)((((val) > 0) ? (val) - (int32_t)(val) \ + : (int32_t)(val) - (val))*100) + + +/** + * @brief Macro for registering an independent module. + * + * Registration creates set of dynamic (RAM) and constant variables associated with the module. + */ +#define NRF_LOG_MODULE_REGISTER() NRF_LOG_INTERNAL_MODULE_REGISTER() + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_LOG_H_ + +/** @} */ diff --git a/components/libraries/log/nrf_log_backend_flash.h b/components/libraries/log/nrf_log_backend_flash.h new file mode 100644 index 0000000..26e6688 --- /dev/null +++ b/components/libraries/log/nrf_log_backend_flash.h @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + /**@file + * + * @defgroup nrf_log_backend_flash Flash logger backend + * @{ + * @ingroup nrf_log + * @brief Flash logger backend. + */ + +#ifndef NRF_LOG_BACKEND_FLASH_H +#define NRF_LOG_BACKEND_FLASH_H + +#include "nrf_log_backend_interface.h" +#include "nrf_fstorage.h" +#include "nrf_log_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Flashlog logger backend API. */ +extern const nrf_log_backend_api_t nrf_log_backend_flashlog_api; + +/** @brief Crashlog logger backend API. */ +extern const nrf_log_backend_api_t nrf_log_backend_crashlog_api; + +/** @brief Flashlog logger backend structure. */ +typedef struct { + nrf_log_backend_t backend; +} nrf_log_backend_flashlog_t; + +/** @brief Crashlog logger backend structure. */ +typedef struct { + nrf_log_backend_t backend; +} nrf_log_backend_crashlog_t; + +/** @brief Macro for creating an instance of the flashlog logger backend. */ +#define NRF_LOG_BACKEND_FLASHLOG_DEF(_name) \ + NRF_LOG_BACKEND_DEF(_name, nrf_log_backend_flashlog_api, NULL) + +/** @brief Macro for creating an instance of the crashlog logger backend. */ +#define NRF_LOG_BACKEND_CRASHLOG_DEF(_name) \ + NRF_LOG_BACKEND_DEF(_name, nrf_log_backend_crashlog_api, NULL) + +/** + * @brief Function for initializing the flash logger backend. + * + * Flash logger backend consists of two logical backends: flashlog and crashlog. Since both + * backends write to the same flash area, the initialization is common. + * + * @param p_fs_api fstorage API to be used. + * + * @return NRF_SUCCESS or error code returned by @ref nrf_fstorage_init. + */ +ret_code_t nrf_log_backend_flash_init(nrf_fstorage_api_t const * p_fs_api); + +/** + * @brief Function for getting a log entry stored in flash. + * + * Log messages stored in flash can be read one by one starting from the oldest one. + * + * @param[in, out] p_token Token reused between consecutive readings of log entries. + * Token must be set to 0 to read the first entry. + * @param[out] pp_header Pointer to the entry header. + * @param[out] pp_data Pointer to the data part of the entry (arguments or data in case of hexdump). + * + * @retval NRF_SUCCESS Entry was successfully read. + * @retval NRF_ERROR_NOT_SUPPORTED fstorage API does not support direct reading. + * @retval NRF_ERROR_NOT_FOUND Entry not found. Last entry was already reached or area is empty. + */ +ret_code_t nrf_log_backend_flash_next_entry_get(uint32_t * p_token, + nrf_log_header_t * * pp_header, + uint8_t * * pp_data); + +/** + * @brief Function for erasing flash area dedicated for the flash logger backend. + */ +ret_code_t nrf_log_backend_flash_erase(void); + +#ifdef __cplusplus +} +#endif + +#endif //NRF_LOG_BACKEND_UART_H + +/** @} */ diff --git a/components/libraries/log/nrf_log_backend_interface.h b/components/libraries/log/nrf_log_backend_interface.h new file mode 100644 index 0000000..067b59c --- /dev/null +++ b/components/libraries/log/nrf_log_backend_interface.h @@ -0,0 +1,271 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_LOG_BACKEND_INTERFACE_H +#define NRF_LOG_BACKEND_INTERFACE_H + +/**@file + * @addtogroup nrf_log Logger module + * @ingroup app_common + * + * @defgroup nrf_log_backend_interface Logger backend interface + * @{ + * @ingroup nrf_log + * @brief The nrf_log backend interface. + */ + +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "nrf_memobj.h" +#endif + +#include "nrf_section.h" +#include "nordic_common.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief nrf_log entry. + */ +#if NRF_LOG_ENABLED +typedef nrf_memobj_t nrf_log_entry_t; +#else +typedef void nrf_log_entry_t; +#endif + +/* Forward declaration of the nrf_log_backend_t type. */ +typedef struct nrf_log_backend_s nrf_log_backend_t; + +/** + * @brief Logger backend API. + */ +typedef struct +{ + /** + * @brief @ref nrf_log_backend_put + */ + void (*put)(nrf_log_backend_t const * p_backend, nrf_log_entry_t * p_entry); + + /** + * @brief @ref nrf_log_backend_panic_set + */ + void (*panic_set)(nrf_log_backend_t const * p_backend); + + /** + * @brief @ref nrf_log_backend_flush + */ + void (*flush)(nrf_log_backend_t const * p_backend); +} nrf_log_backend_api_t; + +/** + * @brief Logger backend control block. + */ +typedef struct +{ + nrf_log_backend_t const * p_next; //!< Pointer to the next backend in the logger. + uint8_t id; //!< ID of the backend. + bool enabled; //!< Enable flag. +} nrf_log_backend_cb_t; + +/** + * @brief Logger backend structure. + */ +struct nrf_log_backend_s +{ + nrf_log_backend_api_t const * p_api; //!< Pointer to interface. + void * p_ctx; //!< User context. + char * p_name; //!< Name of the backend. + nrf_log_backend_cb_t * p_cb; //!< Pointer to the backend control block. +}; + + +#define NRF_LOG_BACKEND_SECTION_NAME log_backends + +#define NRF_LOG_BACKEND_SUBSECTION_NAME(_name) NRF_LOG_BACKEND_SECTION_NAME + +/** @brief Invalid ID value indicating that logger backend is not attached to the logger frontend.*/ +#define NRF_LOG_BACKEND_INVALID_ID 0xFF + +/** @brief Memory section where backends are located. */ +NRF_SECTION_DEF(NRF_LOG_BACKEND_SECTION_NAME, nrf_log_backend_t); + +/** + * @brief Macro for creating a logger backend instance. + * + * @param _name Name of the backend instance. + * @param _api Logger backend API. + * @param _p_ctx Pointer to the user context. + */ +#define NRF_LOG_BACKEND_DEF(_name, _api, _p_ctx) \ + static nrf_log_backend_cb_t CONCAT_2(log_backend_cb_, _name) = { \ + .enabled = false, \ + .id = NRF_LOG_BACKEND_INVALID_ID, \ + .p_next = NULL \ + }; \ + NRF_SECTION_ITEM_REGISTER(NRF_LOG_BACKEND_SUBSECTION_NAME(_name), \ + static const nrf_log_backend_t _name) = { \ + .p_api = &_api, \ + .p_ctx = _p_ctx, \ + .p_cb = &CONCAT_2(log_backend_cb_, _name), \ + .p_name = (char *)STRINGIFY(_name) \ + } + + +/** + * @brief Function for putting message with log entry to the backend. + * + * @param[in] p_backend Pointer to the backend instance. + * @param[in] p_msg Pointer to message with log entry. + */ +__STATIC_INLINE void nrf_log_backend_put(nrf_log_backend_t const * const p_backend, + nrf_log_entry_t * p_msg); + +/** + * @brief Function for reconfiguring backend to panic mode. + * + * @param[in] p_backend Pointer to the backend instance. + */ +__STATIC_INLINE void nrf_log_backend_panic_set(nrf_log_backend_t const * const p_backend); + +/** + * @brief Function for flushing backend. + * + * On flushing request backend should release log message(s). + * + * @param[in] p_backend Pointer to the backend instance. + */ +__STATIC_INLINE void nrf_log_backend_flush(nrf_log_backend_t const * const p_backend); + + +/** + * @brief Function for setting backend id. + * + * @note It is used internally by the logger. + * + * @param[in] p_backend Pointer to the backend instance. + * @param[in] id Id. + */ +__STATIC_INLINE void nrf_log_backend_id_set(nrf_log_backend_t const * const p_backend, uint8_t id); + +/** + * @brief Function for getting backend id. + * + * @note It is used internally by the logger. + * + * @param[in] p_backend Pointer to the backend instance. + * @return Id. + */ +__STATIC_INLINE uint8_t nrf_log_backend_id_get(nrf_log_backend_t const * const p_backend); + +/** + * @brief Function for enabling backend. + * + * @param[in] p_backend Pointer to the backend instance. + */ +__STATIC_INLINE void nrf_log_backend_enable(nrf_log_backend_t const * const p_backend); + +/** + * @brief Function for disabling backend. + * + * @param[in] p_backend Pointer to the backend instance. + */ +__STATIC_INLINE void nrf_log_backend_disable(nrf_log_backend_t const * const p_backend); + +/** + * @brief Function for checking state of the backend. + * + * @param[in] p_backend Pointer to the backend instance. + * + * @return True if backend is enabled, false otherwise. + */ +__STATIC_INLINE bool nrf_log_backend_is_enabled(nrf_log_backend_t const * const p_backend); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE void nrf_log_backend_put(nrf_log_backend_t const * const p_backend, + nrf_log_entry_t * p_msg) +{ + p_backend->p_api->put(p_backend, p_msg); +} + +__STATIC_INLINE void nrf_log_backend_panic_set(nrf_log_backend_t const * const p_backend) +{ + p_backend->p_api->panic_set(p_backend); +} + +__STATIC_INLINE void nrf_log_backend_flush(nrf_log_backend_t const * const p_backend) +{ + p_backend->p_api->flush(p_backend); +} + +__STATIC_INLINE void nrf_log_backend_id_set(nrf_log_backend_t const * const p_backend, uint8_t id) +{ + p_backend->p_cb->id = id; +} + +__STATIC_INLINE uint8_t nrf_log_backend_id_get(nrf_log_backend_t const * const p_backend) +{ + return p_backend->p_cb->id; +} + +__STATIC_INLINE void nrf_log_backend_enable(nrf_log_backend_t const * const p_backend) +{ + p_backend->p_cb->enabled = true; +} + +__STATIC_INLINE void nrf_log_backend_disable(nrf_log_backend_t const * const p_backend) +{ + p_backend->p_cb->enabled = false; +} + +__STATIC_INLINE bool nrf_log_backend_is_enabled(nrf_log_backend_t const * const p_backend) +{ + return p_backend->p_cb->enabled; +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + +#ifdef __cplusplus +} +#endif + +#endif //NRF_LOG_BACKEND_INTERFACE_H + +/** @} */ diff --git a/components/libraries/log/nrf_log_backend_rtt.h b/components/libraries/log/nrf_log_backend_rtt.h new file mode 100644 index 0000000..4281f3a --- /dev/null +++ b/components/libraries/log/nrf_log_backend_rtt.h @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + /**@file + * + * @defgroup nrf_log_backend_rtt Log RTT backend + * @{ + * @ingroup nrf_log + * @brief Log RTT backend. + */ + +#ifndef NRF_LOG_BACKEND_RTT_H +#define NRF_LOG_BACKEND_RTT_H + +#include "nrf_log_backend_interface.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const nrf_log_backend_api_t nrf_log_backend_rtt_api; + +typedef struct { + nrf_log_backend_t backend; +} nrf_log_backend_rtt_t; + +/** + * @brief RTT backend definition + * + * @param _name Name of the instance. + */ +#define NRF_LOG_BACKEND_RTT_DEF(_name) \ + NRF_LOG_BACKEND_DEF(_name, nrf_log_backend_rtt_api, NULL) + +void nrf_log_backend_rtt_init(void); + +#ifdef __cplusplus +} +#endif + +#endif //NRF_LOG_BACKEND_RTT_H + +/** @} */ diff --git a/components/libraries/log/nrf_log_backend_uart.h b/components/libraries/log/nrf_log_backend_uart.h new file mode 100644 index 0000000..87b7b32 --- /dev/null +++ b/components/libraries/log/nrf_log_backend_uart.h @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + /**@file + * + * @defgroup nrf_log_backend_uart Log UART backend + * @{ + * @ingroup nrf_log + * @brief Log UART backend. + */ + +#ifndef NRF_LOG_BACKEND_UART_H +#define NRF_LOG_BACKEND_UART_H + +#include "nrf_log_backend_interface.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const nrf_log_backend_api_t nrf_log_backend_uart_api; + +typedef struct { + nrf_log_backend_t backend; +} nrf_log_backend_uart_t; + +#define NRF_LOG_BACKEND_UART_DEF(_name) \ + NRF_LOG_BACKEND_DEF(_name, nrf_log_backend_uart_api, NULL) + +void nrf_log_backend_uart_init(void); + +#ifdef __cplusplus +} +#endif + +#endif //NRF_LOG_BACKEND_UART_H + +/** @} */ diff --git a/components/libraries/log/nrf_log_ctrl.h b/components/libraries/log/nrf_log_ctrl.h new file mode 100644 index 0000000..587173b --- /dev/null +++ b/components/libraries/log/nrf_log_ctrl.h @@ -0,0 +1,243 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_LOG_CTRL_H +#define NRF_LOG_CTRL_H + +/**@file + * @addtogroup nrf_log Logger module + * @ingroup app_common + * + * @defgroup nrf_log_ctrl Functions for controlling nrf_log + * @{ + * @ingroup nrf_log + * @brief The nrf_log control interface. + */ + +#include "sdk_config.h" +#include "sdk_errors.h" +#include +#include +#include "nrf_log_types.h" +#include "nrf_log_ctrl_internal.h" +#include "nrf_log_backend_interface.h" +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Timestamp function prototype. + * + * @return Timestamp value. + */ +typedef uint32_t (*nrf_log_timestamp_func_t)(void); + + +/**@brief Macro for initializing the logs. + * + * Macro has one or two parameters. First parameter (obligatory) is the timestamp function (@ref nrf_log_timestamp_func_t). + * Additionally, as the second parameter timestamp frequency in Hz can be provided. If not provided then default + * frequency is used (@ref NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY). Frequency is used to format timestamp prefix if + * @ref NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED is set. + * + * @return NRF_SUCCESS after successful initialization, otherwise an error code. + */ +#define NRF_LOG_INIT(...) NRF_LOG_INTERNAL_INIT(__VA_ARGS__) + + +/**@brief Macro for processing a single log entry from a queue of deferred logs. + * + * You can call this macro from the main context or from the error handler to process + * log entries one by one. + * + * @note If logs are not deferred, this call has no use and is defined as 'false'. + * + * @retval true There are more logs to process in the buffer. + * @retval false No more logs in the buffer. + */ +#define NRF_LOG_PROCESS() NRF_LOG_INTERNAL_PROCESS() + +/** @brief Macro for processing all log entries from the buffer. + * It blocks until all buffered entries are processed by the backend. + * + * @note If logs are not deferred, this call has no use and is empty. + */ +#define NRF_LOG_FLUSH() NRF_LOG_INTERNAL_FLUSH() + +/** @brief Macro for flushing log data before reset. + * + * @note If logs are not deferred, this call has no use and is empty. + * + * @note If RTT is used, then a breakpoint is hit once flushed. + */ +#define NRF_LOG_FINAL_FLUSH() NRF_LOG_INTERNAL_FINAL_FLUSH() + +/** + * @brief Function for initializing the frontend and the default backend. + * + * @ref NRF_LOG_INIT calls this function to initialize the frontend and the backend. + * If custom backend is used, then @ref NRF_LOG_INIT should not be called. + * Instead, frontend and user backend should be verbosely initialized. + * + * @param timestamp_func Function for getting a 32-bit timestamp. + * @param timestamp_freq Frequency of the timestamp. + * + * @return Error status. + * + */ +ret_code_t nrf_log_init(nrf_log_timestamp_func_t timestamp_func, uint32_t timestamp_freq); + +/** + * @brief Function for adding new backend interface to the logger. + * + * @param p_backend Pointer to the backend interface. + * @param severity Initial value of severity level for each module forwarded to the backend. This + * option is only applicable if @ref NRF_LOG_FILTERS_ENABLED is set. + * @return -1 if backend cannot be added or positive number (backend ID). + */ +int32_t nrf_log_backend_add(nrf_log_backend_t const * p_backend, nrf_log_severity_t severity); + +/** + * @brief Function for removing backend from the logger. + * + * @param p_backend Pointer to the backend interface. + * + */ +void nrf_log_backend_remove(nrf_log_backend_t const * p_backend); + +/** + * @brief Function for setting logger backends into panic mode. + * + * When this function is called all attached backends are informed about panic state of the system. + * It is up to the backend to react properly (hold or process logs in blocking mode, etc.) + */ +void nrf_log_panic(void); + +/** + * @brief Function for handling a single log entry. + * + * Use this function only if the logs are buffered. It takes a single entry from the + * buffer and attempts to process it. + * + * @retval true If there are more entries to process. + * @retval false If there are no more entries to process. + */ +bool nrf_log_frontend_dequeue(void); + +/** + * @brief Function for getting number of independent log modules registered into the logger. + * + * @return Number of registered modules. + */ +uint32_t nrf_log_module_cnt_get(void); + +/** + * @brief Function for getting module name. + * + * @param module_id Module ID. + * @param is_ordered_idx Module ID is given is index in alphabetically sorted list of modules. + * @return Pointer to string with module name. + */ +const char * nrf_log_module_name_get(uint32_t module_id, bool is_ordered_idx); + +/** + * @brief Function for getting coloring of specific logs. + * + * @param module_id Module ID. + * @param severity Log severity. + * + * @return ID of the color. + */ +uint8_t nrf_log_color_id_get(uint32_t module_id, nrf_log_severity_t severity); + +/** + * @brief Function for configuring filtering ofs logs in the module. + * + * Filtering of logs in modules is independent for each backend. + * + * @param backend_id Backend ID which want to chenge its configuration. + * @param module_id Module ID which logs will be reconfigured. + * @param severity New severity filter. + */ +void nrf_log_module_filter_set(uint32_t backend_id, + uint32_t module_id, + nrf_log_severity_t severity); + +/** + * @brief Function for getting module severity level. + * + * @param backend_id Backend ID. + * @param module_id Module ID. + * @param is_ordered_idx Module ID is given is index in alphabetically sorted list of modules. + * @param dynamic It true current filter for given backend is returned. If false then + * compiled-in level is returned (maximum available). If this parameter is + * false then backend_id parameter is not used. + * + * @return Severity. + */ +nrf_log_severity_t nrf_log_module_filter_get(uint32_t backend_id, + uint32_t module_id, + bool is_ordered_idx, + bool dynamic); + +/** + * @brief Function stores current filtering configuration into non-volatile memory using @ref fds module. + * + * @return NRF_SUCCESS or @ref fds error code. + */ +ret_code_t nrf_log_config_store(void); + +/** + * @brief Function loads configuration from non-volatile memory using @ref fds module. + * + * @retval NRF_SUCCESS On successful loading. + * @retval NRF_ERROR_NOT_FOUND Configuration file not found. + * @retval NRF_ERROR_INTERNAL Other @ref fds error on reading configuration file. + */ +ret_code_t nrf_log_config_load(void); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_LOG_CTRL_H + +/** + *@} + **/ diff --git a/components/libraries/log/nrf_log_default_backends.h b/components/libraries/log/nrf_log_default_backends.h new file mode 100644 index 0000000..191c3a6 --- /dev/null +++ b/components/libraries/log/nrf_log_default_backends.h @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_LOG_DEFAULT_BACKENDS_H__ +#define NRF_LOG_DEFAULT_BACKENDS_H__ + +/**@file + * @addtogroup nrf_log Logger module + * @ingroup app_common + * + * @defgroup nrf_log_default_backends Functions for initializing and adding default backends + * @{ + * @ingroup nrf_log + * @brief The nrf_log default backends. + */ + +#include "sdk_config.h" +#include "sdk_errors.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def NRF_LOG_DEFAULT_BACKENDS_INIT + * @brief Macro for initializing default backends. + * + * Each backend enabled in configuration is initialized and added as a backend to the logger. + */ +#if NRF_LOG_ENABLED +#define NRF_LOG_DEFAULT_BACKENDS_INIT() nrf_log_default_backends_init() +#else +#define NRF_LOG_DEFAULT_BACKENDS_INIT() +#endif + +void nrf_log_default_backends_init(void); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif // NRF_LOG_DEFAULT_BACKENDS_H__ diff --git a/components/libraries/log/nrf_log_instance.h b/components/libraries/log/nrf_log_instance.h new file mode 100644 index 0000000..8e2e6dd --- /dev/null +++ b/components/libraries/log/nrf_log_instance.h @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_LOG_INSTANCE_H +#define NRF_LOG_INSTANCE_H + +#include "sdk_config.h" +#include "nrf_section.h" +#include "nrf_log_types.h" +#include + + +/* + * For GCC, sections are sorted in the group by the linker. For IAR and KEIL, it is assumed that linker will sort + * dynamic and const section in the same order (but in different locations). Proper message formatting + * is based on that assumption. + */ +#if defined(__GNUC__) +#define NRF_LOG_DYNAMIC_SECTION_NAME(_module_name) CONCAT_2(log_dynamic_data_,_module_name) +#define NRF_LOG_FILTER_SECTION_NAME(_module_name) CONCAT_2(log_filter_data_,_module_name) +#define NRF_LOG_CONST_SECTION_NAME(_module_name) CONCAT_2(log_const_data_,_module_name) +#else +#define NRF_LOG_DYNAMIC_SECTION_NAME(_module_name) log_dynamic_data +#define NRF_LOG_FILTER_SECTION_NAME(_module_name) log_filter_data +#define NRF_LOG_CONST_SECTION_NAME(_module_name) log_const_data +#endif + +#define NRF_LOG_ITEM_DATA(_name) CONCAT_3(m_nrf_log_,_name,_logs_data) +#define NRF_LOG_ITEM_DATA_DYNAMIC(_name) CONCAT_2(NRF_LOG_ITEM_DATA(_name),_dynamic) +#define NRF_LOG_ITEM_DATA_FILTER(_name) CONCAT_2(NRF_LOG_ITEM_DATA(_name),_filter) +#define NRF_LOG_ITEM_DATA_CONST(_name) CONCAT_2(NRF_LOG_ITEM_DATA(_name),_const) + +#ifdef UNIT_TEST +#define _CONST +#else +#define _CONST const +#endif + +/*lint -save -esym(526,log_const_data*) -esym(526,log_dynamic_data*)*/ +NRF_SECTION_DEF(log_dynamic_data, nrf_log_module_dynamic_data_t); +NRF_SECTION_DEF(log_filter_data, nrf_log_module_filter_data_t); +NRF_SECTION_DEF(log_const_data, nrf_log_module_const_data_t); +/*lint -restore*/ + +#define NRF_LOG_INTERNAL_CONST_ITEM_REGISTER( \ + _name, _str_name, _info_color, _debug_color, _initial_lvl, _compiled_lvl) \ + NRF_SECTION_ITEM_REGISTER(NRF_LOG_CONST_SECTION_NAME(_name), \ + _CONST nrf_log_module_const_data_t NRF_LOG_ITEM_DATA_CONST(_name)) = { \ + .p_module_name = _str_name, \ + .info_color_id = (_info_color), \ + .debug_color_id = (_debug_color), \ + .compiled_lvl = (nrf_log_severity_t)(_compiled_lvl), \ + .initial_lvl = (nrf_log_severity_t)(_initial_lvl), \ + } + +#if NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_INTERNAL_ITEM_REGISTER( \ + _name, _str_name, _info_color, _debug_color, _initial_lvl, _compiled_lvl) \ + NRF_LOG_INTERNAL_CONST_ITEM_REGISTER(_name, \ + _str_name, \ + _info_color, \ + _debug_color, \ + _initial_lvl, \ + _compiled_lvl); \ + NRF_SECTION_ITEM_REGISTER(NRF_LOG_DYNAMIC_SECTION_NAME(_name), \ + nrf_log_module_dynamic_data_t NRF_LOG_ITEM_DATA_DYNAMIC(_name)); \ + NRF_SECTION_ITEM_REGISTER(NRF_LOG_FILTER_SECTION_NAME(_name), \ + nrf_log_module_filter_data_t NRF_LOG_ITEM_DATA_FILTER(_name)) + +#else +#define NRF_LOG_INTERNAL_ITEM_REGISTER( \ + _name, _str_name, _info_color, _debug_color, _initial_lvl, _compiled_lvl) \ + NRF_LOG_INTERNAL_CONST_ITEM_REGISTER(_name, \ + _str_name, \ + _info_color, \ + _debug_color, \ + _initial_lvl, \ + _compiled_lvl) + +#endif +/**@file + * + * @defgroup nrf_log_instance Macros for logging on instance level + * @{ + * @ingroup nrf_log + * + * @brief Macros for logging on instance level + */ + +/** @def NRF_LOG_INSTANCE_PTR_DECLARE + * @brief Macro for declaring a logger instance pointer in the module stucture. + */ + +/** @def NRF_LOG_INSTANCE_REGISTER + * @brief Macro for creating an independent module instance. + * + * Module instance provides filtering of logs on instance level instead of module level. + */ + +/** @def NRF_LOG_INSTANCE_PTR_INIT + * @brief Macro for initializing a pointer to the logger instance. + */ + + + /** @} */ +#if NRF_LOG_ENABLED && NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_INSTANCE_PTR_DECLARE(_p_name) nrf_log_module_dynamic_data_t * _p_name; + +#define NRF_LOG_INSTANCE_REGISTER( \ + _module_name, _inst_name, _info_color, _debug_color, _initial_lvl, _compiled_lvl) \ + NRF_LOG_INTERNAL_ITEM_REGISTER(CONCAT_3(_module_name,_,_inst_name), \ + STRINGIFY(_module_name._inst_name), \ + _info_color, \ + _debug_color, \ + _initial_lvl, \ + _compiled_lvl) + +#define NRF_LOG_INSTANCE_PTR_INIT(_p_name, _module_name, _inst_name) \ + ._p_name = &NRF_LOG_ITEM_DATA_DYNAMIC(CONCAT_3(_module_name,_,_inst_name)), + +#else +#define NRF_LOG_INSTANCE_PTR_DECLARE(_p_name) +#define NRF_LOG_INSTANCE_REGISTER(_module_name, _inst_name, info_color, debug_color, _initial_lvl, compiled_lvl) +#define NRF_LOG_INSTANCE_PTR_INIT(_p_name, _module_name, _inst_name) +#endif + +#endif //NRF_LOG_INSTANCE_H diff --git a/components/libraries/log/nrf_log_str_formatter.h b/components/libraries/log/nrf_log_str_formatter.h new file mode 100644 index 0000000..cde283f --- /dev/null +++ b/components/libraries/log/nrf_log_str_formatter.h @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * + * @defgroup nrf_log_str_formatter String formatter for the logger messages + * @{ + * @ingroup nrf_log + */ + +#ifndef NRF_LOG_STR_FORMATTER_H +#define NRF_LOG_STR_FORMATTER_H + +#include +#include "nrf_fprintf.h" +#include "nrf_log_ctrl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + uint32_t timestamp; + uint16_t module_id; + uint16_t dropped; + nrf_log_severity_t severity; + uint8_t use_colors; +} nrf_log_str_formatter_entry_params_t; + + +void nrf_log_std_entry_process(char const * p_str, + uint32_t const * p_args, + uint32_t nargs, + nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx); + +void nrf_log_hexdump_entry_process(uint8_t * p_data, + uint32_t data_len, + nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx); + +void nrf_log_str_formatter_timestamp_freq_set(uint32_t freq); +#ifdef __cplusplus +} +#endif + +#endif //NRF_LOG_STR_FORMATTER_H +/** @} */ diff --git a/components/libraries/log/nrf_log_types.h b/components/libraries/log/nrf_log_types.h new file mode 100644 index 0000000..06478da --- /dev/null +++ b/components/libraries/log/nrf_log_types.h @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_LOG_TYPES_H +#define NRF_LOG_TYPES_H + +#include + +/** + * @brief Logger severity levels. + */ +typedef enum +{ + NRF_LOG_SEVERITY_NONE, + NRF_LOG_SEVERITY_ERROR, + NRF_LOG_SEVERITY_WARNING, + NRF_LOG_SEVERITY_INFO, + NRF_LOG_SEVERITY_DEBUG, + NRF_LOG_SEVERITY_INFO_RAW, /* Artificial level to pass information about skipping string postprocessing.*/ +} nrf_log_severity_t; + +/** + * @brief Structure holding dynamic data associated with a module. + * + * See @ref NRF_LOG_MODULE_REGISTER and @ref NRF_LOG_INSTANCE_REGISTER. + */ +typedef struct +{ + uint16_t order_idx; ///< Ordered index of the module (used for auto-completion). + uint16_t filter; ///< Current highest severity level accepted (redundant to @ref nrf_log_module_filter_data_t::filter_lvls, used for optimization) +} nrf_log_module_dynamic_data_t; + +/** + * @brief Structure holding dynamic filters associated with a module or instance if filtering is enabled (@ref NRF_LOG_FILTERS_ENABLED). + * + * @note Backend filters logically are part of @ref nrf_log_module_dynamic_data_t but they are kept separated to enable storing them in non-volatile memory. + */ +typedef struct +{ + uint32_t filter_lvls; ///< Current severity levels for each backend (3 bits per backend). +} nrf_log_module_filter_data_t; + +/** + * @brief Structure holding constant data associated with a module or instance. + * + * See @ref NRF_LOG_MODULE_REGISTER and @ref NRF_LOG_INSTANCE_REGISTER. + */ +typedef struct +{ + const char * p_module_name; ///< Module or instance name. + uint8_t info_color_id; ///< Color code of info messages. + uint8_t debug_color_id; ///< Color code of debug messages. + nrf_log_severity_t compiled_lvl; ///< Compiled highest severity level. + nrf_log_severity_t initial_lvl; ///< Severity level for given module or instance set on backend initialization. +} nrf_log_module_const_data_t; + +#endif //NRF_LOG_TYPES_H diff --git a/components/libraries/log/src/nrf_log_backend_flash.c b/components/libraries/log/src/nrf_log_backend_flash.c new file mode 100644 index 0000000..e65b3b0 --- /dev/null +++ b/components/libraries/log/src/nrf_log_backend_flash.c @@ -0,0 +1,740 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_FLASH) +#include "nrf_log_backend_flash.h" +#include "nrf_log_str_formatter.h" +#include "nrf_fstorage_nvmc.h" +#include "nrf_log.h" +#include "nrf_atomic.h" +#include "nrf_queue.h" +#include "app_error.h" +#include + +#if (NRF_LOG_BACKEND_FLASHLOG_ENABLED == 0) && (NRF_LOG_BACKEND_CRASHLOG_ENABLED == 0) +#error "No flash backend enabled." +#endif + +/** @brief Maximum logger message payload (arguments or data in hexdump) which can be stored. */ +#define FLASH_LOG_MAX_PAYLOAD_SIZE (NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE - sizeof(nrf_log_header_t)) + +/** @brief Size of serialization buffer in words. */ +#define FLASH_LOG_SER_BUFFER_WORDS (NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE/sizeof(uint32_t)) + +/** @brief Length of logger header. */ +#define LOG_HEADER_LEN (sizeof(nrf_log_header_t)) + +/** @brief Length of logger header given in 32 bit words. */ +#define LOG_HEADER_LEN_WORDS (LOG_HEADER_LEN/sizeof(uint32_t)) + +/** @brief Maximum possible length of standard log message. */ +#define STD_LOG_MSG_MAX_LEN (LOG_HEADER_LEN + NRF_LOG_MAX_NUM_OF_ARGS*sizeof(uint32_t)) + +/* Buffer must be multiple of 4. */ +STATIC_ASSERT((NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE % sizeof(uint32_t)) == 0); + +/* Buffer must fit standard log message. */ +STATIC_ASSERT(NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE >= STD_LOG_MSG_MAX_LEN); + +/** @brief Flash page size in bytes. */ +#define CODE_PAGE_SIZE 4096 + +/** @brief Start address of the area dedicated for flash log. */ +#define FLASH_LOG_START_ADDR (NRF_LOG_BACKEND_FLASH_START_PAGE * CODE_PAGE_SIZE) + +/** @brief End address of the area dedicated for flash log. */ +#define FLASH_LOG_END_ADDR (FLASH_LOG_START_ADDR + (NRF_LOG_BACKEND_PAGES * CODE_PAGE_SIZE) - 1) + +/** @brief Size of the area dedicated for flash log. */ +#define FLASH_LOG_SIZE (NRF_LOG_BACKEND_PAGES * CODE_PAGE_SIZE) + +/** @brief Start address determined in runtime. + * + * If configuration indicates that flash log should be placed after application. + * */ +#if defined ( __CC_ARM ) +#define RUNTIME_START_ADDR \ + _Pragma("diag_suppress 170") \ + ((NRF_LOG_BACKEND_FLASH_START_PAGE == 0) ? \ + (CODE_PAGE_SIZE*CEIL_DIV((uint32_t)CODE_END, CODE_PAGE_SIZE)) : FLASH_LOG_START_ADDR) \ + _Pragma("diag_default 170") +#else +#define RUNTIME_START_ADDR ((NRF_LOG_BACKEND_FLASH_START_PAGE == 0) ? \ + (CODE_PAGE_SIZE*CEIL_DIV((uint32_t)CODE_END, CODE_PAGE_SIZE)) : FLASH_LOG_START_ADDR) +#endif +static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt); + +/** @brief Message queue for run time flash log. */ +#if NRF_LOG_BACKEND_FLASHLOG_ENABLED +NRF_QUEUE_DEF(nrf_log_entry_t *, + m_flashlog_queue, + NRF_LOG_BACKEND_FLASHLOG_QUEUE_SIZE, + NRF_QUEUE_MODE_NO_OVERFLOW); +static const nrf_queue_t * mp_flashlog_queue = &m_flashlog_queue; +#else +static const nrf_queue_t * mp_flashlog_queue = NULL; +#endif + + +/** @brief Message FIFO for crash log. */ +#if NRF_LOG_BACKEND_CRASHLOG_ENABLED +NRF_QUEUE_DEF(nrf_log_entry_t *, + m_crashlog_queue, + NRF_LOG_BACKEND_CRASHLOG_FIFO_SIZE, + NRF_QUEUE_MODE_NO_OVERFLOW); +static const nrf_queue_t * mp_crashlog_queue = &m_crashlog_queue; +#else +static const nrf_queue_t * mp_crashlog_queue = NULL; +#endif + + +/** @brief Fstorage instance used for flash log. */ +NRF_FSTORAGE_DEF(nrf_fstorage_t m_log_flash_fstorage) = +{ + /* Set a handler for fstorage events. */ + .evt_handler = fstorage_evt_handler, + .start_addr = FLASH_LOG_START_ADDR, + .end_addr = FLASH_LOG_END_ADDR, +}; + +/** @brief Flash log state. */ +typedef enum +{ + LOG_BACKEND_FLASH_ACTIVE, /**< Flash backend is active. */ + LOG_BACKEND_FLASH_INACTIVE, /**< Flash backend is inactive. All incoming requests are skipped. */ + LOG_BACKEND_FLASH_IN_PANIC, /**< Flash backend is in panic mode. Incoming messages are written to flash in synchronous mode. */ +} log_backend_flash_state_t; + +static log_backend_flash_state_t m_state; /**< Flash logger backend state. */ +static nrf_atomic_flag_t m_busy_flag; /**< Flag indicating if module performs flash writing. */ +static uint32_t m_flash_buf[FLASH_LOG_SER_BUFFER_WORDS]; /**< Buffer used for serializing messages. */ +static uint32_t m_curr_addr; /**< Address of free spot in the storage area. */ +static size_t m_curr_len; /**< Length of current message being written. */ +static uint32_t m_dropped; /**< Number of dropped messages. */ + +/** @brief Log message string injected when entering panic mode. */ +static const char crashlog_str[] = "-----------CRASHLOG------------\r\n"; + +/** @brief Function saturates input to maximum possible length and rounds up value to be multiple + * of word size. + * + * @param length Length value. + * + * @return Modified input length. + */ +static uint32_t saturate_align_length(uint32_t length) +{ + length = (length > FLASH_LOG_MAX_PAYLOAD_SIZE) ? FLASH_LOG_MAX_PAYLOAD_SIZE : length; //saturate + length = CEIL_DIV(length, sizeof(uint32_t))*sizeof(uint32_t); + return length; +} + + +/** + * @brief Function for copying logger message to the buffer. + * + * @param[in] p_msg Logger message. + * @param[out] p_buf Output buffer where serialized message is placed. + * @param[in,out] p_len Buffer size as input, length of prepared data as output. + * + * @return True if message fits into the buffer, false otherwise + */ +static bool msg_to_buf(nrf_log_entry_t * p_msg, uint8_t * p_buf, size_t * p_len) +{ + uint32_t data_len; + nrf_log_header_t header = {0}; + size_t memobj_offset = HEADER_SIZE*sizeof(uint32_t); + + nrf_memobj_read(p_msg, &header, HEADER_SIZE*sizeof(uint32_t), 0); + + memcpy(p_buf, &header, sizeof(nrf_log_header_t)); + p_buf += sizeof(nrf_log_header_t); + + switch (header.base.generic.type) + { + case HEADER_TYPE_STD: + { + data_len = header.base.std.nargs * sizeof(uint32_t); + break; + } + case HEADER_TYPE_HEXDUMP: + { + data_len = saturate_align_length(header.base.hexdump.len); + break; + } + default: + *p_len = 0; + return false; + } + nrf_memobj_read(p_msg, p_buf, data_len, memobj_offset); + + if (*p_len >= sizeof(nrf_log_header_t) + data_len) + { + *p_len = sizeof(nrf_log_header_t) + data_len; + return true; + } + else + { + return false; + } +} + +/** + * @brief Function for getting logger message stored in flash. + * + * @param[in] p_buf Pointer to the location where message is stored. + * @param[out] pp_header Pointer to the log message header. + * @param[out] pp_data Pointer to the log message data (arguments or data in case of hexdump). + * + * @return True if message was successfully fetched, false otherwise. + */ +static bool msg_from_buf(uint32_t * p_buf, + nrf_log_header_t * * pp_header, + uint8_t * * pp_data, + uint32_t * p_len) +{ + *pp_header = (nrf_log_header_t *)p_buf; + *pp_data = (uint8_t *)&p_buf[LOG_HEADER_LEN_WORDS]; + + uint32_t data_len; + + switch ((*pp_header)->base.generic.type) + { + case HEADER_TYPE_STD: + { + data_len = ((*pp_header)->base.std.nargs)*sizeof(uint32_t); + break; + } + case HEADER_TYPE_HEXDUMP: + { + + data_len = saturate_align_length((*pp_header)->base.hexdump.len); + break; + } + default: + return false; + } + + *p_len = LOG_HEADER_LEN + data_len; + return true; +} + +/** + * @brief Function for processing log message queue. + * + * If writing to flash is synchronous then function drains the queue and writes all messages to flash. + * If writing to flash is asynchronous then function starts single write operation. In asynchronous mode + * function is called when new message is put into the queue from from flash operation callback. + * + * Function detects the situation that flash module reports attempt to write outside dedicated area. + * In that case flash backend stops writing any new messages. + * + * @param p_queue Queue will log messages + * @param fstorage_blocking If true it indicates that flash operations are blocking, event handler is not used. + */ +static void log_msg_queue_process(nrf_queue_t const * p_queue, bool fstorage_blocking) +{ + nrf_log_entry_t * p_msg; + bool busy = false; + while (nrf_queue_pop(p_queue, &p_msg) == NRF_SUCCESS) + { + ret_code_t err_code; + + m_curr_len = sizeof(m_flash_buf); + if (!msg_to_buf(p_msg, (uint8_t *)m_flash_buf, &m_curr_len)) + { + nrf_memobj_put(p_msg); + continue; + } + + err_code = nrf_fstorage_write(&m_log_flash_fstorage, m_curr_addr, m_flash_buf, m_curr_len, p_msg); + + if (err_code == NRF_SUCCESS) + { + if (fstorage_blocking) + { + m_curr_addr += m_curr_len; + + nrf_memobj_put(p_msg); + } + else + { + busy = true; + break; + } + } + else if (!fstorage_blocking && (err_code == NRF_ERROR_NO_MEM)) + { + // fstorage queue got full. Drop entry. + nrf_memobj_put(p_msg); + m_dropped++; + break; + } + else if (err_code == NRF_ERROR_INVALID_ADDR) + { + // Trying to write outside the area, flash log is full. Skip any new writes. + nrf_memobj_put(p_msg); + m_state = LOG_BACKEND_FLASH_INACTIVE; + } + else + { + ASSERT(false); + } + } + + if (!busy) + { + UNUSED_RETURN_VALUE(nrf_atomic_flag_clear(&m_busy_flag)); + } +} + +static void queue_element_drop(nrf_queue_t const * p_queue) +{ + nrf_log_entry_t * p_msg; + if (nrf_queue_pop(p_queue, &p_msg) == NRF_SUCCESS) + { + m_dropped++; + nrf_memobj_put(p_msg); + } +} + +static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt) +{ + if (m_state == LOG_BACKEND_FLASH_ACTIVE) + { + switch (p_evt->id) + { + case NRF_FSTORAGE_EVT_WRITE_RESULT: + { + if (p_evt->result == NRF_SUCCESS) + { + m_curr_addr += m_curr_len; + m_curr_len = 0; + log_msg_queue_process(mp_flashlog_queue, false); + } + else + { + m_dropped++; + } + + if (p_evt->p_param) + { + nrf_memobj_put((nrf_log_entry_t *)p_evt->p_param); + } + break; + } + default: + break; + } + } + else if ((m_state == LOG_BACKEND_FLASH_INACTIVE) && + (p_evt->id == NRF_FSTORAGE_EVT_ERASE_RESULT) && + (p_evt->addr == RUNTIME_START_ADDR)) + { + m_state = LOG_BACKEND_FLASH_ACTIVE; + } +} + +/** + * @brief Function for enqueueing new message. + * + * If queue is full then the oldest message is freed. + * + * @param p_queue Queue. + * @param p_msg Message. + * + * @return Number of dropped messages + */ +static uint32_t message_enqueue(nrf_queue_t const * p_queue, nrf_log_entry_t * p_msg) +{ + uint32_t dropped = 0; + + //flag was set, busy so enqueue message + while (nrf_queue_push(p_queue, &p_msg) != NRF_SUCCESS) + { + + nrf_log_entry_t * p_old_msg; + if (nrf_queue_pop(p_queue, &p_old_msg) == NRF_SUCCESS) + { + nrf_memobj_put(p_old_msg); + dropped++; + } + } + + return dropped; +} + + +void nrf_log_backend_flashlog_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg) +{ + if (m_state == LOG_BACKEND_FLASH_ACTIVE) + { + nrf_memobj_get(p_msg); + + m_dropped += message_enqueue(mp_flashlog_queue, p_msg); + + if (nrf_atomic_flag_set_fetch(&m_busy_flag) == 0) + { + log_msg_queue_process(mp_flashlog_queue, false); + } + } +} + + +void nrf_log_backend_crashlog_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg) +{ + if (m_state != LOG_BACKEND_FLASH_INACTIVE) + { + nrf_memobj_get(p_msg); + + UNUSED_RETURN_VALUE(message_enqueue(mp_crashlog_queue, p_msg)); + } + + if (m_state == LOG_BACKEND_FLASH_IN_PANIC) + { + log_msg_queue_process(mp_crashlog_queue, true); + } +} + +void nrf_log_backend_flashlog_flush(nrf_log_backend_t const * p_backend) +{ + queue_element_drop(mp_flashlog_queue); +} + +void nrf_log_backend_crashlog_flush(nrf_log_backend_t const * p_backend) +{ + queue_element_drop(mp_crashlog_queue); +} + +void nrf_log_backend_flashlog_panic_set(nrf_log_backend_t const * p_backend) +{ + /* Empty */ +} + +/** + * @brief Function for injecting log message which will indicate start of crash log. + */ +static void crashlog_marker_inject(void) +{ + nrf_log_header_t crashlog_marker_hdr = { + .base = { + .std = { + .type = HEADER_TYPE_STD, + .severity = NRF_LOG_SEVERITY_INFO_RAW, + .nargs = 0, + .addr = (uint32_t)crashlog_str & STD_ADDR_MASK + } + }, + .module_id = 0, + .timestamp = 0, + }; + m_flash_buf[0] = crashlog_marker_hdr.base.raw; + m_flash_buf[1] = crashlog_marker_hdr.module_id; + m_flash_buf[2] = crashlog_marker_hdr.timestamp; + (void)nrf_fstorage_write(&m_log_flash_fstorage, m_curr_addr, m_flash_buf, LOG_HEADER_LEN, NULL); + m_curr_addr += LOG_HEADER_LEN; +} + + +void nrf_log_backend_crashlog_panic_set(nrf_log_backend_t const * p_backend) +{ + if (nrf_fstorage_init(&m_log_flash_fstorage, &nrf_fstorage_nvmc, NULL) == NRF_SUCCESS) + { + m_state = LOG_BACKEND_FLASH_IN_PANIC; + + /* In case of Softdevice MWU may protect access to NVMC. */ + NVIC_DisableIRQ(MWU_IRQn); + + log_msg_queue_process(mp_flashlog_queue, true); + + crashlog_marker_inject(); + + log_msg_queue_process(mp_crashlog_queue, true); + } + else + { + m_state = LOG_BACKEND_FLASH_INACTIVE; + } +} + +/** + * @brief Function for determining first empty location in area dedicated for flash logger backend. + */ +static uint32_t empty_addr_get(void) +{ + uint32_t token = 0; + nrf_log_header_t * p_dummy_header; + uint8_t * p_dummy_data; + + while(nrf_log_backend_flash_next_entry_get(&token, &p_dummy_header, &p_dummy_data) == NRF_SUCCESS) + { + + } + + return token; +} + + +ret_code_t nrf_log_backend_flash_init(nrf_fstorage_api_t const * p_fs_api) +{ + ret_code_t err_code; + + + uint32_t start_addr = RUNTIME_START_ADDR; + uint32_t end_addr = start_addr + FLASH_LOG_SIZE - 1; + + m_log_flash_fstorage.start_addr = start_addr; + m_log_flash_fstorage.end_addr = end_addr; + + err_code = nrf_fstorage_init(&m_log_flash_fstorage, p_fs_api, NULL); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + m_curr_addr = empty_addr_get(); + m_state = LOG_BACKEND_FLASH_ACTIVE; + + return err_code; +} + + +ret_code_t nrf_log_backend_flash_next_entry_get(uint32_t * p_token, + nrf_log_header_t * * pp_header, + uint8_t * * pp_data) +{ + uint32_t * p_addr = p_token; + uint32_t len; + + *p_addr = (*p_addr == 0) ? RUNTIME_START_ADDR : *p_addr; + + if (nrf_fstorage_rmap(&m_log_flash_fstorage, *p_addr) == NULL) + { + //Supports only memories which can be mapped for reading. + return NRF_ERROR_NOT_SUPPORTED; + } + + if (msg_from_buf((uint32_t *)*p_addr, pp_header, pp_data, &len)) + { + *p_addr += len; + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_NOT_FOUND; + } +} + + +ret_code_t nrf_log_backend_flash_erase(void) +{ + ret_code_t err_code; + + m_state = LOG_BACKEND_FLASH_INACTIVE; + err_code = nrf_fstorage_erase(&m_log_flash_fstorage, RUNTIME_START_ADDR, NRF_LOG_BACKEND_PAGES, NULL); + + m_curr_addr = RUNTIME_START_ADDR; + + return err_code; +} + +#if NRF_LOG_BACKEND_FLASHLOG_ENABLED +const nrf_log_backend_api_t nrf_log_backend_flashlog_api = { + .put = nrf_log_backend_flashlog_put, + .flush = nrf_log_backend_flashlog_flush, + .panic_set = nrf_log_backend_flashlog_panic_set, +}; +#endif + +#if NRF_LOG_BACKEND_CRASHLOG_ENABLED +const nrf_log_backend_api_t nrf_log_backend_crashlog_api = { + .put = nrf_log_backend_crashlog_put, + .flush = nrf_log_backend_crashlog_flush, + .panic_set = nrf_log_backend_crashlog_panic_set, +}; +#endif + +#if NRF_LOG_BACKEND_FLASH_CLI_CMDS +#include "nrf_cli.h" + +static uint8_t m_buffer[64]; +static nrf_cli_t const * mp_cli; + +static void cli_tx(void const * p_context, char const * p_buffer, size_t len); + +static nrf_fprintf_ctx_t m_fprintf_ctx = +{ + .p_io_buffer = (char *)m_buffer, + .io_buffer_size = sizeof(m_buffer)-1, + .io_buffer_cnt = 0, + .auto_flush = true, + .p_user_ctx = &mp_cli, + .fwrite = cli_tx +}; + + +static void flashlog_clear_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv) +{ + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + } + + UNUSED_RETURN_VALUE(nrf_log_backend_flash_erase()); +} + +#include "nrf_delay.h" +static void cli_tx(void const * p_context, char const * p_buffer, size_t len) +{ + nrf_cli_t * * pp_cli = (nrf_cli_t * *)p_context; + char * p_strbuf = (char *)&p_buffer[len]; + *p_strbuf = '\0'; + nrf_cli_fprintf((nrf_cli_t const *)*pp_cli, NRF_CLI_DEFAULT, p_buffer); + // nrf_delay_ms(10); +} + + +static void entry_process(nrf_cli_t const * p_cli, nrf_log_header_t * p_header, uint8_t * p_data) +{ + mp_cli = p_cli; + + nrf_log_str_formatter_entry_params_t params = + { + .timestamp = p_header->timestamp, + .module_id = p_header->module_id, + .use_colors = 0, + }; + + switch (p_header->base.generic.type) + { + case HEADER_TYPE_STD: + { + params.severity = (nrf_log_severity_t)p_header->base.std.severity; + nrf_log_std_entry_process((const char *)((uint32_t)p_header->base.std.addr), + (uint32_t *)p_data, + p_header->base.std.nargs, + ¶ms, + &m_fprintf_ctx); + break; + } + case HEADER_TYPE_HEXDUMP: + { + params.severity = (nrf_log_severity_t)p_header->base.hexdump.severity; + + nrf_log_hexdump_entry_process(p_data, + p_header->base.hexdump.len, + ¶ms, + &m_fprintf_ctx); + break; + } + default: + ASSERT(0); + } + +} + + +static void flashlog_read_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv) +{ + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + } + + uint32_t token = 0; + uint8_t * p_data = NULL; + bool empty = true; + nrf_log_header_t * p_header; + + while (1) + { + if (nrf_log_backend_flash_next_entry_get(&token, &p_header, &p_data) == NRF_SUCCESS) + { + entry_process(p_cli, p_header, p_data); + empty = false; + } + else + { + break; + } + } + + if (empty) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Flash log empty\r\n"); + } +} + + +static void flashlog_status_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv) +{ + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + } + + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Flash log status:\r\n"); + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\t\t- Location (address: 0x%08X, length: %d)\r\n", + RUNTIME_START_ADDR, FLASH_LOG_SIZE); + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\t\t- Current usage:%d%% (%d of %d bytes used)\r\n", + 100ul * (m_curr_addr - RUNTIME_START_ADDR)/FLASH_LOG_SIZE, + m_curr_addr - RUNTIME_START_ADDR, + FLASH_LOG_SIZE); + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\t\t- Dropped logs: %d\r\n", m_dropped); + + +} + + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_flashlog_cmd) +{ + NRF_CLI_CMD(clear, NULL, "Remove logs", flashlog_clear_cmd), + NRF_CLI_CMD(read, NULL, "Read stored logs", flashlog_read_cmd), + NRF_CLI_CMD(status, NULL, "Flash log status", flashlog_status_cmd), + NRF_CLI_SUBCMD_SET_END +}; + +NRF_CLI_CMD_REGISTER(flashlog, &m_flashlog_cmd, "Commands for reading logs stored in non-volatile memory", NULL); + +#endif //NRF_LOG_BACKEND_FLASH_CLI_CMDS + +#endif //NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_FLASH) diff --git a/components/libraries/log/src/nrf_log_backend_rtt.c b/components/libraries/log/src/nrf_log_backend_rtt.c new file mode 100644 index 0000000..fd79348 --- /dev/null +++ b/components/libraries/log/src/nrf_log_backend_rtt.c @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT) +#include "nrf_log_backend_rtt.h" +#include "nrf_log_backend_serial.h" +#include "nrf_log_str_formatter.h" +#include "nrf_log_internal.h" +#include "nrf_delay.h" +#include +#include + +static bool m_host_present; + +static uint8_t m_string_buff[NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE]; + +void nrf_log_backend_rtt_init(void) +{ + SEGGER_RTT_Init(); +} + +static void serial_tx(void const * p_context, char const * buffer, size_t len) +{ + if (len) + { + uint32_t idx = 0; + uint32_t processed; + uint32_t watchdog_counter = NRF_LOG_BACKEND_RTT_TX_RETRY_CNT; + do + { + processed = SEGGER_RTT_WriteNoLock(0, &buffer[idx], len); + idx += processed; + len -= processed; + if (processed == 0) + { + /* There are two possible reasons for not writing any data to RTT: + * - The host is not connected and not reading the data. + * - The buffer got full and will be read by the host. + * These two situations are distinguished using the following algorithm. + * At the begining, the module assumes that the host is active, + * so when no data is read, it busy waits and retries. + * If, after retrying, the host reads the data, the module assumes that the host is active. + * If it fails, the module assumes that the host is inactive and stores that information. On next + * call, only one attempt takes place. The host is marked as active if the attempt is successful. + */ + if (!m_host_present) + { + break; + } + else + { + nrf_delay_ms(NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS); + watchdog_counter--; + if (watchdog_counter == 0) + { + m_host_present = false; + break; + } + } + } + m_host_present = true; + } while (len); + } +} +static void nrf_log_backend_rtt_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg) +{ + nrf_log_backend_serial_put(p_backend, p_msg, m_string_buff, NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE, serial_tx); +} + +static void nrf_log_backend_rtt_flush(nrf_log_backend_t const * p_backend) +{ + +} + +static void nrf_log_backend_rtt_panic_set(nrf_log_backend_t const * p_backend) +{ + +} + +const nrf_log_backend_api_t nrf_log_backend_rtt_api = { + .put = nrf_log_backend_rtt_put, + .flush = nrf_log_backend_rtt_flush, + .panic_set = nrf_log_backend_rtt_panic_set, +}; +#endif //NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT) diff --git a/components/libraries/log/src/nrf_log_backend_serial.c b/components/libraries/log/src/nrf_log_backend_serial.c new file mode 100644 index 0000000..44b3e60 --- /dev/null +++ b/components/libraries/log/src/nrf_log_backend_serial.c @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "nrf_log_backend_serial.h" +#include "nrf_log_str_formatter.h" +#include "nrf_log_internal.h" + +void nrf_log_backend_serial_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg, + uint8_t * p_buffer, + uint32_t length, + nrf_fprintf_fwrite tx_func) +{ + nrf_memobj_get(p_msg); + + nrf_fprintf_ctx_t fprintf_ctx = { + .p_io_buffer = (char *)p_buffer, + .io_buffer_size = length, + .io_buffer_cnt = 0, + .auto_flush = false, + .p_user_ctx = NULL, + .fwrite = tx_func + }; + + nrf_log_str_formatter_entry_params_t params; + + nrf_log_header_t header; + size_t memobj_offset = 0; + + nrf_memobj_read(p_msg, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset); + memobj_offset = HEADER_SIZE*sizeof(uint32_t); + + params.timestamp = header.timestamp; + params.module_id = header.module_id; + params.dropped = header.dropped; + params.use_colors = NRF_LOG_USES_COLORS; + + /*lint -save -e438*/ + if (header.base.generic.type == HEADER_TYPE_STD) + { + char const * p_log_str = (char const *)((uint32_t)header.base.std.addr); + params.severity = (nrf_log_severity_t)header.base.std.severity; + uint32_t nargs = header.base.std.nargs; + uint32_t args[NRF_LOG_MAX_NUM_OF_ARGS]; + + nrf_memobj_read(p_msg, args, nargs*sizeof(uint32_t), memobj_offset); + memobj_offset += (nargs*sizeof(uint32_t)); + + nrf_log_std_entry_process(p_log_str, + args, + nargs, + ¶ms, + &fprintf_ctx); + + } + else if (header.base.generic.type == HEADER_TYPE_HEXDUMP) + { + uint32_t data_len = header.base.hexdump.len; + params.severity = (nrf_log_severity_t)header.base.hexdump.severity; + uint8_t data_buf[8]; + uint32_t chunk_len; + do + { + chunk_len = sizeof(data_buf) > data_len ? data_len : sizeof(data_buf); + nrf_memobj_read(p_msg, data_buf, chunk_len, memobj_offset); + memobj_offset += chunk_len; + data_len -= chunk_len; + + nrf_log_hexdump_entry_process(data_buf, + chunk_len, + ¶ms, + &fprintf_ctx); + } while (data_len > 0); + } + nrf_memobj_put(p_msg); + /*lint -restore*/ +} +#endif //NRF_LOG_ENABLED diff --git a/components/libraries/log/src/nrf_log_backend_serial.h b/components/libraries/log/src/nrf_log_backend_serial.h new file mode 100644 index 0000000..504dad1 --- /dev/null +++ b/components/libraries/log/src/nrf_log_backend_serial.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_LOG_BACKEND_SERIAL_H +#define NRF_LOG_BACKEND_SERIAL_H +/**@file + * @addtogroup nrf_log Logger module + * @ingroup app_common + * + * @defgroup nrf_log_backend_serial Common part of serial backends + * @{ + * @ingroup nrf_log + * @brief The nrf_log serial backend common put function. + */ + + +#include "nrf_log_backend_interface.h" +#include "nrf_fprintf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief A function for processing logger entry with simple serial interface as output. + * + * + */ +void nrf_log_backend_serial_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg, + uint8_t * p_buffer, + uint32_t length, + nrf_fprintf_fwrite tx_func); + +#endif //NRF_LOG_BACKEND_SERIAL_H + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/components/libraries/log/src/nrf_log_backend_uart.c b/components/libraries/log/src/nrf_log_backend_uart.c new file mode 100644 index 0000000..e374ade --- /dev/null +++ b/components/libraries/log/src/nrf_log_backend_uart.c @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_UART) +#include "nrf_log_backend_uart.h" +#include "nrf_log_backend_serial.h" +#include "nrf_log_internal.h" +#include "nrf_drv_uart.h" +#include "app_error.h" + +nrf_drv_uart_t m_uart = NRF_DRV_UART_INSTANCE(0); + +static uint8_t m_string_buff[NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE]; +static volatile bool m_xfer_done; +static bool m_async_mode; +static void uart_evt_handler(nrf_drv_uart_event_t * p_event, void * p_context) +{ + m_xfer_done = true; +} + +static void uart_init(bool async_mode) +{ + nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG; + config.pseltxd = NRF_LOG_BACKEND_UART_TX_PIN; + config.pselrxd = NRF_UART_PSEL_DISCONNECTED; + config.pselcts = NRF_UART_PSEL_DISCONNECTED; + config.pselrts = NRF_UART_PSEL_DISCONNECTED; + config.baudrate = (nrf_uart_baudrate_t)NRF_LOG_BACKEND_UART_BAUDRATE; + ret_code_t err_code = nrf_drv_uart_init(&m_uart, &config, async_mode ? uart_evt_handler : NULL); + APP_ERROR_CHECK(err_code); + + m_async_mode = async_mode; +} + +void nrf_log_backend_uart_init(void) +{ + bool async_mode = NRF_LOG_DEFERRED ? true : false; + uart_init(async_mode); +} + +static void serial_tx(void const * p_context, char const * p_buffer, size_t len) +{ + uint8_t len8 = (uint8_t)(len & 0x000000FF); + m_xfer_done = false; + ret_code_t err_code = nrf_drv_uart_tx(&m_uart, (uint8_t *)p_buffer, len8); + APP_ERROR_CHECK(err_code); + /* wait for completion since buffer is reused*/ + while (m_async_mode && (m_xfer_done == false)) + { + + } + +} + +static void nrf_log_backend_uart_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg) +{ + nrf_log_backend_serial_put(p_backend, p_msg, m_string_buff, + NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE, serial_tx); +} + +static void nrf_log_backend_uart_flush(nrf_log_backend_t const * p_backend) +{ + +} + +static void nrf_log_backend_uart_panic_set(nrf_log_backend_t const * p_backend) +{ + nrf_drv_uart_uninit(&m_uart); + + uart_init(false); +} + +const nrf_log_backend_api_t nrf_log_backend_uart_api = { + .put = nrf_log_backend_uart_put, + .flush = nrf_log_backend_uart_flush, + .panic_set = nrf_log_backend_uart_panic_set, +}; +#endif //NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_UART) diff --git a/components/libraries/log/src/nrf_log_ctrl_internal.h b/components/libraries/log/src/nrf_log_ctrl_internal.h new file mode 100644 index 0000000..51c2818 --- /dev/null +++ b/components/libraries/log/src/nrf_log_ctrl_internal.h @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_LOG_CTRL_INTERNAL_H +#define NRF_LOG_CTRL_INTERNAL_H +/** + * @cond (NODOX) + * @defgroup nrf_log_ctrl_internal Auxiliary internal types declarations + * @{ + * @internal + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) + +#define NRF_LOG_LFCLK_FREQ 32768 + +#ifdef APP_TIMER_CONFIG_RTC_FREQUENCY +#define LOG_TIMESTAMP_DEFAULT_FREQUENCY ((NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY == 0) ? \ + (NRF_LOG_LFCLK_FREQ/(APP_TIMER_CONFIG_RTC_FREQUENCY + 1)) : \ + NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY) +#else +#define LOG_TIMESTAMP_DEFAULT_FREQUENCY NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY +#endif + +#define NRF_LOG_INTERNAL_INIT(...) \ + nrf_log_init(GET_VA_ARG_1(__VA_ARGS__), \ + GET_VA_ARG_1(GET_ARGS_AFTER_1(__VA_ARGS__, LOG_TIMESTAMP_DEFAULT_FREQUENCY))) + +#define NRF_LOG_INTERNAL_PROCESS() nrf_log_frontend_dequeue() +#define NRF_LOG_INTERNAL_FLUSH() \ + do { \ + while (NRF_LOG_INTERNAL_PROCESS()); \ + } while (0) + +#define NRF_LOG_INTERNAL_FINAL_FLUSH() \ + do { \ + nrf_log_panic(); \ + NRF_LOG_INTERNAL_FLUSH(); \ + } while (0) + + +#else // NRF_MODULE_ENABLED(NRF_LOG) +#define NRF_LOG_INTERNAL_PROCESS() false +#define NRF_LOG_INTERNAL_FLUSH() +#define NRF_LOG_INTERNAL_INIT(...) NRF_SUCCESS +#define NRF_LOG_INTERNAL_HANDLERS_SET(default_handler, bytes_handler) \ + UNUSED_PARAMETER(default_handler); UNUSED_PARAMETER(bytes_handler) +#define NRF_LOG_INTERNAL_FINAL_FLUSH() +#endif // NRF_MODULE_ENABLED(NRF_LOG) + +/** @} + * @endcond + */ +#endif // NRF_LOG_CTRL_INTERNAL_H diff --git a/components/libraries/log/src/nrf_log_default_backends.c b/components/libraries/log/src/nrf_log_default_backends.c new file mode 100644 index 0000000..f0ae9e9 --- /dev/null +++ b/components/libraries/log/src/nrf_log_default_backends.c @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "nrf_log_default_backends.h" +#include "nrf_log_ctrl.h" +#include "nrf_log_internal.h" +#include "nrf_assert.h" + +#if defined(NRF_LOG_BACKEND_RTT_ENABLED) && NRF_LOG_BACKEND_RTT_ENABLED +#include "nrf_log_backend_rtt.h" +NRF_LOG_BACKEND_RTT_DEF(rtt_log_backend); +#endif + +#if defined(NRF_LOG_BACKEND_UART_ENABLED) && NRF_LOG_BACKEND_UART_ENABLED +#include "nrf_log_backend_uart.h" +NRF_LOG_BACKEND_UART_DEF(uart_log_backend); +#endif + +void nrf_log_default_backends_init(void) +{ + int32_t backend_id = -1; + (void)backend_id; +#if defined(NRF_LOG_BACKEND_RTT_ENABLED) && NRF_LOG_BACKEND_RTT_ENABLED + nrf_log_backend_rtt_init(); + backend_id = nrf_log_backend_add(&rtt_log_backend, NRF_LOG_SEVERITY_DEBUG); + ASSERT(backend_id >= 0); + nrf_log_backend_enable(&rtt_log_backend); +#endif + +#if defined(NRF_LOG_BACKEND_UART_ENABLED) && NRF_LOG_BACKEND_UART_ENABLED + nrf_log_backend_uart_init(); + backend_id = nrf_log_backend_add(&uart_log_backend, NRF_LOG_SEVERITY_DEBUG); + ASSERT(backend_id >= 0); + nrf_log_backend_enable(&uart_log_backend); +#endif +} +#endif diff --git a/components/libraries/log/src/nrf_log_frontend.c b/components/libraries/log/src/nrf_log_frontend.c new file mode 100644 index 0000000..7305cbd --- /dev/null +++ b/components/libraries/log/src/nrf_log_frontend.c @@ -0,0 +1,1599 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "app_util.h" +#include "app_util_platform.h" +#include "nrf_log.h" +#include "nrf_log_internal.h" +#include "nrf_log_ctrl.h" +#include "nrf_log_backend_interface.h" +#include "nrf_log_str_formatter.h" +#include "nrf_section.h" +#include "nrf_ringbuf.h" +#include "nrf_memobj.h" +#include "nrf_atomic.h" +#include + +STATIC_ASSERT((NRF_LOG_BUFSIZE % 4) == 0); +STATIC_ASSERT(IS_POWER_OF_TWO(NRF_LOG_BUFSIZE)); + +#define NRF_LOG_BUF_WORDS (NRF_LOG_BUFSIZE/4) + +#if NRF_MODULE_ENABLED(FDS) && NRF_LOG_FILTERS_ENABLED +#define LOG_CONFIG_LOAD_STORE_ENABLED 1 +#else +#define LOG_CONFIG_LOAD_STORE_ENABLED 0 +#endif + +#if NRF_LOG_BUF_WORDS < 32 +#warning "NRF_LOG_BUFSIZE too small, significant number of logs may be lost." +#endif + +NRF_MEMOBJ_POOL_DEF(log_mempool, NRF_LOG_MSGPOOL_ELEMENT_SIZE, NRF_LOG_MSGPOOL_ELEMENT_COUNT); +NRF_RINGBUF_DEF(m_log_push_ringbuf, NRF_LOG_STR_PUSH_BUFFER_SIZE); + +#define NRF_LOG_BACKENDS_FULL 0xFF +#define NRF_LOG_FILTER_BITS_PER_BACKEND 3 +#define NRF_LOG_MAX_BACKENDS (32/NRF_LOG_FILTER_BITS_PER_BACKEND) +#define NRF_LOG_MAX_HEXDUMP (NRF_LOG_MSGPOOL_ELEMENT_SIZE*NRF_LOG_MSGPOOL_ELEMENT_COUNT/2) +#define NRF_LOG_INVALID_BACKEND_U32 0xFFFFFFFF + +/* Mask is extracted from the structure log_data_t to allow compile time initialization which + * is needed to allow usage of the logger (logging) before logger is initialized. + * It cannot be part of the log_data_t because some compilers would put whole log_data_t structure + * into flash (including buffer) just because one field is initilized. + */ +static uint32_t m_buffer_mask = NRF_LOG_BUF_WORDS - 1; // Size of buffer (must be power of 2) presented as mask + +/** + * brief An internal control block of the logger + * + * @note Circular buffer is using never cleared indexes and a mask. It means + * that logger may break when indexes overflows. However, it is quite unlikely. + * With rate of 1000 log entries with 2 parameters per second such situation + * would happen after 12 days. + */ +typedef struct +{ + bool autoflush; + uint32_t wr_idx; // Current write index (never reset) + uint32_t rd_idx; // Current read index (never_reset) + uint32_t buffer[NRF_LOG_BUF_WORDS]; + nrf_log_timestamp_func_t timestamp_func; // A pointer to function that returns timestamp + nrf_log_backend_t const * p_backend_head; + nrf_atomic_flag_t log_skipping; + nrf_atomic_flag_t log_skipped; + nrf_atomic_u32_t log_dropped_cnt; +} log_data_t; + +static log_data_t m_log_data; + +NRF_LOG_MODULE_REGISTER(); + +// Helper macros for section variables. +#define NRF_LOG_DYNAMIC_SECTION_VARS_GET(i) NRF_SECTION_ITEM_GET(log_dynamic_data, nrf_log_module_dynamic_data_t, (i)) +#define NRF_LOG_FILTER_SECTION_VARS_GET(i) NRF_SECTION_ITEM_GET(log_filter_data, nrf_log_module_filter_data_t, (i)) + +#define NRF_LOG_CONST_SECTION_VARS_GET(i) NRF_SECTION_ITEM_GET(log_const_data, nrf_log_module_const_data_t, (i)) +#define NRF_LOG_CONST_SECTION_VARS_COUNT NRF_SECTION_ITEM_COUNT(log_const_data, nrf_log_module_const_data_t) + +ret_code_t nrf_log_init(nrf_log_timestamp_func_t timestamp_func, uint32_t timestamp_freq) +{ + (void)NRF_LOG_ITEM_DATA_CONST(app); + + if (NRF_LOG_USES_TIMESTAMP && (timestamp_func == NULL)) + { + return NRF_ERROR_INVALID_PARAM; + } + + m_log_data.autoflush = NRF_LOG_DEFERRED ? false : true; + + if (NRF_LOG_USES_TIMESTAMP) + { + nrf_log_str_formatter_timestamp_freq_set(timestamp_freq); + m_log_data.timestamp_func = timestamp_func; + } + +#ifdef UNIT_TEST + m_buffer_mask = NRF_LOG_BUF_WORDS - 1; +#endif + + ret_code_t err_code = nrf_memobj_pool_init(&log_mempool); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + nrf_ringbuf_init(&m_log_push_ringbuf); + + uint32_t modules_cnt = NRF_LOG_CONST_SECTION_VARS_COUNT; + uint32_t i; + if (NRF_LOG_FILTERS_ENABLED) + { + uint32_t j; + //sort modules by name + for (i = 0; i < modules_cnt; i++) + { + uint32_t idx = 0; + + for (j = 0; j < modules_cnt; j++) + { + if (i != j) + { + char const * p_name0 = NRF_LOG_CONST_SECTION_VARS_GET(i)->p_module_name; + char const * p_name1 = NRF_LOG_CONST_SECTION_VARS_GET(j)->p_module_name; + if (strncmp(p_name0, p_name1, 20) > 0) + { + idx++; + } + } + + } + nrf_log_module_dynamic_data_t * p_module_ddata = NRF_LOG_DYNAMIC_SECTION_VARS_GET(i); + p_module_ddata->order_idx = idx; + } + + /* Initialize filters */ + for (i = 0; i < modules_cnt; i++) + { + nrf_log_module_dynamic_data_t * p_module_ddata = NRF_LOG_DYNAMIC_SECTION_VARS_GET(i); + nrf_log_module_filter_data_t * p_module_filter = NRF_LOG_FILTER_SECTION_VARS_GET(i); + p_module_ddata->filter = 0; + p_module_filter->filter_lvls = 0; + } + } + + return NRF_SUCCESS; +} + +uint32_t nrf_log_module_cnt_get(void) +{ + return NRF_LOG_CONST_SECTION_VARS_COUNT; +} + +static ret_code_t module_idx_get(uint32_t * p_idx, bool ordered_idx) +{ + if (ordered_idx) + { + uint32_t module_cnt = nrf_log_module_cnt_get(); + uint32_t i; + for (i = 0; i < module_cnt; i++) + { + nrf_log_module_dynamic_data_t * p_module_data = NRF_LOG_DYNAMIC_SECTION_VARS_GET(i); + if (p_module_data->order_idx == *p_idx) + { + *p_idx = i; + return NRF_SUCCESS; + } + } + return NRF_ERROR_NOT_FOUND; + } + else + { + return NRF_SUCCESS; + } +} +const char * nrf_log_module_name_get(uint32_t module_id, bool ordered_idx) +{ + if (module_idx_get(&module_id, ordered_idx) == NRF_SUCCESS) + { + nrf_log_module_const_data_t * p_module_data = NRF_LOG_CONST_SECTION_VARS_GET(module_id); + return p_module_data->p_module_name; + } + else + { + return NULL; + } +} + +uint8_t nrf_log_color_id_get(uint32_t module_id, nrf_log_severity_t severity) +{ + nrf_log_module_const_data_t * p_module_data = NRF_LOG_CONST_SECTION_VARS_GET(module_id); + uint8_t color_id; + switch (severity) + { + case NRF_LOG_SEVERITY_ERROR: + color_id = NRF_LOG_ERROR_COLOR; + break; + case NRF_LOG_SEVERITY_WARNING: + color_id = NRF_LOG_WARNING_COLOR; + break; + case NRF_LOG_SEVERITY_INFO: + color_id = p_module_data->info_color_id; + break; + case NRF_LOG_SEVERITY_DEBUG: + color_id = p_module_data->debug_color_id; + break; + default: + color_id = 0; + break; + } + return color_id; +} + +static uint16_t higher_lvl_get(uint32_t lvls) +{ + uint16_t top_lvl = 0; + uint16_t tmp_lvl; + uint32_t i; + + //Find highest level enabled by backends + for (i = 0; i < (32/NRF_LOG_LEVEL_BITS); i+=NRF_LOG_LEVEL_BITS) + { + tmp_lvl = (uint16_t)BF_GET(lvls,NRF_LOG_LEVEL_BITS, i); + if (tmp_lvl > top_lvl) + { + top_lvl = tmp_lvl; + } + } + return top_lvl; +} + +void nrf_log_module_filter_set(uint32_t backend_id, uint32_t module_id, nrf_log_severity_t severity) +{ + if (NRF_LOG_FILTERS_ENABLED) + { + nrf_log_module_dynamic_data_t * p_module_data = NRF_LOG_DYNAMIC_SECTION_VARS_GET(module_id); + nrf_log_module_filter_data_t * p_filter = NRF_LOG_FILTER_SECTION_VARS_GET(module_id); + + p_filter->filter_lvls &= ~BF_MASK(NRF_LOG_LEVEL_BITS, (NRF_LOG_LEVEL_BITS * backend_id)); + p_filter->filter_lvls |= BF_VAL(severity, NRF_LOG_LEVEL_BITS, (NRF_LOG_LEVEL_BITS * backend_id)); + + p_module_data->filter = higher_lvl_get(p_filter->filter_lvls); + } +} + +static nrf_log_severity_t nrf_log_module_init_filter_get(uint32_t module_id) +{ + nrf_log_module_const_data_t * p_module_data = + NRF_LOG_CONST_SECTION_VARS_GET(module_id); + return NRF_LOG_FILTERS_ENABLED ? p_module_data->initial_lvl : p_module_data->compiled_lvl; +} + +nrf_log_severity_t nrf_log_module_filter_get(uint32_t backend_id, + uint32_t module_id, + bool ordered_idx, + bool dynamic) +{ + nrf_log_severity_t severity = NRF_LOG_SEVERITY_NONE; + if (NRF_LOG_FILTERS_ENABLED && dynamic) + { + if (module_idx_get(&module_id, ordered_idx) == NRF_SUCCESS) + { + nrf_log_module_filter_data_t * p_filter = NRF_LOG_FILTER_SECTION_VARS_GET(module_id); + severity = (nrf_log_severity_t)BF_GET(p_filter->filter_lvls, + NRF_LOG_LEVEL_BITS, + (backend_id*NRF_LOG_LEVEL_BITS)); + } + } + else if (!dynamic) + { + if (module_idx_get(&module_id, ordered_idx) == NRF_SUCCESS) + { + nrf_log_module_const_data_t * p_module_data = + NRF_LOG_CONST_SECTION_VARS_GET(module_id); + severity = (nrf_log_severity_t)p_module_data->compiled_lvl; + } + } + return severity; +} +/** + * Function examines current header and omits packets which are in progress. + */ +static bool invalid_packets_omit(nrf_log_header_t const * p_header, uint32_t * p_rd_idx) +{ + bool ret = false; + if (p_header->base.generic.in_progress == 1) + { + switch (p_header->base.generic.type) + { + case HEADER_TYPE_STD: + *p_rd_idx += (HEADER_SIZE + p_header->base.std.nargs); + break; + case HEADER_TYPE_HEXDUMP: + *p_rd_idx += (HEADER_SIZE + p_header->base.hexdump.len); + break; + default: + break; + } + ret = true; + } + return ret; +} +/** + * @brief Skips the oldest, not processed logs to make space for new logs. + * @details This function moves forward read index to prepare space for new logs. + */ + +static uint32_t log_skip(void) +{ + uint16_t dropped = 0; + + (void)nrf_atomic_flag_set(&m_log_data.log_skipped); + (void)nrf_atomic_flag_set(&m_log_data.log_skipping); + + uint32_t rd_idx = m_log_data.rd_idx; + uint32_t mask = m_buffer_mask; + nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask]; + nrf_log_header_t header; + + // Skip packets that may be invalid (interrupted while being in progress) + do { + if (invalid_packets_omit(p_header, &rd_idx)) + { + //something was omitted. Point to new header and try again. + p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask]; + } + else + { + break; + } + } while (true); + + uint32_t i; + for (i = 0; i < HEADER_SIZE; i++) + { + ((uint32_t*)&header)[i] = m_log_data.buffer[rd_idx++ & mask]; + } + + switch (header.base.generic.type) + { + case HEADER_TYPE_HEXDUMP: + dropped = header.dropped; + rd_idx += CEIL_DIV(header.base.hexdump.len, sizeof(uint32_t)); + break; + case HEADER_TYPE_STD: + dropped = header.dropped; + rd_idx += header.base.std.nargs; + break; + default: + ASSERT(false); + break; + } + + uint32_t log_skipping_tmp = nrf_atomic_flag_clear_fetch(&m_log_data.log_skipping); + //update read index only if log_skip was not interrupted by another log skip + if (log_skipping_tmp) + { + m_log_data.rd_idx = rd_idx; + } + + return (uint32_t)dropped; +} + +/** + * @brief Function for getting number of dropped logs. Dropped counter is reset after reading. + * + * @return Number of dropped logs saturated to 16 bits. + */ +static inline uint32_t dropped_sat16_get(void) +{ + uint32_t dropped = nrf_atomic_u32_fetch_store(&m_log_data.log_dropped_cnt, 0); + return __USAT(dropped, 16); //Saturate to 16 bits +} + + +static inline void std_header_set(uint32_t severity_mid, + char const * const p_str, + uint32_t nargs, + uint32_t wr_idx, + uint32_t mask) +{ + + + //Prepare header - in reverse order to ensure that packet type is validated (set to STD as last action) + uint32_t module_id = severity_mid >> NRF_LOG_MODULE_ID_POS; + uint32_t dropped = dropped_sat16_get(); + ASSERT(module_id < nrf_log_module_cnt_get()); + m_log_data.buffer[(wr_idx + 1) & mask] = module_id | (dropped << 16); + + if (NRF_LOG_USES_TIMESTAMP) + { + m_log_data.buffer[(wr_idx + 2) & mask] = m_log_data.timestamp_func(); + } + + nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[wr_idx & mask]; + p_header->base.std.severity = severity_mid & NRF_LOG_LEVEL_MASK; + p_header->base.std.nargs = nargs; + p_header->base.std.addr = ((uint32_t)(p_str) & STD_ADDR_MASK); + p_header->base.std.type = HEADER_TYPE_STD; + p_header->base.std.in_progress = 0; +} + +#if NRF_LOG_DEFERRED +/** + * When using RTOS, application can overide this function so that it could unblock + * the task that is responsible for flushing the logs. + */ +__WEAK void log_pending_hook( void ) +{ +} +#endif + +/** + * @brief Allocates chunk in a buffer for one entry and injects overflow if + * there is no room for requested entry. + * + * @param content_len Number of 32bit arguments. In case of allocating for hex dump it + * is the size of the buffer in 32bit words (ceiled). + * @param p_wr_idx Pointer to write index. + * + * @return True if successful allocation, false otherwise. + * + */ +static inline bool buf_prealloc(uint32_t content_len, uint32_t * p_wr_idx, bool std) +{ + uint32_t req_len = content_len + HEADER_SIZE; + bool ret = true; + CRITICAL_REGION_ENTER(); + *p_wr_idx = m_log_data.wr_idx; + uint32_t available_words = (m_buffer_mask + 1) - (m_log_data.wr_idx - m_log_data.rd_idx); + while (req_len > available_words) + { + UNUSED_RETURN_VALUE(nrf_atomic_u32_add(&m_log_data.log_dropped_cnt, 1)); + if (NRF_LOG_ALLOW_OVERFLOW) + { + uint32_t dropped_in_skip = log_skip(); + UNUSED_RETURN_VALUE(nrf_atomic_u32_add(&m_log_data.log_dropped_cnt, dropped_in_skip)); + available_words = (m_buffer_mask + 1) - (m_log_data.wr_idx - m_log_data.rd_idx); + } + else + { + ret = false; + break; + } + } + + if (ret) + { + nrf_log_main_header_t invalid_header; + invalid_header.raw = 0; + + if (std) + { + invalid_header.std.type = HEADER_TYPE_STD; + invalid_header.std.in_progress = 1; + invalid_header.std.nargs = content_len; + } + else + { + invalid_header.hexdump.type = HEADER_TYPE_HEXDUMP; + invalid_header.hexdump.in_progress = 1; + invalid_header.hexdump.len = content_len; + } + + nrf_log_main_header_t * p_header = + (nrf_log_main_header_t *)&m_log_data.buffer[m_log_data.wr_idx & m_buffer_mask]; + + p_header->raw = invalid_header.raw; + + m_log_data.wr_idx += req_len; + } + + CRITICAL_REGION_EXIT(); + return ret; +} + +char const * nrf_log_push(char * const p_str) +{ + if ((m_log_data.autoflush) || (p_str == NULL)) + { + return p_str; + } + + size_t ssize = strlen(p_str) + 1; // + 1 for null termination + uint8_t * p_dst; + // Allocate space in the ring buffer. It may be smaller than the requested string in case of buffer wrapping or when the ring buffer size is too small. + // Once the string is copied into the buffer, the space is immediately freed. The string is kept in the buffer but can be overwritten. + // It is done that way because there is no other place where space could be freed since string processing happens in + // the logger backends, often by modules which are generic and not aware of internals of the logger. + if (nrf_ringbuf_alloc(&m_log_push_ringbuf, &p_dst, &ssize, true) == NRF_SUCCESS) + { + ret_code_t err; + + memcpy(p_dst, p_str, ssize); + + //Terminate in case string was partial. + p_dst[ssize - 1] = '\0'; + + err = nrf_ringbuf_put(&m_log_push_ringbuf, ssize); + ASSERT(err == NRF_SUCCESS); + + //Immediately free the space where string was put. + err = nrf_ringbuf_free(&m_log_push_ringbuf, ssize); + ASSERT(err == NRF_SUCCESS); + + return (char const *)p_dst; + } + else + { + return NULL; + } +} + +static inline void std_n(uint32_t severity_mid, + char const * const p_str, + uint32_t const * args, + uint32_t nargs) +{ + uint32_t mask = m_buffer_mask; + uint32_t wr_idx; + + if (buf_prealloc(nargs, &wr_idx, true)) + { + // Proceed only if buffer was successfully preallocated. + + uint32_t data_idx = wr_idx + HEADER_SIZE; + uint32_t i; + for (i = 0; i < nargs; i++) + { + m_log_data.buffer[data_idx++ & mask] =args[i]; + } + std_header_set(severity_mid, p_str, nargs, wr_idx, mask); + } + + if (m_log_data.autoflush) + { +#if NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + CRITICAL_REGION_ENTER(); +#endif // NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + + NRF_LOG_FLUSH(); + +#if NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + CRITICAL_REGION_EXIT(); +#endif // NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + } + +#if (NRF_LOG_DEFERRED == 1) + log_pending_hook(); +#endif + +} + +void nrf_log_frontend_std_0(uint32_t severity_mid, char const * const p_str) +{ + std_n(severity_mid, p_str, NULL, 0); +} + + +void nrf_log_frontend_std_1(uint32_t severity_mid, + char const * const p_str, + uint32_t val0) +{ + uint32_t args[] = {val0}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_2(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1) +{ + uint32_t args[] = {val0, val1}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_3(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2) +{ + uint32_t args[] = {val0, val1, val2}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_4(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3) +{ + uint32_t args[] = {val0, val1, val2, val3}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_5(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4) +{ + uint32_t args[] = {val0, val1, val2, val3, val4}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_6(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4, + uint32_t val5) +{ + uint32_t args[] = {val0, val1, val2, val3, val4, val5}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_hexdump(uint32_t severity_mid, + const void * const p_data, + uint16_t length) +{ + uint32_t mask = m_buffer_mask; + + uint32_t wr_idx; + if (buf_prealloc(CEIL_DIV(length, sizeof(uint32_t)), &wr_idx, false)) + { + uint32_t header_wr_idx = wr_idx; + wr_idx += HEADER_SIZE; + + uint32_t space0 = sizeof(uint32_t) * (m_buffer_mask + 1 - (wr_idx & mask)); + if (length <= space0) + { + memcpy(&m_log_data.buffer[wr_idx & mask], p_data, length); + } + else + { + memcpy(&m_log_data.buffer[wr_idx & mask], p_data, space0); + memcpy(&m_log_data.buffer[0], &((uint8_t *)p_data)[space0], length - space0); + } + + //Prepare header - in reverse order to ensure that packet type is validated (set to HEXDUMP as last action) + if (NRF_LOG_USES_TIMESTAMP) + { + m_log_data.buffer[(header_wr_idx + 2) & mask] = m_log_data.timestamp_func(); + } + + uint32_t module_id = severity_mid >> NRF_LOG_MODULE_ID_POS; + uint32_t dropped = dropped_sat16_get(); + m_log_data.buffer[(header_wr_idx + 1) & mask] = module_id | (dropped << 16); + //Header prepare + nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[header_wr_idx & mask]; + p_header->base.hexdump.severity = severity_mid & NRF_LOG_LEVEL_MASK; + p_header->base.hexdump.offset = 0; + p_header->base.hexdump.len = length; + p_header->base.hexdump.type = HEADER_TYPE_HEXDUMP; + p_header->base.hexdump.in_progress = 0; + } + + if (m_log_data.autoflush) + { +#if NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + CRITICAL_REGION_ENTER(); +#endif // NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + + NRF_LOG_FLUSH(); + +#if NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + CRITICAL_REGION_EXIT(); +#endif // NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED + } + +#if (NRF_LOG_DEFERRED == 1) + log_pending_hook(); +#endif +} + + +bool buffer_is_empty(void) +{ + return (m_log_data.rd_idx == m_log_data.wr_idx); +} + +bool nrf_log_frontend_dequeue(void) +{ + + if (buffer_is_empty()) + { + return false; + } + m_log_data.log_skipped = 0; + //It has to be ensured that reading rd_idx occurs after skipped flag is cleared. + __DSB(); + uint32_t rd_idx = m_log_data.rd_idx; + uint32_t mask = m_buffer_mask; + nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask]; + nrf_log_header_t header; + nrf_memobj_t * p_msg_buf = NULL; + size_t memobj_offset = 0; + uint32_t severity = 0; + + // Skip any in progress packets. + do { + if (invalid_packets_omit(p_header, &rd_idx) && (m_log_data.log_skipped == 0)) + { + //Check if end of data is not reached. + if (rd_idx >= m_log_data.wr_idx) + { + m_log_data.rd_idx = m_log_data.wr_idx; + return false; + } + //something was omitted. Point to new header and try again. + p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask]; + } + else + { + break; + } + } while (true); + + uint32_t i; + for (i = 0; i < HEADER_SIZE; i++) + { + ((uint32_t*)&header)[i] = m_log_data.buffer[rd_idx++ & mask]; + } + + if (header.base.generic.type == HEADER_TYPE_HEXDUMP) + { + uint32_t orig_data_len = header.base.hexdump.len; + uint32_t data_len = MIN(header.base.hexdump.len, NRF_LOG_MAX_HEXDUMP); //limit the data + header.base.hexdump.len = data_len; + uint32_t msg_buf_size8 = sizeof(uint32_t)*HEADER_SIZE + data_len; + severity = header.base.hexdump.severity; + p_msg_buf = nrf_memobj_alloc(&log_mempool, msg_buf_size8); + + if (p_msg_buf) + { + nrf_memobj_get(p_msg_buf); + nrf_memobj_write(p_msg_buf, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset); + memobj_offset += HEADER_SIZE*sizeof(uint32_t); + + uint32_t space0 = sizeof(uint32_t) * (mask + 1 - (rd_idx & mask)); + if (data_len > space0) + { + uint8_t * ptr0 = space0 ? + (uint8_t *)&m_log_data.buffer[rd_idx & mask] : + (uint8_t *)&m_log_data.buffer[0]; + uint8_t len0 = space0 ? space0 : data_len; + uint8_t * ptr1 = space0 ? + (uint8_t *)&m_log_data.buffer[0] : NULL; + uint8_t len1 = space0 ? data_len - space0 : 0; + + nrf_memobj_write(p_msg_buf, ptr0, len0, memobj_offset); + memobj_offset += len0; + if (ptr1) + { + nrf_memobj_write(p_msg_buf, ptr1, len1, memobj_offset); + } + } + else + { + uint8_t * p_data = (uint8_t *)&m_log_data.buffer[rd_idx & mask]; + nrf_memobj_write(p_msg_buf, p_data, data_len, memobj_offset); + } + rd_idx += CEIL_DIV(orig_data_len, 4); + } + } + else if (header.base.generic.type == HEADER_TYPE_STD) // standard entry + { + header.base.std.nargs = MIN(header.base.std.nargs, NRF_LOG_MAX_NUM_OF_ARGS); + uint32_t msg_buf_size32 = HEADER_SIZE + header.base.std.nargs; + severity = header.base.std.severity; + + p_msg_buf = nrf_memobj_alloc(&log_mempool, msg_buf_size32*sizeof(uint32_t)); + + if (p_msg_buf) + { + nrf_memobj_get(p_msg_buf); + nrf_memobj_write(p_msg_buf, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset); + memobj_offset += HEADER_SIZE*sizeof(uint32_t); + + for (i = 0; i < header.base.std.nargs; i++) + { + nrf_memobj_write(p_msg_buf, &m_log_data.buffer[rd_idx++ & mask], + sizeof(uint32_t), memobj_offset); + memobj_offset += sizeof(uint32_t); + } + } + } + else + { + //Do nothing. In case of log overflow buffer can contain corrupted data. + } + + if (p_msg_buf) + { + nrf_log_backend_t const * p_backend = m_log_data.p_backend_head; + if (NRF_LOG_ALLOW_OVERFLOW && m_log_data.log_skipped) + { + // Check if any log was skipped during log processing. Do not forward log if skipping + // occured because data may be invalid. + nrf_memobj_put(p_msg_buf); + } + else + { + while (p_backend) + { + bool entry_accepted = false; + if (nrf_log_backend_is_enabled(p_backend) == true) + { + if (NRF_LOG_FILTERS_ENABLED) + { + uint8_t backend_id = nrf_log_backend_id_get(p_backend); + nrf_log_module_filter_data_t * p_module_filter = + NRF_LOG_FILTER_SECTION_VARS_GET(header.module_id); + uint32_t backend_lvl = BF_GET(p_module_filter->filter_lvls, + NRF_LOG_LEVEL_BITS, + (backend_id*NRF_LOG_LEVEL_BITS)); + + //Degrade INFO_RAW level to INFO. + severity = (severity == NRF_LOG_SEVERITY_INFO_RAW) ? + NRF_LOG_SEVERITY_INFO : severity; + if (backend_lvl >= severity) + { + entry_accepted = true; + } + } + else + { + (void)severity; + entry_accepted = true; + } + } + if (entry_accepted) + { + nrf_log_backend_put(p_backend, p_msg_buf); + } + p_backend = p_backend->p_cb->p_next; + } + + nrf_memobj_put(p_msg_buf); + + if (NRF_LOG_ALLOW_OVERFLOW) + { + // Read index can be moved forward only if dequeueing process was not interrupt by + // skipping procedure. If NRF_LOG_ALLOW_OVERFLOW is set then in case of buffer gets full + // and new logger entry occurs, oldest entry is removed. In that case read index is + // changed and updating it here would corrupt the internal circular buffer. + CRITICAL_REGION_ENTER(); + if (m_log_data.log_skipped == 0) + { + m_log_data.rd_idx = rd_idx; + } + CRITICAL_REGION_EXIT(); + } + else + { + m_log_data.rd_idx = rd_idx; + } + } + } + else + { + //Could not allocate memobj - backends are not freeing them on time. + nrf_log_backend_t const * p_backend = m_log_data.p_backend_head; + //Flush all backends + while (p_backend) + { + nrf_log_backend_flush(p_backend); + p_backend = p_backend->p_cb->p_next; + } + NRF_LOG_WARNING("Backends flushed"); + } + + return buffer_is_empty() ? false : true; +} + +static int32_t backend_id_assign(void) +{ + int32_t candidate_id; + nrf_log_backend_t const * p_backend; + bool id_available; + for (candidate_id = 0; candidate_id < NRF_LOG_MAX_BACKENDS; candidate_id++) + { + p_backend = m_log_data.p_backend_head; + id_available = true; + while (p_backend) + { + if (nrf_log_backend_id_get(p_backend) == candidate_id) + { + id_available = false; + break; + } + p_backend = p_backend->p_cb->p_next; + } + if (id_available) + { + return candidate_id; + } + } + return -1; +} + +int32_t nrf_log_backend_add(nrf_log_backend_t const * p_backend, nrf_log_severity_t severity) +{ + int32_t id = backend_id_assign(); + if (id == -1) + { + return id; + } + + nrf_log_backend_id_set(p_backend, id); + //add to list + if (m_log_data.p_backend_head == NULL) + { + m_log_data.p_backend_head = p_backend; + p_backend->p_cb->p_next = NULL; + } + else + { + p_backend->p_cb->p_next = m_log_data.p_backend_head->p_cb->p_next; + m_log_data.p_backend_head->p_cb->p_next = p_backend; + } + + if (NRF_LOG_FILTERS_ENABLED) + { + uint32_t i; + for (i = 0; i < nrf_log_module_cnt_get(); i++) + { + nrf_log_severity_t buildin_lvl = nrf_log_module_init_filter_get(i); + nrf_log_severity_t actual_severity = MIN(buildin_lvl, severity); + nrf_log_module_filter_set(nrf_log_backend_id_get(p_backend), i, actual_severity); + } + } + + return id; +} + +void nrf_log_backend_remove(nrf_log_backend_t const * p_backend) +{ + nrf_log_backend_t const * p_curr = m_log_data.p_backend_head; + nrf_log_backend_t const * p_prev = NULL; + while (p_curr != p_backend) + { + p_prev = p_curr; + p_curr = p_curr->p_cb->p_next; + } + + if (p_prev) + { + p_prev->p_cb->p_next = p_backend->p_cb->p_next; + } + else + { + m_log_data.p_backend_head = NULL; + } + + p_backend->p_cb->id = NRF_LOG_BACKEND_INVALID_ID; +} + +void nrf_log_panic(void) +{ + nrf_log_backend_t const * p_backend = m_log_data.p_backend_head; + m_log_data.autoflush = true; + while (p_backend) + { + nrf_log_backend_enable(p_backend); + nrf_log_backend_panic_set(p_backend); + p_backend = p_backend->p_cb->p_next; + } +} + +#if NRF_MODULE_ENABLED(LOG_CONFIG_LOAD_STORE) +#include "fds.h" +#define LOG_CONFIG_FILE_ID 0x106E +#define LOG_CONFIG_RECORD_ID 0x3427 + +ret_code_t nrf_log_config_store(void) +{ + fds_record_desc_t desc = {0}; + fds_find_token_t token = {0}; + fds_record_t record = { + .file_id = LOG_CONFIG_FILE_ID, + .key = LOG_CONFIG_RECORD_ID, + .data = { + .p_data = NRF_LOG_FILTER_SECTION_VARS_GET(0), + .length_words = NRF_SECTION_LENGTH(log_filter_data)/sizeof(uint32_t) + } + }; + ret_code_t ret = fds_record_find(LOG_CONFIG_FILE_ID, LOG_CONFIG_RECORD_ID, &desc, &token); + if (ret == NRF_SUCCESS) + { + ret = fds_record_update(&desc, &record); + NRF_LOG_INFO("Logger configuration file updated with result:%d", ret); + } + else if (ret == FDS_ERR_NOT_FOUND) + { + ret = fds_record_write(&desc, &record); + NRF_LOG_INFO("Logger configuration file written with result:%d", ret); + } + else + { + ret = NRF_ERROR_INTERNAL; + } + return ret; +} + +ret_code_t nrf_log_config_load(void) +{ + fds_record_desc_t desc = {0}; + fds_find_token_t token = {0}; + + ret_code_t ret = fds_record_find(LOG_CONFIG_FILE_ID, LOG_CONFIG_RECORD_ID, &desc, &token); + if (ret == NRF_SUCCESS) + { + fds_flash_record_t record = {0}; + ret = fds_record_open(&desc, &record); + if (ret == NRF_SUCCESS) + { + void * p_dest = (void *)NRF_LOG_FILTER_SECTION_VARS_GET(0); + uint32_t length = NRF_SECTION_LENGTH(log_filter_data); + memcpy(p_dest, record.p_data, length); + ret = fds_record_close(&desc); + } + } + else if (ret == FDS_ERR_NOT_FOUND) + { + NRF_LOG_WARNING("Logger configuration file not found."); + ret = NRF_ERROR_NOT_FOUND; + } + else + { + ret = NRF_ERROR_INTERNAL; + } + + return ret; +} +#endif //LOG_CONFIG_LOAD_STORE_ENABLED + +#if NRF_LOG_CLI_CMDS && NRF_CLI_ENABLED +#include "nrf_cli.h" + +typedef void (*nrf_log_cli_backend_cmd_t)(nrf_cli_t const * p_cli, + nrf_log_backend_t const * p_backend, + size_t argc, + char * * argv); + +static const char * m_severity_lvls[] = { + "none", + "error", + "warning", + "info", + "debug", +}; + +static const char * m_severity_lvls_sorted[] = { + "debug", + "error", + "info", + "none", + "warning", +}; + +/** + * @brief Function for finding backend instance with given name. + * + * @param p_name Name of the backend instance. + * + * @return Pointer to the instance or NULL. + * + */ +static nrf_log_backend_t const * backend_find(char const * p_name) +{ + size_t num_of_backends; + nrf_log_backend_t const * p_backend; + + num_of_backends = NRF_SECTION_ITEM_COUNT(NRF_LOG_BACKEND_SECTION_NAME, nrf_log_backend_t); + for (size_t i = 0; i < num_of_backends; i++) + { + p_backend = NRF_SECTION_ITEM_GET(NRF_LOG_BACKEND_SECTION_NAME, nrf_log_backend_t, i); + if (strcmp(p_name, p_backend->p_name) == 0) + { + return p_backend; + } + } + return NULL; +} + +/** + * @brief Function for executing command on given backend. + */ +static void nrf_cli_backend_cmd_execute(nrf_cli_t const * p_cli, + size_t argc, + char * * argv, + nrf_log_cli_backend_cmd_t func) +{ + //Based on the structure of backend commands, name of the backend can be found at -1 (log backend command). + char const * p_backend_name = argv[-1]; + + nrf_log_backend_t const * p_backend = backend_find(p_backend_name); + + if (p_backend) + { + func(p_cli, p_backend, argc, argv); + } + else + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Invalid backend: %s\r\n", p_backend_name); + } +} + + +static void log_status(nrf_cli_t const * p_cli, + nrf_log_backend_t const * p_backend, + size_t argc, + char * * argv) +{ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + + uint32_t modules_cnt = nrf_log_module_cnt_get(); + uint32_t i; + + + if (!nrf_log_backend_is_enabled(p_backend)) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Logs are halted!\r\n"); + } + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%-40s | current | built-in \r\n", "module_name"); + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "----------------------------------------------------------\r\n"); + for (i = 0; i < modules_cnt; i++) + { + uint32_t backend_id = p_backend->p_cb->id; + nrf_log_severity_t module_dynamic_lvl = + nrf_log_module_filter_get(backend_id, i, true, true); + nrf_log_severity_t module_compiled_lvl = + nrf_log_module_filter_get(backend_id, i, true, false); + nrf_log_severity_t actual_compiled_lvl = + MIN(module_compiled_lvl, (nrf_log_severity_t)NRF_LOG_DEFAULT_LEVEL); + + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%-40s | %-7s | %s%s\r\n", + nrf_log_module_name_get(i, true), + m_severity_lvls[module_dynamic_lvl], + m_severity_lvls[actual_compiled_lvl], + actual_compiled_lvl < module_compiled_lvl ? "*" : ""); + } +} + + +static void log_self_status(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + log_status(p_cli, p_cli->p_log_backend, argc, argv); +} + + +static void log_backend_status(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + nrf_cli_backend_cmd_execute(p_cli, argc, argv, log_status); +} + + +static bool module_id_get(const char * p_name, uint32_t * p_id) +{ + uint32_t modules_cnt = nrf_log_module_cnt_get(); + const char * p_tmp_name; + uint32_t j; + for (j = 0; j < modules_cnt; j++) + { + p_tmp_name = nrf_log_module_name_get(j, false); + if (strncmp(p_tmp_name, p_name, 32) == 0) + { + *p_id = j; + break; + } + } + return (j != modules_cnt); +} + + +static bool module_id_filter_set(uint32_t backend_id, + uint32_t module_id, + nrf_log_severity_t lvl) +{ + nrf_log_severity_t buildin_lvl = nrf_log_module_filter_get(backend_id, module_id, false, false); + if (lvl > buildin_lvl) + { + return false; + } + else + { + nrf_log_module_filter_set(backend_id, module_id, lvl); + return true; + } +} + + +static void log_ctrl(nrf_cli_t const * p_cli, + nrf_log_backend_t const * p_backend, + size_t argc, + char * * argv) +{ + nrf_log_severity_t lvl; + uint32_t first_m_name_idx; + uint32_t i; + bool all_modules = false; + uint32_t backend_id = p_backend->p_cb->id; + + if (argc > 0) + { + if (strncmp(argv[0], "enable", 7) == 0) + { + if (argc == 1) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Bad parameter count.\r\n"); + return; + } + + if (argc == 2) + { + all_modules = true; + } + + for (i = 0; i < ARRAY_SIZE(m_severity_lvls); i++) + { + if (strncmp(argv[1], m_severity_lvls[i], 10) == 0) + { + break; + } + } + + if (i == ARRAY_SIZE(m_severity_lvls)) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Unknown severity level: %s\r\n", argv[1]); + return; + } + + lvl = (nrf_log_severity_t)i; + first_m_name_idx = 2; + + } + else if (strncmp(argv[0], "disable", 8) == 0) + { + if (argc == 1) + { + all_modules = true; + } + lvl = NRF_LOG_SEVERITY_NONE; + first_m_name_idx = 1; + } + else + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Unknown option: %s\r\n", argv[0]); + return; + } + + if (all_modules) + { + for (i = 0; i < nrf_log_module_cnt_get(); i++) + { + if (module_id_filter_set(backend_id, i, lvl) == false) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, + "Level unavailable for module: %s\r\n", + nrf_log_module_name_get(i, false)); + } + } + } + else + { + for (i = first_m_name_idx; i < argc; i++) + { + uint32_t module_id = 0; + if (module_id_get(argv[i], &module_id) == false) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Unknown module:%s\r\n", argv[i]); + } + else if (module_id_filter_set(backend_id, module_id, lvl) == false) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, + "Level unavailable for module: %s\r\n", + nrf_log_module_name_get(module_id, false)); + } + else + { + /* empty */ + } + } + } + } +} + + +static void log_self_ctrl(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + log_ctrl(p_cli, p_cli->p_log_backend, argc, argv); +} + + +static void log_backend_ctrl(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + nrf_cli_backend_cmd_execute(p_cli, argc, argv, log_ctrl); +} + +static void module_name_get(size_t idx, nrf_cli_static_entry_t * p_static); + +NRF_CLI_CREATE_DYNAMIC_CMD(m_module_name, module_name_get); + +static void module_name_get(size_t idx, nrf_cli_static_entry_t * p_static) +{ + p_static->handler = NULL; + p_static->p_help = NULL; + p_static->p_subcmd = &m_module_name; + p_static->p_syntax = nrf_log_module_name_get(idx, true); +} + + +static void severity_lvl_get(size_t idx, nrf_cli_static_entry_t * p_static) +{ + p_static->handler = NULL; + p_static->p_help = NULL; + p_static->p_subcmd = &m_module_name; + p_static->p_syntax = (idx < ARRAY_SIZE(m_severity_lvls_sorted)) ? + m_severity_lvls_sorted[idx] : NULL; +} + +NRF_CLI_CREATE_DYNAMIC_CMD(m_severity_lvl, severity_lvl_get); + + +static void log_halt(nrf_cli_t const * p_cli, + nrf_log_backend_t const * p_backend, + size_t argc, + char * * argv) +{ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + + nrf_log_backend_disable(p_backend); +} + + +static void log_backend_halt(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + nrf_cli_backend_cmd_execute(p_cli, argc, argv, log_halt); +} + + +static void log_self_halt(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + log_halt(p_cli, p_cli->p_log_backend, argc, argv); +} + + +static void log_go(nrf_cli_t const * p_cli, + nrf_log_backend_t const * p_backend, + size_t argc, + char * * argv) +{ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + + nrf_log_backend_enable(p_backend); +} + + +static void log_backend_go(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + nrf_cli_backend_cmd_execute(p_cli, argc, argv, log_go); +} + + +static void log_self_go(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + log_go(p_cli, p_cli->p_log_backend, argc, argv); +} + + +static void log_cmd_backends_list(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + size_t num_of_backends; + + num_of_backends = NRF_SECTION_ITEM_COUNT(NRF_LOG_BACKEND_SECTION_NAME, nrf_log_backend_t); + for (size_t i = 0; i < num_of_backends; i++) + { + nrf_log_backend_t const * p_backend = + NRF_SECTION_ITEM_GET(NRF_LOG_BACKEND_SECTION_NAME, nrf_log_backend_t, i); + + if (p_backend->p_cb->id == NRF_LOG_BACKEND_INVALID_ID) + { + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, + "%s\r\n" + "\t- Status: deactivated\r\n\r\n", + p_backend->p_name); + } + else + { + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, + "%s\r\n" + "\t- Status: %s\r\n" + "\t- ID: %d\r\n\r\n", + p_backend->p_name, + p_backend->p_cb->enabled ? "enabled" : "disabled", + p_backend->p_cb->id); + } + } +} + + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_log_backend) +{ + NRF_CLI_CMD(disable, &m_module_name, + "'log disable .. ' disables logs in specified " + "modules (all if no modules specified).", + log_backend_ctrl), + NRF_CLI_CMD(enable, &m_severity_lvl, + "'log enable ... ' enables logs up to given level in " + "specified modules (all if no modules specified).", + log_backend_ctrl), + NRF_CLI_CMD(go, NULL, "Resume logging", log_backend_go), + NRF_CLI_CMD(halt, NULL, "Halt logging", log_backend_halt), + NRF_CLI_CMD(status, NULL, "Logger status", log_backend_status), + NRF_CLI_SUBCMD_SET_END +}; + +static void backend_name_get(size_t idx, nrf_cli_static_entry_t * p_static) +{ + p_static->handler = NULL; + p_static->p_help = NULL; + p_static->p_subcmd = &m_sub_log_backend; + p_static->p_syntax = NULL; + + nrf_log_backend_t const * p_backend; + size_t active_idx = 0; + uint32_t i; + + for (i = 0; i < NRF_SECTION_ITEM_COUNT(NRF_LOG_BACKEND_SECTION_NAME, nrf_log_backend_t); i++) + { + p_backend = NRF_SECTION_ITEM_GET(NRF_LOG_BACKEND_SECTION_NAME, nrf_log_backend_t, i); + if (p_backend->p_cb->id != NRF_LOG_BACKEND_INVALID_ID) + { + if (idx == active_idx) + { + p_static->p_syntax = p_backend->p_name; + break; + } + else + { + active_idx++; + } + } + } +} + +NRF_CLI_CREATE_DYNAMIC_CMD(m_backend_name_dynamic, backend_name_get); + +static void log_config_load_cmd(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + +#if LOG_CONFIG_LOAD_STORE_ENABLED + if (nrf_log_config_load() == NRF_SUCCESS) + { + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Configuration loaded.\r\n"); + } + else + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Failed to load the configuration.\r\n"); + } +#else + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Not supported.\r\n"); +#endif +} + +static void log_config_store_cmd(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + +#if LOG_CONFIG_LOAD_STORE_ENABLED + if (nrf_log_config_store() == NRF_SUCCESS) + { + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Configuration stored.\r\n"); + } + else + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Failed to store the configuration.\r\n"); + } +#else + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Not supported.\r\n"); +#endif +} + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_log_config) +{ + NRF_CLI_CMD(load, NULL, "Load configuration stored in non-volatile memory.", log_config_load_cmd), + NRF_CLI_CMD(store, NULL, "Store current configuration in non-volatile memory.", log_config_store_cmd), + NRF_CLI_SUBCMD_SET_END +}; + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_log_stat) +{ + NRF_CLI_CMD(backend, &m_backend_name_dynamic, "Logger backends commands.", NULL), + NRF_CLI_CMD(config, &m_sub_log_config, "Manage logger configuration", NULL), + NRF_CLI_CMD(disable, &m_module_name, + "'log disable .. ' disables logs in specified " + "modules (all if no modules specified).", + log_self_ctrl), + NRF_CLI_CMD(enable, &m_severity_lvl, + "'log enable ... ' enables logs up to given level in " + "specified modules (all if no modules specified).", + log_self_ctrl), + NRF_CLI_CMD(go, NULL, "Resume logging", log_self_go), + NRF_CLI_CMD(halt, NULL, "Halt logging", log_self_halt), + NRF_CLI_CMD(list_backends, NULL, "Lists logger backends.", log_cmd_backends_list), + NRF_CLI_CMD(status, NULL, "Logger status", log_self_status), + NRF_CLI_SUBCMD_SET_END +}; + +static void log_cmd(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if ((argc == 1) || nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "%s:%s%s\r\n", argv[0], " unknown parameter: ", argv[1]); +} + +NRF_CLI_CMD_REGISTER(log, &m_sub_log_stat, "Commands for controlling logger", log_cmd); + +#endif //NRF_LOG_CLI_CMDS + +#endif // NRF_MODULE_ENABLED(NRF_LOG) diff --git a/components/libraries/log/src/nrf_log_internal.h b/components/libraries/log/src/nrf_log_internal.h new file mode 100644 index 0000000..44cbe08 --- /dev/null +++ b/components/libraries/log/src/nrf_log_internal.h @@ -0,0 +1,516 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_LOG_INTERNAL_H__ +#define NRF_LOG_INTERNAL_H__ +#include "sdk_common.h" +#include "nrf.h" +#include "nrf_error.h" +#include "app_util.h" +#include +#include +#include "nrf_log_instance.h" +#include "nrf_log_types.h" + +#ifndef NRF_LOG_ERROR_COLOR + #define NRF_LOG_ERROR_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_WARNING_COLOR + #define NRF_LOG_WARNING_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_INFO_COLOR + #define NRF_LOG_INFO_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_DEBUG_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_LOG_COLOR_DEFAULT +#endif + + +#ifndef NRF_LOG_COLOR_DEFAULT +#define NRF_LOG_COLOR_DEFAULT 0 +#endif + +#ifndef NRF_LOG_DEFAULT_LEVEL +#define NRF_LOG_DEFAULT_LEVEL 0 +#endif + +#ifndef NRF_LOG_USES_COLORS +#define NRF_LOG_USES_COLORS 0 +#endif + +#ifndef NRF_LOG_USES_TIMESTAMP +#define NRF_LOG_USES_TIMESTAMP 0 +#endif + +#ifndef NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_FILTERS_ENABLED 0 +#endif + +#ifndef NRF_LOG_MODULE_NAME + #define NRF_LOG_MODULE_NAME app +#endif + +#define NRF_LOG_LEVEL_BITS 3 +#define NRF_LOG_LEVEL_MASK ((1UL << NRF_LOG_LEVEL_BITS) - 1) +#define NRF_LOG_MODULE_ID_BITS 16 +#define NRF_LOG_MODULE_ID_POS 16 + + +#define NRF_LOG_MAX_NUM_OF_ARGS 6 + + +#if NRF_LOG_FILTERS_ENABLED && NRF_LOG_ENABLED + #define NRF_LOG_FILTER NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME).filter + #define NRF_LOG_INST_FILTER(p_inst) (p_inst)->filter +#else + #undef NRF_LOG_FILTER + #define NRF_LOG_FILTER NRF_LOG_SEVERITY_DEBUG + #define NRF_LOG_INST_FILTER(p_inst) NRF_LOG_SEVERITY_DEBUG +#endif + +/** + * @brief Macro for calculating module id based on address and section start address + */ +#define NRF_LOG_MODULE_ID_GET_CONST(addr) (((uint32_t)(addr) - \ + (uint32_t)NRF_SECTION_START_ADDR(log_const_data)) / \ + sizeof(nrf_log_module_const_data_t)) +/** + * @brief Macro for calculating module id based on address and section start address + */ +#define NRF_LOG_MODULE_ID_GET_DYNAMIC(addr) (((uint32_t)(addr) - \ + (uint32_t)NRF_SECTION_START_ADDR(log_dynamic_data)) / \ + sizeof(nrf_log_module_dynamic_data_t)) + + +#if NRF_LOG_ENABLED +#define NRF_LOG_MODULE_ID NRF_LOG_MODULE_ID_GET_CONST(&NRF_LOG_ITEM_DATA_CONST(NRF_LOG_MODULE_NAME)) +#if NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_INST_ID(p_inst) NRF_LOG_MODULE_ID_GET_DYNAMIC(p_inst) +#else +#define NRF_LOG_INST_ID(p_inst) NRF_LOG_MODULE_ID +#endif +#else +#define NRF_LOG_MODULE_ID 0 +#define NRF_LOG_INST_ID(p_inst) 0 +#endif + + +#define LOG_INTERNAL_X(N, ...) CONCAT_2(LOG_INTERNAL_, N) (__VA_ARGS__) +#define LOG_INTERNAL(type, ...) LOG_INTERNAL_X(NUM_VA_ARGS_LESS_1( \ + __VA_ARGS__), type, __VA_ARGS__) +#if NRF_LOG_ENABLED +#define NRF_LOG_INTERNAL_LOG_PUSH(_str) nrf_log_push(_str) +#define LOG_INTERNAL_0(type, str) \ + nrf_log_frontend_std_0(type, str) +#define LOG_INTERNAL_1(type, str, arg0) \ + /*lint -save -e571*/nrf_log_frontend_std_1(type, str, (uint32_t)(arg0))/*lint -restore*/ +#define LOG_INTERNAL_2(type, str, arg0, arg1) \ + /*lint -save -e571*/nrf_log_frontend_std_2(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1))/*lint -restore*/ +#define LOG_INTERNAL_3(type, str, arg0, arg1, arg2) \ + /*lint -save -e571*/nrf_log_frontend_std_3(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2))/*lint -restore*/ +#define LOG_INTERNAL_4(type, str, arg0, arg1, arg2, arg3) \ + /*lint -save -e571*/nrf_log_frontend_std_4(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3))/*lint -restore*/ +#define LOG_INTERNAL_5(type, str, arg0, arg1, arg2, arg3, arg4) \ + /*lint -save -e571*/nrf_log_frontend_std_5(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4))/*lint -restore*/ +#define LOG_INTERNAL_6(type, str, arg0, arg1, arg2, arg3, arg4, arg5) \ + /*lint -save -e571*/nrf_log_frontend_std_6(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4), (uint32_t)(arg5))/*lint -restore*/ + + +#else //NRF_LOG_ENABLED +#define NRF_LOG_INTERNAL_LOG_PUSH(_str) (void)(_str) +#define LOG_INTERNAL_0(_type, _str) \ + (void)(_type); (void)(_str) +#define LOG_INTERNAL_1(_type, _str, _arg0) \ + (void)(_type); (void)(_str); (void)(_arg0) +#define LOG_INTERNAL_2(_type, _str, _arg0, _arg1) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1) +#define LOG_INTERNAL_3(_type, _str, _arg0, _arg1, _arg2) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2) +#define LOG_INTERNAL_4(_type, _str, _arg0, _arg1, _arg2, _arg3) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3) +#define LOG_INTERNAL_5(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4) +#define LOG_INTERNAL_6(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4, _arg5) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4); (void)(_arg5) +#endif //NRF_LOG_ENABLED + +#define LOG_SEVERITY_MOD_ID(severity) ((severity) | NRF_LOG_MODULE_ID << NRF_LOG_MODULE_ID_POS) +#define LOG_SEVERITY_INST_ID(severity,p_inst) ((severity) | NRF_LOG_INST_ID(p_inst) << NRF_LOG_MODULE_ID_POS) + +#if NRF_LOG_ENABLED +#define LOG_HEXDUMP(_severity, _p_data, _length) \ + nrf_log_frontend_hexdump((_severity), (_p_data), (_length)) +#else +#define LOG_HEXDUMP(_severity, _p_data, _length) \ + (void)(_severity); (void)(_p_data); (void)_length +#endif + +#define NRF_LOG_INTERNAL_INST(level, level_id, p_inst, ...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ + (level <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_INST_FILTER(p_inst) >= level) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_INST_ID(level_id, p_inst), __VA_ARGS__); \ + } \ + } + +#define NRF_LOG_INTERNAL_MODULE(level, level_id, ...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ + (level <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= level) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_MOD_ID(level_id), __VA_ARGS__); \ + } \ + } + +#define NRF_LOG_INTERNAL_HEXDUMP_INST(level, level_id, p_inst, p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ + (level <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_INST_FILTER(p_inst) >= level) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_INST_ID(level_id, p_inst), \ + (p_data), (len)); \ + } \ + } + +#define NRF_LOG_INTERNAL_HEXDUMP_MODULE(level, level_id, p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \ + (level <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= level) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(level_id), \ + (p_data), (len)); \ + } \ + } + +#define NRF_LOG_INTERNAL_INST_ERROR(p_inst, ...) \ + NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_inst, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_ERROR(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR,__VA_ARGS__) + +#define NRF_LOG_INTERNAL_HEXDUMP_INST_ERROR(p_inst, p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_inst, p_data, len) + +#define NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_data, len) + +#define NRF_LOG_INTERNAL_INST_WARNING(p_inst, ...) \ + NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_inst, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_WARNING(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING,__VA_ARGS__) + +#define NRF_LOG_INTERNAL_HEXDUMP_INST_WARNING(p_inst, p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_inst, p_data, len) + +#define NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_data, len) + +#define NRF_LOG_INTERNAL_INST_INFO(p_inst, ...) \ + NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_inst, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_INFO(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_HEXDUMP_INST_INFO(p_inst, p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_inst, p_data, len) + +#define NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_data, len) + +#define NRF_LOG_INTERNAL_RAW_INFO(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO_RAW, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO_RAW, p_data, len) + +#define NRF_LOG_INTERNAL_INST_DEBUG(p_inst, ...) \ + NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_inst, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_DEBUG(...) \ + NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, __VA_ARGS__) + +#define NRF_LOG_INTERNAL_HEXDUMP_INST_DEBUG(p_inst, p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_inst, p_data, len) + +#define NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) \ + NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_data, len) + + +#if NRF_LOG_ENABLED + +#ifdef UNIT_TEST +#define COMPILED_LOG_LEVEL 4 +#else +#define COMPILED_LOG_LEVEL NRF_LOG_LEVEL +#endif + + +#define NRF_LOG_INTERNAL_MODULE_REGISTER() \ + NRF_LOG_INTERNAL_ITEM_REGISTER(NRF_LOG_MODULE_NAME, \ + STRINGIFY(NRF_LOG_MODULE_NAME), \ + NRF_LOG_INFO_COLOR, \ + NRF_LOG_DEBUG_COLOR, \ + NRF_LOG_INITIAL_LEVEL, \ + COMPILED_LOG_LEVEL) + +#else +#define NRF_LOG_INTERNAL_MODULE_REGISTER() /*lint -save -e19*/ /*lint -restore*/ +#endif + +extern nrf_log_module_dynamic_data_t NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME); +extern _CONST nrf_log_module_const_data_t NRF_LOG_ITEM_DATA_CONST(NRF_LOG_MODULE_NAME); + +/** + * Set of macros for encoding and decoding header for log entries. + * There are 2 types of entries: + * 1. Standard entry (STD) + * An entry consists of header, pointer to string and values. Header contains + * severity leveland determines number of arguments and thus size of the entry. + * Since flash address space starts from 0x00000000 and is limited to kB rather + * than MB 22 bits are used to store the address (4MB). It is used that way to + * save one RAM memory. + * + * -------------------------------- + * |TYPE|SEVERITY|NARGS| P_STR | + * |------------------------------| + * | Module_ID (optional) | + * |------------------------------| + * | TIMESTAMP (optional) | + * |------------------------------| + * | ARG0 | + * |------------------------------| + * | .... | + * |------------------------------| + * | ARG(nargs-1) | + * -------------------------------- + * + * 2. Hexdump entry (HEXDUMP) is used for dumping raw data. An entry consists of + * header, optional timestamp, pointer to string and data. A header contains + * length (10bit) and offset which is updated after backend processes part of + * data. + * + * -------------------------------- + * |TYPE|SEVERITY|NARGS|OFFSET|LEN| + * |------------------------------| + * | Module_ID (optional) | + * |------------------------------| + * | TIMESTAMP (optional) | + * |------------------------------| + * | P_STR | + * |------------------------------| + * | data | + * |------------------------------| + * | data | dummy | + * -------------------------------- + * + */ + +#define STD_ADDR_MASK ((uint32_t)(1U << 22) - 1U) +#define HEADER_TYPE_STD 1U +#define HEADER_TYPE_HEXDUMP 2U +#define HEADER_TYPE_INVALID 3U + +typedef struct +{ + uint32_t type : 2; + uint32_t in_progress: 1; + uint32_t data : 29; +} nrf_log_generic_header_t; + +typedef struct +{ + uint32_t type : 2; + uint32_t in_progress: 1; + uint32_t severity : 3; + uint32_t nargs : 4; + uint32_t addr : 22; +} nrf_log_std_header_t; + +typedef struct +{ + uint32_t type : 2; + uint32_t in_progress: 1; + uint32_t severity : 3; + uint32_t offset : 10; + uint32_t reserved : 6; + uint32_t len : 10; +} nrf_log_hexdump_header_t; + +typedef union +{ + nrf_log_generic_header_t generic; + nrf_log_std_header_t std; + nrf_log_hexdump_header_t hexdump; + uint32_t raw; +} nrf_log_main_header_t; + +typedef struct +{ + nrf_log_main_header_t base; + uint16_t module_id; + uint16_t dropped; + uint32_t timestamp; +} nrf_log_header_t; + +#define HEADER_SIZE (sizeof(nrf_log_header_t)/sizeof(uint32_t) - \ + (NRF_LOG_USES_TIMESTAMP ? 0 : 1)) + +/** + * @brief A function for logging raw string. + * + * @param severity_mid Severity. + * @param p_str A pointer to a string. + */ +void nrf_log_frontend_std_0(uint32_t severity_mid, char const * const p_str); + +/** + * @brief A function for logging a formatted string with one argument. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0 An argument. + */ +void nrf_log_frontend_std_1(uint32_t severity_mid, + char const * const p_str, + uint32_t val0); + +/** + * @brief A function for logging a formatted string with 2 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1 Arguments for formatting string. + */ +void nrf_log_frontend_std_2(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1); + +/** + * @brief A function for logging a formatted string with 3 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2 Arguments for formatting string. + */ +void nrf_log_frontend_std_3(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2); + +/** + * @brief A function for logging a formatted string with 4 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3 Arguments for formatting string. + */ +void nrf_log_frontend_std_4(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3); + +/** + * @brief A function for logging a formatted string with 5 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3, val4 Arguments for formatting string. + */ +void nrf_log_frontend_std_5(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4); + +/** + * @brief A function for logging a formatted string with 6 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3, val4, val5 Arguments for formatting string. + */ +void nrf_log_frontend_std_6(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4, + uint32_t val5); + +/** + * @brief A function for logging raw data. + * + * @param severity_mid Severity. + * @param p_str A pointer to a string which is prefixing the data. + * @param p_data A pointer to data to be dumped. + * @param length Length of data (in bytes). + * + */ +void nrf_log_frontend_hexdump(uint32_t severity_mid, + const void * const p_data, + uint16_t length); + +/** + * @brief A function for reading a byte from log backend. + * + * @return Byte. + */ +uint8_t nrf_log_getchar(void); +#endif // NRF_LOG_INTERNAL_H__ diff --git a/components/libraries/log/src/nrf_log_str_formatter.c b/components/libraries/log/src/nrf_log_str_formatter.c new file mode 100644 index 0000000..7803f43 --- /dev/null +++ b/components/libraries/log/src/nrf_log_str_formatter.c @@ -0,0 +1,258 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "nrf_log_str_formatter.h" +#include "nrf_log_internal.h" +#include "nrf_log_ctrl.h" +#include "nrf_fprintf.h" +#include + +#define NRF_LOG_COLOR_CODE_DEFAULT "\x1B[0m" +#define NRF_LOG_COLOR_CODE_BLACK "\x1B[1;30m" +#define NRF_LOG_COLOR_CODE_RED "\x1B[1;31m" +#define NRF_LOG_COLOR_CODE_GREEN "\x1B[1;32m" +#define NRF_LOG_COLOR_CODE_YELLOW "\x1B[1;33m" +#define NRF_LOG_COLOR_CODE_BLUE "\x1B[1;34m" +#define NRF_LOG_COLOR_CODE_MAGENTA "\x1B[1;35m" +#define NRF_LOG_COLOR_CODE_CYAN "\x1B[1;36m" +#define NRF_LOG_COLOR_CODE_WHITE "\x1B[1;37m" + +#define NRF_LOG_CHAR_CODE_MAX 0x7E + +static const char * severity_names[] = { + NULL, + "error", + "warning", + "info", + "debug" +}; + +static const char * m_colors[] = { + NRF_LOG_COLOR_CODE_DEFAULT, + NRF_LOG_COLOR_CODE_BLACK, + NRF_LOG_COLOR_CODE_RED, + NRF_LOG_COLOR_CODE_GREEN, + NRF_LOG_COLOR_CODE_YELLOW, + NRF_LOG_COLOR_CODE_BLUE, + NRF_LOG_COLOR_CODE_MAGENTA, + NRF_LOG_COLOR_CODE_CYAN, + NRF_LOG_COLOR_CODE_WHITE, +}; + +static uint32_t m_freq; +static uint32_t m_timestamp_div; + +static void timestamp_print(nrf_fprintf_ctx_t * p_ctx, uint32_t timestamp) +{ + if (NRF_LOG_USES_TIMESTAMP) + { + if (NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED) + { + timestamp /= m_timestamp_div; + uint32_t seconds = timestamp/m_freq; + uint32_t hours = seconds/3600; + seconds -= hours * 3600; + uint32_t mins = seconds/60; + seconds -= mins * 60; + + uint32_t reminder = timestamp % m_freq; + uint32_t ms = (reminder * 1000)/m_freq; + uint32_t us = (1000*(1000*reminder - (ms * m_freq)))/m_freq; + + nrf_fprintf(p_ctx, "[%02d:%02d:%02d.%03d,%03d] ", hours, mins, seconds, ms, us); + } + else + { + nrf_fprintf(p_ctx, "[%08lu] ", timestamp); + } + } +} +static void prefix_process(nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx) +{ + if (p_params->dropped) + { + nrf_fprintf(p_ctx, + "%sLogs dropped (%d)%s\r\n", + NRF_LOG_COLOR_CODE_RED, + p_params->dropped, + NRF_LOG_COLOR_CODE_DEFAULT); + } + + if (!(p_params->severity == NRF_LOG_SEVERITY_INFO_RAW)) + { + if (p_params->use_colors) + { + nrf_fprintf(p_ctx, "%s", + m_colors[nrf_log_color_id_get( p_params->module_id, p_params->severity)]); + } + timestamp_print(p_ctx, p_params->timestamp); + + nrf_fprintf(p_ctx, "<%s> %s: ", + severity_names[p_params->severity], nrf_log_module_name_get(p_params->module_id, false)); + } +} + +static void postfix_process(nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx, + bool newline) +{ + if (!(p_params->severity == NRF_LOG_SEVERITY_INFO_RAW)) + { + if (p_params->use_colors) + { + nrf_fprintf(p_ctx, "%s", m_colors[0]); + } + nrf_fprintf(p_ctx, "\r\n"); + } + else if (newline) + { + nrf_fprintf(p_ctx, "\r\n"); + } + nrf_fprintf_buffer_flush(p_ctx); +} + +void nrf_log_std_entry_process(char const * p_str, + uint32_t const * p_args, + uint32_t nargs, + nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx) +{ + bool auto_flush = p_ctx->auto_flush; + p_ctx->auto_flush = false; + + prefix_process(p_params, p_ctx); + + switch (nargs) + { + case 0: + nrf_fprintf(p_ctx, p_str); + break; + case 1: + nrf_fprintf(p_ctx, p_str, p_args[0]); + break; + case 2: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1]); + break; + case 3: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2]); + break; + case 4: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3]); + break; + case 5: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3], p_args[4]); + break; + case 6: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5]); + break; + + default: + break; + } + + postfix_process(p_params, p_ctx, false); + p_ctx->auto_flush = auto_flush; +} + +#define HEXDUMP_BYTES_IN_LINE 8 + +void nrf_log_hexdump_entry_process(uint8_t * p_data, + uint32_t data_len, + nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx) +{ + if (data_len > HEXDUMP_BYTES_IN_LINE) + { + return; + } + bool auto_flush = p_ctx->auto_flush; + p_ctx->auto_flush = false; + + prefix_process(p_params, p_ctx); + + uint32_t i; + + for (i = 0; i < HEXDUMP_BYTES_IN_LINE; i++) + { + if (i < data_len) + { + nrf_fprintf(p_ctx, " %02x", p_data[i]); + } + else + { + nrf_fprintf(p_ctx, " "); + } + } + nrf_fprintf(p_ctx, "|"); + + for (i = 0; i < HEXDUMP_BYTES_IN_LINE; i++) + { + if (i < data_len) + { + char c = (char)p_data[i]; + nrf_fprintf(p_ctx, "%c", ((c <= NRF_LOG_CHAR_CODE_MAX) && isprint((int)c)) ? c :'.'); + } + else + { + nrf_fprintf(p_ctx, " "); + } + } + + postfix_process(p_params, p_ctx, true); + + p_ctx->auto_flush = auto_flush; +} + +void nrf_log_str_formatter_timestamp_freq_set(uint32_t freq) +{ + m_timestamp_div = 1; + /* There is no point to have frequency higher than 1MHz (ns are not printed) and too high + * frequency leads to overflows in calculations. + */ + while (freq > 1000000) + { + freq /= 2; + m_timestamp_div *= 2; + } + m_freq = freq; +} +#endif //NRF_LOG_ENABLED diff --git a/components/libraries/mem_manager/mem_manager.c b/components/libraries/mem_manager/mem_manager.c new file mode 100644 index 0000000..6df4fcd --- /dev/null +++ b/components/libraries/mem_manager/mem_manager.c @@ -0,0 +1,979 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(MEM_MANAGER) +#include +#include "mem_manager.h" +#include "nrf_assert.h" + +#define NRF_LOG_MODULE_NAME mem_mngr + +#if MEM_MANAGER_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL MEM_MANAGER_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR MEM_MANAGER_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR MEM_MANAGER_CONFIG_DEBUG_COLOR +#else //MEM_MANAGER_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //MEM_MANAGER_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/** + * @defgroup memory_manager_mutex_lock_unlock Module's Mutex Lock/Unlock Macros. + * + * @details Macros used to lock and unlock modules. Currently the SDK does not use mutexes but + * framework is provided in case need arises to use an alternative architecture. + * @{ + */ +#define MM_MUTEX_LOCK() SDK_MUTEX_LOCK(m_mm_mutex) /**< Lock module using mutex. */ +#define MM_MUTEX_UNLOCK() SDK_MUTEX_UNLOCK(m_mm_mutex) /**< Unlock module using mutex. */ +/** @} */ + +#undef NULL_PARAM_CHECK +#undef NULL_PARAM_CHECK_VOID +#undef VERIFY_MODULE_INITIALIZED +#undef VERIFY_MODULE_INITIALIZED_VOID +#undef VERIFY_REQUESTED_SIZE +#undef VERIFY_REQUESTED_SIZE_VOID + +#if (MEM_MANAGER_DISABLE_API_PARAM_CHECK == 0) + +/** + * @brief Macro for verifying NULL parameters. + * Returning with an appropriate error code on failure. + * + * @param[in] PARAM Parameter checked for NULL. + * + * @retval (NRF_ERROR_NULL | NRF_ERROR_MEMORY_MANAGER_ERR_BASE) when @ref PARAM is NULL. + */ +#define NULL_PARAM_CHECK(PARAM) \ + if ((PARAM) == NULL) \ + { \ + return (NRF_ERROR_NULL | NRF_ERROR_MEMORY_MANAGER_ERR_BASE); \ + } + +/** + * @brief Macro for verifying NULL parameters are not passed to API and returning on failure. + * + * @param[in] PARAM Parameter checked for NULL. + */ +#define NULL_PARAM_CHECK_VOID(PARAM) \ + if ((PARAM) == NULL) \ + { \ + return; \ + } + + +/** + * @brief Macro for verifying module's initialization status. + * Returning with an appropriate error code on failure. + * + * @retval (NRF_ERROR_INVALID_STATE | NRF_ERROR_MEMORY_MANAGER_ERR_BASE) module is uninitialized. + */ +#define VERIFY_MODULE_INITIALIZED() \ + do \ + { \ + if (!m_module_initialized) \ + { \ + return (NRF_ERROR_INVALID_STATE | NRF_ERROR_MEMORY_MANAGER_ERR_BASE); \ + } \ + } while (0) + +/** + * @brief Macro for verifying module's initialization status and returning on failure. + */ +#define VERIFY_MODULE_INITIALIZED_VOID() \ + do \ + { \ + if (!m_module_initialized) \ + { \ + return; \ + } \ + } while (0) + + +/** + * @brief Macro for verifying requested size of memory does not exceed maximum block + * size supported by the module. Returning with appropriate error code on failure. + * + * @param[in] SIZE Requested size to be allocated. + * + * @retval (NRF_ERROR_INVALID_PARAM | NRF_ERROR_MEMORY_MANAGER_ERR_BASE) if requested size is greater + * than the largest block size managed by the module. + */ +#define VERIFY_REQUESTED_SIZE(SIZE) \ + do \ + { \ + if (((SIZE) == 0) ||((SIZE) > MAX_MEM_SIZE)) \ + { \ + return (NRF_ERROR_INVALID_PARAM | NRF_ERROR_MEMORY_MANAGER_ERR_BASE); \ + } \ + } while (0) + + +/** + * @brief Macro for verifying requested size of memory does not exceed maximum block + * size supported by the module. Returns on failure. + * + * @param[in] SIZE Requested size to be allocated. + */ +#define VERIFY_REQUESTED_SIZE_VOID(SIZE) \ + do \ + { \ + if (((SIZE) == 0) ||((SIZE) > MAX_MEM_SIZE)) \ + { \ + return; \ + } \ + } while (0) + + +/**@} */ +#else //MEM_MANAGER_DISABLE_API_PARAM_CHECK + +#define NULL_PARAM_CHECK(PARAM) +#define VERIFY_MODULE_INITIALIZED() +#define VERIFY_REQUESTED_SIZE(SIZE) + +#endif //MEM_MANAGER_DISABLE_API_PARAM_CHECK + + +/**@brief Setting defaults in case XXSmall block not used by application. */ +#ifndef MEMORY_MANAGER_XXSMALL_BLOCK_COUNT + #define MEMORY_MANAGER_XXSMALL_BLOCK_COUNT 0 + #define MEMORY_MANAGER_XXSMALL_BLOCK_SIZE 0 + #define XXSMALL_BLOCK_START 0 + #define XXSMALL_BLOCK_END 0 + #define XXSMALL_MEMORY_START 0 +#endif // MEMORY_MANAGER_XXSMALL_BLOCK_SIZE + + +/**@brief Setting defaults in case XSmall block not used by application. */ +#ifndef MEMORY_MANAGER_XSMALL_BLOCK_COUNT + #define MEMORY_MANAGER_XSMALL_BLOCK_COUNT 0 + #define MEMORY_MANAGER_XSMALL_BLOCK_SIZE 0 + #define XSMALL_BLOCK_START 0 + #define XSMALL_BLOCK_END 0 + #define XSMALL_MEMORY_START 0 +#endif // MEMORY_MANAGER_XSMALL_BLOCK_SIZE + + +/**@brief Setting defaults in case Small block not used by application. */ +#ifndef MEMORY_MANAGER_SMALL_BLOCK_COUNT + #define MEMORY_MANAGER_SMALL_BLOCK_COUNT 0 + #define MEMORY_MANAGER_SMALL_BLOCK_SIZE 0 + #define SMALL_BLOCK_START 0 + #define SMALL_BLOCK_END 0 + #define SMALL_MEMORY_START 0 +#endif // MEMORY_MANAGER_SMALL_BLOCK_COUNT + + +/**@brief Setting defaults in case Medium block not used by application. */ +#ifndef MEMORY_MANAGER_MEDIUM_BLOCK_COUNT + #define MEMORY_MANAGER_MEDIUM_BLOCK_COUNT 0 + #define MEMORY_MANAGER_MEDIUM_BLOCK_SIZE 0 + #define MEDIUM_BLOCK_START 0 + #define MEDIUM_BLOCK_END 0 + #define MEDIUM_MEMORY_START 0 +#endif // MEMORY_MANAGER_MEDIUM_BLOCK_COUNT + + +/**@brief Setting defaults in case Large block not used by application. */ +#ifndef MEMORY_MANAGER_LARGE_BLOCK_COUNT + #define MEMORY_MANAGER_LARGE_BLOCK_COUNT 0 + #define MEMORY_MANAGER_LARGE_BLOCK_SIZE 0 + #define LARGE_BLOCK_START 0 + #define LARGE_BLOCK_END 0 + #define LARGE_MEMORY_START 0 +#endif // MEMORY_MANAGER_LARGE_BLOCK_COUNT + + +/**@brief Setting defaults in case XLarge block not used by application. */ +#ifndef MEMORY_MANAGER_XLARGE_BLOCK_COUNT + #define MEMORY_MANAGER_XLARGE_BLOCK_COUNT 0 + #define MEMORY_MANAGER_XLARGE_BLOCK_SIZE 0 + #define XLARGE_BLOCK_START 0 + #define XLARGE_BLOCK_END 0 + #define XLARGE_MEMORY_START 0 +#endif // MEMORY_MANAGER_XLARGE_BLOCK_COUNT + + +/**@brief Setting defaults in case XXLarge block not used by application. */ +#ifndef MEMORY_MANAGER_XXLARGE_BLOCK_COUNT + #define MEMORY_MANAGER_XXLARGE_BLOCK_COUNT 0 + #define MEMORY_MANAGER_XXLARGE_BLOCK_SIZE 0 + #define XXLARGE_BLOCK_START 0 + #define XXLARGE_BLOCK_END 0 + #define XXLARGE_MEMORY_START 0 +#endif // MEMORY_MANAGER_XXLARGE_BLOCK_COUNT + + +/**@brief Based on which blocks are defined, MAX_MEM_SIZE is determined. + * + * @note Also, in case none of these are defined, a compile time error is indicated. + */ +#if (MEMORY_MANAGER_XXLARGE_BLOCK_COUNT != 0) + #define MAX_MEM_SIZE MEMORY_MANAGER_XXLARGE_BLOCK_SIZE +#elif (MEMORY_MANAGER_XLARGE_BLOCK_COUNT != 0) + #define MAX_MEM_SIZE MEMORY_MANAGER_XLARGE_BLOCK_SIZE +#elif (MEMORY_MANAGER_LARGE_BLOCK_COUNT != 0) + #define MAX_MEM_SIZE MEMORY_MANAGER_LARGE_BLOCK_SIZE +#elif (MEMORY_MANAGER_MEDIUM_BLOCK_COUNT != 0) + #define MAX_MEM_SIZE MEMORY_MANAGER_MEDIUM_BLOCK_SIZE +#elif (MEMORY_MANAGER_SMALL_BLOCK_COUNT != 0) + #define MAX_MEM_SIZE MEMORY_MANAGER_SMALL_BLOCK_SIZE +#elif (MEMORY_MANAGER_XSMALL_BLOCK_COUNT != 0) + #define MAX_MEM_SIZE MEMORY_MANAGER_XSMALL_BLOCK_SIZE +#elif (MEMORY_MANAGER_XXSMALL_BLOCK_COUNT != 0) + #define MAX_MEM_SIZE MEMORY_MANAGER_XXSMALL_BLOCK_SIZE +#else + #err "One of MEMORY_MANAGER_SMALL_BLOCK_COUNT, MEMORY_MANAGER_MEDIUM_BLOCK_COUNT or \ + or MEMORY_MANAGER_LARGE_BLOCK_COUNT should be defined." +#endif + +/**@brief XXSmall block start index in case XXSmall Block is defined. */ +#ifndef XXSMALL_BLOCK_START +#define XXSMALL_BLOCK_START 0 +#endif // XXSMALL_BLOCK_START + + +/**@brief XSmall block start index in case XSmall Block is defined. */ +#ifndef XSMALL_BLOCK_START +#define XSMALL_BLOCK_START (XXSMALL_BLOCK_START + MEMORY_MANAGER_XXSMALL_BLOCK_COUNT) +#endif // XSMALL_BLOCK_START + + +/**@brief Small block start index in case Small Block is defined. */ +#ifndef SMALL_BLOCK_START +#define SMALL_BLOCK_START (XSMALL_BLOCK_START + MEMORY_MANAGER_XSMALL_BLOCK_COUNT) +#endif // SMALL_BLOCK_START + + +/**@brief Medium block start index in case Medium Block is defined. */ +#ifndef MEDIUM_BLOCK_START +#define MEDIUM_BLOCK_START (SMALL_BLOCK_START + MEMORY_MANAGER_SMALL_BLOCK_COUNT) +#endif // MEDIUM_BLOCK_START + + +/**@brief Large block start index in case Large Block is defined. */ +#ifndef LARGE_BLOCK_START +#define LARGE_BLOCK_START (MEDIUM_BLOCK_START + MEMORY_MANAGER_MEDIUM_BLOCK_COUNT) +#endif // LARGE_BLOCK_START + + +/**@brief XLarge block start index in case XLarge Block is defined. */ +#ifndef XLARGE_BLOCK_START +#define XLARGE_BLOCK_START (LARGE_BLOCK_START + MEMORY_MANAGER_LARGE_BLOCK_COUNT) +#endif // XLARGE_BLOCK_START + +/**@brief XXLarge block start index in case XXLarge Block is defined. */ +#ifndef XXLARGE_BLOCK_START +#define XXLARGE_BLOCK_START (XLARGE_BLOCK_START + MEMORY_MANAGER_XLARGE_BLOCK_COUNT) +#endif //XXLARGE_BLOCK_START + + +/**@brief XXSmall block end index in case XXSmall Block is defined. */ +#ifndef XXSMALL_BLOCK_END +#define XXSMALL_BLOCK_END (XXSMALL_BLOCK_START + MEMORY_MANAGER_XXSMALL_BLOCK_COUNT) +#endif // XXSMALL_BLOCK_END + +/**@brief XSmall block end index in case XSmall Block is defined. */ +#ifndef XSMALL_BLOCK_END +#define XSMALL_BLOCK_END (XSMALL_BLOCK_START + MEMORY_MANAGER_XSMALL_BLOCK_COUNT) +#endif // XSMALL_BLOCK_END + + +/**@brief Small block end index in case Small Block is defined. */ +#ifndef SMALL_BLOCK_END +#define SMALL_BLOCK_END (SMALL_BLOCK_START + MEMORY_MANAGER_SMALL_BLOCK_COUNT) +#endif // SMALL_BLOCK_END + + +/**@brief Medium block end index in case Medium Block is defined. */ +#ifndef MEDIUM_BLOCK_END +#define MEDIUM_BLOCK_END (MEDIUM_BLOCK_START + MEMORY_MANAGER_MEDIUM_BLOCK_COUNT) +#endif // MEDIUM_BLOCK_END + + +/**@brief Large block end index in case Large Block is defined. */ +#ifndef LARGE_BLOCK_END +#define LARGE_BLOCK_END (LARGE_BLOCK_START + MEMORY_MANAGER_LARGE_BLOCK_COUNT) +#endif // LARGE_BLOCK_END + + +/**@brief XLarge block end index in case XLarge Block is defined. */ +#ifndef XLARGE_BLOCK_END +#define XLARGE_BLOCK_END (XLARGE_BLOCK_START + MEMORY_MANAGER_XLARGE_BLOCK_COUNT) +#endif // XLARGE_BLOCK_END + + +/**@brief XXLarge block end index in case XXLarge Block is defined. */ +#ifndef XXLARGE_BLOCK_END +#define XXLARGE_BLOCK_END (XXLARGE_BLOCK_START + MEMORY_MANAGER_XXLARGE_BLOCK_COUNT) +#endif //XXLARGE_BLOCK_END + + +#define XXSMALL_MEMORY_SIZE (MEMORY_MANAGER_XXSMALL_BLOCK_COUNT * MEMORY_MANAGER_XXSMALL_BLOCK_SIZE) +#define XSMALL_MEMORY_SIZE (MEMORY_MANAGER_XSMALL_BLOCK_COUNT * MEMORY_MANAGER_XSMALL_BLOCK_SIZE) +#define SMALL_MEMORY_SIZE (MEMORY_MANAGER_SMALL_BLOCK_COUNT * MEMORY_MANAGER_SMALL_BLOCK_SIZE) +#define MEDIUM_MEMORY_SIZE (MEMORY_MANAGER_MEDIUM_BLOCK_COUNT * MEMORY_MANAGER_MEDIUM_BLOCK_SIZE) +#define LARGE_MEMORY_SIZE (MEMORY_MANAGER_LARGE_BLOCK_COUNT * MEMORY_MANAGER_LARGE_BLOCK_SIZE) +#define XLARGE_MEMORY_SIZE (MEMORY_MANAGER_XLARGE_BLOCK_COUNT * MEMORY_MANAGER_XLARGE_BLOCK_SIZE) +#define XXLARGE_MEMORY_SIZE (MEMORY_MANAGER_XXLARGE_BLOCK_COUNT * MEMORY_MANAGER_XXLARGE_BLOCK_SIZE) + + +/**@brief XXSmall memory start index in case XXSmall Block is defined. */ +#ifndef XXSMALL_MEMORY_START +#define XXSMALL_MEMORY_START 0 +#endif // XXSMALL_MEMORY_START + + +/**@brief XSmall memory start index in case XSmall Block is defined. */ +#ifndef XSMALL_MEMORY_START +#define XSMALL_MEMORY_START (XXSMALL_MEMORY_START + XXSMALL_MEMORY_SIZE) +#endif // XSMALL_MEMORY_START + + +/**@brief Small memory start index in case Small Block is defined. */ +#ifndef SMALL_MEMORY_START +#define SMALL_MEMORY_START (XSMALL_MEMORY_START + XSMALL_MEMORY_SIZE) +#endif // SMALL_MEMORY_START + + +/**@brief Medium memory start index in case Medium Block is defined. */ +#ifndef MEDIUM_MEMORY_START +#define MEDIUM_MEMORY_START (SMALL_MEMORY_START + SMALL_MEMORY_SIZE) +#endif // MEDIUM_MEMORY_START + + +/**@brief Large memory start index in case Large Block is defined. */ +#ifndef LARGE_MEMORY_START +#define LARGE_MEMORY_START (MEDIUM_MEMORY_START + MEDIUM_MEMORY_SIZE) +#endif // LARGE_MEMORY_START + + +/**@brief XLarge memory start index in case XLarge Block is defined. */ +#ifndef XLARGE_MEMORY_START +#define XLARGE_MEMORY_START (LARGE_MEMORY_START + LARGE_MEMORY_SIZE) +#endif // XLARGE_MEMORY_START + + +/**@brief XXLarge memory start index in case XXLarge Block is defined. */ +#ifndef XXLARGE_MEMORY_START +#define XXLARGE_MEMORY_START (XLARGE_MEMORY_START + XLARGE_MEMORY_SIZE) +#endif // XLARGE_MEMORY_START + + +/**@brief Total count of block managed by the module. */ +#define TOTAL_BLOCK_COUNT (MEMORY_MANAGER_XXSMALL_BLOCK_COUNT + \ + MEMORY_MANAGER_XSMALL_BLOCK_COUNT + \ + MEMORY_MANAGER_SMALL_BLOCK_COUNT + \ + MEMORY_MANAGER_MEDIUM_BLOCK_COUNT + \ + MEMORY_MANAGER_LARGE_BLOCK_COUNT + \ + MEMORY_MANAGER_XLARGE_BLOCK_COUNT + \ + MEMORY_MANAGER_XXLARGE_BLOCK_COUNT) + + +/**@brief Total memory managed by the module. */ +#define TOTAL_MEMORY_SIZE (XXSMALL_MEMORY_SIZE + \ + XSMALL_MEMORY_SIZE + \ + SMALL_MEMORY_SIZE + \ + MEDIUM_MEMORY_SIZE + \ + LARGE_MEMORY_SIZE + \ + XLARGE_MEMORY_SIZE + \ + XXLARGE_MEMORY_SIZE) + + +#define BLOCK_CAT_COUNT 7 /**< Block category count is 7 (xxsmall, xsmall, small, medium, large, xlarge, xxlarge). Having one of the block count to zero has no impact on this count. */ +#define BLOCK_CAT_XXS 0 /**< Extra Extra Small category identifier. */ +#define BLOCK_CAT_XS 1 /**< Extra Small category identifier. */ +#define BLOCK_CAT_SMALL 2 /**< Small category identifier. */ +#define BLOCK_CAT_MEDIUM 3 /**< Medium category identifier. */ +#define BLOCK_CAT_LARGE 4 /**< Large category identifier. */ +#define BLOCK_CAT_XL 5 /**< Extra Large category identifier. */ +#define BLOCK_CAT_XXL 6 /**< Extra Extra Large category identifier. */ + +#define BITMAP_SIZE 32 /**< Bitmap size for each word used to contain block information. */ +#define BLOCK_BITMAP_ARRAY_SIZE CEIL_DIV(TOTAL_BLOCK_COUNT, BITMAP_SIZE) /**< Determines number of blocks needed for book keeping availability status of all blocks. */ + + +/**@brief Lookup table for maximum memory size per block category. */ +static const uint32_t m_block_size[BLOCK_CAT_COUNT] = +{ + MEMORY_MANAGER_XXSMALL_BLOCK_SIZE, + MEMORY_MANAGER_XSMALL_BLOCK_SIZE, + MEMORY_MANAGER_SMALL_BLOCK_SIZE, + MEMORY_MANAGER_MEDIUM_BLOCK_SIZE, + MEMORY_MANAGER_LARGE_BLOCK_SIZE, + MEMORY_MANAGER_XLARGE_BLOCK_SIZE, + MEMORY_MANAGER_XXLARGE_BLOCK_SIZE +}; + +/**@brief Lookup table for block start index for each block category. */ +static const uint32_t m_block_start[BLOCK_CAT_COUNT] = +{ + XXSMALL_BLOCK_START, + XSMALL_BLOCK_START, + SMALL_BLOCK_START, + MEDIUM_BLOCK_START, + LARGE_BLOCK_START, + XLARGE_BLOCK_START, + XXLARGE_BLOCK_START +}; + +/**@brief Lookup table for last block index for each block category. */ +static const uint32_t m_block_end[BLOCK_CAT_COUNT] = +{ + XXSMALL_BLOCK_END, + XSMALL_BLOCK_END, + SMALL_BLOCK_END, + MEDIUM_BLOCK_END, + LARGE_BLOCK_END, + XLARGE_BLOCK_END, + XXLARGE_BLOCK_END +}; + +/**@brief Lookup table for memory start range for each block category. */ +static const uint32_t m_block_mem_start[BLOCK_CAT_COUNT] = +{ + XXSMALL_MEMORY_START, + XSMALL_MEMORY_START, + SMALL_MEMORY_START, + MEDIUM_MEMORY_START, + LARGE_MEMORY_START, + XLARGE_MEMORY_START, + XXLARGE_MEMORY_START +}; + +static uint8_t m_memory[TOTAL_MEMORY_SIZE]; /**< Memory managed by the module. */ +static uint32_t m_mem_pool[BLOCK_BITMAP_ARRAY_SIZE]; /**< Bitmap used for book-keeping availability of all blocks managed by the module. */ + +#if defined(MEM_MANAGER_ENABLE_DIAGNOSTICS) && (MEM_MANAGER_ENABLE_DIAGNOSTICS == 1) + +uint8_t* mem_begin = &m_memory[0]; +uint8_t* mem_end = &m_memory[TOTAL_MEMORY_SIZE]; + +/**@brief Lookup table for descriptive strings for each block category. */ +static const char * m_block_desc_str[BLOCK_CAT_COUNT] = +{ + "XXSmall", + "XSmall", + "Small", + "Medium", + "Large", + "XLarge", + "XXLarge" +}; + +static const uint32_t m_min_size_default[BLOC_CAT_COUNT] = +{ + MEMORY_MANAGER_XXSMALL_BLOCK_SIZE, + MEMORY_MANAGER_XSMALL_BLOCK_SIZE, + MEMORY_MANAGER_SMALL_BLOCK_SIZE, + MEMORY_MANAGER_MEDIUM_BLOCK_SIZE, + MEMORY_MANAGER_LARGE_BLOCK_SIZE, + MEMORY_MANAGER_XLARGE_BLOCK_SIZE, + MEMORY_MANAGER_XXLARGE_BLOCK_SIZE +} + +/**@brief Table for book keeping smallest size allocated in each block range. */ +static uint32_t m_min_size[BLOCK_CAT_COUNT]; + +/**@brief Table for book keeping largest size allocated in each block range. */ +static uint32_t m_max_size[BLOCK_CAT_COUNT]; + +/**@brief Table for keeping the peak count in each block range. */ +static uint32_t m_peak_count[BLOCK_CAT_COUNT]; + +/**@brief Table for keeping the current count in each block range. */ +static uint32_t m_cur_count[BLOCK_CAT_COUNT]; + +/**@brief Global pointing to minimum size holder for block type being allocated. */ +static uint32_t * p_min_size; + +/**@brief Global pointing to maximum size holder for block type being allocated. */ +static uint32_t * p_max_size; + +/**@brief Lookup table for count of block available in each block category. */ +static uint32_t m_block_count[BLOCK_CAT_COUNT] = +{ + MEMORY_MANAGER_XXSMALL_BLOCK_COUNT, + MEMORY_MANAGER_XSMALL_BLOCK_COUNT, + MEMORY_MANAGER_SMALL_BLOCK_COUNT, + MEMORY_MANAGER_MEDIUM_BLOCK_COUNT, + MEMORY_MANAGER_LARGE_BLOCK_COUNT, + MEMORY_MANAGER_XLARGE_BLOCK_COUNT, + MEMORY_MANAGER_XXLARGE_BLOCK_COUNT +}; + +#endif // MEM_MANAGER_ENABLE_DIAGNOSTICS + +SDK_MUTEX_DEFINE(m_mm_mutex) /**< Mutex variable. Currently unused, this declaration does not occupy any space in RAM. */ +#if (MEM_MANAGER_DISABLE_API_PARAM_CHECK == 0) +static bool m_module_initialized = false; /**< State indicating if module is initialized or not. */ +#endif // MEM_MANAGER_DISABLE_API_PARAM_CHECK + + +/**@brief Function to get X and Y coordinates. + * + * @details Function to get X and Y co-ordinates for the block identified by index. + * Here, X determines relevant word for the block. Y determines the actual bit in the word. + * + * @param[in] index Identifies the block. + * @param[out] p_x Points to the word that contains the bit representing the block. + * @param[out] p_y Contains the bitnumber in the the word 'X' relevant to the block. + */ +static __INLINE void get_block_coordinates(uint32_t block_index, uint32_t * p_x, uint32_t * p_y) +{ + // Determine position of the block in the bitmap. + // X determines relevant word for the block. Y determines the actual bit in the word. + const uint32_t x = block_index / BITMAP_SIZE; + const uint32_t y = (block_index - x * BITMAP_SIZE); + + (*p_x) = x; + (*p_y) = y; +} + + +/**@brief Function to get the category of the block of size 'size' or block number 'block_index'.*/ +static __INLINE uint32_t get_block_cat(uint32_t size, uint32_t block_index) +{ + for (uint32_t block_cat = 0; block_cat < BLOCK_CAT_COUNT; block_cat++) + { + if (((size != 0) && (size <= m_block_size[block_cat]) && + (m_block_end[block_cat] != m_block_start[block_cat])) || + (block_index < m_block_end[block_cat])) + { + return block_cat; + } + } + + return 0; +} + +/**@brief Initializes the block by setting it to be free. */ +static void block_init (uint32_t block_index) +{ + uint32_t x; + uint32_t y; + + // Determine position of the block in the bitmap. + // X determines relevant word for the block. Y determines the actual bit in the word. + get_block_coordinates(block_index, &x, &y); + +#if defined(MEM_MANAGER_ENABLE_DIAGNOSTICS) && (MEM_MANAGER_ENABLE_DIAGNOSTICS == 1) + // Update current use statistics: lower current count in block + if (!IS_SET(m_mem_pool[x], y)) + { + uint32_t block_cat = get_block_cat(0, block_index); + m_cur_count[block_cat]--; + } +#endif // MEM_MANAGER_ENABLE_DIAGNOSTICS + + // Set bit related to the block to indicate that the block is free. + SET_BIT(m_mem_pool[x], y); +} + + +/**@brief Function to get the size of the block number 'block_index'. */ +static __INLINE uint32_t get_block_size(uint32_t block_index) +{ + const uint32_t block_cat = get_block_cat(0, block_index); + +#if defined(MEM_MANAGER_ENABLE_DIAGNOSTICS) && (MEM_MANAGER_ENABLE_DIAGNOSTICS == 1) + p_min_size = &m_min_size[block_cat]; + p_max_size = &m_max_size[block_cat]; +#endif // MEM_MANAGER_ENABLE_DIAGNOSTICS + + return m_block_size[block_cat]; +} + + +/**@brief Function to free the block identified by block number 'block_index'. */ +static bool is_block_free(uint32_t block_index) +{ + uint32_t x; + uint32_t y; + + // Determine position of the block in the bitmap. + // X determines relevant word for the block. Y determines the actual bit in the word. + get_block_coordinates(block_index, &x, &y); + + return IS_SET(m_mem_pool[x], y); +} + + +/**@brief Function to allocate the block identified by block number 'block_index'. */ +static void block_allocate(uint32_t block_index) +{ + uint32_t x; + uint32_t y; + + // Determine position of the block in the bitmap. + // X determines relevant word for the block. Y determines the actual bit in the word. + get_block_coordinates(block_index, &x, &y); + + CLR_BIT(m_mem_pool[x], y); + +#if defined(MEM_MANAGER_ENABLE_DIAGNOSTICS) && (MEM_MANAGER_ENABLE_DIAGNOSTICS == 1) + // Update statistics: Add to current count in block. + uint32_t block_cat = get_block_cat(0, block_index); + m_cur_count[block_cat]++; + + // Report if the peak usage goes up in current block + if (m_cur_count[block_cat] > m_peak_count[block_cat]) + { + NRF_LOG_INFO("%d: %d -> %d", block_cat, m_peak_count[block_cat], m_cur_count[block_cat]); + m_peak_count[block_cat] = m_cur_count[block_cat]; + } +#endif // MEM_MANAGER_ENABLE_DIAGNOSTICS +} + + +uint32_t nrf_mem_init(void) +{ + NRF_LOG_DEBUG(">> %s.", (uint32_t)__func__); + + SDK_MUTEX_INIT(m_mm_mutex); + + MM_MUTEX_LOCK(); + + uint32_t block_index = 0; + + for (block_index = 0; block_index < TOTAL_BLOCK_COUNT; block_index++) + { + block_init(block_index); + } + + NRF_MEM_MANAGER_DIAGNOSE_RESET + +#if (MEM_MANAGER_DISABLE_API_PARAM_CHECK == 0) + m_module_initialized = true; +#endif // MEM_MANAGER_DISABLE_API_PARAM_CHECK + + NRF_MEM_MANAGER_DIAGNOSE + + MM_MUTEX_UNLOCK(); + + NRF_LOG_DEBUG("<< %s.", (uint32_t)__func__); + + return NRF_SUCCESS; +} + + +uint32_t nrf_mem_reserve(uint8_t ** pp_buffer, uint32_t * p_size) +{ + VERIFY_MODULE_INITIALIZED(); + NULL_PARAM_CHECK(pp_buffer); + NULL_PARAM_CHECK(p_size); + + const uint32_t requested_size = (*p_size); + + VERIFY_REQUESTED_SIZE(requested_size); + + NRF_LOG_DEBUG(">> %s, size 0x%04lX.", (uint32_t)__func__, requested_size); + + MM_MUTEX_LOCK(); + + const uint32_t block_cat = get_block_cat(requested_size, TOTAL_BLOCK_COUNT); + uint32_t block_index = m_block_start[block_cat]; + uint32_t memory_index = m_block_mem_start[block_cat]; + uint32_t err_code = (NRF_ERROR_NO_MEM | NRF_ERROR_MEMORY_MANAGER_ERR_BASE); + + NRF_LOG_DEBUG("Start index for the pool = 0x%08lX, total block count 0x%08X", + block_index, + TOTAL_BLOCK_COUNT); + + for (; block_index < TOTAL_BLOCK_COUNT; block_index++) + { + uint32_t block_size = get_block_size(block_index); + + if (is_block_free(block_index) == true) + { + NRF_LOG_DEBUG("Reserving block 0x%08lX", block_index); + + // Search succeeded, found free block. + err_code = NRF_SUCCESS; + + // Allocate block. + block_allocate(block_index); + + (*pp_buffer) = &m_memory[memory_index]; + (*p_size) = block_size; + + #if defined(MEM_MANAGER_ENABLE_DIAGNOSTICS) && (MEM_MANAGER_ENABLE_DIAGNOSTICS == 1) + (*p_min_size) = MIN((*p_min_size), requested_size); + (*p_max_size) = MAX((*p_max_size), requested_size); + #endif // MEM_MANAGER_ENABLE_DIAGNOSTICS + + break; + } + memory_index += block_size; + } + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Memory reservation failed: err_code %d, memory %p, size %d!", + err_code, + (uint32_t)(*pp_buffer), + (*p_size)); + + NRF_MEM_MANAGER_DIAGNOSE + } + + MM_MUTEX_UNLOCK(); + + NRF_LOG_DEBUG("<< %s %p, result 0x%08lX.", (uint32_t)__func__, + (uint32_t)(*pp_buffer), err_code); + + return err_code; +} + + +void * nrf_malloc(uint32_t size) +{ + uint8_t * buffer = NULL; + uint32_t allocated_size = size; + + uint32_t retval = nrf_mem_reserve(&buffer, &allocated_size); + + if (retval != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed to malloc side: %d", size); + buffer = NULL; + } + + return buffer; +} + + +void * nrf_calloc(uint32_t count, uint32_t size) +{ + uint8_t * buffer = NULL; + uint32_t allocated_size = (size * count); + + NRF_LOG_DEBUG("[%s]: Requested size %d, count %d", (uint32_t)__func__, allocated_size, count); + + uint32_t retval = nrf_mem_reserve(&buffer, &allocated_size); + if (retval == NRF_SUCCESS) + { + NRF_LOG_DEBUG("[%s]: buffer %p, total size %d", (uint32_t)__func__, (uint32_t)buffer, allocated_size); + memset(buffer,0, allocated_size); + } + else + { + NRF_LOG_ERROR("[%s]: Failed to allocate memory %d", (uint32_t)__func__, allocated_size); + buffer = NULL; + } + + return buffer; +} + + +void nrf_free(void * p_mem) +{ + VERIFY_MODULE_INITIALIZED_VOID(); + NULL_PARAM_CHECK_VOID(p_mem); + + NRF_LOG_DEBUG(">> %s %p.", (uint32_t)__func__, (uint32_t)p_mem); + + MM_MUTEX_LOCK(); + + uint32_t index; + uint32_t memory_index = 0; + + for (index = 0; index < TOTAL_BLOCK_COUNT; index++) + { + if (&m_memory[memory_index] == p_mem) + { + // Found a free block of memory, assign. + NRF_LOG_DEBUG("<< Freeing block %d.", index); + block_init(index); + break; + } + memory_index += get_block_size(index); + } + + MM_MUTEX_UNLOCK(); + + NRF_LOG_DEBUG("<< %s.", (uint32_t)__func__); + return; +} + + +void * nrf_realloc(void * p_mem, uint32_t size) +{ + return p_mem; +} + + +#if defined(MEM_MANAGER_ENABLE_DIAGNOSTICS) && (MEM_MANAGER_ENABLE_DIAGNOSTICS == 1) + +/**@brief Function to format and print information with respect to each block. + * + * @details Internal function that formats and prints information related to the block category + * identified by 'block_cat'. This function also appends the number of bytes in use to + * p_mem_in_use based on current count of block in the category. + * + * @param[in] block_cat Identifies the category of block. + * @param[out] p_mem_in_use Updates the memory in use based on count in use. + */ +void print_block_info(uint32_t block_cat, uint32_t * p_mem_in_use) +{ + #define PRINT_COLUMN_WIDTH 13 + #define PRINT_BUFFER_SIZE 100 + #define ASCII_VALUE_FOR_SPACE 32 + + char print_buffer[PRINT_BUFFER_SIZE]; + const uint32_t total_count = (m_block_start[block_cat] + m_block_count[block_cat]); + uint32_t in_use = 0; + uint32_t num_of_blocks = 0; + uint32_t index = m_block_start[block_cat]; + uint32_t column_number; + + // No statistic provided in case block category is not included. + if (m_block_count[block_cat] != 0) + { + memset(print_buffer, ASCII_VALUE_FOR_SPACE, PRINT_BUFFER_SIZE); + + for (; index < total_count; index++) + { + if (is_block_free(index) == false) + { + num_of_blocks++; + in_use += m_block_size[block_cat]; + } + } + + column_number = 0; + snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH], + PRINT_COLUMN_WIDTH, + "| %s", + m_block_desc_str[block_cat]); + + column_number++; + snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH], + PRINT_COLUMN_WIDTH, + "| %d", + (int)m_block_size[block_cat]); + + column_number++; + snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH], + PRINT_COLUMN_WIDTH, + "| %d", + (int)m_block_count[block_cat]); + + column_number++; + snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH], + PRINT_COLUMN_WIDTH, + "| %d", + (int)num_of_blocks); + + column_number++; + snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH], + PRINT_COLUMN_WIDTH, + "| %d", + (int)m_min_size[block_cat]); + + column_number++; + snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH], + PRINT_COLUMN_WIDTH, + "| %d", + (int)m_max_size[block_cat]); + + column_number++; + snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH], + PRINT_COLUMN_WIDTH, + "| %d", + (int)m_max_count[block_cat]); + + column_number++; + const uint32_t column_end = (column_number * PRINT_COLUMN_WIDTH); + + for (int j = 0; j < column_end; j ++) + { + if (print_buffer[j] == 0) + { + print_buffer[j] = 0x20; + } + } + snprintf(&print_buffer[column_end], 2, "|"); + + NRF_LOG_INFO("%s", print_buffer); + + (*p_mem_in_use) += in_use; + } +} + + +void nrf_mem_diagnose(void) +{ + uint32_t in_use = 0; + + NRF_LOG_INFO(""); + NRF_LOG_INFO("+------------+------------+------------+------------+------------+------------+"); + NRF_LOG_INFO("| Block | Size | Total | In Use | Min Alloc | Max Alloc |"); + NRF_LOG_INFO("+------------+------------+------------+------------+------------+------------+"); + + print_block_info(BLOCK_CAT_XXS, &in_use); + print_block_info(BLOCK_CAT_XS, &in_use); + print_block_info(BLOCK_CAT_SMALL, &in_use); + print_block_info(BLOCK_CAT_MEDIUM, &in_use); + print_block_info(BLOCK_CAT_LARGE, &in_use); + print_block_info(BLOCK_CAT_XL, &in_use); + print_block_info(BLOCK_CAT_XXL, &in_use); + + NRF_LOG_INFO("+------------+------------+------------+------------+------------+------------+"); + NRF_LOG_INFO("| Total | %d | %d | %d", + TOTAL_MEMORY_SIZE, TOTAL_BLOCK_COUNT,in_use); + NRF_LOG_INFO("+------------+------------+------------+------------+------------+------------+"); +} + + +void nrf_mem_diagnose_reset(void) +{ + memcpy(&m_min_size, &m_min_size_default, sizeof(m_min_size)); + memset(&m_max_size, 0, sizeof(m_max_size)); + memset(&m_peak_count, 0, sizeof(m_max_count)); + memset(&m_cur_count, 0, sizeof(m_cur_count)); +} + +#endif // MEM_MANAGER_ENABLE_DIAGNOSTICS +/** @} */ +#endif //NRF_MODULE_ENABLED(MEM_MANAGER) + diff --git a/components/libraries/mem_manager/mem_manager.h b/components/libraries/mem_manager/mem_manager.h new file mode 100644 index 0000000..3388e6c --- /dev/null +++ b/components/libraries/mem_manager/mem_manager.h @@ -0,0 +1,207 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup mem_manager Memory Manager + * @{ + * @ingroup app_common + * @brief Memory Manager for the @nRFXX SDK + * + * @details This module allows for dynamic use of memory. Currently, + * this module can be used only to allocate and free memory in the RAM. + * + * The Memory Manager manages static memory blocks of fixed sizes. These blocks can be requested for + * usage, and freed when the application no longer needs them. A maximum of seven block categories + * can be managed by the module. These block categories are identified by xxsmall, xmall, small, + * medium, large, xlarge, and xxlarge. They are ordered in increasing block sizes. + * The size and the count of each of the block categories can be configured based on the application + * requirements in the configuration file @c sdk_config.h. + * To use fewer than seven buffer pools, do not define the count for the unwanted block + * or explicitly set it to zero. At least one block category must be configured + * for this module to function as expected. + */ + +#ifndef MEM_MANAGER_H__ +#define MEM_MANAGER_H__ + +#include "sdk_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Initializes Memory Manager. + * + * @details API to initialize the Memory Manager. Always call this API before using any of the other + * APIs of the module. This API should be called only once. + * + * @retval NRF_SUCCESS If initialization was successful. + * Otherwise, an error code that indicates the reason for the failure is returned. + * + * @warning If this API fails, the application shall not proceed with using other APIs of this + * module. + */ +uint32_t nrf_mem_init(void); + + +/**@brief Reserves a block of memory for the application. + * + * @details API to request a contiguous memory block of the given length. If + * the memory allocation succeeds, pp_buffer points to the memory block. If + * the memory allocation fails, pp_buffer points to NULL and the return value of + * the API indicates the reason for the failure. The memory block reserved using this API can + * be freed using the @ref nrf_free function. + * + * @param[out] pp_buffer Pointer to the allocated memory block if memory allocation + * succeeds; otherwise points to NULL. + * @param[inout] p_size Requested memory size. This parameter returns the actual size + * allocated. If the procedure was successful, the actual size + * returned is always greater than or equal to requested size, + * never less. + * + * @retval NRF_SUCCESS If memory was successfully allocated. + * Otherwise, an error code indicating the reason for failure. + * @retval NRF_ERROR_INVALID_PARAM If the requested memory size is zero or greater than the + * largest memory block that the module is configured to + * support. + * @retval NRF_ERROR_NO_MEM If there is no memory available of the requested size. + */ +uint32_t nrf_mem_reserve(uint8_t ** pp_buffer, uint32_t * p_size); + + +/**@brief 'malloc' styled memory allocation function. + * + * @details API to allocate memory, same as nrf_mem_reserve but uses malloc signature. + * + * @param[in] size Requested memory size. + * + * @retval Valid memory location if the procedure was successful, else, NULL. + */ +void * nrf_malloc(uint32_t size); + + +/**@brief 'calloc' styled memory allocation function. + * + * @details API to allocate zero-initialized memory of size count*size. + * + * @param[in] nmemb Number of elements of 'size' bytes. + * @param[in] size Size of each element allocated. + * + * @retval Valid, zero-initialized memory location if the procedure was successful, else, NULL. + */ +void * nrf_calloc(uint32_t nmemb, uint32_t size); + + +/**@brief Free allocated memory - standard 'free' styles API. + * + * @details API to resubmit memory allocated, same in functionality nrf_free. + * + * @param[out] p_buffer Pointer to the memory block that is being freed. + */ +void nrf_free(void * p_buffer); + + +/**@brief Memory reallocation (trim) function. + * + * @details API to reallocate memory or to trim it. Trim is mentioned here to avoid use of API to + * request memory size larger than original memory allocated. + * + * @param[in] p_buffer Pointer to the memory block that needs to be trimmed. + * @param[in] size Size of memory at the beginning of the buffer to be left untrimmed. + * + * @retval Pointer to memory location with trimmed size, else, NULL. + */ +void * nrf_realloc(void *p_buffer, uint32_t size); + +#if defined(MEM_MANAGER_ENABLE_DIAGNOSTICS) && (MEM_MANAGER_ENABLE_DIAGNOSTICS == 1) + +/**@brief Function to print statistics related to memory blocks managed by memory manager. + * + * @details This API prints information with respects to each block function, including size, total + * block count, number of blocks in use at the time of printing, smallest memory size + * allocated in the block and the largest one. This API is intended to help developers + * tune the block sizes to make optimal use of memory for the application. + * This functionality is never needed in final application and therefore, is disabled by + * default. + */ +void nrf_mem_diagnose(void); + + +/**@brief Function to reset memory block statistics. + * + * @details This API resets the statistics of the memory manager. + * + */ +void nrf_mem_diagnose_reset(void); + + +/**@brief Macro that will log the mem_manager statistics if MEM_MANAGER_ENABLE_DIAGNOSTICS + * is enabled + */ +#define NRF_MEM_MANAGER_DIAGNOSE nrf_mem_diagnose() + + +/*@brief Macro that will reset the mem_manager statisitics if MEM_MANAGER_ENABLE_DIAGNOSTICS +* is enabled +*/ +#define NRF_MEM_MANAGER_DIAGNOSE_RESET nrf_mem_diagnose_reset() + +#else + +/**@brief Macro that will log the mem_manager statistics if MEM_MANAGER_ENABLE_DIAGNOSTICS + * is enabled + */ +#define NRF_MEM_MANAGER_DIAGNOSE + + +/*@brief Macro that will reset the mem_manager statisitics if MEM_MANAGER_ENABLE_DIAGNOSTICS +* is enabled +*/ +#define NRF_MEM_MANAGER_DIAGNOSE_RESET + +#endif // MEM_MANAGER_ENABLE_DIAGNOSTICS + +#ifdef __cplusplus +} +#endif + +#endif // MEM_MANAGER_H__ +/** @} */ diff --git a/components/libraries/memobj/nrf_memobj.c b/components/libraries/memobj/nrf_memobj.c new file mode 100644 index 0000000..230c00b --- /dev/null +++ b/components/libraries/memobj/nrf_memobj.c @@ -0,0 +1,258 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_memobj.h" +#include "nrf_atomic.h" +#include "nrf_assert.h" + +typedef struct memobj_elem_s memobj_elem_t; + +/** @brief Standard chunk header. */ +typedef struct +{ + memobj_elem_t * p_next; ///< Pointer to the next element. +} memobj_header_t; + +/** @brief Head header extension fields. */ +typedef struct +{ + uint8_t user_cnt; ///< User counter (see @ref nrf_memobj_get and @ref nrf_memobj_put). + uint8_t chunk_cnt; ///< Number of chunks in the object. + uint16_t chunk_size; ///< Single chunk size +} memobj_head_header_fields_t; + +/** @brief Head header extension. */ +typedef struct +{ + union + { + nrf_atomic_u32_t atomic_user_cnt; + memobj_head_header_fields_t fields; + } data; +} memobj_head_header_t; + +/** @brief Head chunk structure. */ +typedef struct +{ + memobj_header_t header; ///< Standard header. + memobj_head_header_t head_header; ///< Head-specific header part. + uint8_t data[1]; ///< Data. +} memobj_head_t; + +STATIC_ASSERT(sizeof(memobj_header_t) == NRF_MEMOBJ_STD_HEADER_SIZE); + +/** @brief Standard chunk structure. */ +struct memobj_elem_s +{ + memobj_header_t header; ///< Standard header. + uint8_t data[1]; ///< Data. +}; + +ret_code_t nrf_memobj_pool_init(nrf_memobj_pool_t const * p_pool) +{ + return nrf_balloc_init((nrf_balloc_t const *)p_pool); +} + +nrf_memobj_t * nrf_memobj_alloc(nrf_memobj_pool_t const * p_pool, + size_t size) +{ + uint32_t bsize = (uint32_t)NRF_BALLOC_ELEMENT_SIZE((nrf_balloc_t const *)p_pool) - sizeof(memobj_header_t); + uint8_t num_of_chunks = (uint8_t)CEIL_DIV(size + sizeof(memobj_head_header_t), bsize); + + memobj_head_t * p_head = nrf_balloc_alloc((nrf_balloc_t const *)p_pool); + if (p_head == NULL) + { + return NULL; + } + p_head->head_header.data.fields.user_cnt = 0; + p_head->head_header.data.fields.chunk_cnt = 1; + p_head->head_header.data.fields.chunk_size = bsize; + + memobj_header_t * p_prev = (memobj_header_t *)p_head; + memobj_header_t * p_curr; + uint32_t i; + uint32_t chunk_less1 = (uint32_t)num_of_chunks - 1; + + p_prev->p_next = (memobj_elem_t *)p_pool; + for (i = 0; i < chunk_less1; i++) + { + p_curr = (memobj_header_t *)nrf_balloc_alloc((nrf_balloc_t const *)p_pool); + if (p_curr) + { + (p_head->head_header.data.fields.chunk_cnt)++; + p_prev->p_next = (memobj_elem_t *)p_curr; + p_curr->p_next = (memobj_elem_t *)p_pool; + p_prev = p_curr; + } + else + { + //Could not allocate all requested buffers + nrf_memobj_free((nrf_memobj_t *)p_head); + return NULL; + } + } + return (nrf_memobj_t *)p_head; +} + +void nrf_memobj_free(nrf_memobj_t * p_obj) +{ + memobj_head_t * p_head = (memobj_head_t *)p_obj; + uint8_t chunk_cnt = p_head->head_header.data.fields.chunk_cnt; + uint32_t i; + memobj_header_t * p_curr = (memobj_header_t *)p_obj; + memobj_header_t * p_next; + uint32_t chunk_less1 = (uint32_t)chunk_cnt - 1; + + for (i = 0; i < chunk_less1; i++) + { + p_curr = (memobj_header_t *)p_curr->p_next; + } + nrf_balloc_t const * p_pool2 = (nrf_balloc_t const *)p_curr->p_next; + + p_curr = (memobj_header_t *)p_obj; + for (i = 0; i < chunk_cnt; i++) + { + p_next = (memobj_header_t *)p_curr->p_next; + nrf_balloc_free(p_pool2, p_curr); + p_curr = p_next; + } +} + +void nrf_memobj_get(nrf_memobj_t const * p_obj) +{ + memobj_head_t * p_head = (memobj_head_t *)p_obj; + (void)nrf_atomic_u32_add(&p_head->head_header.data.atomic_user_cnt, 1); +} + +void nrf_memobj_put(nrf_memobj_t * p_obj) +{ + memobj_head_t * p_head = (memobj_head_t *)p_obj; + uint32_t user_cnt = nrf_atomic_u32_sub(&p_head->head_header.data.atomic_user_cnt, 1); + memobj_head_header_fields_t * p_fields = (memobj_head_header_fields_t *)&user_cnt; + if (p_fields->user_cnt == 0) + { + nrf_memobj_free(p_obj); + } +} + +static void memobj_op(nrf_memobj_t * p_obj, + void * p_data, + size_t * p_len, + size_t offset, + bool read) +{ + + ASSERT(p_obj); + + memobj_head_t * p_head = (memobj_head_t *)p_obj; + memobj_elem_t * p_curr_chunk = (memobj_elem_t *)p_obj; + size_t obj_capacity; + size_t chunk_size; + size_t chunk_idx; + size_t chunk_offset; + size_t len; + + obj_capacity = (p_head->head_header.data.fields.chunk_size * + p_head->head_header.data.fields.chunk_cnt) - + sizeof(memobj_head_header_fields_t); + + ASSERT(offset < obj_capacity); + + chunk_size = p_head->head_header.data.fields.chunk_size; + chunk_idx = (offset + sizeof(memobj_head_header_fields_t)) / chunk_size; + chunk_offset = (offset + sizeof(memobj_head_header_fields_t)) % chunk_size; + len = ((*p_len + offset) > obj_capacity) ? obj_capacity - offset : *p_len; + + //Return number of available bytes + *p_len = len; + + //Move to the first chunk to be used + while (chunk_idx > 0) + { + p_curr_chunk = p_curr_chunk->header.p_next; + chunk_idx--; + } + + size_t user_mem_offset = 0; + size_t curr_cpy_size = chunk_size - chunk_offset; + curr_cpy_size = curr_cpy_size > len ? len : curr_cpy_size; + + while (len) + { + void * p_user_mem = &((uint8_t *)p_data)[user_mem_offset]; + void * p_obj_mem = &p_curr_chunk->data[chunk_offset]; + if (read) + { + memcpy(p_user_mem, p_obj_mem, curr_cpy_size); + } + else + { + memcpy(p_obj_mem, p_user_mem, curr_cpy_size); + } + + chunk_offset = 0; + p_curr_chunk = p_curr_chunk->header.p_next; + len -= curr_cpy_size; + user_mem_offset += curr_cpy_size; + curr_cpy_size = (chunk_size > len) ? len : chunk_size; + } +} + +void nrf_memobj_write(nrf_memobj_t * p_obj, + void * p_data, + size_t len, + size_t offset) +{ + + size_t op_len = len; + memobj_op(p_obj, p_data, &op_len, offset, false); + ASSERT(op_len == len); +} + +void nrf_memobj_read(nrf_memobj_t * p_obj, + void * p_data, + size_t len, + size_t offset) +{ + size_t op_len = len; + memobj_op(p_obj, p_data, &op_len, offset, true); + ASSERT(op_len == len); + +} diff --git a/components/libraries/memobj/nrf_memobj.h b/components/libraries/memobj/nrf_memobj.h new file mode 100644 index 0000000..1b5a579 --- /dev/null +++ b/components/libraries/memobj/nrf_memobj.h @@ -0,0 +1,203 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_MEMOBJ_H +#define NRF_MEMOBJ_H + +/** +* @defgroup nrf_memobj Memory Object module +* @{ +* @ingroup app_common +* @brief Functions for controlling a memory object. +*/ +#include +#include +#include "sdk_errors.h" +#include "nrf_balloc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * A memory object can consist of multiple chunks with the same size. Each object has a header part + * and a data part. The first element in a memory object is memory object head which has a special header. + * The remaining objects have a header of the same size. + * +@verbatim + _____________________ _____________________ _____________________ +| | | | | | +|4 B head header | --> |4 B p_next |------->|4 B p_memobj_pool | +|_____________________| | |_____________________| |_____________________| +| | | | | | | +|4 B p_next |--| | | | | +|_____________________| | | .... | | +| | | data | | data | +| | | | | | +| data | | | | | +| | | | | | +|_____________________| |_____________________| |_____________________| + head mid_element last_element +@endverbatim + * + */ +#define NRF_MEMOBJ_STD_HEADER_SIZE sizeof(uint32_t) + +/** + * @brief Macro for creating an nrf_memobj pool. + * + * This macro declares an nrf_balloc object. The element in the pool contains a user-defined data part and + * a memory object header. + * + * @param _name Name of the instance. + * @param _chunk_size Size of a single chunk. + * @param _pool_size Number of chunks in the pool. + */ +#define NRF_MEMOBJ_POOL_DEF(_name, _chunk_size, _pool_size) \ + STATIC_ASSERT((_chunk_size) > sizeof(uint32_t)); \ + NRF_BALLOC_DEF(_name, ((_chunk_size)+NRF_MEMOBJ_STD_HEADER_SIZE), (_pool_size)) + +/** + * @brief Pool of memory objects. + */ +typedef nrf_balloc_t nrf_memobj_pool_t; + +/** + * @brief Memory object handle. + */ +typedef void * nrf_memobj_t; + +/** + * @brief Function for initializing the memobj pool instance. + * + * This function initializes the pool. + * + * @param[in] p_pool Pointer to the memobj pool instance structure. + * + * @return NRF_SUCCESS on success, otherwise an error code. + */ +ret_code_t nrf_memobj_pool_init(nrf_memobj_pool_t const * p_pool); + +/** + * @brief Function for allocating a memobj with a requested size. + * + * Fixed length elements in the pool are linked together to provide the amount of memory requested by + * the user. If a memory object is successfully allocated, then the users can use the memory. + * However, it is fragmented into multiple objects so it must be accessed through the API: + * @ref nrf_memobj_write and @ref nrf_memobj_read. + * + * @param[in] p_pool Pointer to the memobj pool instance structure. + * @param[in] size Data size of requested object. + * + * @return Pointer to a memory object or NULL if the requested size cannot be allocated. + */ +nrf_memobj_t * nrf_memobj_alloc(nrf_memobj_pool_t const * p_pool, + size_t size); + +/** + * @brief Function for indicating that a memory object is used and cannot be freed. + * + * Memory object can be shared and reused between multiple modules and this mechanism ensures that + * object is freed when no longer used by any module. Memory object has a counter which is incremented + * whenever this function is called. @ref nrf_memobj_put function decrements the counter. + * + * @param[in] p_obj Pointer to memory object. + */ +void nrf_memobj_get(nrf_memobj_t const * p_obj); + + +/** + * @brief Function for indicated that memory object is no longer used by the module and can be freed + * if no other module is using it. + * + * Memory object is returned to the pool if internal counter reaches 0 after decrementing. It means + * that no other module is needing it anymore. + * + * @note Memory object holds pointer to the pool which was used to allocate it so it does not have + * to be provided explicitly to this function. + * + * @param[in] p_obj Pointer to memory object. + */ +void nrf_memobj_put(nrf_memobj_t * p_obj); + + +/** + * @brief Function for forcing freeing of the memory object. + * + * @note This function should be use with caution because it can lead to undefined behavior of the + * modules since modules using the memory object are not aware that it has been freed. + * + * @param[in] p_obj Pointer to memory object. + */ +void nrf_memobj_free(nrf_memobj_t * p_obj); + +/** + * @brief Function for writing data to the memory object. + * + * @param[in] p_obj Pointer to memory object. + * @param[in] p_data Pointer to data to be written to the memory object. + * @param[in] len Amount of data to be written to the memory object. + * @param[in] offset Offset. + */ +void nrf_memobj_write(nrf_memobj_t * p_obj, + void * p_data, + size_t len, + size_t offset); + +/** + * @brief Function for reading data from the memory object. + * + * @param[in] p_obj Pointer to memory object. + * @param[in] p_data Pointer to the destination buffer. + * @param[in] len Amount of data to be read from the memory object. + * @param[in] offset Offset. + */ +void nrf_memobj_read(nrf_memobj_t * p_obj, + void * p_data, + size_t len, + size_t offset); + +#ifdef __cplusplus +} +#endif + +#endif //NRF_MEMOBJ_H + +/** @} */ diff --git a/components/libraries/mutex/nrf_mtx.h b/components/libraries/mutex/nrf_mtx.h new file mode 100644 index 0000000..48a939a --- /dev/null +++ b/components/libraries/mutex/nrf_mtx.h @@ -0,0 +1,159 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * @defgroup nrf_mtx nRF Mutex + * @{ + * @ingroup app_common + * @brief Mutex used for protecting resources. + * + * This module provides a mutex that can be used to ensure only one context may enter a critical + * section holding the lock. + */ +#ifndef NRF_MTX_H__ +#define NRF_MTX_H__ + +#include +#include +#include "nrf.h" +#include "nrf_atomic.h" +#include "nrf_assert.h" + +#define NRF_MTX_LOCKED 1 +#define NRF_MTX_UNLOCKED 0 + +/** + * @brief Mutex data type. + * + * All fields in this struct are internal, and should never be modified outside of the nrf_mtx_* + * functions. + */ +typedef nrf_atomic_u32_t nrf_mtx_t; + +/** + * @brief Initialize mutex. + * + * This function _must_ be called before nrf_mtx_trylock() and nrf_mtx_unlock() functions. + * + * @param[in, out] p_mtx The mutex to be initialized. + */ +__STATIC_INLINE void nrf_mtx_init(nrf_mtx_t * p_mtx); + + +/** + * @brief Destroy mutex. + * + * This function can be used in abort scenarios or when the mutex is no longer to be used. + * + * @param[in] p_mtx The mutex to be destroy. + */ +__STATIC_INLINE void nrf_mtx_destroy(nrf_mtx_t * p_mtx); + +/** + * @brief Try to lock a mutex. + * + * If the mutex is already held by another context, this function will return immediately. + * + * @param[in, out] p_mtx The mutex to be locked. + * @return true if lock was acquired, false if not + */ +__STATIC_INLINE bool nrf_mtx_trylock(nrf_mtx_t * p_mtx); + +/** + * @brief Unlock a mutex. + * + * This function _must_ only be called when holding the lock. Unlocking a mutex which you do not + * hold will give undefined behavior. + * + * @note Unlock must happen from the same context as the one used to lock the mutex. + * + * @param[in, out] p_mtx The mutex to be unlocked. + */ +__STATIC_INLINE void nrf_mtx_unlock(nrf_mtx_t * p_mtx); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_mtx_init(nrf_mtx_t * p_mtx) +{ + ASSERT(p_mtx != NULL); + + *p_mtx = NRF_MTX_UNLOCKED; + __DMB(); +} + +__STATIC_INLINE void nrf_mtx_destroy(nrf_mtx_t * p_mtx) +{ + ASSERT(p_mtx != NULL); + + // Add memory barrier to ensure that any memory operations protected by the mutex complete + // before the mutex is destroyed. + __DMB(); + + *p_mtx = NRF_MTX_UNLOCKED; +} + +__STATIC_INLINE bool nrf_mtx_trylock(nrf_mtx_t * p_mtx) +{ + ASSERT(p_mtx != NULL); + + uint32_t old_val = nrf_atomic_u32_fetch_store(p_mtx, NRF_MTX_LOCKED); + + // Add memory barrier to ensure that the mutex is locked before any memory operations protected + // by the mutex are started. + __DMB(); + + return (old_val == NRF_MTX_UNLOCKED); +} + +__STATIC_INLINE void nrf_mtx_unlock(nrf_mtx_t * p_mtx) +{ + ASSERT(p_mtx != NULL); + ASSERT(*p_mtx == NRF_MTX_LOCKED); + + // Add memory barrier to ensure that any memory operations protected by the mutex complete + // before the mutex is unlocked. + __DMB(); + + *p_mtx = NRF_MTX_UNLOCKED; +} + +#endif //SUPPRESS_INLINE_IMPLEMENTATION + +#endif // NRF_MTX_H__ +/** @} */ diff --git a/components/libraries/pwr_mgmt/nrf_pwr_mgmt.c b/components/libraries/pwr_mgmt/nrf_pwr_mgmt.c new file mode 100644 index 0000000..3e83c17 --- /dev/null +++ b/components/libraries/pwr_mgmt/nrf_pwr_mgmt.c @@ -0,0 +1,482 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_PWR_MGMT) + +#include "nrf_pwr_mgmt.h" +#include "nrf.h" +#include "nrf_mtx.h" +#include "nrf_power.h" +#include "app_error.h" +#include "nrf_assert.h" +#include "nrf_log_ctrl.h" +#include "app_util_platform.h" + +#define NRF_LOG_MODULE_NAME pwr_mgmt +#if NRF_PWR_MGMT_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_PWR_MGMT_CONFIG_LOG_LEVEL + #define NRF_LOG_INFO_COLOR NRF_PWR_MGMT_CONFIG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_PWR_MGMT_CONFIG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_PWR_MGMT_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#ifdef SOFTDEVICE_PRESENT + #include "nrf_soc.h" + #include "nrf_sdh.h" +#endif // SOFTDEVICE_PRESENT + + +#if NRF_PWR_MGMT_CONFIG_USE_SCHEDULER + #if (APP_SCHEDULER_ENABLED != 1) + #error "APP_SCHEDULER is required." + #endif + #include "app_scheduler.h" +#endif // NRF_PWR_MGMT_CONFIG_USE_SCHEDULER + + +// Create section "pwr_mgmt_data". +NRF_SECTION_SET_DEF(pwr_mgmt_data, + nrf_pwr_mgmt_shutdown_handler_t, + NRF_PWR_MGMT_CONFIG_HANDLER_PRIORITY_COUNT); + +static nrf_pwr_mgmt_evt_t m_pwr_mgmt_evt; /**< Event type which will be passed to the shutdown + handlers.*/ +static nrf_mtx_t m_sysoff_mtx; /**< Module API lock.*/ +static bool m_shutdown_started; /**< True if application started the shutdown preparation. */ +static nrf_section_iter_t m_handlers_iter; /**< Shutdown handlers iterator. */ + +#if (NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED && __FPU_PRESENT) + #define PWR_MGMT_FPU_SLEEP_PREPARE() pwr_mgmt_fpu_sleep_prepare() + + __STATIC_INLINE void pwr_mgmt_fpu_sleep_prepare(void) + { + uint32_t original_fpscr; + + CRITICAL_REGION_ENTER(); + original_fpscr = __get_FPSCR(); + /* + * Clear FPU exceptions. + * Without this step, the FPU interrupt is marked as pending, + * preventing system from sleeping. Exceptions cleared: + * - IOC - Invalid Operation cumulative exception bit. + * - DZC - Division by Zero cumulative exception bit. + * - OFC - Overflow cumulative exception bit. + * - UFC - Underflow cumulative exception bit. + * - IXC - Inexact cumulative exception bit. + * - IDC - Input Denormal cumulative exception bit. + */ + __set_FPSCR(original_fpscr & ~0x9Fu); + __DMB(); + NVIC_ClearPendingIRQ(FPU_IRQn); + CRITICAL_REGION_EXIT(); + + /* + * The last chance to indicate an error in FPU to the user + * as the FPSCR is now cleared + * + * This assert is related to previous FPU operations + * and not power management. + * + * Critical FPU exceptions signaled: + * - IOC - Invalid Operation cumulative exception bit. + * - DZC - Division by Zero cumulative exception bit. + * - OFC - Overflow cumulative exception bit. + */ + ASSERT((original_fpscr & 0x7) == 0); + } +#else + #define PWR_MGMT_FPU_SLEEP_PREPARE() +#endif // NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED + + +#if NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED + #undef PWR_MGMT_SLEEP_IN_CRITICAL_SECTION_REQUIRED + #define PWR_MGMT_SLEEP_IN_CRITICAL_SECTION_REQUIRED + + #include "nrf_gpio.h" + #define PWR_MGMT_DEBUG_PINS_INIT() pwr_mgmt_debug_pins_init() + #define PWR_MGMT_DEBUG_PIN_CLEAR() nrf_gpio_pin_clear(NRF_PWR_MGMT_SLEEP_DEBUG_PIN) + #define PWR_MGMT_DEBUG_PIN_SET() nrf_gpio_pin_set(NRF_PWR_MGMT_SLEEP_DEBUG_PIN) + + __STATIC_INLINE void pwr_mgmt_debug_pins_init(void) + { + nrf_gpio_pin_clear(NRF_PWR_MGMT_SLEEP_DEBUG_PIN); + nrf_gpio_cfg_output(NRF_PWR_MGMT_SLEEP_DEBUG_PIN); + } + +#else + #define PWR_MGMT_DEBUG_PIN_CLEAR() + #define PWR_MGMT_DEBUG_PIN_SET() + #define PWR_MGMT_DEBUG_PINS_INIT() +#endif + + +#if NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED + #undef PWR_MGMT_SLEEP_IN_CRITICAL_SECTION_REQUIRED + #define PWR_MGMT_SLEEP_IN_CRITICAL_SECTION_REQUIRED + + #undef PWR_MGMT_TIMER_REQUIRED + #define PWR_MGMT_TIMER_REQUIRED + #include "app_timer.h" + + #define PWR_MGMT_CPU_USAGE_MONITOR_INIT() pwr_mgmt_cpu_usage_monitor_init() + #define PWR_MGMT_CPU_USAGE_MONITOR_UPDATE() pwr_mgmt_cpu_usage_monitor_update() + #define PWR_MGMT_CPU_USAGE_MONITOR_SUMMARY() NRF_LOG_INFO("Maximum CPU usage: %u%%", \ + m_max_cpu_usage) + #define PWR_MGMT_CPU_USAGE_MONITOR_SECTION_ENTER() \ + { \ + uint32_t sleep_start = app_timer_cnt_get() + + #define PWR_MGMT_CPU_USAGE_MONITOR_SECTION_EXIT() \ + uint32_t sleep_end = app_timer_cnt_get(); \ + uint32_t sleep_duration; \ + sleep_duration = app_timer_cnt_diff_compute(sleep_end, \ + sleep_start); \ + m_ticks_sleeping += sleep_duration; \ + } + + static uint32_t m_ticks_sleeping; /**< Number of ticks spent in sleep mode (__WFE()). */ + static uint32_t m_ticks_last; /**< Number of ticks from the last CPU usage computation. */ + static uint8_t m_max_cpu_usage; /**< Maximum observed CPU usage (0 - 100%). */ + + __STATIC_INLINE void pwr_mgmt_cpu_usage_monitor_init(void) + { + m_ticks_sleeping = 0; + m_ticks_last = 0; + m_max_cpu_usage = 0; + } + + __STATIC_INLINE void pwr_mgmt_cpu_usage_monitor_update(void) + { + uint32_t delta; + uint32_t ticks; + uint8_t cpu_usage; + + ticks = app_timer_cnt_get(); + delta = app_timer_cnt_diff_compute(ticks, m_ticks_last); + cpu_usage = 100 * (delta - m_ticks_sleeping) / delta; + + NRF_LOG_INFO("CPU Usage: %u%%", cpu_usage); + if (m_max_cpu_usage < cpu_usage) + { + m_max_cpu_usage = cpu_usage; + } + + m_ticks_last = ticks; + m_ticks_sleeping = 0; + } + +#else + #define PWR_MGMT_CPU_USAGE_MONITOR_INIT() + #define PWR_MGMT_CPU_USAGE_MONITOR_UPDATE() + #define PWR_MGMT_CPU_USAGE_MONITOR_SUMMARY() + #define PWR_MGMT_CPU_USAGE_MONITOR_SECTION_ENTER() + #define PWR_MGMT_CPU_USAGE_MONITOR_SECTION_EXIT() +#endif // NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED + + +#if NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED + #undef PWR_MGMT_TIMER_REQUIRED + #define PWR_MGMT_TIMER_REQUIRED + + #define PWR_MGMT_STANDBY_TIMEOUT_INIT() pwr_mgmt_standby_timeout_clear() + #define PWR_MGMT_STANDBY_TIMEOUT_CLEAR() pwr_mgmt_standby_timeout_clear() + #define PWR_MGMT_STANDBY_TIMEOUT_CHECK() pwr_mgmt_standby_timeout_check() + + static uint16_t m_standby_counter; /**< Number of seconds from the last activity + (@ref pwr_mgmt_feed). */ + + __STATIC_INLINE void pwr_mgmt_standby_timeout_clear(void) + { + m_standby_counter = 0; + } + + __STATIC_INLINE void pwr_mgmt_standby_timeout_check(void) + { + if (m_standby_counter < NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S) + { + m_standby_counter++; + } + else if (m_shutdown_started == false) + { + nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF); + } + } + +#else + #define PWR_MGMT_STANDBY_TIMEOUT_INIT() + #define PWR_MGMT_STANDBY_TIMEOUT_CLEAR() + #define PWR_MGMT_STANDBY_TIMEOUT_CHECK() +#endif // NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED + + +#if NRF_PWR_MGMT_CONFIG_AUTO_SHUTDOWN_RETRY + #undef PWR_MGMT_TIMER_REQUIRED + #define PWR_MGMT_TIMER_REQUIRED + + #define PWR_MGMT_AUTO_SHUTDOWN_RETRY() pwr_mgmt_auto_shutdown_retry() + + __STATIC_INLINE void pwr_mgmt_auto_shutdown_retry(void) + { + if (m_shutdown_started) + { + // Try to continue the shutdown procedure. + nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_CONTINUE); + } + } + +#else + #define PWR_MGMT_AUTO_SHUTDOWN_RETRY() +#endif // NRF_PWR_MGMT_CONFIG_AUTO_SHUTDOWN_RETRY + + +#ifdef PWR_MGMT_SLEEP_IN_CRITICAL_SECTION_REQUIRED + #define PWR_MGMT_SLEEP_INIT() pwr_mgmt_sleep_init() + #define PWR_MGMT_SLEEP_LOCK_ACQUIRE() CRITICAL_REGION_ENTER() + #define PWR_MGMT_SLEEP_LOCK_RELEASE() CRITICAL_REGION_EXIT() + + __STATIC_INLINE void pwr_mgmt_sleep_init(void) + { + #ifdef SOFTDEVICE_PRESENT + ASSERT(current_int_priority_get() >= APP_IRQ_PRIORITY_LOW); + #endif + SCB->SCR |= SCB_SCR_SEVONPEND_Msk; + } + +#else + #define PWR_MGMT_SLEEP_INIT() + #define PWR_MGMT_SLEEP_LOCK_ACQUIRE() + #define PWR_MGMT_SLEEP_LOCK_RELEASE() +#endif // PWR_MGMT_SLEEP_IN_CRITICAL_SECTION_REQUIRED + + +#ifdef PWR_MGMT_TIMER_REQUIRED + #include "app_timer.h" + #define PWR_MGMT_TIMER_CREATE() pwr_mgmt_timer_create() + + APP_TIMER_DEF(m_pwr_mgmt_timer); /**< Timer used by this module. */ + + /**@brief Handle events from m_pwr_mgmt_timer. + */ + static void nrf_pwr_mgmt_timeout_handler(void * p_context) + { + PWR_MGMT_CPU_USAGE_MONITOR_UPDATE(); + PWR_MGMT_AUTO_SHUTDOWN_RETRY(); + PWR_MGMT_STANDBY_TIMEOUT_CHECK(); + } + + __STATIC_INLINE ret_code_t pwr_mgmt_timer_create(void) + { + ret_code_t ret_code = app_timer_create(&m_pwr_mgmt_timer, + APP_TIMER_MODE_REPEATED, + nrf_pwr_mgmt_timeout_handler); + if (ret_code != NRF_SUCCESS) + { + return ret_code; + } + + return app_timer_start(m_pwr_mgmt_timer, APP_TIMER_TICKS(1000), NULL); + } +#else + #define PWR_MGMT_TIMER_CREATE() NRF_SUCCESS +#endif // PWR_MGMT_TIMER_REQUIRED + +ret_code_t nrf_pwr_mgmt_init(void) +{ + NRF_LOG_INFO("Init"); + + m_shutdown_started = false; + nrf_mtx_init(&m_sysoff_mtx); + nrf_section_iter_init(&m_handlers_iter, &pwr_mgmt_data); + + PWR_MGMT_SLEEP_INIT(); + PWR_MGMT_DEBUG_PINS_INIT(); + PWR_MGMT_STANDBY_TIMEOUT_INIT(); + PWR_MGMT_CPU_USAGE_MONITOR_INIT(); + + return PWR_MGMT_TIMER_CREATE(); +} + +void nrf_pwr_mgmt_run(void) +{ + PWR_MGMT_FPU_SLEEP_PREPARE(); + PWR_MGMT_SLEEP_LOCK_ACQUIRE(); + PWR_MGMT_CPU_USAGE_MONITOR_SECTION_ENTER(); + PWR_MGMT_DEBUG_PIN_SET(); + + // Wait for an event. +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + ret_code_t ret_code = sd_app_evt_wait(); + ASSERT((ret_code == NRF_SUCCESS) || (ret_code == NRF_ERROR_SOFTDEVICE_NOT_ENABLED)); + UNUSED_VARIABLE(ret_code); + } + else +#endif // SOFTDEVICE_PRESENT + { + // Wait for an event. + __WFE(); + // Clear the internal event register. + __SEV(); + __WFE(); + } + + PWR_MGMT_DEBUG_PIN_CLEAR(); + PWR_MGMT_CPU_USAGE_MONITOR_SECTION_EXIT(); + PWR_MGMT_SLEEP_LOCK_RELEASE(); +} + +void nrf_pwr_mgmt_feed(void) +{ + NRF_LOG_DEBUG("Feed"); + // It does not stop started shutdown process. + PWR_MGMT_STANDBY_TIMEOUT_CLEAR(); +} + +/**@brief Function runs the shutdown procedure. + */ +static void shutdown_process(void) +{ + NRF_LOG_INFO("Shutdown started. Type %d", m_pwr_mgmt_evt); + // Executing all callbacks. + for (/* m_handlers_iter is initialized in nrf_pwr_mgmt_init(). Thanks to that each handler is + called only once.*/; + nrf_section_iter_get(&m_handlers_iter) != NULL; + nrf_section_iter_next(&m_handlers_iter)) + { + nrf_pwr_mgmt_shutdown_handler_t * p_handler = + (nrf_pwr_mgmt_shutdown_handler_t *) nrf_section_iter_get(&m_handlers_iter); + if ((*p_handler)(m_pwr_mgmt_evt)) + { + NRF_LOG_INFO("SysOff handler 0x%08X => ready", (unsigned int)*p_handler); + } + else + { + // One of the modules is not ready. + NRF_LOG_INFO("SysOff handler 0x%08X => blocking", (unsigned int)*p_handler); + return; + } + } + + PWR_MGMT_CPU_USAGE_MONITOR_SUMMARY(); + NRF_LOG_INFO("Shutdown complete."); + NRF_LOG_FINAL_FLUSH(); + + if ((m_pwr_mgmt_evt == NRF_PWR_MGMT_EVT_PREPARE_RESET) + || (m_pwr_mgmt_evt == NRF_PWR_MGMT_EVT_PREPARE_DFU)) + { + NVIC_SystemReset(); + } + else + { + // Enter System OFF. +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + ret_code_t ret_code = sd_power_system_off(); + ASSERT((ret_code == NRF_SUCCESS) || (ret_code == NRF_ERROR_SOFTDEVICE_NOT_ENABLED)); + UNUSED_VARIABLE(ret_code); +#ifdef DEBUG + while (true) + { + /* Since the CPU is kept on in an emulated System OFF mode, it is recommended + * to add an infinite loop directly after entering System OFF, to prevent + * the CPU from executing code that normally should not be executed. */ + __WFE(); + + } +#endif + } +#endif // SOFTDEVICE_PRESENT + nrf_power_system_off(); + } +} + +#if NRF_PWR_MGMT_CONFIG_USE_SCHEDULER +/**@brief Handle events from app_scheduler. + */ +static void scheduler_shutdown_handler(void * p_event_data, uint16_t event_size) +{ + UNUSED_PARAMETER(p_event_data); + UNUSED_PARAMETER(event_size); + shutdown_process(); +} +#endif // NRF_PWR_MGMT_CONFIG_USE_SCHEDULER + +void nrf_pwr_mgmt_shutdown(nrf_pwr_mgmt_shutdown_t shutdown_type) +{ + // Check if shutdown procedure is not started. + if (!nrf_mtx_trylock(&m_sysoff_mtx)) + { + return; + } + + if (shutdown_type != NRF_PWR_MGMT_SHUTDOWN_CONTINUE) + { + if (m_shutdown_started) + { + nrf_mtx_unlock(&m_sysoff_mtx); + return; + } + else + { + m_pwr_mgmt_evt = (nrf_pwr_mgmt_evt_t)shutdown_type; + m_shutdown_started = true; + } + } + + ASSERT(m_shutdown_started); + NRF_LOG_INFO("Shutdown request %d", shutdown_type); + +#if NRF_PWR_MGMT_CONFIG_USE_SCHEDULER + ret_code_t ret_code = app_sched_event_put(NULL, 0, scheduler_shutdown_handler); + APP_ERROR_CHECK(ret_code); +#else + shutdown_process(); +#endif // NRF_PWR_MGMT_CONFIG_USE_SCHEDULER + + nrf_mtx_unlock(&m_sysoff_mtx); +} + +#endif // NRF_MODULE_ENABLED(NRF_PWR_MGMT) diff --git a/components/libraries/pwr_mgmt/nrf_pwr_mgmt.h b/components/libraries/pwr_mgmt/nrf_pwr_mgmt.h new file mode 100644 index 0000000..89f2703 --- /dev/null +++ b/components/libraries/pwr_mgmt/nrf_pwr_mgmt.h @@ -0,0 +1,158 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * @defgroup nrf_pwr_mgmt Power management + * @ingroup app_common + * @{ + * @brief This module handles power management features. + * + */ +#ifndef NRF_PWR_MGMT_H__ +#define NRF_PWR_MGMT_H__ + +#include +#include +#include +#include "nrf_section_iter.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Power management shutdown types. */ +typedef enum +{ + NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF, + //!< Go to System OFF. + + NRF_PWR_MGMT_SHUTDOWN_STAY_IN_SYSOFF, + //!< Go to System OFF and stay there. + /**< + * Useful when battery level is dangerously low, for example. + */ + + NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU, + //!< Go to DFU mode. + + NRF_PWR_MGMT_SHUTDOWN_RESET, + //!< Reset chip. + + NRF_PWR_MGMT_SHUTDOWN_CONTINUE + //!< Continue shutdown. + /**< + * This should be used by modules that block the shutdown process, when they become ready for + * shutdown. + */ +} nrf_pwr_mgmt_shutdown_t; + +/**@brief Shutdown event types. */ +typedef enum +{ + NRF_PWR_MGMT_EVT_PREPARE_WAKEUP = NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF, + //!< Application will prepare the wakeup mechanism. + + NRF_PWR_MGMT_EVT_PREPARE_SYSOFF = NRF_PWR_MGMT_SHUTDOWN_STAY_IN_SYSOFF, + //!< Application will prepare to stay in System OFF state. + + NRF_PWR_MGMT_EVT_PREPARE_DFU = NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU, + //!< Application will prepare to enter DFU mode. + + NRF_PWR_MGMT_EVT_PREPARE_RESET = NRF_PWR_MGMT_SHUTDOWN_RESET, + //!< Application will prepare to chip reset. +} nrf_pwr_mgmt_evt_t; + +/**@brief Shutdown callback. + * @param[in] event Type of shutdown process. + * + * @retval true System OFF / Enter DFU preparation successful. Process will be continued. + * @retval false System OFF / Enter DFU preparation failed. @ref NRF_PWR_MGMT_SHUTDOWN_CONTINUE + * should be used to continue the shutdown process. + */ +typedef bool (*nrf_pwr_mgmt_shutdown_handler_t)(nrf_pwr_mgmt_evt_t event); + +/**@brief Macro for registering a shutdown handler. Modules that want to get events + * from this module must register the handler using this macro. + * + * @details This macro places the handler in a section named "pwr_mgmt_data". + * + * @param[in] _handler Event handler (@ref nrf_pwr_mgmt_shutdown_handler_t). + * @param[in] _priority Priority of the given handler. + */ +#define NRF_PWR_MGMT_HANDLER_REGISTER(_handler, _priority) \ + STATIC_ASSERT(_priority < NRF_PWR_MGMT_CONFIG_HANDLER_PRIORITY_COUNT); \ + /*lint -esym(528,*_handler_function) -esym(529,*_handler_function) : Symbol not referenced. */ \ + NRF_SECTION_SET_ITEM_REGISTER(pwr_mgmt_data, _priority, \ + static nrf_pwr_mgmt_shutdown_handler_t const CONCAT_2(_handler, _handler_function)) = (_handler) + +/**@brief Function for initializing power management. + * + * @warning Depending on configuration, this function sets SEVONPEND in System Control Block (SCB). + * This operation is unsafe with the SoftDevice from interrupt priority higher than SVC. + * + * @retval NRF_SUCCESS + */ +ret_code_t nrf_pwr_mgmt_init(void); + +/**@brief Function for running power management. Should run in the main loop. + */ +void nrf_pwr_mgmt_run(void); + +/**@brief Function for indicating activity. + * + * @details Call this function whenever doing something that constitutes "activity". + * For example, whenever sending data, call this function to indicate that the application + * is active and should not disconnect any ongoing communication links. + */ +void nrf_pwr_mgmt_feed(void); + +/**@brief Function for shutting down the system. + * + * @param[in] shutdown_type Type of operation. + * + * @details All callbacks will be executed prior to shutdown. + */ +void nrf_pwr_mgmt_shutdown(nrf_pwr_mgmt_shutdown_t shutdown_type); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_PWR_MGMT_H__ +/** @} */ diff --git a/components/libraries/queue/nrf_queue.c b/components/libraries/queue/nrf_queue.c new file mode 100644 index 0000000..4031dc1 --- /dev/null +++ b/components/libraries/queue/nrf_queue.c @@ -0,0 +1,580 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_QUEUE) +#include "nrf_queue.h" +#include "app_util_platform.h" + +#if NRF_QUEUE_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_QUEUE_CONFIG_LOG_LEVEL + #define NRF_LOG_INIT_FILTER_LEVEL NRF_QUEUE_CONFIG_LOG_INIT_FILTER_LEVEL + #define NRF_LOG_INFO_COLOR NRF_QUEUE_CONFIG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_QUEUE_CONFIG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_QUEUE_CONFIG_LOG_ENABLED +#include "nrf_log.h" + +NRF_SECTION_DEF(nrf_queue, nrf_queue_t); + +#if NRF_QUEUE_CLI_CMDS && NRF_CLI_ENABLED +#include "nrf_cli.h" + +static void nrf_queue_status(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + UNUSED_PARAMETER(argv); + + if (nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + + if (argc > 1) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Bad argument count"); + return; + } + + uint32_t num_of_instances = NRF_SECTION_ITEM_COUNT(nrf_queue, nrf_queue_t); + uint32_t i; + + for (i = 0; i < num_of_instances; i++) + { + const nrf_queue_t * p_instance = NRF_SECTION_ITEM_GET(nrf_queue, nrf_queue_t, i); + + uint32_t element_size = p_instance->element_size; + uint32_t size = p_instance->size; + uint32_t max_util = nrf_queue_max_utilization_get(p_instance); + uint32_t util = nrf_queue_utilization_get(p_instance); + const char * p_name = p_instance->p_name; + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, + "%s\r\n\t- Element size:\t%d\r\n" + "\t- Usage:\t%u%% (%u out of %u elements)\r\n" + "\t- Maximum:\t%u%% (%u out of %u elements)\r\n" + "\t- Mode:\t\t%s\r\n\r\n", + p_name, element_size, + 100ul * util/size, util,size, + 100ul * max_util/size, max_util,size, + (p_instance->mode == NRF_QUEUE_MODE_OVERFLOW) ? "Overflow" : "No overflow"); + + } +} +// Register "queue" command and its subcommands in CLI. +NRF_CLI_CREATE_STATIC_SUBCMD_SET(nrf_queue_commands) +{ + NRF_CLI_CMD(status, NULL, "Print status of queue instances.", nrf_queue_status), + NRF_CLI_SUBCMD_SET_END +}; + +NRF_CLI_CMD_REGISTER(queue, &nrf_queue_commands, "Commands for BALLOC management", nrf_queue_status); +#endif //NRF_QUEUE_CLI_CMDS + +__STATIC_INLINE size_t circullar_buffer_size_get(nrf_queue_t const * p_queue) +{ + static const uint8_t full_queue_indicator = 1; + + /* When a queue is implemented as a cyclic buffer, it is not possible to + * distinguish a full queue from an empty queue. In order to solve this + * problem, the cyclic buffer has been implemented one element larger than + * the queue size. + */ + return p_queue->size + full_queue_indicator; +} + +/**@brief Get next element index. + * + * @param[in] p_queue Pointer to the queue instance. + * @param[in] idx Current index. + * + * @return Next element index. + */ +__STATIC_INLINE size_t nrf_queue_next_idx(nrf_queue_t const * p_queue, size_t idx) +{ + ASSERT(p_queue != NULL); + return (idx < p_queue->size) ? (idx + 1) : 0; +} + +/**@brief Get current queue utilization. This function assumes that this process will not be interrupted. + * + * @param[in] p_queue Pointer to the queue instance. + * + * @return Current queue utilization. + */ +__STATIC_INLINE size_t queue_utilization_get(nrf_queue_t const * p_queue) +{ + size_t front = p_queue->p_cb->front; + size_t back = p_queue->p_cb->back; + + return (back >= front) ? (back - front) : + (circullar_buffer_size_get(p_queue) - front + back); +} + +bool nrf_queue_is_full(nrf_queue_t const * p_queue) +{ + ASSERT(p_queue != NULL); + size_t front = p_queue->p_cb->front; + size_t back = p_queue->p_cb->back; + + return (nrf_queue_next_idx(p_queue, back) == front); +} + +ret_code_t nrf_queue_push(nrf_queue_t const * p_queue, void const * p_element) +{ + ret_code_t status = NRF_SUCCESS; + + ASSERT(p_queue != NULL); + ASSERT(p_element != NULL); + + CRITICAL_REGION_ENTER(); + bool is_full = nrf_queue_is_full(p_queue); + + if (!is_full || (p_queue->mode == NRF_QUEUE_MODE_OVERFLOW)) + { + // Get write position. + size_t write_pos = p_queue->p_cb->back; + p_queue->p_cb->back = nrf_queue_next_idx(p_queue, p_queue->p_cb->back); + if (is_full) + { + // Overwrite the oldest element. + NRF_LOG_INST_WARNING(p_queue->p_log, "Queue full. Overwriting oldest element."); + p_queue->p_cb->front = nrf_queue_next_idx(p_queue, p_queue->p_cb->front); + } + + // Write a new element. + switch (p_queue->element_size) + { + case sizeof(uint8_t): + ((uint8_t *)p_queue->p_buffer)[write_pos] = *((uint8_t *)p_element); + break; + + case sizeof(uint16_t): + ((uint16_t *)p_queue->p_buffer)[write_pos] = *((uint16_t *)p_element); + break; + + case sizeof(uint32_t): + ((uint32_t *)p_queue->p_buffer)[write_pos] = *((uint32_t *)p_element); + break; + + case sizeof(uint64_t): + ((uint64_t *)p_queue->p_buffer)[write_pos] = *((uint64_t *)p_element); + break; + + default: + memcpy((void *)((size_t)p_queue->p_buffer + write_pos * p_queue->element_size), + p_element, + p_queue->element_size); + break; + } + + // Update utilization. + size_t utilization = queue_utilization_get(p_queue); + if (p_queue->p_cb->max_utilization < utilization) + { + p_queue->p_cb->max_utilization = utilization; + } + } + else + { + status = NRF_ERROR_NO_MEM; + } + + CRITICAL_REGION_EXIT(); + + NRF_LOG_INST_DEBUG(p_queue->p_log, "pushed element 0x%08X, status:%d", p_element, status); + return status; +} + +ret_code_t nrf_queue_generic_pop(nrf_queue_t const * p_queue, + void * p_element, + bool just_peek) +{ + ret_code_t status = NRF_SUCCESS; + + ASSERT(p_queue != NULL); + ASSERT(p_element != NULL); + + CRITICAL_REGION_ENTER(); + + if (!nrf_queue_is_empty(p_queue)) + { + // Get read position. + size_t read_pos = p_queue->p_cb->front; + + // Update next read position. + if (!just_peek) + { + p_queue->p_cb->front = nrf_queue_next_idx(p_queue, p_queue->p_cb->front); + } + + // Read element. + switch (p_queue->element_size) + { + case sizeof(uint8_t): + *((uint8_t *)p_element) = ((uint8_t *)p_queue->p_buffer)[read_pos]; + break; + + case sizeof(uint16_t): + *((uint16_t *)p_element) = ((uint16_t *)p_queue->p_buffer)[read_pos]; + break; + + case sizeof(uint32_t): + *((uint32_t *)p_element) = ((uint32_t *)p_queue->p_buffer)[read_pos]; + break; + + case sizeof(uint64_t): + *((uint64_t *)p_element) = ((uint64_t *)p_queue->p_buffer)[read_pos]; + break; + + default: + memcpy(p_element, + (void const *)((size_t)p_queue->p_buffer + read_pos * p_queue->element_size), + p_queue->element_size); + break; + } + } + else + { + status = NRF_ERROR_NOT_FOUND; + } + + CRITICAL_REGION_EXIT(); + NRF_LOG_INST_DEBUG(p_queue->p_log, "%s element 0x%08X, status:%d", + just_peek ? "peeked" : "popped", p_element, status); + return status; +} + +/* Purpose of this function is to provide number of continous bytes in the queue's + * array before circullar buffer needs to wrapp. + */ +static size_t continous_items_get(nrf_queue_t const * p_queue, bool write) +{ + size_t front = p_queue->p_cb->front; + size_t back = p_queue->p_cb->back; + + /* Number of continous items for queue write operation */ + if (write) + { + return (back >= front) ? circullar_buffer_size_get(p_queue) - back : front - back; + } + else + { + return (back >= front) ? back - front : circullar_buffer_size_get(p_queue) - front; + } +} + +/**@brief Write elements to the queue. This function assumes that there is enough room in the queue + * to write the requested number of elements and that this process will not be interrupted. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[in] p_data Pointer to the buffer with elements to write. + * @param[in] element_count Number of elements to write. + */ +static void queue_write(nrf_queue_t const * p_queue, void const * p_data, uint32_t element_count) +{ + size_t prev_available = nrf_queue_available_get(p_queue); + size_t continuous = continous_items_get(p_queue, true); + void * p_write_ptr = (void *)((size_t)p_queue->p_buffer + + p_queue->p_cb->back * p_queue->element_size); + + if (element_count <= continuous) + { + memcpy(p_write_ptr, + p_data, + element_count * p_queue->element_size); + + p_queue->p_cb->back = ((p_queue->p_cb->back + element_count) <= p_queue->size) + ? (p_queue->p_cb->back + element_count) + : 0; + } + else + { + size_t first_write_length = continuous * p_queue->element_size; + memcpy(p_write_ptr, + p_data, + first_write_length); + + size_t elements_left = element_count - continuous; + memcpy(p_queue->p_buffer, + (void const *)((size_t)p_data + first_write_length), + elements_left * p_queue->element_size); + + p_queue->p_cb->back = elements_left; + if (prev_available < element_count) + { + // Overwrite the oldest elements. + p_queue->p_cb->front = nrf_queue_next_idx(p_queue, p_queue->p_cb->back); + } + } + + // Update utilization. + size_t utilization = queue_utilization_get(p_queue); + if (p_queue->p_cb->max_utilization < utilization) + { + p_queue->p_cb->max_utilization = utilization; + } +} + +ret_code_t nrf_queue_write(nrf_queue_t const * p_queue, + void const * p_data, + size_t element_count) +{ + ret_code_t status = NRF_SUCCESS; + + ASSERT(p_queue != NULL); + ASSERT(p_data != NULL); + ASSERT(element_count <= p_queue->size); + + if (element_count == 0) + { + return NRF_SUCCESS; + } + + CRITICAL_REGION_ENTER(); + + if ((nrf_queue_available_get(p_queue) >= element_count) + || (p_queue->mode == NRF_QUEUE_MODE_OVERFLOW)) + { + queue_write(p_queue, p_data, element_count); + } + else + { + status = NRF_ERROR_NO_MEM; + } + + CRITICAL_REGION_EXIT(); + + NRF_LOG_INST_DEBUG(p_queue->p_log, "Write %d elements (start address: 0x%08X), status:%d", + element_count, p_data, status); + return status; +} + + +size_t nrf_queue_in(nrf_queue_t const * p_queue, + void const * p_data, + size_t element_count) +{ + ASSERT(p_queue != NULL); + ASSERT(p_data != NULL); + + size_t req_element_count = element_count; + + if (element_count == 0) + { + return 0; + } + + CRITICAL_REGION_ENTER(); + + if (p_queue->mode == NRF_QUEUE_MODE_OVERFLOW) + { + element_count = MIN(element_count, p_queue->size); + } + else + { + size_t available = nrf_queue_available_get(p_queue); + element_count = MIN(element_count, available); + } + + queue_write(p_queue, p_data, element_count); + + CRITICAL_REGION_EXIT(); + + NRF_LOG_INST_DEBUG(p_queue->p_log, "Put in %d elements (start address: 0x%08X), requested :%d", + element_count, p_data, req_element_count); + + return element_count; +} + +/**@brief Read elements from the queue. This function assumes that there are enough elements + * in the queue to read and that this process will not be interrupted. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[out] p_data Pointer to the buffer where elements will be copied. + * @param[in] element_count Number of elements to read. + */ +static void queue_read(nrf_queue_t const * p_queue, void * p_data, uint32_t element_count) +{ + size_t front = p_queue->p_cb->front; + size_t continuous = continous_items_get(p_queue, false); + void const * p_read_ptr = (void const *)((size_t)p_queue->p_buffer + + front * p_queue->element_size); + + if (element_count <= continuous) + { + memcpy(p_data, + p_read_ptr, + element_count * p_queue->element_size); + + p_queue->p_cb->front = ((front + element_count) <= p_queue->size) + ? (front + element_count) + : 0; + } + else + { + size_t first_read_length = continuous * p_queue->element_size; + memcpy(p_data, + p_read_ptr, + first_read_length); + + size_t elements_left = element_count - continuous; + memcpy((void *)((size_t)p_data + first_read_length), + p_queue->p_buffer, + elements_left * p_queue->element_size); + + p_queue->p_cb->front = elements_left; + } +} + +ret_code_t nrf_queue_read(nrf_queue_t const * p_queue, + void * p_data, + size_t element_count) +{ + ret_code_t status = NRF_SUCCESS; + + ASSERT(p_queue != NULL); + ASSERT(p_data != NULL); + + if (element_count == 0) + { + return NRF_SUCCESS; + } + + CRITICAL_REGION_ENTER(); + + if (element_count <= queue_utilization_get(p_queue)) + { + queue_read(p_queue, p_data, element_count); + } + else + { + status = NRF_ERROR_NOT_FOUND; + } + + CRITICAL_REGION_EXIT(); + + NRF_LOG_INST_DEBUG(p_queue->p_log, "Read %d elements (start address: 0x%08X), status :%d", + element_count, p_data, status); + return status; +} + +size_t nrf_queue_out(nrf_queue_t const * p_queue, + void * p_data, + size_t element_count) +{ + ASSERT(p_queue != NULL); + ASSERT(p_data != NULL); + + size_t req_element_count = element_count; + + if (element_count == 0) + { + return 0; + } + + CRITICAL_REGION_ENTER(); + + size_t utilization = queue_utilization_get(p_queue); + element_count = MIN(element_count, utilization); + + queue_read(p_queue, p_data, element_count); + + CRITICAL_REGION_EXIT(); + + NRF_LOG_INST_DEBUG(p_queue->p_log, "Out %d elements (start address: 0x%08X), requested :%d", + element_count, p_data, req_element_count); + return element_count; +} + +void nrf_queue_reset(nrf_queue_t const * p_queue) +{ + ASSERT(p_queue != NULL); + + CRITICAL_REGION_ENTER(); + + memset(p_queue->p_cb, 0, sizeof(nrf_queue_cb_t)); + + CRITICAL_REGION_EXIT(); + + NRF_LOG_INST_DEBUG(p_queue->p_log, "Reset"); +} + +size_t nrf_queue_utilization_get(nrf_queue_t const * p_queue) +{ + size_t utilization; + ASSERT(p_queue != NULL); + + CRITICAL_REGION_ENTER(); + + utilization = queue_utilization_get(p_queue); + + CRITICAL_REGION_EXIT(); + + return utilization; +} + +bool nrf_queue_is_empty(nrf_queue_t const * p_queue) +{ + ASSERT(p_queue != NULL); + size_t front = p_queue->p_cb->front; + size_t back = p_queue->p_cb->back; + return (front == back); +} + +size_t nrf_queue_available_get(nrf_queue_t const * p_queue) +{ + ASSERT(p_queue != NULL); + return p_queue->size - nrf_queue_utilization_get(p_queue); +} + +size_t nrf_queue_max_utilization_get(nrf_queue_t const * p_queue) +{ + ASSERT(p_queue != NULL); + return p_queue->p_cb->max_utilization; +} + +void nrf_queue_max_utilization_reset(nrf_queue_t const * p_queue) +{ + ASSERT(p_queue != NULL); + p_queue->p_cb->max_utilization = 0; +} + + +#endif // NRF_MODULE_ENABLED(NRF_QUEUE) diff --git a/components/libraries/queue/nrf_queue.h b/components/libraries/queue/nrf_queue.h new file mode 100644 index 0000000..cac6d12 --- /dev/null +++ b/components/libraries/queue/nrf_queue.h @@ -0,0 +1,471 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** +* @defgroup nrf_queue Queue module +* @{ +* @ingroup app_common +* @brief Functions that handle the queue instances. +*/ + +#ifndef NRF_QUEUE_H__ +#define NRF_QUEUE_H__ + +#include +#include +#include +#include "nrf_assert.h" +#include "sdk_errors.h" +#include "app_util.h" +#include "app_util_platform.h" +#include "nrf_log_instance.h" +#include "nrf_section.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Name of the module used for logger messaging. + */ +#define NRF_QUEUE_LOG_NAME queue + +/**@brief Queue control block. */ +typedef struct +{ + volatile size_t front; //!< Queue front index. + volatile size_t back; //!< Queue back index. + size_t max_utilization; //!< Maximum utilization of the queue. +} nrf_queue_cb_t; + +/**@brief Supported queue modes. */ +typedef enum +{ + NRF_QUEUE_MODE_OVERFLOW, //!< If the queue is full, new element will overwrite the oldest. + NRF_QUEUE_MODE_NO_OVERFLOW, //!< If the queue is full, new element will not be accepted. +} nrf_queue_mode_t; + +/**@brief Instance of the queue. */ +typedef struct +{ + nrf_queue_cb_t * p_cb; //!< Pointer to the instance control block. + void * p_buffer; //!< Pointer to the memory that is used as storage. + size_t size; //!< Size of the queue. + size_t element_size; //!< Size of one element. + nrf_queue_mode_t mode; //!< Mode of the queue. +#if NRF_QUEUE_CLI_CMDS + const char * p_name; //!< Pointer to string with queue name. +#endif + NRF_LOG_INSTANCE_PTR_DECLARE(p_log) //!< Pointer to instance of the logger object (Conditionally compiled). +} nrf_queue_t; + +#if NRF_QUEUE_CLI_CMDS +#define __NRF_QUEUE_ASSIGN_POOL_NAME(_name) .p_name = STRINGIFY(_name), +#else +#define __NRF_QUEUE_ASSIGN_POOL_NAME(_name) +#endif +/**@brief Create a queue instance. + * + * @note This macro reserves memory for the given queue instance. + * + * @param[in] _type Type which is stored. + * @param[in] _name Name of the queue. + * @param[in] _size Size of the queue. + * @param[in] _mode Mode of the queue. + */ +#define NRF_QUEUE_DEF(_type, _name, _size, _mode) \ + static _type CONCAT_2(_name, _nrf_queue_buffer[(_size) + 1]); \ + static nrf_queue_cb_t CONCAT_2(_name, _nrf_queue_cb); \ + NRF_LOG_INSTANCE_REGISTER(NRF_QUEUE_LOG_NAME, _name, \ + NRF_QUEUE_CONFIG_INFO_COLOR, \ + NRF_QUEUE_CONFIG_DEBUG_COLOR, \ + NRF_QUEUE_CONFIG_LOG_INIT_FILTER_LEVEL, \ + NRF_QUEUE_CONFIG_LOG_ENABLED ? \ + NRF_QUEUE_CONFIG_LOG_LEVEL : NRF_LOG_SEVERITY_NONE); \ + NRF_SECTION_ITEM_REGISTER(nrf_queue, const nrf_queue_t _name) = \ + { \ + .p_cb = &CONCAT_2(_name, _nrf_queue_cb), \ + .p_buffer = CONCAT_2(_name,_nrf_queue_buffer), \ + .size = (_size), \ + .element_size = sizeof(_type), \ + .mode = _mode, \ + __NRF_QUEUE_ASSIGN_POOL_NAME(_name) \ + NRF_LOG_INSTANCE_PTR_INIT(p_log, NRF_QUEUE_LOG_NAME, _name) \ + } + +#if !(defined(__LINT__)) +/**@brief Create multiple queue instances. + * + * @note This macro reserves memory for array of queue instances. + * + * @param[in] _type Type which is stored. + * @param[in] _name Name of the array with queue instances. + * @param[in] _size Size of single queue instance. + * @param[in] _mode Mode of single queue instance. + * @param[in] _num Number of queue instances within array. + */ +#define NRF_QUEUE_ARRAY_DEF(_type, _name, _size, _mode, _num) \ + MACRO_REPEAT_FOR(_num, NRF_QUEUE_ARRAY_INSTANCE_ELEMS_DEC, _type, _name, _size, _mode) \ + static const nrf_queue_t _name[] = \ + { \ + MACRO_REPEAT_FOR(_num, NRF_QUEUE_ARRAY_INSTANCE_INIT, _type, _name, _size, _mode) \ + }; \ + STATIC_ASSERT(ARRAY_SIZE(_name) == _num) +#else +#define NRF_QUEUE_ARRAY_DEF(_type, _name, _size, _mode, _num) \ + static const nrf_queue_t _name[_num]; +#endif // !(defined(__LINT__)) + +/**@brief Helping macro used to declare elements for nrf_queue_t instance. + * Used in @ref NRF_QUEUE_ARRAY_DEF. + */ +#define NRF_QUEUE_ARRAY_INSTANCE_ELEMS_DEC(_num, _type, _name, _size, _mode) \ + static _type CONCAT_3(_name, _num, _nrf_queue_buffer[(_size) + 1]); \ + static nrf_queue_cb_t CONCAT_3(_name, _num, _nrf_queue_cb); + +/**@brief Helping macro used to initialize nrf_queue_t instance in an array fashion. + * Used in @ref NRF_QUEUE_ARRAY_DEF. + */ +#define NRF_QUEUE_ARRAY_INSTANCE_INIT(_num, _type, _name, _size, _mode) \ + { \ + .p_cb = &CONCAT_3(_name, _num, _nrf_queue_cb), \ + .p_buffer = CONCAT_3(_name, _num, _nrf_queue_buffer), \ + .size = (_size), \ + .element_size = sizeof(_type), \ + .mode = _mode, \ + }, + +/**@brief Declare a queue interface. + * + * @param[in] _type Type which is stored. + * @param[in] _name Name of the queue. + */ +#define NRF_QUEUE_INTERFACE_DEC(_type, _name) \ + ret_code_t _name##_push(_type const * p_element); \ + ret_code_t _name##_pop(_type * p_element); \ + ret_code_t _name##_peek(_type * p_element); \ + ret_code_t _name##_write(_type const * p_data, \ + size_t element_count); \ + ret_code_t _name##_read(_type * p_data, \ + size_t element_count); \ + size_t _name##_out(_type * p_data, \ + size_t element_count); \ + size_t _name##_in(_type const * p_data, \ + size_t element_count); \ + bool _name##_is_full(void); \ + bool _name##_is_empty(void); \ + size_t _name##_utilization_get(void); \ + size_t _name##_available_get(void); \ + size_t _name##_max_utilization_get(void); \ + void _name##_reset(void) + +/**@brief Define a queue interface. + * + * @param[in] _type Type which is stored. + * @param[in] _name Name of the queue. + * @param[in] _p_queue Queue instance. + */ +#define NRF_QUEUE_INTERFACE_DEF(_type, _name, _p_queue) \ + ret_code_t _name##_push(_type const * p_element) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + ASSERT((_p_queue)->element_size == sizeof(_type)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_push((_p_queue), p_element); \ + } \ + ret_code_t _name##_pop(_type * p_element) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + ASSERT((_p_queue)->element_size == sizeof(_type)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_pop((_p_queue), p_element); \ + } \ + ret_code_t _name##_peek(_type * p_element) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + ASSERT((_p_queue)->element_size == sizeof(_type)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_peek((_p_queue), p_element); \ + } \ + ret_code_t _name##_write(_type const * p_data, \ + size_t element_count) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + ASSERT((_p_queue)->element_size == sizeof(_type)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_write((_p_queue), p_data, element_count); \ + } \ + ret_code_t _name##_read(_type * p_data, \ + size_t element_count) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + ASSERT((_p_queue)->element_size == sizeof(_type)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_read((_p_queue), p_data, element_count); \ + } \ + size_t _name##_in(_type const * p_data, \ + size_t element_count) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + ASSERT((_p_queue)->element_size == sizeof(_type)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_in((_p_queue), p_data, element_count); \ + } \ + size_t _name##_out(_type * p_data, \ + size_t element_count) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + ASSERT((_p_queue)->element_size == sizeof(_type)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_out((_p_queue), p_data, element_count); \ + } \ + bool _name##_is_full(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + return nrf_queue_is_full(_p_queue); \ + GCC_PRAGMA("GCC diagnostic pop") \ + } \ + bool _name##_is_empty(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_is_empty(_p_queue); \ + } \ + size_t _name##_utilization_get(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_utilization_get(_p_queue); \ + } \ + size_t _name##_available_get(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_available_get(_p_queue); \ + } \ + size_t _name##_max_utilization_get(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_max_utilization_get(_p_queue); \ + } \ + void _name##_reset(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + GCC_PRAGMA("GCC diagnostic pop") \ + nrf_queue_reset(_p_queue); \ + } + +/**@brief Function for pushing an element to the end of queue. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[in] p_element Pointer to the element that will be stored in the queue. + * + * @return NRF_SUCCESS If an element has been successfully added. + * @return NRF_ERROR_NO_MEM If the queue is full (only in @ref NRF_QUEUE_MODE_NO_OVERFLOW). + */ +ret_code_t nrf_queue_push(nrf_queue_t const * p_queue, void const * p_element); + +/**@brief Generic pop implementation. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[out] p_element Pointer where the element will be copied. + * @param[out] just_peek If true, the returned element will not be removed from queue. + * + * @return NRF_SUCCESS If an element was returned. + * @return NRF_ERROR_NOT_FOUND If there are no more elements in the queue. + */ +ret_code_t nrf_queue_generic_pop(nrf_queue_t const * p_queue, + void * p_element, + bool just_peek); + +/**@brief Pop element from the front of the queue. + * + * @param[in] _p_queue Pointer to the nrf_queue_t instance. + * @param[out] _p_element Pointer where the element will be copied. + * + * @return NRF_SUCCESS If an element was returned. + * @return NRF_ERROR_NOT_FOUND If there are no more elements in the queue. + */ +#define nrf_queue_pop(_p_queue, _p_element) nrf_queue_generic_pop((_p_queue), (_p_element), false) + +/**@brief Peek element from the front of the queue. + * + * @param[in] _p_queue Pointer to the nrf_queue_t instance. + * @param[out] _p_element Pointer where the element will be copied. + * + * @return NRF_SUCCESS If an element was returned. + * @return NRF_ERROR_NOT_FOUND If there are no more elements in the queue. + */ +#define nrf_queue_peek(_p_queue, _p_element) nrf_queue_generic_pop((_p_queue), (_p_element), true) + +/**@brief Function for writing elements to the queue. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[in] p_data Pointer to the buffer with elements to write. + * @param[in] element_count Number of elements to write. + * + * @return NRF_SUCCESS If an element was written. + * @return NRF_ERROR_NO_MEM There is not enough space in the queue. No element was written. + */ +ret_code_t nrf_queue_write(nrf_queue_t const * p_queue, + void const * p_data, + size_t element_count); + +/**@brief Function for writing a portion of elements to the queue. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[in] p_data Pointer to the buffer with elements to write. + * @param[in] element_count Number of elements to write. + * + * @return The number of added elements. + */ +size_t nrf_queue_in(nrf_queue_t const * p_queue, + void const * p_data, + size_t element_count); + +/**@brief Function for reading elements from the queue. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[out] p_data Pointer to the buffer where elements will be copied. + * @param[in] element_count Number of elements to read. + * + * @return NRF_SUCCESS If an element was returned. + * @return NRF_ERROR_NOT_FOUND There is not enough elements in the queue. + */ +ret_code_t nrf_queue_read(nrf_queue_t const * p_queue, + void * p_data, + size_t element_count); + +/**@brief Function for reading a portion of elements from the queue. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[out] p_data Pointer to the buffer where elements will be copied. + * @param[in] element_count Number of elements to read. + * + * @return The number of read elements. + */ +size_t nrf_queue_out(nrf_queue_t const * p_queue, + void * p_data, + size_t element_count); + +/**@brief Function for checking if the queue is full. + * + * @param[in] p_queue Pointer to the queue instance. + * + * @return True if the queue is full. + */ +bool nrf_queue_is_full(nrf_queue_t const * p_queue); + +/**@brief Function for checking if the queue is empty. + * + * @param[in] p_queue Pointer to the queue instance. + * + * @return True if the queue is empty. + */ +bool nrf_queue_is_empty(nrf_queue_t const * p_queue); + +/**@brief Function for getting the current queue utilization. + * + * @param[in] p_queue Pointer to the queue instance. + * + * @return Current queue utilization. + */ +size_t nrf_queue_utilization_get(nrf_queue_t const * p_queue); + +/**@brief Function for getting the size of available space. + * + * @param[in] p_queue Pointer to the queue instance. + * + * @return Size of available space. + */ +size_t nrf_queue_available_get(nrf_queue_t const * p_queue); + +/**@brief Function for getting the maximal queue utilization. + * + * @param[in] p_queue Pointer to the queue instance. + * + * @return Maximal queue utilization. + */ +size_t nrf_queue_max_utilization_get(nrf_queue_t const * p_queue); + +/**@brief Function for resetting the maximal queue utilization. + * + * @param[in] p_queue Pointer to the queue instance. + * + */ +void nrf_queue_max_utilization_reset(nrf_queue_t const * p_queue); + +/**@brief Function for resetting the queue state. + * + * @param[in] p_queue Pointer to the queue instance. + */ +void nrf_queue_reset(nrf_queue_t const * p_queue); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_QUEUE_H__ +/** @} */ diff --git a/components/libraries/ringbuf/nrf_ringbuf.c b/components/libraries/ringbuf/nrf_ringbuf.c new file mode 100644 index 0000000..47bce54 --- /dev/null +++ b/components/libraries/ringbuf/nrf_ringbuf.c @@ -0,0 +1,239 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_ringbuf.h" +#include "app_util_platform.h" +#include "nrf_assert.h" + +#define WR_OFFSET 0 +#define RD_OFFSET 1 + +void nrf_ringbuf_init(nrf_ringbuf_t const * p_ringbuf) +{ + p_ringbuf->p_cb->wr_idx = 0; + p_ringbuf->p_cb->rd_idx = 0; + p_ringbuf->p_cb->tmp_rd_idx = 0; + p_ringbuf->p_cb->tmp_wr_idx = 0; + p_ringbuf->p_cb->rd_flag = 0; + p_ringbuf->p_cb->wr_flag = 0; +} + +ret_code_t nrf_ringbuf_alloc(nrf_ringbuf_t const * p_ringbuf, uint8_t * * pp_data, size_t * p_length, bool start) +{ + ASSERT(pp_data); + ASSERT(p_length); + + if (start) + { + if (nrf_atomic_flag_set_fetch(&p_ringbuf->p_cb->wr_flag)) + { + return NRF_ERROR_BUSY; + } + } + + if (p_ringbuf->p_cb->tmp_wr_idx - p_ringbuf->p_cb->rd_idx == p_ringbuf->bufsize_mask + 1) + { + *p_length = 0; + if (start) + { + UNUSED_RETURN_VALUE(nrf_atomic_flag_clear(&p_ringbuf->p_cb->wr_flag)); + } + return NRF_SUCCESS; + } + + uint32_t wr_idx = p_ringbuf->p_cb->tmp_wr_idx & p_ringbuf->bufsize_mask; + uint32_t rd_idx = p_ringbuf->p_cb->rd_idx & p_ringbuf->bufsize_mask; + uint32_t available = (wr_idx >= rd_idx) ? p_ringbuf->bufsize_mask + 1 - wr_idx : + p_ringbuf->p_cb->rd_idx - (p_ringbuf->p_cb->tmp_wr_idx - (p_ringbuf->bufsize_mask + 1)); + *p_length = *p_length < available ? *p_length : available; + *pp_data = &p_ringbuf->p_buffer[wr_idx]; + p_ringbuf->p_cb->tmp_wr_idx += *p_length; + + return NRF_SUCCESS; +} + +ret_code_t nrf_ringbuf_put(nrf_ringbuf_t const * p_ringbuf, size_t length) +{ + uint32_t available = p_ringbuf->bufsize_mask + 1 - + (p_ringbuf->p_cb->wr_idx - p_ringbuf->p_cb->rd_idx); + if (length > available) + { + return NRF_ERROR_NO_MEM; + } + + p_ringbuf->p_cb->wr_idx += length; + p_ringbuf->p_cb->tmp_wr_idx = p_ringbuf->p_cb->wr_idx; + if (nrf_atomic_flag_clear_fetch(&p_ringbuf->p_cb->wr_flag) == 0) + { + /* Flag was already cleared. Suggests misuse. */ + return NRF_ERROR_INVALID_STATE; + } + return NRF_SUCCESS; +} + +ret_code_t nrf_ringbuf_cpy_put(nrf_ringbuf_t const * p_ringbuf, + uint8_t const * p_data, + size_t * p_length) +{ + ASSERT(p_data); + ASSERT(p_length); + + if (nrf_atomic_flag_set_fetch(&p_ringbuf->p_cb->wr_flag)) + { + return NRF_ERROR_BUSY; + } + + uint32_t available = p_ringbuf->bufsize_mask + 1 - + (p_ringbuf->p_cb->wr_idx - p_ringbuf->p_cb->rd_idx); + *p_length = available > *p_length ? *p_length : available; + size_t length = *p_length; + uint32_t masked_wr_idx = (p_ringbuf->p_cb->wr_idx & p_ringbuf->bufsize_mask); + uint32_t trail = p_ringbuf->bufsize_mask + 1 - masked_wr_idx; + + if (length > trail) + { + memcpy(&p_ringbuf->p_buffer[masked_wr_idx], p_data, trail); + length -= trail; + masked_wr_idx = 0; + p_data += trail; + } + memcpy(&p_ringbuf->p_buffer[masked_wr_idx], p_data, length); + p_ringbuf->p_cb->wr_idx += *p_length; + p_ringbuf->p_cb->tmp_wr_idx = p_ringbuf->p_cb->wr_idx; + + UNUSED_RETURN_VALUE(nrf_atomic_flag_clear(&p_ringbuf->p_cb->wr_flag)); + + return NRF_SUCCESS; +} + +ret_code_t nrf_ringbuf_get(nrf_ringbuf_t const * p_ringbuf, uint8_t * * pp_data, size_t * p_length, bool start) +{ + ASSERT(pp_data); + ASSERT(p_length); + + if (start) + { + if (nrf_atomic_flag_set_fetch(&p_ringbuf->p_cb->rd_flag)) + { + return NRF_ERROR_BUSY; + } + } + + uint32_t available = p_ringbuf->p_cb->wr_idx - p_ringbuf->p_cb->tmp_rd_idx; + if (available == 0) + { + *p_length = 0; + if (start) + { + UNUSED_RETURN_VALUE(nrf_atomic_flag_clear(&p_ringbuf->p_cb->rd_flag)); + } + return NRF_SUCCESS; + } + + uint32_t masked_tmp_rd_idx = p_ringbuf->p_cb->tmp_rd_idx & p_ringbuf->bufsize_mask; + uint32_t masked_wr_idx = p_ringbuf->p_cb->wr_idx & p_ringbuf->bufsize_mask; + + if ((masked_wr_idx > masked_tmp_rd_idx) && (available < *p_length)) + { + *p_length = available; + } + else if (masked_wr_idx <= masked_tmp_rd_idx) + { + uint32_t trail = p_ringbuf->bufsize_mask + 1 - masked_tmp_rd_idx; + if (*p_length > trail) + { + *p_length = trail; + } + } + *pp_data = &p_ringbuf->p_buffer[masked_tmp_rd_idx]; + p_ringbuf->p_cb->tmp_rd_idx += *p_length; + + return NRF_SUCCESS; +} + +ret_code_t nrf_ringbuf_cpy_get(nrf_ringbuf_t const * p_ringbuf, + uint8_t * p_data, + size_t * p_length) +{ + ASSERT(p_data); + ASSERT(p_length); + + if (nrf_atomic_flag_set_fetch(&p_ringbuf->p_cb->rd_flag)) + { + return NRF_ERROR_BUSY; + } + + uint32_t available = p_ringbuf->p_cb->wr_idx - p_ringbuf->p_cb->rd_idx; + *p_length = available > *p_length ? *p_length : available; + size_t length = *p_length; + uint32_t masked_rd_idx = (p_ringbuf->p_cb->rd_idx & p_ringbuf->bufsize_mask); + uint32_t masked_wr_idx = (p_ringbuf->p_cb->wr_idx & p_ringbuf->bufsize_mask); + uint32_t trail = (masked_wr_idx > masked_rd_idx) ? masked_wr_idx - masked_rd_idx : + p_ringbuf->bufsize_mask + 1 - masked_rd_idx; + + if (length > trail) + { + memcpy(p_data, &p_ringbuf->p_buffer[masked_rd_idx], trail); + length -= trail; + masked_rd_idx = 0; + p_data += trail; + } + memcpy(p_data, &p_ringbuf->p_buffer[masked_rd_idx], length); + p_ringbuf->p_cb->rd_idx += *p_length; + p_ringbuf->p_cb->tmp_rd_idx = p_ringbuf->p_cb->rd_idx; + + UNUSED_RETURN_VALUE(nrf_atomic_flag_clear(&p_ringbuf->p_cb->rd_flag)); + + return NRF_SUCCESS; +} + +ret_code_t nrf_ringbuf_free(nrf_ringbuf_t const * p_ringbuf, size_t length) +{ + uint32_t available = (p_ringbuf->p_cb->wr_idx - p_ringbuf->p_cb->rd_idx); + if (length > available) + { + return NRF_ERROR_NO_MEM; + } + + p_ringbuf->p_cb->rd_idx += length; + p_ringbuf->p_cb->tmp_rd_idx = p_ringbuf->p_cb->rd_idx; + UNUSED_RETURN_VALUE(nrf_atomic_flag_clear(&p_ringbuf->p_cb->rd_flag)); + + return NRF_SUCCESS; +} diff --git a/components/libraries/ringbuf/nrf_ringbuf.h b/components/libraries/ringbuf/nrf_ringbuf.h new file mode 100644 index 0000000..b22674a --- /dev/null +++ b/components/libraries/ringbuf/nrf_ringbuf.h @@ -0,0 +1,206 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_RINGBUF_H +#define NRF_RINGBUF_H + +/** +* @defgroup nrf_ringbuf Ring buffer +* @{ +* @ingroup app_common +* @brief Functions for controlling the ring buffer. +*/ + +#include +#include "nrf_atomic.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @brief Ring buffer instance control block. + * */ +typedef struct +{ + nrf_atomic_flag_t wr_flag; //!< Protection flag. + nrf_atomic_flag_t rd_flag; //!< Protection flag. + uint32_t wr_idx; //!< Write index (updated when putting). + uint32_t tmp_wr_idx; //!< Temporary write index (updated when allocating). + uint32_t rd_idx; //!< Read index (updated when freeing). + uint32_t tmp_rd_idx; //!< Temporary read index (updated when getting). +} nrf_ringbuf_cb_t; + +/** + * @brief Ring buffer instance structure. + * */ +typedef struct +{ + uint8_t * p_buffer; //!< Pointer to the memory used by the ring buffer. + uint32_t bufsize_mask; //!< Buffer size mask (buffer size must be a power of 2). + nrf_ringbuf_cb_t * p_cb; //!< Pointer to the instance control block. +} nrf_ringbuf_t; + +/** + * @brief Macro for defining a ring buffer instance. + * + * @param _name Instance name. + * @param _size Size of the ring buffer (must be a power of 2). + * */ +#define NRF_RINGBUF_DEF(_name, _size) \ + STATIC_ASSERT(IS_POWER_OF_TWO(_size)); \ + static uint8_t CONCAT_2(_name,_buf)[_size]; \ + static nrf_ringbuf_cb_t CONCAT_2(_name,_cb); \ + static const nrf_ringbuf_t _name = { \ + .p_buffer = CONCAT_2(_name,_buf), \ + .bufsize_mask = _size - 1, \ + .p_cb = &CONCAT_2(_name,_cb), \ + } + +/** + * @brief Function for initializing a ring buffer instance. + * + * @param p_ringbuf Pointer to the ring buffer instance. + * + * */ +void nrf_ringbuf_init(nrf_ringbuf_t const * p_ringbuf); + +/** + * @brief Function for allocating memory from a ring buffer. + * + * This function attempts to allocate the amount of memory requested by the user, or a smaller amount if + * the requested amount is not available. If a start flag is set, then exclusive access to allocation + * is established. @ref nrf_ringbuf_put frees access to allocation. If a start flag is not set, then + * exclusive access check is omitted. + * + * @param[in] p_ringbuf Pointer to the ring buffer instance. + * @param[in] pp_data Pointer to the pointer to the allocated buffer. + * @param[in, out] p_length Pointer to length. Length is set to the requested amount and filled + * by the function with actually allocated amount. + * @param[in] start Set to true if exclusive access should be controlled. + * + * @retval NRF_SUCCESS Successful allocation (can be smaller amount than requested). + * NRF_ERROR_BUSY Ring buffer allocation process (alloc-put) is ongoing. + * + * */ +ret_code_t nrf_ringbuf_alloc(nrf_ringbuf_t const * p_ringbuf, uint8_t * * pp_data, size_t * p_length, bool start); + +/** + * @brief Function for commiting data to a ring buffer. + * + * When an allocated buffer (see @ref nrf_ringbuf_alloc) has been filled with data, it must be committed + * to make it available for @ref nrf_ringbuf_get and @ref nrf_ringbuf_cpy_get. This function commits + * the data (can be smaller amount than allocated). + * + * @param[in] p_ringbuf Pointer to the ring buffer instance. + * @param[in] length Amount of bytes to put. + + * @return NRF_SUCCESS on successful put or error. + * */ +ret_code_t nrf_ringbuf_put(nrf_ringbuf_t const * p_ringbuf, size_t length); + +/** + * @brief Function for copying data directly into the ring buffer. + * + * This function copies a user buffer to the ring buffer. + * + * @param[in] p_ringbuf Pointer to the ring buffer instance. + * @param[in] p_data Pointer to the input buffer. + * @param[in, out] p_length Amount of bytes to copy. Amount of bytes copied. + + * @return NRF_SUCCESS on successful put or error. + * */ +ret_code_t nrf_ringbuf_cpy_put(nrf_ringbuf_t const * p_ringbuf, + uint8_t const* p_data, + size_t * p_length); + + +/** + * Function for getting data from the ring buffer. + * + * This function attempts to get the requested amount of data from the ring buffer. If a start flag is set, then + * exclusive access to getting data from the ring buffer is established. @ref nrf_ringbuf_free frees + * access to getting data from the ring buffer. If a start flag is not set, then + * exclusive access check is omitted. + * + * @param[in] p_ringbuf Pointer to the ring buffer instance. + * @param[in] pp_data Pointer to the pointer to the buffer with data. + * @param[in, out] p_length Pointer to length. Length is set to the requested amount and filled + * by the function with the actual amount. + * @param[in] start Set to true if exclusive access should be controlled. + * + * @retval NRF_SUCCESS Successful getting (can be smaller amount than requested). + * NRF_ERROR_BUSY Ring buffer getting process (get-free) is ongoing. + */ +ret_code_t nrf_ringbuf_get(nrf_ringbuf_t const * p_ringbuf, uint8_t * * pp_data, size_t * p_length, bool start); + +/** + * @brief Function for freeing a buffer back to the ring buffer. + * + * When a buffer with data taken from the ring buffer (see @ref nrf_ringbuf_get) has been processed, it + * must be freed to make it available for further use. This function frees the buffer (can be smaller + * amount than get). + * + * @param[in] p_ringbuf Pointer to the ring buffer instance. + * @param[in] length Amount of bytes to free. + + * @return NRF_SUCCESS on successful put or error. + * */ +ret_code_t nrf_ringbuf_free(nrf_ringbuf_t const * p_ringbuf, size_t length); + +/** + * @brief Function for copying data directly out of the ring buffer. + * + * This function copies available data from the ring buffer to a user buffer. + * + * @param[in] p_ringbuf Pointer to the ring buffer instance. + * @param[in] p_data Pointer to the input buffer. + * @param[in, out] p_length Amount of bytes to copy. Amount of bytes copied. + + * @return NRF_SUCCESS on successful put or error. + * */ +ret_code_t nrf_ringbuf_cpy_get(nrf_ringbuf_t const * p_ringbuf, + uint8_t * p_data, + size_t * p_length); +#ifdef __cplusplus +} +#endif + +#endif //NRF_RINGBUF_H +/** @} */ diff --git a/components/libraries/scheduler/app_scheduler.c b/components/libraries/scheduler/app_scheduler.c new file mode 100644 index 0000000..47b57ac --- /dev/null +++ b/components/libraries/scheduler/app_scheduler.c @@ -0,0 +1,288 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(APP_SCHEDULER) +#include "app_scheduler.h" +#include +#include +#include +#include "nrf_soc.h" +#include "nrf_assert.h" +#include "app_util_platform.h" + +/**@brief Structure for holding a scheduled event header. */ +typedef struct +{ + app_sched_event_handler_t handler; /**< Pointer to event handler to receive the event. */ + uint16_t event_data_size; /**< Size of event data. */ +} event_header_t; + +STATIC_ASSERT(sizeof(event_header_t) <= APP_SCHED_EVENT_HEADER_SIZE); + +static event_header_t * m_queue_event_headers; /**< Array for holding the queue event headers. */ +static uint8_t * m_queue_event_data; /**< Array for holding the queue event data. */ +static volatile uint8_t m_queue_start_index; /**< Index of queue entry at the start of the queue. */ +static volatile uint8_t m_queue_end_index; /**< Index of queue entry at the end of the queue. */ +static uint16_t m_queue_event_size; /**< Maximum event size in queue. */ +static uint16_t m_queue_size; /**< Number of queue entries. */ + +#if APP_SCHEDULER_WITH_PROFILER +static uint16_t m_max_queue_utilization; /**< Maximum observed queue utilization. */ +#endif + +#if APP_SCHEDULER_WITH_PAUSE +static uint32_t m_scheduler_paused_counter = 0; /**< Counter storing the difference between pausing + and resuming the scheduler. */ +#endif + +/**@brief Function for incrementing a queue index, and handle wrap-around. + * + * @param[in] index Old index. + * + * @return New (incremented) index. + */ +static __INLINE uint8_t next_index(uint8_t index) +{ + return (index < m_queue_size) ? (index + 1) : 0; +} + + +static __INLINE uint8_t app_sched_queue_full() +{ + uint8_t tmp = m_queue_start_index; + return next_index(m_queue_end_index) == tmp; +} + +/**@brief Macro for checking if a queue is full. */ +#define APP_SCHED_QUEUE_FULL() app_sched_queue_full() + + +static __INLINE uint8_t app_sched_queue_empty() +{ + uint8_t tmp = m_queue_start_index; + return m_queue_end_index == tmp; +} + +/**@brief Macro for checking if a queue is empty. */ +#define APP_SCHED_QUEUE_EMPTY() app_sched_queue_empty() + + +uint32_t app_sched_init(uint16_t event_size, uint16_t queue_size, void * p_event_buffer) +{ + uint16_t data_start_index = (queue_size + 1) * sizeof(event_header_t); + + // Check that buffer is correctly aligned + if (!is_word_aligned(p_event_buffer)) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Initialize event scheduler + m_queue_event_headers = p_event_buffer; + m_queue_event_data = &((uint8_t *)p_event_buffer)[data_start_index]; + m_queue_end_index = 0; + m_queue_start_index = 0; + m_queue_event_size = event_size; + m_queue_size = queue_size; + +#if APP_SCHEDULER_WITH_PROFILER + m_max_queue_utilization = 0; +#endif + + return NRF_SUCCESS; +} + + +uint16_t app_sched_queue_space_get() +{ + uint16_t start = m_queue_start_index; + uint16_t end = m_queue_end_index; + uint16_t free_space = m_queue_size - ((end >= start) ? + (end - start) : (m_queue_size + 1 - start + end)); + return free_space; +} + + +#if APP_SCHEDULER_WITH_PROFILER +static void queue_utilization_check(void) +{ + uint16_t start = m_queue_start_index; + uint16_t end = m_queue_end_index; + uint16_t queue_utilization = (end >= start) ? (end - start) : + (m_queue_size + 1 - start + end); + + if (queue_utilization > m_max_queue_utilization) + { + m_max_queue_utilization = queue_utilization; + } +} + +uint16_t app_sched_queue_utilization_get(void) +{ + return m_max_queue_utilization; +} +#endif // APP_SCHEDULER_WITH_PROFILER + + +uint32_t app_sched_event_put(void const * p_event_data, + uint16_t event_data_size, + app_sched_event_handler_t handler) +{ + uint32_t err_code; + + if (event_data_size <= m_queue_event_size) + { + uint16_t event_index = 0xFFFF; + + CRITICAL_REGION_ENTER(); + + if (!APP_SCHED_QUEUE_FULL()) + { + event_index = m_queue_end_index; + m_queue_end_index = next_index(m_queue_end_index); + + #if APP_SCHEDULER_WITH_PROFILER + // This function call must be protected with critical region because + // it modifies 'm_max_queue_utilization'. + queue_utilization_check(); + #endif + } + + CRITICAL_REGION_EXIT(); + + if (event_index != 0xFFFF) + { + // NOTE: This can be done outside the critical region since the event consumer will + // always be called from the main loop, and will thus never interrupt this code. + m_queue_event_headers[event_index].handler = handler; + if ((p_event_data != NULL) && (event_data_size > 0)) + { + memcpy(&m_queue_event_data[event_index * m_queue_event_size], + p_event_data, + event_data_size); + m_queue_event_headers[event_index].event_data_size = event_data_size; + } + else + { + m_queue_event_headers[event_index].event_data_size = 0; + } + + err_code = NRF_SUCCESS; + } + else + { + err_code = NRF_ERROR_NO_MEM; + } + } + else + { + err_code = NRF_ERROR_INVALID_LENGTH; + } + + return err_code; +} + + +#if APP_SCHEDULER_WITH_PAUSE +void app_sched_pause(void) +{ + CRITICAL_REGION_ENTER(); + + if (m_scheduler_paused_counter < UINT32_MAX) + { + m_scheduler_paused_counter++; + } + CRITICAL_REGION_EXIT(); +} + +void app_sched_resume(void) +{ + CRITICAL_REGION_ENTER(); + + if (m_scheduler_paused_counter > 0) + { + m_scheduler_paused_counter--; + } + CRITICAL_REGION_EXIT(); +} +#endif //APP_SCHEDULER_WITH_PAUSE + + +/**@brief Function for checking if scheduler is paused which means that should break processing + * events. + * + * @return Boolean value - true if scheduler is paused, false otherwise. + */ +static __INLINE bool is_app_sched_paused(void) +{ +#if APP_SCHEDULER_WITH_PAUSE + return (m_scheduler_paused_counter > 0); +#else + return false; +#endif +} + + +void app_sched_execute(void) +{ + while (!is_app_sched_paused() && !APP_SCHED_QUEUE_EMPTY()) + { + // Since this function is only called from the main loop, there is no + // need for a critical region here, however a special care must be taken + // regarding update of the queue start index (see the end of the loop). + uint16_t event_index = m_queue_start_index; + + void * p_event_data; + uint16_t event_data_size; + app_sched_event_handler_t event_handler; + + p_event_data = &m_queue_event_data[event_index * m_queue_event_size]; + event_data_size = m_queue_event_headers[event_index].event_data_size; + event_handler = m_queue_event_headers[event_index].handler; + + event_handler(p_event_data, event_data_size); + + // Event processed, now it is safe to move the queue start index, + // so the queue entry occupied by this event can be used to store + // a next one. + m_queue_start_index = next_index(m_queue_start_index); + } +} +#endif //NRF_MODULE_ENABLED(APP_SCHEDULER) diff --git a/components/libraries/scheduler/app_scheduler.h b/components/libraries/scheduler/app_scheduler.h new file mode 100644 index 0000000..44d0a32 --- /dev/null +++ b/components/libraries/scheduler/app_scheduler.h @@ -0,0 +1,211 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup app_scheduler Scheduler + * @{ + * @ingroup app_common + * + * @brief The scheduler is used for transferring execution from the interrupt context to the main + * context. + * + * @details See @ref seq_diagrams_sched for sequence diagrams illustrating the flow of events + * when using the Scheduler. + * + * @section app_scheduler_req Requirements: + * + * @subsection main_context_logic Logic in main context: + * + * - Define an event handler for each type of event expected. + * - Initialize the scheduler by calling the APP_SCHED_INIT() macro before entering the + * application main loop. + * - Call app_sched_execute() from the main loop each time the application wakes up because of an + * event (typically when sd_app_evt_wait() returns). + * + * @subsection int_context_logic Logic in interrupt context: + * + * - In the interrupt handler, call app_sched_event_put() + * with the appropriate data and event handler. This will insert an event into the + * scheduler's queue. The app_sched_execute() function will pull this event and call its + * handler in the main context. + * + * @if (PERIPHERAL) + * For an example usage of the scheduler, see the implementations of + * @ref ble_sdk_app_hids_mouse and @ref ble_sdk_app_hids_keyboard. + * @endif + * + * @image html scheduler_working.svg The high level design of the scheduler + */ + +#ifndef APP_SCHEDULER_H__ +#define APP_SCHEDULER_H__ + +#include "sdk_config.h" +#include +#include "app_error.h" +#include "app_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define APP_SCHED_EVENT_HEADER_SIZE 8 /**< Size of app_scheduler.event_header_t (only for use inside APP_SCHED_BUF_SIZE()). */ + +/**@brief Compute number of bytes required to hold the scheduler buffer. + * + * @param[in] EVENT_SIZE Maximum size of events to be passed through the scheduler. + * @param[in] QUEUE_SIZE Number of entries in scheduler queue (i.e. the maximum number of events + * that can be scheduled for execution). + * + * @return Required scheduler buffer size (in bytes). + */ +#define APP_SCHED_BUF_SIZE(EVENT_SIZE, QUEUE_SIZE) \ + (((EVENT_SIZE) + APP_SCHED_EVENT_HEADER_SIZE) * ((QUEUE_SIZE) + 1)) + +/**@brief Scheduler event handler type. */ +typedef void (*app_sched_event_handler_t)(void * p_event_data, uint16_t event_size); + +/**@brief Macro for initializing the event scheduler. + * + * @details It will also handle dimensioning and allocation of the memory buffer required by the + * scheduler, making sure the buffer is correctly aligned. + * + * @param[in] EVENT_SIZE Maximum size of events to be passed through the scheduler. + * @param[in] QUEUE_SIZE Number of entries in scheduler queue (i.e. the maximum number of events + * that can be scheduled for execution). + * + * @note Since this macro allocates a buffer, it must only be called once (it is OK to call it + * several times as long as it is from the same location, e.g. to do a reinitialization). + */ +#define APP_SCHED_INIT(EVENT_SIZE, QUEUE_SIZE) \ + do \ + { \ + static uint32_t APP_SCHED_BUF[CEIL_DIV(APP_SCHED_BUF_SIZE((EVENT_SIZE), (QUEUE_SIZE)), \ + sizeof(uint32_t))]; \ + uint32_t ERR_CODE = app_sched_init((EVENT_SIZE), (QUEUE_SIZE), APP_SCHED_BUF); \ + APP_ERROR_CHECK(ERR_CODE); \ + } while (0) + +/**@brief Function for initializing the Scheduler. + * + * @details It must be called before entering the main loop. + * + * @param[in] max_event_size Maximum size of events to be passed through the scheduler. + * @param[in] queue_size Number of entries in scheduler queue (i.e. the maximum number of + * events that can be scheduled for execution). + * @param[in] p_evt_buffer Pointer to memory buffer for holding the scheduler queue. It must + * be dimensioned using the APP_SCHED_BUFFER_SIZE() macro. The buffer + * must be aligned to a 4 byte boundary. + * + * @note Normally initialization should be done using the APP_SCHED_INIT() macro, as that will both + * allocate the scheduler buffer, and also align the buffer correctly. + * + * @retval NRF_SUCCESS Successful initialization. + * @retval NRF_ERROR_INVALID_PARAM Invalid parameter (buffer not aligned to a 4 byte + * boundary). + */ +uint32_t app_sched_init(uint16_t max_event_size, uint16_t queue_size, void * p_evt_buffer); + +/**@brief Function for executing all scheduled events. + * + * @details This function must be called from within the main loop. It will execute all events + * scheduled since the last time it was called. + */ +void app_sched_execute(void); + +/**@brief Function for scheduling an event. + * + * @details Puts an event into the event queue. + * + * @param[in] p_event_data Pointer to event data to be scheduled. + * @param[in] event_size Size of event data to be scheduled. + * @param[in] handler Event handler to receive the event. + * + * @return NRF_SUCCESS on success, otherwise an error code. + */ +uint32_t app_sched_event_put(void const * p_event_data, + uint16_t event_size, + app_sched_event_handler_t handler); + +/**@brief Function for getting the maximum observed queue utilization. + * + * Function for tuning the module and determining QUEUE_SIZE value and thus module RAM usage. + * + * @note @ref APP_SCHEDULER_WITH_PROFILER must be enabled to use this functionality. + * + * @return Maximum number of events in queue observed so far. + */ +uint16_t app_sched_queue_utilization_get(void); + +/**@brief Function for getting the current amount of free space in the queue. + * + * @details The real amount of free space may be less if entries are being added from an interrupt. + * To get the sxact value, this function should be called from the critical section. + * + * @return Amount of free space in the queue. + */ +uint16_t app_sched_queue_space_get(void); + +/**@brief A function to pause the scheduler. + * + * @details When the scheduler is paused events are not pulled from the scheduler queue for + * processing. The function can be called multiple times. To unblock the scheduler the + * function @ref app_sched_resume has to be called the same number of times. + * + * @note @ref APP_SCHEDULER_WITH_PAUSE must be enabled to use this functionality. + */ +void app_sched_pause(void); + +/**@brief A function to resume a scheduler. + * + * @details To unblock the scheduler this function has to be called the same number of times as + * @ref app_sched_pause function. + * + * @note @ref APP_SCHEDULER_WITH_PAUSE must be enabled to use this functionality. + */ +void app_sched_resume(void); + +#ifdef __cplusplus +} +#endif + +#endif // APP_SCHEDULER_H__ + +/** @} */ diff --git a/components/libraries/scheduler/app_scheduler_serconn.c b/components/libraries/scheduler/app_scheduler_serconn.c new file mode 100644 index 0000000..fd7211a --- /dev/null +++ b/components/libraries/scheduler/app_scheduler_serconn.c @@ -0,0 +1,298 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "app_scheduler.h" +#include +#include +#include +#include "nrf_soc.h" +#include "nrf_assert.h" +#include "app_util.h" +#include "app_util_platform.h" + +/**@brief Structure for holding a scheduled event header. */ +typedef struct +{ + app_sched_event_handler_t handler; /**< Pointer to event handler to receive the event. */ + uint16_t event_data_size; /**< Size of event data. */ +} event_header_t; + +STATIC_ASSERT(sizeof (event_header_t) <= APP_SCHED_EVENT_HEADER_SIZE); + +static event_header_t * m_queue_event_headers; /**< Array for holding the queue event headers. */ +static uint8_t * m_queue_event_data; /**< Array for holding the queue event data. */ +static volatile uint8_t m_queue_start_index; /**< Index of queue entry at the start of the queue. */ +static volatile uint8_t m_queue_end_index; /**< Index of queue entry at the end of the queue. */ +static uint16_t m_queue_event_size; /**< Maximum event size in queue. */ +static uint16_t m_queue_size; /**< Number of queue entries. */ + +#if APP_SCHEDULER_WITH_PROFILER +static uint16_t m_max_queue_utilization; /**< Maximum observed queue utilization. */ +#endif + +static uint32_t m_scheduler_paused_counter = 0; /**< Counter storing the difference between pausing + and resuming the scheduler. */ + +/**@brief Function for incrementing a queue index, and handle wrap-around. + * + * @param[in] index Old index. + * + * @return New (incremented) index. + */ +static __INLINE uint8_t next_index(uint8_t index) +{ + return (index < m_queue_size) ? (index + 1) : 0; +} + +static __INLINE uint8_t app_sched_queue_full(void) +{ + uint8_t tmp = m_queue_start_index; + return next_index(m_queue_end_index) == tmp; +} + +/**@brief Macro for checking if a queue is full. */ +#define APP_SCHED_QUEUE_FULL() app_sched_queue_full() + +static __INLINE uint8_t app_sched_queue_empty(void) +{ + uint8_t tmp = m_queue_start_index; + return m_queue_end_index == tmp; +} + +/**@brief Macro for checking if a queue is empty. */ +#define APP_SCHED_QUEUE_EMPTY() app_sched_queue_empty() + + +uint32_t app_sched_init(uint16_t event_size, uint16_t queue_size, void * p_event_buffer) +{ + uint16_t data_start_index = (queue_size + 1) * sizeof (event_header_t); + + //Check that buffer is correctly aligned + if (!is_word_aligned(p_event_buffer)) + { + return NRF_ERROR_INVALID_PARAM; + } + + //Initialize event scheduler + m_queue_event_headers = p_event_buffer; + m_queue_event_data = &((uint8_t *)p_event_buffer)[data_start_index]; + m_queue_end_index = 0; + m_queue_start_index = 0; + m_queue_event_size = event_size; + m_queue_size = queue_size; + +#if APP_SCHEDULER_WITH_PROFILER + m_max_queue_utilization = 0; +#endif + + return NRF_SUCCESS; +} + + +uint16_t app_sched_queue_space_get() +{ + uint16_t start = m_queue_start_index; + uint16_t end = m_queue_end_index; + uint16_t free_space = m_queue_size - ((end >= start) ? + (end - start) : (m_queue_size + 1 - start + end)); + return free_space; +} + + +#if APP_SCHEDULER_WITH_PROFILER +static __INLINE void check_queue_utilization(void) +{ + uint16_t start = m_queue_start_index; + uint16_t end = m_queue_end_index; + uint16_t queue_utilization = (end >= start) ? (end - start) : + (m_queue_size + 1 - start + end); + + if (queue_utilization > m_max_queue_utilization) + { + m_max_queue_utilization = queue_utilization; + } +} + +uint16_t app_sched_queue_utilization_get(void) +{ + return m_max_queue_utilization; +} +#endif // APP_SCHEDULER_WITH_PROFILER + + +uint32_t app_sched_event_put(void * p_event_data, + uint16_t event_data_size, + app_sched_event_handler_t handler) +{ + uint32_t err_code; + + if (event_data_size <= m_queue_event_size) + { + uint16_t event_index = 0xFFFF; + + CRITICAL_REGION_ENTER(); + + if (!APP_SCHED_QUEUE_FULL()) + { + event_index = m_queue_end_index; + m_queue_end_index = next_index(m_queue_end_index); + } + + CRITICAL_REGION_EXIT(); + + if (event_index != 0xFFFF) + { + //NOTE: This can be done outside the critical region since the event consumer will + //always be called from the main loop, and will thus never interrupt this code. + m_queue_event_headers[event_index].handler = handler; + + if ((p_event_data != NULL) && (event_data_size > 0)) + { + memcpy(&m_queue_event_data[event_index * m_queue_event_size], + p_event_data, + event_data_size); + m_queue_event_headers[event_index].event_data_size = event_data_size; + } + else + { + m_queue_event_headers[event_index].event_data_size = 0; + } + + #if APP_SCHEDULER_WITH_PROFILER + check_queue_utilization(); + #endif + + err_code = NRF_SUCCESS; + } + else + { + err_code = NRF_ERROR_NO_MEM; + } + } + else + { + err_code = NRF_ERROR_INVALID_LENGTH; + } + + return err_code; +} + + +/**@brief Function for reading the next event from specified event queue. + * + * @param[out] pp_event_data Pointer to pointer to event data. + * @param[out] p_event_data_size Pointer to size of event data. + * @param[out] p_event_handler Pointer to event handler function pointer. + * + * @return NRF_SUCCESS if new event, NRF_ERROR_NOT_FOUND if event queue is empty. + */ +static uint32_t app_sched_event_get(void * * pp_event_data, + uint16_t * p_event_data_size, + app_sched_event_handler_t * p_event_handler) +{ + uint32_t err_code = NRF_ERROR_NOT_FOUND; + + if (!APP_SCHED_QUEUE_EMPTY()) + { + uint16_t event_index; + + //NOTE: There is no need for a critical region here, as this function will only be called + //from app_sched_execute() from inside the main loop, so it will never interrupt + //app_sched_event_put(). Also, updating of (i.e. writing to) the start index will be + //an atomic operation. + event_index = m_queue_start_index; + m_queue_start_index = next_index(m_queue_start_index); + + *pp_event_data = &m_queue_event_data[event_index * m_queue_event_size]; + *p_event_data_size = m_queue_event_headers[event_index].event_data_size; + *p_event_handler = m_queue_event_headers[event_index].handler; + + err_code = NRF_SUCCESS; + } + + return err_code; +} + + +void app_sched_pause(void) +{ + CRITICAL_REGION_ENTER(); + + if (m_scheduler_paused_counter < UINT32_MAX) + { + m_scheduler_paused_counter++; + } + CRITICAL_REGION_EXIT(); +} + + +void app_sched_resume(void) +{ + CRITICAL_REGION_ENTER(); + + if (m_scheduler_paused_counter > 0) + { + m_scheduler_paused_counter--; + } + CRITICAL_REGION_EXIT(); +} + +/**@brief Function for checking if scheduler is paused which means that should break processing + * events. + * + * @return Boolean value - true if scheduler is paused, false otherwise. + */ +static __INLINE bool is_app_sched_paused(void) +{ + return (m_scheduler_paused_counter > 0); +} + +void app_sched_execute(void) +{ + void * p_event_data; + uint16_t event_data_size; + app_sched_event_handler_t event_handler; + + //Get next event (if any), and execute handler + while ((!is_app_sched_paused()) && + (app_sched_event_get(&p_event_data, &event_data_size, &event_handler) == NRF_SUCCESS)) + { + event_handler(p_event_data, event_data_size); + } +} diff --git a/components/libraries/sortlist/nrf_sortlist.c b/components/libraries/sortlist/nrf_sortlist.c new file mode 100644 index 0000000..8788e99 --- /dev/null +++ b/components/libraries/sortlist/nrf_sortlist.c @@ -0,0 +1,126 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_SORTLIST) +#include "nrf_sortlist.h" +#include "nrf_assert.h" + +#define NRF_LOG_MODULE_NAME sortlist +#if NRF_SORTLIST_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_SORTLIST_CONFIG_LOG_LEVEL + #define NRF_LOG_INFO_COLOR NRF_SORTLIST_CONFIG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_SORTLIST_CONFIG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_SORTLIST_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +void nrf_sortlist_add(nrf_sortlist_t const * p_list, nrf_sortlist_item_t * p_item) +{ + ASSERT(p_list); + ASSERT(p_item); + + nrf_sortlist_item_t ** pp_curr = &(p_list->p_cb->p_head); + + while(*pp_curr != NULL) + { + if(!(p_list->compare_func(*pp_curr, p_item))) + { + break; + } + pp_curr = &((*pp_curr)->p_next); + } + + p_item->p_next = *pp_curr; + *pp_curr = p_item; + + NRF_LOG_INFO("List:%s, adding element:%08X after:%08X, before:%08X", + p_list->p_name, p_item, *pp_curr, p_item->p_next); +} + +nrf_sortlist_item_t * nrf_sortlist_pop(nrf_sortlist_t const * p_list) +{ + ASSERT(p_list); + nrf_sortlist_item_t * ret = p_list->p_cb->p_head; + if (p_list->p_cb->p_head != NULL) + { + p_list->p_cb->p_head = p_list->p_cb->p_head->p_next; + } + NRF_LOG_INFO("List:%s, poping element:%08X", p_list->p_name, ret); + return ret; +} + +nrf_sortlist_item_t const * nrf_sortlist_peek(nrf_sortlist_t const * p_list) +{ + ASSERT(p_list); + return p_list->p_cb->p_head; +} + +nrf_sortlist_item_t const * nrf_sortlist_next(nrf_sortlist_item_t const * p_item) +{ + ASSERT(p_item); + return p_item->p_next; +} + +bool nrf_sortlist_remove(nrf_sortlist_t const * p_list, nrf_sortlist_item_t * p_item) +{ + ASSERT(p_list); + ASSERT(p_item); + bool ret = false; + + nrf_sortlist_item_t ** pp_curr = &(p_list->p_cb->p_head); + + while(*pp_curr != NULL) + { + if(*pp_curr == p_item) + { + *pp_curr = p_item->p_next; + ret = true; + break; + } + pp_curr = &((*pp_curr)->p_next); + } + + NRF_LOG_INFO("List:%s, removing element:%08X %s", + p_list->p_name, p_item, ret ? "succeeded" : "not found"); + return ret; +} +#endif //NRF_SORTLIST_ENABLED diff --git a/components/libraries/sortlist/nrf_sortlist.h b/components/libraries/sortlist/nrf_sortlist.h new file mode 100644 index 0000000..12cc8ea --- /dev/null +++ b/components/libraries/sortlist/nrf_sortlist.h @@ -0,0 +1,179 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_SORTLIST_H +#define NRF_SORTLIST_H + +#include "sdk_config.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @defgroup nrf_sortlist Sorted list + * @{ + * @ingroup app_common + * @brief Module for storing items in the ordered list. + */ + +/** + * @brief Forward declaration of sorted list item. + */ +typedef struct nrf_sortlist_item_s nrf_sortlist_item_t; + +/** @brief Prototype of a function which compares two elements. + * + * @param p_item0 Item 0. + * @param p_item1 Item 1. + * + * @return True if Item 0 should be higher than Item 1 and false otherwise. + * + */ +typedef bool (*nrf_sortlist_compare_func_t)(nrf_sortlist_item_t * p_item0, nrf_sortlist_item_t * p_item1); + +/** + * @brief A structure for item in the sorted list. + */ +struct nrf_sortlist_item_s +{ + nrf_sortlist_item_t * p_next; /* Pointer to the next item in the list. */ +}; + +/** + * @brief Sorted list instance control block. + * + * Control block contains instance data which must be located in read/write memory. + */ +typedef struct +{ + nrf_sortlist_item_t * p_head; /* List head.*/ +} nrf_sortlist_cb_t; +/** + * @brief Structure for sorted list instance. + * + * Instance can be placed in read only memory. + */ +typedef struct +{ + char * p_name; /* List name. */ + nrf_sortlist_cb_t * p_cb; /* List head.*/ + nrf_sortlist_compare_func_t compare_func; /* Function used for comparison. */ +} nrf_sortlist_t; + +/** + * @brief Macro for conditionally including instance name. + * + * @param _name Instance name. + */ +#define NRF_SORTLIST_INST_NAME(_name) (NRF_LOG_ENABLED && NRF_SORTLIST_CONFIG_LOG_ENABLED) ? \ + STRINGIFY(_name) : NULL +/** + * @brief Macro for defining a sorted list instance. + * + * @param _name Instance name. + * @param _compare_func Pointer to a compare function. + */ +#define NRF_SORTLIST_DEF(_name, _compare_func) \ + static nrf_sortlist_cb_t CONCAT_2(_name,_sortlist_cb) = { \ + .p_head = NULL \ + }; \ + static const nrf_sortlist_t _name = { \ + .p_name = NRF_SORTLIST_INST_NAME(_name), \ + .p_cb = &CONCAT_2(_name,_sortlist_cb), \ + .compare_func = _compare_func, \ + } + +/** + * @brief Function for adding an element into a list. + * + * New item will be placed in the queue based on the compare function. + * + * @param p_list List instance. + * @param p_item Item. + */ +void nrf_sortlist_add(nrf_sortlist_t const * p_list, nrf_sortlist_item_t * p_item); + +/** + * @brief Function for removing an item from the list head. + * + * @param p_list List instance. + * + * @return Pointer to the item which was on the list head. + */ +nrf_sortlist_item_t * nrf_sortlist_pop(nrf_sortlist_t const * p_list); + +/** + * @brief Function for getting (without removing) an item from the list head. + * + * @param p_list List instance. + * + * @return Pointer to the item which is on the list head. + */ +nrf_sortlist_item_t const * nrf_sortlist_peek(nrf_sortlist_t const * p_list); + +/** + * @brief Function for iterating over the list. + * + * @param p_item Item in the list. + * + * @return Pointer to the next item in the list. + */ +nrf_sortlist_item_t const * nrf_sortlist_next(nrf_sortlist_item_t const * p_item); + +/** + * @brief Function for removing an item from the queue. + * + * @param p_list List instance. + * @param p_item Item. + * + * @retval true Item was found and removed. + * @retval false Item not found in the list. + */ +bool nrf_sortlist_remove(nrf_sortlist_t const * p_list, nrf_sortlist_item_t * p_item); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif //NRF_SORTLIST_H + diff --git a/components/libraries/stack_info/nrf_stack_info.h b/components/libraries/stack_info/nrf_stack_info.h new file mode 100644 index 0000000..8e8f942 --- /dev/null +++ b/components/libraries/stack_info/nrf_stack_info.h @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup nrf_stack_info Stack info functions and definitions + * @{ + * @ingroup app_common + * + * @brief Functions and definitions used to obtain information about the state of the stack. + */ + +#ifndef NRF_STACK_INFO_H__ +#define NRF_STACK_INFO_H__ + +#include +#include +#include "compiler_abstraction.h" +#include "app_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Top (highest) stack address. + */ +#define NRF_STACK_INFO_TOP ((uint32_t)STACK_TOP) + + +/** + * @brief Base (lowest) stack address. + */ +#define NRF_STACK_INFO_BASE ((uint32_t)STACK_BASE) + + +/** + * @brief Function to get the current stack pointer value. + * + * @return Current stack pointer value. + */ +#define NRF_STACK_INFO_GET_SP() ((uint32_t)GET_SP()) + + +__STATIC_INLINE size_t nrf_stack_info_get_available(void); +__STATIC_INLINE size_t nrf_stack_info_get_depth(void); +__STATIC_INLINE bool nrf_stack_info_overflowed(void); +__STATIC_INLINE bool nrf_stack_info_is_on_stack(void const * const p_address); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +/** + * @brief Calculate the available (free) space on the stack. + * + * @return Number of available bytes on the stack. + */ + __STATIC_INLINE size_t nrf_stack_info_get_available(void) +{ + uint32_t sp = NRF_STACK_INFO_GET_SP(); + if (sp > NRF_STACK_INFO_BASE) + { + return (size_t)(sp - NRF_STACK_INFO_BASE); + } + + // Stack overflow + return 0; +} + + +/** + * @brief Calculate the current stack depth (occupied space). + * + * @return Current stack depth in bytes. + */ +__STATIC_INLINE size_t nrf_stack_info_get_depth(void) +{ + return (size_t)(NRF_STACK_INFO_TOP - NRF_STACK_INFO_GET_SP()); +} + + +/** + * @brief Function for checking if the stack is currently overflowed. + * + * @details This function checks if the stack is currently in an overflowed by comparing the stack + * pointer with the stack base address. Intended to be used to be used to ease debugging. + * + * @return true if stack is currently overflowed, false otherwise. + */ + __STATIC_INLINE bool nrf_stack_info_overflowed(void) + { + if (NRF_STACK_INFO_GET_SP() < NRF_STACK_INFO_BASE) + { + return true; + } + + return false; + } + + +/** + * @brief Function for checking if provided address is located in stack space. + * + * @param[in] p_address Address to be checked. + * + * @return true if address is in stack space, false otherwise. + */ +__STATIC_INLINE bool nrf_stack_info_is_on_stack(void const * const p_address) +{ + if (((uint32_t)p_address >= NRF_STACK_INFO_BASE) && ((uint32_t)p_address < NRF_STACK_INFO_TOP)) + { + return true; + } + + return false; +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + +#ifdef __cplusplus +} +#endif + +#endif // NRF_STACK_INFO_H__ + +/**@} */ diff --git a/components/libraries/strerror/nrf_strerror.c b/components/libraries/strerror/nrf_strerror.c new file mode 100644 index 0000000..d6e7744 --- /dev/null +++ b/components/libraries/strerror/nrf_strerror.c @@ -0,0 +1,161 @@ +/** + * Copyright (c) 2011 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_STRERROR) +#include "nrf_strerror.h" + +/** + * @brief Macro for adding an entity to the description array. + * + * Macro that helps to create a single entity in the description array. + */ +#define NRF_STRERROR_ENTITY(mnemonic) {.code = mnemonic, .name = #mnemonic} + +/** + * @brief Array entity element that describes an error. + */ +typedef struct +{ + ret_code_t code; /**< Error code. */ + char const * name; /**< Descriptive name (the same as the internal error mnemonic). */ +}nrf_strerror_desc_t; + +/** + * @brief Unknown error code. + * + * The constant string used by @ref nrf_strerror_get when the error description was not found. + */ +static char const m_unknown_str[] = "Unknown error code"; + +/** + * @brief Array with error codes. + * + * Array that describes error codes. + * + * @note It is required for this array to have error codes placed in ascending order. + * This condition is checked in automatic unit test before the release. + */ +static nrf_strerror_desc_t const nrf_strerror_array[] = +{ + NRF_STRERROR_ENTITY(NRF_SUCCESS), + NRF_STRERROR_ENTITY(NRF_ERROR_SVC_HANDLER_MISSING), + NRF_STRERROR_ENTITY(NRF_ERROR_SOFTDEVICE_NOT_ENABLED), + NRF_STRERROR_ENTITY(NRF_ERROR_INTERNAL), + NRF_STRERROR_ENTITY(NRF_ERROR_NO_MEM), + NRF_STRERROR_ENTITY(NRF_ERROR_NOT_FOUND), + NRF_STRERROR_ENTITY(NRF_ERROR_NOT_SUPPORTED), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_PARAM), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_STATE), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_LENGTH), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_FLAGS), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_DATA), + NRF_STRERROR_ENTITY(NRF_ERROR_DATA_SIZE), + NRF_STRERROR_ENTITY(NRF_ERROR_TIMEOUT), + NRF_STRERROR_ENTITY(NRF_ERROR_NULL), + NRF_STRERROR_ENTITY(NRF_ERROR_FORBIDDEN), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_ADDR), + NRF_STRERROR_ENTITY(NRF_ERROR_BUSY), +#ifdef NRF_ERROR_CONN_COUNT + NRF_STRERROR_ENTITY(NRF_ERROR_CONN_COUNT), +#endif +#ifdef NRF_ERROR_RESOURCES + NRF_STRERROR_ENTITY(NRF_ERROR_RESOURCES), +#endif + + /* SDK Common errors */ + NRF_STRERROR_ENTITY(NRF_ERROR_MODULE_NOT_INITIALIZED), + NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_INIT_FAILED), + NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_LOCK_FAILED), + NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_UNLOCK_FAILED), + NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_COND_INIT_FAILED), + NRF_STRERROR_ENTITY(NRF_ERROR_MODULE_ALREADY_INITIALIZED), + NRF_STRERROR_ENTITY(NRF_ERROR_STORAGE_FULL), + NRF_STRERROR_ENTITY(NRF_ERROR_API_NOT_IMPLEMENTED), + NRF_STRERROR_ENTITY(NRF_ERROR_FEATURE_NOT_ENABLED), + NRF_STRERROR_ENTITY(NRF_ERROR_IO_PENDING), + + /* TWI error codes */ + NRF_STRERROR_ENTITY(NRF_ERROR_DRV_TWI_ERR_OVERRUN), + NRF_STRERROR_ENTITY(NRF_ERROR_DRV_TWI_ERR_ANACK), + NRF_STRERROR_ENTITY(NRF_ERROR_DRV_TWI_ERR_DNACK), + + /* IPSP error codes */ + NRF_STRERROR_ENTITY(NRF_ERROR_BLE_IPSP_RX_PKT_TRUNCATED), + NRF_STRERROR_ENTITY(NRF_ERROR_BLE_IPSP_CHANNEL_ALREADY_EXISTS), + NRF_STRERROR_ENTITY(NRF_ERROR_BLE_IPSP_LINK_DISCONNECTED), + NRF_STRERROR_ENTITY(NRF_ERROR_BLE_IPSP_PEER_REJECTED) +}; + + +char const * nrf_strerror_get(ret_code_t code) +{ + char const * p_ret = nrf_strerror_find(code); + return (p_ret == NULL) ? m_unknown_str : p_ret; +} + +char const * nrf_strerror_find(ret_code_t code) +{ + nrf_strerror_desc_t const * p_start; + nrf_strerror_desc_t const * p_end; + p_start = nrf_strerror_array; + p_end = nrf_strerror_array + ARRAY_SIZE(nrf_strerror_array); + + while (p_start < p_end) + { + nrf_strerror_desc_t const * p_mid = p_start + ((p_end - p_start) / 2); + ret_code_t mid_c = p_mid->code; + if (mid_c > code) + { + p_end = p_mid; + } + else if (mid_c < code) + { + p_start = p_mid + 1; + } + else + { + return p_mid->name; + } + } + return NULL; +} + +#endif /* NRF_STRERROR enabled */ diff --git a/components/libraries/strerror/nrf_strerror.h b/components/libraries/strerror/nrf_strerror.h new file mode 100644 index 0000000..cc3744f --- /dev/null +++ b/components/libraries/strerror/nrf_strerror.h @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @defgroup nrf_strerror Error code to string converter + * @ingroup app_common + * + * @brief Module for converting error code into a printable string. + * @{ + */ +#ifndef NRF_STRERROR_H__ +#define NRF_STRERROR_H__ + +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for getting a printable error string. + * + * @param code Error code to convert. + * + * @note This function cannot fail. + * For the function that may fail with error translation, see @ref nrf_strerror_find. + * + * @return Pointer to the printable string. + * If the string is not found, + * it returns a simple string that says that the error is unknown. + */ +char const * nrf_strerror_get(ret_code_t code); + +/** + * @brief Function for finding a printable error string. + * + * This function gets the error string in the same way as @ref nrf_strerror_get, + * but if the string is not found, it returns NULL. + * + * @param code Error code to convert. + * @return Pointer to the printable string. + * If the string is not found, NULL is returned. + */ +char const * nrf_strerror_find(ret_code_t code); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_STRERROR_H__ */ diff --git a/components/libraries/svc/nrf_svc_function.h b/components/libraries/svc/nrf_svc_function.h new file mode 100644 index 0000000..3fd3a07 --- /dev/null +++ b/components/libraries/svc/nrf_svc_function.h @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup sdk_nrf_svc_function Supervisor function + * @{ + * @ingroup app_common + * + * @brief Macros to create Supervisor functions. + */ + +#ifndef NRF_SVC_FUNCTION_H__ +#define NRF_SVC_FUNCTION_H__ + +#include +#include "nrf_section.h" +#include "app_util.h" +#include "nrf_svci.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @brief Function to be called from an SVC handler. + * + * @warning This function prototype has no arguments. It will be cast to a function prototype + * that has 0 to 4 arguments. 4 arguments is the highest number of allowed arguments in + * a Supervisor call. + * + * @warning The nrf_svc_func_t function prototype should not have void as parameter list as there + * will be 0 to 4 arguments after casting. + */ +typedef uint32_t (*nrf_svc_func_t)(); + +/** @brief Type holding the SVC number, SVCI number, and the pointer to the corresponding handler + * function. + * + * @note The function that is pointed to must not change version. + */ +typedef struct +{ + uint32_t svc_num; /**< Supervisor call number (actually 8-bit, padded for alignment). */ + uint32_t svci_num; /**< Supervisor call indirect number. */ + nrf_svc_func_t func_ptr; +} nrf_svc_func_reg_t; + + +// Verify that the size of nrf_svc_func_t is aligned to make sure it can be used in nrf_section. +STATIC_ASSERT(sizeof(nrf_svc_func_reg_t) % 4 == 0); + + +/** @brief Macro for registering a structure holding SVC number and SVC handler + * function pointer. + * + * @details This macro places a variable in a section named "svc_data" that + * the SVC handler uses during regular operation. + * + * @note This macro must be invoked from a source file. There should only be one + * registration by a given SVC number. SVC number 0 (zero) is invalid input + * and will cause a compile time assertion. + * + * @param[in] name Name of the structure. Logically accessible from the source file. + * @param[in] svc_number SVC number to register. + * @param[in] func Function to call for a given SVC number. + * + * @retval Variable registration in @ref lib_section_vars named svc_data. + */ +#define NRF_SVC_FUNCTION_REGISTER(svc_number, name, func) \ +STATIC_ASSERT(svc_number != 0); \ +NRF_SECTION_ITEM_REGISTER(svc_data, nrf_svc_func_reg_t const name) = \ +{ \ + .svc_num = svc_number, \ + .svci_num = NRF_SVCI_SVC_NUM_INVALID, \ + .func_ptr = (nrf_svc_func_t)func \ +} + + +/** @brief Macro for registering a structure holding SVC number, SVCI number, and SVCI handler + * function pointer. + * + * @details This macro places a variable in a section named "svc_data" that + * the SVC handler uses during regular operation. + * + * @note This macro must be invoked from a source file. There should only be one registration + * for a given SVC indirect number. + * + * @param[in] name Name of the structure. Logically accessible from the source file. + * @param[in] svci_number SVC indirect number to register. + * @param[in] func Function to call for a given SVC indirect number. + * + * @retval Variable registration in @ref lib_section_vars named svc_data. + */ +#define NRF_SVCI_FUNCTION_REGISTER(svci_number, name, func) \ +NRF_SECTION_ITEM_REGISTER(svc_data, nrf_svc_func_reg_t const name) = \ +{ \ + .svc_num = NRF_SVCI_SVC_NUM, \ + .svci_num = svci_number, \ + .func_ptr = (nrf_svc_func_t)func \ +} + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SVC_FUNCTION_H__ + +/** @} */ diff --git a/components/libraries/svc/nrf_svc_handler.c b/components/libraries/svc/nrf_svc_handler.c new file mode 100644 index 0000000..940748f --- /dev/null +++ b/components/libraries/svc/nrf_svc_handler.c @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include "nrf_svc_function.h" +#include "nrf_error.h" + +//lint -esym(526, svc_dataBase) -esym(526, svc_dataLimit) +NRF_SECTION_DEF(svc_data, const nrf_svc_func_t); +#define SVC_DATA_SECTION_ITEM_GET(i) NRF_SECTION_ITEM_GET(svc_data, nrf_svc_func_reg_t, (i)) +#define SVC_DATA_SECTION_ITEM_COUNT NRF_SECTION_ITEM_COUNT(svc_data, nrf_svc_func_reg_t) + + +#ifdef __GNUC__ +// Prevent GCC from removing this function (called from assembly branch) +void nrf_svc_handler_c(uint32_t* p_svc_args) __attribute__((used)); +#endif + + + +/**@brief Function for handling second stage of Supervisor Calls (SVC). +* +* @details The function will use loop through the registered svc functions stored +* in the named section "svc_data" and will call the registered function +* if the svn_num corresponds with the registration. +* +* @param[in] p_svc_args Argument list for the SVC. +* +* @return This function returns by updating p_svc_arsg[0]. This will be reported back to the caller of SVC +* @ref NRF_ERROR_SVC_HANDLER_MISSING is returned if no SVC handler is implemented for the +* provided svc_num. +*/ +void nrf_svc_handler_c(uint32_t* p_svc_args) +{ + uint32_t const num_funcs = SVC_DATA_SECTION_ITEM_COUNT; + bool handled = false; + uint8_t const svc_num = ((uint8_t *)p_svc_args[6])[-2]; + uint32_t svci_num = NRF_SVCI_SVC_NUM_INVALID; + + if (svc_num == NRF_SVCI_SVC_NUM) + { + // load the stacked R12 as the svci_num + svci_num = p_svc_args[4]; + } + + for (uint32_t i = 0; i < num_funcs; i++) + { + nrf_svc_func_reg_t const * func_reg = SVC_DATA_SECTION_ITEM_GET(i); + if (func_reg->svc_num != svc_num) + { + continue; + } + + if (svci_num != NRF_SVCI_SVC_NUM_INVALID && func_reg->svci_num != svci_num) + { + continue; + } + + // Return value is placed in R0 + p_svc_args[0] = func_reg->func_ptr(p_svc_args[0], p_svc_args[1], p_svc_args[2], p_svc_args[3]); + handled = true; + break; + } + + if (handled == false) + { + // Return value is placed in R0 + p_svc_args[0] = NRF_ERROR_SVC_HANDLER_MISSING; + } +} + +/**@brief Function for handling the first stage of Supervisor Calls (SVC) in assembly. +* +* @details The function will use the link register (LR) to determine the stack (PSP or MSP) to be +* used and then decode the SVC number afterwards. After decoding the SVC number, +* @ref C_SVC_Handler is called for further processing of the SVC. +*/ +#if defined ( __CC_ARM ) +__ASM void SVC_Handler(void) +{ + tst lr, #4 ; Test bit 2 of EXT_RETURN to see if MSP or PSP is used + ite eq ; + mrseq r0, MSP ; If equal, copy stack pointer from MSP + mrsne r0, PSP ; If not equal, copy stack pointer from PSP + B __cpp(nrf_svc_handler_c) ; Call C-implementation of handler. Exception stack frame in R0 + ALIGN 4 ; Protect with alignment +} +#elif defined ( __GNUC__ ) +void __attribute__((naked)) SVC_Handler(void) +{ + __ASM volatile + ( + "tst lr, #4\t\n" // Test bit 2 of EXT_RETURN to see if MSP or PSP is used + "ite eq\t\n" // + "mrseq r0, MSP\t\n" // Move MSP into R0. + "mrsne r0, PSP\t\n" // Move PSP into R0. + "b nrf_svc_handler_c\t\n" // Call C-implementation of handler. Exception stack frame in R0 + ".align\t\n" // Protect with alignment + ); +} +#elif defined ( __ICCARM__ ) +void SVC_Handler(void) +{ + __ASM volatile + ( + "tst lr, #4\t\n" // Test bit in link register responsible for stack indication. + "ite eq\t\n" // Test bit 2 of EXT_RETURN to see if MSP or PSP is used + "mrseq r0, MSP\t\n" // Move MSP into R0. + "mrsne r0, PSP\t\n" // Move PSP into R0. + "b nrf_svc_handler_c\t\n" : // Call C-implementation of handler. Exception stack frame in R0 + ); +} +#else + +#error Compiler not supported. + +#endif diff --git a/components/libraries/svc/nrf_svci.h b/components/libraries/svc/nrf_svci.h new file mode 100644 index 0000000..396a1d2 --- /dev/null +++ b/components/libraries/svc/nrf_svci.h @@ -0,0 +1,300 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup sdk_nrf_svci Supervisor instructions with indirect number + * @{ + * @ingroup app_common + * + * @brief Macros to create Supervisor instructions using indirect number. + */ + +#ifndef NRF_SVCI_H__ +#define NRF_SVCI_H__ + +#include "stdint.h" +#include "compiler_abstraction.h" +#include "app_util.h" + + + + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_SVCI_SVC_NUM 0 /**< SVC number used for all SVCI functions. */ +#define NRF_SVCI_SVC_NUM_INVALID (0xFFFFFFFF) /**< Invalid SVCI number. */ + +#ifdef __cplusplus + #define GCC_CAST_CPP (uint16_t) +#else + #define GCC_CAST_CPP +#endif + +#if (__LINT__ != 1) + +#if defined (__CC_ARM) + + #define SVCI_DECL(svci_num, return_type, function_name, ...) \ + return_type __svc_indirect(NRF_SVCI_SVC_NUM) \ + svci_ ## function_name(uint32_t _svci_num, ##__VA_ARGS__); + + #define SVCI_DECL_0(svci_num, return_type, function_name) \ + return_type __svc_indirect(NRF_SVCI_SVC_NUM) \ + svci_ ## function_name(uint32_t _svci_num); + + #define SVCI_0(svci_num, return_type, function_name) \ + SVCI_DECL_0(svci_num, return_type, function_name) \ + static __INLINE return_type function_name(void) \ + { \ + return svci_ ## function_name(svci_num); \ + } + + #define SVCI_1(svci_num, return_type, function_name, p0t, p0n) \ + SVCI_DECL(svci_num, return_type, function_name, p0t p0n) \ + static __INLINE return_type function_name(p0t p0n) \ + { \ + return svci_ ## function_name(svci_num, p0n); \ + } + + #define SVCI_2(svci_num, return_type, function_name, p0t, p0n, p1t, p1n) \ + SVCI_DECL(svci_num, return_type, function_name, p0t p0n, p1t p1n) \ + static __INLINE return_type function_name(p0t p0n, p1t p1n) \ + { \ + return svci_ ## function_name(svci_num, p0n, p1n); \ + } + + #define SVCI_3(svci_num, return_type, function_name, p0t, p0n, p1t, p1n, p2t, p2n) \ + SVCI_DECL(svci_num, return_type, function_name, p0t p0n, p1t p1n, p2t p2n) \ + static __INLINE return_type function_name(p0t p0n, p1t p1n, p2t p2n) \ + { \ + return svci_ ## function_name(svci_num, p0n, p1n, p2n); \ + } + + #define SVCI_4(svci_num, return_type, function_name, p0t, p0n, p1t, p1n, p2t, p2n, p3t, p3n) \ + SVCI_DECL(svci_num, return_type, function_name, p0t p0n, p1t p1n, p2t p2n, p3t p3n) \ + static __INLINE return_type function_name(p0t p0n, p1t p1n, p2t p2n, p3t p3n) \ + { \ + return svci_ ## function_name(svci_num, p0n, p1n, p2n, p3n); \ + } + +#else + +#if defined (__GNUC__) + + #define SVCI_DECL_0(svci_num, return_type, function_name) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wreturn-type\"") \ + __attribute__((naked, unused)) \ + static return_type svci_ ## function_name(void) \ + { \ + /* Do the SuperVisor call by using svc instruction with \ + R12 containing the SVCI number */ \ + __ASM __volatile \ + ( \ + " ldr r12, =%0 \n" \ + " svc %1 \n" \ + " bx lr \n" \ + " .ltorg" \ + : /* output */ \ + : /* input */ \ + "X"(svci_num), \ + "I"(GCC_CAST_CPP NRF_SVCI_SVC_NUM) \ + : /* clobbers */ \ + "r12" \ + ); \ + } \ + _Pragma("GCC diagnostic pop") + + #define SVCI_DECL(svci_num, return_type, function_name, ...) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wreturn-type\"") \ + __attribute__((naked, unused)) \ + static return_type svci_ ## function_name(__VA_ARGS__) \ + { \ + /* Do the SuperVisor call by using svc instruction with \ + R12 containing the SVCI number */ \ + __ASM __volatile \ + ( \ + " ldr.w r12, =%0 \n" \ + " svc %1 \n" \ + " bx lr \n" \ + " .ltorg" \ + : /* output */ \ + : /* input */ \ + "X"(svci_num), \ + "I"(GCC_CAST_CPP NRF_SVCI_SVC_NUM) \ + : /* clobbers */ \ + "r12" \ + ); \ + } \ + _Pragma("GCC diagnostic pop") + +#elif defined (__ICCARM__) + + #define SVCI_DECL_0(svci_num, return_type, function_name) \ + /* Suppress return value warning. */ \ + _Pragma("diag_suppress=Pe940") \ + static __root return_type svci_ ## function_name(void) \ + { \ + /* Do the SuperVisor call by using svc instruction with \ + R12 containing the SVCI number */ \ + __ASM volatile \ + ( \ + " mov r12, %0 \n" \ + " svc %1 \n" \ + : /*no output*/ \ + : "r" (svci_num), "I" (NRF_SVCI_SVC_NUM) \ + : \ + ); \ + } + + #define SVCI_DECL(svci_num, return_type, function_name, ...) \ + /* Suppress return value warning. */ \ + _Pragma("diag_suppress=Pe940") \ + static __root return_type svci_ ## function_name(__VA_ARGS__) \ + { \ + /* We stack r0-r3 as r0 is used to set high register (r12) \ + This CODE MUST BE IN ITS OWN __ASM BLOCK! */ \ + __ASM volatile ( "push {r0, r1, r2, r3}\n\t" ); \ + /* Set R12 to the svc_number, this will use r0 as indirect \ + * storage. Pop r0-r3 to reset value before SVCI. */ \ + __ASM volatile \ + ( \ + " mov r12, %0 \n" \ + " pop {r0, r1, r2, r3} \n" \ + : /*no output */ \ + : "r" (svci_num) \ + : \ + ); \ + /* Do the SuperVisor call by using svc instruction with \ + R12 containing the SVCI number */ \ + __ASM volatile \ + ( \ + " svc %0 \n" \ + " bx lr \n" \ + : /*no output*/ \ + : "I" (NRF_SVCI_SVC_NUM) \ + : \ + ); \ + } +#else // Not defined (__ICCARM__) or defined (__GNUC__) + + #error Unsupported compiler for SVCI interface + +#endif // Not defined (__ICCARM__) or defined (__GNUC__) + + #define SVCI_0(svci_num, return_type, function_name) \ + SVCI_DECL_0(svci_num, return_type, function_name) \ + static __INLINE return_type function_name(void) \ + { \ + return svci_ ## function_name(); \ + } + + #define SVCI_1(svci_num, return_type, function_name, p0t, p0n) \ + SVCI_DECL(svci_num, return_type, function_name, p0t p0n) \ + static __INLINE return_type function_name(p0t p0n) \ + { \ + return svci_ ## function_name(p0n); \ + } + + #define SVCI_2(svci_num, return_type, function_name, p0t, p0n, p1t, p1n) \ + SVCI_DECL(svci_num, return_type, function_name, p0t p0n, p1t p1n) \ + static __INLINE return_type function_name(p0t p0n, p1t p1n) \ + { \ + return svci_ ## function_name(p0n, p1n); \ + } + + #define SVCI_3(svci_num, return_type, function_name, p0t, p0n, p1t, p1n, p2t, p2n) \ + SVCI_DECL(svci_num, return_type, function_name, p0t p0n, p1t p1n, p2t p2n) \ + static __INLINE return_type function_name(p0t p0n, p1t p1n, p2t p2n) \ + { \ + return svci_ ## function_name(p0n, p1n, p2n); \ + } + + #define SVCI_4(svci_num, return_type, function_name, p0t, p0n, p1t, p1n, p2t, p2n, p3t, p3n) \ + SVCI_DECL(svci_num, return_type, function_name, p0t p0n, p1t p1n, p2t p2n, p3t p3n) \ + static __INLINE return_type function_name(p0t p0n, p1t p1n, p2t p2n, p3t p3n) \ + { \ + return svci_ ## function_name(p0n, p1n, p2n, p3n); \ + } + +#endif // Not __CC_ARM + +#define VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, N, ...) N +#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 4, 4, 3, 3, 2, 2, 1, 1, 0) + +#ifdef SVCALL_INDIRECT_AS_NORMAL_FUNCTION + +#define SVCI(svci_num, return_type, function_name, ...) \ + return_type function_name(##__VA_ARGS__) + +#else + + +#define SVCI_IMPLI(count, svci_num, return_type, function_name, ...) \ + SVCI##_##count (svci_num, return_type, function_name, ##__VA_ARGS__) + +#define SVCI_IMPL(count, svci_num, return_type, function_name, ...) \ + SVCI_IMPLI(count, svci_num, return_type, function_name, ##__VA_ARGS__) + +#define SVCI(svci_num, return_type, function_name, ...) \ + SVCI_IMPL(VA_NARGS(__VA_ARGS__), svci_num, return_type, function_name, ##__VA_ARGS__) + + +#endif // SVCALL_INDIRECT_AS_NORMAL_FUNCTION + +#else // (__LINT__ == 1) + #define SVCI(svci_num, return_type, function_name, ...) +#endif + +#ifdef __cplusplus +} +#endif + + + +#endif // NRF_SVCI_H__ + + + + +/** @} */ diff --git a/components/libraries/svc/nrf_svci_async_function.h b/components/libraries/svc/nrf_svci_async_function.h new file mode 100644 index 0000000..0956a7f --- /dev/null +++ b/components/libraries/svc/nrf_svci_async_function.h @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup sdk_nrf_svci_async_function Asynchronous Supervisor function interface + * @{ + * @ingroup app_common + * + * @brief Macros to create Asynchronous Supervisor interface functions. + */ + +#ifndef NRF_SVC_ASYNC_FUNCTION_H__ +#define NRF_SVC_ASYNC_FUNCTION_H__ + +#include "nrf_svci.h" +#include "nrf_svci_async_handler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Macro for creating type definition for SVCI interface init function. + * + * @warning Do not call this macro directly! Use @ref NRF_SVCI_ASYNC_FUNC_DECLARE instead. + * + * @param[in] name Name of async request function. Will be appended with _async_fn_t. + * @param[in] param_type Parameter type. + * @param[in] state_type State type. + * + * @retval Type definition a named SVCI async init function. + */ +#define NRF_SVCI_ACYNC_FUNC_TYPEDEF(name, param_type, state_type) \ +typedef uint32_t (* name ## _async_fn_t)(param_type * p_param, state_type * p_state) + + +/**@brief Macro for creating type definition for SVCI interface event function. + * + * @warning Do not call this macro directly! Use @ref NRF_SVCI_ASYNC_FUNC_DECLARE instead. + * + * @details Calling this function with sys-events will report @ref NRF_ERROR_BUSY until + * the asynchronous calls is finished, at which time it will report either + * NRF_SUCCESS or any another error-message. + * + * @param[in] name Name of the event function. Will be appended with _event_fn_t + * @param[in] state_type Type parameter for the state. + * + * @retval Type definition for a named SVCI async event function. + */ +#define NRF_SVCI_ASYNC_EVENT_FUNC_TYPEDEF(name, state_type) \ +typedef uint32_t (* name ## _event_fn_t)(uint32_t sys_evt, state_type * p_state) + + +/**@brief Macro for creating a declaration of a named async function for the SVCI interface. + * + * @details The async interface provides a method to call into a external application + * through the SVCI interface without relying on allocated or reserved memory inside the + * external application. + * + * This macro declares variables and function types in use by the async SVCI interface. + * + * @note This is intended to be invoked in a header file shared by both the + * caller and the recipient (handler). + * + * @param[in] svci_num SVC indirect number. + * @param[in] name Name of the async function. + * @param[in] param_type Type of the param used for the async interface. + * @param[in] state_type Type of the state used for the async interface. + * + * @retval A type definition of NAME_svc_async_t to be used for async access + * through the SVCI interface. + */ +#define NRF_SVCI_ASYNC_FUNC_DECLARE(svci_num, \ + name, \ + param_type, \ + state_type) \ +/*lint --e{19} */ \ +NRF_SVCI_ACYNC_FUNC_TYPEDEF(name, param_type, state_type); \ +NRF_SVCI_ASYNC_EVENT_FUNC_TYPEDEF(name, state_type); \ + \ +typedef struct \ +{ \ + name ## _async_fn_t async_func; \ + name ## _event_fn_t sys_evt_handler; \ + state_type state; \ +} name ## _svci_async_t; + + + +//lint -save --e{10, 19, 40, 102} -esym(526, *_init) -esym(628, *_init) + +/**@brief Macro for defining a named SVCI async interface. + * + * @details The async interface provides a method to call into an external application + * through the SVCI interface without relying on allocated or reserved memory inside the + * external application. + * + * Running this macro creates a defintion of the structure that holds the + * information about the async function, the event handler, and the state. + * + * Running this macro also defines convenience functions to the SVCI interface. + * + * The available functions are: + * -NAME_init - Function to call to set up the async SVCI interface. + * -NAME - Function to call the async SVCI interface. + * -NAME_on_sys_event - Function to report sys events to the async + * SVCI interface. + * -NAME_is_initialized - Function to check if the async SVCI interface is + * initialized and ready to use. + * + * @note Invoking this macro is only possible in a source file as the macro creates + * a static variable for the async interface as well as static functions to call + * into the async interface. + * + * @param[in] svci_num SVC indirect number. + * @param[in] name Name of the async function. + * @param[in] param_type Type of the param used for the async interface. + * + * @retval Instance of the async SVCI interface and convenience functions for using it. + */ +#define NRF_SVCI_ASYNC_FUNC_DEFINE(svci_num, name, param_type) \ + \ +SVCI(svci_num, uint32_t, name ## _svci_async_init, name ## _svci_async_t *, p_async); \ +static name ## _svci_async_t name ## _svci_async_def = {0}; \ + \ +static __INLINE uint32_t name ## _init (void) \ +{ \ + return name ## _svci_async_init(&name ## _svci_async_def); \ +} \ + \ +static __INLINE uint32_t name(param_type * p_param) \ +{ \ + return name ## _svci_async_def.async_func(p_param, &name ## _svci_async_def.state); \ +} \ + \ +static __INLINE uint32_t name ## _on_sys_evt(uint32_t sys_evt) \ +{ \ + return name ## _svci_async_def.sys_evt_handler(sys_evt, &name ## _svci_async_def.state); \ +} \ + \ +static __INLINE uint32_t name ## _is_initialized(void) \ +{ \ + return (name ## _svci_async_def.async_func != NULL && \ + name ## _svci_async_def.sys_evt_handler != NULL ); \ +} + +//lint -restore + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SVC_ASYNC_FUNCTION_H__ + +/** @} */ diff --git a/components/libraries/svc/nrf_svci_async_handler.h b/components/libraries/svc/nrf_svci_async_handler.h new file mode 100644 index 0000000..64a3a1f --- /dev/null +++ b/components/libraries/svc/nrf_svci_async_handler.h @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup sdk_nrf_svci_async_handler Asynchronous Supervisor handler functions + * @{ + * @ingroup app_common + * + * @brief Macros to create Asynchronous Supervisor interface handler functions. + */ + +#ifndef NRF_SVCI_ASYNC_HANDLER_H__ +#define NRF_SVCI_ASYNC_HANDLER_H__ + +#include "nrf_svc_function.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Macro for creating a registration for an async handler for the SVCI interface + * + * @details Calling this macro will register a SVCI function handler using @ref + * NRF_SVCI_FUNCTION_REGISTER + * + * @note This macro must be invoked from a source file as it declares static functions + * to be implemented and because it creates a @ref lib_section_vars registration to + * SVCI interface which is intended to be unique. + * + * @param[in] svci_num SVC indirect number. + * @param[in] name Name of the async function. + * @param[in] param_type Type of the param to send when running the async interface. + * @param[in] state_type Type of the state to be called together with sys_event. + * + * @retval Static declarations to handler functions to be implemented in the form NAME_handler + * NAME_on_call, and NAME_on_sys_event. + */ +#define NRF_SVCI_ASYNC_HANDLER_CREATE(svci_num, \ + name, \ + param_type, \ + state_type) \ + \ +static uint32_t name ## _handler(name ## _svci_async_t * p_async); \ +static uint32_t name ## _on_call(param_type * p_param, state_type * p_state); \ +static uint32_t name ## _on_sys_evt(uint32_t sys_event, state_type * p_state); \ + \ +NRF_SVCI_FUNCTION_REGISTER(svci_num, name ## _var, name ## _handler) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SVCI_ASYNC_HANDLER_H__ + +/** @} */ diff --git a/components/libraries/timer/app_timer.c b/components/libraries/timer/app_timer.c new file mode 100644 index 0000000..679eebe --- /dev/null +++ b/components/libraries/timer/app_timer.c @@ -0,0 +1,1075 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(APP_TIMER) +#include "app_timer.h" +#include +#include "nrf.h" +#include "nrf_peripherals.h" +#include "nrf_soc.h" +#include "app_error.h" +#include "nrf_delay.h" +#include "app_util_platform.h" +#if APP_TIMER_CONFIG_USE_SCHEDULER +#include "app_scheduler.h" +#endif + +#define RTC1_IRQ_PRI APP_TIMER_CONFIG_IRQ_PRIORITY /**< Priority of the RTC1 interrupt (used for checking for timeouts and executing timeout handlers). */ +#define SWI_IRQ_PRI APP_TIMER_CONFIG_IRQ_PRIORITY /**< Priority of the SWI interrupt (used for updating the timer list). */ + +// The current design assumes that both interrupt handlers run at the same interrupt level. +// If this is to be changed, protection must be added to prevent them from interrupting each other +// (e.g. by using guard/trigger flags). +STATIC_ASSERT(RTC1_IRQ_PRI == SWI_IRQ_PRI); + +#define MAX_RTC_COUNTER_VAL 0x00FFFFFF /**< Maximum value of the RTC counter. */ + +#define RTC_COMPARE_OFFSET_MIN 3 /**< Minimum offset between the current RTC counter value and the Capture Compare register. Although the nRF51 Series User Specification recommends this value to be 2, we use 3 to be safer.*/ + +#define MAX_RTC_TASKS_DELAY 47 /**< Maximum delay until an RTC task is executed. */ + +#ifdef EGU_PRESENT +#define SWI_PART(_id) CONCAT_2(SWI,_id) +#define EGU_PART(_id) CONCAT_2(_EGU,_id) +#define SWI_IRQ_n(_id) CONCAT_3(SWI_PART(_id), EGU_PART(_id),_IRQn) +#define SWI_IRQ_Handler_n(_id) CONCAT_3(SWI_PART(_id), EGU_PART(_id),_IRQHandler) +#else //EGU_PRESENT +#define SWI_IRQ_n(_id) CONCAT_3(SWI,_id,_IRQn) +#define SWI_IRQ_Handler_n(_id) CONCAT_3(SWI,_id,_IRQHandler) +#endif + +#define SWI_IRQn SWI_IRQ_n(APP_TIMER_CONFIG_SWI_NUMBER) +#define SWI_IRQHandler SWI_IRQ_Handler_n(APP_TIMER_CONFIG_SWI_NUMBER) + + +#define MODULE_INITIALIZED (m_op_queue.size != 0) /**< Macro designating whether the module has been initialized properly. */ + +/**@brief Timer node type. The nodes will be used form a linked list of running timers. */ +typedef struct +{ + uint32_t ticks_to_expire; /**< Number of ticks from previous timer interrupt to timer expiry. */ + uint32_t ticks_at_start; /**< Current RTC counter value when the timer was started. */ + uint32_t ticks_first_interval; /**< Number of ticks in the first timer interval. */ + uint32_t ticks_periodic_interval; /**< Timer period (for repeating timers). */ + bool is_running; /**< True if timer is running, False otherwise. */ + app_timer_mode_t mode; /**< Timer mode. */ + app_timer_timeout_handler_t p_timeout_handler; /**< Pointer to function to be executed when the timer expires. */ + void * p_context; /**< General purpose pointer. Will be passed to the timeout handler when the timer expires. */ + void * next; /**< Pointer to the next node. */ +} timer_node_t; + +STATIC_ASSERT(sizeof(timer_node_t) == APP_TIMER_NODE_SIZE); + +/**@brief Set of available timer operation types. */ +typedef enum +{ + TIMER_USER_OP_TYPE_NONE, /**< Invalid timer operation type. */ + TIMER_USER_OP_TYPE_START, /**< Timer operation type Start. */ + TIMER_USER_OP_TYPE_STOP, /**< Timer operation type Stop. */ + TIMER_USER_OP_TYPE_STOP_ALL /**< Timer operation type Stop All. */ +} timer_user_op_type_t; + +/**@brief Structure describing a timer start operation. */ +typedef struct +{ + uint32_t ticks_at_start; /**< Current RTC counter value when the timer was started. */ + uint32_t ticks_first_interval; /**< Number of ticks in the first timer interval. */ + uint32_t ticks_periodic_interval; /**< Timer period (for repeating timers). */ + void * p_context; /**< General purpose pointer. Will be passed to the timeout handler when the timer expires. */ +} timer_user_op_start_t; + +/**@brief Structure describing a timer operation. */ +typedef struct +{ + timer_user_op_type_t op_type; /**< Id of timer on which the operation is to be performed. */ + timer_node_t * p_node; + union + { + timer_user_op_start_t start; /**< Structure describing a timer start operation. */ + } params; +} timer_user_op_t; + +/**@brief Structure describing a timer operations queue. + * + * @details This queue will hold timer operations issued by the application + * until the timer interrupt handler processes these operations. + */ +typedef struct +{ + uint8_t first; /**< Index of first entry to have been inserted in the queue (i.e. the next entry to be executed). */ + uint8_t last; /**< Index of last entry to have been inserted in the queue. */ + uint8_t size; /**< Queue size. */ + timer_user_op_t user_op_queue[APP_TIMER_CONFIG_OP_QUEUE_SIZE+1]; /**< Queue buffer. */ +} timer_op_queue_t; + +STATIC_ASSERT(sizeof(timer_op_queue_t) % 4 == 0); + +#define CONTEXT_QUEUE_SIZE_MAX (2) + +static timer_op_queue_t m_op_queue; /**< Timer operations queue. */ +static timer_node_t * mp_timer_id_head; /**< First timer in list of running timers. */ +static uint32_t m_ticks_latest; /**< Last known RTC counter value. */ +static uint32_t m_ticks_elapsed[CONTEXT_QUEUE_SIZE_MAX]; /**< Timer internal elapsed ticks queue. */ +static uint8_t m_ticks_elapsed_q_read_ind; /**< Timer internal elapsed ticks queue read index. */ +static uint8_t m_ticks_elapsed_q_write_ind; /**< Timer internal elapsed ticks queue write index. */ +static bool m_rtc1_running; /**< Boolean indicating if RTC1 is running. */ +static bool m_rtc1_reset; /**< Boolean indicating if RTC1 counter has been reset due to last timer removed from timer list during the timer list handling. */ + +#if APP_TIMER_WITH_PROFILER +static uint8_t m_max_user_op_queue_utilization; /**< Maximum observed timer user operations queue utilization. */ +#endif + +/**@brief Function for initializing the RTC1 counter. + * + * @param[in] prescaler Value of the RTC1 PRESCALER register. Set to 0 for no prescaling. + */ +static void rtc1_init(uint32_t prescaler) +{ + NRF_RTC1->PRESCALER = prescaler; + NVIC_SetPriority(RTC1_IRQn, RTC1_IRQ_PRI); +} + + +/**@brief Function for starting the RTC1 timer. + */ +static void rtc1_start(void) +{ + NRF_RTC1->EVTENSET = RTC_EVTEN_COMPARE0_Msk; + NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk; + + NVIC_ClearPendingIRQ(RTC1_IRQn); + NVIC_EnableIRQ(RTC1_IRQn); + + NRF_RTC1->TASKS_START = 1; + nrf_delay_us(MAX_RTC_TASKS_DELAY); + + m_rtc1_running = true; +} + + +/**@brief Function for stopping the RTC1 timer. + */ +static void rtc1_stop(void) +{ + NVIC_DisableIRQ(RTC1_IRQn); + + NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk; + NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk; + + NRF_RTC1->TASKS_STOP = 1; + nrf_delay_us(MAX_RTC_TASKS_DELAY); + + NRF_RTC1->TASKS_CLEAR = 1; + m_ticks_latest = 0; + nrf_delay_us(MAX_RTC_TASKS_DELAY); + + m_rtc1_running = false; +} + + +/**@brief Function for returning the current value of the RTC1 counter. + * + * @return Current value of the RTC1 counter. + */ +static __INLINE uint32_t rtc1_counter_get(void) +{ + return NRF_RTC1->COUNTER; +} + + +/**@brief Function for computing the difference between two RTC1 counter values. + * + * @return Number of ticks elapsed from ticks_old to ticks_now. + */ +static __INLINE uint32_t ticks_diff_get(uint32_t ticks_now, uint32_t ticks_old) +{ + return ((ticks_now - ticks_old) & MAX_RTC_COUNTER_VAL); +} + + +/**@brief Function for setting the RTC1 Capture Compare register 0, and enabling the corresponding + * event. + * + * @param[in] value New value of Capture Compare register 0. + */ +static __INLINE void rtc1_compare0_set(uint32_t value) +{ + NRF_RTC1->CC[0] = value; +} + + +/**@brief Function for inserting a timer in the timer list. + * + * @param[in] timer_id Id of timer to insert. + */ +static void timer_list_insert(timer_node_t * p_timer) +{ + if (mp_timer_id_head == NULL) + { + mp_timer_id_head = p_timer; + } + else + { + if (p_timer->ticks_to_expire <= mp_timer_id_head->ticks_to_expire) + { + mp_timer_id_head->ticks_to_expire -= p_timer->ticks_to_expire; + + p_timer->next = mp_timer_id_head; + mp_timer_id_head = p_timer; + } + else + { + timer_node_t * p_previous; + timer_node_t * p_current; + uint32_t ticks_to_expire; + + ticks_to_expire = p_timer->ticks_to_expire; + p_previous = mp_timer_id_head; + p_current = mp_timer_id_head; + + while ((p_current != NULL) && (ticks_to_expire > p_current->ticks_to_expire)) + { + ticks_to_expire -= p_current->ticks_to_expire; + p_previous = p_current; + p_current = p_current->next; + } + + if (p_current != NULL) + { + p_current->ticks_to_expire -= ticks_to_expire; + } + + p_timer->ticks_to_expire = ticks_to_expire; + p_timer->next = p_current; + p_previous->next = p_timer; + } + } +} + + +/**@brief Function for removing a timer from the timer queue. + * + * @param[in] timer_id Id of timer to remove. + * + * @return TRUE if Capture Compare register must be updated, FALSE otherwise. + */ +static bool timer_list_remove(timer_node_t * p_timer) +{ + timer_node_t * p_old_head; + timer_node_t * p_previous; + timer_node_t * p_current; + uint32_t timeout; + + // Find the timer's position in timer list. + p_old_head = mp_timer_id_head; + p_previous = mp_timer_id_head; + p_current = p_previous; + + while (p_current != NULL) + { + if (p_current == p_timer) + { + break; + } + p_previous = p_current; + p_current = p_current->next; + } + + // Timer not in active list. + if (p_current == NULL) + { + return false; + } + + // Timer is the first in the list + if (p_previous == p_current) + { + mp_timer_id_head = mp_timer_id_head->next; + + // No more timers in the list. Reset RTC1 in case Start timer operations are present in the queue. + if (mp_timer_id_head == NULL) + { + NRF_RTC1->TASKS_CLEAR = 1; + m_ticks_latest = 0; + m_rtc1_reset = true; + nrf_delay_us(MAX_RTC_TASKS_DELAY); + } + } + + // Remaining timeout between next timeout. + timeout = p_current->ticks_to_expire; + + // Link previous timer with next of this timer, i.e. removing the timer from list. + p_previous->next = p_current->next; + + // If this is not the last timer, increment the next timer by this timer timeout. + p_current = p_previous->next; + if (p_current != NULL) + { + p_current->ticks_to_expire += timeout; + } + + return (p_old_head != mp_timer_id_head); +} + + +/**@brief Function for scheduling a check for timeouts by generating a RTC1 interrupt. + */ +static void timer_timeouts_check_sched(void) +{ + NVIC_SetPendingIRQ(RTC1_IRQn); +} + + +/**@brief Function for scheduling a timer list update by generating a SWI interrupt. + */ +static void timer_list_handler_sched(void) +{ + NVIC_SetPendingIRQ(SWI_IRQn); +} + +#if APP_TIMER_CONFIG_USE_SCHEDULER +static void timeout_handler_scheduled_exec(void * p_event_data, uint16_t event_size) +{ + APP_ERROR_CHECK_BOOL(event_size == sizeof(app_timer_event_t)); + app_timer_event_t const * p_timer_event = (app_timer_event_t *)p_event_data; + + p_timer_event->timeout_handler(p_timer_event->p_context); +} +#endif + +/**@brief Function for executing an application timeout handler, either by calling it directly, or + * by passing an event to the @ref app_scheduler. + * + * @param[in] p_timer Pointer to expired timer. + */ +static void timeout_handler_exec(timer_node_t * p_timer) +{ +#if APP_TIMER_CONFIG_USE_SCHEDULER + app_timer_event_t timer_event; + + timer_event.timeout_handler = p_timer->p_timeout_handler; + timer_event.p_context = p_timer->p_context; + uint32_t err_code = app_sched_event_put(&timer_event, sizeof(timer_event), timeout_handler_scheduled_exec); + APP_ERROR_CHECK(err_code); +#else + p_timer->p_timeout_handler(p_timer->p_context); +#endif +} + + +/**@brief Function for checking for expired timers. + */ +static void timer_timeouts_check(void) +{ + // Handle expired of timer + if (mp_timer_id_head != NULL) + { + timer_node_t * p_timer; + timer_node_t * p_previous_timer; + uint32_t ticks_elapsed; + uint32_t ticks_expired; + + // Initialize actual elapsed ticks being consumed to 0. + ticks_expired = 0; + + // ticks_elapsed is collected here, job will use it. + ticks_elapsed = ticks_diff_get(rtc1_counter_get(), m_ticks_latest); + + // Auto variable containing the head of timers expiring. + p_timer = mp_timer_id_head; + + // Expire all timers within ticks_elapsed and collect ticks_expired. + while (p_timer != NULL) + { + // Do nothing if timer did not expire. + if (ticks_elapsed < p_timer->ticks_to_expire) + { + break; + } + + // Decrement ticks_elapsed and collect expired ticks. + ticks_elapsed -= p_timer->ticks_to_expire; + ticks_expired += p_timer->ticks_to_expire; + + // Move to next timer. + p_previous_timer = p_timer; + p_timer = p_timer->next; + + // Execute Task. + if (p_previous_timer->is_running) + { + p_previous_timer->is_running = false; + timeout_handler_exec(p_previous_timer); + } + } + + // Prepare to queue the ticks expired in the m_ticks_elapsed queue. + if (m_ticks_elapsed_q_read_ind == m_ticks_elapsed_q_write_ind) + { + // The read index of the queue is equal to the write index. This means the new + // value of ticks_expired should be stored at a new location in the m_ticks_elapsed + // queue (which is implemented as a double buffer). + + // Check if there will be a queue overflow. + if (++m_ticks_elapsed_q_write_ind == CONTEXT_QUEUE_SIZE_MAX) + { + // There will be a queue overflow. Hence the write index should point to the start + // of the queue. + m_ticks_elapsed_q_write_ind = 0; + } + } + + // Queue the ticks expired. + m_ticks_elapsed[m_ticks_elapsed_q_write_ind] = ticks_expired; + + timer_list_handler_sched(); + } +} + + +/**@brief Function for acquiring the number of ticks elapsed. + * + * @param[out] p_ticks_elapsed Number of ticks elapsed. + * + * @return TRUE if elapsed ticks was read from queue, FALSE otherwise. + */ +static bool elapsed_ticks_acquire(uint32_t * p_ticks_elapsed) +{ + // Pick the elapsed value from queue. + if (m_ticks_elapsed_q_read_ind != m_ticks_elapsed_q_write_ind) + { + // Dequeue elapsed value. + m_ticks_elapsed_q_read_ind++; + if (m_ticks_elapsed_q_read_ind == CONTEXT_QUEUE_SIZE_MAX) + { + m_ticks_elapsed_q_read_ind = 0; + } + + *p_ticks_elapsed = m_ticks_elapsed[m_ticks_elapsed_q_read_ind]; + + m_ticks_latest += *p_ticks_elapsed; + m_ticks_latest &= MAX_RTC_COUNTER_VAL; + + return true; + } + else + { + // No elapsed value in queue. + *p_ticks_elapsed = 0; + return false; + } +} + + +/**@brief Function for updating the timer list for expired timers. + * + * @param[in] ticks_elapsed Number of elapsed ticks. + * @param[in] ticks_previous Previous known value of the RTC counter. + * @param[out] p_restart_list_head List of repeating timers to be restarted. + */ +static void expired_timers_handler(uint32_t ticks_elapsed, + uint32_t ticks_previous, + timer_node_t ** p_restart_list_head) +{ + uint32_t ticks_expired = 0; + + while (mp_timer_id_head != NULL) + { + timer_node_t * p_timer; + timer_node_t * p_timer_expired; + + // Auto variable for current timer node. + p_timer = mp_timer_id_head; + + // Do nothing if timer did not expire + if (ticks_elapsed < p_timer->ticks_to_expire) + { + p_timer->ticks_to_expire -= ticks_elapsed; + break; + } + + // Decrement ticks_elapsed and collect expired ticks. + ticks_elapsed -= p_timer->ticks_to_expire; + ticks_expired += p_timer->ticks_to_expire; + + // Timer expired, set ticks_to_expire zero. + p_timer->ticks_to_expire = 0; + + // Remove the expired timer from head. + p_timer_expired = mp_timer_id_head; + mp_timer_id_head = p_timer->next; + + // Timer will be restarted if periodic. + if (p_timer->ticks_periodic_interval != 0) + { + p_timer->ticks_at_start = (ticks_previous + ticks_expired) & MAX_RTC_COUNTER_VAL; + p_timer->ticks_first_interval = p_timer->ticks_periodic_interval; + p_timer->next = *p_restart_list_head; + *p_restart_list_head = p_timer_expired; + } + } +} + + +/**@brief Function for handling timer list insertions. + * + * @param[in] p_restart_list_head List of repeating timers to be restarted. + * + * @return TRUE if Capture Compare register must be updated, FALSE otherwise. + */ +static bool list_insertions_handler(timer_node_t * p_restart_list_head) +{ + bool compare_update = false; + + timer_node_t * p_timer_id_old_head; + + // Remember the old head, so as to decide if new compare needs to be set. + p_timer_id_old_head = mp_timer_id_head; + + // Handle insertions of timers. + while ((p_restart_list_head != NULL) || (m_op_queue.first != m_op_queue.last)) + { + timer_node_t * p_timer; + + if (p_restart_list_head != NULL) + { + p_timer = p_restart_list_head; + p_restart_list_head = p_timer->next; + } + else + { + timer_user_op_t * p_user_op = &m_op_queue.user_op_queue[m_op_queue.first]; + + m_op_queue.first++; + if (m_op_queue.first == m_op_queue.size) + { + m_op_queue.first = 0; + } + + p_timer = p_user_op->p_node; + + switch (p_user_op->op_type) + { + case TIMER_USER_OP_TYPE_STOP: + // Delete node if timer is running. + if (timer_list_remove(p_user_op->p_node)) + { + compare_update = true; + } + + p_timer->is_running = false; + continue; + + case TIMER_USER_OP_TYPE_STOP_ALL: + // Delete list of running timers, and mark all timers as not running. + while (mp_timer_id_head != NULL) + { + timer_node_t * p_head = mp_timer_id_head; + + p_head->is_running = false; + mp_timer_id_head = p_head->next; + } + continue; + case TIMER_USER_OP_TYPE_START: + break; + default: + // No implementation needed. + continue; + } + + if (p_timer->is_running) + { + continue; + } + + p_timer->ticks_at_start = p_user_op->params.start.ticks_at_start; + p_timer->ticks_first_interval = p_user_op->params.start.ticks_first_interval; + p_timer->ticks_periodic_interval = p_user_op->params.start.ticks_periodic_interval; + p_timer->p_context = p_user_op->params.start.p_context; + + if (m_rtc1_reset) + { + p_timer->ticks_at_start = 0; + } + } + + // Prepare the node to be inserted. + if ( + ((p_timer->ticks_at_start - m_ticks_latest) & MAX_RTC_COUNTER_VAL) + < + (MAX_RTC_COUNTER_VAL / 2) + ) + { + p_timer->ticks_to_expire = ticks_diff_get(p_timer->ticks_at_start, m_ticks_latest) + + p_timer->ticks_first_interval; + } + else + { + uint32_t delta_current_start; + + delta_current_start = ticks_diff_get(m_ticks_latest, p_timer->ticks_at_start); + if (p_timer->ticks_first_interval > delta_current_start) + { + p_timer->ticks_to_expire = p_timer->ticks_first_interval - delta_current_start; + } + else + { + p_timer->ticks_to_expire = 0; + } + } + + p_timer->ticks_at_start = 0; + p_timer->ticks_first_interval = 0; + p_timer->is_running = true; + p_timer->next = NULL; + + // Insert into list + timer_list_insert(p_timer); + } + + return (compare_update || (mp_timer_id_head != p_timer_id_old_head)); +} + + +/**@brief Function for updating the Capture Compare register. + */ +static void compare_reg_update(timer_node_t * p_timer_id_head_old) +{ + // Setup the timeout for timers on the head of the list + if (mp_timer_id_head != NULL) + { + uint32_t ticks_to_expire = mp_timer_id_head->ticks_to_expire; + uint32_t pre_counter_val = rtc1_counter_get(); + uint32_t cc = m_ticks_latest; + uint32_t ticks_elapsed = ticks_diff_get(pre_counter_val, cc) + RTC_COMPARE_OFFSET_MIN; + + if (!m_rtc1_running) + { + // No timers were already running, start RTC + rtc1_start(); + } + + cc += (ticks_elapsed < ticks_to_expire) ? ticks_to_expire : ticks_elapsed; + cc &= MAX_RTC_COUNTER_VAL; + + rtc1_compare0_set(cc); + + uint32_t post_counter_val = rtc1_counter_get(); + + if ( + (ticks_diff_get(post_counter_val, pre_counter_val) + RTC_COMPARE_OFFSET_MIN) + > + ticks_diff_get(cc, pre_counter_val) + ) + { + // When this happens the COMPARE event may not be triggered by the RTC. + // The nRF51 Series User Specification states that if the COUNTER value is N + // (i.e post_counter_val = N), writing N or N + 1 to a CC register may not trigger a + // COMPARE event. Hence the RTC interrupt is forcefully pended by calling the following + // function. + rtc1_compare0_set(rtc1_counter_get()); // this should prevent CC to fire again in the background while the code is in RTC-ISR + nrf_delay_us(MAX_RTC_TASKS_DELAY); + timer_timeouts_check_sched(); + } + } + else + { +#if (APP_TIMER_KEEPS_RTC_ACTIVE == 0) + // No timers are running, stop RTC + rtc1_stop(); +#endif //(APP_TIMER_KEEPS_RTC_ACTIVE == 0) + } +} + + +/**@brief Function for handling changes to the timer list. + */ +static void timer_list_handler(void) +{ + timer_node_t * p_restart_list_head = NULL; + + uint32_t ticks_elapsed; + uint32_t ticks_previous; + bool ticks_have_elapsed; + bool compare_update = false; + timer_node_t * p_timer_id_head_old; + +#if APP_TIMER_WITH_PROFILER + { + uint8_t size = m_op_queue.size; + uint8_t first = m_op_queue.first; + uint8_t last = m_op_queue.last; + uint8_t utilization = (first <= last) ? (last - first) : (size + 1 - first + last); + + if (utilization > m_max_user_op_queue_utilization) + { + m_max_user_op_queue_utilization = utilization; + } + } +#endif + + // Back up the previous known tick and previous list head + ticks_previous = m_ticks_latest; + p_timer_id_head_old = mp_timer_id_head; + + // Get number of elapsed ticks + ticks_have_elapsed = elapsed_ticks_acquire(&ticks_elapsed); + + // Handle expired timers + if (ticks_have_elapsed) + { + expired_timers_handler(ticks_elapsed, ticks_previous, &p_restart_list_head); + compare_update = true; + } + + + // Handle list insertions + if (list_insertions_handler(p_restart_list_head)) + { + compare_update = true; + } + + // Update compare register if necessary + if (compare_update) + { + compare_reg_update(p_timer_id_head_old); + } + m_rtc1_reset = false; +} + + +/**@brief Function for enqueueing a new operations queue entry. + * + * @param[in] last_index Index of the next last index to be enqueued. + */ +static void user_op_enque(uint8_t last_index) +{ + m_op_queue.last = last_index; +} + + +/**@brief Function for allocating a new operations queue entry. + * + * @param[out] p_last_index Index of the next last index to be enqueued. + * + * @return Pointer to allocated queue entry, or NULL if queue is full. + */ +static timer_user_op_t * user_op_alloc( uint8_t * p_last_index) +{ + uint8_t last; + timer_user_op_t * p_user_op; + + last = m_op_queue.last + 1; + if (last == m_op_queue.size) + { + // Overflow case. + last = 0; + } + if (last == m_op_queue.first) + { + // Queue is full. + return NULL; + } + + *p_last_index = last; + p_user_op = &m_op_queue.user_op_queue[m_op_queue.last]; + + return p_user_op; +} + + +/**@brief Function for scheduling a Timer Start operation. + * + * @param[in] timer_id Id of timer to start. + * @param[in] timeout_initial Time (in ticks) to first timer expiry. + * @param[in] timeout_periodic Time (in ticks) between periodic expiries. + * @param[in] p_context General purpose pointer. Will be passed to the timeout handler when + * the timer expires. + * @return NRF_SUCCESS on success, otherwise an error code. + */ + +static uint32_t timer_start_op_schedule(timer_node_t * p_node, + uint32_t timeout_initial, + uint32_t timeout_periodic, + void * p_context) +{ + uint8_t last_index; + uint32_t err_code = NRF_SUCCESS; + + CRITICAL_REGION_ENTER(); + timer_user_op_t * p_user_op = user_op_alloc(&last_index); + if (p_user_op == NULL) + { + err_code = NRF_ERROR_NO_MEM; + } + else + { + p_user_op->op_type = TIMER_USER_OP_TYPE_START; + p_user_op->p_node = p_node; + p_user_op->params.start.ticks_at_start = rtc1_counter_get(); + p_user_op->params.start.ticks_first_interval = timeout_initial; + p_user_op->params.start.ticks_periodic_interval = timeout_periodic; + p_user_op->params.start.p_context = p_context; + + user_op_enque(last_index); + } + CRITICAL_REGION_EXIT(); + + if (err_code == NRF_SUCCESS) + { + timer_list_handler_sched(); + } + + return err_code; +} + + +/**@brief Function for scheduling a Timer Stop operation. + * + * @param[in] timer_id Id of timer to stop. + * @param[in] op_type Type of stop operation + * + * @return NRF_SUCCESS on successful scheduling a timer stop operation. NRF_ERROR_NO_MEM when there + * is no memory left to schedule the timer stop operation. + */ +static uint32_t timer_stop_op_schedule(timer_node_t * p_node, + timer_user_op_type_t op_type) +{ + uint8_t last_index; + uint32_t err_code = NRF_SUCCESS; + + CRITICAL_REGION_ENTER(); + timer_user_op_t * p_user_op = user_op_alloc(&last_index); + if (p_user_op == NULL) + { + err_code = NRF_ERROR_NO_MEM; + } + else + { + p_user_op->op_type = op_type; + p_user_op->p_node = p_node; + + user_op_enque(last_index); + } + CRITICAL_REGION_EXIT(); + + if (err_code == NRF_SUCCESS) + { + timer_list_handler_sched(); + } + + return err_code; +} + +/**@brief Function for handling the RTC1 interrupt. + * + * @details Checks for timeouts, and executes timeout handlers for expired timers. + */ +void RTC1_IRQHandler(void) +{ + // Clear all events (also unexpected ones) + NRF_RTC1->EVENTS_COMPARE[0] = 0; + NRF_RTC1->EVENTS_COMPARE[1] = 0; + NRF_RTC1->EVENTS_COMPARE[2] = 0; + NRF_RTC1->EVENTS_COMPARE[3] = 0; + NRF_RTC1->EVENTS_TICK = 0; + NRF_RTC1->EVENTS_OVRFLW = 0; + + // Check for expired timers + timer_timeouts_check(); +} + + +/**@brief Function for handling the SWI interrupt. + * + * @details Performs all updates to the timer list. + */ +void SWI_IRQHandler(void) +{ + timer_list_handler(); +} + + +ret_code_t app_timer_init(void) +{ + // Stop RTC to prevent any running timers from expiring (in case of reinitialization) + rtc1_stop(); + + // Initialize operation queue + m_op_queue.first = 0; + m_op_queue.last = 0; + m_op_queue.size = APP_TIMER_CONFIG_OP_QUEUE_SIZE+1; + + mp_timer_id_head = NULL; + m_ticks_elapsed_q_read_ind = 0; + m_ticks_elapsed_q_write_ind = 0; + +#if APP_TIMER_WITH_PROFILER + m_max_user_op_queue_utilization = 0; +#endif + + NVIC_ClearPendingIRQ(SWI_IRQn); + NVIC_SetPriority(SWI_IRQn, SWI_IRQ_PRI); + NVIC_EnableIRQ(SWI_IRQn); + + rtc1_init(APP_TIMER_CONFIG_RTC_FREQUENCY); + + m_ticks_latest = rtc1_counter_get(); + + return NRF_SUCCESS; +} + + +ret_code_t app_timer_create(app_timer_id_t const * p_timer_id, + app_timer_mode_t mode, + app_timer_timeout_handler_t timeout_handler) +{ + // Check state and parameters + VERIFY_MODULE_INITIALIZED(); + + if (timeout_handler == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + if (p_timer_id == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + if (((timer_node_t*)*p_timer_id)->is_running) + { + return NRF_ERROR_INVALID_STATE; + } + + timer_node_t * p_node = (timer_node_t *)*p_timer_id; + p_node->is_running = false; + p_node->mode = mode; + p_node->p_timeout_handler = timeout_handler; + return NRF_SUCCESS; +} + +ret_code_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context) +{ + uint32_t timeout_periodic; + timer_node_t * p_node = (timer_node_t*)timer_id; + + // Check state and parameters + VERIFY_MODULE_INITIALIZED(); + + if (timer_id == 0) + { + return NRF_ERROR_INVALID_STATE; + } + if ((timeout_ticks < APP_TIMER_MIN_TIMEOUT_TICKS) || (timeout_ticks > MAX_RTC_COUNTER_VAL)) + { + return NRF_ERROR_INVALID_PARAM; + } + if (p_node->p_timeout_handler == NULL) + { + return NRF_ERROR_INVALID_STATE; + } + + // Schedule timer start operation + timeout_periodic = (p_node->mode == APP_TIMER_MODE_REPEATED) ? timeout_ticks : 0; + + return timer_start_op_schedule(p_node, + timeout_ticks, + timeout_periodic, + p_context); +} + + +ret_code_t app_timer_stop(app_timer_id_t timer_id) +{ + timer_node_t * p_node = (timer_node_t*)timer_id; + // Check state and parameters + VERIFY_MODULE_INITIALIZED(); + + if ((timer_id == NULL) || (p_node->p_timeout_handler == NULL)) + { + return NRF_ERROR_INVALID_STATE; + } + + p_node->is_running = false; + + // Schedule timer stop operation + return timer_stop_op_schedule(p_node, TIMER_USER_OP_TYPE_STOP); +} + + +ret_code_t app_timer_stop_all(void) +{ + // Check state + VERIFY_MODULE_INITIALIZED(); + + return timer_stop_op_schedule(NULL, TIMER_USER_OP_TYPE_STOP_ALL); +} + + +uint32_t app_timer_cnt_get(void) +{ + return rtc1_counter_get(); +} + + +uint32_t app_timer_cnt_diff_compute(uint32_t ticks_to, + uint32_t ticks_from) +{ + return ticks_diff_get(ticks_to, ticks_from); +} + +#if APP_TIMER_WITH_PROFILER +uint8_t app_timer_op_queue_utilization_get(void) +{ + return m_max_user_op_queue_utilization; +} +#endif + +void app_timer_pause(void) +{ + NRF_RTC1->TASKS_STOP = 1; +} + +void app_timer_resume(void) +{ + NRF_RTC1->TASKS_START = 1; +} + +#endif //NRF_MODULE_ENABLED(APP_TIMER) diff --git a/components/libraries/timer/app_timer.h b/components/libraries/timer/app_timer.h new file mode 100644 index 0000000..cd5b6d2 --- /dev/null +++ b/components/libraries/timer/app_timer.h @@ -0,0 +1,320 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup app_timer Application Timer + * @{ + * @ingroup app_common + * + * @brief Application timer functionality. + * + * @details This module enables the application to create multiple timer instances based on the RTC1 + * peripheral. Checking for time-outs and invocation of user time-out handlers is performed + * in the RTC1 interrupt handler. List handling is done using a software interrupt (SWI0). + * Both interrupt handlers are running in APP_LOW priority level. + * + * @details When calling app_timer_start() or app_timer_stop(), the timer operation is just queued, + * and the software interrupt is triggered. The actual timer start/stop operation is + * executed by the SWI0 interrupt handler. Since the SWI0 interrupt is running in APP_LOW, + * if the application code calling the timer function is running in APP_LOW or APP_HIGH, + * the timer operation will not be performed until the application handler has returned. + * This will be the case, for example, when stopping a timer from a time-out handler when not using + * the scheduler. + * + * @details Use the USE_SCHEDULER parameter of the APP_TIMER_INIT() macro to select if the + * @ref app_scheduler should be used or not. Even if the scheduler is + * not used, app_timer.h will include app_scheduler.h, so when + * compiling, app_scheduler.h must be available in one of the compiler include paths. + */ + +#ifndef APP_TIMER_H__ +#define APP_TIMER_H__ +#include "sdk_config.h" +#include "app_error.h" +#include "app_util.h" +#include "compiler_abstraction.h" +#include "nordic_common.h" +#ifdef APP_TIMER_V2 +#include "nrf_log_instance.h" +#include "nrf_sortlist.h" +#endif +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Name of the module used for logger messaging. + */ +#define APP_TIMER_LOG_NAME app_timer + +#define APP_TIMER_CLOCK_FREQ 32768 /**< Clock frequency of the RTC timer used to implement the app timer module. */ +#define APP_TIMER_MIN_TIMEOUT_TICKS 5 /**< Minimum value of the timeout_ticks parameter of app_timer_start(). */ + +#ifdef RTX +#define APP_TIMER_NODE_SIZE 40 /**< Size of app_timer.timer_node_t (used to allocate data). */ +#else +#define APP_TIMER_NODE_SIZE 32 /**< Size of app_timer.timer_node_t (used to allocate data). */ +#endif // RTX + +#define APP_TIMER_SCHED_EVENT_DATA_SIZE sizeof(app_timer_event_t) /**< Size of event data when scheduler is used. */ + +#define APP_TIMER_MAX_CNT_VAL RTC_COUNTER_COUNTER_Msk /**< Maximum counter value that can be returned by @ref app_timer_cnt_get. */ + +/**@brief Convert milliseconds to timer ticks. + * + * This macro uses 64-bit integer arithmetic, but as long as the macro parameters are + * constants (i.e. defines), the computation will be done by the preprocessor. + * + * @param[in] MS Milliseconds. + * + * @return Number of timer ticks. + */ +#ifndef FREERTOS +#define APP_TIMER_TICKS(MS) \ + ((uint32_t)ROUNDED_DIV( \ + (MS) * (uint64_t)APP_TIMER_CLOCK_FREQ, \ + 1000 * (APP_TIMER_CONFIG_RTC_FREQUENCY + 1))) +#else +#include "FreeRTOSConfig.h" +#define APP_TIMER_TICKS(MS) (uint32_t)ROUNDED_DIV((MS)*configTICK_RATE_HZ,1000) +#endif + +/** @brief Invalid value used to indicate that timer is idle. */ +#define APP_TIMER_IDLE_VAL 0xFFFFFFFFFFFFFFFFULL + +/** + * @brief Create a timer identifier and statically allocate memory for the timer. + * + * @param timer_id Name of the timer identifier variable that will be used to control the timer. + */ +#define APP_TIMER_DEF(timer_id) _APP_TIMER_DEF(timer_id) + +/**@brief Application time-out handler type. */ +typedef void (*app_timer_timeout_handler_t)(void * p_context); + +#ifdef APP_TIMER_V2 +/** + * @brief app_timer control block + */ +typedef struct +{ + nrf_sortlist_item_t list_item; /**< Token used by sortlist. */ + uint64_t end_val; /**< RTC counter value when timer expires or @ref APP_TIMER_IDLE_VAL. */ + uint32_t repeat_period; /**< Repeat period (0 if single shot mode). */ + app_timer_timeout_handler_t handler; /**< User handler. */ + void * p_context; /**< User context. */ + NRF_LOG_INSTANCE_PTR_DECLARE(p_log) /**< Pointer to instance of the logger object (Conditionally compiled). */ +} app_timer_t; + +/**@brief Timer ID type. + * Never declare a variable of this type, but use the macro @ref APP_TIMER_DEF instead.*/ +typedef app_timer_t * app_timer_id_t; + +#define _APP_TIMER_DEF(timer_id) \ + NRF_LOG_INSTANCE_REGISTER(APP_TIMER_LOG_NAME, timer_id, \ + APP_TIMER_CONFIG_INFO_COLOR, \ + APP_TIMER_CONFIG_DEBUG_COLOR, \ + APP_TIMER_CONFIG_INITIAL_LOG_LEVEL, \ + APP_TIMER_CONFIG_LOG_ENABLED ? \ + APP_TIMER_CONFIG_LOG_LEVEL : NRF_LOG_SEVERITY_NONE); \ + static app_timer_t CONCAT_2(timer_id,_data) = { \ + .end_val = APP_TIMER_IDLE_VAL, \ + NRF_LOG_INSTANCE_PTR_INIT(p_log, APP_TIMER_LOG_NAME, timer_id) \ + }; \ + static const app_timer_id_t timer_id = &CONCAT_2(timer_id,_data) + +#else //APP_TIMER_V2 +typedef struct app_timer_t { uint32_t data[CEIL_DIV(APP_TIMER_NODE_SIZE, sizeof(uint32_t))]; } app_timer_t; + +/**@brief Timer ID type. + * Never declare a variable of this type, but use the macro @ref APP_TIMER_DEF instead.*/ +typedef app_timer_t * app_timer_id_t; + +#define _APP_TIMER_DEF(timer_id) \ + static app_timer_t CONCAT_2(timer_id,_data) = { {0} }; \ + static const app_timer_id_t timer_id = &CONCAT_2(timer_id,_data) + +#endif + + +/**@brief Structure passed to app_scheduler. */ +typedef struct +{ + app_timer_timeout_handler_t timeout_handler; + void * p_context; +} app_timer_event_t; + +/**@brief Timer modes. */ +typedef enum +{ + APP_TIMER_MODE_SINGLE_SHOT, /**< The timer will expire only once. */ + APP_TIMER_MODE_REPEATED /**< The timer will restart each time it expires. */ +} app_timer_mode_t; + +/**@brief Function for initializing the timer module. + * + * @retval NRF_SUCCESS If the module was initialized successfully. + */ +ret_code_t app_timer_init(void); + +/**@brief Function for creating a timer instance. + * + * @param[in] p_timer_id Pointer to timer identifier. + * @param[in] mode Timer mode. + * @param[in] timeout_handler Function to be executed when the timer expires. + * + * @retval NRF_SUCCESS If the timer was successfully created. + * @retval NRF_ERROR_INVALID_PARAM If a parameter was invalid. + * @retval NRF_ERROR_INVALID_STATE If the application timer module has not been initialized or + * the timer is running. + * + * @note This function does the timer allocation in the caller's context. It is also not protected + * by a critical region. Therefore care must be taken not to call it from several interrupt + * levels simultaneously. + * @note The function can be called again on the timer instance and will re-initialize the instance if + * the timer is not running. + * @attention The FreeRTOS and RTX app_timer implementation does not allow app_timer_create to + * be called on the previously initialized instance. + */ +ret_code_t app_timer_create(app_timer_id_t const * p_timer_id, + app_timer_mode_t mode, + app_timer_timeout_handler_t timeout_handler); + +/**@brief Function for starting a timer. + * + * @param[in] timer_id Timer identifier. + * @param[in] timeout_ticks Number of ticks (of RTC1, including prescaling) to time-out event + * (minimum 5 ticks). + * @param[in] p_context General purpose pointer. Will be passed to the time-out handler when + * the timer expires. + * + * @retval NRF_SUCCESS If the timer was successfully started. + * @retval NRF_ERROR_INVALID_PARAM If a parameter was invalid. + * @retval NRF_ERROR_INVALID_STATE If the application timer module has not been initialized or the timer + * has not been created. + * @retval NRF_ERROR_NO_MEM If the timer operations queue was full. + * + * @note The minimum timeout_ticks value is 5. + * @note For multiple active timers, time-outs occurring in close proximity to each other (in the + * range of 1 to 3 ticks) will have a positive jitter of maximum 3 ticks. + * @note When calling this method on a timer that is already running, the second start operation + * is ignored. + */ +ret_code_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context); + +/**@brief Function for stopping the specified timer. + * + * @note If stop is called from the thread context or interrupt context with priority + * less or equal than app timer interrupt priority (RTC1), timer expiration handler + * will not be called followed stop call. However, stopping timer from higher priority + * interrupt may interrupt expiry process. In that case, handler may still be called + * after stop. + * + * @param[in] timer_id Timer identifier. + * + * @retval NRF_SUCCESS If the timer was successfully stopped. + * @retval NRF_ERROR_INVALID_PARAM If a parameter was invalid. + * @retval NRF_ERROR_INVALID_STATE If the application timer module has not been initialized or the timer + * has not been created. + * @retval NRF_ERROR_NO_MEM If the timer operations queue was full. + */ +ret_code_t app_timer_stop(app_timer_id_t timer_id); + +/**@brief Function for stopping all running timers. + * + * @retval NRF_SUCCESS If all timers were successfully stopped. + * @retval NRF_ERROR_INVALID_STATE If the application timer module has not been initialized. + * @retval NRF_ERROR_NO_MEM If the timer operations queue was full. + */ +ret_code_t app_timer_stop_all(void); + +/**@brief Function for returning the current value of the RTC1 counter. + * + * @return Current value of the RTC1 counter. + */ +uint32_t app_timer_cnt_get(void); + +/**@brief Function for computing the difference between two RTC1 counter values. + * + * @param[in] ticks_to Value returned by app_timer_cnt_get(). + * @param[in] ticks_from Value returned by app_timer_cnt_get(). + * + * @return Number of ticks from ticks_from to ticks_to. + */ +uint32_t app_timer_cnt_diff_compute(uint32_t ticks_to, + uint32_t ticks_from); + + +/**@brief Function for getting the maximum observed operation queue utilization. + * + * Function for tuning the module and determining OP_QUEUE_SIZE value and thus module RAM usage. + * + * @note APP_TIMER_WITH_PROFILER must be enabled to use this functionality. + * + * @return Maximum number of events in queue observed so far. + */ +uint8_t app_timer_op_queue_utilization_get(void); + +/** + * @brief Function for pausing RTC activity which drives app_timer. + * + * @note This function can be used for debugging purposes to ensure + * that application is halted when entering a breakpoint. + */ +void app_timer_pause(void); + +/** + * @brief Function for resuming RTC activity which drives app_timer. + * + * @note This function can be used for debugging purposes to resume + * application activity. + */ +void app_timer_resume(void); + +#ifdef __cplusplus +} +#endif + +#endif // APP_TIMER_H__ + +/** @} */ diff --git a/components/libraries/timer/app_timer2.c b/components/libraries/timer/app_timer2.c new file mode 100644 index 0000000..dfafbcb --- /dev/null +++ b/components/libraries/timer/app_timer2.c @@ -0,0 +1,720 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "app_timer.h" +#include "nrf_atfifo.h" +#include "nrf_sortlist.h" +#include "nrf_delay.h" +#if APP_TIMER_WITH_PROFILER +#include "app_util_platform.h" +#endif +#if APP_TIMER_CONFIG_USE_SCHEDULER +#include "app_scheduler.h" +#endif +#include +#define NRF_LOG_MODULE_NAME APP_TIMER_LOG_NAME +#if APP_TIMER_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL APP_TIMER_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR APP_TIMER_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR APP_TIMER_CONFIG_DEBUG_COLOR +#else //APP_TIMER_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //APP_TIMER_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#include "drv_rtc.h" + +/** + * Maximum possible relative value is limited by safe window to detect cases when requested + * compare event has already occured. + */ +#define APP_TIMER_SAFE_WINDOW APP_TIMER_TICKS(APP_TIMER_SAFE_WINDOW_MS) + +#define APP_TIMER_RTC_MAX_VALUE (DRV_RTC_MAX_CNT - APP_TIMER_SAFE_WINDOW) + +/* Check if timer is idle */ +#define APP_TIMER_IS_IDLE(timer) (timer->end_val == APP_TIMER_IDLE_VAL) + +static drv_rtc_t m_rtc_inst = DRV_RTC_INSTANCE(1); + +#if APP_TIMER_WITH_PROFILER +static uint8_t m_max_user_op_queue_utilization; /**< Maximum observed timer user operations queue utilization. */ +static uint8_t m_current_user_op_queue_utilization; /**< Currently observed timer user operations queue utilization. */ +#endif /* APP_TIMER_WITH_PROFILER */ + +/** + * @brief Timer requests types. + */ +typedef enum +{ + TIMER_REQ_START, + TIMER_REQ_STOP, + TIMER_REQ_STOP_ALL +} app_timer_req_type_t; + +/** + * @brief Operation request structure. + */ +typedef struct +{ + app_timer_req_type_t type; /**< Request type. */ + app_timer_t * p_timer; /**< Timer instance. */ +} timer_req_t; + +static app_timer_t * volatile mp_active_timer; /**< Timer currently handled by RTC driver. */ +static bool m_global_active; /**< Flag used to globally disable all timers. */ +static uint64_t m_base_counter; +static uint64_t m_stamp64; + +/* Request FIFO instance. */ +NRF_ATFIFO_DEF(m_req_fifo, timer_req_t, APP_TIMER_CONFIG_OP_QUEUE_SIZE); + +/* Sortlist instance. */ +static bool compare_func(nrf_sortlist_item_t * p_item0, nrf_sortlist_item_t *p_item1); +NRF_SORTLIST_DEF(m_app_timer_sortlist, compare_func); /**< Sortlist used for storing queued timers. */ + +/** + * @brief Return current 64 bit timestamp + */ +static uint64_t get_now(void) +{ + uint64_t now = m_base_counter + drv_rtc_counter_get(&m_rtc_inst); + + /* it is possible that base was not updated and overflow occured, in that case 'now' will be + * 24bit value behind. Additional timestamp updated on every 24 bit period is used to detect + * that case. Apart from that 'now' should never be behind previously read timestamp. + */ + if (now < m_stamp64) { + now += (DRV_RTC_MAX_CNT + 1); + } + + return now; +} +/** + * @brief Function used for comparing items in sorted list. + */ +static inline bool compare_func(nrf_sortlist_item_t * p_item0, nrf_sortlist_item_t *p_item1) +{ + app_timer_t * p0 = CONTAINER_OF(p_item0, app_timer_t, list_item); + app_timer_t * p1 = CONTAINER_OF(p_item1, app_timer_t, list_item); + + uint64_t p0_end = p0->end_val; + uint64_t p1_end = p1->end_val; + return (p0_end <= p1_end) ? true : false; +} + +#if APP_TIMER_CONFIG_USE_SCHEDULER +static void scheduled_timeout_handler(void * p_event_data, uint16_t event_size) +{ + ASSERT(event_size == sizeof(app_timer_event_t)); + app_timer_event_t const * p_timer_event = (app_timer_event_t *)p_event_data; + + p_timer_event->timeout_handler(p_timer_event->p_context); +} +#endif + +/** + * @brief Function called on timer expiration + * If end value is not reached it is assumed that it was partial expiration and time is put back + * into the list. Otherwise function calls user handler if timer was not stopped before. If timer + * is in repeated mode then timer is rescheduled. + * + * @param p_timer Timer instance. + * + * @return True if reevaluation of sortlist needed (becasue it was updated). + */ +static bool timer_expire(app_timer_t * p_timer) +{ + ASSERT(p_timer->handler); + bool ret = false; + + if ((m_global_active == true) && (p_timer != NULL)) + { + if (get_now() >= p_timer->end_val) { + bool cont; + + /* timer expired */ + CRITICAL_REGION_ENTER(); + /* In case of single shot, set timer to idle. */ + if (p_timer->repeat_period == 0) + { + p_timer->end_val = APP_TIMER_IDLE_VAL; + } + CRITICAL_REGION_EXIT(); + #if APP_TIMER_CONFIG_USE_SCHEDULER + app_timer_event_t timer_event; + + timer_event.timeout_handler = p_timer->handler; + timer_event.p_context = p_timer->p_context; + uint32_t err_code = app_sched_event_put(&timer_event, + sizeof(timer_event), + scheduled_timeout_handler); + APP_ERROR_CHECK(err_code); + #else + NRF_LOG_DEBUG("Timer expired (context: %d)", (uint32_t)p_timer->p_context) + p_timer->handler(p_timer->p_context); + #endif + CRITICAL_REGION_ENTER(); + /* check active flag as it may have been stopped in the user handler */ + if (p_timer->repeat_period && !APP_TIMER_IS_IDLE(p_timer)) + { + p_timer->end_val += p_timer->repeat_period; + cont = true; + } + else + { + cont = false; + } + CRITICAL_REGION_EXIT(); + + if (cont) + { + nrf_sortlist_add(&m_app_timer_sortlist, &p_timer->list_item); + ret = true; + } + } + else if (!APP_TIMER_IS_IDLE(p_timer)) + { + nrf_sortlist_add(&m_app_timer_sortlist, &p_timer->list_item); + ret = true; + } + } + return ret; +} + +/** + * @brief Function is configuring RTC driver to trigger timeout interrupt for given timer. + * + * It is possible that RTC driver will indicate that timeout already occured. In that case timer + * expires and function indicates that RTC was not configured. + * + * @param p_timer Timer instance. + * @param [in,out] p_rerun Flag indicating that sortlist reevaluation is required. + * + * @return True if RTC was successfully configured, false if timer already expired and RTC was not + * configured. + * + */ +static bool rtc_schedule(app_timer_t * p_timer, bool * p_rerun) +{ + ret_code_t ret = NRF_ERROR_TIMEOUT; + *p_rerun = false; + /* In case timer got stopped in between, end_val will be very far in the + * future. RTC will be reconfigured on the next iteration. + */ + uint64_t end_val = p_timer->end_val; + int64_t remaining = (int64_t)(end_val - get_now()); + + if (remaining > 0) { + uint32_t cc_val = ((uint32_t)remaining > APP_TIMER_RTC_MAX_VALUE) ? + (app_timer_cnt_get() + APP_TIMER_RTC_MAX_VALUE) : end_val; + + ret = drv_rtc_windowed_compare_set(&m_rtc_inst, 0, cc_val, APP_TIMER_SAFE_WINDOW); + NRF_LOG_DEBUG("Setting CC to 0x%08x (err: %d)", cc_val & DRV_RTC_MAX_CNT, ret); + if (ret == NRF_SUCCESS) + { + return true; + } + } + else + { + drv_rtc_compare_disable(&m_rtc_inst, 0); + } + + if (ret == NRF_ERROR_TIMEOUT) + { + *p_rerun = timer_expire(p_timer); + } + else + { + NRF_LOG_ERROR("Unexpected error: %d", ret); + ASSERT(0); + } + + return false; +} + +static inline app_timer_t * sortlist_pop(void) +{ + nrf_sortlist_item_t * p_next_item = nrf_sortlist_pop(&m_app_timer_sortlist); + return p_next_item ? CONTAINER_OF(p_next_item, app_timer_t, list_item) : NULL; +} + +static inline app_timer_t * sortlist_peek(void) +{ + nrf_sortlist_item_t const * p_next_item = nrf_sortlist_peek(&m_app_timer_sortlist); + return p_next_item ? CONTAINER_OF(p_next_item, app_timer_t, list_item) : NULL; +} + +/** + * @brief Function for deactivating all timers which are in the sorted list (active timers). + */ +static void sorted_list_stop_all(void) +{ + app_timer_t * p_next; + do + { + p_next = sortlist_pop(); + if (p_next) + { + p_next->end_val = APP_TIMER_IDLE_VAL; + } + } while (p_next); +} + +/** + * @brief Function for handling RTC counter overflow. + * + * Increment base counter used to calculate 64 bit timestamp. + */ +static void on_overflow_evt(void) +{ + NRF_LOG_DEBUG("Overflow EVT"); + m_base_counter += (DRV_RTC_MAX_CNT + 1); +} + +/** + * #brief Function for handling RTC compare event - active timer expiration. + */ +static void on_compare_evt(drv_rtc_t const * const p_instance) +{ + if (mp_active_timer) + { + /* If assert fails it suggests that safe window should be increased. */ + ASSERT(app_timer_cnt_diff_compute(drv_rtc_counter_get(p_instance), + drv_rtc_compare_get(p_instance, 0)) < APP_TIMER_SAFE_WINDOW); + + NRF_LOG_INST_DEBUG(mp_active_timer->p_log, "Compare EVT"); + UNUSED_RETURN_VALUE(timer_expire(mp_active_timer)); + mp_active_timer = NULL; + } + else + { + NRF_LOG_WARNING("Compare event but no active timer (already stopped?)"); + } +} + +/** + * @brief Channel 1 is triggered in the middle of 24 bit period to updated control timestamp in + * place where there is no risk of overflow. + */ +static void on_compare1_evt(drv_rtc_t const * const p_instance) +{ + m_stamp64 = get_now(); +} + +/** + * @brief Function updates RTC. + * + * Function is called at the end of RTC interrupt when all new user request and/or timer expiration + * occured. It configures RTC if there is any pending timer, reconfigures if the are timers with + * shorted timeout than active one or stops RTC if there is no active timers. + */ +static void rtc_update(drv_rtc_t const * const p_instance) +{ + while(1) + { + app_timer_t * p_next = sortlist_peek(); + bool rtc_reconf = false; + if (p_next) //Candidate for active timer + { + /* If timer was stopped just remove it from the sortlist and continue. + * Note that it is possible, that stop/start requests are pending in + * the request queue if added from higher priority context. In + * that case end_val was first set to invalid value and then to the + * new timeout in the future. In that case, timer location in sortlist + * is invalid. However, it will all be sorted out when stop and start + * requests are handled. + */ + if (APP_TIMER_IS_IDLE(p_next)) { + (void)sortlist_pop(); + continue; + } + else if (mp_active_timer == NULL) + { + //There is no active timer so candidate will become active timer. + rtc_reconf = true; + } + else if (p_next->end_val < mp_active_timer->end_val) + { + //Candidate has shorter timeout than current active timer. Candidate will replace active timer. + //Active timer is put back into sorted list. + rtc_reconf = true; + if (!APP_TIMER_IS_IDLE(mp_active_timer)) + { + NRF_LOG_INST_DEBUG(mp_active_timer->p_log, "Timer preempted."); + nrf_sortlist_add(&m_app_timer_sortlist, &mp_active_timer->list_item); + } + } + + if (rtc_reconf) + { + bool rerun; + p_next = sortlist_pop(); + NRF_LOG_INST_DEBUG(p_next->p_log, "Activating timer (CC:%d/%08x).", p_next->end_val, p_next->end_val); + if (rtc_schedule(p_next, &rerun)) + { + if (!APP_TIMER_KEEPS_RTC_ACTIVE && (mp_active_timer == NULL)) + { + drv_rtc_start(p_instance); + } + mp_active_timer = p_next; + + if (rerun == false) + { + //RTC was successfully updated and sortlist was not updated. Function can be terminated. + break; + } + } + else + { + //If RTC driver indicated that timeout already occured a new candidate will be taken from sorted list. + NRF_LOG_INST_DEBUG(p_next->p_log,"Timer expired before scheduled to RTC."); + mp_active_timer = NULL; + } + } + else + { + //RTC will not be updated. Function can terminate. + break; + } + } + else //No candidate for active timer. + { + if (!APP_TIMER_KEEPS_RTC_ACTIVE && (mp_active_timer == NULL)) + { + drv_rtc_stop(p_instance); + } + break; + } + } +} + +/** + * @brief Function for processing user requests. + * + * Function is called only in the context of RTC interrupt. + */ +static void timer_req_process(drv_rtc_t const * const p_instance) +{ + nrf_atfifo_item_get_t fifo_ctx; + timer_req_t * p_req = nrf_atfifo_item_get(m_req_fifo, &fifo_ctx); + + while (p_req) + { + switch (p_req->type) + { + case TIMER_REQ_START: + /* Check for idle in most of the cases is not needed but it serves + * for following corner case: + * - timer was active (request processed) + * - timer was stopped and started from higher priority which + * interrupted handling timeout. End_val is currently set to the + * timeout value of the next start request. If that value already + * expired, timeout expires before stop, start requests are handled. + * - When start request is handled, timer is idle and should not be + * added to the queue but just dropped. + */ + if (!APP_TIMER_IS_IDLE(p_req->p_timer)) + { + nrf_sortlist_add(&m_app_timer_sortlist, &(p_req->p_timer->list_item)); + NRF_LOG_INST_DEBUG(p_req->p_timer->p_log,"Start request (expiring at %d/0x%08x).", + p_req->p_timer->end_val, p_req->p_timer->end_val); + } + break; + case TIMER_REQ_STOP: + if (p_req->p_timer == mp_active_timer) + { + mp_active_timer = NULL; + } + else + { + bool found = nrf_sortlist_remove(&m_app_timer_sortlist, &(p_req->p_timer->list_item)); + if (!found) + { + NRF_LOG_INFO("Timer not found on sortlist (stopping expired timer)."); + } + } + NRF_LOG_INST_DEBUG(p_req->p_timer->p_log,"Stop request."); + break; + case TIMER_REQ_STOP_ALL: + sorted_list_stop_all(); + m_global_active = true; + NRF_LOG_INFO("Stop all request."); + break; + default: + break; + } +#if APP_TIMER_WITH_PROFILER + CRITICAL_REGION_ENTER(); +#endif + UNUSED_RETURN_VALUE(nrf_atfifo_item_free(m_req_fifo, &fifo_ctx)); +#if APP_TIMER_WITH_PROFILER + if (m_max_user_op_queue_utilization < m_current_user_op_queue_utilization) + { + m_max_user_op_queue_utilization = m_current_user_op_queue_utilization; + } + --m_current_user_op_queue_utilization; + CRITICAL_REGION_EXIT(); +#endif /* APP_TIMER_WITH_PROFILER */ + p_req = nrf_atfifo_item_get(m_req_fifo, &fifo_ctx); + } +} + +static void rtc_irq(drv_rtc_t const * const p_instance) +{ + if (drv_rtc_overflow_pending(p_instance)) + { + on_overflow_evt(); + } + if (drv_rtc_compare_pending(p_instance, 0)) + { + on_compare_evt(p_instance); + } + if (drv_rtc_compare_pending(p_instance, 1)) + { + on_compare1_evt(p_instance); + } + + timer_req_process(p_instance); + rtc_update(p_instance); +} + +/** + * @brief Function for triggering processing user requests. + * + * @note All user requests are processed in a single context - RTC interrupt. + */ +static inline void timer_request_proc_trigger(void) +{ + drv_rtc_irq_trigger(&m_rtc_inst); +} + +/** + * @brief Function for putting user request into the request queue + */ +static ret_code_t timer_req_schedule(app_timer_req_type_t type, app_timer_t * p_timer) +{ + nrf_atfifo_item_put_t fifo_ctx; + timer_req_t * p_req; +#if APP_TIMER_WITH_PROFILER + CRITICAL_REGION_ENTER(); +#endif + p_req = nrf_atfifo_item_alloc(m_req_fifo, &fifo_ctx); +#if APP_TIMER_WITH_PROFILER + if (p_req) + { + ++m_current_user_op_queue_utilization; + } + CRITICAL_REGION_EXIT(); +#endif /* APP_TIMER_WITH_PROFILER */ + if (p_req) + { + p_req->type = type; + p_req->p_timer = p_timer; + if (nrf_atfifo_item_put(m_req_fifo, &fifo_ctx)) + { + timer_request_proc_trigger(); + } + else + { + NRF_LOG_WARNING("Scheduling interrupted another scheduling."); + } + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_NO_MEM; + } +} + +ret_code_t app_timer_init(void) +{ + ret_code_t err_code; + drv_rtc_config_t config = { + .prescaler = APP_TIMER_CONFIG_RTC_FREQUENCY, + .interrupt_priority = APP_TIMER_CONFIG_IRQ_PRIORITY + }; + + err_code = NRF_ATFIFO_INIT(m_req_fifo); + if (err_code != NRFX_SUCCESS) + { + return err_code; + } + + err_code = drv_rtc_init(&m_rtc_inst, &config, rtc_irq); + if (err_code != NRFX_SUCCESS) + { + return err_code; + } + drv_rtc_overflow_enable(&m_rtc_inst, true); + drv_rtc_compare_set(&m_rtc_inst, 1, DRV_RTC_MAX_CNT >> 1, true); + if (APP_TIMER_KEEPS_RTC_ACTIVE) + { + drv_rtc_start(&m_rtc_inst); + } + + m_global_active = true; + return err_code; +} + +ret_code_t app_timer_create(app_timer_id_t const * p_timer_id, + app_timer_mode_t mode, + app_timer_timeout_handler_t timeout_handler) +{ + ASSERT(p_timer_id); + ASSERT(timeout_handler); + + if (timeout_handler == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + + app_timer_t * p_t = (app_timer_t *) *p_timer_id; + p_t->end_val = APP_TIMER_IDLE_VAL; + p_t->handler = timeout_handler; + p_t->repeat_period = (mode == APP_TIMER_MODE_REPEATED) ? 1 : 0; + return NRF_SUCCESS; +} + +ret_code_t app_timer_start(app_timer_t * p_timer, uint32_t timeout_ticks, void * p_context) +{ + ASSERT(p_timer); + app_timer_t * p_t = (app_timer_t *) p_timer; + bool cont; + + CRITICAL_REGION_ENTER(); + if (APP_TIMER_IS_IDLE(p_t)) + { + /* TImer is idle and can be started. Note that timer can still be + * in use by the engine since stop request may be still pending if + * it was scheduled from higher priority interrupt (same as this start). + * In that case, end value is shifted to the future which will prevent + * previous timeout value to expire.*/ + p_t->end_val = get_now() + timeout_ticks; + cont = true; + } + else + { + cont = false; + } + CRITICAL_REGION_EXIT(); + + /* Timer in use */ + if (!cont) + { + return NRF_SUCCESS; + } + + p_t->p_context = p_context; + + if (p_t->repeat_period) + { + p_t->repeat_period = timeout_ticks; + } + + return timer_req_schedule(TIMER_REQ_START, p_t); +} + + +ret_code_t app_timer_stop(app_timer_t * p_timer) +{ + ASSERT(p_timer); + app_timer_t * p_t = (app_timer_t *) p_timer; + + bool cont; + + CRITICAL_REGION_ENTER(); + if (APP_TIMER_IS_IDLE(p_t)) + { + /* TImer is idle and can not be stopped. */ + cont = false; + } + else + { + /* Set end value to invalid (unrealistic future) value. */ + p_t->end_val = APP_TIMER_IDLE_VAL; + cont = true; + } + CRITICAL_REGION_EXIT(); + + if (!cont) + { + return NRF_SUCCESS; + } + + return timer_req_schedule(TIMER_REQ_STOP, p_t); +} + +ret_code_t app_timer_stop_all(void) +{ + //block timer globally + m_global_active = false; + + return timer_req_schedule(TIMER_REQ_STOP_ALL, NULL); +} + +#if APP_TIMER_WITH_PROFILER +uint8_t app_timer_op_queue_utilization_get(void) +{ + return m_max_user_op_queue_utilization; +} +#endif /* APP_TIMER_WITH_PROFILER */ + +uint32_t app_timer_cnt_diff_compute(uint32_t ticks_to, + uint32_t ticks_from) +{ + return ((ticks_to - ticks_from) & RTC_COUNTER_COUNTER_Msk); +} + +uint32_t app_timer_cnt_get(void) +{ + return drv_rtc_counter_get(&m_rtc_inst); +} + +void app_timer_pause(void) +{ + drv_rtc_stop(&m_rtc_inst); +} + +void app_timer_resume(void) +{ + drv_rtc_start(&m_rtc_inst); +} diff --git a/components/libraries/timer/app_timer_freertos.c b/components/libraries/timer/app_timer_freertos.c new file mode 100644 index 0000000..0c9fc38 --- /dev/null +++ b/components/libraries/timer/app_timer_freertos.c @@ -0,0 +1,243 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(APP_TIMER) +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" + +#include "app_timer.h" +#include +#include +#include "nrf.h" +#include "app_error.h" + +/** + * Note that this implementation is made only for enable SDK components which interacts with app_timer to work with FreeRTOS. + * It is more suitable to use native FreeRTOS timer for other purposes. + */ +/* Check if RTC FreeRTOS version is used */ +#if configTICK_SOURCE != FREERTOS_USE_RTC +#error app_timer in FreeRTOS variant have to be used with RTC tick source configuration. Default configuration have to be used in other case. +#endif + +/** + * @brief Waiting time for the timer queue + * + * Number of system ticks to wait for the timer queue to put the message. + * It is strongly recommended to set this to the value bigger than 1. + * In other case if timer message queue is full - any operation on timer may fail. + * @note + * Timer functions called from interrupt context would never wait. + */ +#define APP_TIMER_WAIT_FOR_QUEUE 2 + +/**@brief This structure keeps information about osTimer.*/ +typedef struct +{ + void * argument; + TimerHandle_t osHandle; + app_timer_timeout_handler_t func; + /** + * This member is to make sure that timer function is only called if timer is running. + * FreeRTOS may have timer running even after stop function is called, + * because it processes commands in Timer task and stopping function only puts command into the queue. */ + bool active; + bool single_shot; +}app_timer_info_t; + + +/* Check if freeRTOS timers are activated */ +#if configUSE_TIMERS == 0 + #error app_timer for freeRTOS requires configUSE_TIMERS option to be activated. +#endif + +/* Check if app_timer_t variable type can held our app_timer_info_t structure */ +STATIC_ASSERT(sizeof(app_timer_info_t) <= sizeof(app_timer_t)); + + +/** + * @brief Internal callback function for the system timer + * + * Internal function that is called from the system timer. + * It gets our parameter from timer data and sends it to user function. + * @param[in] xTimer Timer handler + */ +static void app_timer_callback(TimerHandle_t xTimer) +{ + app_timer_info_t * pinfo = (app_timer_info_t*)(pvTimerGetTimerID(xTimer)); + ASSERT(pinfo->osHandle == xTimer); + ASSERT(pinfo->func != NULL); + + if (pinfo->active) + { + pinfo->active = (pinfo->single_shot) ? false : true; + pinfo->func(pinfo->argument); + } +} + + +uint32_t app_timer_init(void) +{ + return NRF_SUCCESS; +} + + +uint32_t app_timer_create(app_timer_id_t const * p_timer_id, + app_timer_mode_t mode, + app_timer_timeout_handler_t timeout_handler) +{ + app_timer_info_t * pinfo = (app_timer_info_t*)(*p_timer_id); + uint32_t err_code = NRF_SUCCESS; + unsigned long timer_mode; + + if ((timeout_handler == NULL) || (p_timer_id == NULL)) + { + return NRF_ERROR_INVALID_PARAM; + } + if (pinfo->active) + { + return NRF_ERROR_INVALID_STATE; + } + + if (pinfo->osHandle == NULL) + { + /* New timer is created */ + memset(pinfo, 0, sizeof(app_timer_info_t)); + + timer_mode = (mode == APP_TIMER_MODE_SINGLE_SHOT) ? pdFALSE : pdTRUE; + pinfo->single_shot = (mode == APP_TIMER_MODE_SINGLE_SHOT); + pinfo->func = timeout_handler; + pinfo->osHandle = xTimerCreate(" ", 1000, timer_mode, pinfo, app_timer_callback); + + if (pinfo->osHandle == NULL) + err_code = NRF_ERROR_NULL; + } + else + { + /* Timer cannot be reinitialized using FreeRTOS API */ + return NRF_ERROR_INVALID_STATE; + } + + return err_code; +} + + +uint32_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context) +{ + app_timer_info_t * pinfo = (app_timer_info_t*)(timer_id); + TimerHandle_t hTimer = pinfo->osHandle; + + if (hTimer == NULL) + { + return NRF_ERROR_INVALID_STATE; + } + if (pinfo->active) + { + // Timer already running - exit silently + return NRF_SUCCESS; + } + + pinfo->argument = p_context; + + if (__get_IPSR() != 0) + { + BaseType_t yieldReq = pdFALSE; + + if (xTimerChangePeriodFromISR(hTimer, timeout_ticks, &yieldReq) != pdPASS) + { + return NRF_ERROR_NO_MEM; + } + + if ( xTimerStartFromISR(hTimer, &yieldReq) != pdPASS ) + { + return NRF_ERROR_NO_MEM; + } + + portYIELD_FROM_ISR(yieldReq); + } + else + { + if (xTimerChangePeriod(hTimer, timeout_ticks, APP_TIMER_WAIT_FOR_QUEUE) != pdPASS) + { + return NRF_ERROR_NO_MEM; + } + + if (xTimerStart(hTimer, APP_TIMER_WAIT_FOR_QUEUE) != pdPASS) + { + return NRF_ERROR_NO_MEM; + } + } + + pinfo->active = true; + return NRF_SUCCESS; +} + + +uint32_t app_timer_stop(app_timer_id_t timer_id) +{ + app_timer_info_t * pinfo = (app_timer_info_t*)(timer_id); + TimerHandle_t hTimer = pinfo->osHandle; + if (hTimer == NULL) + { + return NRF_ERROR_INVALID_STATE; + } + + if (__get_IPSR() != 0) + { + BaseType_t yieldReq = pdFALSE; + if (xTimerStopFromISR(hTimer, &yieldReq) != pdPASS) + { + return NRF_ERROR_NO_MEM; + } + portYIELD_FROM_ISR(yieldReq); + } + else + { + if (xTimerStop(hTimer, APP_TIMER_WAIT_FOR_QUEUE) != pdPASS) + { + return NRF_ERROR_NO_MEM; + } + } + + pinfo->active = false; + return NRF_SUCCESS; +} +#endif //NRF_MODULE_ENABLED(APP_TIMER) diff --git a/components/libraries/timer/app_timer_rtx.c b/components/libraries/timer/app_timer_rtx.c new file mode 100644 index 0000000..aaebbdd --- /dev/null +++ b/components/libraries/timer/app_timer_rtx.c @@ -0,0 +1,278 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(APP_TIMER) +#include "app_timer.h" +#include +#include "nrf.h" +#include "nrf_soc.h" +#include "app_error.h" +#include "cmsis_os.h" +#include "app_util_platform.h" + +#define RTC1_IRQ_PRI APP_IRQ_PRIORITY_LOWEST /**< Priority of the RTC1 interrupt. */ + +#define MAX_RTC_COUNTER_VAL 0x00FFFFFF /**< Maximum value of the RTC counter. */ + +/**@brief This structure keeps information about osTimer.*/ +typedef struct +{ + osTimerDef_t timerDef; + uint32_t buffer[6]; + osTimerId id; +}app_timer_info_t; + +/**@brief Store an array of timers with configuration. */ +typedef struct +{ + uint8_t max_timers; /**< The maximum number of timers*/ + uint32_t prescaler; + app_timer_info_t * app_timers; /**< Pointer to table of timers*/ +}app_timer_control_t; + +app_timer_control_t app_timer_control; + +/**@brief This structure is defined by RTX. It keeps information about created osTimers. It is used in app_timer_start(). */ +typedef struct os_timer_cb_ +{ + struct os_timer_cb_ * next; /**< Pointer to next active Timer */ + uint8_t state; /**< Timer State */ + uint8_t type; /**< Timer Type (Periodic/One-shot). */ + uint16_t reserved; /**< Reserved. */ + uint32_t tcnt; /**< Timer Delay Count. */ + uint32_t icnt; /**< Timer Initial Count. */ + void * arg; /**< Timer Function Argument. */ + const osTimerDef_t * timer; /**< Pointer to Timer definition. */ +} os_timer_cb; + +/**@brief This functions are defined by RTX.*/ +//lint --save -e10 -e19 -e526 +extern osStatus svcTimerStop(osTimerId timer_id); /**< Used in app_timer_stop(). */ +extern osStatus svcTimerStart(osTimerId timer_id, uint32_t millisec); /**< Used in app_timer_start(). */ +// lint --restore +static void * rt_id2obj (void *id) /**< Used in app_timer_start(). This function gives information if osTimerID is valid */ +{ + if ((uint32_t)id & 3U) + { + return NULL; + } + +#ifdef OS_SECTIONS_LINK_INFO + + if ((os_section_id$$Base != 0U) && (os_section_id$$Limit != 0U)) + { + if (id < (void *)os_section_id$$Base) + { + return NULL; + } + + if (id >= (void *)os_section_id$$Limit) + { + return NULL; + } + } +#endif + + return id; +} + + + +ret_code_t app_timer_init(void) +{ + if (p_buffer == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + + app_timer_control.app_timers = p_buffer; + NVIC_SetPriority(RTC1_IRQn, RTC1_IRQ_PRI); + + return NRF_SUCCESS; +} + + +ret_code_t app_timer_create(app_timer_id_t const * p_timer_id, + app_timer_mode_t mode, + app_timer_timeout_handler_t timeout_handler) +{ + + if ((timeout_handler == NULL) || (p_timer_id == NULL)) + { + return NRF_ERROR_INVALID_PARAM; + } + + app_timer_info_t * p_timer_info = (app_timer_info_t *)*p_timer_id; + p_timer_info->timerDef.timer = p_timer_info->buffer; + p_timer_info->timerDef.ptimer = (os_ptimer)timeout_handler; + + p_timer_info->id = osTimerCreate(&(p_timer_info->timerDef), (os_timer_type)mode, NULL); + + if (p_timer_info->id) + return NRF_SUCCESS; + else + { + return NRF_ERROR_INVALID_PARAM; // This error is unspecified by rtx + } +} + +#define osTimerRunning 2 +ret_code_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context) +{ + if ((timeout_ticks < APP_TIMER_MIN_TIMEOUT_TICKS)) + { + return NRF_ERROR_INVALID_PARAM; + } + uint32_t timeout_ms = + ((uint32_t)ROUNDED_DIV(timeout_ticks * 1000 * (APP_TIMER_CONFIG_RTC_FREQUENCY + 1), + (uint32_t)APP_TIMER_CLOCK_FREQ)); + + app_timer_info_t * p_timer_info = (app_timer_info_t *)timer_id; + if (rt_id2obj((void *)p_timer_info->id) == NULL) + return NRF_ERROR_INVALID_PARAM; + + // Pass p_context to timer_timeout_handler + ((os_timer_cb *)(p_timer_info->id))->arg = p_context; + + if (((os_timer_cb *)(p_timer_info->id))->state == osTimerRunning) + { + return NRF_SUCCESS; + } + // osTimerStart() returns osErrorISR if it is called in interrupt routine. + switch (osTimerStart((osTimerId)p_timer_info->id, timeout_ms) ) + { + case osOK: + return NRF_SUCCESS; + + case osErrorISR: + break; + + case osErrorParameter: + return NRF_ERROR_INVALID_PARAM; + + default: + return NRF_ERROR_INVALID_PARAM; + } + + // Start timer without svcCall + switch (svcTimerStart((osTimerId)p_timer_info->id, timeout_ms)) + { + case osOK: + return NRF_SUCCESS; + + case osErrorISR: + return NRF_ERROR_INVALID_STATE; + + case osErrorParameter: + return NRF_ERROR_INVALID_PARAM; + + default: + return NRF_ERROR_INVALID_PARAM; + } +} + +ret_code_t app_timer_stop(app_timer_id_t timer_id) +{ + app_timer_info_t * p_timer_info = (app_timer_info_t *)timer_id; + switch (osTimerStop((osTimerId)p_timer_info->id) ) + { + case osOK: + return NRF_SUCCESS; + + case osErrorISR: + break; + + case osErrorParameter: + return NRF_ERROR_INVALID_PARAM; + + case osErrorResource: + return NRF_SUCCESS; + + default: + return NRF_ERROR_INVALID_PARAM; + } + + // Stop timer without svcCall + switch (svcTimerStop((osTimerId)p_timer_info->id)) + { + case osOK: + return NRF_SUCCESS; + + case osErrorISR: + return NRF_ERROR_INVALID_STATE; + + case osErrorParameter: + return NRF_ERROR_INVALID_PARAM; + + case osErrorResource: + return NRF_SUCCESS; + + default: + return NRF_ERROR_INVALID_PARAM; + } +} + + +ret_code_t app_timer_stop_all(void) +{ + for (int i = 0; i < app_timer_control.max_timers; i++) + { + if (app_timer_control.app_timers[i].id) + { + (void)app_timer_stop((app_timer_id_t)app_timer_control.app_timers[i].id); + } + } + return 0; +} + + +extern uint32_t os_tick_val(void); +uint32_t app_timer_cnt_get(void) +{ + return os_tick_val(); +} + + +uint32_t app_timer_cnt_diff_compute(uint32_t ticks_to, + uint32_t ticks_from) +{ + return ((ticks_to - ticks_from) & MAX_RTC_COUNTER_VAL); +} +#endif //NRF_MODULE_ENABLED(APP_TIMER) diff --git a/components/libraries/timer/drv_rtc.c b/components/libraries/timer/drv_rtc.c new file mode 100644 index 0000000..26e507d --- /dev/null +++ b/components/libraries/timer/drv_rtc.c @@ -0,0 +1,363 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include + +/* Module is integral part of app_timer implementation. */ +#define NRF_LOG_MODULE_NAME app_timer +#include + +#define EVT_TO_STR(event) \ + (event == NRF_RTC_EVENT_TICK ? "NRF_RTC_EVENT_TICK" : \ + (event == NRF_RTC_EVENT_OVERFLOW ? "NRF_RTC_EVENT_OVERFLOW" : \ + (event == NRF_RTC_EVENT_COMPARE_0 ? "NRF_RTC_EVENT_COMPARE_0" : \ + (event == NRF_RTC_EVENT_COMPARE_1 ? "NRF_RTC_EVENT_COMPARE_1" : \ + (event == NRF_RTC_EVENT_COMPARE_2 ? "NRF_RTC_EVENT_COMPARE_2" : \ + (event == NRF_RTC_EVENT_COMPARE_3 ? "NRF_RTC_EVENT_COMPARE_3" : \ + "UNKNOWN EVENT")))))) +#if defined ( __ICCARM__ ) +/* IAR gives warning for offsetof with non-constant expression.*/ +#define CC_IDX_TO_CC_EVENT(_cc) \ + ((nrf_rtc_event_t)(offsetof(NRF_RTC_Type, EVENTS_COMPARE[0]) + sizeof(uint32_t)*_cc)) +#else +#define CC_IDX_TO_CC_EVENT(_cc) \ + ((nrf_rtc_event_t)(offsetof(NRF_RTC_Type, EVENTS_COMPARE[_cc]))) +#endif + +/**@brief RTC driver instance control block structure. */ +typedef struct +{ + drv_rtc_t const * p_instance; + nrfx_drv_state_t state; /**< Instance state. */ +} drv_rtc_cb_t; + +// User callbacks local storage. +static drv_rtc_handler_t m_handlers[DRV_RTC_ENABLED_COUNT]; +static drv_rtc_cb_t m_cb[DRV_RTC_ENABLED_COUNT]; + +// According to Produce Specification RTC may not trigger COMPARE event if CC value set is equal to +// COUNTER value or COUNTER+1. +#define COUNTER_TO_CC_MIN_DISTANCE 2 + +ret_code_t drv_rtc_init(drv_rtc_t const * const p_instance, + drv_rtc_config_t const * p_config, + drv_rtc_handler_t handler) +{ + ASSERT(p_instance); + ASSERT(p_config); + ASSERT(handler); + + ret_code_t err_code; + + m_handlers[p_instance->instance_id] = handler; + + if (m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("RTC instance already initialized."); + return err_code; + } + + nrf_rtc_prescaler_set(p_instance->p_reg, p_config->prescaler); + NRFX_IRQ_PRIORITY_SET(p_instance->irq, p_config->interrupt_priority); + NRFX_IRQ_ENABLE(p_instance->irq); + + m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_INITIALIZED; + m_cb[p_instance->instance_id].p_instance = p_instance; + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("RTC: initialized."); + return err_code; +} + +void drv_rtc_uninit(drv_rtc_t const * const p_instance) +{ + ASSERT(p_instance); + uint32_t mask = NRF_RTC_INT_TICK_MASK | + NRF_RTC_INT_OVERFLOW_MASK | + NRF_RTC_INT_COMPARE0_MASK | + NRF_RTC_INT_COMPARE1_MASK | + NRF_RTC_INT_COMPARE2_MASK | + NRF_RTC_INT_COMPARE3_MASK; + ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED); + + NRFX_IRQ_DISABLE(p_instance->irq); + + drv_rtc_stop(p_instance); + nrf_rtc_event_disable(p_instance->p_reg, mask); + nrf_rtc_int_disable(p_instance->p_reg, mask); + + m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_UNINITIALIZED; + NRF_LOG_INFO("RTC: Uninitialized."); +} + +void drv_rtc_start(drv_rtc_t const * const p_instance) +{ + ASSERT(p_instance); + nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_START); +} + +void drv_rtc_stop(drv_rtc_t const * const p_instance) +{ + ASSERT(p_instance); + nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_STOP); +} + +void drv_rtc_compare_set(drv_rtc_t const * const p_instance, + uint32_t cc, + uint32_t abs_value, + bool irq_enable) +{ + ASSERT(p_instance); + nrf_rtc_int_t cc_int_mask = (nrf_rtc_int_t)(NRF_RTC_INT_COMPARE0_MASK << cc); + nrf_rtc_event_t cc_evt = CC_IDX_TO_CC_EVENT(cc); + abs_value &= RTC_COUNTER_COUNTER_Msk; + + nrf_rtc_int_disable(p_instance->p_reg, cc_int_mask); + nrf_rtc_event_disable(p_instance->p_reg, cc_int_mask); + nrf_rtc_event_clear(p_instance->p_reg, cc_evt); + nrf_rtc_cc_set(p_instance->p_reg, cc,abs_value); + nrf_rtc_event_enable(p_instance->p_reg, cc_int_mask); + + if (irq_enable) + { + nrf_rtc_int_enable(p_instance->p_reg, cc_int_mask); + } +} + +static void evt_enable(drv_rtc_t const * const p_instance, uint32_t mask, bool irq_enable) +{ + ASSERT(p_instance); + nrf_rtc_event_enable(p_instance->p_reg, mask); + if (irq_enable) + { + nrf_rtc_int_enable(p_instance->p_reg, mask); + } +} + +static void evt_disable(drv_rtc_t const * const p_instance, uint32_t mask) +{ + ASSERT(p_instance); + nrf_rtc_event_disable(p_instance->p_reg, mask); + nrf_rtc_int_disable(p_instance->p_reg, mask); +} + +static bool evt_pending(drv_rtc_t const * const p_instance, nrf_rtc_event_t event) +{ + ASSERT(p_instance); + if (nrf_rtc_event_pending(p_instance->p_reg, event)) + { + nrf_rtc_event_clear(p_instance->p_reg, event); + return true; + } + return false; +} + +static uint32_t ticks_sub(uint32_t a, uint32_t b) +{ + return (a - b) & RTC_COUNTER_COUNTER_Msk; +} + +ret_code_t drv_rtc_windowed_compare_set(drv_rtc_t const * const p_instance, + uint32_t cc, + uint32_t abs_value, + uint32_t safe_window) +{ + ASSERT(p_instance); + uint32_t prev_cc_set; + uint32_t now; + uint32_t diff; + nrf_rtc_int_t cc_int_mask = (nrf_rtc_int_t)(NRF_RTC_INT_COMPARE0_MASK << cc); + nrf_rtc_event_t cc_evt = CC_IDX_TO_CC_EVENT(cc);; + abs_value &=RTC_COUNTER_COUNTER_Msk; + + evt_disable(p_instance, cc_int_mask); + + /* First handle potential prefiring caused by CC being set to next tick. Even if CC is + * overwritten it may happen that event will be generated for previous CC in next tick. + * Following algorith is applied: + * - read previous CC + * - write current counter value to CC (furtherest in future) + * - if previous CC was in one tick from now wait half of the 32k tick and clear event which + * may be set. Half tick delay is used because CC is latched in the middle of the 32k tick. + */ + now = nrf_rtc_counter_get(p_instance->p_reg); + prev_cc_set = nrf_rtc_cc_get(p_instance->p_reg, cc); + nrf_rtc_cc_set(p_instance->p_reg, cc, now); + nrf_rtc_event_clear(p_instance->p_reg, cc_evt); + + if (ticks_sub(prev_cc_set, now) == 1) + { + nrf_delay_us(16); + nrf_rtc_event_clear(p_instance->p_reg, cc_evt); + } + + now = nrf_rtc_counter_get(p_instance->p_reg); + diff = ticks_sub(abs_value, now); + + nrf_rtc_event_enable(p_instance->p_reg, cc_int_mask); + + /* Setting CC for +1 from now may not generate event. In that case set CC+2 and check if counter + * changed during that process. If changed it means that 1 tick expired. */ + if (diff == 1) + { + nrf_rtc_cc_set(p_instance->p_reg, cc, abs_value + 1); + nrf_delay_us(16); + if (now != nrf_rtc_counter_get(p_instance->p_reg)) + { + /* one tick elapsed already. */ + return NRF_ERROR_TIMEOUT; + } + } else { + nrf_rtc_cc_set(p_instance->p_reg, cc, abs_value); + now = nrf_rtc_counter_get(p_instance->p_reg); + diff = ticks_sub(abs_value - 1, now); + /* Check if counter equals cc value or is behind in the safe window. If yes it means that + * CC expired. */ + if (diff > (RTC_COUNTER_COUNTER_Msk - safe_window)) + { + return NRF_ERROR_TIMEOUT; + } + else if (diff == 0) + { + /* If cc value == counter + 1, it may hit +1 case. */ + nrf_rtc_cc_set(p_instance->p_reg, cc, abs_value + 1); + if (now != nrf_rtc_counter_get(p_instance->p_reg)) + { + /* one tick elapsed already. */ + return NRF_ERROR_TIMEOUT; + } + } + } + + evt_enable(p_instance, cc_int_mask, true); + + return NRF_SUCCESS; +} + +void drv_rtc_overflow_enable(drv_rtc_t const * const p_instance, bool irq_enable) +{ + evt_enable(p_instance, NRF_RTC_INT_OVERFLOW_MASK, irq_enable); +} + +void drv_rtc_overflow_disable(drv_rtc_t const * const p_instance) +{ + evt_disable(p_instance, NRF_RTC_INT_OVERFLOW_MASK); +} + +bool drv_rtc_overflow_pending(drv_rtc_t const * const p_instance) +{ + return evt_pending(p_instance, NRF_RTC_EVENT_OVERFLOW); +} + +void drv_rtc_tick_enable(drv_rtc_t const * const p_instance, bool irq_enable) +{ + evt_enable(p_instance, NRF_RTC_INT_TICK_MASK, irq_enable); +} + +void drv_rtc_tick_disable(drv_rtc_t const * const p_instance) +{ + evt_disable(p_instance, NRF_RTC_INT_TICK_MASK); +} + +bool drv_rtc_tick_pending(drv_rtc_t const * const p_instance) +{ + return evt_pending(p_instance, NRF_RTC_EVENT_TICK); +} + +void drv_rtc_compare_enable(drv_rtc_t const * const p_instance, + uint32_t cc, + bool irq_enable) +{ + evt_enable(p_instance, (uint32_t)NRF_RTC_INT_COMPARE0_MASK << cc, irq_enable); +} + +void drv_rtc_compare_disable(drv_rtc_t const * const p_instance, uint32_t cc) +{ + evt_disable(p_instance, (uint32_t)NRF_RTC_INT_COMPARE0_MASK << cc); +} + +bool drv_rtc_compare_pending(drv_rtc_t const * const p_instance, uint32_t cc) +{ + nrf_rtc_event_t cc_evt = CC_IDX_TO_CC_EVENT(cc); + return evt_pending(p_instance, cc_evt); +} + +uint32_t drv_rtc_compare_get(drv_rtc_t const * const p_instance, uint32_t cc) +{ + return nrf_rtc_cc_get(p_instance->p_reg, cc); +} + +uint32_t drv_rtc_counter_get(drv_rtc_t const * const p_instance) +{ + return nrf_rtc_counter_get(p_instance->p_reg); +} + +void drv_rtc_irq_trigger(drv_rtc_t const * const p_instance) +{ + NVIC_SetPendingIRQ(p_instance->irq); +} + +#define drv_rtc_rtc_0_irq_handler RTC0_IRQHandler +#define drv_rtc_rtc_1_irq_handler RTC1_IRQHandler +#define drv_rtc_rtc_2_irq_handler RTC2_IRQHandler + +#if defined(APP_TIMER_V2_RTC0_ENABLED) +void drv_rtc_rtc_0_irq_handler(void) +{ + m_handlers[DRV_RTC_RTC0_INST_IDX](m_cb[DRV_RTC_RTC0_INST_IDX].p_instance); +} +#endif + +#if defined(APP_TIMER_V2_RTC1_ENABLED) +void drv_rtc_rtc_1_irq_handler(void) +{ + m_handlers[DRV_RTC_RTC1_INST_IDX](m_cb[DRV_RTC_RTC1_INST_IDX].p_instance); +} +#endif + +#if defined(APP_TIMER_V2_RTC2_ENABLED) +void drv_rtc_rtc_2_irq_handler(void) +{ + m_handlers[DRV_RTC_RTC2_INST_IDX](m_cb[DRV_RTC_RTC2_INST_IDX].p_instance); +} +#endif diff --git a/components/libraries/timer/drv_rtc.h b/components/libraries/timer/drv_rtc.h new file mode 100644 index 0000000..6f7d912 --- /dev/null +++ b/components/libraries/timer/drv_rtc.h @@ -0,0 +1,315 @@ +/** + * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef DRV_RTC_H__ +#define DRV_RTC_H__ + +#include +#include +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup drv_rtc RTC driver + * @{ + * @ingroup app_timer + * @brief Real Timer Counter (RTC) peripheral driver for app_timer. + */ + +/** @brief Maximum RTC counter value. */ +#define DRV_RTC_MAX_CNT RTC_COUNTER_COUNTER_Msk + +/** @brief Time requires to update registers between RTC and MCU domains. */ +#define DRV_RTC_CONFIG_APPLY_TIME_US 33 + +/** + * @brief Minimum delta value between set value and counter value. + * + * RTC peripheral requires two ticks to be sure that value it properly set in RTC value. Compare + * channel function requires additional one tick to avoid problematic situations (lack or additional + * unspecified event) when Compare Channel register is reseting or setting to N+2 value. + */ +#define DRV_RTC_MIN_TICK_HANDLED 3 + +/** @brief Macro to convert microseconds into ticks. */ +#define DRV_RTC_US_TO_TICKS(us,freq) (us >= 2^17 ? \ + ((((us)/1000)*(freq))/1000U) : (((us)*(freq))/1000000U) ) + + +/** @brief RTC driver instance structure. */ +typedef struct +{ + NRF_RTC_Type * p_reg; /**< Pointer to instance register set. */ + IRQn_Type irq; /**< Instance IRQ ID. */ + uint8_t instance_id; /**< Instance index. */ + uint8_t cc_channel_count; /**< Number of capture/compare channels. */ +} drv_rtc_t; + +/** @brief Macro for creating RTC driver instance.*/ +#define DRV_RTC_INSTANCE(id) \ +{ \ + .p_reg = NRFX_CONCAT_2(NRF_RTC, id), \ + .irq = NRFX_CONCAT_3(RTC, id, _IRQn), \ + .instance_id = NRFX_CONCAT_3(DRV_RTC_RTC, id, _INST_IDX), \ + .cc_channel_count = NRF_RTC_CC_CHANNEL_COUNT(id), \ +} + +enum { +#if defined(APP_TIMER_V2_RTC0_ENABLED) + DRV_RTC_RTC0_INST_IDX, +#endif +#if defined(APP_TIMER_V2_RTC1_ENABLED) + DRV_RTC_RTC1_INST_IDX, +#endif +#if defined(APP_TIMER_V2_RTC2_ENABLED) + DRV_RTC_RTC2_INST_IDX, +#endif + DRV_RTC_ENABLED_COUNT +}; + +/** @brief RTC driver instance configuration structure. */ +typedef struct +{ + uint16_t prescaler; /**< Prescaler. */ + uint8_t interrupt_priority; /**< Interrupt priority. */ +} drv_rtc_config_t; + +/** @brief RTC instance default configuration. */ +#define DRV_RTC_DEFAULT_CONFIG \ +{ \ + .prescaler = RTC_FREQ_TO_PRESCALER(DRV_RTC_DEFAULT_CONFIG_FREQUENCY), \ + .interrupt_priority = DRV_RTC_DEFAULT_CONFIG_IRQ_PRIORITY, \ +} + +/** @brief RTC driver instance handler type. */ +typedef void (*drv_rtc_handler_t)(drv_rtc_t const * const p_instance); + +/** + * @brief Function for initializing the RTC driver instance. + * + * After initialization, the instance is in power off state. The LFCLK (@ref nrfx_clock) + * has to be started before using @ref drv_rtc. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_config Pointer to the structure with initial configuration. + * @param[in] handler Event handler provided by the user. Must not be NULL. + * + * @retval NRF_SUCCESS If successfully initialized. + * @retval NRF_ERROR_INVALID_STATE If the instance is already initialized. + */ +ret_code_t drv_rtc_init(drv_rtc_t const * const p_instance, + drv_rtc_config_t const * p_config, + drv_rtc_handler_t handler); + +/** + * @brief Function for uninitializing the RTC driver instance. + * + * After uninitialization, the instance is in idle state. The hardware should return to the state + * before initialization. The function asserts if the instance is in idle state. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void drv_rtc_uninit(drv_rtc_t const * const p_instance); + +/** + * @brief Function for starting RTC clock. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void drv_rtc_start(drv_rtc_t const * const p_instance); + +/** + * @brief Function for stopping RTC clock. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void drv_rtc_stop(drv_rtc_t const * const p_instance); + +/** + * @brief Function for configuring compare channel. + * + * @note Function disables interrupts and only enable compare events. Remember to enable interrupt + * using @ref drv_rtc_compare_enable in case of using it. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] cc Compare channel index. + * @param[in] abs_value Absolute value to be set in the compare register. + * @param[in] irq_enable True to enable interrupt. + */ +void drv_rtc_compare_set(drv_rtc_t const * const p_instance, + uint32_t cc, + uint32_t abs_value, + bool irq_enable); + +/** + * @brief Function for configuring compare channel with safe window. + * + * Maximum possible relative value is limited by safe window to detect + * cases when requested compare event has already occured. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] cc Compare channel index. + * @param[in] abs_value Absolute value to be set in the compare register. + * @param[in] safe_window Width of the safe window. + * + * @retval NRF_ERROR_TIMEOUT If @par abs_value is in safe window of event occured before + * enabling compare channel intterupt. + * @retval NRF_SUCCESS If successfully set. + */ +ret_code_t drv_rtc_windowed_compare_set(drv_rtc_t const * const p_instance, + uint32_t cc, + uint32_t abs_value, + uint32_t safe_window); + +/** + * @brief Function for enabling overflow event and interrupt. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] irq_enable True to enable interrupt. + */ +void drv_rtc_overflow_enable(drv_rtc_t const * const p_instance, bool irq_enable); + +/** + * @brief Function for diabling overflow event and interrupt. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void drv_rtc_overflow_disable(drv_rtc_t const * const p_instance); + +/** + * @brief Function for checking if overflow event has occured. + * + * @note Event is cleared after reading. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @return True if interrupt pending, false otherwise. + */ +bool drv_rtc_overflow_pending(drv_rtc_t const * const p_instance); + +/** + * @brief Function for enabling tick event and interrupt. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] irq_enable True to enable interrupt. + */ +void drv_rtc_tick_enable(drv_rtc_t const * const p_instance, bool irq_enable); + +/** + * @brief Function for disabling tick event and interrupt. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void drv_rtc_tick_disable(drv_rtc_t const * const p_instance); + +/** + * @brief Function for checking if tick event has occured. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @return True if interrupt pending, false otherwise. + */ +bool drv_rtc_tick_pending(drv_rtc_t const * const p_instance); + +/** + * @brief Function for enabling compare channel event and interrupt. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] cc Compare channel index. + * @param[in] irq_enable True to enable interrupt. + */ +void drv_rtc_compare_enable(drv_rtc_t const * const p_instance, + uint32_t cc, + bool irq_enable); + +/** + * @brief Function for disabling compare channel event and interrupt. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] cc Compare channel index. + */ +void drv_rtc_compare_disable(drv_rtc_t const * const p_instance, uint32_t cc); + +/** + * @brief Function for checking if compare channel event has occured. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] cc Compare channel index. + * + * @return True if interrupt pending, false otherwise. + */ +bool drv_rtc_compare_pending(drv_rtc_t const * const p_instance, uint32_t cc); + +/** + * @brief Function for reading compare value. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] cc Compare channel index. + * + * @return Compare value set for given channel. + */ +uint32_t drv_rtc_compare_get(drv_rtc_t const * const p_instance, uint32_t cc); + +/** + * @brief Function for getting current value of RTC counter. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @return Counter value. + */ +uint32_t drv_rtc_counter_get(drv_rtc_t const * const p_instance); + +/** + * @brief Function for triggering RTC interrupt. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void drv_rtc_irq_trigger(drv_rtc_t const * const p_instance); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // DRV_RTC_H__ diff --git a/components/libraries/uart/app_uart.c b/components/libraries/uart/app_uart.c new file mode 100644 index 0000000..a7b4f92 --- /dev/null +++ b/components/libraries/uart/app_uart.c @@ -0,0 +1,164 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(APP_UART) +#include "app_uart.h" +#include "nrf_drv_uart.h" +#include "nrf_assert.h" + +static uint8_t tx_buffer[1]; +static uint8_t rx_buffer[1]; +static volatile bool rx_done; +static app_uart_event_handler_t m_event_handler; /**< Event handler function. */ +static nrf_drv_uart_t app_uart_inst = NRF_DRV_UART_INSTANCE(APP_UART_DRIVER_INSTANCE); + +static void uart_event_handler(nrf_drv_uart_event_t * p_event, void* p_context) +{ + if (p_event->type == NRF_DRV_UART_EVT_RX_DONE) + { + // Received bytes counter has to be checked, because there could be event from RXTO interrupt + if (p_event->data.rxtx.bytes) + { + app_uart_evt_t app_uart_event; + app_uart_event.evt_type = APP_UART_DATA; + app_uart_event.data.value = p_event->data.rxtx.p_data[0]; + rx_done = true; + m_event_handler(&app_uart_event); + } + (void)nrf_drv_uart_rx(&app_uart_inst, rx_buffer, 1); + } + else if (p_event->type == NRF_DRV_UART_EVT_ERROR) + { + app_uart_evt_t app_uart_event; + app_uart_event.evt_type = APP_UART_COMMUNICATION_ERROR; + app_uart_event.data.error_communication = p_event->data.error.error_mask; + (void)nrf_drv_uart_rx(&app_uart_inst, rx_buffer, 1); + m_event_handler(&app_uart_event); + } + else if (p_event->type == NRF_DRV_UART_EVT_TX_DONE) + { + // Last byte from FIFO transmitted, notify the application. + // Notify that new data is available if this was first byte put in the buffer. + app_uart_evt_t app_uart_event; + app_uart_event.evt_type = APP_UART_TX_EMPTY; + m_event_handler(&app_uart_event); + } +} + +uint32_t app_uart_init(const app_uart_comm_params_t * p_comm_params, + app_uart_buffers_t * p_buffers, + app_uart_event_handler_t event_handler, + app_irq_priority_t irq_priority) +{ + nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG; + config.baudrate = (nrf_uart_baudrate_t)p_comm_params->baud_rate; + config.hwfc = (p_comm_params->flow_control == APP_UART_FLOW_CONTROL_DISABLED) ? + NRF_UART_HWFC_DISABLED : NRF_UART_HWFC_ENABLED; + config.interrupt_priority = irq_priority; + config.parity = p_comm_params->use_parity ? NRF_UART_PARITY_INCLUDED : NRF_UART_PARITY_EXCLUDED; + config.pselcts = p_comm_params->cts_pin_no; + config.pselrts = p_comm_params->rts_pin_no; + config.pselrxd = p_comm_params->rx_pin_no; + config.pseltxd = p_comm_params->tx_pin_no; + + m_event_handler = event_handler; + + rx_done = false; + + uint32_t err_code = nrf_drv_uart_init(&app_uart_inst, &config, uart_event_handler); + VERIFY_SUCCESS(err_code); + + // Turn on receiver if RX pin is connected + if (p_comm_params->rx_pin_no != UART_PIN_DISCONNECTED) + { + return nrf_drv_uart_rx(&app_uart_inst, rx_buffer,1); + } + else + { + return NRF_SUCCESS; + } +} + + +uint32_t app_uart_get(uint8_t * p_byte) +{ + ASSERT(p_byte); + uint32_t err_code = NRF_SUCCESS; + if (rx_done) + { + *p_byte = rx_buffer[0]; + rx_done = false; + } + else + { + err_code = NRF_ERROR_NOT_FOUND; + } + return err_code; +} + +uint32_t app_uart_put(uint8_t byte) +{ + tx_buffer[0] = byte; + ret_code_t ret = nrf_drv_uart_tx(&app_uart_inst, tx_buffer, 1); + if (NRF_ERROR_BUSY == ret) + { + return NRF_ERROR_NO_MEM; + } + else if (ret != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + else + { + return NRF_SUCCESS; + } +} + +uint32_t app_uart_flush(void) +{ + return NRF_SUCCESS; +} + +uint32_t app_uart_close(void) +{ + nrf_drv_uart_uninit(&app_uart_inst); + return NRF_SUCCESS; +} +#endif //NRF_MODULE_ENABLED(APP_UART) diff --git a/components/libraries/uart/app_uart.h b/components/libraries/uart/app_uart.h new file mode 100644 index 0000000..ba2fed5 --- /dev/null +++ b/components/libraries/uart/app_uart.h @@ -0,0 +1,262 @@ +/** + * Copyright (c) 2013 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup app_uart UART module + * @{ + * @ingroup app_common + * + * @brief UART module interface. + */ + +#ifndef APP_UART_H__ +#define APP_UART_H__ + +#include +#include +#include "app_util_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UART_PIN_DISCONNECTED 0xFFFFFFFF /**< Value indicating that no pin is connected to this UART register. */ + +/**@brief UART Flow Control modes for the peripheral. + */ +typedef enum +{ + APP_UART_FLOW_CONTROL_DISABLED, /**< UART Hw Flow Control is disabled. */ + APP_UART_FLOW_CONTROL_ENABLED, /**< Standard UART Hw Flow Control is enabled. */ +} app_uart_flow_control_t; + +/**@brief UART communication structure holding configuration settings for the peripheral. + */ +typedef struct +{ + uint32_t rx_pin_no; /**< RX pin number. */ + uint32_t tx_pin_no; /**< TX pin number. */ + uint32_t rts_pin_no; /**< RTS pin number, only used if flow control is enabled. */ + uint32_t cts_pin_no; /**< CTS pin number, only used if flow control is enabled. */ + app_uart_flow_control_t flow_control; /**< Flow control setting, if flow control is used, the system will use low power UART mode, based on CTS signal. */ + bool use_parity; /**< Even parity if TRUE, no parity if FALSE. */ + uint32_t baud_rate; /**< Baud rate configuration. */ +} app_uart_comm_params_t; + +/**@brief UART buffer for transmitting/receiving data. + */ +typedef struct +{ + uint8_t * rx_buf; /**< Pointer to the RX buffer. */ + uint32_t rx_buf_size; /**< Size of the RX buffer. */ + uint8_t * tx_buf; /**< Pointer to the TX buffer. */ + uint32_t tx_buf_size; /**< Size of the TX buffer. */ +} app_uart_buffers_t; + +/**@brief Enumeration which defines events used by the UART module upon data reception or error. + * + * @details The event type is used to indicate the type of additional information in the event + * @ref app_uart_evt_t. + */ +typedef enum +{ + APP_UART_DATA_READY, /**< An event indicating that UART data has been received. The data is available in the FIFO and can be fetched using @ref app_uart_get. */ + APP_UART_FIFO_ERROR, /**< An error in the FIFO module used by the app_uart module has occured. The FIFO error code is stored in app_uart_evt_t.data.error_code field. */ + APP_UART_COMMUNICATION_ERROR, /**< An communication error has occured during reception. The error is stored in app_uart_evt_t.data.error_communication field. */ + APP_UART_TX_EMPTY, /**< An event indicating that UART has completed transmission of all available data in the TX FIFO. */ + APP_UART_DATA, /**< An event indicating that UART data has been received, and data is present in data field. This event is only used when no FIFO is configured. */ +} app_uart_evt_type_t; + +/**@brief Struct containing events from the UART module. + * + * @details The app_uart_evt_t is used to notify the application of asynchronous events when data + * are received on the UART peripheral or in case an error occured during data reception. + */ +typedef struct +{ + app_uart_evt_type_t evt_type; /**< Type of event. */ + union + { + uint32_t error_communication; /**< Field used if evt_type is: APP_UART_COMMUNICATION_ERROR. This field contains the value in the ERRORSRC register for the UART peripheral. The UART_ERRORSRC_x defines from nrf5x_bitfields.h can be used to parse the error code. See also the \nRFXX Series Reference Manual for specification. */ + uint32_t error_code; /**< Field used if evt_type is: NRF_ERROR_x. Additional status/error code if the error event type is APP_UART_FIFO_ERROR. This error code refer to errors defined in nrf_error.h. */ + uint8_t value; /**< Field used if evt_type is: NRF_ERROR_x. Additional status/error code if the error event type is APP_UART_FIFO_ERROR. This error code refer to errors defined in nrf_error.h. */ + } data; +} app_uart_evt_t; + +/**@brief Function for handling app_uart event callback. + * + * @details Upon an event in the app_uart module this callback function will be called to notify + * the application about the event. + * + * @param[in] p_app_uart_event Pointer to UART event. + */ +typedef void (* app_uart_event_handler_t) (app_uart_evt_t * p_app_uart_event); + +/**@brief Macro for safe initialization of the UART module in a single user instance when using + * a FIFO together with UART. + * + * @param[in] P_COMM_PARAMS Pointer to a UART communication structure: app_uart_comm_params_t + * @param[in] RX_BUF_SIZE Size of desired RX buffer, must be a power of 2 or ZERO (No FIFO). + * @param[in] TX_BUF_SIZE Size of desired TX buffer, must be a power of 2 or ZERO (No FIFO). + * @param[in] EVT_HANDLER Event handler function to be called when an event occurs in the + * UART module. + * @param[in] IRQ_PRIO IRQ priority, app_irq_priority_t, for the UART module irq handler. + * @param[out] ERR_CODE The return value of the UART initialization function will be + * written to this parameter. + * + * @note Since this macro allocates a buffer and registers the module as a GPIOTE user when flow + * control is enabled, it must only be called once. + */ +#define APP_UART_FIFO_INIT(P_COMM_PARAMS, RX_BUF_SIZE, TX_BUF_SIZE, EVT_HANDLER, IRQ_PRIO, ERR_CODE) \ + do \ + { \ + app_uart_buffers_t buffers; \ + static uint8_t rx_buf[RX_BUF_SIZE]; \ + static uint8_t tx_buf[TX_BUF_SIZE]; \ + \ + buffers.rx_buf = rx_buf; \ + buffers.rx_buf_size = sizeof (rx_buf); \ + buffers.tx_buf = tx_buf; \ + buffers.tx_buf_size = sizeof (tx_buf); \ + ERR_CODE = app_uart_init(P_COMM_PARAMS, &buffers, EVT_HANDLER, IRQ_PRIO); \ + } while (0) + +/**@brief Macro for safe initialization of the UART module in a single user instance. + * + * @param[in] P_COMM_PARAMS Pointer to a UART communication structure: app_uart_comm_params_t + * @param[in] EVT_HANDLER Event handler function to be called when an event occurs in the + * UART module. + * @param[in] IRQ_PRIO IRQ priority, app_irq_priority_t, for the UART module irq handler. + * @param[out] ERR_CODE The return value of the UART initialization function will be + * written to this parameter. + * + * @note Since this macro allocates registers the module as a GPIOTE user when flow control is + * enabled, it must only be called once. + */ +#define APP_UART_INIT(P_COMM_PARAMS, EVT_HANDLER, IRQ_PRIO, ERR_CODE) \ + do \ + { \ + ERR_CODE = app_uart_init(P_COMM_PARAMS, NULL, EVT_HANDLER, IRQ_PRIO); \ + } while (0) + +/**@brief Function for initializing the UART module. Use this initialization when several instances of the UART + * module are needed. + * + * + * @note Normally single initialization should be done using the APP_UART_INIT() or + * APP_UART_INIT_FIFO() macro depending on whether the FIFO should be used by the UART, as + * that will allocate the buffers needed by the UART module (including aligning the buffer + * correctly). + + * @param[in] p_comm_params Pin and communication parameters. + * @param[in] p_buffers RX and TX buffers, NULL is FIFO is not used. + * @param[in] error_handler Function to be called in case of an error. + * @param[in] irq_priority Interrupt priority level. + * + * @retval NRF_SUCCESS If successful initialization. + * @retval NRF_ERROR_INVALID_LENGTH If a provided buffer is not a power of two. + * @retval NRF_ERROR_NULL If one of the provided buffers is a NULL pointer. + * + * The below errors are propagated by the UART module to the caller upon registration when Hardware + * Flow Control is enabled. When Hardware Flow Control is not used, these errors cannot occur. + * @retval NRF_ERROR_INVALID_STATE The GPIOTE module is not in a valid state when registering + * the UART module as a user. + * @retval NRF_ERROR_INVALID_PARAM The UART module provides an invalid callback function when + * registering the UART module as a user. + * Or the value pointed to by *p_uart_uid is not a valid + * GPIOTE number. + * @retval NRF_ERROR_NO_MEM GPIOTE module has reached the maximum number of users. + */ +uint32_t app_uart_init(const app_uart_comm_params_t * p_comm_params, + app_uart_buffers_t * p_buffers, + app_uart_event_handler_t error_handler, + app_irq_priority_t irq_priority); + +/**@brief Function for getting a byte from the UART. + * + * @details This function will get the next byte from the RX buffer. If the RX buffer is empty + * an error code will be returned and the app_uart module will generate an event upon + * reception of the first byte which is added to the RX buffer. + * + * @param[out] p_byte Pointer to an address where next byte received on the UART will be copied. + * + * @retval NRF_SUCCESS If a byte has been received and pushed to the pointer provided. + * @retval NRF_ERROR_NOT_FOUND If no byte is available in the RX buffer of the app_uart module. + */ +uint32_t app_uart_get(uint8_t * p_byte); + +/**@brief Function for putting a byte on the UART. + * + * @details This call is non-blocking. + * + * @param[in] byte Byte to be transmitted on the UART. + * + * @retval NRF_SUCCESS If the byte was successfully put on the TX buffer for transmission. + * @retval NRF_ERROR_NO_MEM If no more space is available in the TX buffer. + * NRF_ERROR_NO_MEM may occur if flow control is enabled and CTS signal + * is high for a long period and the buffer fills up. + * @retval NRF_ERROR_INTERNAL If UART driver reported error. + */ +uint32_t app_uart_put(uint8_t byte); + +/**@brief Function for flushing the RX and TX buffers (Only valid if FIFO is used). + * This function does nothing if FIFO is not used. + * + * @retval NRF_SUCCESS Flushing completed (Current implementation will always succeed). + */ +uint32_t app_uart_flush(void); + +/**@brief Function for closing the UART module. + * + * @retval NRF_SUCCESS If successfully closed. + * @retval NRF_ERROR_INVALID_PARAM If an invalid user id is provided or the user id differs from + * the current active user. + */ +uint32_t app_uart_close(void); + + + +#ifdef __cplusplus +} +#endif + +#endif //APP_UART_H__ + +/** @} */ diff --git a/components/libraries/uart/app_uart_fifo.c b/components/libraries/uart/app_uart_fifo.c new file mode 100644 index 0000000..2e95736 --- /dev/null +++ b/components/libraries/uart/app_uart_fifo.c @@ -0,0 +1,252 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(APP_UART) +#include "app_uart.h" +#include "app_fifo.h" +#include "nrf_drv_uart.h" +#include "nrf_assert.h" + +static nrf_drv_uart_t app_uart_inst = NRF_DRV_UART_INSTANCE(APP_UART_DRIVER_INSTANCE); + +static __INLINE uint32_t fifo_length(app_fifo_t * const fifo) +{ + uint32_t tmp = fifo->read_pos; + return fifo->write_pos - tmp; +} + +#define FIFO_LENGTH(F) fifo_length(&F) /**< Macro to calculate length of a FIFO. */ + + +static app_uart_event_handler_t m_event_handler; /**< Event handler function. */ +static uint8_t tx_buffer[1]; +static uint8_t rx_buffer[1]; +static bool m_rx_ovf; + +static app_fifo_t m_rx_fifo; /**< RX FIFO buffer for storing data received on the UART until the application fetches them using app_uart_get(). */ +static app_fifo_t m_tx_fifo; /**< TX FIFO buffer for storing data to be transmitted on the UART when TXD is ready. Data is put to the buffer on using app_uart_put(). */ + +static void uart_event_handler(nrf_drv_uart_event_t * p_event, void* p_context) +{ + app_uart_evt_t app_uart_event; + uint32_t err_code; + + switch (p_event->type) + { + case NRF_DRV_UART_EVT_RX_DONE: + // If 0, then this is a RXTO event with no new bytes. + if(p_event->data.rxtx.bytes == 0) + { + // A new start RX is needed to continue to receive data + (void)nrf_drv_uart_rx(&app_uart_inst, rx_buffer, 1); + break; + } + + // Write received byte to FIFO. + err_code = app_fifo_put(&m_rx_fifo, p_event->data.rxtx.p_data[0]); + if (err_code != NRF_SUCCESS) + { + app_uart_event.evt_type = APP_UART_FIFO_ERROR; + app_uart_event.data.error_code = err_code; + m_event_handler(&app_uart_event); + } + // Notify that there are data available. + else if (FIFO_LENGTH(m_rx_fifo) != 0) + { + app_uart_event.evt_type = APP_UART_DATA_READY; + m_event_handler(&app_uart_event); + } + + // Start new RX if size in buffer. + if (FIFO_LENGTH(m_rx_fifo) <= m_rx_fifo.buf_size_mask) + { + (void)nrf_drv_uart_rx(&app_uart_inst, rx_buffer, 1); + } + else + { + // Overflow in RX FIFO. + m_rx_ovf = true; + } + + break; + + case NRF_DRV_UART_EVT_ERROR: + app_uart_event.evt_type = APP_UART_COMMUNICATION_ERROR; + app_uart_event.data.error_communication = p_event->data.error.error_mask; + (void)nrf_drv_uart_rx(&app_uart_inst, rx_buffer, 1); + m_event_handler(&app_uart_event); + break; + + case NRF_DRV_UART_EVT_TX_DONE: + // Get next byte from FIFO. + if (app_fifo_get(&m_tx_fifo, tx_buffer) == NRF_SUCCESS) + { + (void)nrf_drv_uart_tx(&app_uart_inst, tx_buffer, 1); + } + else + { + // Last byte from FIFO transmitted, notify the application. + app_uart_event.evt_type = APP_UART_TX_EMPTY; + m_event_handler(&app_uart_event); + } + break; + + default: + break; + } +} + + +uint32_t app_uart_init(const app_uart_comm_params_t * p_comm_params, + app_uart_buffers_t * p_buffers, + app_uart_event_handler_t event_handler, + app_irq_priority_t irq_priority) +{ + uint32_t err_code; + + m_event_handler = event_handler; + + if (p_buffers == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Configure buffer RX buffer. + err_code = app_fifo_init(&m_rx_fifo, p_buffers->rx_buf, p_buffers->rx_buf_size); + VERIFY_SUCCESS(err_code); + + // Configure buffer TX buffer. + err_code = app_fifo_init(&m_tx_fifo, p_buffers->tx_buf, p_buffers->tx_buf_size); + VERIFY_SUCCESS(err_code); + + nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG; + config.baudrate = (nrf_uart_baudrate_t)p_comm_params->baud_rate; + config.hwfc = (p_comm_params->flow_control == APP_UART_FLOW_CONTROL_DISABLED) ? + NRF_UART_HWFC_DISABLED : NRF_UART_HWFC_ENABLED; + config.interrupt_priority = irq_priority; + config.parity = p_comm_params->use_parity ? NRF_UART_PARITY_INCLUDED : NRF_UART_PARITY_EXCLUDED; + config.pselcts = p_comm_params->cts_pin_no; + config.pselrts = p_comm_params->rts_pin_no; + config.pselrxd = p_comm_params->rx_pin_no; + config.pseltxd = p_comm_params->tx_pin_no; + + err_code = nrf_drv_uart_init(&app_uart_inst, &config, uart_event_handler); + VERIFY_SUCCESS(err_code); + m_rx_ovf = false; + + // Turn on receiver if RX pin is connected + if (p_comm_params->rx_pin_no != UART_PIN_DISCONNECTED) + { + return nrf_drv_uart_rx(&app_uart_inst, rx_buffer,1); + } + else + { + return NRF_SUCCESS; + } +} + + +uint32_t app_uart_flush(void) +{ + uint32_t err_code; + + err_code = app_fifo_flush(&m_rx_fifo); + VERIFY_SUCCESS(err_code); + + err_code = app_fifo_flush(&m_tx_fifo); + VERIFY_SUCCESS(err_code); + + return NRF_SUCCESS; +} + + +uint32_t app_uart_get(uint8_t * p_byte) +{ + ASSERT(p_byte); + bool rx_ovf = m_rx_ovf; + + ret_code_t err_code = app_fifo_get(&m_rx_fifo, p_byte); + + // If FIFO was full new request to receive one byte was not scheduled. Must be done here. + if (rx_ovf) + { + m_rx_ovf = false; + uint32_t uart_err_code = nrf_drv_uart_rx(&app_uart_inst, rx_buffer, 1); + + // RX resume should never fail. + APP_ERROR_CHECK(uart_err_code); + } + + return err_code; +} + + +uint32_t app_uart_put(uint8_t byte) +{ + uint32_t err_code; + err_code = app_fifo_put(&m_tx_fifo, byte); + if (err_code == NRF_SUCCESS) + { + // The new byte has been added to FIFO. It will be picked up from there + // (in 'uart_event_handler') when all preceding bytes are transmitted. + // But if UART is not transmitting anything at the moment, we must start + // a new transmission here. + if (!nrf_drv_uart_tx_in_progress(&app_uart_inst)) + { + // This operation should be almost always successful, since we've + // just added a byte to FIFO, but if some bigger delay occurred + // (some heavy interrupt handler routine has been executed) since + // that time, FIFO might be empty already. + if (app_fifo_get(&m_tx_fifo, tx_buffer) == NRF_SUCCESS) + { + err_code = nrf_drv_uart_tx(&app_uart_inst, tx_buffer, 1); + } + } + } + return err_code; +} + + +uint32_t app_uart_close(void) +{ + nrf_drv_uart_uninit(&app_uart_inst); + return NRF_SUCCESS; +} +#endif //NRF_MODULE_ENABLED(APP_UART) diff --git a/components/libraries/uart/retarget.c b/components/libraries/uart/retarget.c new file mode 100644 index 0000000..b38e382 --- /dev/null +++ b/components/libraries/uart/retarget.c @@ -0,0 +1,186 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +/** @file + * + * @defgroup retarget Retarget layer for stdio functions + * @{ + * @ingroup app_common + * @} */ +#if NRF_MODULE_ENABLED(RETARGET) +#if !defined(NRF_LOG_USES_RTT) || NRF_LOG_USES_RTT != 1 +#if !defined(HAS_SIMPLE_UART_RETARGET) + + +#include +#include +#include "app_uart.h" +#include "nrf_error.h" + + +#if defined(__CC_ARM) + +// This part is taken from MDK-ARM template file and is required here to prevent +// linker from selecting libraries functions that use semihosting and failing +// because of multiple definitions of fgetc() and fputc(). +// Refer to: http://www.keil.com/support/man/docs/gsac/gsac_retargetcortex.htm +// -- BEGIN -- +struct __FILE { int handle; /* Add whatever you need here */ }; +FILE __stdout; +FILE __stdin; +// --- END --- + +int fgetc(FILE * p_file) +{ + uint8_t input; + while (app_uart_get(&input) == NRF_ERROR_NOT_FOUND) + { + // No implementation needed. + } + return input; +} + +int fputc(int ch, FILE * p_file) +{ + UNUSED_PARAMETER(p_file); + + UNUSED_VARIABLE(app_uart_put((uint8_t)ch)); + return ch; +} + +#elif defined(__GNUC__) && defined(__SES_ARM) + +int __getchar(FILE * p_file) +{ + uint8_t input; + while (app_uart_get(&input) == NRF_ERROR_NOT_FOUND) + { + // No implementation needed. + } + return input; +} + +#if defined(__SES_VERSION) && (__SES_VERSION >= 34000) +int __putchar(int ch, __printf_tag_ptr tag_ptr) +{ + UNUSED_PARAMETER(tag_ptr); + + UNUSED_VARIABLE(app_uart_put((uint8_t)ch)); + return ch; +} +#else +int __putchar(int ch, FILE * p_file) +{ + UNUSED_PARAMETER(p_file); + + UNUSED_VARIABLE(app_uart_put((uint8_t)ch)); + return ch; +} +#endif + +#elif defined(__GNUC__) && !defined(__SES_ARM) + +int _write(int file, const char * p_char, int len) +{ + int i; + + UNUSED_PARAMETER(file); + + for (i = 0; i < len; i++) + { + UNUSED_VARIABLE(app_uart_put(*p_char++)); + } + + return len; +} + +int _read(int file, char * p_char, int len) +{ + UNUSED_PARAMETER(file); + while (app_uart_get((uint8_t *)p_char) == NRF_ERROR_NOT_FOUND) + { + // No implementation needed. + } + + return 1; +} +#elif defined(__ICCARM__) + +size_t __write(int handle, const unsigned char * buffer, size_t size) +{ + int i; + UNUSED_PARAMETER(handle); + for (i = 0; i < size; i++) + { + UNUSED_VARIABLE(app_uart_put(*buffer++)); + } + return size; +} + +size_t __read(int handle, unsigned char * buffer, size_t size) +{ + UNUSED_PARAMETER(handle); + UNUSED_PARAMETER(size); + while (app_uart_get((uint8_t *)buffer) == NRF_ERROR_NOT_FOUND) + { + // No implementation needed. + } + + return 1; +} + +long __lseek(int handle, long offset, int whence) +{ + return -1; +} +int __close(int handle) +{ + return 0; +} +int remove(const char * filename) +{ + return 0; +} + +#endif + +#endif // !defined(HAS_SIMPLE_UART_RETARGET) +#endif // NRF_LOG_USES_RTT != 1 +#endif //NRF_MODULE_ENABLED(RETARGET) diff --git a/components/libraries/util/app_error.c b/components/libraries/util/app_error.c new file mode 100644 index 0000000..edc3ea7 --- /dev/null +++ b/components/libraries/util/app_error.c @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup app_error Common application error handler + * @{ + * @ingroup app_common + * + * @brief Common application error handler. + */ + +#include "nrf.h" +#include +#include "app_error.h" +#include "nordic_common.h" +#include "sdk_errors.h" + +/**@brief Function for error handling, which is called when an error has occurred. + * + * @warning This handler is an example only and does not fit a final product. You need to analyze + * how your product is supposed to react in case of error. + * + * @param[in] error_code Error code supplied to the handler. + * @param[in] line_num Line number where the handler is called. + * @param[in] p_file_name Pointer to the file name. + */ +void app_error_handler_bare(ret_code_t error_code) +{ + error_info_t error_info = + { + .line_num = 0, + .p_file_name = NULL, + .err_code = error_code, + }; + + app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info)); + + UNUSED_VARIABLE(error_info); +} + +void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info) +{ + /* static error variables - in order to prevent removal by optimizers */ + static volatile struct + { + uint32_t fault_id; + uint32_t pc; + uint32_t error_info; + assert_info_t * p_assert_info; + error_info_t * p_error_info; + ret_code_t err_code; + uint32_t line_num; + const uint8_t * p_file_name; + } m_error_data = {0}; + + // The following variable helps Keil keep the call stack visible, in addition, it can be set to + // 0 in the debugger to continue executing code after the error check. + volatile bool loop = true; + UNUSED_VARIABLE(loop); + + m_error_data.fault_id = id; + m_error_data.pc = pc; + m_error_data.error_info = info; + + switch (id) + { + case NRF_FAULT_ID_SDK_ASSERT: + m_error_data.p_assert_info = (assert_info_t *)info; + m_error_data.line_num = m_error_data.p_assert_info->line_num; + m_error_data.p_file_name = m_error_data.p_assert_info->p_file_name; + break; + + case NRF_FAULT_ID_SDK_ERROR: + m_error_data.p_error_info = (error_info_t *)info; + m_error_data.err_code = m_error_data.p_error_info->err_code; + m_error_data.line_num = m_error_data.p_error_info->line_num; + m_error_data.p_file_name = m_error_data.p_error_info->p_file_name; + break; + } + + UNUSED_VARIABLE(m_error_data); + + // If printing is disrupted, remove the irq calls, or set the loop variable to 0 in the debugger. + __disable_irq(); + while (loop); + + __enable_irq(); +} diff --git a/components/libraries/util/app_error.h b/components/libraries/util/app_error.h new file mode 100644 index 0000000..d65f620 --- /dev/null +++ b/components/libraries/util/app_error.h @@ -0,0 +1,194 @@ +/** + * Copyright (c) 2013 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup app_error Common application error handler + * @{ + * @ingroup app_common + * + * @brief Common application error handler and macros for utilizing a common error handler. + */ + +#ifndef APP_ERROR_H__ +#define APP_ERROR_H__ + + +#include +#include +#include +#include "nrf.h" +#include "sdk_errors.h" +#include "nordic_common.h" +#include "app_error_weak.h" +#ifdef ANT_STACK_SUPPORT_REQD +#include "ant_error.h" +#endif // ANT_STACK_SUPPORT_REQD + + + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_FAULT_ID_SDK_RANGE_START (0x00004000) /**< The start of the range of error IDs defined in the SDK. */ + +/**@defgroup APP_ERROR_FAULT_IDS Fault ID types + * @{ */ +#define NRF_FAULT_ID_SDK_ERROR (NRF_FAULT_ID_SDK_RANGE_START + 1) /**< An error stemming from a call to @ref APP_ERROR_CHECK or @ref APP_ERROR_CHECK_BOOL. The info parameter is a pointer to an @ref error_info_t variable. */ +#define NRF_FAULT_ID_SDK_ASSERT (NRF_FAULT_ID_SDK_RANGE_START + 2) /**< An error stemming from a call to ASSERT (nrf_assert.h). The info parameter is a pointer to an @ref assert_info_t variable. */ +/**@} */ + +/**@brief Structure containing info about an error of the type @ref NRF_FAULT_ID_SDK_ERROR. + */ +typedef struct +{ + uint32_t line_num; /**< The line number where the error occurred. */ + uint8_t const * p_file_name; /**< The file in which the error occurred. */ + uint32_t err_code; /**< The error code representing the error that occurred. */ +} error_info_t; + +/**@brief Structure containing info about an error of the type @ref NRF_FAULT_ID_SDK_ASSERT. + */ +typedef struct +{ + uint32_t line_num; /**< The line number where the error occurred. */ + uint8_t const * p_file_name; /**< The file in which the error occurred. */ +} assert_info_t; + +/**@brief Defines required by app_error_handler assembler intructions. + */ +#define APP_ERROR_ERROR_INFO_OFFSET_LINE_NUM (offsetof(error_info_t, line_num)) +#define APP_ERROR_ERROR_INFO_OFFSET_P_FILE_NAME (offsetof(error_info_t, p_file_name)) +#define APP_ERROR_ERROR_INFO_OFFSET_ERR_CODE (offsetof(error_info_t, err_code)) +#define APP_ERROR_ERROR_INFO_SIZE (sizeof(error_info_t)) +#define APP_ERROR_ERROR_INFO_SIZE_ALIGNED_8BYTE \ + ALIGN_NUM(APP_ERROR_ERROR_INFO_SIZE, sizeof(uint64_t)) + + +/**@brief Function for error handling, which is called when an error has occurred. + * + * @param[in] error_code Error code supplied to the handler. + * @param[in] line_num Line number where the handler is called. + * @param[in] p_file_name Pointer to the file name. + */ +void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name); + +/**@brief Function for error handling, which is called when an error has occurred. + * + * @param[in] error_code Error code supplied to the handler. + */ +void app_error_handler_bare(ret_code_t error_code); + +/**@brief Function for saving the parameters and entering an eternal loop, for debug purposes. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. Refer to each fault + * identifier for details. + */ +void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info); + +/**@brief Function for logging details of error and flushing logs. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. Refer to each fault + * identifier for details. + */ +void app_error_log_handle(uint32_t id, uint32_t pc, uint32_t info); + + +/**@brief Macro for calling error handler function. + * + * @param[in] ERR_CODE Error code supplied to the error handler. + */ +#ifdef DEBUG +#define APP_ERROR_HANDLER(ERR_CODE) \ + do \ + { \ + app_error_handler((ERR_CODE), __LINE__, (uint8_t*) __FILE__); \ + } while (0) +#else +#define APP_ERROR_HANDLER(ERR_CODE) \ + do \ + { \ + app_error_handler_bare((ERR_CODE)); \ + } while (0) +#endif +/**@brief Macro for calling error handler function if supplied error code any other than NRF_SUCCESS. + * + * @param[in] ERR_CODE Error code supplied to the error handler. + * + * 시스템 에러 시 리셋(SoftDevice 초기화) 후 BLE Advertising 시작 + */ +#define APP_ERROR_CHECK(ERR_CODE) \ + do \ + { \ + const uint32_t LOCAL_ERR_CODE = (ERR_CODE); \ + if (LOCAL_ERR_CODE != NRF_SUCCESS) \ + { \ + APP_ERROR_HANDLER(LOCAL_ERR_CODE); \ + } \ + } while (0) + +/**@brief Macro for calling error handler function if supplied boolean value is false. + * + * @param[in] BOOLEAN_VALUE Boolean value to be evaluated. + */ +#define APP_ERROR_CHECK_BOOL(BOOLEAN_VALUE) \ + do \ + { \ + const uint32_t LOCAL_BOOLEAN_VALUE = (BOOLEAN_VALUE); \ + if (!LOCAL_BOOLEAN_VALUE) \ + { \ + APP_ERROR_HANDLER(0); \ + } \ + } while (0) + + +#ifdef __cplusplus +} +#endif + +#endif // APP_ERROR_H__ + +/** @} */ diff --git a/components/libraries/util/app_error_handler_gcc.c b/components/libraries/util/app_error_handler_gcc.c new file mode 100644 index 0000000..b517ec4 --- /dev/null +++ b/components/libraries/util/app_error_handler_gcc.c @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#include "compiler_abstraction.h" +#include "app_error.h" + +#if defined (__CORTEX_M) && (__CORTEX_M == 0x04) +void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name) __attribute__(( naked )); + +void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name) +{ + __ASM volatile( + + "push {lr} \n" + + /* reserve space on stack for error_info_t struct - preserve 8byte stack aligment */ + "sub sp, sp, %0 \n" + + /* prepare error_info_t struct */ + "str r0, [sp, %1] \n" + "str r1, [sp, %3] \n" + "str r2, [sp, %2] \n" + + /* prepare arguments and call function: app_error_fault_handler */ + "ldr r0, =%4 \n" + "mov r1, lr \n" + "mov r2, sp \n" + "bl %5 \n" + + /* release stack */ + "add sp, sp, %0 \n" + + "pop {pc} \n" + ".ltorg \n" + + : /* Outputs */ + : /* Inputs */ + "I" (APP_ERROR_ERROR_INFO_SIZE_ALIGNED_8BYTE), + "I" (APP_ERROR_ERROR_INFO_OFFSET_ERR_CODE), + "I" (APP_ERROR_ERROR_INFO_OFFSET_P_FILE_NAME), + "I" (APP_ERROR_ERROR_INFO_OFFSET_LINE_NUM), + "X" (NRF_FAULT_ID_SDK_ERROR), + "X" (app_error_fault_handler) + : /* Clobbers */ + "r0", "r1", "r2" + ); +} +#elif defined(__CORTEX_M) && (__CORTEX_M == 0x00) +/* NRF51 implementation is currently not supporting PC readout */ +void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name) +{ + error_info_t error_info = { + .line_num = line_num, + .p_file_name = p_file_name, + .err_code = error_code, + }; + app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info)); + + UNUSED_VARIABLE(error_info); +} +#else +#error Architecture not supported +#endif + diff --git a/components/libraries/util/app_error_handler_iar.c b/components/libraries/util/app_error_handler_iar.c new file mode 100644 index 0000000..8dacff0 --- /dev/null +++ b/components/libraries/util/app_error_handler_iar.c @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#include "compiler_abstraction.h" +#include "app_error.h" + +#if defined (__CORTEX_M) && (__CORTEX_M == 0x04) +void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name) +{ + __ASM volatile( + "push {lr} \n" + /* reserve space on stack for error_info_t struct */ + "sub sp, sp, %0 \n" + + /* prepare error_info_t struct */ + "str r0, [sp, %1] \n" + "str r1, [sp, %3] \n" + "str r2, [sp, %2] \n" + + /* prepare arguments and call function: app_error_fault_handler */ + "ldr.n r0, 1f \n" + "mov r1, LR \n" + "mov r2, sp \n" + + /* call app_error_fault_handler */ + "bl %c5 \n" + + /* release stack */ + "add sp, sp, %0 \n" + "pop {pc} \n" + + "DATA \n" + "1: \n" + " DC32 %c4 \n" + + : /* Outputs */ + : /* Inputs */ + "i" (APP_ERROR_ERROR_INFO_SIZE_ALIGNED_8BYTE), + "i" (APP_ERROR_ERROR_INFO_OFFSET_ERR_CODE), + "i" (APP_ERROR_ERROR_INFO_OFFSET_P_FILE_NAME), + "i" (APP_ERROR_ERROR_INFO_OFFSET_LINE_NUM), + "i" (NRF_FAULT_ID_SDK_ERROR), + "i" (app_error_fault_handler) + : /* CLobbers */ + "r0", "r1", "r2" + ); +} +#elif defined(__CORTEX_M) && (__CORTEX_M == 0x00) +/* NRF51 implementation is currently not supporting PC readout */ +void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name) +{ + error_info_t error_info = { + .line_num = line_num, + .p_file_name = p_file_name, + .err_code = error_code, + }; + app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info)); + + UNUSED_VARIABLE(error_info); +} +#else +#error Architecture not supported +#endif + diff --git a/components/libraries/util/app_error_handler_keil.c b/components/libraries/util/app_error_handler_keil.c new file mode 100644 index 0000000..390bbe2 --- /dev/null +++ b/components/libraries/util/app_error_handler_keil.c @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#include "compiler_abstraction.h" +#include "app_error.h" + +#if defined (__CORTEX_M) && (__CORTEX_M == 0x04) +__ASM void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name) +{ + PRESERVE8 {TRUE} + THUMB + + push {lr} + + /* reserve space on stack for error_info_t struct - preserve 8byte stack aligment */ + sub sp, sp, #__cpp(APP_ERROR_ERROR_INFO_SIZE_ALIGNED_8BYTE) + + /* prepare error_info_t struct */ + str r0, [sp, #__cpp(APP_ERROR_ERROR_INFO_OFFSET_ERR_CODE)] + str r1, [sp, #__cpp(APP_ERROR_ERROR_INFO_OFFSET_LINE_NUM)] + str r2, [sp, #__cpp(APP_ERROR_ERROR_INFO_OFFSET_P_FILE_NAME)] + + /* prepare arguments and call function: app_error_fault_handler */ + mov r0, #__cpp(NRF_FAULT_ID_SDK_ERROR) + mov r1, lr + mov r2, sp + + /* call function */ + bl __cpp(app_error_fault_handler) + + /* release stack */ + add sp, sp, #__cpp(APP_ERROR_ERROR_INFO_SIZE_ALIGNED_8BYTE) + + pop {pc} +} +#elif defined(__CORTEX_M) && (__CORTEX_M == 0x00) +/* NRF51 implementation is currently not supporting PC readout */ +void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name) +{ + error_info_t error_info = { + .line_num = line_num, + .p_file_name = p_file_name, + .err_code = error_code, + }; + app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info)); + + UNUSED_VARIABLE(error_info); +} +#else +#error Architecture not supported +#endif + diff --git a/components/libraries/util/app_error_weak.c b/components/libraries/util/app_error_weak.c new file mode 100644 index 0000000..879bec2 --- /dev/null +++ b/components/libraries/util/app_error_weak.c @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "app_error.h" + +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +#include "app_util_platform.h" +#include "nrf_strerror.h" + +#if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT +#include "nrf_sdm.h" +#endif + +/*lint -save -e14 */ +/** + * Function is implemented as weak so that it can be overwritten by custom application error handler + * when needed. + */ +__WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) +{ + __disable_irq(); + NRF_LOG_FINAL_FLUSH(); + +#ifndef DEBUG + NRF_LOG_ERROR("Fatal error"); +#else + switch (id) + { +#if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT + case NRF_FAULT_ID_SD_ASSERT: + NRF_LOG_ERROR("SOFTDEVICE: ASSERTION FAILED"); + break; + case NRF_FAULT_ID_APP_MEMACC: + NRF_LOG_ERROR("SOFTDEVICE: INVALID MEMORY ACCESS"); + break; +#endif + case NRF_FAULT_ID_SDK_ASSERT: + { + assert_info_t * p_info = (assert_info_t *)info; + NRF_LOG_ERROR("ASSERTION FAILED at %s:%u", + p_info->p_file_name, + p_info->line_num); + break; + } + case NRF_FAULT_ID_SDK_ERROR: + { + error_info_t * p_info = (error_info_t *)info; + NRF_LOG_ERROR("ERROR %u [%s] at %s:%u\r\nPC at: 0x%08x", + p_info->err_code, + nrf_strerror_get(p_info->err_code), + p_info->p_file_name, + p_info->line_num, + pc); + NRF_LOG_ERROR("End of error report"); + break; + } + default: + NRF_LOG_ERROR("UNKNOWN FAULT at 0x%08X", pc); + break; + } +#endif + + NRF_BREAKPOINT_COND; + // On assert, the system can only recover with a reset. + +#ifndef DEBUG // DEBUG 모드가 아닌 경우 = RELEASE 모드인 경우 + NRF_LOG_WARNING("System reset"); + NVIC_SystemReset(); +#else // DEBUG 모드인 경우 + app_error_save_and_stop(id, pc, info); +#endif +} +/*lint -restore */ diff --git a/components/libraries/util/app_error_weak.h b/components/libraries/util/app_error_weak.h new file mode 100644 index 0000000..8f103bd --- /dev/null +++ b/components/libraries/util/app_error_weak.h @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef APP_ERROR_WEAK_H__ +#define APP_ERROR_WEAK_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file + * + * @defgroup app_error Common application error handler + * @{ + * @ingroup app_common + * + * @brief Common application error handler. + */ + +/**@brief Callback function for errors, asserts, and faults. + * + * @details This function is called every time an error is raised in app_error, nrf_assert, or + * in the SoftDevice. Information about the error can be found in the @p info + * parameter. + * + * See also @ref nrf_fault_handler_t for more details. + * + * @note The function is implemented as weak so that it can be redefined by a custom error + * handler when needed. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. The value of the @p id + * parameter dictates how to interpret this parameter. Refer to the documentation + * for each fault identifier (@ref NRF_FAULT_IDS and @ref APP_ERROR_FAULT_IDS) for + * details about interpreting @p info. + */ +void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info); + + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif // APP_ERROR_WEAK_H__ diff --git a/components/libraries/util/app_util.h b/components/libraries/util/app_util.h new file mode 100644 index 0000000..279a19e --- /dev/null +++ b/components/libraries/util/app_util.h @@ -0,0 +1,1326 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup app_util Utility Functions and Definitions + * @{ + * @ingroup app_common + * + * @brief Various types and definitions available to all applications. + */ + +#ifndef APP_UTIL_H__ +#define APP_UTIL_H__ + +#include +#include +#include +#include "compiler_abstraction.h" +#include "nordic_common.h" +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @cond (NODOX) + */ +/*lint -save -e27 -e10 -e19 */ +#if defined (__LINT__) +#define STACK_BASE 0x1F000 // Arbitrary value. +#define STACK_TOP 0x20000 // Arbitrary value. + +#elif defined ( __CC_ARM ) +extern char STACK$$Base; +extern char STACK$$Length; +#define STACK_BASE &STACK$$Base +#define STACK_TOP ((void*)((uint32_t)STACK_BASE + (uint32_t)&STACK$$Length)) + +#elif defined ( __ICCARM__ ) +extern char CSTACK$$Base; +extern char CSTACK$$Length; +#define STACK_BASE &CSTACK$$Base +#define STACK_TOP ((void*)((uint32_t)STACK_BASE + (uint32_t)&CSTACK$$Length)) + +#elif defined ( __GNUC__ ) +extern uint32_t __StackTop; +extern uint32_t __StackLimit; +#define STACK_BASE &__StackLimit +#define STACK_TOP &__StackTop +#endif + +/* These macros are valid only when absolute placement is used for the application + * image. The macros are not compile time symbols. They cannot be used as a + * constant expression, for example, inside a static assert or linker script + * at-placement. */ +#if defined (__LINT__) +#define CODE_START (0) // Arbitrary value. +#define CODE_END (0x1000) // Arbitrary value. +#define CODE_SIZE (0x1000) // Arbitrary value. + +#elif defined ( __CC_ARM ) +extern char Load$$LR$$LR_IROM1$$Base; +extern char Load$$LR$$LR_IROM1$$Length; +extern char Load$$LR$$LR_IROM1$$Limit; +#define CODE_START ((uint32_t)&Load$$LR$$LR_IROM1$$Base) +#define CODE_END ((uint32_t)&Load$$LR$$LR_IROM1$$Limit) +#define CODE_SIZE ((uint32_t)&Load$$LR$$LR_IROM1$$Length) + +#elif defined ( __ICCARM__ ) +extern void * __vector_table; +extern char RO_END$$Base; +#define CODE_START ((uint32_t)&__vector_table) +#define CODE_END ((uint32_t)&RO_END$$Base) +#define CODE_SIZE (CODE_END - CODE_START) + +#elif defined(__SES_ARM) +extern uint32_t * _vectors; +extern uint32_t __FLASH1_segment_used_end__; +#define CODE_START ((uint32_t)&_vectors) +#define CODE_END ((uint32_t)&__FLASH1_segment_used_end__) +#define CODE_SIZE (CODE_END - CODE_START) + +#elif defined ( __GNUC__ ) +extern uint32_t __isr_vector; +extern uint32_t __etext; +#define CODE_START ((uint32_t)&__isr_vector) +#define CODE_END ((uint32_t)&__etext) +#define CODE_SIZE (CODE_END - CODE_START) +#endif +/** @} + * @endcond + */ +/* lint -restore */ + +#if defined(MBR_PRESENT) || defined(SOFTDEVICE_PRESENT) +#include "nrf_mbr.h" +#define BOOTLOADER_ADDRESS ((*(uint32_t *)MBR_BOOTLOADER_ADDR) == 0xFFFFFFFF ? *MBR_UICR_BOOTLOADER_ADDR : *(uint32_t *)MBR_BOOTLOADER_ADDR) /**< The currently configured start address of the bootloader. If 0xFFFFFFFF, no bootloader start address is configured. */ +#define MBR_PARAMS_PAGE_ADDRESS ((*(uint32_t *)MBR_PARAM_PAGE_ADDR) == 0xFFFFFFFF ? *MBR_UICR_PARAM_PAGE_ADDR : *(uint32_t *)MBR_PARAM_PAGE_ADDR) /**< The currently configured address of the MBR params page. If 0xFFFFFFFF, no MBR params page address is configured. */ +#else +#define BOOTLOADER_ADDRESS (NRF_UICR->NRFFW[0]) /**< Check UICR, just in case. */ +#define MBR_PARAMS_PAGE_ADDRESS (NRF_UICR->NRFFW[1]) /**< Check UICR, just in case. */ +#endif + +enum +{ + UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */ + UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */ + UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */ +}; + +/** + * @brief Counts number of bits required for the given value + * + * The macro technically searches for the highest bit set. + * For value 0 it returns 0. + * + * @param val Value to be processed + * + * @return Number of bits required for the given value + */ +//lint -emacro(572,VBITS) +#define VBITS(val) VBITS_32(val) + +/** + * @def VBITS_1 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_2 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_4 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_8 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_16 + * @brief Internal macro used by @ref VBITS */ +/** + * @def VBITS_32 + * @brief Internal macro used by @ref VBITS */ +#define VBITS_1( v) ((((v) & (0x0001U << 0)) != 0) ? 1U : 0U) +#define VBITS_2( v) ((((v) & (0x0001U << 1)) != 0) ? VBITS_1 ((v) >> 1) + 1 : VBITS_1 (v)) +#define VBITS_4( v) ((((v) & (0x0003U << 2)) != 0) ? VBITS_2 ((v) >> 2) + 2 : VBITS_2 (v)) +#define VBITS_8( v) ((((v) & (0x000fU << 4)) != 0) ? VBITS_4 ((v) >> 4) + 4 : VBITS_4 (v)) +#define VBITS_16(v) ((((v) & (0x00ffU << 8)) != 0) ? VBITS_8 ((v) >> 8) + 8 : VBITS_8 (v)) +#define VBITS_32(v) ((((v) & (0xffffU << 16)) != 0) ? VBITS_16((v) >> 16) + 16 : VBITS_16(v)) + + +/*Segger embedded studio originally has offsetof macro which cannot be used in macros (like STATIC_ASSERT). + This redefinition is to allow using that. */ +#if defined(__SES_ARM) && defined(__GNUC__) +#undef offsetof +#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) +#endif + +/**@brief Implementation specific macro for delayed macro expansion used in string concatenation +* +* @param[in] lhs Left hand side in concatenation +* @param[in] rhs Right hand side in concatenation +*/ +#define STRING_CONCATENATE_IMPL(lhs, rhs) lhs ## rhs + + +/**@brief Macro used to concatenate string using delayed macro expansion +* +* @note This macro will delay concatenation until the expressions have been resolved +* +* @param[in] lhs Left hand side in concatenation +* @param[in] rhs Right hand side in concatenation +*/ +#define STRING_CONCATENATE(lhs, rhs) STRING_CONCATENATE_IMPL(lhs, rhs) + + +#ifndef __LINT__ + +#ifdef __GNUC__ +#ifdef __cplusplus +#define STATIC_ASSERT_SIMPLE(EXPR) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] +#define STATIC_ASSERT_MSG(EXPR, MSG) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] +#else +#define STATIC_ASSERT_SIMPLE(EXPR) _Static_assert(EXPR, "unspecified message") +#define STATIC_ASSERT_MSG(EXPR, MSG) _Static_assert(EXPR, MSG) +#endif +#endif + +#ifdef __CC_ARM +#define STATIC_ASSERT_SIMPLE(EXPR) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] +#define STATIC_ASSERT_MSG(EXPR, MSG) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] +#endif + +#ifdef __ICCARM__ +#define STATIC_ASSERT_SIMPLE(EXPR) static_assert(EXPR, "unspecified message") +#define STATIC_ASSERT_MSG(EXPR, MSG) static_assert(EXPR, MSG) +#endif + +#else // __LINT__ + +#define STATIC_ASSERT_SIMPLE(EXPR) extern char (*_ignore(void)) +#define STATIC_ASSERT_MSG(EXPR, MSG) extern char (*_ignore(void)) + +#endif + + +#define _SELECT_ASSERT_FUNC(x, EXPR, MSG, ASSERT_MACRO, ...) ASSERT_MACRO + +/** + * @brief Static (i.e. compile time) assert macro. + * + * @note The output of STATIC_ASSERT can be different across compilers. + * + * Usage: + * STATIC_ASSERT(expression); + * STATIC_ASSERT(expression, message); + * + * @hideinitializer + */ +//lint -save -esym(???, STATIC_ASSERT) +#define STATIC_ASSERT(...) \ + _SELECT_ASSERT_FUNC(x, ##__VA_ARGS__, \ + STATIC_ASSERT_MSG(__VA_ARGS__), \ + STATIC_ASSERT_SIMPLE(__VA_ARGS__)) +//lint -restore + + +/**@brief Implementation details for NUM_VAR_ARGS */ +#define NUM_VA_ARGS_IMPL( \ + _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ + _61, _62, N, ...) N + + +/**@brief Macro to get the number of arguments in a call variadic macro call + * + * param[in] ... List of arguments + * + * @retval Number of variadic arguments in the argument list + */ +#define NUM_VA_ARGS(...) NUM_VA_ARGS_IMPL(__VA_ARGS__, 63, 62, 61, \ + 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ + 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + +/**@brief Implementation details for NUM_VAR_ARGS */ +#define NUM_VA_ARGS_LESS_1_IMPL( \ + _ignored, \ + _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ + _61, _62, N, ...) N + +/**@brief Macro to get the number of arguments in a call variadic macro call. + * First argument is not counted. + * + * param[in] ... List of arguments + * + * @retval Number of variadic arguments in the argument list + */ +#define NUM_VA_ARGS_LESS_1(...) NUM_VA_ARGS_LESS_1_IMPL(__VA_ARGS__, 63, 62, 61, \ + 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ + 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, ~) + + +/**@brief type for holding an encoded (i.e. little endian) 16 bit unsigned integer. */ +typedef uint8_t uint16_le_t[2]; + +/**@brief Type for holding an encoded (i.e. little endian) 32 bit unsigned integer. */ +typedef uint8_t uint32_le_t[4]; + +/**@brief Byte array type. */ +typedef struct +{ + uint16_t size; /**< Number of array entries. */ + uint8_t * p_data; /**< Pointer to array entries. */ +} uint8_array_t; + + +/**@brief Macro for performing rounded integer division (as opposed to truncating the result). + * + * @param[in] A Numerator. + * @param[in] B Denominator. + * + * @return Rounded (integer) result of dividing A by B. + */ +#define ROUNDED_DIV(A, B) (((A) + ((B) / 2)) / (B)) + + +/**@brief Macro for checking if an integer is a power of two. + * + * @param[in] A Number to be tested. + * + * @return true if value is power of two. + * @return false if value not power of two. + */ +#define IS_POWER_OF_TWO(A) ( ((A) != 0) && ((((A) - 1) & (A)) == 0) ) + + +/**@brief Macro for converting milliseconds to ticks. + * + * @param[in] TIME Number of milliseconds to convert. + * @param[in] RESOLUTION Unit to be converted to in [us/ticks]. + */ +#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) + + +/**@brief Macro for performing integer division, making sure the result is rounded up. + * + * @details One typical use for this is to compute the number of objects with size B is needed to + * hold A number of bytes. + * + * @param[in] A Numerator. + * @param[in] B Denominator. + * + * @return Integer result of dividing A by B, rounded up. + */ +#define CEIL_DIV(A, B) \ + (((A) + (B) - 1) / (B)) + + +/**@brief Macro for creating a buffer aligned to 4 bytes. + * + * @param[in] NAME Name of the buffor. + * @param[in] MIN_SIZE Size of this buffor (it will be rounded up to multiples of 4 bytes). + */ +#define WORD_ALIGNED_MEM_BUFF(NAME, MIN_SIZE) static uint32_t NAME[CEIL_DIV(MIN_SIZE, sizeof(uint32_t))] + + +/**@brief Macro for calculating the number of words that are needed to hold a number of bytes. + * + * @details Adds 3 and divides by 4. + * + * @param[in] n_bytes The number of bytes. + * + * @return The number of words that @p n_bytes take up (rounded up). + */ +#define BYTES_TO_WORDS(n_bytes) (((n_bytes) + 3) >> 2) + + +/**@brief The number of bytes in a word. + */ +#define BYTES_PER_WORD (4) + + +/**@brief Macro for increasing a number to the nearest (larger) multiple of another number. + * + * @param[in] alignment The number to align to. + * @param[in] number The number to align (increase). + * + * @return The aligned (increased) @p number. + */ +#define ALIGN_NUM(alignment, number) (((number) - 1) + (alignment) - (((number) - 1) % (alignment))) + +/**@brief Macro for getting first of 2 parameters. + * + * @param[in] a1 First parameter. + * @param[in] a2 Second parameter. + */ +#define GET_ARG_1(a1, a2) a1 + +/**@brief Macro for getting second of 2 parameters. + * + * @param[in] a1 First parameter. + * @param[in] a2 Second parameter. + */ +#define GET_ARG_2(a1, a2) a2 + + +/**@brief Container of macro (borrowed from Linux kernel). + * + * This macro returns parent structure address basing on child member address. + * + * @param ptr Address of child type. + * @param type Type of parent structure. + * @param member Name of child field in parent structure. + * + * @return Parent structure address. + * */ +#define CONTAINER_OF(ptr, type, member) \ + (type *)((char *)ptr - offsetof(type, member)) + + +/** + * @brief Define Bit-field mask + * + * Macro that defined the mask with selected number of bits set, starting from + * provided bit number. + * + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + */ +#define BF_MASK(bcnt, boff) ( ((1U << (bcnt)) - 1U) << (boff) ) + +/** + * @brief Get bit-field + * + * Macro that extracts selected bit-field from provided value + * + * @param[in] val Value from which selected bit-field would be extracted + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + * + * @return Value of the selected bits + */ +#define BF_GET(val, bcnt, boff) ( ( (val) & BF_MASK((bcnt), (boff)) ) >> (boff) ) + +/** + * @brief Create bit-field value + * + * Value is masked and shifted to match given bit-field + * + * @param[in] val Value to set on bit-field + * @param[in] bcnt Number of bits for bit-field + * @param[in] boff Offset of bit-field + * + * @return Value positioned of given bit-field. + */ +#define BF_VAL(val, bcnt, boff) ( (((uint32_t)(val)) << (boff)) & BF_MASK(bcnt, boff) ) + +/** + * @name Configuration of complex bit-field + * + * @sa BF_CX + * @{ + */ +/** @brief Position of bit count in complex bit-field value */ +#define BF_CX_BCNT_POS 0U +/** @brief Mask of bit count in complex bit-field value */ +#define BF_CX_BCNT_MASK (0xffU << BF_CX_BCNT_POS) +/** @brief Position of bit position in complex bit-field value */ +#define BF_CX_BOFF_POS 8U +/** @brief Mask of bit position in complex bit-field value */ +#define BF_CX_BOFF_MASK (0xffU << BF_CX_BOFF_POS) +/** @} */ + +/** + * @brief Define complex bit-field + * + * Complex bit-field would contain its position and size in one number. + * @sa BF_CX_MASK + * @sa BF_CX_POS + * @sa BF_CX_GET + * + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + * + * @return The single number that describes the bit-field completely. + */ +#define BF_CX(bcnt, boff) ( ((((uint32_t)(bcnt)) << BF_CX_BCNT_POS) & BF_CX_BCNT_MASK) | ((((uint32_t)(boff)) << BF_CX_BOFF_POS) & BF_CX_BOFF_MASK) ) + +/** + * @brief Get number of bits in bit-field + * + * @sa BF_CX + * + * @param bf_cx Complex bit-field + * + * @return Number of bits in given bit-field + */ +#define BF_CX_BCNT(bf_cx) ( ((bf_cx) & BF_CX_BCNT_MASK) >> BF_CX_BCNT_POS ) + +/** + * @brief Get lowest bit number in the field + * + * @sa BF_CX + * + * @param[in] bf_cx Complex bit-field + * + * @return Lowest bit number in given bit-field + */ +#define BF_CX_BOFF(bf_cx) ( ((bf_cx) & BF_CX_BOFF_MASK) >> BF_CX_BOFF_POS ) + +/** + * @brief Get bit mask of the selected field + * + * @sa BF_CX + * + * @param[in] bf_cx Complex bit-field + * + * @return Mask of given bit-field + */ +#define BF_CX_MASK(bf_cx) BF_MASK(BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Get bit-field + * + * Macro that extracts selected bit-field from provided value. + * Bit-field is given as a complex value. + * + * @sa BF_CX + * @sa BF_GET + * + * @param[in] val Value from which selected bit-field would be extracted + * @param[in] bf_cx Complex bit-field + * + * @return Value of the selected bits. + */ +#define BF_CX_GET(val, bf_cx) BF_GET(val, BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Create bit-field value + * + * Value is masked and shifted to match given bit-field. + * + * @param[in] val Value to set on bit-field + * @param[in] bf_cx Complex bit-field + * + * @return Value positioned of given bit-field. + */ +#define BF_CX_VAL(val, bf_cx) BF_VAL(val, BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Extracting data from the brackets + * + * This macro get rid of brackets around the argument. + * It can be used to pass multiple arguments in logical one argument to a macro. + * Call it with arguments inside brackets: + * @code + * #define ARGUMENTS (a, b, c) + * BRACKET_EXTRACT(ARGUMENTS) + * @endcode + * It would produce: + * @code + * a, b, c + * @endcode + * + * @param a Argument with anything inside brackets + * @return Anything that appears inside the brackets of the argument + * + * @note + * The argument of the macro have to be inside brackets. + * In other case the compilation would fail. + */ +#define BRACKET_EXTRACT(a) BRACKET_EXTRACT_(a) +#define BRACKET_EXTRACT_(a) BRACKET_EXTRACT__ a +#define BRACKET_EXTRACT__(...) __VA_ARGS__ + + +/** + * @brief Check if number of parameters is more than 1 + * + * @param ... Arguments to count + * + * @return 0 If argument count is <= 1 + * @return 1 If argument count is > 1 + * + * @sa NUM_VA_ARGS + * @sa NUM_IS_MORE_THAN_1 + */ +#define NUM_VA_ARGS_IS_MORE_THAN_1(...) NUM_IS_MORE_THAN_1(NUM_VA_ARGS(__VA_ARGS__)) + +/** + * @brief Check if given numeric value is bigger than 1 + * + * This macro accepts numeric value, that may be the result of argument expansion. + * This numeric value is then converted to 0 if it is lover than 1 or to 1 if + * its value is higher than 1. + * The generated result can be used to glue it into other macro mnemonic name. + * + * @param N Numeric value to check + * + * @return 0 If argument is <= 1 + * @return 1 If argument is > 1 + * + * @note Any existing definition of a form NUM_IS_MORE_THAN_1_PROBE_[N] can + * broke the result of this macro + */ +#define NUM_IS_MORE_THAN_1(N) NUM_IS_MORE_THAN_1_(N) +#define NUM_IS_MORE_THAN_1_(N) NUM_IS_MORE_THAN_1_PROBE_(NUM_IS_MORE_THAN_1_PROBE_ ## N, 1) +#define NUM_IS_MORE_THAN_1_PROBE_(...) GET_VA_ARG_1(GET_ARGS_AFTER_1(__VA_ARGS__)) +#define NUM_IS_MORE_THAN_1_PROBE_0 ~, 0 +#define NUM_IS_MORE_THAN_1_PROBE_1 ~, 0 + +/** + * @brief Get the first argument + * + * @param ... Arguments to select + * + * @return First argument or empty if no arguments are provided + */ +#define GET_VA_ARG_1(...) GET_VA_ARG_1_(__VA_ARGS__, ) // Make sure that also for 1 argument it works +#define GET_VA_ARG_1_(a1, ...) a1 + +/** + * @brief Get all the arguments but the first one + * + * @param ... Arguments to select + * + * @return All arguments after the first one or empty if less than 2 arguments are provided + */ +#define GET_ARGS_AFTER_1(...) GET_ARGS_AFTER_1_(__VA_ARGS__, ) // Make sure that also for 1 argument it works +#define GET_ARGS_AFTER_1_(a1, ...) __VA_ARGS__ + +/** + * @brief Size of a field in declared structure + * + * Macro that returns the size of the structure field. + * @param struct_type Variable type to get the field size from + * @param field Field name to analyze. It can be even field inside field (field.somethingelse.and_another). + * + * @return Size of the field + */ +#define FIELD_SIZE(struct_type, field) sizeof(((struct struct_type*)NULL)->field) + +/** + * @brief Number of elements in field array in declared structure + * + * Macro that returns number of elementy in structure field. + * @param struct_type Variable type to get the field size from + * @param field Field name to analyze. + * + * @return Number of elements in field array + * + * @sa FIELD_SIZE + */ +#define FIELD_ARRAY_SIZE(struct_type, field) (FIELD_SIZE(struct_type, field) / FIELD_SIZE(struct_type, field[0])) + +/** + * @brief Mapping macro + * + * Macro that process all arguments using given macro + * + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP(...) MACRO_MAP_(__VA_ARGS__) +#define MACRO_MAP_(...) MACRO_MAP_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) // To make sure it works also for 2 arguments in total + +/** + * @brief Mapping macro, recursive version + * + * Can be used in @ref MACRO_MAP macro + */ +#define MACRO_MAP_REC(...) MACRO_MAP_REC_(__VA_ARGS__) +#define MACRO_MAP_REC_(...) MACRO_MAP_REC_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) // To make sure it works also for 2 arguments in total +/** + * @brief Mapping N arguments macro + * + * Macro similar to @ref MACRO_MAP but maps exact number of arguments. + * If there is more arguments given, the rest would be ignored. + * + * @param N Number of arguments to map + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument) + * + * @return Selected number of arguments processed by given macro + */ +#define MACRO_MAP_N(N, ...) MACRO_MAP_N_(N, __VA_ARGS__) +#define MACRO_MAP_N_(N, ...) CONCAT_2(MACRO_MAP_, N)(__VA_ARGS__, ) + +/** + * @brief Mapping N arguments macro, recursive version + * + * Can be used in @ref MACRO_MAP_N macro + */ +#define MACRO_MAP_REC_N(N, ...) MACRO_MAP_REC_N_(N, __VA_ARGS__) +#define MACRO_MAP_REC_N_(N, ...) CONCAT_2(MACRO_MAP_REC_, N)(__VA_ARGS__, ) + +#define MACRO_MAP_0( ...) +#define MACRO_MAP_1( macro, a, ...) macro(a) +#define MACRO_MAP_2( macro, a, ...) macro(a) MACRO_MAP_1 (macro, __VA_ARGS__, ) +#define MACRO_MAP_3( macro, a, ...) macro(a) MACRO_MAP_2 (macro, __VA_ARGS__, ) +#define MACRO_MAP_4( macro, a, ...) macro(a) MACRO_MAP_3 (macro, __VA_ARGS__, ) +#define MACRO_MAP_5( macro, a, ...) macro(a) MACRO_MAP_4 (macro, __VA_ARGS__, ) +#define MACRO_MAP_6( macro, a, ...) macro(a) MACRO_MAP_5 (macro, __VA_ARGS__, ) +#define MACRO_MAP_7( macro, a, ...) macro(a) MACRO_MAP_6 (macro, __VA_ARGS__, ) +#define MACRO_MAP_8( macro, a, ...) macro(a) MACRO_MAP_7 (macro, __VA_ARGS__, ) +#define MACRO_MAP_9( macro, a, ...) macro(a) MACRO_MAP_8 (macro, __VA_ARGS__, ) +#define MACRO_MAP_10(macro, a, ...) macro(a) MACRO_MAP_9 (macro, __VA_ARGS__, ) +#define MACRO_MAP_11(macro, a, ...) macro(a) MACRO_MAP_10(macro, __VA_ARGS__, ) +#define MACRO_MAP_12(macro, a, ...) macro(a) MACRO_MAP_11(macro, __VA_ARGS__, ) +#define MACRO_MAP_13(macro, a, ...) macro(a) MACRO_MAP_12(macro, __VA_ARGS__, ) +#define MACRO_MAP_14(macro, a, ...) macro(a) MACRO_MAP_13(macro, __VA_ARGS__, ) +#define MACRO_MAP_15(macro, a, ...) macro(a) MACRO_MAP_14(macro, __VA_ARGS__, ) +#define MACRO_MAP_16(macro, a, ...) macro(a) MACRO_MAP_15(macro, __VA_ARGS__, ) +#define MACRO_MAP_17(macro, a, ...) macro(a) MACRO_MAP_16(macro, __VA_ARGS__, ) +#define MACRO_MAP_18(macro, a, ...) macro(a) MACRO_MAP_17(macro, __VA_ARGS__, ) +#define MACRO_MAP_19(macro, a, ...) macro(a) MACRO_MAP_18(macro, __VA_ARGS__, ) +#define MACRO_MAP_20(macro, a, ...) macro(a) MACRO_MAP_19(macro, __VA_ARGS__, ) +#define MACRO_MAP_21(macro, a, ...) macro(a) MACRO_MAP_20(macro, __VA_ARGS__, ) +#define MACRO_MAP_22(macro, a, ...) macro(a) MACRO_MAP_21(macro, __VA_ARGS__, ) +#define MACRO_MAP_23(macro, a, ...) macro(a) MACRO_MAP_22(macro, __VA_ARGS__, ) +#define MACRO_MAP_24(macro, a, ...) macro(a) MACRO_MAP_23(macro, __VA_ARGS__, ) +#define MACRO_MAP_25(macro, a, ...) macro(a) MACRO_MAP_24(macro, __VA_ARGS__, ) +#define MACRO_MAP_26(macro, a, ...) macro(a) MACRO_MAP_25(macro, __VA_ARGS__, ) +#define MACRO_MAP_27(macro, a, ...) macro(a) MACRO_MAP_26(macro, __VA_ARGS__, ) +#define MACRO_MAP_28(macro, a, ...) macro(a) MACRO_MAP_27(macro, __VA_ARGS__, ) +#define MACRO_MAP_29(macro, a, ...) macro(a) MACRO_MAP_28(macro, __VA_ARGS__, ) +#define MACRO_MAP_30(macro, a, ...) macro(a) MACRO_MAP_29(macro, __VA_ARGS__, ) +#define MACRO_MAP_31(macro, a, ...) macro(a) MACRO_MAP_30(macro, __VA_ARGS__, ) +#define MACRO_MAP_32(macro, a, ...) macro(a) MACRO_MAP_31(macro, __VA_ARGS__, ) + + +#define MACRO_MAP_REC_0( ...) +#define MACRO_MAP_REC_1( macro, a, ...) macro(a) +#define MACRO_MAP_REC_2( macro, a, ...) macro(a) MACRO_MAP_REC_1 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_3( macro, a, ...) macro(a) MACRO_MAP_REC_2 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_4( macro, a, ...) macro(a) MACRO_MAP_REC_3 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_5( macro, a, ...) macro(a) MACRO_MAP_REC_4 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_6( macro, a, ...) macro(a) MACRO_MAP_REC_5 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_7( macro, a, ...) macro(a) MACRO_MAP_REC_6 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_8( macro, a, ...) macro(a) MACRO_MAP_REC_7 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_9( macro, a, ...) macro(a) MACRO_MAP_REC_8 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_10(macro, a, ...) macro(a) MACRO_MAP_REC_9 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_11(macro, a, ...) macro(a) MACRO_MAP_REC_10(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_12(macro, a, ...) macro(a) MACRO_MAP_REC_11(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_13(macro, a, ...) macro(a) MACRO_MAP_REC_12(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_14(macro, a, ...) macro(a) MACRO_MAP_REC_13(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_15(macro, a, ...) macro(a) MACRO_MAP_REC_14(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_16(macro, a, ...) macro(a) MACRO_MAP_REC_15(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_17(macro, a, ...) macro(a) MACRO_MAP_REC_16(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_18(macro, a, ...) macro(a) MACRO_MAP_REC_17(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_19(macro, a, ...) macro(a) MACRO_MAP_REC_18(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_20(macro, a, ...) macro(a) MACRO_MAP_REC_19(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_21(macro, a, ...) macro(a) MACRO_MAP_REC_20(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_22(macro, a, ...) macro(a) MACRO_MAP_REC_21(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_23(macro, a, ...) macro(a) MACRO_MAP_REC_22(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_24(macro, a, ...) macro(a) MACRO_MAP_REC_23(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_25(macro, a, ...) macro(a) MACRO_MAP_REC_24(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_26(macro, a, ...) macro(a) MACRO_MAP_REC_25(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_27(macro, a, ...) macro(a) MACRO_MAP_REC_26(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_28(macro, a, ...) macro(a) MACRO_MAP_REC_27(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_29(macro, a, ...) macro(a) MACRO_MAP_REC_28(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_30(macro, a, ...) macro(a) MACRO_MAP_REC_29(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_31(macro, a, ...) macro(a) MACRO_MAP_REC_30(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_32(macro, a, ...) macro(a) MACRO_MAP_REC_31(macro, __VA_ARGS__, ) + + +/** + * @brief Mapping macro with current index + * + * Basically macro similar to @ref MACRO_MAP, but the processing function would get an argument + * and current argument index (beginning from 0). + * + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index) + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR(...) MACRO_MAP_FOR_(__VA_ARGS__) +#define MACRO_MAP_FOR_N_LIST 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, \ + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 +#define MACRO_MAP_FOR_(...) MACRO_MAP_FOR_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) + +/** + * @brief Mapping N arguments macro with current index + * + * Macro is similar to @ref MACRO_MAP_FOR but maps exact number of arguments. + * If there is more arguments given, the rest would be ignored. + * + * @param N Number of arguments to map + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index) + * + * @return Selected number of arguments processed by given macro + */ +#define MACRO_MAP_FOR_N(N, ...) MACRO_MAP_FOR_N_(N, __VA_ARGS__) +#define MACRO_MAP_FOR_N_(N, ...) CONCAT_2(MACRO_MAP_FOR_, N)((MACRO_MAP_FOR_N_LIST), __VA_ARGS__, ) + +#define MACRO_MAP_FOR_0( n_list, ...) +#define MACRO_MAP_FOR_1( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) +#define MACRO_MAP_FOR_2( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_1 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_3( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_2 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_4( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_3 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_5( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_4 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_6( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_5 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_7( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_6 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_8( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_7 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_9( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_8 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_10(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_9 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_11(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_12(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_13(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_14(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_15(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_16(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_15((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_17(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_16((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_18(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_17((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_19(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_18((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_20(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_19((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_21(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_20((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_22(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_21((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_23(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_22((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_24(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_23((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_25(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_24((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_26(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_25((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_27(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_26((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_28(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_27((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_29(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_28((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_30(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_29((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_31(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_30((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_32(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_31((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) + + +/** + * @brief Mapping macro with current index and parameter + * + * Version of @ref MACRO_MAP_FOR that passes also the same parameter to all macros. + * + * @param param Parameter that would be passed to each macro call during mapping. + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index, param) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR_PARAM(param, ...) MACRO_MAP_FOR_PARAM_(param, __VA_ARGS__) +#define MACRO_MAP_FOR_PARAM_(param, ...) MACRO_MAP_FOR_PARAM_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), param, __VA_ARGS__) + +/** + * @brief Mapping N arguments macro with with current index and parameter + * + * @param N Number of arguments to map + * @param param Parameter that would be passed to each macro call during mapping. + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index, param) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR_PARAM_N(N, param, ...) MACRO_MAP_FOR_PARAM_N_(N, param, __VA_ARGS__) +#define MACRO_MAP_FOR_PARAM_N_(N, param, ...) CONCAT_2(MACRO_MAP_FOR_PARAM_, N)((MACRO_MAP_FOR_N_LIST), param, __VA_ARGS__, ) + + +#define MACRO_MAP_FOR_PARAM_0( n_list, param, ...) +#define MACRO_MAP_FOR_PARAM_1( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) +#define MACRO_MAP_FOR_PARAM_2( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_1 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_3( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_2 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_4( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_3 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_5( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_4 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_6( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_5 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_7( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_6 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_8( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_7 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_9( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_8 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_10(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_9 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_11(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_12(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_13(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_14(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_15(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_16(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_15((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_17(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_16((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_18(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_17((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_19(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_18((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_20(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_19((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_21(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_20((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_22(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_21((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_23(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_22((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_24(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_23((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_25(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_24((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_26(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_25((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_27(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_26((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_28(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_27((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_29(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_28((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_30(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_29((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_31(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_30((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_32(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_31((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) + + + +/** + * @brief Repeating macro. + * + * @param count Count of repeats. + * @param macro Macro must have the following form: MACRO(arguments). + * @param ... Arguments passed to the macro. + * + * @return All arguments processed by the given macro. + */ +#define MACRO_REPEAT(count, macro, ...) MACRO_REPEAT_(count, macro, __VA_ARGS__) +#define MACRO_REPEAT_(count, macro, ...) CONCAT_2(MACRO_REPEAT_, count)(macro, __VA_ARGS__) + +#define MACRO_REPEAT_0(macro, ...) +#define MACRO_REPEAT_1(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_0(macro, __VA_ARGS__) +#define MACRO_REPEAT_2(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_1(macro, __VA_ARGS__) +#define MACRO_REPEAT_3(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_2(macro, __VA_ARGS__) +#define MACRO_REPEAT_4(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_3(macro, __VA_ARGS__) +#define MACRO_REPEAT_5(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_4(macro, __VA_ARGS__) +#define MACRO_REPEAT_6(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_5(macro, __VA_ARGS__) +#define MACRO_REPEAT_7(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_6(macro, __VA_ARGS__) +#define MACRO_REPEAT_8(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_7(macro, __VA_ARGS__) +#define MACRO_REPEAT_9(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_8(macro, __VA_ARGS__) +#define MACRO_REPEAT_10(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_9(macro, __VA_ARGS__) +#define MACRO_REPEAT_11(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_10(macro, __VA_ARGS__) +#define MACRO_REPEAT_12(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_11(macro, __VA_ARGS__) +#define MACRO_REPEAT_13(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_12(macro, __VA_ARGS__) +#define MACRO_REPEAT_14(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_13(macro, __VA_ARGS__) +#define MACRO_REPEAT_15(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_14(macro, __VA_ARGS__) +#define MACRO_REPEAT_16(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_15(macro, __VA_ARGS__) +#define MACRO_REPEAT_17(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_16(macro, __VA_ARGS__) +#define MACRO_REPEAT_18(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_17(macro, __VA_ARGS__) +#define MACRO_REPEAT_19(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_18(macro, __VA_ARGS__) +#define MACRO_REPEAT_20(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_19(macro, __VA_ARGS__) +#define MACRO_REPEAT_21(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_20(macro, __VA_ARGS__) +#define MACRO_REPEAT_22(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_21(macro, __VA_ARGS__) +#define MACRO_REPEAT_23(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_22(macro, __VA_ARGS__) +#define MACRO_REPEAT_24(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_23(macro, __VA_ARGS__) +#define MACRO_REPEAT_25(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_24(macro, __VA_ARGS__) +#define MACRO_REPEAT_26(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_25(macro, __VA_ARGS__) +#define MACRO_REPEAT_27(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_26(macro, __VA_ARGS__) +#define MACRO_REPEAT_28(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_27(macro, __VA_ARGS__) +#define MACRO_REPEAT_29(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_28(macro, __VA_ARGS__) +#define MACRO_REPEAT_30(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_29(macro, __VA_ARGS__) +#define MACRO_REPEAT_31(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_30(macro, __VA_ARGS__) +#define MACRO_REPEAT_32(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_31(macro, __VA_ARGS__) + + +/** + * @brief Repeating macro with current index. + * + * Macro similar to @ref MACRO_REPEAT but the processing function gets the arguments + * and the current argument index (beginning from 0). + + * @param count Count of repeats. + * @param macro Macro must have the following form: MACRO(index, arguments). + * @param ... Arguments passed to the macro. + * + * @return All arguments processed by the given macro. + */ +#define MACRO_REPEAT_FOR(count, macro, ...) MACRO_REPEAT_FOR_(count, macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_(count, macro, ...) CONCAT_2(MACRO_REPEAT_FOR_, count)((MACRO_MAP_FOR_N_LIST), macro, __VA_ARGS__) + +#define MACRO_REPEAT_FOR_0(n_list, macro, ...) +#define MACRO_REPEAT_FOR_1(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_0((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_2(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_1((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_3(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_2((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_4(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_3((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_5(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_4((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_6(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_5((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_7(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_6((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_8(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_7((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_9(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_8((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_10(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_9((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_11(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_12(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_13(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_14(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_15(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_16(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_15((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_17(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_16((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_18(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_17((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_19(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_18((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_20(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_19((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_21(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_20((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_22(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_21((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_23(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_22((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_24(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_23((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_25(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_24((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_26(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_25((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_27(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_26((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_28(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_27((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_29(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_28((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_30(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_29((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_31(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_30((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_32(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_31((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) + + +/**@brief Adding curly brace to the macro parameter. + * + * Useful in array of structures initialization. + * + * @param p Parameter to put into the curly brace. */ +#define PARAM_CBRACE(p) { p }, + + +/**@brief Function for changing the value unit. + * + * @param[in] value Value to be rescaled. + * @param[in] old_unit_reversal Reversal of the incoming unit. + * @param[in] new_unit_reversal Reversal of the desired unit. + * + * @return Number of bytes written. + */ +static __INLINE uint64_t value_rescale(uint32_t value, uint32_t old_unit_reversal, uint16_t new_unit_reversal) +{ + return (uint64_t)ROUNDED_DIV((uint64_t)value * new_unit_reversal, old_unit_reversal); +} + +/**@brief Function for encoding a uint16 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint16_encode(uint16_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x00FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0xFF00) >> 8); + return sizeof(uint16_t); +} + +/**@brief Function for encoding a three-byte value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint24_encode(uint32_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); + return 3; +} + +/**@brief Function for encoding a uint32 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint32_encode(uint32_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((value & 0xFF000000) >> 24); + return sizeof(uint32_t); +} + +/**@brief Function for encoding a uint40 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint40_encode(uint64_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x00000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x000000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x0000FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((value & 0x00FF000000) >> 24); + p_encoded_data[4] = (uint8_t) ((value & 0xFF00000000) >> 32); + return 5; +} + +/**@brief Function for encoding a uint48 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint48_encode(uint64_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x0000000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x00000000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x000000FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((value & 0x0000FF000000) >> 24); + p_encoded_data[4] = (uint8_t) ((value & 0x00FF00000000) >> 32); + p_encoded_data[5] = (uint8_t) ((value & 0xFF0000000000) >> 40); + return 6; +} + +/**@brief Function for decoding a uint16 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint16_t uint16_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint16_t)((uint8_t *)p_encoded_data)[0])) | + (((uint16_t)((uint8_t *)p_encoded_data)[1]) << 8 )); +} + +/**@brief Function for decoding a uint16 value in big-endian format. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint16_t uint16_big_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint16_t)((uint8_t *)p_encoded_data)[0]) << 8 ) | + (((uint16_t)((uint8_t *)p_encoded_data)[1])) ); +} + +/**@brief Function for decoding a three-byte value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value (uint32_t). + */ +static __INLINE uint32_t uint24_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16)); +} + +/**@brief Function for decoding a uint32 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint32_t uint32_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 24 )); +} + +/**@brief Function for decoding a uint32 value in big-endian format. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint32_t uint32_big_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 24) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 16) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 0) ); +} + +/** + * @brief Function for encoding an uint16 value in big-endian format. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data will be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint16_big_encode(uint16_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) (value >> 8); + p_encoded_data[1] = (uint8_t) (value & 0xFF); + + return sizeof(uint16_t); +} + +/*lint -esym(526, __rev) */ +/*lint -esym(628, __rev) */ +/**@brief Function for encoding a uint32 value in big-endian format. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data will be written. + * The address pointed to must be word alligned. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint32_big_encode(uint32_t value, uint8_t * p_encoded_data) +{ + *(uint32_t *)p_encoded_data = __REV(value); + return sizeof(uint32_t); +} + +/**@brief Function for decoding a uint40 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. (uint64_t) + */ +static __INLINE uint64_t uint40_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint64_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint64_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint64_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint64_t)((uint8_t *)p_encoded_data)[3]) << 24) | + (((uint64_t)((uint8_t *)p_encoded_data)[4]) << 32 )); +} + +/**@brief Function for decoding a uint48 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. (uint64_t) + */ +static __INLINE uint64_t uint48_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint64_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint64_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint64_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint64_t)((uint8_t *)p_encoded_data)[3]) << 24) | + (((uint64_t)((uint8_t *)p_encoded_data)[4]) << 32) | + (((uint64_t)((uint8_t *)p_encoded_data)[5]) << 40 )); +} + +/** @brief Function for converting the input voltage (in milli volts) into percentage of 3.0 Volts. + * + * @details The calculation is based on a linearized version of the battery's discharge + * curve. 3.0V returns 100% battery level. The limit for power failure is 2.1V and + * is considered to be the lower boundary. + * + * The discharge curve for CR2032 is non-linear. In this model it is split into + * 4 linear sections: + * - Section 1: 3.0V - 2.9V = 100% - 42% (58% drop on 100 mV) + * - Section 2: 2.9V - 2.74V = 42% - 18% (24% drop on 160 mV) + * - Section 3: 2.74V - 2.44V = 18% - 6% (12% drop on 300 mV) + * - Section 4: 2.44V - 2.1V = 6% - 0% (6% drop on 340 mV) + * + * These numbers are by no means accurate. Temperature and + * load in the actual application is not accounted for! + * + * @param[in] mvolts The voltage in mV + * + * @return Battery level in percent. +*/ +static __INLINE uint8_t battery_level_in_percent(const uint16_t mvolts) +{ + uint8_t battery_level; + + if (mvolts >= 3000) + { + battery_level = 100; + } + else if (mvolts > 2900) + { + battery_level = 100 - ((3000 - mvolts) * 58) / 100; + } + else if (mvolts > 2740) + { + battery_level = 42 - ((2900 - mvolts) * 24) / 160; + } + else if (mvolts > 2440) + { + battery_level = 18 - ((2740 - mvolts) * 12) / 300; + } + else if (mvolts > 2100) + { + battery_level = 6 - ((2440 - mvolts) * 6) / 340; + } + else + { + battery_level = 0; + } + + return battery_level; +} + +/**@brief Function for checking if a pointer value is aligned to a 4 byte boundary. + * + * @param[in] p Pointer value to be checked. + * + * @return TRUE if pointer is aligned to a 4 byte boundary, FALSE otherwise. + */ +static __INLINE bool is_word_aligned(void const* p) +{ + return (((uintptr_t)p & 0x03) == 0); +} + +/*lint -e{568, 685} */ +/** + * @brief Function for checking if provided address is located in stack space. + * + * @param[in] ptr Pointer to be checked. + * + * @return true if address is in stack space, false otherwise. + */ +static __INLINE bool is_address_from_stack(void * ptr) +{ + if (((uint32_t)ptr >= (uint32_t)STACK_BASE) && + ((uint32_t)ptr < (uint32_t)STACK_TOP) ) + { + return true; + } + else + { + return false; + } +} + +#ifdef __cplusplus +} +#endif + +#endif // APP_UTIL_H__ + +/** @} */ diff --git a/components/libraries/util/app_util_bds.h b/components/libraries/util/app_util_bds.h new file mode 100644 index 0000000..b39b976 --- /dev/null +++ b/components/libraries/util/app_util_bds.h @@ -0,0 +1,449 @@ +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup app_util Utility Functions and Definitions + * @{ + * @ingroup app_common + * + * @brief Various types and definitions available to all applications. + */ + +#ifndef APP_UTIL_BDS_H__ +#define APP_UTIL_BDS_H__ + +#include +#include +#include +#include "compiler_abstraction.h" +#include "app_util.h" +#include "ble_srv_common.h" +#include "nordic_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint8_t nibble_t; +typedef uint32_t uint24_t; +typedef uint64_t uint40_t; + +/**@brief IEEE 11073-20601 Regulatory Certification Data List Structure */ +typedef struct +{ + uint8_t * p_list; /**< Pointer the byte array containing the encoded opaque structure based on IEEE 11073-20601 specification. */ + uint8_t list_len; /**< Length of the byte array. */ +} regcertdatalist_t; + +/**@brief SFLOAT format (IEEE-11073 16-bit FLOAT, meaning 4 bits for exponent (base 10) and 12 bits mantissa) */ +typedef struct +{ + int8_t exponent; /**< Base 10 exponent, should be using only 4 bits */ + int16_t mantissa; /**< Mantissa, should be using only 12 bits */ +} sfloat_t; + +/**@brief Date and Time structure. */ +typedef struct +{ + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hours; + uint8_t minutes; + uint8_t seconds; +} ble_date_time_t; + + +/**@brief Function for encoding a uint16 value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_uint16_encode(const uint16_t * p_value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((*p_value & 0x00FF) >> 0); + p_encoded_data[1] = (uint8_t) ((*p_value & 0xFF00) >> 8); + return sizeof(uint16_t); +} + +static __INLINE uint8_t bds_int16_encode(const int16_t * p_value, uint8_t * p_encoded_data) +{ + uint16_t tmp = *p_value; + return bds_uint16_encode(&tmp, p_encoded_data); +} + +/**@brief Function for encoding a uint24 value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_uint24_encode(const uint32_t * p_value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((*p_value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((*p_value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((*p_value & 0x00FF0000) >> 16); + return (3); +} + + +/**@brief Function for encoding a uint32 value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_uint32_encode(const uint32_t * p_value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((*p_value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((*p_value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((*p_value & 0x00FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((*p_value & 0xFF000000) >> 24); + return sizeof(uint32_t); +} + + +/**@brief Function for encoding a uint40 value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_uint40_encode(const uint64_t * p_value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((*p_value & 0x00000000000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((*p_value & 0x000000000000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((*p_value & 0x0000000000FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((*p_value & 0x00000000FF000000) >> 24); + p_encoded_data[4] = (uint8_t) ((*p_value & 0x000000FF00000000) >> 32); + return 5; +} + +/**@brief Function for encoding a sfloat value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_sfloat_encode(const sfloat_t * p_value, uint8_t * p_encoded_data) +{ + uint16_t encoded_val; + + encoded_val = ((p_value->exponent << 12) & 0xF000) | + ((p_value->mantissa << 0) & 0x0FFF); + + return(bds_uint16_encode(&encoded_val, p_encoded_data)); +} + + +/**@brief Function for encoding a uint8_array value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + */ +static __INLINE uint8_t bds_uint8_array_encode(const uint8_array_t * p_value, + uint8_t * p_encoded_data) +{ + memcpy(p_encoded_data, p_value->p_data, p_value->size); + return p_value->size; +} + + +/**@brief Function for encoding a utf8_str value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + + */ +static __INLINE uint8_t bds_ble_srv_utf8_str_encode(const ble_srv_utf8_str_t * p_value, + uint8_t * p_encoded_data) +{ + memcpy(p_encoded_data, p_value->p_str, p_value->length); + return p_value->length; +} + +/**@brief Function for encoding a regcertdatalist value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + + */ +static __INLINE uint8_t bds_regcertdatalist_encode(const regcertdatalist_t * p_value, + uint8_t * p_encoded_data) +{ + memcpy(p_encoded_data, p_value->p_list, p_value->list_len); + return p_value->list_len; +} + + +/**@brief Function for decoding a date_time value. + * + * @param[in] p_date_time pointer to the date_time structure to encode. + * @param[in] p_encoded_data pointer to the encoded data + * @return length of the encoded field. + */ +static __INLINE uint8_t bds_ble_date_time_encode(const ble_date_time_t * p_date_time, + uint8_t * p_encoded_data) +{ + uint8_t len = bds_uint16_encode(&p_date_time->year, &p_encoded_data[0]); + + p_encoded_data[len++] = p_date_time->month; + p_encoded_data[len++] = p_date_time->day; + p_encoded_data[len++] = p_date_time->hours; + p_encoded_data[len++] = p_date_time->minutes; + p_encoded_data[len++] = p_date_time->seconds; + + return len; +} + + +/**@brief Function for decoding a uint16 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint16_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint16_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + *p_decoded_val = (((uint16_t)((uint8_t *)p_encoded_data)[0])) | + (((uint16_t)((uint8_t *)p_encoded_data)[1]) << 8 ); + return (sizeof(uint16_t)); +} + + +/**@brief Function for decoding a int16 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_int16_decode(const uint8_t len, + const uint8_t * p_encoded_data, + int16_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + uint16_t tmp = 0; + uint8_t retval = bds_uint16_decode(len, p_encoded_data, &tmp); + *p_decoded_val = (int16_t)tmp; + return retval; +} + + +/**@brief Function for decoding a uint24 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint24_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint32_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + *p_decoded_val = (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16); + return (3); +} + + +/**@brief Function for decoding a uint32 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint32_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint32_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + *p_decoded_val = (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 24 ); + return (sizeof(uint32_t)); +} + + +/**@brief Function for decoding a uint40 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint40_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint64_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + *p_decoded_val = (((uint64_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint64_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint64_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint64_t)((uint8_t *)p_encoded_data)[3]) << 24 )| + (((uint64_t)((uint8_t *)p_encoded_data)[4]) << 32 ); + return (40); +} + + +/**@brief Function for decoding a sfloat value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + + */ +static __INLINE uint8_t bds_sfloat_decode(const uint8_t len, + const uint8_t * p_encoded_data, + sfloat_t * p_decoded_val) +{ + + p_decoded_val->exponent = 0; + bds_uint16_decode(len, p_encoded_data, (uint16_t*)&p_decoded_val->mantissa); + p_decoded_val->exponent = (uint8_t)((p_decoded_val->mantissa & 0xF000) >> 12); + p_decoded_val->mantissa &= 0x0FFF; + return len; +} + + +/**@brief Function for decoding a uint8_array value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint8_array_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint8_array_t * p_decoded_val) +{ + memcpy(p_decoded_val->p_data, p_encoded_data, len); + p_decoded_val->size = len; + return p_decoded_val->size; +} + + +/**@brief Function for decoding a utf8_str value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_ble_srv_utf8_str_decode(const uint8_t len, + const uint8_t * p_encoded_data, + ble_srv_utf8_str_t * p_decoded_val) +{ + p_decoded_val->p_str = (uint8_t*)p_encoded_data; + p_decoded_val->length = len; + return p_decoded_val->length; +} + + +/**@brief Function for decoding a regcertdatalist value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_regcertdatalist_decode(const uint8_t len, + const uint8_t * p_encoded_data, + regcertdatalist_t * p_decoded_val) +{ + memcpy(p_decoded_val->p_list, p_encoded_data, len); + p_decoded_val->list_len = len; + return p_decoded_val->list_len; +} + + +/**@brief Function for decoding a date_time value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_date_time pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_ble_date_time_decode(const uint8_t len, + const uint8_t * p_encoded_data, + ble_date_time_t * p_date_time) +{ + UNUSED_VARIABLE(len); + uint8_t pos = bds_uint16_decode(len, &p_encoded_data[0], &p_date_time->year); + p_date_time->month = p_encoded_data[pos++]; + p_date_time->day = p_encoded_data[pos++]; + p_date_time->hours = p_encoded_data[pos++]; + p_date_time->minutes = p_encoded_data[pos++]; + p_date_time->seconds = p_encoded_data[pos++]; + + return pos; +} + + +#ifdef __cplusplus +} +#endif + +#endif // APP_UTIL_BDS_H__ + +/** @} */ diff --git a/components/libraries/util/app_util_platform.c b/components/libraries/util/app_util_platform.c new file mode 100644 index 0000000..67fc50f --- /dev/null +++ b/components/libraries/util/app_util_platform.c @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "app_util_platform.h" + +#ifdef SOFTDEVICE_PRESENT +/* Global nvic state instance, required by nrf_nvic.h */ +nrf_nvic_state_t nrf_nvic_state; +#endif + +static uint32_t m_in_critical_region = 0; + +void app_util_disable_irq(void) +{ + __disable_irq(); + m_in_critical_region++; +} + +void app_util_enable_irq(void) +{ + m_in_critical_region--; + if (m_in_critical_region == 0) + { + __enable_irq(); + } +} + +void app_util_critical_region_enter(uint8_t *p_nested) +{ +#if __CORTEX_M == (0x04U) + ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get()) +#endif + +#if defined(SOFTDEVICE_PRESENT) + /* return value can be safely ignored */ + (void) sd_nvic_critical_region_enter(p_nested); +#else + app_util_disable_irq(); +#endif +} + +void app_util_critical_region_exit(uint8_t nested) +{ +#if __CORTEX_M == (0x04U) + ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get()) +#endif + +#if defined(SOFTDEVICE_PRESENT) + /* return value can be safely ignored */ + (void) sd_nvic_critical_region_exit(nested); +#else + app_util_enable_irq(); +#endif +} + + +uint8_t privilege_level_get(void) +{ +#if __CORTEX_M == (0x00U) || defined(_WIN32) || defined(__unix) || defined(__APPLE__) + /* the Cortex-M0 has no concept of privilege */ + return APP_LEVEL_PRIVILEGED; +#elif __CORTEX_M >= (0x04U) + uint32_t isr_vector_num = __get_IPSR() & IPSR_ISR_Msk ; + if (0 == isr_vector_num) + { + /* Thread Mode, check nPRIV */ + int32_t control = __get_CONTROL(); + return control & CONTROL_nPRIV_Msk ? APP_LEVEL_UNPRIVILEGED : APP_LEVEL_PRIVILEGED; + } + else + { + /* Handler Mode, always privileged */ + return APP_LEVEL_PRIVILEGED; + } +#endif +} + + +uint8_t current_int_priority_get(void) +{ + uint32_t isr_vector_num = __get_IPSR() & IPSR_ISR_Msk ; + if (isr_vector_num > 0) + { + int32_t irq_type = ((int32_t)isr_vector_num - EXTERNAL_INT_VECTOR_OFFSET); + return (NVIC_GetPriority((IRQn_Type)irq_type) & 0xFF); + } + else + { + return APP_IRQ_PRIORITY_THREAD; + } +} diff --git a/components/libraries/util/app_util_platform.h b/components/libraries/util/app_util_platform.h new file mode 100644 index 0000000..7939f8a --- /dev/null +++ b/components/libraries/util/app_util_platform.h @@ -0,0 +1,280 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup app_util_platform Utility Functions and Definitions (Platform) + * @{ + * @ingroup app_common + * + * @brief Various types and definitions available to all applications when using SoftDevice. + */ + +#ifndef APP_UTIL_PLATFORM_H__ +#define APP_UTIL_PLATFORM_H__ + +#include +#include "compiler_abstraction.h" +#include "nrf.h" +#ifdef SOFTDEVICE_PRESENT +#include "nrf_soc.h" +#include "nrf_nvic.h" +#endif +#include "nrf_assert.h" +#include "app_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if __CORTEX_M == (0x00U) +#define _PRIO_SD_HIGH 0 +#define _PRIO_APP_HIGH 1 +#define _PRIO_APP_MID 1 +#define _PRIO_SD_LOW 2 +#define _PRIO_APP_LOW_MID 3 +#define _PRIO_APP_LOW 3 +#define _PRIO_APP_LOWEST 3 +#define _PRIO_THREAD 4 +#elif __CORTEX_M >= (0x04U) +#define _PRIO_SD_HIGH 0 +#define _PRIO_SD_MID 1 +#define _PRIO_APP_HIGH 2 +#define _PRIO_APP_MID 3 +#define _PRIO_SD_LOW 4 +#define _PRIO_APP_LOW_MID 5 +#define _PRIO_APP_LOW 6 +#define _PRIO_APP_LOWEST 7 +#define _PRIO_THREAD 15 +#else + #error "No platform defined" +#endif + + +//lint -save -e113 -e452 +/**@brief The interrupt priorities available to the application while the SoftDevice is active. */ +typedef enum +{ +#ifndef SOFTDEVICE_PRESENT + APP_IRQ_PRIORITY_HIGHEST = _PRIO_SD_HIGH, /**< Running in Application Highest interrupt level. */ +#else + APP_IRQ_PRIORITY_HIGHEST = _PRIO_APP_HIGH, /**< Running in Application Highest interrupt level. */ +#endif + APP_IRQ_PRIORITY_HIGH = _PRIO_APP_HIGH, /**< Running in Application High interrupt level. */ +#ifndef SOFTDEVICE_PRESENT + APP_IRQ_PRIORITY_MID = _PRIO_SD_LOW, /**< Running in Application Middle interrupt level. */ +#else + APP_IRQ_PRIORITY_MID = _PRIO_APP_MID, /**< Running in Application Middle interrupt level. */ +#endif + APP_IRQ_PRIORITY_LOW_MID = _PRIO_APP_LOW_MID, /**< Running in Application Middle Low interrupt level. */ + APP_IRQ_PRIORITY_LOW = _PRIO_APP_LOW, /**< Running in Application Low interrupt level. */ + APP_IRQ_PRIORITY_LOWEST = _PRIO_APP_LOWEST, /**< Running in Application Lowest interrupt level. */ + APP_IRQ_PRIORITY_THREAD = _PRIO_THREAD /**< Running in Thread Mode. */ +} app_irq_priority_t; +//lint -restore + + +/*@brief The privilege levels available to applications in Thread Mode */ +typedef enum +{ + APP_LEVEL_UNPRIVILEGED, + APP_LEVEL_PRIVILEGED +} app_level_t; + +/**@cond NO_DOXYGEN */ +#define EXTERNAL_INT_VECTOR_OFFSET 16 +/**@endcond */ + +/**@brief Macro for setting a breakpoint. + */ +#if defined(__GNUC__) +#define NRF_BREAKPOINT __asm__("BKPT 0"); +#else +#define NRF_BREAKPOINT __BKPT(0) +#endif + +/** @brief Macro for setting a breakpoint. + * + * If it is possible to detect debugger presence then it is set only in that case. + * + */ +#if __CORTEX_M == 0x04 +#define NRF_BREAKPOINT_COND do { \ + /* C_DEBUGEN == 1 -> Debugger Connected */ \ + if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) \ + { \ + /* Generate breakpoint if debugger is connected */ \ + NRF_BREAKPOINT; \ + } \ + }while (0) +#else +#define NRF_BREAKPOINT_COND NRF_BREAKPOINT +#endif // __CORTEX_M == 0x04 + +#if defined ( __CC_ARM ) +#define PACKED(TYPE) __packed TYPE +#define PACKED_STRUCT PACKED(struct) +#elif defined ( __GNUC__ ) +#define PACKED __attribute__((packed)) +#define PACKED_STRUCT struct PACKED +#elif defined (__ICCARM__) +#define PACKED_STRUCT __packed struct +#endif + +#if defined ( __CC_ARM ) +#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma ("push") \ + _Pragma ("O3") +#define PRAGMA_OPTIMIZATION_FORCE_END _Pragma ("pop") +#elif defined ( __GNUC__ ) +#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma("GCC push_options") \ + _Pragma ("GCC optimize (\"Os\")") +#define PRAGMA_OPTIMIZATION_FORCE_END _Pragma ("GCC pop_options") +#elif defined (__ICCARM__) +#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma ("optimize=high z") +#define PRAGMA_OPTIMIZATION_FORCE_END +#endif + +void app_util_disable_irq(void); +void app_util_enable_irq(void); + +void app_util_critical_region_enter (uint8_t *p_nested); +void app_util_critical_region_exit (uint8_t nested); + +/**@brief Macro for entering a critical region. + * + * @note Due to implementation details, there must exist one and only one call to + * CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located + * in the same scope. + */ +#ifdef SOFTDEVICE_PRESENT +#define CRITICAL_REGION_ENTER() \ + { \ + uint8_t __CR_NESTED = 0; \ + app_util_critical_region_enter(&__CR_NESTED); +#else +#define CRITICAL_REGION_ENTER() app_util_critical_region_enter(NULL) +#endif + +/**@brief Macro for leaving a critical region. + * + * @note Due to implementation details, there must exist one and only one call to + * CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located + * in the same scope. + */ +#ifdef SOFTDEVICE_PRESENT +#define CRITICAL_REGION_EXIT() \ + app_util_critical_region_exit(__CR_NESTED); \ + } +#else +#define CRITICAL_REGION_EXIT() app_util_critical_region_exit(0) +#endif + +/* Workaround for Keil 4 */ +#ifndef IPSR_ISR_Msk +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ +#endif + + + +/**@brief Macro to enable anonymous unions from a certain point in the code. + */ +#if defined(__CC_ARM) + #define ANON_UNIONS_ENABLE _Pragma("push") \ + _Pragma("anon_unions") \ + struct semicolon_swallower +#elif defined(__ICCARM__) + #define ANON_UNIONS_ENABLE _Pragma("language=extended") \ + struct semicolon_swallower +#else + #define ANON_UNIONS_ENABLE struct semicolon_swallower + // No action will be taken. + // For GCC anonymous unions are enabled by default. +#endif + +/**@brief Macro to disable anonymous unions from a certain point in the code. + * @note Call only after first calling @ref ANON_UNIONS_ENABLE. + */ +#if defined(__CC_ARM) + #define ANON_UNIONS_DISABLE _Pragma("pop") \ + struct semicolon_swallower +#elif defined(__ICCARM__) + #define ANON_UNIONS_DISABLE struct semicolon_swallower + // for IAR leave anonymous unions enabled +#else + #define ANON_UNIONS_DISABLE struct semicolon_swallower + // No action will be taken. + // For GCC anonymous unions are enabled by default. +#endif + +/**@brief Macro for adding pragma directive only for GCC. + */ +#ifdef __GNUC__ +#define GCC_PRAGMA(v) _Pragma(v) +#else +#define GCC_PRAGMA(v) +#endif + +/* Workaround for Keil 4 */ +#ifndef CONTROL_nPRIV_Msk +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ +#endif + +/**@brief Function for finding the current interrupt level. + * + * @return Current interrupt level. See @ref app_irq_priority_t for values. + */ +uint8_t current_int_priority_get(void); + + +/**@brief Function for finding out the current privilege level. + * + * @return Current privilege level. + * @retval APP_LEVEL_UNPRIVILEGED We are running in unprivileged level. + * @retval APP_LEVEL_PRIVILEGED We are running in privileged level. + */ +uint8_t privilege_level_get(void); + + +#ifdef __cplusplus +} +#endif + +#endif // APP_UTIL_PLATFORM_H__ + +/** @} */ diff --git a/components/libraries/util/nordic_common.h b/components/libraries/util/nordic_common.h new file mode 100644 index 0000000..71f7a56 --- /dev/null +++ b/components/libraries/util/nordic_common.h @@ -0,0 +1,215 @@ +/** + * Copyright (c) 2008 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * @brief Common defines and macros for firmware developed by Nordic Semiconductor. + */ + +#ifndef NORDIC_COMMON_H__ +#define NORDIC_COMMON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Check if selected module is enabled + * + * This is save function for driver enable checking. + * Correct from Lint point of view (not using default of undefined value). + * + * Usage: + * @code + #if NRF_MODULE_ENABLED(UART) + ... + #endif + * @endcode + * + * @param module The module name. + * + * @retval 1 The macro _ENABLE is defined and is non-zero. + * @retval 0 The macro _ENABLE is not defined or it equals zero. + * + * @note + * This macro intentionally does not implement second expansion level. + * The name of the module to be checked has to be given directly as a parameter. + * And given parameter would be connected with @c _ENABLED postfix directly + * without evaluating its value. + */ +//lint -emacro(491,NRF_MODULE_ENABLED) // Suppers warning 491 "non-standard use of 'defined' preprocessor operator" +#ifdef NRF_MODULE_ENABLE_ALL +#warning "Do not use NRF_MODULE_ENABLE_ALL for real builds." +#define NRF_MODULE_ENABLED(module) 1 +#else +#define NRF_MODULE_ENABLED(module) \ + ((defined(module ## _ENABLED) && (module ## _ENABLED)) ? 1 : 0) +#endif +/** The upper 8 bits of a 32 bit value */ +//lint -emacro(572,MSB_32) // Suppress warning 572 "Excessive shift value" +#define MSB_32(a) (((a) & 0xFF000000) >> 24) +/** The lower 8 bits (of a 32 bit value) */ +#define LSB_32(a) ((a) & 0x000000FF) + +/** The upper 8 bits of a 16 bit value */ +//lint -emacro(572,MSB_16) // Suppress warning 572 "Excessive shift value" +#define MSB_16(a) (((a) & 0xFF00) >> 8) +/** The lower 8 bits (of a 16 bit value) */ +#define LSB_16(a) ((a) & 0x00FF) + +/** Leaves the minimum of the two 32-bit arguments */ +/*lint -emacro(506, MIN) */ /* Suppress "Constant value Boolean */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +/** Leaves the maximum of the two 32-bit arguments */ +/*lint -emacro(506, MAX) */ /* Suppress "Constant value Boolean */ +#define MAX(a, b) ((a) < (b) ? (b) : (a)) + +/**@brief Concatenates two parameters. + * + * It realizes two level expansion to make it sure that all the parameters + * are actually expanded before gluing them together. + * + * @param p1 First parameter to concatenating + * @param p2 Second parameter to concatenating + * + * @return Two parameters glued together. + * They have to create correct C mnemonic in other case + * preprocessor error would be generated. + * + * @sa CONCAT_3 + */ +#define CONCAT_2(p1, p2) CONCAT_2_(p1, p2) +/** Auxiliary macro used by @ref CONCAT_2 */ +#define CONCAT_2_(p1, p2) p1##p2 + +/**@brief Concatenates three parameters. + * + * It realizes two level expansion to make it sure that all the parameters + * are actually expanded before gluing them together. + * + * @param p1 First parameter to concatenating + * @param p2 Second parameter to concatenating + * @param p3 Third parameter to concatenating + * + * @return Three parameters glued together. + * They have to create correct C mnemonic in other case + * preprocessor error would be generated. + * + * @sa CONCAT_2 + */ +#define CONCAT_3(p1, p2, p3) CONCAT_3_(p1, p2, p3) +/** Auxiliary macro used by @ref CONCAT_3 */ +#define CONCAT_3_(p1, p2, p3) p1##p2##p3 + +#define STRINGIFY_(val) #val +/** Converts a macro argument into a character constant. + */ +#define STRINGIFY(val) STRINGIFY_(val) + +/** Counts number of elements inside the array + */ +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +/**@brief Set a bit in the uint32 word. + * + * @param[in] W Word whose bit is being set. + * @param[in] B Bit number in the word to be set. + */ +#define SET_BIT(W, B) ((W) |= (uint32_t)(1U << (B))) + + +/**@brief Clears a bit in the uint32 word. + * + * @param[in] W Word whose bit is to be cleared. + * @param[in] B Bit number in the word to be cleared. + */ +#define CLR_BIT(W, B) ((W) &= (~(uint32_t)(1U << (B)))) + + +/**@brief Checks if a bit is set. + * + * @param[in] W Word whose bit is to be checked. + * @param[in] B Bit number in the word to be checked. + * + * @retval 1 if bit is set. + * @retval 0 if bit is not set. + */ +#define IS_SET(W, B) (((W) >> (B)) & 1) + +#define BIT_0 0x01 /**< The value of bit 0 */ +#define BIT_1 0x02 /**< The value of bit 1 */ +#define BIT_2 0x04 /**< The value of bit 2 */ +#define BIT_3 0x08 /**< The value of bit 3 */ +#define BIT_4 0x10 /**< The value of bit 4 */ +#define BIT_5 0x20 /**< The value of bit 5 */ +#define BIT_6 0x40 /**< The value of bit 6 */ +#define BIT_7 0x80 /**< The value of bit 7 */ +#define BIT_8 0x0100 /**< The value of bit 8 */ +#define BIT_9 0x0200 /**< The value of bit 9 */ +#define BIT_10 0x0400 /**< The value of bit 10 */ +#define BIT_11 0x0800 /**< The value of bit 11 */ +#define BIT_12 0x1000 /**< The value of bit 12 */ +#define BIT_13 0x2000 /**< The value of bit 13 */ +#define BIT_14 0x4000 /**< The value of bit 14 */ +#define BIT_15 0x8000 /**< The value of bit 15 */ +#define BIT_16 0x00010000 /**< The value of bit 16 */ +#define BIT_17 0x00020000 /**< The value of bit 17 */ +#define BIT_18 0x00040000 /**< The value of bit 18 */ +#define BIT_19 0x00080000 /**< The value of bit 19 */ +#define BIT_20 0x00100000 /**< The value of bit 20 */ +#define BIT_21 0x00200000 /**< The value of bit 21 */ +#define BIT_22 0x00400000 /**< The value of bit 22 */ +#define BIT_23 0x00800000 /**< The value of bit 23 */ +#define BIT_24 0x01000000 /**< The value of bit 24 */ +#define BIT_25 0x02000000 /**< The value of bit 25 */ +#define BIT_26 0x04000000 /**< The value of bit 26 */ +#define BIT_27 0x08000000 /**< The value of bit 27 */ +#define BIT_28 0x10000000 /**< The value of bit 28 */ +#define BIT_29 0x20000000 /**< The value of bit 29 */ +#define BIT_30 0x40000000 /**< The value of bit 30 */ +#define BIT_31 0x80000000 /**< The value of bit 31 */ + +#define UNUSED_VARIABLE(X) ((void)(X)) +#define UNUSED_PARAMETER(X) UNUSED_VARIABLE(X) +#define UNUSED_RETURN_VALUE(X) UNUSED_VARIABLE(X) + +#ifdef __cplusplus +} +#endif + +#endif // NORDIC_COMMON_H__ diff --git a/components/libraries/util/nrf_assert.c b/components/libraries/util/nrf_assert.c new file mode 100644 index 0000000..1c76201 --- /dev/null +++ b/components/libraries/util/nrf_assert.c @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2006 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_assert.h" +#include "app_error.h" +#include "nordic_common.h" + +__WEAK void assert_nrf_callback(uint16_t line_num, const uint8_t * file_name) +{ + assert_info_t assert_info = + { + .line_num = line_num, + .p_file_name = file_name, + }; + app_error_fault_handler(NRF_FAULT_ID_SDK_ASSERT, 0, (uint32_t)(&assert_info)); + + UNUSED_VARIABLE(assert_info); +} diff --git a/components/libraries/util/nrf_assert.h b/components/libraries/util/nrf_assert.h new file mode 100644 index 0000000..cd28884 --- /dev/null +++ b/components/libraries/util/nrf_assert.h @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2006 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * @brief Utilities for verifying program logic + */ + +#ifndef NRF_ASSERT_H_ +#define NRF_ASSERT_H_ + +#include +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Function for handling assertions. + * + * + * @note + * This function is called when an assertion has triggered. + * + * @note + * This function is deprecated and will be removed in future releases. + * Use app_error_fault_handler instead. + * + * + * @post + * All hardware is put into an idle non-emitting state (in particular the radio is highly + * important to switch off since the radio might be in a state that makes it send + * packets continiously while a typical final infinit ASSERT loop is executing). + * + * + * @param line_num The line number where the assertion is called + * @param file_name Pointer to the file name + */ +//lint -save -esym(14, assert_nrf_callback) +void assert_nrf_callback(uint16_t line_num, const uint8_t *file_name); +//lint -restore + +#if (defined(DEBUG_NRF) || defined(DEBUG_NRF_USER)) +#define NRF_ASSERT_PRESENT 1 +#else +#define NRF_ASSERT_PRESENT 0 +#endif + +//#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER) + +/*lint -emacro(506, ASSERT) */ /* Suppress "Constant value Boolean */ +/*lint -emacro(774, ASSERT) */ /* Suppress "Boolean within 'if' always evaluates to True" */ \ + +/** @brief Function for checking intended for production code. + * + * Check passes if "expr" evaluates to true. */ + +#ifdef _lint +#define ASSERT(expr) \ +if (expr) \ +{ \ +} \ +else \ +{ \ + while (1); \ +} +#else //_lint +#define ASSERT(expr) \ +if (NRF_ASSERT_PRESENT) \ +{ \ + if (expr) \ + { \ + } \ + else \ + { \ + assert_nrf_callback((uint16_t)__LINE__, (uint8_t *)__FILE__); \ + } \ +} + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ASSERT_H_ */ diff --git a/components/libraries/util/nrf_bitmask.h b/components/libraries/util/nrf_bitmask.h new file mode 100644 index 0000000..59e1ed0 --- /dev/null +++ b/components/libraries/util/nrf_bitmask.h @@ -0,0 +1,147 @@ +/** + * Copyright (c) 2006 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_BITMASK_H +#define NRF_BITMASK_H + +#include "compiler_abstraction.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define BITMASK_BYTE_GET(abs_bit) ((abs_bit)/8) +#define BITMASK_RELBIT_GET(abs_bit) ((abs_bit) & 0x00000007) + +/** + * Function for checking if bit in the multi-byte bit mask is set. + * + * @param bit Bit index. + * @param p_mask A pointer to mask with bit fields. + * + * @return 0 if bit is not set, positive value otherwise. + */ +__STATIC_INLINE uint32_t nrf_bitmask_bit_is_set(uint32_t bit, void const * p_mask) +{ + uint8_t const * p_mask8 = (uint8_t const *)p_mask; + uint32_t byte_idx = BITMASK_BYTE_GET(bit); + bit = BITMASK_RELBIT_GET(bit); + return (1 << bit) & p_mask8[byte_idx]; +} + +/** + * Function for setting a bit in the multi-byte bit mask. + * + * @param bit Bit index. + * @param p_mask A pointer to mask with bit fields. + */ +__STATIC_INLINE void nrf_bitmask_bit_set(uint32_t bit, void * p_mask) +{ + uint8_t * p_mask8 = (uint8_t *)p_mask; + uint32_t byte_idx = BITMASK_BYTE_GET(bit); + bit = BITMASK_RELBIT_GET(bit); + p_mask8[byte_idx] |= (1 << bit); +} + +/** + * Function for clearing a bit in the multi-byte bit mask. + * + * @param bit Bit index. + * @param p_mask A pointer to mask with bit fields. + */ +__STATIC_INLINE void nrf_bitmask_bit_clear(uint32_t bit, void * p_mask) +{ + uint8_t * p_mask8 = (uint8_t *)p_mask; + uint32_t byte_idx = BITMASK_BYTE_GET(bit); + bit = BITMASK_RELBIT_GET(bit); + p_mask8[byte_idx] &= ~(1 << bit); +} + +/** + * Function for performing bitwise OR operation on two multi-byte bit masks. + * + * @param p_mask1 A pointer to the first bit mask. + * @param p_mask2 A pointer to the second bit mask. + * @param p_mask_out A pointer to the output bit mask. + * @param length Length of output mask in bytes. + */ +__STATIC_INLINE void nrf_bitmask_masks_or(void const * p_mask1, + void const * p_mask2, + void * p_out_mask, + uint32_t length) +{ + uint8_t const * p_mask8_1 = (uint8_t const *)p_mask1; + uint8_t const * p_mask8_2 = (uint8_t const *)p_mask2; + uint8_t * p_mask8_out = (uint8_t *)p_out_mask; + uint32_t i; + for (i = 0; i < length; i++) + { + p_mask8_out[i] = p_mask8_1[i] | p_mask8_2[i]; + } +} + +/** + * Function for performing bitwise AND operation on two multi-byte bit masks. + * + * @param p_mask1 A pointer to the first bit mask. + * @param p_mask2 A pointer to the second bit mask. + * @param p_mask_out A pointer to the output bit mask. + * @param length Length of output mask in bytes. + */ +__STATIC_INLINE void nrf_bitmask_masks_and(void const * p_mask1, + void const * p_mask2, + void * p_out_mask, + uint32_t length) +{ + uint8_t const * p_mask8_1 = (uint8_t const *)p_mask1; + uint8_t const * p_mask8_2 = (uint8_t const *)p_mask2; + uint8_t * p_mask8_out = (uint8_t *)p_out_mask; + uint32_t i; + for (i = 0; i < length; i++) + { + p_mask8_out[i] = p_mask8_1[i] & p_mask8_2[i]; + } +} + +#ifdef __cplusplus +} +#endif + +#endif //NRF_BITMASK_H diff --git a/components/libraries/util/sdk_alloca.h b/components/libraries/util/sdk_alloca.h new file mode 100644 index 0000000..0485e02 --- /dev/null +++ b/components/libraries/util/sdk_alloca.h @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file sdk_alloca.h + * + * @brief Defines alloca() function. + * + * @details This file defines alloca() function. This can be done directly or by including system + * header files. Not all platforms support alloca(). In this case no error will be shown, but + * SDK_ALLOCA_DEFINED will be set to 0. + */ + +#ifndef SDK_ALLOCA_H__ +#define SDK_ALLOCA_H__ + + +#if defined(__SDK_DOXYGEN__) + /** @brief Set to one it alloca() function is available on this platform and it is correctly defined + * by this header file. + */ + #define SDK_ALLOCA_DEFINED 1 +#elif defined(__GNUC__) + #if defined(__SES_ARM) + // SES does not have definition of alloca(), but it have working GCC's __builtin_alloca(). + #if !defined(alloca) + #define alloca(size) __builtin_alloca((size)) + #endif + #else + // alloca() can be defined in on some platforms, but if not then try standard header file. + #include + #if !defined(alloca) + #include + #endif + #endif + #define SDK_ALLOCA_DEFINED 1 +#elif defined(__IAR_SYSTEMS_ICC__) + // IAR does not support alloca() function. + #define SDK_ALLOCA_DEFINED 0 +#else + // All other supported compilers have alloca() definition in header file. + #include + #define SDK_ALLOCA_DEFINED 1 +#endif + + +/*lint -"d__builtin_alloca=(void*)" */ + + +#endif // NRF_ALLOCA_H__ diff --git a/components/libraries/util/sdk_common.h b/components/libraries/util/sdk_common.h new file mode 100644 index 0000000..057a3cb --- /dev/null +++ b/components/libraries/util/sdk_common.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2013 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @cond */ +/**@file + * + * @ingroup experimental_api + * @defgroup sdk_common SDK Common Header + * @brief All common headers needed for SDK examples will be included here so that application + * developer does not have to include headers on him/herself. + * @{ + */ + +#ifndef SDK_COMMON_H__ +#define SDK_COMMON_H__ + +#include +#include +#include +#include "sdk_config.h" +#include "nordic_common.h" +#include "compiler_abstraction.h" +#include "sdk_os.h" +#include "sdk_errors.h" +#include "app_util.h" +#include "sdk_macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @} */ +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_COMMON_H__ + diff --git a/components/libraries/util/sdk_errors.h b/components/libraries/util/sdk_errors.h new file mode 100644 index 0000000..3b04f10 --- /dev/null +++ b/components/libraries/util/sdk_errors.h @@ -0,0 +1,168 @@ +/** + * Copyright (c) 2013 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_error SDK Error codes + * @{ + * @ingroup app_common + * @{ + * @details Error codes are 32-bit unsigned integers with the most significant 16-bit reserved for + * identifying the module where the error occurred while the least least significant LSB + * are used to provide the cause or nature of error. Each module is assigned a 16-bit + * unsigned integer. Which it will use to identify all errors that occurred in it. 16-bit + * LSB range is with module id as the MSB in the 32-bit error code is reserved for the + * module. As an example, if 0x8800 identifies a certain SDK module, all values from + * 0x88000000 - 0x8800FFFF are reserved for this module. + * It should be noted that common error reasons have been assigned values to make it + * possible to decode error reason easily. As an example, lets module uninitialized has + * been assigned an error code 0x000A0. Then, if application encounters an error code + * 0xZZZZ00A0, it knows that it accessing a certain module without initializing it. + * Apart from this, each module is allowed to define error codes that are not covered by + * the common ones, however, these values are defined in a range that does not conflict + * with common error values. For module, specific error however, it is possible that the + * same error value is used by two different modules to indicated errors of very different + * nature. If error is already defined by the NRF common error codes, these are reused. + * A range is reserved for application as well, it can use this range for defining + * application specific errors. + * + * @note Success code, NRF_SUCCESS, does not include any module identifier. + + */ + +#ifndef SDK_ERRORS_H__ +#define SDK_ERRORS_H__ + +#include +#include "nrf_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup sdk_err_base Base defined for SDK Modules + * @{ + */ +#define NRF_ERROR_SDK_ERROR_BASE (NRF_ERROR_BASE_NUM + 0x8000) /**< Base value defined for SDK module identifiers. */ +#define NRF_ERROR_SDK_COMMON_ERROR_BASE (NRF_ERROR_BASE_NUM + 0x0080) /**< Base error value to be used for SDK error values. */ +/** @} */ + +/** + * @defgroup sdk_module_codes Codes reserved as identification for module where the error occurred. + * @{ + */ +#define NRF_ERROR_MEMORY_MANAGER_ERR_BASE (0x8100) /**< Base address for Memory Manager related errors. */ +#define NRF_ERROR_PERIPH_DRIVERS_ERR_BASE (0x8200) /**< Base address for Peripheral drivers related errors. */ +#define NRF_ERROR_GAZELLE_ERR_BASE (0x8300) /**< Base address for Gazelle related errors. */ +#define NRF_ERROR_BLE_IPSP_ERR_BASE (0x8400) /**< Base address for BLE IPSP related errors. */ +#define NRF_ERROR_CRYPTO_ERR_BASE (0x8500) /**< Base address for crypto related errors. */ +#define NRF_ERROR_FDS_ERR_BASE (0x8600) /**< Base address for FDS related errors. */ +/** @} */ + + +/** + * @defgroup sdk_iot_errors Codes reserved as identification for IoT errors. + * @{ + */ +#define NRF_ERROR_IOT_ERR_BASE_START (0xA000) +#define NRF_ERROR_IOT_ERR_BASE_STOP (0xAFFF) +/** @} */ + + +/** + * @defgroup sdk_common_errors Codes reserved as identification for common errors. + * @{ + */ +#define NRF_ERROR_MODULE_NOT_INITIALIZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0000) ///< Module not initialized +#define NRF_ERROR_MUTEX_INIT_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0001) ///< Mutex initialization failed +#define NRF_ERROR_MUTEX_LOCK_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0002) ///< Mutex lock failed +#define NRF_ERROR_MUTEX_UNLOCK_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0003) ///< Mutex unlock failed +#define NRF_ERROR_MUTEX_COND_INIT_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0004) ///< Mutex conditional initialization failed +#define NRF_ERROR_MODULE_ALREADY_INITIALIZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0005) ///< Module already initialized +#define NRF_ERROR_STORAGE_FULL (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0006) ///< Storage full +#define NRF_ERROR_API_NOT_IMPLEMENTED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0010) ///< API not implemented +#define NRF_ERROR_FEATURE_NOT_ENABLED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0011) ///< Feature not enabled +#define NRF_ERROR_IO_PENDING (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0012) ///< Input/Output pending +/** @} */ + + +/** + * @defgroup drv_specific_errors Error / status codes specific to drivers. + * @{ + */ +#define NRF_ERROR_DRV_TWI_ERR_OVERRUN (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0000) +#define NRF_ERROR_DRV_TWI_ERR_ANACK (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0001) +#define NRF_ERROR_DRV_TWI_ERR_DNACK (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0002) +/** @} */ + + +/** + * @defgroup ble_ipsp_errors IPSP codes + * @brief Error and status codes specific to IPSP. + * @{ + */ +#define NRF_ERROR_BLE_IPSP_RX_PKT_TRUNCATED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0000) +#define NRF_ERROR_BLE_IPSP_CHANNEL_ALREADY_EXISTS (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0001) +#define NRF_ERROR_BLE_IPSP_LINK_DISCONNECTED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0002) +#define NRF_ERROR_BLE_IPSP_PEER_REJECTED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0003) +/* @} */ + + +/** + * @brief API Result. + * + * @details Indicates success or failure of an API procedure. In case of failure, a comprehensive + * error code indicating cause or reason for failure is provided. + * + * Though called an API result, it could used in Asynchronous notifications callback along + * with asynchronous callback as event result. This mechanism is employed when an event + * marks the end of procedure initiated using API. API result, in this case, will only be + * an indicative of whether the procedure has been requested successfully. + */ +typedef uint32_t ret_code_t; + +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_ERRORS_H__ diff --git a/components/libraries/util/sdk_macros.h b/components/libraries/util/sdk_macros.h new file mode 100644 index 0000000..27681e3 --- /dev/null +++ b/components/libraries/util/sdk_macros.h @@ -0,0 +1,224 @@ +/** + * Copyright (c) 2013 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + + * @defgroup sdk_common_macros SDK Common Header + * @ingroup app_common + * @brief Macros for parameter checking and similar tasks + * @{ + */ + +#ifndef SDK_MACROS_H__ +#define SDK_MACROS_H__ + +#include "nrf_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Macro for parameter checking. + * + * If @p _cond evaluates to true, does nothing. Otherwise, + * if @p _module ## _PARAM_CHECK_DISABLED is @e not set (default), prints an error message + * if @p _printfn is provided, and returns from the calling function context with code @p _err. + * If @p _module ## _PARAM_CHECK_DISABLED is set, behaves like the ASSERT macro. + * + * Parameter checking implemented using this macro can be optionally turned off for release code. + * Only disable runtime parameter checks if size if a major concern. + * + * @param _module The module name. + * @param _cond The condition to be evaluated. + * @param _err The error to be returned. + * @param _printfn A printf-compatible function used to log the error. + * Leave empty if no logging is needed. + * + * @hideinitializer + */ +/*lint -esym(666, NRF_PARAM_CHECK*) : Expression with side effects passed to macro */ +#define NRF_PARAM_CHECK(_module, _cond, _err, _printfn) \ + do \ + { \ + if ((_cond)) \ + { \ + /* Do nothing. */ \ + } \ + else if (!(_module ## _PARAM_CHECK_DISABLED)) \ + { \ + _printfn("%s check failed in %s() with value 0x%x.", #_cond, __func__, _err); \ + return (_err); \ + } \ + else \ + { \ + ASSERT((_cond)); \ + } \ + } while (0); + + +/**@brief Macro for verifying statement to be true. It will cause the exterior function to return + * err_code if the statement is not true. + * + * @param[in] statement Statement to test. + * @param[in] err_code Error value to return if test was invalid. + * + * @retval nothing, but will cause the exterior function to return @p err_code if @p statement + * is false. + */ +#define VERIFY_TRUE(statement, err_code) \ +do \ +{ \ + if (!(statement)) \ + { \ + return err_code; \ + } \ +} while (0) + + +/**@brief Macro for verifying statement to be true. It will cause the exterior function to return + * if the statement is not true. + * + * @param[in] statement Statement to test. + */ +#define VERIFY_TRUE_VOID(statement) VERIFY_TRUE((statement), ) + + +/**@brief Macro for verifying statement to be false. It will cause the exterior function to return + * err_code if the statement is not false. + * + * @param[in] statement Statement to test. + * @param[in] err_code Error value to return if test was invalid. + * + * @retval nothing, but will cause the exterior function to return @p err_code if @p statement + * is true. + */ +#define VERIFY_FALSE(statement, err_code) \ +do \ +{ \ + if ((statement)) \ + { \ + return err_code; \ + } \ +} while (0) + + +/**@brief Macro for verifying statement to be false. It will cause the exterior function to return + * if the statement is not false. + * + * @param[in] statement Statement to test. + */ +#define VERIFY_FALSE_VOID(statement) VERIFY_FALSE((statement), ) + + +/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior + * function to return error code of statement if it is not @ref NRF_SUCCESS. + * + * @param[in] statement Statement to check against NRF_SUCCESS. + */ +#define VERIFY_SUCCESS(statement) \ +do \ +{ \ + uint32_t _err_code = (uint32_t) (statement); \ + if (_err_code != NRF_SUCCESS) \ + { \ + return _err_code; \ + } \ +} while(0) + + +/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior + * function to return if the err_code is not @ref NRF_SUCCESS. + * + * @param[in] err_code The error code to check. + */ +#define VERIFY_SUCCESS_VOID(err_code) VERIFY_TRUE_VOID((err_code) == NRF_SUCCESS) + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return @ref NRF_ERROR_INVALID_STATE if not. + * + * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED + * should be true if the module is initialized, false if not. + */ +#define VERIFY_MODULE_INITIALIZED() VERIFY_TRUE((MODULE_INITIALIZED), NRF_ERROR_INVALID_STATE) + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED + * should be true if the module is initialized, false if not. + */ +#define VERIFY_MODULE_INITIALIZED_VOID() VERIFY_TRUE_VOID((MODULE_INITIALIZED)) + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return false if not. + * + * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED + * should be true if the module is initialized, false if not. + */ +#define VERIFY_MODULE_INITIALIZED_BOOL() VERIFY_TRUE((MODULE_INITIALIZED), false) + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @param[in] param The variable to check if is NULL. + */ +#define VERIFY_PARAM_NOT_NULL(param) VERIFY_FALSE(((param) == NULL), NRF_ERROR_NULL) + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @param[in] param The variable to check if is NULL. + */ +#define VERIFY_PARAM_NOT_NULL_VOID(param) VERIFY_FALSE_VOID(((param) == NULL)) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_MACROS_H__ + diff --git a/components/libraries/util/sdk_mapped_flags.c b/components/libraries/util/sdk_mapped_flags.c new file mode 100644 index 0000000..4d1b26e --- /dev/null +++ b/components/libraries/util/sdk_mapped_flags.c @@ -0,0 +1,220 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_mapped_flags.h" +#include +#include +#include +#include "compiler_abstraction.h" + + +// Test whether the flag collection type is large enough to hold all the flags. If this fails, +// reduce SDK_MAPPED_FLAGS_N_KEYS or increase the size of sdk_mapped_flags_t. +STATIC_ASSERT((sizeof(sdk_mapped_flags_t) * SDK_MAPPED_FLAGS_N_KEYS_PER_BYTE) >= SDK_MAPPED_FLAGS_N_KEYS); + + +/**@brief Function for setting the state of a flag to true. + * + * @note This function does not check whether the index is valid. + * + * @param[in] p_flags The collection of flags to modify. + * @param[in] index The index of the flag to modify. + */ +static __INLINE void sdk_mapped_flags_set_by_index(sdk_mapped_flags_t * p_flags, uint16_t index) +{ + *p_flags |= (1U << index); +} + + +/**@brief Function for setting the state of a flag to false. + * + * @note This function does not check whether the index is valid. + * + * @param[in] p_flags The collection of flags to modify. + * @param[in] index The index of the flag to modify. + */ +static __INLINE void sdk_mapped_flags_clear_by_index(sdk_mapped_flags_t * p_flags, uint16_t index) +{ + *p_flags &= ~(1U << index); +} + + +/**@brief Function for getting the state of a flag. + * + * @note This function does not check whether the index is valid. + * + * @param[in] p_flags The collection of flags to read. + * @param[in] index The index of the flag to get. + */ +static __INLINE bool sdk_mapped_flags_get_by_index(sdk_mapped_flags_t flags, uint16_t index) +{ + return ((flags & (1 << index)) != 0); +} + + + +uint16_t sdk_mapped_flags_first_key_index_get(sdk_mapped_flags_t flags) +{ + for (uint16_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (sdk_mapped_flags_get_by_index(flags, i)) + { + return i; + } + } + return SDK_MAPPED_FLAGS_INVALID_INDEX; +} + + +void sdk_mapped_flags_update_by_key(uint16_t * p_keys, + sdk_mapped_flags_t * p_flags, + uint16_t key, + bool value) +{ + sdk_mapped_flags_bulk_update_by_key(p_keys, p_flags, 1, key, value); +} + + +void sdk_mapped_flags_bulk_update_by_key(uint16_t * p_keys, + sdk_mapped_flags_t * p_flags, + uint32_t n_flag_collections, + uint16_t key, + bool value) +{ + if ((p_keys != NULL) && (p_flags != NULL) && (n_flag_collections > 0)) + { + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (p_keys[i] == key) + { + for (uint32_t j = 0; j < n_flag_collections; j++) + { + if (value) + { + sdk_mapped_flags_set_by_index(&p_flags[j], i); + } + else + { + sdk_mapped_flags_clear_by_index(&p_flags[j], i); + } + } + return; + } + } + } +} + + +bool sdk_mapped_flags_get_by_key_w_idx(uint16_t * p_keys, + sdk_mapped_flags_t flags, + uint16_t key, + uint8_t * p_index) +{ + if (p_keys != NULL) + { + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (p_keys[i] == key) + { + if (p_index != NULL) + { + *p_index = i; + } + return sdk_mapped_flags_get_by_index(flags, i); + } + } + } + if (p_index != NULL) + { + *p_index = SDK_MAPPED_FLAGS_N_KEYS; + } + return false; +} + + +bool sdk_mapped_flags_get_by_key(uint16_t * p_keys, sdk_mapped_flags_t flags, uint16_t key) +{ + if (p_keys != NULL) + { + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (p_keys[i] == key) + { + return sdk_mapped_flags_get_by_index(flags, i); + } + } + } + return false; +} + + +sdk_mapped_flags_key_list_t sdk_mapped_flags_key_list_get(uint16_t * p_keys, + sdk_mapped_flags_t flags) +{ + sdk_mapped_flags_key_list_t key_list; + key_list.len = 0; + + if (p_keys != NULL) + { + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (sdk_mapped_flags_get_by_index(flags, i)) + { + key_list.flag_keys[key_list.len++] = p_keys[i]; + } + } + } + + return key_list; +} + + +uint32_t sdk_mapped_flags_n_flags_set(sdk_mapped_flags_t flags) +{ + uint32_t n_flags_set = 0; + + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (sdk_mapped_flags_get_by_index(flags, i)) + { + n_flags_set += 1; + } + } + return n_flags_set; +} diff --git a/components/libraries/util/sdk_mapped_flags.h b/components/libraries/util/sdk_mapped_flags.h new file mode 100644 index 0000000..e15f846 --- /dev/null +++ b/components/libraries/util/sdk_mapped_flags.h @@ -0,0 +1,199 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef SDK_MAPPED_FLAGS_H__ +#define SDK_MAPPED_FLAGS_H__ + +#include +#include +#include "app_util.h" +#include "compiler_abstraction.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * @defgroup sdk_mapped_flags Mapped flags + * @ingroup app_common + * @{ + * @brief Module for writing and reading flags that are associated + * with keys. + * + * @details The flags are represented as bits in a bitmap called a flag collection. The keys + * are uint16_t. Each flag collection contains all flags of the same type, one flag for + * each key. + * + * The mapped flags module does not keep the flag states, nor the list of keys. These are + * provided in the API calls. A key's index in the key list determines which bit in the + * flag collection is associated with it. This module does not ever edit the key list, and + * does not edit flags except in function calls that take the flag collection as a pointer. + * + */ + +#define SDK_MAPPED_FLAGS_N_KEYS 32 /**< The number of keys to keep flags for. This is also the number of flags in a flag collection. If changing this value, you might also need change the width of the sdk_mapped_flags_t type. */ +#define SDK_MAPPED_FLAGS_N_KEYS_PER_BYTE 8 /**< The number of flags that fit in one byte. */ +#define SDK_MAPPED_FLAGS_INVALID_INDEX 0xFFFF /**< A flag index guaranteed to be invalid. */ + +typedef uint32_t sdk_mapped_flags_t; /**< The bitmap to hold flags. Each flag is one bit, and each bit represents the flag state associated with one key. */ + + +/**@brief Type used to present a subset of the registered keys. + */ +typedef struct +{ + uint32_t len; /**< The length of the list. */ + uint16_t flag_keys[SDK_MAPPED_FLAGS_N_KEYS]; /**< The list of keys. */ +} sdk_mapped_flags_key_list_t; + + +/**@brief Function for getting the first index at which the flag is true in the provided + * collection. + * + * @param[in] flags The flag collection to search for a flag set to true. + * + * @return The first index that has its flag set to true. If none were found, the + * function returns @ref SDK_MAPPED_FLAGS_INVALID_INDEX. + */ +uint16_t sdk_mapped_flags_first_key_index_get(sdk_mapped_flags_t flags); + + +/**@brief Function for updating the state of a flag. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[out] p_flags The flag collection to modify. + * @param[in] key The key to modify the flag of. + * @param[in] value The state to set the flag to. + */ +void sdk_mapped_flags_update_by_key(uint16_t * p_keys, + sdk_mapped_flags_t * p_flags, + uint16_t key, + bool value); + + +/**@brief Function for updating the state of the same flag in multiple flag collections. + * + * @details The key and value are the same for all flag collections in the p_flags array. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[out] p_flags The flag collections to modify. + * @param[out] n_flag_collections The number of flag collections in p_flags. + * @param[in] key The key to modify the flag of. + * @param[in] value The state to set the flag to. + */ +void sdk_mapped_flags_bulk_update_by_key(uint16_t * p_keys, + sdk_mapped_flags_t * p_flags, + uint32_t n_flag_collections, + uint16_t key, + bool value); + + +/**@brief Function for getting the state of a specific flag. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[in] flags The flag collection to read from. + * @param[in] key The key to get the flag for. + * + * @return The state of the flag. + */ +bool sdk_mapped_flags_get_by_key(uint16_t * p_keys, sdk_mapped_flags_t flags, uint16_t key); + + +/**@brief Function for getting the state of a specific flag. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[in] flags The flag collection from which to read. + * @param[in] key The key for which to get the flag. + * @param[out] p_index If not NULL, the index of the key. + * + * @return The state of the flag. + */ +bool sdk_mapped_flags_get_by_key_w_idx(uint16_t * p_keys, + sdk_mapped_flags_t flags, + uint16_t key, + uint8_t * p_index); + + +/**@brief Function for getting a list of all keys that have a specific flag set to true. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[in] flags The flag collection to search. + * + * @return The list of keys. + */ +sdk_mapped_flags_key_list_t sdk_mapped_flags_key_list_get(uint16_t * p_keys, + sdk_mapped_flags_t flags); + + +/**@brief Function for getting the number of keys that have a specific flag set to true. + * + * @param[in] flags The flag collection to search. + * + * @return The number of keys. + */ +uint32_t sdk_mapped_flags_n_flags_set(sdk_mapped_flags_t flags); + + +/**@brief Function for querying whether any flags in the collection are set. + * + * @param[in] flags The flag collection to query. + * + * @retval true If one or more flags are set to true. + * @retval false Otherwise. + */ +static __INLINE bool sdk_mapped_flags_any_set(sdk_mapped_flags_t flags) +{ + return (flags != 0); +} + + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif /* SDK_MAPPED_FLAGS_H__ */ diff --git a/components/libraries/util/sdk_os.h b/components/libraries/util/sdk_os.h new file mode 100644 index 0000000..62e9d1e --- /dev/null +++ b/components/libraries/util/sdk_os.h @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2013 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @cond */ +/**@file + * + * @defgroup sdk_os SDK OS Abstraction + * @ingroup experimental_api + * @details In order to made SDK modules independent of use of an embedded OS, and permit + * application with varied task architecture, SDK abstracts the OS specific + * elements here in order to make all other modules agnostic to the OS or task + * architecture. + * @{ + */ + +#ifndef SDK_OS_H__ +#define SDK_OS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SDK_MUTEX_DEFINE(X) +#define SDK_MUTEX_INIT(X) +#define SDK_MUTEX_LOCK(X) +#define SDK_MUTEX_UNLOCK(X) + +/** + * @defgroup os_data_type Data types. + */ + +/** @} */ +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_OS_H__ + diff --git a/components/libraries/util/sdk_resources.h b/components/libraries/util/sdk_resources.h new file mode 100644 index 0000000..fa9b035 --- /dev/null +++ b/components/libraries/util/sdk_resources.h @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * @brief Definition file for resource usage by SoftDevice, ESB and Gazell. + */ + +#ifndef SDK_RESOURCES_H__ +#define SDK_RESOURCES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(SOFTDEVICE_PRESENT) || defined (BLE_STACK_SUPPORT_REQD) || defined (ANT_STACK_SUPPORT_REQD) + #include "nrf_sd_def.h" +#else + #define SD_PPI_RESTRICTED 0uL /**< 1 if PPI peripheral is restricted, 0 otherwise. */ + #define SD_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by SotfDevice (not available to th spplication). */ + #define SD_PPI_GROUPS_USED 0uL /**< PPI groups utilized by SotfDevice (not available to th spplication). */ + #define SD_TIMERS_USED 0uL /**< Timers used by SoftDevice. */ + #define SD_SWI_USED 0uL /**< Software interrupts used by SoftDevice. */ +#endif + +#ifdef GAZELL_PRESENT + #include "nrf_gzll_resources.h" +#else + #define GZLL_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by Gazell (not available to th spplication). */ + #define GZLL_TIMERS_USED 0uL /**< Timers used by Gazell. */ + #define GZLL_SWI_USED 0uL /**< Software interrupts used by Gazell */ +#endif + +#ifdef ESB_PRESENT + #include "nrf_esb_resources.h" +#else + #define ESB_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by ESB (not available to th spplication). */ + #define ESB_TIMERS_USED 0uL /**< Timers used by ESB. */ + #define ESB_SWI_USED 0uL /**< Software interrupts used by ESB */ +#endif + +#define NRF_PPI_CHANNELS_USED (SD_PPI_CHANNELS_USED | GZLL_PPI_CHANNELS_USED | ESB_PPI_CHANNELS_USED) +#define NRF_PPI_GROUPS_USED (SD_PPI_GROUPS_USED) +#define NRF_SWI_USED (SD_SWI_USED | GZLL_SWI_USED | ESB_SWI_USED) +#define NRF_TIMERS_USED (SD_TIMERS_USED | GZLL_TIMERS_USED | ESB_TIMERS_USED) + +#ifdef __cplusplus +} +#endif + +#endif // SDK_RESOURCES_H__ diff --git a/components/sdk_validation.h b/components/sdk_validation.h new file mode 100644 index 0000000..20f934d --- /dev/null +++ b/components/sdk_validation.h @@ -0,0 +1,305 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef SDK_VALIDATION_H +#define SDK_VALIDATION_H + +#include "nrf_peripherals.h" +#include "sdk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Validate peripheral availibility + +#if ((defined(SAADC_ENABLED)) && (SAADC_ENABLED > 0) && (!defined(SAADC_PRESENT))) +#error "SAADC not present in selected MCU." +#endif + +#if ((defined(ADC_ENABLED)) && (ADC_ENABLED > 0) && (!defined(ADC_PRESENT))) +#error "SAADC not present in selected MCU." +#endif + +#if ((defined(I2S_ENABLED)) && (I2S_ENABLED > 0) && (!defined(I2S_PRESENT))) +#error "I2S not present in selected MCU." +#endif + +#if ((defined(COMP_ENABLED)) && (COMP_ENABLED > 0) && (!defined(COMP_PRESENT))) +#error "COMP not present in selected MCU." +#endif + +#if ((defined(LPCOMP_ENABLED)) && (LPCOMP_ENABLED > 0) && (!defined(LPCOMP_PRESENT))) +#error "LPCOMP not present in selected MCU." +#endif + +#if ((defined(SPIS0_ENABLED)) && (SPIS0_ENABLED > 0) && (!defined(SPIS_PRESENT))) +#error "SPIS0 instance not present in selected MCU." +#endif + +#if ((defined(EGU_ENABLED)) && (EGU_ENABLED > 0) && (!defined(EGU_PRESENT))) +#error "EGU instance not present in selected MCU." +#endif + +#if ((defined(NFC_HAL_ENABLED)) && (NFC_HAL_ENABLED > 0) && (!defined(NFCT_PRESENT))) +#error "NFC TAG not present in selected MCU." +#endif + +// Validate count of instances + +#if ((defined(RTC2_ENABLED)) && (RTC2_ENABLED > 0) && (RTC_COUNT < 2)) +#error "RTC2 not present in selected MCU." +#endif + +#if ((defined(TWIS0_ENABLED) || defined(TWIS1_ENABLED)) &&\ + ((TWIS0_ENABLED + TWIS1_ENABLED) > 0) &&\ + (!defined(TWIS_PRESENT))) +#error "TWIS not present in selected MCU." +#endif + +#if ((defined(SPIS2_ENABLED)) && (SPIS2_ENABLED > 0) && (SPIS_COUNT < 2)) +#error "SPI2/SPIS2 instance not present in selected MCU." +#endif + +#if ((defined(TIMER3_ENABLED) || defined(TIMER4_ENABLED)) &&\ + ((TIMER3_ENABLED + TIMER4_ENABLED ) > 0) &&\ + (TIMER_COUNT < 5)) +#error "TIMER3 and TIMER4 not present in selected MCU." +#endif + +// Validate peripheral sharing feature +#if !NRFX_CHECK(NRFX_PRS_ENABLED) + +#if ((defined(TWIM0_ENABLED) && defined(TWIS0_ENABLED)) &&\ + ((TWIM0_ENABLED + TWIS0_ENABLED) > 1)) +#error "Peripherals overlap. TWIM0, TWIS0 - only one of these can be enabled." +#endif + +#if ((defined(TWIM0_ENABLED) && defined(SPIM0_ENABLED)) &&\ + ((TWIM0_ENABLED + SPIM0_ENABLED) > 1)) +#error "Peripherals overlap. TWIM0, SPIM0 - only one of these can be enabled." +#endif + +#if ((defined(TWIM0_ENABLED) && defined(SPIS0_ENABLED)) &&\ + ((TWIM0_ENABLED + SPIS0_ENABLED) > 1)) +#error "Peripherals overlap. TWIM0, SPIS0 - only one of these can be enabled." +#endif + +#if ((defined(TWIM0_ENABLED) && defined(SPI0_ENABLED)) &&\ + ((TWIM0_ENABLED + SPI0_ENABLED) > 1)) +#error "Peripherals overlap. TWIM0, SPI0 - only one of these can be enabled." +#endif + +#if ((defined(TWIM0_ENABLED) && defined(TWI0_ENABLED)) &&\ + ((TWIM0_ENABLED + TWI0_ENABLED) > 1)) +#error "Peripherals overlap. TWIM0, TWI0 - only one of these can be enabled." +#endif + +#if ((defined(TWIS0_ENABLED) && defined(SPIM0_ENABLED)) &&\ + ((TWIS0_ENABLED + SPIM0_ENABLED) > 1)) +#error "Peripherals overlap. TWIS0, SPIM0 - only one of these can be enabled." +#endif + +#if ((defined(TWIS0_ENABLED) && defined(SPIS0_ENABLED)) &&\ + ((TWIS0_ENABLED + SPIS0_ENABLED) > 1)) +#error "Peripherals overlap. TWIS0, SPIS0 - only one of these can be enabled." +#endif + +#if ((defined(TWIS0_ENABLED) && defined(SPI0_ENABLED)) &&\ + ((TWIS0_ENABLED + SPI0_ENABLED) > 1)) +#error "Peripherals overlap. TWIS0, SPI0 - only one of these can be enabled." +#endif + +#if ((defined(TWIS0_ENABLED) && defined(TWI0_ENABLED)) &&\ + ((TWIS0_ENABLED + TWI0_ENABLED) > 1)) +#error "Peripherals overlap. TWIS0, TWI0 - only one of these can be enabled." +#endif + +#if ((defined(SPIM0_ENABLED) && defined(SPIS0_ENABLED)) &&\ + ((SPIM0_ENABLED + SPIS0_ENABLED) > 1)) +#error "Peripherals overlap. SPIM0, SPIS0 - only one of these can be enabled." +#endif + +#if ((defined(SPIM0_ENABLED) && defined(SPI0_ENABLED)) &&\ + ((SPIM0_ENABLED + SPI0_ENABLED) > 1)) +#error "Peripherals overlap. SPIM0, SPI0 - only one of these can be enabled." +#endif + +#if ((defined(SPIM0_ENABLED) && defined(TWI0_ENABLED)) &&\ + ((SPIM0_ENABLED + TWI0_ENABLED) > 1)) +#error "Peripherals overlap. SPIM0, TWI0 - only one of these can be enabled." +#endif + +#if ((defined(SPIS0_ENABLED) && defined(SPI0_ENABLED)) &&\ + ((SPIS0_ENABLED + SPI0_ENABLED) > 1)) +#error "Peripherals overlap. SPIS0, SPI0 - only one of these can be enabled." +#endif + +#if ((defined(SPIS0_ENABLED) && defined(TWI0_ENABLED)) &&\ + ((SPIS0_ENABLED + TWI0_ENABLED) > 1)) +#error "Peripherals overlap. SPIS0, TWI0 - only one of these can be enabled." +#endif + +#if ((defined(SPI0_ENABLED) && defined(TWI0_ENABLED)) &&\ + ((SPI0_ENABLED + TWI0_ENABLED) > 1)) +#error "Peripherals overlap. SPI0, TWI0 - only one of these can be enabled." +#endif + +#if ((defined(TWIM1_ENABLED) && defined(TWIS1_ENABLED)) &&\ + ((TWIM1_ENABLED + TWIS1_ENABLED) > 1)) +#error "Peripherals overlap. TWIM1, TWIS1 - only one of these can be enabled." +#endif + +#if ((defined(TWIM1_ENABLED) && defined(SPIM1_ENABLED)) &&\ + ((TWIM1_ENABLED + SPIM1_ENABLED) > 1)) +#error "Peripherals overlap. TWIM1, SPIM1 - only one of these can be enabled." +#endif + +#if ((defined(TWIM1_ENABLED) && defined(SPIS1_ENABLED)) &&\ + ((TWIM1_ENABLED + SPIS1_ENABLED) > 1)) +#error "Peripherals overlap. TWIM1, SPIS1 - only one of these can be enabled." +#endif + +#if ((defined(TWIM1_ENABLED) && defined(SPI1_ENABLED)) &&\ + ((TWIM1_ENABLED + SPI1_ENABLED) > 1)) +#error "Peripherals overlap. TWIM1, SPI1 - only one of these can be enabled." +#endif + +#if ((defined(TWIM1_ENABLED) && defined(TWI1_ENABLED)) &&\ + ((TWIM1_ENABLED + TWI1_ENABLED) > 1)) +#error "Peripherals overlap. TWIM1, TWI1 - only one of these can be enabled." +#endif + +#if ((defined(TWIS1_ENABLED) && defined(SPIM1_ENABLED)) &&\ + ((TWIS1_ENABLED + SPIM1_ENABLED) > 1)) +#error "Peripherals overlap. TWIS1, SPIM1 - only one of these can be enabled." +#endif + +#if ((defined(TWIS1_ENABLED) && defined(SPIS1_ENABLED)) &&\ + ((TWIS1_ENABLED + SPIS1_ENABLED) > 1)) +#error "Peripherals overlap. TWIS1, SPIS1 - only one of these can be enabled." +#endif + +#if ((defined(TWIS1_ENABLED) && defined(SPI1_ENABLED)) &&\ + ((TWIS1_ENABLED + SPI1_ENABLED) > 1)) +#error "Peripherals overlap. TWIS1, SPI1 - only one of these can be enabled." +#endif + +#if ((defined(TWIS1_ENABLED) && defined(TWI1_ENABLED)) &&\ + ((TWIS1_ENABLED + TWI1_ENABLED) > 1)) +#error "Peripherals overlap. TWIS1, TWI1 - only one of these can be enabled." +#endif + +#if ((defined(SPIM1_ENABLED) && defined(SPIS1_ENABLED)) &&\ + ((SPIM1_ENABLED + SPIS1_ENABLED) > 1)) +#error "Peripherals overlap. SPIM1, SPIS1 - only one of these can be enabled." +#endif + +#if ((defined(SPIM1_ENABLED) && defined(SPI1_ENABLED)) &&\ + ((SPIM1_ENABLED + SPI1_ENABLED) > 1)) +#error "Peripherals overlap. SPIM1, SPI1 - only one of these can be enabled." +#endif + +#if ((defined(SPIM1_ENABLED) && defined(TWI1_ENABLED)) &&\ + ((SPIM1_ENABLED + TWI1_ENABLED) > 1)) +#error "Peripherals overlap. SPIM1, TWI1 - only one of these can be enabled." +#endif + +#if ((defined(SPIS1_ENABLED) && defined(SPI1_ENABLED)) &&\ + ((SPIS1_ENABLED + SPI1_ENABLED) > 1)) +#error "Peripherals overlap. SPIS1, SPI1 - only one of these can be enabled." +#endif + +#if ((defined(SPIS1_ENABLED) && defined(TWI1_ENABLED)) &&\ + ((SPIS1_ENABLED + TWI1_ENABLED) > 1)) +#error "Peripherals overlap. SPIS1, TWI1 - only one of these can be enabled." +#endif + +#if ((defined(SPI1_ENABLED) && defined(TWI1_ENABLED)) &&\ + ((SPI1_ENABLED + TWI1_ENABLED) > 1)) +#error "Peripherals overlap. SPI1, TWI1 - only one of these can be enabled." +#endif + +#if ((defined(SPI2_ENABLED) && defined(SPIS2_ENABLED)) &&\ + ((SPI2_ENABLED + SPIS2_ENABLED) > 1)) +#error "Peripherals overlap. SPI2, SPIS2 - only one of these can be enabled." +#endif + +#if ((defined(SPIM2_ENABLED) && defined(SPIS2_ENABLED)) &&\ + ((SPI2_ENABLED + SPIS2_ENABLED) > 1)) +#error "Peripherals overlap. SPIM2, SPIS2 - only one of these can be enabled." +#endif + +#if ((defined(SPIM2_ENABLED) && defined(SPI2_ENABLED)) &&\ + ((SPI2_ENABLED + SPIS2_ENABLED) > 1)) +#error "Peripherals overlap. SPIM2, SPI2 - only one of these can be enabled." +#endif + +#endif // !NRFX_CHECK(NRFX_PRS_ENABLED) + +#ifdef NFCT_PRESENT + +#if ((defined(NFC_HAL_ENABLED) && defined(NRF_CLOCK_ENABLED)) &&\ + ((NFC_HAL_ENABLED) && (!NRF_CLOCK_ENABLED))) +#error "NFC_HAL requires CLOCK to work. NFC_HAL can not be enabled without CLOCK." +#endif + +#if ((defined(NFC_HAL_ENABLED) && defined(TIMER4_ENABLED)) &&\ + ((NFC_HAL_ENABLED + TIMER4_ENABLED) > 1)) +#error "TIMER4 is used by NFC_HAL. NFC_HAL, TIMER4 - only one of these can be enabled." +#endif + +#endif +// Complex driver validation +#ifdef LPCOMP_PRESENT + +#if ((defined(COMP_ENABLED) && defined(LPCOMP_ENABLED)) && \ + (!NRFX_CHECK(NRFX_PRS_ENABLED)) && \ + ((COMP_ENABLED + LPCOMP_ENABLED) > 1)) +#error "Peripherals overlap. COMP, LPCOMP - only one of these can be enabled." +#endif + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // SDK_VALIDATION_H diff --git a/components/softdevice/common/nrf_sdh.c b/components/softdevice/common/nrf_sdh.c new file mode 100644 index 0000000..7a10108 --- /dev/null +++ b/components/softdevice/common/nrf_sdh.c @@ -0,0 +1,402 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_SDH) + +#include "nrf_sdh.h" + +#include + +#include "nrf_sdm.h" +#include "nrf_nvic.h" +#include "sdk_config.h" +#include "app_error.h" +#include "app_util_platform.h" + + +#define NRF_LOG_MODULE_NAME nrf_sdh +#if NRF_SDH_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_SDH_LOG_LEVEL + #define NRF_LOG_INFO_COLOR NRF_SDH_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_SDH_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_SDH_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +// Validate configuration options. + +#if (NRF_SDH_DISPATCH_MODEL == NRF_SDH_DISPATCH_MODEL_APPSH) + #if (!APP_SCHEDULER_ENABLED) + #error app_scheduler is required when NRF_SDH_DISPATCH_MODEL is set to NRF_SDH_DISPATCH_MODEL_APPSH + #endif + #include "app_scheduler.h" +#endif + +#if ( (NRF_SDH_CLOCK_LF_SRC == NRF_CLOCK_LF_SRC_RC) \ + && (NRF_SDH_CLOCK_LF_ACCURACY != NRF_CLOCK_LF_ACCURACY_500_PPM)) + #warning Please select NRF_CLOCK_LF_ACCURACY_500_PPM when using NRF_CLOCK_LF_SRC_RC +#endif + + +// Create section "sdh_req_observers". +NRF_SECTION_SET_DEF(sdh_req_observers, nrf_sdh_req_observer_t, NRF_SDH_REQ_OBSERVER_PRIO_LEVELS); + +// Create section "sdh_state_observers". +NRF_SECTION_SET_DEF(sdh_state_observers, nrf_sdh_state_observer_t, NRF_SDH_STATE_OBSERVER_PRIO_LEVELS); + +// Create section "sdh_stack_observers". +NRF_SECTION_SET_DEF(sdh_stack_observers, nrf_sdh_stack_observer_t, NRF_SDH_STACK_OBSERVER_PRIO_LEVELS); + + +static bool m_nrf_sdh_enabled; /**< Variable to indicate whether the SoftDevice is enabled. */ +static bool m_nrf_sdh_suspended; /**< Variable to indicate whether this module is suspended. */ +static bool m_nrf_sdh_continue; /**< Variable to indicate whether enable/disable process was started. */ + + +/**@brief Function for notifying request observers. + * + * @param[in] evt Type of request event. + */ +static ret_code_t sdh_request_observer_notify(nrf_sdh_req_evt_t req) +{ + nrf_section_iter_t iter; + + NRF_LOG_DEBUG("State request: 0x%08X", req); + + for (nrf_section_iter_init(&iter, &sdh_req_observers); + nrf_section_iter_get(&iter) != NULL; + nrf_section_iter_next(&iter)) + { + nrf_sdh_req_observer_t * p_observer; + nrf_sdh_req_evt_handler_t handler; + + p_observer = (nrf_sdh_req_observer_t *) nrf_section_iter_get(&iter); + handler = p_observer->handler; + + if (handler(req, p_observer->p_context)) + { + NRF_LOG_DEBUG("Notify observer 0x%08X => ready", p_observer); + } + else + { + // Process is stopped. + NRF_LOG_DEBUG("Notify observer 0x%08X => blocking", p_observer); + return NRF_ERROR_BUSY; + } + } + return NRF_SUCCESS; +} + + +/**@brief Function for stage request observers. + * + * @param[in] evt Type of stage event. + */ +static void sdh_state_observer_notify(nrf_sdh_state_evt_t evt) +{ + nrf_section_iter_t iter; + + NRF_LOG_DEBUG("State change: 0x%08X", evt); + + for (nrf_section_iter_init(&iter, &sdh_state_observers); + nrf_section_iter_get(&iter) != NULL; + nrf_section_iter_next(&iter)) + { + nrf_sdh_state_observer_t * p_observer; + nrf_sdh_state_evt_handler_t handler; + + p_observer = (nrf_sdh_state_observer_t *) nrf_section_iter_get(&iter); + handler = p_observer->handler; + + handler(evt, p_observer->p_context); + } +} + + +static void softdevices_evt_irq_enable(void) +{ +#ifdef SOFTDEVICE_PRESENT + ret_code_t ret_code = sd_nvic_EnableIRQ((IRQn_Type)SD_EVT_IRQn); + APP_ERROR_CHECK(ret_code); +#else + // In case of serialization, NVIC must be accessed directly. + NVIC_EnableIRQ(SD_EVT_IRQn); +#endif +} + + +static void softdevice_evt_irq_disable(void) +{ +#ifdef SOFTDEVICE_PRESENT + ret_code_t ret_code = sd_nvic_DisableIRQ((IRQn_Type)SD_EVT_IRQn); + APP_ERROR_CHECK(ret_code); +#else + // In case of serialization, NVIC must be accessed directly. + NVIC_DisableIRQ(SD_EVT_IRQn); +#endif +} + + +ret_code_t nrf_sdh_enable_request(void) +{ + ret_code_t ret_code; + + if (m_nrf_sdh_enabled) + { + return NRF_ERROR_INVALID_STATE; + } + + m_nrf_sdh_continue = true; + + // Notify observers about SoftDevice enable request. + if (sdh_request_observer_notify(NRF_SDH_EVT_ENABLE_REQUEST) == NRF_ERROR_BUSY) + { + // Enable process was stopped. + return NRF_SUCCESS; + } + + // Notify observers about starting SoftDevice enable process. + sdh_state_observer_notify(NRF_SDH_EVT_STATE_ENABLE_PREPARE); + + nrf_clock_lf_cfg_t const clock_lf_cfg = + { + .source = NRF_SDH_CLOCK_LF_SRC, + .rc_ctiv = NRF_SDH_CLOCK_LF_RC_CTIV, + .rc_temp_ctiv = NRF_SDH_CLOCK_LF_RC_TEMP_CTIV, + .accuracy = NRF_SDH_CLOCK_LF_ACCURACY + }; + + CRITICAL_REGION_ENTER(); +#ifdef ANT_LICENSE_KEY + ret_code = sd_softdevice_enable(&clock_lf_cfg, app_error_fault_handler, ANT_LICENSE_KEY); +#else + ret_code = sd_softdevice_enable(&clock_lf_cfg, app_error_fault_handler); +#endif + m_nrf_sdh_enabled = (ret_code == NRF_SUCCESS); + CRITICAL_REGION_EXIT(); + + if (ret_code != NRF_SUCCESS) + { + return ret_code; + } + + m_nrf_sdh_continue = false; + m_nrf_sdh_suspended = false; + + // Enable event interrupt. + // Interrupt priority has already been set by the stack. + softdevices_evt_irq_enable(); + + // Notify observers about a finished SoftDevice enable process. + sdh_state_observer_notify(NRF_SDH_EVT_STATE_ENABLED); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_sdh_disable_request(void) +{ + ret_code_t ret_code; + + if (!m_nrf_sdh_enabled) + { + return NRF_ERROR_INVALID_STATE; + } + + m_nrf_sdh_continue = true; + + // Notify observers about SoftDevice disable request. + if (sdh_request_observer_notify(NRF_SDH_EVT_DISABLE_REQUEST) == NRF_ERROR_BUSY) + { + // Disable process was stopped. + return NRF_SUCCESS; + } + + // Notify observers about starting SoftDevice disable process. + sdh_state_observer_notify(NRF_SDH_EVT_STATE_DISABLE_PREPARE); + + CRITICAL_REGION_ENTER(); + ret_code = sd_softdevice_disable(); + m_nrf_sdh_enabled = false; + CRITICAL_REGION_EXIT(); + + if (ret_code != NRF_SUCCESS) + { + return ret_code; + } + + m_nrf_sdh_continue = false; + + softdevice_evt_irq_disable(); + + // Notify observers about a finished SoftDevice enable process. + sdh_state_observer_notify(NRF_SDH_EVT_STATE_DISABLED); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_sdh_request_continue(void) +{ + if (!m_nrf_sdh_continue) + { + return NRF_ERROR_INVALID_STATE; + } + + if (m_nrf_sdh_enabled) + { + return nrf_sdh_disable_request(); + } + else + { + return nrf_sdh_enable_request(); + } +} + + +bool nrf_sdh_is_enabled(void) +{ + return m_nrf_sdh_enabled; +} + + +void nrf_sdh_suspend(void) +{ + if (!m_nrf_sdh_enabled) + { + return; + } + + softdevice_evt_irq_disable(); + m_nrf_sdh_suspended = true; +} + + +void nrf_sdh_resume(void) +{ + if ((!m_nrf_sdh_suspended) || (!m_nrf_sdh_enabled)) + { + return; + } + + // Force calling ISR again to make sure that events not previously pulled have been processed. +#ifdef SOFTDEVICE_PRESENT + ret_code_t ret_code = sd_nvic_SetPendingIRQ((IRQn_Type)SD_EVT_IRQn); + APP_ERROR_CHECK(ret_code); +#else + NVIC_SetPendingIRQ((IRQn_Type)SD_EVT_IRQn); +#endif + + softdevices_evt_irq_enable(); + + m_nrf_sdh_suspended = false; +} + + +bool nrf_sdh_is_suspended(void) +{ + return (!m_nrf_sdh_enabled) || (m_nrf_sdh_suspended); +} + + +void nrf_sdh_evts_poll(void) +{ + nrf_section_iter_t iter; + + // Notify observers about pending SoftDevice event. + for (nrf_section_iter_init(&iter, &sdh_stack_observers); + nrf_section_iter_get(&iter) != NULL; + nrf_section_iter_next(&iter)) + { + nrf_sdh_stack_observer_t * p_observer; + nrf_sdh_stack_evt_handler_t handler; + + p_observer = (nrf_sdh_stack_observer_t *) nrf_section_iter_get(&iter); + handler = p_observer->handler; + + handler(p_observer->p_context); + } +} + + +#if (NRF_SDH_DISPATCH_MODEL == NRF_SDH_DISPATCH_MODEL_INTERRUPT) + +void SD_EVT_IRQHandler(void) +{ + nrf_sdh_evts_poll(); +} + +#elif (NRF_SDH_DISPATCH_MODEL == NRF_SDH_DISPATCH_MODEL_APPSH) + +/**@brief Function for polling SoftDevice events. + * + * @note This function is compatible with @ref app_sched_event_handler_t. + * + * @param[in] p_event_data Pointer to the event data. + * @param[in] event_size Size of the event data. + */ +static void appsh_events_poll(void * p_event_data, uint16_t event_size) +{ + UNUSED_PARAMETER(p_event_data); + UNUSED_PARAMETER(event_size); + + nrf_sdh_evts_poll(); +} + + +void SD_EVT_IRQHandler(void) +{ + ret_code_t ret_code = app_sched_event_put(NULL, 0, appsh_events_poll); + APP_ERROR_CHECK(ret_code); +} + +#elif (NRF_SDH_DISPATCH_MODEL == NRF_SDH_DISPATCH_MODEL_POLLING) + +#else + +#error "Unknown SoftDevice handler dispatch model." + +#endif // NRF_SDH_DISPATCH_MODEL + +#endif // NRF_MODULE_ENABLED(NRF_SDH) diff --git a/components/softdevice/common/nrf_sdh.h b/components/softdevice/common/nrf_sdh.h new file mode 100644 index 0000000..8add9c8 --- /dev/null +++ b/components/softdevice/common/nrf_sdh.h @@ -0,0 +1,305 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** @file + * + * @defgroup nrf_sdh SoftDevice Handler + * @{ + * @ingroup app_common + * @brief API for initializing and disabling the SoftDevice. + */ + +#ifndef NRF_SDH_H__ +#define NRF_SDH_H__ + +#include +#include "sdk_config.h" +#include "sdk_errors.h" +#include "nrf_section_iter.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Softdevice Handler dispatch models + * @{ + * @ingroup nrf_sdh */ + +/**@brief SoftDevice events are passed to the application from the interrupt context. */ +#define NRF_SDH_DISPATCH_MODEL_INTERRUPT 0 + +/**@brief SoftDevice events are passed to the application using @ref app_scheduler. + * + * @note @ref app_scheduler must be initialized before enabling the SoftDevice handler. + */ +#define NRF_SDH_DISPATCH_MODEL_APPSH 1 + +/**@brief SoftDevice events are polled manually using @ref nrf_sdh_evts_poll(). + * + * @note In this mode, a user application can also implement SD_EVT_IRQHandler() to receive a + * notification about incoming events. + */ +#define NRF_SDH_DISPATCH_MODEL_POLLING 2 + +/** @} */ + +/** + * @name SoftDevice Handler state change requests + * @{ + * @ingroup nrf_sdh */ + +/**@brief SoftDevice Handler state requests. */ +typedef enum +{ + NRF_SDH_EVT_ENABLE_REQUEST, //!< Request to enable the SoftDevice. + NRF_SDH_EVT_DISABLE_REQUEST, //!< Request to disable the SoftDevice. +} nrf_sdh_req_evt_t; + +/**@brief SoftDevice Handler state request handler. + * + * @retval true If ready for the SoftDevice to change state. + * @retval false If not ready for the SoftDevice to change state. + * If false is returned, the state change is aborted. + */ +typedef bool (*nrf_sdh_req_evt_handler_t)(nrf_sdh_req_evt_t request, void * p_context); + +/**@brief SoftDevice Handler state request observer. */ +typedef struct +{ + nrf_sdh_req_evt_handler_t handler; //!< Request handler. + void * p_context; //!< A parameter to the handler function. +} const nrf_sdh_req_observer_t; + +/**@brief Macro for registering a SoftDevice state change request observer. + * + * An observer of SoftDevice state change requests receives requests to change the state of the + * SoftDevice from enabled to disabled and vice versa. These requests may or may not be acknowledged + * by the observer, depending on the value returned by its request handler function. Thus, a + * request observer has the capability to defer the change of state of the SoftDevice. If it does + * so, it has the responsibility to call @ref nrf_sdh_request_continue when it is ready to let the + * SoftDevice change its state. If such capability is not necessary and you only need to be informed + * about changes of the SoftDevice state, use the @ref NRF_SDH_STATE_OBSERVER macro instead. + * + * @note This macro places the observer in a section named "sdh_req_observers". + * + * @param[in] _observer Name of the observer. + * @param[in] _prio Priority of the observer's event handler. + * The smaller the number, the higher the priority. + * @hideinitializer + */ +#define NRF_SDH_REQUEST_OBSERVER(_observer, _prio) \ +STATIC_ASSERT(NRF_SDH_ENABLED, "NRF_SDH_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_REQ_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +/*lint -esym(528,*_observer) -esym(529,*_observer) : Symbol not referenced. */ \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_req_observers, _prio, nrf_sdh_req_observer_t const _observer) + +/** @} */ + +/** + * @name SoftDevice Handler state events + * @{ + * @ingroup nrf_sdh */ + +/**@brief SoftDevice Handler state events. */ +typedef enum +{ + NRF_SDH_EVT_STATE_ENABLE_PREPARE, //!< SoftDevice is going to be enabled. + NRF_SDH_EVT_STATE_ENABLED, //!< SoftDevice is enabled. + NRF_SDH_EVT_STATE_DISABLE_PREPARE, //!< SoftDevice is going to be disabled. + NRF_SDH_EVT_STATE_DISABLED, //!< SoftDevice is disabled. +} nrf_sdh_state_evt_t; + +/**@brief SoftDevice Handler state event handler. */ +typedef void (*nrf_sdh_state_evt_handler_t)(nrf_sdh_state_evt_t state, void * p_context); + +/**@brief SoftDevice Handler state observer. */ +typedef struct +{ + nrf_sdh_state_evt_handler_t handler; //!< State event handler. + void * p_context; //!< A parameter to the event handler. +} const nrf_sdh_state_observer_t; + +/**@brief Macro for registering a SoftDevice state observer. + * + * A SoftDevice state observer receives events when the SoftDevice state has changed or is + * about to change. These events are only meant to inform the state observer, which, contrary + * to a state change request observer, does not have the capability to defer the change of state. + * If such capability is required, use the @ref NRF_SDH_REQUEST_OBSERVER macro instead. + * + * This macro places the observer in a section named "sdh_state_observers". + * + * @param[in] _observer Name of the observer. + * @param[in] _prio Priority of the observer's event handler. + * The smaller the number, the higher the priority. + * @hideinitializer + */ +#define NRF_SDH_STATE_OBSERVER(_observer, _prio) \ +STATIC_ASSERT(NRF_SDH_ENABLED, "NRF_SDH_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_STATE_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +/*lint -esym(528,*_observer) -esym(529,*_observer) : Symbol not referenced. */ \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_state_observers, _prio, static nrf_sdh_state_observer_t const _observer) + +/** @} */ + +/** + * @name SoftDevice stack events + * @{ + * @ingroup nrf_sdh */ + +/**@brief SoftDevice stack event handler. */ +typedef void (*nrf_sdh_stack_evt_handler_t)(void * p_evt); + +/**@brief SoftDevice stack event observer. */ +typedef struct +{ + nrf_sdh_stack_evt_handler_t handler; //!< SoftDevice event handler. + void * p_context; //!< A parameter to the event handler. +} const nrf_sdh_stack_observer_t; + +/**@brief Macro for registering a SoftDevice stack events observer. + * + * A SoftDevice stack event observer receives all events from the SoftDevice. These events can be + * either BLE, ANT, or SoC events. If you need to receive BLE, ANT, or SoC events separately, use the + * @ref NRF_SDH_BLE_OBSERVER, @ref NRF_SDH_ANT_OBSERVER, or @ref NRF_SDH_SOC_OBSERVER macros + * respectively. + * + * @note This macro places the observer in a section named "sdh_stack_observers". + * + * @param[in] _observer Name of the observer. + * @param[in] _prio Priority of the observer's event handler. + * The smaller the number, the higher the priority. + ** @hideinitializer + */ +#define NRF_SDH_STACK_OBSERVER(_observer, _prio) \ +STATIC_ASSERT(NRF_SDH_ENABLED, "NRF_SDH_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_STACK_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +/*lint -esym(528,*_observer) -esym(529,*_observer) : Symbol not referenced. */ \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_stack_observers, _prio, static nrf_sdh_stack_observer_t const _observer) + +/** @} */ + +/**@brief Function for requesting to enable the SoftDevice. + * + * This function issues a @ref NRF_SDH_EVT_ENABLE_REQUEST request to all observers that + * were registered using the @ref NRF_SDH_REQUEST_OBSERVER macro. The observers may or + * may not acknowledge the request. If all observers acknowledge the request, the + * SoftDevice will be enabled. Otherwise, the process will be stopped and the observers + * that did not acknowledge have the responsibility to restart it by calling + * @ref nrf_sdh_request_continue when they are ready for the SoftDevice to change state. + * + * @retval NRF_SUCCESS The process is started. + * @retval NRF_ERROR_INVALID_STATE The SoftDevice is already enabled. + */ +ret_code_t nrf_sdh_enable_request(void); + + +/**@brief Function for requesting to disable the SoftDevice. + * + * This function issues a @ref NRF_SDH_EVT_DISABLE_REQUEST request to all observers that + * were registered using the @ref NRF_SDH_REQUEST_OBSERVER macro. The observers may or + * may not acknowledge the request. If all observers acknowledge the request, the + * SoftDevice will be disabled. Otherwise, the process will be stopped and the observers + * that did not acknowledge have the responsibility to restart it by calling + * @ref nrf_sdh_request_continue when they are ready for the SoftDevice to change state. + * + * @retval NRF_SUCCESS The process is started. + * @retval NRF_ERROR_INVALID_STATE The SoftDevice is already disabled. + */ +ret_code_t nrf_sdh_disable_request(void); + + +/**@brief Function for restarting the SoftDevice Enable/Disable process. + * + * Modules which did not acknowledge a @ref NRF_SDH_EVT_ENABLE_REQUEST or + * @ref NRF_SDH_EVT_DISABLE_REQUEST request must call this function to restart the + * SoftDevice state change process. + * + * @retval NRF_SUCCESS The process is restarted. + * @retval NRF_ERROR_INVALID_STATE No state change request was pending. + */ +ret_code_t nrf_sdh_request_continue(void); + + +/**@brief Function for retrieving the SoftDevice state. + * + * @retval true If the SoftDevice is enabled. + * @retval false If the SoftDevice is disabled. + */ +bool nrf_sdh_is_enabled(void); + + +/**@brief Function for stopping the incoming stack events. + * + * This function disables the SoftDevice interrupt. To resume polling for events, + * call @ref nrf_sdh_resume. + */ +void nrf_sdh_suspend(void); + + +/**@brief Function for resuming polling incoming events from the SoftDevice. */ +void nrf_sdh_resume(void); + + +/**@brief Function for retrieving the information about the module state. + * + * @retval true The SoftDevice handler is paused, and it will not fetch events from the stack. + * @retval false The SoftDevice handler is running, and it will fetch and dispatch events from + * the stack to the registered stack observers. + */ +bool nrf_sdh_is_suspended(void); + + +/**@brief Function for polling stack events from the SoftDevice. + * + * The events are passed to the application using the registered event handlers. + * + * @note @ref NRF_SDH_DISPATCH_MODEL_POLLING must be selected to use this function. + */ +void nrf_sdh_evts_poll(void); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SDH_H__ + +/** @} */ diff --git a/components/softdevice/common/nrf_sdh_ant.c b/components/softdevice/common/nrf_sdh_ant.c new file mode 100644 index 0000000..db5644c --- /dev/null +++ b/components/softdevice/common/nrf_sdh_ant.c @@ -0,0 +1,162 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_SDH_ANT) + +#include "nrf_sdh_ant.h" + +#include "nrf_sdh.h" +#include "app_error.h" +#include "nrf_strerror.h" +#include "ant_interface.h" + + +#define NRF_LOG_MODULE_NAME nrf_sdh_ant +#if NRF_SDH_ANT_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_SDH_ANT_LOG_LEVEL + #define NRF_LOG_INFO_COLOR NRF_SDH_ANT_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_SDH_ANT_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_SDH_ANT_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +STATIC_ASSERT(NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED <= MAX_ANT_CHANNELS); +STATIC_ASSERT(NRF_SDH_ANT_ENCRYPTED_CHANNELS <= NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED); + +// Create section set "sdh_ant_observers". +NRF_SECTION_SET_DEF(sdh_ant_observers, nrf_sdh_ant_evt_observer_t, NRF_SDH_ANT_OBSERVER_PRIO_LEVELS); + +// Memory buffer provided in order to support channel configuration. +__ALIGN(4) static uint8_t m_ant_stack_buffer[NRF_SDH_ANT_BUF_SIZE]; + + +static bool m_stack_is_enabled; + + +ret_code_t nrf_sdh_ant_enable(void) +{ + ANT_ENABLE ant_enable_cfg = + { + .ucTotalNumberOfChannels = NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED, + .ucNumberOfEncryptedChannels = NRF_SDH_ANT_ENCRYPTED_CHANNELS, + .usNumberOfEvents = NRF_SDH_ANT_EVENT_QUEUE_SIZE, + .pucMemoryBlockStartLocation = m_ant_stack_buffer, + .usMemoryBlockByteSize = sizeof(m_ant_stack_buffer), + }; + + ret_code_t ret_code = sd_ant_enable(&ant_enable_cfg); + if (ret_code == NRF_SUCCESS) + { + m_stack_is_enabled = true; + } + else + { + NRF_LOG_ERROR("sd_ant_enable() returned %s.", nrf_strerror_get(ret_code)); + } + + return ret_code; +} + + +/**@brief Function for polling ANT events. + * + * @param[in] p_context Context of the observer. + */ +static void nrf_sdh_ant_evts_poll(void * p_context) +{ + UNUSED_VARIABLE(p_context); + + ret_code_t ret_code; + +#ifndef SER_CONNECTIVITY + if (!m_stack_is_enabled) + { + return; + } +#else + UNUSED_VARIABLE(m_stack_is_enabled); +#endif // SER_CONNECTIVITY + + while (true) + { + ant_evt_t ant_evt; + + ret_code = sd_ant_event_get(&ant_evt.channel, &ant_evt.event, ant_evt.message.aucMessage); + if (ret_code != NRF_SUCCESS) + { + break; + } + + NRF_LOG_DEBUG("ANT Event 0x%02X Channel 0x%02X", ant_evt.event, ant_evt.channel); + + // Forward the event to ANT observers. + nrf_section_iter_t iter; + for (nrf_section_iter_init(&iter, &sdh_ant_observers); + nrf_section_iter_get(&iter) != NULL; + nrf_section_iter_next(&iter)) + { + nrf_sdh_ant_evt_observer_t * p_observer; + nrf_sdh_ant_evt_handler_t handler; + + p_observer = (nrf_sdh_ant_evt_observer_t *) nrf_section_iter_get(&iter); + handler = p_observer->handler; + + handler(&ant_evt, p_observer->p_context); + } + } + + if (ret_code != NRF_ERROR_NOT_FOUND) + { + APP_ERROR_HANDLER(ret_code); + } +} + + +NRF_SDH_STACK_OBSERVER(m_nrf_sdh_ant_evts_poll, NRF_SDH_ANT_STACK_OBSERVER_PRIO) = +{ + .handler = nrf_sdh_ant_evts_poll, + .p_context = NULL, +}; + +#endif // NRF_MODULE_ENABLED(NRF_SDH_ANT) diff --git a/components/softdevice/common/nrf_sdh_ant.h b/components/softdevice/common/nrf_sdh_ant.h new file mode 100644 index 0000000..2cfcbc2 --- /dev/null +++ b/components/softdevice/common/nrf_sdh_ant.h @@ -0,0 +1,182 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * + * @defgroup nrf_sdh_ant ANT support in SoftDevice Handler + * @{ + * @ingroup nrf_sdh + * @brief This file contains the declarations of types and functions required for ANT stack support. + */ + +#ifndef NRF_SDH_ANT_H__ +#define NRF_SDH_ANT_H__ + +#include "ant_parameters.h" +#include "app_util.h" +#include "nrf_section_iter.h" +#include "sdk_errors.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_SDH_ANT_EVT_CHANNEL_FIELD_SIZE 1 //!< Size of the channel field in ANT stack event +#define NRF_SDH_ANT_EVT_EVENT_FIELD_SIZE 1 //!< Size of the event field in ANT stack event + +/**@brief Size of the buffer provided to the ANT SoftDevice. + * @hideinitializer + */ +#define NRF_SDH_ANT_BUF_SIZE ANT_ENABLE_GET_REQUIRED_SPACE( \ + NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED, \ + NRF_SDH_ANT_ENCRYPTED_CHANNELS, \ + NRF_SDH_ANT_BURST_QUEUE_SIZE, \ + NRF_SDH_ANT_EVENT_QUEUE_SIZE) + +/**@brief Size of the buffer provided to the ANT SoftDevice to receive ANT events. */ +#define NRF_SDH_ANT_MESSAGE_SIZE ((CEIL_DIV(MESG_BUFFER_SIZE, sizeof(uint32_t))) * sizeof(uint32_t)) + +/**@brief Size of the buffer provided to the Events Scheduler to hold ANT events. */ +#define NRF_SDH_ANT_EVT_BUF_SIZE ((CEIL_DIV(NRF_SDH_ANT_MESSAGE_SIZE + \ + NRF_SDH_ANT_EVT_CHANNEL_FIELD_SIZE + \ + NRF_SDH_ANT_EVT_EVENT_FIELD_SIZE, \ + sizeof(uint32_t))) * sizeof(uint32_t)) + + +#if !(defined(__LINT__)) +/**@brief Macro for registering an ANT observer. Modules that want to be + * notified about ANT events must register the handler using this macro. + * + * @details This macro places the observer in a section named "sdh_ant_observers". + * + * @param[in] _name Observer name. + * @param[in] _prio Priority of the observer event handler. + * The smaller the number, the higher the priority. + * @param[in] _handler ANT event handler. + * @param[in] _context Parameter to the event handler. + * @hideinitializer + */ +#define NRF_SDH_ANT_OBSERVER(_name, _prio, _handler, _context) \ +STATIC_ASSERT(NRF_SDH_ANT_ENABLED, "NRF_SDH_ANT_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_ANT_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_ant_observers, _prio, static nrf_sdh_ant_evt_observer_t _name) = \ +{ \ + .handler = _handler, \ + .p_context = _context \ +} + +/**@brief Macro for registering an array of @ref nrf_sdh_ant_evt_observer_t. + * Modules that want to be notified about ANT events must register the handler using + * this macro. + * + * Each observer's handler will be dispatched an event with its relative context from @p _context. + * This macro places the observer in a section named "sdh_ant_observers". + * + * @param[in] _name Observer name. + * @param[in] _prio Priority of the observer event handler. + * The smaller the number, the higher the priority. + * @param[in] _handler ANT event handler. + * @param[in] _context An array of parameters to the event handler. + * @param[in] _cnt Number of observers to register. + * @hideinitializer + */ +#define NRF_SDH_ANT_OBSERVERS(_name, _prio, _handler, _context, _cnt) \ +STATIC_ASSERT(NRF_SDH_ANT_ENABLED, "NRF_SDH_ANT_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_ANT_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_ant_observers, _prio, static nrf_sdh_ant_evt_observer_t _name[_cnt]) = \ +{ \ + MACRO_REPEAT_FOR(_cnt, HANDLER_SET, _handler, _context) \ +} + +#if !(defined(DOXYGEN)) +#define HANDLER_SET(_idx, _handler, _context) \ +{ \ + .handler = _handler, \ + .p_context = _context[_idx], \ +}, +#endif + +#else // __LINT__ + +/* Swallow semicolons */ +/*lint -save -esym(528, *) -esym(529, *) : Symbol not referenced. */ +#define NRF_SDH_ANT_OBSERVER(A, B, C, D) static int semicolon_swallow_##A +#define NRF_SDH_ANT_OBSERVERS(A, B, C, D, E) static int semicolon_swallow_##A +/*lint -restore */ + +#endif + + +/**@brief ANT stack event. */ +typedef struct +{ + ANT_MESSAGE message; //!< ANT Message. + uint8_t channel; //!< Channel number. + uint8_t event; //!< Event code. +} ant_evt_t; + +/**@brief ANT stack event handler. */ +typedef void (*nrf_sdh_ant_evt_handler_t)(ant_evt_t * p_ant_evt, void * p_context); + +/**@brief ANT event observer. */ +typedef struct +{ + nrf_sdh_ant_evt_handler_t handler; //!< ANT event handler. + void * p_context; //!< A parameter to the event handler. +} const nrf_sdh_ant_evt_observer_t; + + +/**@brief Function for configuring and enabling the ANT stack. + * + * @details The function sets the channel configuration for the stack using the parameters + * provided in the @c sdk_config file. It also assigns a correspondingly large + * buffer as a static resource. + */ +ret_code_t nrf_sdh_ant_enable(void); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SDH_ANT_H__ + +/** @} */ diff --git a/components/softdevice/common/nrf_sdh_ble.c b/components/softdevice/common/nrf_sdh_ble.c new file mode 100644 index 0000000..ed61e85 --- /dev/null +++ b/components/softdevice/common/nrf_sdh_ble.c @@ -0,0 +1,326 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_SDH_BLE) + +#include "nrf_sdh_ble.h" + +#include "nrf_sdh.h" +#include "app_error.h" +#include "nrf_strerror.h" + + +#define NRF_LOG_MODULE_NAME nrf_sdh_ble +#if NRF_SDH_BLE_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_SDH_BLE_LOG_LEVEL + #define NRF_LOG_INFO_COLOR NRF_SDH_BLE_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_SDH_BLE_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_SDH_BLE_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +// Create section set "sdh_ble_observers". +NRF_SECTION_SET_DEF(sdh_ble_observers, nrf_sdh_ble_evt_observer_t, NRF_SDH_BLE_OBSERVER_PRIO_LEVELS); + + +//lint -save -e10 -e19 -e40 -e27 Illegal character (0x24) +#if defined(__CC_ARM) + extern uint32_t Image$$RW_IRAM1$$Base; + uint32_t const * const m_ram_start = &Image$$RW_IRAM1$$Base; +#elif defined(__ICCARM__) + extern uint32_t __ICFEDIT_region_RAM_start__; + uint32_t const * const m_ram_start = &__ICFEDIT_region_RAM_start__; +#elif defined(__SES_ARM) + extern uint32_t __app_ram_start__; + uint32_t const * const m_ram_start = &__app_ram_start__; +#elif defined(__GNUC__) + extern uint32_t __data_start__; + uint32_t const * const m_ram_start = &__data_start__; +#endif +//lint -restore + +#define RAM_START 0x20000000 +#define APP_RAM_START (uint32_t)m_ram_start + + +static bool m_stack_is_enabled; + + +ret_code_t nrf_sdh_ble_app_ram_start_get(uint32_t * p_app_ram_start) +{ + if (p_app_ram_start == NULL) + { + return NRF_ERROR_NULL; + } + + *p_app_ram_start = APP_RAM_START; + + return NRF_SUCCESS; +} + + +ret_code_t nrf_sdh_ble_default_cfg_set(uint8_t conn_cfg_tag, uint32_t * p_ram_start) +{ + uint32_t ret_code; + + ret_code = nrf_sdh_ble_app_ram_start_get(p_ram_start); + if (ret_code != NRF_SUCCESS) + { + return ret_code; + } + +#if defined (S112) || defined(S312) + STATIC_ASSERT(NRF_SDH_BLE_CENTRAL_LINK_COUNT == 0, "When using s112, NRF_SDH_BLE_CENTRAL_LINK_COUNT must be 0."); +#endif + + // Overwrite some of the default settings of the BLE stack. + // If any of the calls to sd_ble_cfg_set() fail, log the error but carry on so that + // wrong RAM settings can be caught by nrf_sdh_ble_enable() and a meaningful error + // message will be printed to the user suggesting the correct value. + ble_cfg_t ble_cfg; + +#if (NRF_SDH_BLE_TOTAL_LINK_COUNT != 0) + // Configure the connection count. + memset(&ble_cfg, 0, sizeof(ble_cfg)); + ble_cfg.conn_cfg.conn_cfg_tag = conn_cfg_tag; + ble_cfg.conn_cfg.params.gap_conn_cfg.conn_count = NRF_SDH_BLE_TOTAL_LINK_COUNT; + ble_cfg.conn_cfg.params.gap_conn_cfg.event_length = NRF_SDH_BLE_GAP_EVENT_LENGTH; + + ret_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_cfg, *p_ram_start); + if (ret_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_CONN_CFG_GAP.", + nrf_strerror_get(ret_code)); + } + + // Configure the connection roles. + memset(&ble_cfg, 0, sizeof(ble_cfg)); +#if !defined (S122) + ble_cfg.gap_cfg.role_count_cfg.periph_role_count = NRF_SDH_BLE_PERIPHERAL_LINK_COUNT; +#endif // !defined (S122) +#if !defined (S112) && !defined(S312) && !defined(S113) + ble_cfg.gap_cfg.role_count_cfg.central_role_count = NRF_SDH_BLE_CENTRAL_LINK_COUNT; + ble_cfg.gap_cfg.role_count_cfg.central_sec_count = MIN(NRF_SDH_BLE_CENTRAL_LINK_COUNT, + BLE_GAP_ROLE_COUNT_CENTRAL_SEC_DEFAULT); +#endif // !defined (S112) && !defined(S312) && !defined(S113) + + ret_code = sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &ble_cfg, *p_ram_start); + if (ret_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_GAP_CFG_ROLE_COUNT.", + nrf_strerror_get(ret_code)); + } + + // Configure the maximum ATT MTU. +#if (NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 23) + memset(&ble_cfg, 0x00, sizeof(ble_cfg)); + ble_cfg.conn_cfg.conn_cfg_tag = conn_cfg_tag; + ble_cfg.conn_cfg.params.gatt_conn_cfg.att_mtu = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; + + ret_code = sd_ble_cfg_set(BLE_CONN_CFG_GATT, &ble_cfg, *p_ram_start); + if (ret_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_CONN_CFG_GATT.", + nrf_strerror_get(ret_code)); + } +#endif // NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 23 +#endif // NRF_SDH_BLE_TOTAL_LINK_COUNT != 0 + + // Configure number of custom UUIDS. + memset(&ble_cfg, 0, sizeof(ble_cfg)); + ble_cfg.common_cfg.vs_uuid_cfg.vs_uuid_count = NRF_SDH_BLE_VS_UUID_COUNT; + + ret_code = sd_ble_cfg_set(BLE_COMMON_CFG_VS_UUID, &ble_cfg, *p_ram_start); + if (ret_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_COMMON_CFG_VS_UUID.", + nrf_strerror_get(ret_code)); + } + + // Configure the GATTS attribute table. + memset(&ble_cfg, 0x00, sizeof(ble_cfg)); + ble_cfg.gatts_cfg.attr_tab_size.attr_tab_size = NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE; + + ret_code = sd_ble_cfg_set(BLE_GATTS_CFG_ATTR_TAB_SIZE, &ble_cfg, *p_ram_start); + if (ret_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_GATTS_CFG_ATTR_TAB_SIZE.", + nrf_strerror_get(ret_code)); + } + + // Configure Service Changed characteristic. + memset(&ble_cfg, 0x00, sizeof(ble_cfg)); + ble_cfg.gatts_cfg.service_changed.service_changed = NRF_SDH_BLE_SERVICE_CHANGED; + + ret_code = sd_ble_cfg_set(BLE_GATTS_CFG_SERVICE_CHANGED, &ble_cfg, *p_ram_start); + if (ret_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_GATTS_CFG_SERVICE_CHANGED.", + nrf_strerror_get(ret_code)); + } + + return NRF_SUCCESS; +} + + +/**@brief Function for finding the end address of the RAM. */ +static uint32_t ram_end_address_get(void) +{ + uint32_t ram_total_size; + +#ifdef NRF51 + uint32_t block_size = NRF_FICR->SIZERAMBLOCKS; + ram_total_size = block_size * NRF_FICR->NUMRAMBLOCK; +#else + ram_total_size = NRF_FICR->INFO.RAM * 1024; +#endif + + return RAM_START + ram_total_size; +} + + +ret_code_t nrf_sdh_ble_enable(uint32_t * const p_app_ram_start) +{ + // Start of RAM, obtained from linker symbol. + uint32_t const app_ram_start_link = *p_app_ram_start; + + ret_code_t ret_code = sd_ble_enable(p_app_ram_start); + if (*p_app_ram_start > app_ram_start_link) + { + NRF_LOG_WARNING("Insufficient RAM allocated for the SoftDevice."); + + NRF_LOG_WARNING("Change the RAM start location from 0x%x to 0x%x.", + app_ram_start_link, *p_app_ram_start); + NRF_LOG_WARNING("Maximum RAM size for application is 0x%x.", + ram_end_address_get() - (*p_app_ram_start)); + } + else + { + NRF_LOG_DEBUG("RAM starts at 0x%x", app_ram_start_link); + if (*p_app_ram_start != app_ram_start_link) + { + NRF_LOG_DEBUG("RAM start location can be adjusted to 0x%x.", *p_app_ram_start); + + NRF_LOG_DEBUG("RAM size for application can be adjusted to 0x%x.", + ram_end_address_get() - (*p_app_ram_start)); + } + } + + if (ret_code == NRF_SUCCESS) + { + m_stack_is_enabled = true; + } + else + { + NRF_LOG_ERROR("sd_ble_enable() returned %s.", nrf_strerror_get(ret_code)); + } + + return ret_code; +} + + +/**@brief Function for polling BLE events. + * + * @param[in] p_context Context of the observer. + */ +static void nrf_sdh_ble_evts_poll(void * p_context) +{ + UNUSED_VARIABLE(p_context); + + ret_code_t ret_code; + + if (!m_stack_is_enabled) + { + return; + } + + while (true) + { + /*lint -save -e(587) */ + __ALIGN(4) uint8_t evt_buffer[NRF_SDH_BLE_EVT_BUF_SIZE]; + /*lint -restore */ + + ble_evt_t * p_ble_evt; + uint16_t evt_len = (uint16_t)sizeof(evt_buffer); + + ret_code = sd_ble_evt_get(evt_buffer, &evt_len); + if (ret_code != NRF_SUCCESS) + { + break; + } + + p_ble_evt = (ble_evt_t *)evt_buffer; + + NRF_LOG_DEBUG("BLE event: 0x%x.", p_ble_evt->header.evt_id); + + // Forward the event to BLE observers. + nrf_section_iter_t iter; + for (nrf_section_iter_init(&iter, &sdh_ble_observers); + nrf_section_iter_get(&iter) != NULL; + nrf_section_iter_next(&iter)) + { + nrf_sdh_ble_evt_observer_t * p_observer; + nrf_sdh_ble_evt_handler_t handler; + + p_observer = (nrf_sdh_ble_evt_observer_t *)nrf_section_iter_get(&iter); + handler = p_observer->handler; + + handler(p_ble_evt, p_observer->p_context); + } + } + + if (ret_code != NRF_ERROR_NOT_FOUND) + { + APP_ERROR_HANDLER(ret_code); + } +} + + +NRF_SDH_STACK_OBSERVER(m_nrf_sdh_ble_evts_poll, NRF_SDH_BLE_STACK_OBSERVER_PRIO) = +{ + .handler = nrf_sdh_ble_evts_poll, + .p_context = NULL, +}; + +#endif // NRF_MODULE_ENABLED(NRF_SDH_BLE) diff --git a/components/softdevice/common/nrf_sdh_ble.h b/components/softdevice/common/nrf_sdh_ble.h new file mode 100644 index 0000000..612fdc0 --- /dev/null +++ b/components/softdevice/common/nrf_sdh_ble.h @@ -0,0 +1,184 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * + * @defgroup nrf_sdh_ble BLE support in SoftDevice Handler + * @{ + * @ingroup nrf_sdh + * @brief This file contains the declarations of types and functions required for BLE stack + * support. + */ + +#ifndef NRF_SDH_BLE_H__ +#define NRF_SDH_BLE_H__ + +#include "app_util.h" +#include "ble.h" +#include "nrf_section_iter.h" +#include "sdk_config.h" +#include "sdk_errors.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Size of the buffer for a BLE event. */ +#define NRF_SDH_BLE_EVT_BUF_SIZE BLE_EVT_LEN_MAX(NRF_SDH_BLE_GATT_MAX_MTU_SIZE) + + +#if !(defined(__LINT__)) +/**@brief Macro for registering @ref nrf_sdh_soc_evt_observer_t. Modules that want to be + * notified about SoC events must register the handler using this macro. + * + * @details This macro places the observer in a section named "sdh_soc_observers". + * + * @param[in] _name Observer name. + * @param[in] _prio Priority of the observer event handler. + * The smaller the number, the higher the priority. + * @param[in] _handler BLE event handler. + * @param[in] _context Parameter to the event handler. + * @hideinitializer + */ +#define NRF_SDH_BLE_OBSERVER(_name, _prio, _handler, _context) \ +STATIC_ASSERT(NRF_SDH_BLE_ENABLED, "NRF_SDH_BLE_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_BLE_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_ble_observers, _prio, static nrf_sdh_ble_evt_observer_t _name) = \ +{ \ + .handler = _handler, \ + .p_context = _context \ +} + +/**@brief Macro for registering an array of @ref nrf_sdh_ble_evt_observer_t. + * Modules that want to be notified about SoC events must register the handler using + * this macro. + * + * Each observer's handler will be dispatched an event with its relative context from @p _context. + * This macro places the observer in a section named "sdh_ble_observers". + * + * @param[in] _name Observer name. + * @param[in] _prio Priority of the observer event handler. + * The smaller the number, the higher the priority. + * @param[in] _handler BLE event handler. + * @param[in] _context An array of parameters to the event handler. + * @param[in] _cnt Number of observers to register. + * @hideinitializer + */ +#define NRF_SDH_BLE_OBSERVERS(_name, _prio, _handler, _context, _cnt) \ +STATIC_ASSERT(NRF_SDH_BLE_ENABLED, "NRF_SDH_BLE_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_BLE_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_ble_observers, _prio, static nrf_sdh_ble_evt_observer_t _name[_cnt]) = \ +{ \ + MACRO_REPEAT_FOR(_cnt, HANDLER_SET, _handler, _context) \ +} + +#if !(defined(DOXYGEN)) +#define HANDLER_SET(_idx, _handler, _context) \ +{ \ + .handler = _handler, \ + .p_context = _context[_idx], \ +}, +#endif + +#else // __LINT__ + +/* Swallow semicolons */ +/*lint -save -esym(528, *) -esym(529, *) : Symbol not referenced. */ +#define NRF_SDH_BLE_OBSERVER(A, B, C, D) static int semicolon_swallow_##A +#define NRF_SDH_BLE_OBSERVERS(A, B, C, D, E) static int semicolon_swallow_##A +/*lint -restore */ + +#endif + + +/**@brief BLE stack event handler. */ +typedef void (*nrf_sdh_ble_evt_handler_t)(ble_evt_t const * p_ble_evt, void * p_context); + +/**@brief BLE event observer. */ +typedef struct +{ + nrf_sdh_ble_evt_handler_t handler; //!< BLE event handler. + void * p_context; //!< A parameter to the event handler. +} const nrf_sdh_ble_evt_observer_t; + + +/**@brief Function for retrieving the address of the start of application's RAM. + * + * @param[out] p_app_ram_start Address of the start of application's RAM. + * + * @retval NRF_SUCCESS If the address was successfully retrieved. + * @retval NRF_ERROR_NULL If @p p_app_ram_start was @c NULL. + */ +ret_code_t nrf_sdh_ble_app_ram_start_get(uint32_t * p_app_ram_start); + + +/**@brief Set the default BLE stack configuration. + * + * This function configures the BLE stack with the settings specified in the + * SoftDevice handler BLE configuration. The following configurations will be set: + * - Number of peripheral links + * - Number of central links + * - ATT MTU size (for the given connection) + * - Vendor specific UUID count + * - GATTS Attribute table size + * - Service changed + * + * @param[in] conn_cfg_tag The connection to configure. + * @param[out] p_ram_start Application RAM start address. + */ +ret_code_t nrf_sdh_ble_default_cfg_set(uint8_t conn_cfg_tag, uint32_t * p_ram_start); + + +/**@brief Function for configuring and enabling the BLE stack. + * + * @param[in] p_app_ram_start Address of the start of application's RAM. + */ +ret_code_t nrf_sdh_ble_enable(uint32_t * p_app_ram_start); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SDH_BLE_H__ + +/** @} */ diff --git a/components/softdevice/common/nrf_sdh_freertos.c b/components/softdevice/common/nrf_sdh_freertos.c new file mode 100644 index 0000000..dbe3b20 --- /dev/null +++ b/components/softdevice/common/nrf_sdh_freertos.c @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_sdh_freertos.h" +#include "nrf_sdh.h" + +/* Group of FreeRTOS-related includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define NRF_LOG_MODULE_NAME nrf_sdh_freertos +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define NRF_BLE_FREERTOS_SDH_TASK_STACK 256 + + +static TaskHandle_t m_softdevice_task; //!< Reference to SoftDevice FreeRTOS task. +static nrf_sdh_freertos_task_hook_t m_task_hook; //!< A hook function run by the SoftDevice task before entering its loop. + + +void SD_EVT_IRQHandler(void) +{ + BaseType_t yield_req = pdFALSE; + + vTaskNotifyGiveFromISR(m_softdevice_task, &yield_req); + + /* Switch the task if required. */ + portYIELD_FROM_ISR(yield_req); +} + + +/* This function gets events from the SoftDevice and processes them. */ +static void softdevice_task(void * pvParameter) +{ + NRF_LOG_DEBUG("Enter softdevice_task."); + + if (m_task_hook != NULL) + { + m_task_hook(pvParameter); + } + + while (true) + { + nrf_sdh_evts_poll(); /* let the handlers run first, incase the EVENT occured before creating this task */ + + (void) ulTaskNotifyTake(pdTRUE, /* Clear the notification value before exiting (equivalent to the binary semaphore). */ + portMAX_DELAY); /* Block indefinitely (INCLUDE_vTaskSuspend has to be enabled).*/ + } +} + + +void nrf_sdh_freertos_init(nrf_sdh_freertos_task_hook_t hook_fn, void * p_context) +{ + NRF_LOG_DEBUG("Creating a SoftDevice task."); + + m_task_hook = hook_fn; + + BaseType_t xReturned = xTaskCreate(softdevice_task, + "BLE", + NRF_BLE_FREERTOS_SDH_TASK_STACK, + p_context, + 2, + &m_softdevice_task); + if (xReturned != pdPASS) + { + NRF_LOG_ERROR("SoftDevice task not created."); + APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); + } +} diff --git a/components/softdevice/common/nrf_sdh_freertos.h b/components/softdevice/common/nrf_sdh_freertos.h new file mode 100644 index 0000000..531c530 --- /dev/null +++ b/components/softdevice/common/nrf_sdh_freertos.h @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_SDH_FREERTOS_H__ +#define NRF_SDH_FREERTOS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name FreeRTOS implementation of SoftDevice Handler + * @{ + * @ingroup nrf_sdh + */ + +typedef void (*nrf_sdh_freertos_task_hook_t)(void * p_context); + +/**@brief Function for creating a task to retrieve SoftDevice events. + * @param[in] hook Function to run in the SoftDevice FreeRTOS task, + * before entering the task loop. + * @param[in] p_context Parameter for the function @p hook. + */ +void nrf_sdh_freertos_init(nrf_sdh_freertos_task_hook_t hook, void * p_context); + +/** + * @} + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_SDH_FREERTOS_H__ */ diff --git a/components/softdevice/common/nrf_sdh_soc.c b/components/softdevice/common/nrf_sdh_soc.c new file mode 100644 index 0000000..ec0a040 --- /dev/null +++ b/components/softdevice/common/nrf_sdh_soc.c @@ -0,0 +1,118 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_SDH_SOC) + +#include "nrf_sdh_soc.h" + +#include "nrf_sdh.h" +#include "nrf_soc.h" +#include "app_error.h" + + +#define NRF_LOG_MODULE_NAME nrf_sdh_soc +#if NRF_SDH_SOC_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_SDH_SOC_LOG_LEVEL + #define NRF_LOG_INFO_COLOR NRF_SDH_SOC_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_SDH_SOC_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_SDH_SOC_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +// Create section set "sdh_soc_observers". +NRF_SECTION_SET_DEF(sdh_soc_observers, nrf_sdh_soc_evt_observer_t, NRF_SDH_SOC_OBSERVER_PRIO_LEVELS); + + +/**@brief Function for polling SoC events. + * + * @param[in] p_context Context of the observer. + */ +static void nrf_sdh_soc_evts_poll(void * p_context) +{ + ret_code_t ret_code; + + UNUSED_VARIABLE(p_context); + + while (true) + { + uint32_t evt_id; + + ret_code = sd_evt_get(&evt_id); + if (ret_code != NRF_SUCCESS) + { + break; + } + + NRF_LOG_DEBUG("SoC event: 0x%x.", evt_id); + + // Forward the event to SoC observers. + nrf_section_iter_t iter; + for (nrf_section_iter_init(&iter, &sdh_soc_observers); + nrf_section_iter_get(&iter) != NULL; + nrf_section_iter_next(&iter)) + { + nrf_sdh_soc_evt_observer_t * p_observer; + nrf_sdh_soc_evt_handler_t handler; + + p_observer = (nrf_sdh_soc_evt_observer_t *) nrf_section_iter_get(&iter); + handler = p_observer->handler; + + handler(evt_id, p_observer->p_context); + } + } + + if (ret_code != NRF_ERROR_NOT_FOUND) + { + APP_ERROR_HANDLER(ret_code); + } +} + + +NRF_SDH_STACK_OBSERVER(m_nrf_sdh_soc_evts_poll, NRF_SDH_SOC_STACK_OBSERVER_PRIO) = +{ + .handler = nrf_sdh_soc_evts_poll, + .p_context = NULL, +}; + +#endif // NRF_MODULE_ENABLED(NRF_SDH_SOC) diff --git a/components/softdevice/common/nrf_sdh_soc.h b/components/softdevice/common/nrf_sdh_soc.h new file mode 100644 index 0000000..32c32a5 --- /dev/null +++ b/components/softdevice/common/nrf_sdh_soc.h @@ -0,0 +1,143 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * + * @defgroup nrf_sdh_soc SoC support in SoftDevice Handler + * @{ + * @ingroup nrf_sdh + * @brief This file contains the declarations of types and functions required for SoftDevice Handler + * SoC support. + */ + +#ifndef NRF_SDH_SOC_H__ +#define NRF_SDH_SOC_H__ + +#include "sdk_common.h" +#include "nrf_section_iter.h" +#include "nrf_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if !(defined(__LINT__)) +/**@brief Macro for registering @ref nrf_sdh_soc_evt_observer_t. Modules that want to be + * notified about SoC events must register the handler using this macro. + * + * @details This macro places the observer in a section named "sdh_soc_observers". + * + * @param[in] _name Observer name. + * @param[in] _prio Priority of the observer event handler. + * The smaller the number, the higher the priority. + * @param[in] _handler SoC event handler. + * @param[in] _context Parameter to the event handler. + * @hideinitializer + */ +#define NRF_SDH_SOC_OBSERVER(_name, _prio, _handler, _context) \ +STATIC_ASSERT(NRF_SDH_SOC_ENABLED, "NRF_SDH_SOC_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_SOC_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_soc_observers, _prio, static nrf_sdh_soc_evt_observer_t _name) = \ +{ \ + .handler = _handler, \ + .p_context = _context \ +} + +/**@brief Macro for registering an array of @ref nrf_sdh_soc_evt_observer_t. + * Modules that want to be notified about SoC events must register the handler using + * this macro. + * + * Each observer's handler will be dispatched an event with its relative context from @p _context. + * This macro places the observer in a section named "sdh_soc_observers". + * + * @param[in] _name Observer name. + * @param[in] _prio Priority of the observer event handler. + * The smaller the number, the higher the priority. + * @param[in] _handler SoC event handler. + * @param[in] _context An array of parameters to the event handler. + * @param[in] _cnt Number of observers to register. + * @hideinitializer + */ +#define NRF_SDH_SOC_EVENT_OBSERVERS(_name, _prio, _handler, _context, _cnt) \ +STATIC_ASSERT(NRF_SDH_SOC_ENABLED, "NRF_SDH_SOC_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_SOC_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_soc_observers, _prio, static nrf_sdh_soc_evt_observer_t _name[_cnt]) = \ +{ \ + MACRO_REPEAT_FOR(_cnt, HANDLER_SET, _handler, _context) \ +} + +#if !(defined(DOXYGEN)) +#define HANDLER_SET(_idx, _handler, _context) \ +{ \ + .handler = _handler, \ + .p_context = _context[_idx], \ +}, +#endif + +#else // __LINT__ + +/* Swallow semicolons */ +/*lint -save -esym(528, *) -esym(529, *) : Symbol not referenced. */ +#define NRF_SDH_SOC_OBSERVER(A, B, C, D) static int semicolon_swallow_##A +#define NRF_SDH_SOC_OBSERVERS(A, B, C, D, E) static int semicolon_swallow_##A +/*lint -restore */ + +#endif + + +/**@brief SoC event handler. */ +typedef void (*nrf_sdh_soc_evt_handler_t) (uint32_t evt_id, void * p_context); + +/**@brief SoC event observer. */ +typedef struct +{ + nrf_sdh_soc_evt_handler_t handler; //!< SoC event handler. + void * p_context; //!< A parameter to the event handler. +} const nrf_sdh_soc_evt_observer_t; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SDH_SOC_H__ + +/** @} */ diff --git a/components/softdevice/s140/doc/s140_nrf52_7.2.0_licence-agreement.txt b/components/softdevice/s140/doc/s140_nrf52_7.2.0_licence-agreement.txt new file mode 100644 index 0000000..8ac5192 --- /dev/null +++ b/components/softdevice/s140/doc/s140_nrf52_7.2.0_licence-agreement.txt @@ -0,0 +1,35 @@ +Copyright (c) 2007 - 2020, Nordic Semiconductor ASA +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form, except as embedded into a Nordic + Semiconductor ASA integrated circuit in a product or a software update for + such product, must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +3. Neither the name of Nordic Semiconductor ASA nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +4. This software, with or without modification, must only be used with a + Nordic Semiconductor ASA integrated circuit. + +5. Any software provided in binary form under this license must not be reverse + engineered, decompiled, modified and/or disassembled. + +THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/components/softdevice/s140/doc/s140_nrf52_7.2.0_migration-document.pdf b/components/softdevice/s140/doc/s140_nrf52_7.2.0_migration-document.pdf new file mode 100644 index 0000000..6e77a2f Binary files /dev/null and b/components/softdevice/s140/doc/s140_nrf52_7.2.0_migration-document.pdf differ diff --git a/components/softdevice/s140/doc/s140_nrf52_7.2.0_release-notes.pdf b/components/softdevice/s140/doc/s140_nrf52_7.2.0_release-notes.pdf new file mode 100644 index 0000000..af90b89 Binary files /dev/null and b/components/softdevice/s140/doc/s140_nrf52_7.2.0_release-notes.pdf differ diff --git a/components/softdevice/s140/headers/ble.h b/components/softdevice/s140/headers/ble.h new file mode 100644 index 0000000..36303bb --- /dev/null +++ b/components/softdevice/s140/headers/ble.h @@ -0,0 +1,679 @@ +/* + * Copyright (c) 2012 - 2020, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @addtogroup BLE_COMMON BLE SoftDevice Common + @{ + @defgroup ble_api Events, type definitions and API calls + @{ + + @brief Module independent events, type definitions and API calls for the BLE SoftDevice. + + */ + +#ifndef BLE_H__ +#define BLE_H__ + +#include +#include "nrf_svc.h" +#include "nrf_error.h" +#include "ble_err.h" +#include "ble_gap.h" +#include "ble_l2cap.h" +#include "ble_gatt.h" +#include "ble_gattc.h" +#include "ble_gatts.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup BLE_COMMON_ENUMERATIONS Enumerations + * @{ */ + +/** + * @brief Common API SVC numbers. + */ +enum BLE_COMMON_SVCS +{ + SD_BLE_ENABLE = BLE_SVC_BASE, /**< Enable and initialize the BLE stack */ + SD_BLE_EVT_GET, /**< Get an event from the pending events queue. */ + SD_BLE_UUID_VS_ADD, /**< Add a Vendor Specific base UUID. */ + SD_BLE_UUID_DECODE, /**< Decode UUID bytes. */ + SD_BLE_UUID_ENCODE, /**< Encode UUID bytes. */ + SD_BLE_VERSION_GET, /**< Get the local version information (company ID, Link Layer Version, Link Layer Subversion). */ + SD_BLE_USER_MEM_REPLY, /**< User Memory Reply. */ + SD_BLE_OPT_SET, /**< Set a BLE option. */ + SD_BLE_OPT_GET, /**< Get a BLE option. */ + SD_BLE_CFG_SET, /**< Add a configuration to the BLE stack. */ + SD_BLE_UUID_VS_REMOVE, /**< Remove a Vendor Specific base UUID. */ +}; + +/** + * @brief BLE Module Independent Event IDs. + */ +enum BLE_COMMON_EVTS +{ + BLE_EVT_USER_MEM_REQUEST = BLE_EVT_BASE + 0, /**< User Memory request. See @ref ble_evt_user_mem_request_t + \n Reply with @ref sd_ble_user_mem_reply. */ + BLE_EVT_USER_MEM_RELEASE = BLE_EVT_BASE + 1, /**< User Memory release. See @ref ble_evt_user_mem_release_t */ +}; + +/**@brief BLE Connection Configuration IDs. + * + * IDs that uniquely identify a connection configuration. + */ +enum BLE_CONN_CFGS +{ + BLE_CONN_CFG_GAP = BLE_CONN_CFG_BASE + 0, /**< BLE GAP specific connection configuration. */ + BLE_CONN_CFG_GATTC = BLE_CONN_CFG_BASE + 1, /**< BLE GATTC specific connection configuration. */ + BLE_CONN_CFG_GATTS = BLE_CONN_CFG_BASE + 2, /**< BLE GATTS specific connection configuration. */ + BLE_CONN_CFG_GATT = BLE_CONN_CFG_BASE + 3, /**< BLE GATT specific connection configuration. */ + BLE_CONN_CFG_L2CAP = BLE_CONN_CFG_BASE + 4, /**< BLE L2CAP specific connection configuration. */ +}; + +/**@brief BLE Common Configuration IDs. + * + * IDs that uniquely identify a common configuration. + */ +enum BLE_COMMON_CFGS +{ + BLE_COMMON_CFG_VS_UUID = BLE_CFG_BASE, /**< Vendor specific base UUID configuration */ +}; + +/**@brief Common Option IDs. + * IDs that uniquely identify a common option. + */ +enum BLE_COMMON_OPTS +{ + BLE_COMMON_OPT_PA_LNA = BLE_OPT_BASE + 0, /**< PA and LNA options */ + BLE_COMMON_OPT_CONN_EVT_EXT = BLE_OPT_BASE + 1, /**< Extended connection events option */ + BLE_COMMON_OPT_EXTENDED_RC_CAL = BLE_OPT_BASE + 2, /**< Extended RC calibration option */ +}; + +/** @} */ + +/** @addtogroup BLE_COMMON_DEFINES Defines + * @{ */ + +/** @brief Required pointer alignment for BLE Events. +*/ +#define BLE_EVT_PTR_ALIGNMENT 4 + +/** @brief Leaves the maximum of the two arguments. +*/ +#define BLE_MAX(a, b) ((a) < (b) ? (b) : (a)) + +/** @brief Maximum possible length for BLE Events. + * @note The highest value used for @ref ble_gatt_conn_cfg_t::att_mtu in any connection configuration shall be used as a parameter. + * If that value has not been configured for any connections then @ref BLE_GATT_ATT_MTU_DEFAULT must be used instead. +*/ +#define BLE_EVT_LEN_MAX(ATT_MTU) ( \ + offsetof(ble_evt_t, evt.gattc_evt.params.prim_srvc_disc_rsp.services) + ((ATT_MTU) - 1) / 4 * sizeof(ble_gattc_service_t) \ +) + +/** @defgroup BLE_USER_MEM_TYPES User Memory Types + * @{ */ +#define BLE_USER_MEM_TYPE_INVALID 0x00 /**< Invalid User Memory Types. */ +#define BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES 0x01 /**< User Memory for GATTS queued writes. */ +/** @} */ + +/** @defgroup BLE_UUID_VS_COUNTS Vendor Specific base UUID counts + * @{ + */ +#define BLE_UUID_VS_COUNT_DEFAULT 10 /**< Default VS UUID count. */ +#define BLE_UUID_VS_COUNT_MAX 254 /**< Maximum VS UUID count. */ +/** @} */ + +/** @defgroup BLE_COMMON_CFG_DEFAULTS Configuration defaults. + * @{ + */ +#define BLE_CONN_CFG_TAG_DEFAULT 0 /**< Default configuration tag, SoftDevice default connection configuration. */ + +/** @} */ + +/** @} */ + +/** @addtogroup BLE_COMMON_STRUCTURES Structures + * @{ */ + +/**@brief User Memory Block. */ +typedef struct +{ + uint8_t *p_mem; /**< Pointer to the start of the user memory block. */ + uint16_t len; /**< Length in bytes of the user memory block. */ +} ble_user_mem_block_t; + +/**@brief Event structure for @ref BLE_EVT_USER_MEM_REQUEST. */ +typedef struct +{ + uint8_t type; /**< User memory type, see @ref BLE_USER_MEM_TYPES. */ +} ble_evt_user_mem_request_t; + +/**@brief Event structure for @ref BLE_EVT_USER_MEM_RELEASE. */ +typedef struct +{ + uint8_t type; /**< User memory type, see @ref BLE_USER_MEM_TYPES. */ + ble_user_mem_block_t mem_block; /**< User memory block */ +} ble_evt_user_mem_release_t; + +/**@brief Event structure for events not associated with a specific function module. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which this event occurred. */ + union + { + ble_evt_user_mem_request_t user_mem_request; /**< User Memory Request Event Parameters. */ + ble_evt_user_mem_release_t user_mem_release; /**< User Memory Release Event Parameters. */ + } params; /**< Event parameter union. */ +} ble_common_evt_t; + +/**@brief BLE Event header. */ +typedef struct +{ + uint16_t evt_id; /**< Value from a BLE__EVT series. */ + uint16_t evt_len; /**< Length in octets including this header. */ +} ble_evt_hdr_t; + +/**@brief Common BLE Event type, wrapping the module specific event reports. */ +typedef struct +{ + ble_evt_hdr_t header; /**< Event header. */ + union + { + ble_common_evt_t common_evt; /**< Common Event, evt_id in BLE_EVT_* series. */ + ble_gap_evt_t gap_evt; /**< GAP originated event, evt_id in BLE_GAP_EVT_* series. */ + ble_gattc_evt_t gattc_evt; /**< GATT client originated event, evt_id in BLE_GATTC_EVT* series. */ + ble_gatts_evt_t gatts_evt; /**< GATT server originated event, evt_id in BLE_GATTS_EVT* series. */ + ble_l2cap_evt_t l2cap_evt; /**< L2CAP originated event, evt_id in BLE_L2CAP_EVT* series. */ + } evt; /**< Event union. */ +} ble_evt_t; + + +/** + * @brief Version Information. + */ +typedef struct +{ + uint8_t version_number; /**< Link Layer Version number. See https://www.bluetooth.org/en-us/specification/assigned-numbers/link-layer for assigned values. */ + uint16_t company_id; /**< Company ID, Nordic Semiconductor's company ID is 89 (0x0059) (https://www.bluetooth.org/apps/content/Default.aspx?doc_id=49708). */ + uint16_t subversion_number; /**< Link Layer Sub Version number, corresponds to the SoftDevice Config ID or Firmware ID (FWID). */ +} ble_version_t; + +/** + * @brief Configuration parameters for the PA and LNA. + */ +typedef struct +{ + uint8_t enable :1; /**< Enable toggling for this amplifier */ + uint8_t active_high :1; /**< Set the pin to be active high */ + uint8_t gpio_pin :6; /**< The GPIO pin to toggle for this amplifier */ +} ble_pa_lna_cfg_t; + +/** + * @brief PA & LNA GPIO toggle configuration + * + * This option configures the SoftDevice to toggle pins when the radio is active for use with a power amplifier and/or + * a low noise amplifier. + * + * Toggling the pins is achieved by using two PPI channels and a GPIOTE channel. The hardware channel IDs are provided + * by the application and should be regarded as reserved as long as any PA/LNA toggling is enabled. + * + * @note @ref sd_ble_opt_get is not supported for this option. + * @note Setting this option while the radio is in use (i.e. any of the roles are active) may have undefined consequences + * and must be avoided by the application. + */ +typedef struct +{ + ble_pa_lna_cfg_t pa_cfg; /**< Power Amplifier configuration */ + ble_pa_lna_cfg_t lna_cfg; /**< Low Noise Amplifier configuration */ + + uint8_t ppi_ch_id_set; /**< PPI channel used for radio pin setting */ + uint8_t ppi_ch_id_clr; /**< PPI channel used for radio pin clearing */ + uint8_t gpiote_ch_id; /**< GPIOTE channel used for radio pin toggling */ +} ble_common_opt_pa_lna_t; + +/** + * @brief Configuration of extended BLE connection events. + * + * When enabled the SoftDevice will dynamically extend the connection event when possible. + * + * The connection event length is controlled by the connection configuration as set by @ref ble_gap_conn_cfg_t::event_length. + * The connection event can be extended if there is time to send another packet pair before the start of the next connection interval, + * and if there are no conflicts with other BLE roles requesting radio time. + * + * @note @ref sd_ble_opt_get is not supported for this option. + */ +typedef struct +{ + uint8_t enable : 1; /**< Enable extended BLE connection events, disabled by default. */ +} ble_common_opt_conn_evt_ext_t; + +/** + * @brief Enable/disable extended RC calibration. + * + * If extended RC calibration is enabled and the internal RC oscillator (@ref NRF_CLOCK_LF_SRC_RC) is used as the SoftDevice + * LFCLK source, the SoftDevice as a peripheral will by default try to increase the receive window if two consecutive packets + * are not received. If it turns out that the packets were not received due to clock drift, the RC calibration is started. + * This calibration comes in addition to the periodic calibration that is configured by @ref sd_softdevice_enable(). When + * using only peripheral connections, the periodic calibration can therefore be configured with a much longer interval as the + * peripheral will be able to detect and adjust automatically to clock drift, and calibrate on demand. + * + * If extended RC calibration is disabled and the internal RC oscillator is used as the SoftDevice LFCLK source, the + * RC oscillator is calibrated periodically as configured by @ref sd_softdevice_enable(). + * + * @note @ref sd_ble_opt_get is not supported for this option. + */ +typedef struct +{ + uint8_t enable : 1; /**< Enable extended RC calibration, enabled by default. */ +} ble_common_opt_extended_rc_cal_t; + +/**@brief Option structure for common options. */ +typedef union +{ + ble_common_opt_pa_lna_t pa_lna; /**< Parameters for controlling PA and LNA pin toggling. */ + ble_common_opt_conn_evt_ext_t conn_evt_ext; /**< Parameters for enabling extended connection events. */ + ble_common_opt_extended_rc_cal_t extended_rc_cal; /**< Parameters for enabling extended RC calibration. */ +} ble_common_opt_t; + +/**@brief Common BLE Option type, wrapping the module specific options. */ +typedef union +{ + ble_common_opt_t common_opt; /**< COMMON options, opt_id in @ref BLE_COMMON_OPTS series. */ + ble_gap_opt_t gap_opt; /**< GAP option, opt_id in @ref BLE_GAP_OPTS series. */ + ble_gattc_opt_t gattc_opt; /**< GATTC option, opt_id in @ref BLE_GATTC_OPTS series. */ +} ble_opt_t; + +/**@brief BLE connection configuration type, wrapping the module specific configurations, set with + * @ref sd_ble_cfg_set. + * + * @note Connection configurations don't have to be set. + * In the case that no configurations has been set, or fewer connection configurations has been set than enabled connections, + * the default connection configuration will be automatically added for the remaining connections. + * When creating connections with the default configuration, @ref BLE_CONN_CFG_TAG_DEFAULT should be used in + * place of @ref ble_conn_cfg_t::conn_cfg_tag. + * + * @sa sd_ble_gap_adv_start() + * @sa sd_ble_gap_connect() + * + * @mscs + * @mmsc{@ref BLE_CONN_CFG} + * @endmscs + + */ +typedef struct +{ + uint8_t conn_cfg_tag; /**< The application chosen tag it can use with the + @ref sd_ble_gap_adv_start() and @ref sd_ble_gap_connect() calls + to select this configuration when creating a connection. + Must be different for all connection configurations added and not @ref BLE_CONN_CFG_TAG_DEFAULT. */ + union { + ble_gap_conn_cfg_t gap_conn_cfg; /**< GAP connection configuration, cfg_id is @ref BLE_CONN_CFG_GAP. */ + ble_gattc_conn_cfg_t gattc_conn_cfg; /**< GATTC connection configuration, cfg_id is @ref BLE_CONN_CFG_GATTC. */ + ble_gatts_conn_cfg_t gatts_conn_cfg; /**< GATTS connection configuration, cfg_id is @ref BLE_CONN_CFG_GATTS. */ + ble_gatt_conn_cfg_t gatt_conn_cfg; /**< GATT connection configuration, cfg_id is @ref BLE_CONN_CFG_GATT. */ + ble_l2cap_conn_cfg_t l2cap_conn_cfg; /**< L2CAP connection configuration, cfg_id is @ref BLE_CONN_CFG_L2CAP. */ + } params; /**< Connection configuration union. */ +} ble_conn_cfg_t; + +/** + * @brief Configuration of Vendor Specific base UUIDs, set with @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_INVALID_PARAM Too many UUIDs configured. + */ +typedef struct +{ + uint8_t vs_uuid_count; /**< Number of 128-bit Vendor Specific base UUID bases to allocate memory for. + Default value is @ref BLE_UUID_VS_COUNT_DEFAULT. Maximum value is + @ref BLE_UUID_VS_COUNT_MAX. */ +} ble_common_cfg_vs_uuid_t; + +/**@brief Common BLE Configuration type, wrapping the common configurations. */ +typedef union +{ + ble_common_cfg_vs_uuid_t vs_uuid_cfg; /**< Vendor Specific base UUID configuration, cfg_id is @ref BLE_COMMON_CFG_VS_UUID. */ +} ble_common_cfg_t; + +/**@brief BLE Configuration type, wrapping the module specific configurations. */ +typedef union +{ + ble_conn_cfg_t conn_cfg; /**< Connection specific configurations, cfg_id in @ref BLE_CONN_CFGS series. */ + ble_common_cfg_t common_cfg; /**< Global common configurations, cfg_id in @ref BLE_COMMON_CFGS series. */ + ble_gap_cfg_t gap_cfg; /**< Global GAP configurations, cfg_id in @ref BLE_GAP_CFGS series. */ + ble_gatts_cfg_t gatts_cfg; /**< Global GATTS configuration, cfg_id in @ref BLE_GATTS_CFGS series. */ +} ble_cfg_t; + +/** @} */ + +/** @addtogroup BLE_COMMON_FUNCTIONS Functions + * @{ */ + +/**@brief Enable the BLE stack + * + * @param[in, out] p_app_ram_base Pointer to a variable containing the start address of the + * application RAM region (APP_RAM_BASE). On return, this will + * contain the minimum start address of the application RAM region + * required by the SoftDevice for this configuration. + * @warning After this call, the SoftDevice may generate several events. The list of events provided + * below require the application to initiate a SoftDevice API call. The corresponding API call + * is referenced in the event documentation. + * If the application fails to do so, the BLE connection may timeout, or the SoftDevice may stop + * communicating with the peer device. + * - @ref BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST + * - @ref BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST + * - @ref BLE_GAP_EVT_PHY_UPDATE_REQUEST + * - @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST + * - @ref BLE_GAP_EVT_SEC_INFO_REQUEST + * - @ref BLE_GAP_EVT_SEC_REQUEST + * - @ref BLE_GAP_EVT_AUTH_KEY_REQUEST + * - @ref BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST + * - @ref BLE_EVT_USER_MEM_REQUEST + * - @ref BLE_L2CAP_EVT_CH_SETUP_REQUEST + * + * @note The memory requirement for a specific configuration will not increase between SoftDevices + * with the same major version number. + * + * @note At runtime the IC's RAM is split into 2 regions: The SoftDevice RAM region is located + * between 0x20000000 and APP_RAM_BASE-1 and the application's RAM region is located between + * APP_RAM_BASE and the start of the call stack. + * + * @details This call initializes the BLE stack, no BLE related function other than @ref + * sd_ble_cfg_set can be called before this one. + * + * @mscs + * @mmsc{@ref BLE_COMMON_ENABLE} + * @endmscs + * + * @retval ::NRF_SUCCESS The BLE stack has been initialized successfully. + * @retval ::NRF_ERROR_INVALID_STATE The BLE stack had already been initialized and cannot be reinitialized. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid or not sufficiently aligned pointer supplied. + * @retval ::NRF_ERROR_NO_MEM One or more of the following is true: + * - The amount of memory assigned to the SoftDevice by *p_app_ram_base is not + * large enough to fit this configuration's memory requirement. Check *p_app_ram_base + * and set the start address of the application RAM region accordingly. + * - Dynamic part of the SoftDevice RAM region is larger then 64 kB which + * is currently not supported. + * @retval ::NRF_ERROR_RESOURCES The total number of L2CAP Channels configured using @ref sd_ble_cfg_set is too large. + */ +SVCALL(SD_BLE_ENABLE, uint32_t, sd_ble_enable(uint32_t * p_app_ram_base)); + +/**@brief Add configurations for the BLE stack + * + * @param[in] cfg_id Config ID, see @ref BLE_CONN_CFGS, @ref BLE_COMMON_CFGS, @ref + * BLE_GAP_CFGS or @ref BLE_GATTS_CFGS. + * @param[in] p_cfg Pointer to a ble_cfg_t structure containing the configuration value. + * @param[in] app_ram_base The start address of the application RAM region (APP_RAM_BASE). + * See @ref sd_ble_enable for details about APP_RAM_BASE. + * + * @note The memory requirement for a specific configuration will not increase between SoftDevices + * with the same major version number. + * + * @note If a configuration is set more than once, the last one set is the one that takes effect on + * @ref sd_ble_enable. + * + * @note Any part of the BLE stack that is NOT configured with @ref sd_ble_cfg_set will have default + * configuration. + * + * @note @ref sd_ble_cfg_set may be called at any time when the SoftDevice is enabled (see @ref + * sd_softdevice_enable) while the BLE part of the SoftDevice is not enabled (see @ref + * sd_ble_enable). + * + * @note Error codes for the configurations are described in the configuration structs. + * + * @mscs + * @mmsc{@ref BLE_COMMON_ENABLE} + * @endmscs + * + * @retval ::NRF_SUCCESS The configuration has been added successfully. + * @retval ::NRF_ERROR_INVALID_STATE The BLE stack had already been initialized. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid or not sufficiently aligned pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid cfg_id supplied. + * @retval ::NRF_ERROR_NO_MEM The amount of memory assigned to the SoftDevice by app_ram_base is not + * large enough to fit this configuration's memory requirement. + */ +SVCALL(SD_BLE_CFG_SET, uint32_t, sd_ble_cfg_set(uint32_t cfg_id, ble_cfg_t const * p_cfg, uint32_t app_ram_base)); + +/**@brief Get an event from the pending events queue. + * + * @param[out] p_dest Pointer to buffer to be filled in with an event, or NULL to retrieve the event length. + * This buffer must be aligned to the extend defined by @ref BLE_EVT_PTR_ALIGNMENT. + * The buffer should be interpreted as a @ref ble_evt_t struct. + * @param[in, out] p_len Pointer the length of the buffer, on return it is filled with the event length. + * + * @details This call allows the application to pull a BLE event from the BLE stack. The application is signaled that + * an event is available from the BLE stack by the triggering of the SD_EVT_IRQn interrupt. + * The application is free to choose whether to call this function from thread mode (main context) or directly from the + * Interrupt Service Routine that maps to SD_EVT_IRQn. In any case however, and because the BLE stack runs at a higher + * priority than the application, this function should be called in a loop (until @ref NRF_ERROR_NOT_FOUND is returned) + * every time SD_EVT_IRQn is raised to ensure that all available events are pulled from the BLE stack. Failure to do so + * could potentially leave events in the internal queue without the application being aware of this fact. + * + * Sizing the p_dest buffer is equally important, since the application needs to provide all the memory necessary for the event to + * be copied into application memory. If the buffer provided is not large enough to fit the entire contents of the event, + * @ref NRF_ERROR_DATA_SIZE will be returned and the application can then call again with a larger buffer size. + * The maximum possible event length is defined by @ref BLE_EVT_LEN_MAX. The application may also "peek" the event length + * by providing p_dest as a NULL pointer and inspecting the value of *p_len upon return: + * + * \code + * uint16_t len; + * errcode = sd_ble_evt_get(NULL, &len); + * \endcode + * + * @mscs + * @mmsc{@ref BLE_COMMON_IRQ_EVT_MSC} + * @mmsc{@ref BLE_COMMON_THREAD_EVT_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Event pulled and stored into the supplied buffer. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid or not sufficiently aligned pointer supplied. + * @retval ::NRF_ERROR_NOT_FOUND No events ready to be pulled. + * @retval ::NRF_ERROR_DATA_SIZE Event ready but could not fit into the supplied buffer. + */ +SVCALL(SD_BLE_EVT_GET, uint32_t, sd_ble_evt_get(uint8_t *p_dest, uint16_t *p_len)); + + +/**@brief Add a Vendor Specific base UUID. + * + * @details This call enables the application to add a Vendor Specific base UUID to the BLE stack's table, for later + * use with all other modules and APIs. This then allows the application to use the shorter, 24-bit @ref ble_uuid_t + * format when dealing with both 16-bit and 128-bit UUIDs without having to check for lengths and having split code + * paths. This is accomplished by extending the grouping mechanism that the Bluetooth SIG standard base UUID uses + * for all other 128-bit UUIDs. The type field in the @ref ble_uuid_t structure is an index (relative to + * @ref BLE_UUID_TYPE_VENDOR_BEGIN) to the table populated by multiple calls to this function, and the UUID field + * in the same structure contains the 2 bytes at indexes 12 and 13. The number of possible 128-bit UUIDs available to + * the application is therefore the number of Vendor Specific UUIDs added with the help of this function times 65536, + * although restricted to modifying bytes 12 and 13 for each of the entries in the supplied array. + * + * @note Bytes 12 and 13 of the provided UUID will not be used internally, since those are always replaced by + * the 16-bit uuid field in @ref ble_uuid_t. + * + * @note If a UUID is already present in the BLE stack's internal table, the corresponding index will be returned in + * p_uuid_type along with an @ref NRF_SUCCESS error code. + * + * @param[in] p_vs_uuid Pointer to a 16-octet (128-bit) little endian Vendor Specific base UUID disregarding + * bytes 12 and 13. + * @param[out] p_uuid_type Pointer to a uint8_t where the type field in @ref ble_uuid_t corresponding to this UUID will be stored. + * + * @retval ::NRF_SUCCESS Successfully added the Vendor Specific base UUID. + * @retval ::NRF_ERROR_INVALID_ADDR If p_vs_uuid or p_uuid_type is NULL or invalid. + * @retval ::NRF_ERROR_NO_MEM If there are no more free slots for VS UUIDs. + */ +SVCALL(SD_BLE_UUID_VS_ADD, uint32_t, sd_ble_uuid_vs_add(ble_uuid128_t const *p_vs_uuid, uint8_t *p_uuid_type)); + + +/**@brief Remove a Vendor Specific base UUID. + * + * @details This call removes a Vendor Specific base UUID. This function allows + * the application to reuse memory allocated for Vendor Specific base UUIDs. + * + * @note Currently this function can only be called with a p_uuid_type set to @ref BLE_UUID_TYPE_UNKNOWN or the last added UUID type. + * + * @param[inout] p_uuid_type Pointer to a uint8_t where its value matches the UUID type in @ref ble_uuid_t::type to be removed. + * If the type is set to @ref BLE_UUID_TYPE_UNKNOWN, or the pointer is NULL, the last Vendor Specific + * base UUID will be removed. If the function returns successfully, the UUID type that was removed will + * be written back to @p p_uuid_type. If function returns with a failure, it contains the last type that + * is in use by the ATT Server. + * + * @retval ::NRF_SUCCESS Successfully removed the Vendor Specific base UUID. + * @retval ::NRF_ERROR_INVALID_ADDR If p_uuid_type is invalid. + * @retval ::NRF_ERROR_INVALID_PARAM If p_uuid_type points to a non-valid UUID type. + * @retval ::NRF_ERROR_FORBIDDEN If the Vendor Specific base UUID is in use by the ATT Server. + */ +SVCALL(SD_BLE_UUID_VS_REMOVE, uint32_t, sd_ble_uuid_vs_remove(uint8_t *p_uuid_type)); + + +/** @brief Decode little endian raw UUID bytes (16-bit or 128-bit) into a 24 bit @ref ble_uuid_t structure. + * + * @details The raw UUID bytes excluding bytes 12 and 13 (i.e. bytes 0-11 and 14-15) of p_uuid_le are compared + * to the corresponding ones in each entry of the table of Vendor Specific base UUIDs + * to look for a match. If there is such a match, bytes 12 and 13 are returned as p_uuid->uuid and the index + * relative to @ref BLE_UUID_TYPE_VENDOR_BEGIN as p_uuid->type. + * + * @note If the UUID length supplied is 2, then the type set by this call will always be @ref BLE_UUID_TYPE_BLE. + * + * @param[in] uuid_le_len Length in bytes of the buffer pointed to by p_uuid_le (must be 2 or 16 bytes). + * @param[in] p_uuid_le Pointer pointing to little endian raw UUID bytes. + * @param[out] p_uuid Pointer to a @ref ble_uuid_t structure to be filled in. + * + * @retval ::NRF_SUCCESS Successfully decoded into the @ref ble_uuid_t structure. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_LENGTH Invalid UUID length. + * @retval ::NRF_ERROR_NOT_FOUND For a 128-bit UUID, no match in the populated table of UUIDs. + */ +SVCALL(SD_BLE_UUID_DECODE, uint32_t, sd_ble_uuid_decode(uint8_t uuid_le_len, uint8_t const *p_uuid_le, ble_uuid_t *p_uuid)); + + +/** @brief Encode a @ref ble_uuid_t structure into little endian raw UUID bytes (16-bit or 128-bit). + * + * @note The pointer to the destination buffer p_uuid_le may be NULL, in which case only the validity and size of p_uuid is computed. + * + * @param[in] p_uuid Pointer to a @ref ble_uuid_t structure that will be encoded into bytes. + * @param[out] p_uuid_le_len Pointer to a uint8_t that will be filled with the encoded length (2 or 16 bytes). + * @param[out] p_uuid_le Pointer to a buffer where the little endian raw UUID bytes (2 or 16) will be stored. + * + * @retval ::NRF_SUCCESS Successfully encoded into the buffer. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid UUID type. + */ +SVCALL(SD_BLE_UUID_ENCODE, uint32_t, sd_ble_uuid_encode(ble_uuid_t const *p_uuid, uint8_t *p_uuid_le_len, uint8_t *p_uuid_le)); + + +/**@brief Get Version Information. + * + * @details This call allows the application to get the BLE stack version information. + * + * @param[out] p_version Pointer to a ble_version_t structure to be filled in. + * + * @retval ::NRF_SUCCESS Version information stored successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_BUSY The BLE stack is busy (typically doing a locally-initiated disconnection procedure). + */ +SVCALL(SD_BLE_VERSION_GET, uint32_t, sd_ble_version_get(ble_version_t *p_version)); + + +/**@brief Provide a user memory block. + * + * @note This call can only be used as a response to a @ref BLE_EVT_USER_MEM_REQUEST event issued to the application. + * + * @param[in] conn_handle Connection handle. + * @param[in] p_block Pointer to a user memory block structure or NULL if memory is managed by the application. + * + * @mscs + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_PEER_CANCEL_MSC} + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_AUTH_MSC} + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_NOAUTH_MSC} + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_BUF_AUTH_MSC} + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_BUF_NOAUTH_MSC} + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_QUEUE_FULL_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Successfully queued a response to the peer. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_LENGTH Invalid user memory block length supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection state or no user memory request pending. + */ +SVCALL(SD_BLE_USER_MEM_REPLY, uint32_t, sd_ble_user_mem_reply(uint16_t conn_handle, ble_user_mem_block_t const *p_block)); + +/**@brief Set a BLE option. + * + * @details This call allows the application to set the value of an option. + * + * @param[in] opt_id Option ID, see @ref BLE_COMMON_OPTS, @ref BLE_GAP_OPTS, and @ref BLE_GATTC_OPTS. + * @param[in] p_opt Pointer to a @ref ble_opt_t structure containing the option value. + * + * @retval ::NRF_SUCCESS Option set successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check parameter limits and constraints. + * @retval ::NRF_ERROR_INVALID_STATE Unable to set the parameter at this time. + * @retval ::NRF_ERROR_BUSY The BLE stack is busy or the previous procedure has not completed. + */ +SVCALL(SD_BLE_OPT_SET, uint32_t, sd_ble_opt_set(uint32_t opt_id, ble_opt_t const *p_opt)); + + +/**@brief Get a BLE option. + * + * @details This call allows the application to retrieve the value of an option. + * + * @param[in] opt_id Option ID, see @ref BLE_COMMON_OPTS and @ref BLE_GAP_OPTS. + * @param[out] p_opt Pointer to a ble_opt_t structure to be filled in. + * + * @retval ::NRF_SUCCESS Option retrieved successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check parameter limits and constraints. + * @retval ::NRF_ERROR_INVALID_STATE Unable to retrieve the parameter at this time. + * @retval ::NRF_ERROR_BUSY The BLE stack is busy or the previous procedure has not completed. + * @retval ::NRF_ERROR_NOT_SUPPORTED This option is not supported. + * + */ +SVCALL(SD_BLE_OPT_GET, uint32_t, sd_ble_opt_get(uint32_t opt_id, ble_opt_t *p_opt)); + +/** @} */ +#ifdef __cplusplus +} +#endif +#endif /* BLE_H__ */ + +/** + @} + @} +*/ diff --git a/components/softdevice/s140/headers/ble_err.h b/components/softdevice/s140/headers/ble_err.h new file mode 100644 index 0000000..1b4820d --- /dev/null +++ b/components/softdevice/s140/headers/ble_err.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @addtogroup BLE_COMMON + @{ + @addtogroup nrf_error + @{ + @ingroup BLE_COMMON + @} + + @defgroup ble_err General error codes + @{ + + @brief General error code definitions for the BLE API. + + @ingroup BLE_COMMON +*/ +#ifndef NRF_BLE_ERR_H__ +#define NRF_BLE_ERR_H__ + +#include "nrf_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* @defgroup BLE_ERRORS Error Codes + * @{ */ +#define BLE_ERROR_NOT_ENABLED (NRF_ERROR_STK_BASE_NUM+0x001) /**< @ref sd_ble_enable has not been called. */ +#define BLE_ERROR_INVALID_CONN_HANDLE (NRF_ERROR_STK_BASE_NUM+0x002) /**< Invalid connection handle. */ +#define BLE_ERROR_INVALID_ATTR_HANDLE (NRF_ERROR_STK_BASE_NUM+0x003) /**< Invalid attribute handle. */ +#define BLE_ERROR_INVALID_ADV_HANDLE (NRF_ERROR_STK_BASE_NUM+0x004) /**< Invalid advertising handle. */ +#define BLE_ERROR_INVALID_ROLE (NRF_ERROR_STK_BASE_NUM+0x005) /**< Invalid role. */ +#define BLE_ERROR_BLOCKED_BY_OTHER_LINKS (NRF_ERROR_STK_BASE_NUM+0x006) /**< The attempt to change link settings failed due to the scheduling of other links. */ +/** @} */ + + +/** @defgroup BLE_ERROR_SUBRANGES Module specific error code subranges + * @brief Assignment of subranges for module specific error codes. + * @note For specific error codes, see ble_.h or ble_error_.h. + * @{ */ +#define NRF_L2CAP_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x100) /**< L2CAP specific errors. */ +#define NRF_GAP_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x200) /**< GAP specific errors. */ +#define NRF_GATTC_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x300) /**< GATT client specific errors. */ +#define NRF_GATTS_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x400) /**< GATT server specific errors. */ +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif + + +/** + @} + @} +*/ diff --git a/components/softdevice/s140/headers/ble_gap.h b/components/softdevice/s140/headers/ble_gap.h new file mode 100644 index 0000000..5eae97b --- /dev/null +++ b/components/softdevice/s140/headers/ble_gap.h @@ -0,0 +1,2853 @@ +/* + * Copyright (c) 2011 - 2020, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @addtogroup BLE_GAP Generic Access Profile (GAP) + @{ + @brief Definitions and prototypes for the GAP interface. + */ + +#ifndef BLE_GAP_H__ +#define BLE_GAP_H__ + +#include +#include "nrf_svc.h" +#include "nrf_error.h" +#include "ble_hci.h" +#include "ble_ranges.h" +#include "ble_types.h" +#include "ble_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@addtogroup BLE_GAP_ENUMERATIONS Enumerations + * @{ */ + +/**@brief GAP API SVC numbers. + */ +enum BLE_GAP_SVCS +{ + SD_BLE_GAP_ADDR_SET = BLE_GAP_SVC_BASE, /**< Set own Bluetooth Address. */ + SD_BLE_GAP_ADDR_GET = BLE_GAP_SVC_BASE + 1, /**< Get own Bluetooth Address. */ + SD_BLE_GAP_WHITELIST_SET = BLE_GAP_SVC_BASE + 2, /**< Set active whitelist. */ + SD_BLE_GAP_DEVICE_IDENTITIES_SET = BLE_GAP_SVC_BASE + 3, /**< Set device identity list. */ + SD_BLE_GAP_PRIVACY_SET = BLE_GAP_SVC_BASE + 4, /**< Set Privacy settings*/ + SD_BLE_GAP_PRIVACY_GET = BLE_GAP_SVC_BASE + 5, /**< Get Privacy settings*/ + SD_BLE_GAP_ADV_SET_CONFIGURE = BLE_GAP_SVC_BASE + 6, /**< Configure an advertising set. */ + SD_BLE_GAP_ADV_START = BLE_GAP_SVC_BASE + 7, /**< Start Advertising. */ + SD_BLE_GAP_ADV_STOP = BLE_GAP_SVC_BASE + 8, /**< Stop Advertising. */ + SD_BLE_GAP_CONN_PARAM_UPDATE = BLE_GAP_SVC_BASE + 9, /**< Connection Parameter Update. */ + SD_BLE_GAP_DISCONNECT = BLE_GAP_SVC_BASE + 10, /**< Disconnect. */ + SD_BLE_GAP_TX_POWER_SET = BLE_GAP_SVC_BASE + 11, /**< Set TX Power. */ + SD_BLE_GAP_APPEARANCE_SET = BLE_GAP_SVC_BASE + 12, /**< Set Appearance. */ + SD_BLE_GAP_APPEARANCE_GET = BLE_GAP_SVC_BASE + 13, /**< Get Appearance. */ + SD_BLE_GAP_PPCP_SET = BLE_GAP_SVC_BASE + 14, /**< Set PPCP. */ + SD_BLE_GAP_PPCP_GET = BLE_GAP_SVC_BASE + 15, /**< Get PPCP. */ + SD_BLE_GAP_DEVICE_NAME_SET = BLE_GAP_SVC_BASE + 16, /**< Set Device Name. */ + SD_BLE_GAP_DEVICE_NAME_GET = BLE_GAP_SVC_BASE + 17, /**< Get Device Name. */ + SD_BLE_GAP_AUTHENTICATE = BLE_GAP_SVC_BASE + 18, /**< Initiate Pairing/Bonding. */ + SD_BLE_GAP_SEC_PARAMS_REPLY = BLE_GAP_SVC_BASE + 19, /**< Reply with Security Parameters. */ + SD_BLE_GAP_AUTH_KEY_REPLY = BLE_GAP_SVC_BASE + 20, /**< Reply with an authentication key. */ + SD_BLE_GAP_LESC_DHKEY_REPLY = BLE_GAP_SVC_BASE + 21, /**< Reply with an LE Secure Connections DHKey. */ + SD_BLE_GAP_KEYPRESS_NOTIFY = BLE_GAP_SVC_BASE + 22, /**< Notify of a keypress during an authentication procedure. */ + SD_BLE_GAP_LESC_OOB_DATA_GET = BLE_GAP_SVC_BASE + 23, /**< Get the local LE Secure Connections OOB data. */ + SD_BLE_GAP_LESC_OOB_DATA_SET = BLE_GAP_SVC_BASE + 24, /**< Set the remote LE Secure Connections OOB data. */ + SD_BLE_GAP_ENCRYPT = BLE_GAP_SVC_BASE + 25, /**< Initiate encryption procedure. */ + SD_BLE_GAP_SEC_INFO_REPLY = BLE_GAP_SVC_BASE + 26, /**< Reply with Security Information. */ + SD_BLE_GAP_CONN_SEC_GET = BLE_GAP_SVC_BASE + 27, /**< Obtain connection security level. */ + SD_BLE_GAP_RSSI_START = BLE_GAP_SVC_BASE + 28, /**< Start reporting of changes in RSSI. */ + SD_BLE_GAP_RSSI_STOP = BLE_GAP_SVC_BASE + 29, /**< Stop reporting of changes in RSSI. */ + SD_BLE_GAP_SCAN_START = BLE_GAP_SVC_BASE + 30, /**< Start Scanning. */ + SD_BLE_GAP_SCAN_STOP = BLE_GAP_SVC_BASE + 31, /**< Stop Scanning. */ + SD_BLE_GAP_CONNECT = BLE_GAP_SVC_BASE + 32, /**< Connect. */ + SD_BLE_GAP_CONNECT_CANCEL = BLE_GAP_SVC_BASE + 33, /**< Cancel ongoing connection procedure. */ + SD_BLE_GAP_RSSI_GET = BLE_GAP_SVC_BASE + 34, /**< Get the last RSSI sample. */ + SD_BLE_GAP_PHY_UPDATE = BLE_GAP_SVC_BASE + 35, /**< Initiate or respond to a PHY Update Procedure. */ + SD_BLE_GAP_DATA_LENGTH_UPDATE = BLE_GAP_SVC_BASE + 36, /**< Initiate or respond to a Data Length Update Procedure. */ + SD_BLE_GAP_QOS_CHANNEL_SURVEY_START = BLE_GAP_SVC_BASE + 37, /**< Start Quality of Service (QoS) channel survey module. */ + SD_BLE_GAP_QOS_CHANNEL_SURVEY_STOP = BLE_GAP_SVC_BASE + 38, /**< Stop Quality of Service (QoS) channel survey module. */ + SD_BLE_GAP_ADV_ADDR_GET = BLE_GAP_SVC_BASE + 39, /**< Get the Address used on air while Advertising. */ + SD_BLE_GAP_NEXT_CONN_EVT_COUNTER_GET = BLE_GAP_SVC_BASE + 40, /**< Get the next connection event counter. */ + SD_BLE_GAP_CONN_EVT_TRIGGER_START = BLE_GAP_SVC_BASE + 41, /** Start triggering a given task on connection event start. */ + SD_BLE_GAP_CONN_EVT_TRIGGER_STOP = BLE_GAP_SVC_BASE + 42, /** Stop triggering the task configured using @ref sd_ble_gap_conn_evt_trigger_start. */ +}; + +/**@brief GAP Event IDs. + * IDs that uniquely identify an event coming from the stack to the application. + */ +enum BLE_GAP_EVTS +{ + BLE_GAP_EVT_CONNECTED = BLE_GAP_EVT_BASE, /**< Connected to peer. \n See @ref ble_gap_evt_connected_t */ + BLE_GAP_EVT_DISCONNECTED = BLE_GAP_EVT_BASE + 1, /**< Disconnected from peer. \n See @ref ble_gap_evt_disconnected_t. */ + BLE_GAP_EVT_CONN_PARAM_UPDATE = BLE_GAP_EVT_BASE + 2, /**< Connection Parameters updated. \n See @ref ble_gap_evt_conn_param_update_t. */ + BLE_GAP_EVT_SEC_PARAMS_REQUEST = BLE_GAP_EVT_BASE + 3, /**< Request to provide security parameters. \n Reply with @ref sd_ble_gap_sec_params_reply. \n See @ref ble_gap_evt_sec_params_request_t. */ + BLE_GAP_EVT_SEC_INFO_REQUEST = BLE_GAP_EVT_BASE + 4, /**< Request to provide security information. \n Reply with @ref sd_ble_gap_sec_info_reply. \n See @ref ble_gap_evt_sec_info_request_t. */ + BLE_GAP_EVT_PASSKEY_DISPLAY = BLE_GAP_EVT_BASE + 5, /**< Request to display a passkey to the user. \n In LESC Numeric Comparison, reply with @ref sd_ble_gap_auth_key_reply. \n See @ref ble_gap_evt_passkey_display_t. */ + BLE_GAP_EVT_KEY_PRESSED = BLE_GAP_EVT_BASE + 6, /**< Notification of a keypress on the remote device.\n See @ref ble_gap_evt_key_pressed_t */ + BLE_GAP_EVT_AUTH_KEY_REQUEST = BLE_GAP_EVT_BASE + 7, /**< Request to provide an authentication key. \n Reply with @ref sd_ble_gap_auth_key_reply. \n See @ref ble_gap_evt_auth_key_request_t. */ + BLE_GAP_EVT_LESC_DHKEY_REQUEST = BLE_GAP_EVT_BASE + 8, /**< Request to calculate an LE Secure Connections DHKey. \n Reply with @ref sd_ble_gap_lesc_dhkey_reply. \n See @ref ble_gap_evt_lesc_dhkey_request_t */ + BLE_GAP_EVT_AUTH_STATUS = BLE_GAP_EVT_BASE + 9, /**< Authentication procedure completed with status. \n See @ref ble_gap_evt_auth_status_t. */ + BLE_GAP_EVT_CONN_SEC_UPDATE = BLE_GAP_EVT_BASE + 10, /**< Connection security updated. \n See @ref ble_gap_evt_conn_sec_update_t. */ + BLE_GAP_EVT_TIMEOUT = BLE_GAP_EVT_BASE + 11, /**< Timeout expired. \n See @ref ble_gap_evt_timeout_t. */ + BLE_GAP_EVT_RSSI_CHANGED = BLE_GAP_EVT_BASE + 12, /**< RSSI report. \n See @ref ble_gap_evt_rssi_changed_t. */ + BLE_GAP_EVT_ADV_REPORT = BLE_GAP_EVT_BASE + 13, /**< Advertising report. \n See @ref ble_gap_evt_adv_report_t. */ + BLE_GAP_EVT_SEC_REQUEST = BLE_GAP_EVT_BASE + 14, /**< Security Request. \n Reply with @ref sd_ble_gap_authenticate + \n or with @ref sd_ble_gap_encrypt if required security information is available +. \n See @ref ble_gap_evt_sec_request_t. */ + BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST = BLE_GAP_EVT_BASE + 15, /**< Connection Parameter Update Request. \n Reply with @ref sd_ble_gap_conn_param_update. \n See @ref ble_gap_evt_conn_param_update_request_t. */ + BLE_GAP_EVT_SCAN_REQ_REPORT = BLE_GAP_EVT_BASE + 16, /**< Scan request report. \n See @ref ble_gap_evt_scan_req_report_t. */ + BLE_GAP_EVT_PHY_UPDATE_REQUEST = BLE_GAP_EVT_BASE + 17, /**< PHY Update Request. \n Reply with @ref sd_ble_gap_phy_update. \n See @ref ble_gap_evt_phy_update_request_t. */ + BLE_GAP_EVT_PHY_UPDATE = BLE_GAP_EVT_BASE + 18, /**< PHY Update Procedure is complete. \n See @ref ble_gap_evt_phy_update_t. */ + BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST = BLE_GAP_EVT_BASE + 19, /**< Data Length Update Request. \n Reply with @ref sd_ble_gap_data_length_update. \n See @ref ble_gap_evt_data_length_update_request_t. */ + BLE_GAP_EVT_DATA_LENGTH_UPDATE = BLE_GAP_EVT_BASE + 20, /**< LL Data Channel PDU payload length updated. \n See @ref ble_gap_evt_data_length_update_t. */ + BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT = BLE_GAP_EVT_BASE + 21, /**< Channel survey report. \n See @ref ble_gap_evt_qos_channel_survey_report_t. */ + BLE_GAP_EVT_ADV_SET_TERMINATED = BLE_GAP_EVT_BASE + 22, /**< Advertising set terminated. \n See @ref ble_gap_evt_adv_set_terminated_t. */ +}; + +/**@brief GAP Option IDs. + * IDs that uniquely identify a GAP option. + */ +enum BLE_GAP_OPTS +{ + BLE_GAP_OPT_CH_MAP = BLE_GAP_OPT_BASE, /**< Channel Map. @ref ble_gap_opt_ch_map_t */ + BLE_GAP_OPT_LOCAL_CONN_LATENCY = BLE_GAP_OPT_BASE + 1, /**< Local connection latency. @ref ble_gap_opt_local_conn_latency_t */ + BLE_GAP_OPT_PASSKEY = BLE_GAP_OPT_BASE + 2, /**< Set passkey. @ref ble_gap_opt_passkey_t */ + BLE_GAP_OPT_COMPAT_MODE_1 = BLE_GAP_OPT_BASE + 3, /**< Compatibility mode. @ref ble_gap_opt_compat_mode_1_t */ + BLE_GAP_OPT_AUTH_PAYLOAD_TIMEOUT = BLE_GAP_OPT_BASE + 4, /**< Set Authenticated payload timeout. @ref ble_gap_opt_auth_payload_timeout_t */ + BLE_GAP_OPT_SLAVE_LATENCY_DISABLE = BLE_GAP_OPT_BASE + 5, /**< Disable slave latency. @ref ble_gap_opt_slave_latency_disable_t */ +}; + +/**@brief GAP Configuration IDs. + * + * IDs that uniquely identify a GAP configuration. + */ +enum BLE_GAP_CFGS +{ + BLE_GAP_CFG_ROLE_COUNT = BLE_GAP_CFG_BASE, /**< Role count configuration. */ + BLE_GAP_CFG_DEVICE_NAME = BLE_GAP_CFG_BASE + 1, /**< Device name configuration. */ + BLE_GAP_CFG_PPCP_INCL_CONFIG = BLE_GAP_CFG_BASE + 2, /**< Peripheral Preferred Connection Parameters characteristic + inclusion configuration. */ + BLE_GAP_CFG_CAR_INCL_CONFIG = BLE_GAP_CFG_BASE + 3, /**< Central Address Resolution characteristic + inclusion configuration. */ +}; + +/**@brief GAP TX Power roles. + */ +enum BLE_GAP_TX_POWER_ROLES +{ + BLE_GAP_TX_POWER_ROLE_ADV = 1, /**< Advertiser role. */ + BLE_GAP_TX_POWER_ROLE_SCAN_INIT = 2, /**< Scanner and initiator role. */ + BLE_GAP_TX_POWER_ROLE_CONN = 3, /**< Connection role. */ +}; + +/** @} */ + +/**@addtogroup BLE_GAP_DEFINES Defines + * @{ */ + +/**@defgroup BLE_ERRORS_GAP SVC return values specific to GAP + * @{ */ +#define BLE_ERROR_GAP_UUID_LIST_MISMATCH (NRF_GAP_ERR_BASE + 0x000) /**< UUID list does not contain an integral number of UUIDs. */ +#define BLE_ERROR_GAP_DISCOVERABLE_WITH_WHITELIST (NRF_GAP_ERR_BASE + 0x001) /**< Use of Whitelist not permitted with discoverable advertising. */ +#define BLE_ERROR_GAP_INVALID_BLE_ADDR (NRF_GAP_ERR_BASE + 0x002) /**< The upper two bits of the address do not correspond to the specified address type. */ +#define BLE_ERROR_GAP_WHITELIST_IN_USE (NRF_GAP_ERR_BASE + 0x003) /**< Attempt to modify the whitelist while already in use by another operation. */ +#define BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE (NRF_GAP_ERR_BASE + 0x004) /**< Attempt to modify the device identity list while already in use by another operation. */ +#define BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE (NRF_GAP_ERR_BASE + 0x005) /**< The device identity list contains entries with duplicate identity addresses. */ +/**@} */ + + +/**@defgroup BLE_GAP_ROLES GAP Roles + * @{ */ +#define BLE_GAP_ROLE_INVALID 0x0 /**< Invalid Role. */ +#define BLE_GAP_ROLE_PERIPH 0x1 /**< Peripheral Role. */ +#define BLE_GAP_ROLE_CENTRAL 0x2 /**< Central Role. */ +/**@} */ + + +/**@defgroup BLE_GAP_TIMEOUT_SOURCES GAP Timeout sources + * @{ */ +#define BLE_GAP_TIMEOUT_SRC_SCAN 0x01 /**< Scanning timeout. */ +#define BLE_GAP_TIMEOUT_SRC_CONN 0x02 /**< Connection timeout. */ +#define BLE_GAP_TIMEOUT_SRC_AUTH_PAYLOAD 0x03 /**< Authenticated payload timeout. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADDR_TYPES GAP Address types + * @{ */ +#define BLE_GAP_ADDR_TYPE_PUBLIC 0x00 /**< Public (identity) address.*/ +#define BLE_GAP_ADDR_TYPE_RANDOM_STATIC 0x01 /**< Random static (identity) address. */ +#define BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE 0x02 /**< Random private resolvable address. */ +#define BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE 0x03 /**< Random private non-resolvable address. */ +#define BLE_GAP_ADDR_TYPE_ANONYMOUS 0x7F /**< An advertiser may advertise without its address. + This type of advertising is called anonymous. */ +/**@} */ + + +/**@brief The default interval in seconds at which a private address is refreshed. */ +#define BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S (900) /* 15 minutes. */ +/**@brief The maximum interval in seconds at which a private address can be refreshed. */ +#define BLE_GAP_MAX_PRIVATE_ADDR_CYCLE_INTERVAL_S (41400) /* 11 hours 30 minutes. */ + + +/** @brief BLE address length. */ +#define BLE_GAP_ADDR_LEN (6) + +/**@defgroup BLE_GAP_PRIVACY_MODES Privacy modes + * @{ */ +#define BLE_GAP_PRIVACY_MODE_OFF 0x00 /**< Device will send and accept its identity address for its own address. */ +#define BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY 0x01 /**< Device will send and accept only private addresses for its own address. */ +#define BLE_GAP_PRIVACY_MODE_NETWORK_PRIVACY 0x02 /**< Device will send and accept only private addresses for its own address, + and will not accept a peer using identity address as sender address when + the peer IRK is exchanged, non-zero and added to the identity list. */ +/**@} */ + +/** @brief Invalid power level. */ +#define BLE_GAP_POWER_LEVEL_INVALID 127 + +/** @brief Advertising set handle not set. */ +#define BLE_GAP_ADV_SET_HANDLE_NOT_SET (0xFF) + +/** @brief The default number of advertising sets. */ +#define BLE_GAP_ADV_SET_COUNT_DEFAULT (1) + +/** @brief The maximum number of advertising sets supported by this SoftDevice. */ +#define BLE_GAP_ADV_SET_COUNT_MAX (1) + +/**@defgroup BLE_GAP_ADV_SET_DATA_SIZES Advertising data sizes. + * @{ */ +#define BLE_GAP_ADV_SET_DATA_SIZE_MAX (31) /**< Maximum data length for an advertising set. + If more advertising data is required, use extended advertising instead. */ +#define BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED (255) /**< Maximum supported data length for an extended advertising set. */ + +#define BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED (238) /**< Maximum supported data length for an extended connectable advertising set. */ +/**@}. */ + +/** @brief Set ID not available in advertising report. */ +#define BLE_GAP_ADV_REPORT_SET_ID_NOT_AVAILABLE 0xFF + +/**@defgroup BLE_GAP_EVT_ADV_SET_TERMINATED_REASON GAP Advertising Set Terminated reasons + * @{ */ +#define BLE_GAP_EVT_ADV_SET_TERMINATED_REASON_TIMEOUT 0x01 /**< Timeout value reached. */ +#define BLE_GAP_EVT_ADV_SET_TERMINATED_REASON_LIMIT_REACHED 0x02 /**< @ref ble_gap_adv_params_t::max_adv_evts was reached. */ +/**@} */ + +/**@defgroup BLE_GAP_AD_TYPE_DEFINITIONS GAP Advertising and Scan Response Data format + * @note Found at https://www.bluetooth.org/Technical/AssignedNumbers/generic_access_profile.htm + * @{ */ +#define BLE_GAP_AD_TYPE_FLAGS 0x01 /**< Flags for discoverability. */ +#define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE 0x02 /**< Partial list of 16 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE 0x03 /**< Complete list of 16 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE 0x04 /**< Partial list of 32 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_COMPLETE 0x05 /**< Complete list of 32 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE 0x06 /**< Partial list of 128 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE 0x07 /**< Complete list of 128 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME 0x08 /**< Short local device name. */ +#define BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME 0x09 /**< Complete local device name. */ +#define BLE_GAP_AD_TYPE_TX_POWER_LEVEL 0x0A /**< Transmit power level. */ +#define BLE_GAP_AD_TYPE_CLASS_OF_DEVICE 0x0D /**< Class of device. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C 0x0E /**< Simple Pairing Hash C. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R 0x0F /**< Simple Pairing Randomizer R. */ +#define BLE_GAP_AD_TYPE_SECURITY_MANAGER_TK_VALUE 0x10 /**< Security Manager TK Value. */ +#define BLE_GAP_AD_TYPE_SECURITY_MANAGER_OOB_FLAGS 0x11 /**< Security Manager Out Of Band Flags. */ +#define BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE 0x12 /**< Slave Connection Interval Range. */ +#define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT 0x14 /**< List of 16-bit Service Solicitation UUIDs. */ +#define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT 0x15 /**< List of 128-bit Service Solicitation UUIDs. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA 0x16 /**< Service Data - 16-bit UUID. */ +#define BLE_GAP_AD_TYPE_PUBLIC_TARGET_ADDRESS 0x17 /**< Public Target Address. */ +#define BLE_GAP_AD_TYPE_RANDOM_TARGET_ADDRESS 0x18 /**< Random Target Address. */ +#define BLE_GAP_AD_TYPE_APPEARANCE 0x19 /**< Appearance. */ +#define BLE_GAP_AD_TYPE_ADVERTISING_INTERVAL 0x1A /**< Advertising Interval. */ +#define BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS 0x1B /**< LE Bluetooth Device Address. */ +#define BLE_GAP_AD_TYPE_LE_ROLE 0x1C /**< LE Role. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C256 0x1D /**< Simple Pairing Hash C-256. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R256 0x1E /**< Simple Pairing Randomizer R-256. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA_32BIT_UUID 0x20 /**< Service Data - 32-bit UUID. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA_128BIT_UUID 0x21 /**< Service Data - 128-bit UUID. */ +#define BLE_GAP_AD_TYPE_LESC_CONFIRMATION_VALUE 0x22 /**< LE Secure Connections Confirmation Value */ +#define BLE_GAP_AD_TYPE_LESC_RANDOM_VALUE 0x23 /**< LE Secure Connections Random Value */ +#define BLE_GAP_AD_TYPE_URI 0x24 /**< URI */ +#define BLE_GAP_AD_TYPE_3D_INFORMATION_DATA 0x3D /**< 3D Information Data. */ +#define BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA 0xFF /**< Manufacturer Specific Data. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADV_FLAGS GAP Advertisement Flags + * @{ */ +#define BLE_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE (0x01) /**< LE Limited Discoverable Mode. */ +#define BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE (0x02) /**< LE General Discoverable Mode. */ +#define BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED (0x04) /**< BR/EDR not supported. */ +#define BLE_GAP_ADV_FLAG_LE_BR_EDR_CONTROLLER (0x08) /**< Simultaneous LE and BR/EDR, Controller. */ +#define BLE_GAP_ADV_FLAG_LE_BR_EDR_HOST (0x10) /**< Simultaneous LE and BR/EDR, Host. */ +#define BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE (BLE_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) /**< LE Limited Discoverable Mode, BR/EDR not supported. */ +#define BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE (BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) /**< LE General Discoverable Mode, BR/EDR not supported. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADV_INTERVALS GAP Advertising interval max and min + * @{ */ +#define BLE_GAP_ADV_INTERVAL_MIN 0x000020 /**< Minimum Advertising interval in 625 us units, i.e. 20 ms. */ +#define BLE_GAP_ADV_INTERVAL_MAX 0x004000 /**< Maximum Advertising interval in 625 us units, i.e. 10.24 s. */ + /**@} */ + + +/**@defgroup BLE_GAP_SCAN_INTERVALS GAP Scan interval max and min + * @{ */ +#define BLE_GAP_SCAN_INTERVAL_MIN 0x0004 /**< Minimum Scan interval in 625 us units, i.e. 2.5 ms. */ +#define BLE_GAP_SCAN_INTERVAL_MAX 0xFFFF /**< Maximum Scan interval in 625 us units, i.e. 40,959.375 s. */ + /** @} */ + + +/**@defgroup BLE_GAP_SCAN_WINDOW GAP Scan window max and min + * @{ */ +#define BLE_GAP_SCAN_WINDOW_MIN 0x0004 /**< Minimum Scan window in 625 us units, i.e. 2.5 ms. */ +#define BLE_GAP_SCAN_WINDOW_MAX 0xFFFF /**< Maximum Scan window in 625 us units, i.e. 40,959.375 s. */ + /** @} */ + + +/**@defgroup BLE_GAP_SCAN_TIMEOUT GAP Scan timeout max and min + * @{ */ +#define BLE_GAP_SCAN_TIMEOUT_MIN 0x0001 /**< Minimum Scan timeout in 10 ms units, i.e 10 ms. */ +#define BLE_GAP_SCAN_TIMEOUT_UNLIMITED 0x0000 /**< Continue to scan forever. */ + /** @} */ + +/**@defgroup BLE_GAP_SCAN_BUFFER_SIZE GAP Minimum scanner buffer size + * + * Scan buffers are used for storing advertising data received from an advertiser. + * If ble_gap_scan_params_t::extended is set to 0, @ref BLE_GAP_SCAN_BUFFER_MIN is the minimum scan buffer length. + * else the minimum scan buffer size is @ref BLE_GAP_SCAN_BUFFER_EXTENDED_MIN. + * @{ */ +#define BLE_GAP_SCAN_BUFFER_MIN (31) /**< Minimum data length for an + advertising set. */ +#define BLE_GAP_SCAN_BUFFER_MAX (31) /**< Maximum data length for an + advertising set. */ +#define BLE_GAP_SCAN_BUFFER_EXTENDED_MIN (255) /**< Minimum data length for an + extended advertising set. */ +#define BLE_GAP_SCAN_BUFFER_EXTENDED_MAX (1650) /**< Maximum data length for an + extended advertising set. */ +#define BLE_GAP_SCAN_BUFFER_EXTENDED_MAX_SUPPORTED (255) /**< Maximum supported data length for + an extended advertising set. */ +/** @} */ + +/**@defgroup BLE_GAP_ADV_TYPES GAP Advertising types + * + * Advertising types defined in Bluetooth Core Specification v5.0, Vol 6, Part B, Section 4.4.2. + * + * The maximum advertising data length is defined by @ref BLE_GAP_ADV_SET_DATA_SIZE_MAX. + * The maximum supported data length for an extended advertiser is defined by + * @ref BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED + * Note that some of the advertising types do not support advertising data. Non-scannable types do not support + * scan response data. + * + * @{ */ +#define BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED 0x01 /**< Connectable and scannable undirected + advertising events. */ +#define BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED_HIGH_DUTY_CYCLE 0x02 /**< Connectable non-scannable directed advertising + events. Advertising interval is less that 3.75 ms. + Use this type for fast reconnections. + @note Advertising data is not supported. */ +#define BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED 0x03 /**< Connectable non-scannable directed advertising + events. + @note Advertising data is not supported. */ +#define BLE_GAP_ADV_TYPE_NONCONNECTABLE_SCANNABLE_UNDIRECTED 0x04 /**< Non-connectable scannable undirected + advertising events. */ +#define BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED 0x05 /**< Non-connectable non-scannable undirected + advertising events. */ +#define BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_UNDIRECTED 0x06 /**< Connectable non-scannable undirected advertising + events using extended advertising PDUs. */ +#define BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_DIRECTED 0x07 /**< Connectable non-scannable directed advertising + events using extended advertising PDUs. */ +#define BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_SCANNABLE_UNDIRECTED 0x08 /**< Non-connectable scannable undirected advertising + events using extended advertising PDUs. + @note Only scan response data is supported. */ +#define BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_SCANNABLE_DIRECTED 0x09 /**< Non-connectable scannable directed advertising + events using extended advertising PDUs. + @note Only scan response data is supported. */ +#define BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED 0x0A /**< Non-connectable non-scannable undirected advertising + events using extended advertising PDUs. */ +#define BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_NONSCANNABLE_DIRECTED 0x0B /**< Non-connectable non-scannable directed advertising + events using extended advertising PDUs. */ +/**@} */ + +/**@defgroup BLE_GAP_ADV_FILTER_POLICIES GAP Advertising filter policies + * @{ */ +#define BLE_GAP_ADV_FP_ANY 0x00 /**< Allow scan requests and connect requests from any device. */ +#define BLE_GAP_ADV_FP_FILTER_SCANREQ 0x01 /**< Filter scan requests with whitelist. */ +#define BLE_GAP_ADV_FP_FILTER_CONNREQ 0x02 /**< Filter connect requests with whitelist. */ +#define BLE_GAP_ADV_FP_FILTER_BOTH 0x03 /**< Filter both scan and connect requests with whitelist. */ +/**@} */ + +/**@defgroup BLE_GAP_ADV_DATA_STATUS GAP Advertising data status + * @{ */ +#define BLE_GAP_ADV_DATA_STATUS_COMPLETE 0x00 /**< All data in the advertising event have been received. */ +#define BLE_GAP_ADV_DATA_STATUS_INCOMPLETE_MORE_DATA 0x01 /**< More data to be received. + @note This value will only be used if + @ref ble_gap_scan_params_t::report_incomplete_evts and + @ref ble_gap_adv_report_type_t::extended_pdu are set to true. */ +#define BLE_GAP_ADV_DATA_STATUS_INCOMPLETE_TRUNCATED 0x02 /**< Incomplete data. Buffer size insufficient to receive more. + @note This value will only be used if + @ref ble_gap_adv_report_type_t::extended_pdu is set to true. */ +#define BLE_GAP_ADV_DATA_STATUS_INCOMPLETE_MISSED 0x03 /**< Failed to receive the remaining data. + @note This value will only be used if + @ref ble_gap_adv_report_type_t::extended_pdu is set to true. */ +/**@} */ + +/**@defgroup BLE_GAP_SCAN_FILTER_POLICIES GAP Scanner filter policies + * @{ */ +#define BLE_GAP_SCAN_FP_ACCEPT_ALL 0x00 /**< Accept all advertising packets except directed advertising packets + not addressed to this device. */ +#define BLE_GAP_SCAN_FP_WHITELIST 0x01 /**< Accept advertising packets from devices in the whitelist except directed + packets not addressed to this device. */ +#define BLE_GAP_SCAN_FP_ALL_NOT_RESOLVED_DIRECTED 0x02 /**< Accept all advertising packets specified in @ref BLE_GAP_SCAN_FP_ACCEPT_ALL. + In addition, accept directed advertising packets, where the advertiser's + address is a resolvable private address that cannot be resolved. */ +#define BLE_GAP_SCAN_FP_WHITELIST_NOT_RESOLVED_DIRECTED 0x03 /**< Accept all advertising packets specified in @ref BLE_GAP_SCAN_FP_WHITELIST. + In addition, accept directed advertising packets, where the advertiser's + address is a resolvable private address that cannot be resolved. */ +/**@} */ + +/**@defgroup BLE_GAP_ADV_TIMEOUT_VALUES GAP Advertising timeout values in 10 ms units + * @{ */ +#define BLE_GAP_ADV_TIMEOUT_HIGH_DUTY_MAX (128) /**< Maximum high duty advertising time in 10 ms units. Corresponds to 1.28 s. */ +#define BLE_GAP_ADV_TIMEOUT_LIMITED_MAX (18000) /**< Maximum advertising time in 10 ms units corresponding to TGAP(lim_adv_timeout) = 180 s in limited discoverable mode. */ +#define BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED (0) /**< Unlimited advertising in general discoverable mode. + For high duty cycle advertising, this corresponds to @ref BLE_GAP_ADV_TIMEOUT_HIGH_DUTY_MAX. */ +/**@} */ + + +/**@defgroup BLE_GAP_DISC_MODES GAP Discovery modes + * @{ */ +#define BLE_GAP_DISC_MODE_NOT_DISCOVERABLE 0x00 /**< Not discoverable discovery Mode. */ +#define BLE_GAP_DISC_MODE_LIMITED 0x01 /**< Limited Discovery Mode. */ +#define BLE_GAP_DISC_MODE_GENERAL 0x02 /**< General Discovery Mode. */ +/**@} */ + + +/**@defgroup BLE_GAP_IO_CAPS GAP IO Capabilities + * @{ */ +#define BLE_GAP_IO_CAPS_DISPLAY_ONLY 0x00 /**< Display Only. */ +#define BLE_GAP_IO_CAPS_DISPLAY_YESNO 0x01 /**< Display and Yes/No entry. */ +#define BLE_GAP_IO_CAPS_KEYBOARD_ONLY 0x02 /**< Keyboard Only. */ +#define BLE_GAP_IO_CAPS_NONE 0x03 /**< No I/O capabilities. */ +#define BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY 0x04 /**< Keyboard and Display. */ +/**@} */ + + +/**@defgroup BLE_GAP_AUTH_KEY_TYPES GAP Authentication Key Types + * @{ */ +#define BLE_GAP_AUTH_KEY_TYPE_NONE 0x00 /**< No key (may be used to reject). */ +#define BLE_GAP_AUTH_KEY_TYPE_PASSKEY 0x01 /**< 6-digit Passkey. */ +#define BLE_GAP_AUTH_KEY_TYPE_OOB 0x02 /**< Out Of Band data. */ +/**@} */ + + +/**@defgroup BLE_GAP_KP_NOT_TYPES GAP Keypress Notification Types + * @{ */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_START 0x00 /**< Passkey entry started. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_DIGIT_IN 0x01 /**< Passkey digit entered. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_DIGIT_OUT 0x02 /**< Passkey digit erased. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_CLEAR 0x03 /**< Passkey cleared. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_END 0x04 /**< Passkey entry completed. */ +/**@} */ + + +/**@defgroup BLE_GAP_SEC_STATUS GAP Security status + * @{ */ +#define BLE_GAP_SEC_STATUS_SUCCESS 0x00 /**< Procedure completed with success. */ +#define BLE_GAP_SEC_STATUS_TIMEOUT 0x01 /**< Procedure timed out. */ +#define BLE_GAP_SEC_STATUS_PDU_INVALID 0x02 /**< Invalid PDU received. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE1_BEGIN 0x03 /**< Reserved for Future Use range #1 begin. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE1_END 0x80 /**< Reserved for Future Use range #1 end. */ +#define BLE_GAP_SEC_STATUS_PASSKEY_ENTRY_FAILED 0x81 /**< Passkey entry failed (user canceled or other). */ +#define BLE_GAP_SEC_STATUS_OOB_NOT_AVAILABLE 0x82 /**< Out of Band Key not available. */ +#define BLE_GAP_SEC_STATUS_AUTH_REQ 0x83 /**< Authentication requirements not met. */ +#define BLE_GAP_SEC_STATUS_CONFIRM_VALUE 0x84 /**< Confirm value failed. */ +#define BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP 0x85 /**< Pairing not supported. */ +#define BLE_GAP_SEC_STATUS_ENC_KEY_SIZE 0x86 /**< Encryption key size. */ +#define BLE_GAP_SEC_STATUS_SMP_CMD_UNSUPPORTED 0x87 /**< Unsupported SMP command. */ +#define BLE_GAP_SEC_STATUS_UNSPECIFIED 0x88 /**< Unspecified reason. */ +#define BLE_GAP_SEC_STATUS_REPEATED_ATTEMPTS 0x89 /**< Too little time elapsed since last attempt. */ +#define BLE_GAP_SEC_STATUS_INVALID_PARAMS 0x8A /**< Invalid parameters. */ +#define BLE_GAP_SEC_STATUS_DHKEY_FAILURE 0x8B /**< DHKey check failure. */ +#define BLE_GAP_SEC_STATUS_NUM_COMP_FAILURE 0x8C /**< Numeric Comparison failure. */ +#define BLE_GAP_SEC_STATUS_BR_EDR_IN_PROG 0x8D /**< BR/EDR pairing in progress. */ +#define BLE_GAP_SEC_STATUS_X_TRANS_KEY_DISALLOWED 0x8E /**< BR/EDR Link Key cannot be used for LE keys. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE2_BEGIN 0x8F /**< Reserved for Future Use range #2 begin. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE2_END 0xFF /**< Reserved for Future Use range #2 end. */ +/**@} */ + + +/**@defgroup BLE_GAP_SEC_STATUS_SOURCES GAP Security status sources + * @{ */ +#define BLE_GAP_SEC_STATUS_SOURCE_LOCAL 0x00 /**< Local failure. */ +#define BLE_GAP_SEC_STATUS_SOURCE_REMOTE 0x01 /**< Remote failure. */ +/**@} */ + + +/**@defgroup BLE_GAP_CP_LIMITS GAP Connection Parameters Limits + * @{ */ +#define BLE_GAP_CP_MIN_CONN_INTVL_NONE 0xFFFF /**< No new minimum connection interval specified in connect parameters. */ +#define BLE_GAP_CP_MIN_CONN_INTVL_MIN 0x0006 /**< Lowest minimum connection interval permitted, in units of 1.25 ms, i.e. 7.5 ms. */ +#define BLE_GAP_CP_MIN_CONN_INTVL_MAX 0x0C80 /**< Highest minimum connection interval permitted, in units of 1.25 ms, i.e. 4 s. */ +#define BLE_GAP_CP_MAX_CONN_INTVL_NONE 0xFFFF /**< No new maximum connection interval specified in connect parameters. */ +#define BLE_GAP_CP_MAX_CONN_INTVL_MIN 0x0006 /**< Lowest maximum connection interval permitted, in units of 1.25 ms, i.e. 7.5 ms. */ +#define BLE_GAP_CP_MAX_CONN_INTVL_MAX 0x0C80 /**< Highest maximum connection interval permitted, in units of 1.25 ms, i.e. 4 s. */ +#define BLE_GAP_CP_SLAVE_LATENCY_MAX 0x01F3 /**< Highest slave latency permitted, in connection events. */ +#define BLE_GAP_CP_CONN_SUP_TIMEOUT_NONE 0xFFFF /**< No new supervision timeout specified in connect parameters. */ +#define BLE_GAP_CP_CONN_SUP_TIMEOUT_MIN 0x000A /**< Lowest supervision timeout permitted, in units of 10 ms, i.e. 100 ms. */ +#define BLE_GAP_CP_CONN_SUP_TIMEOUT_MAX 0x0C80 /**< Highest supervision timeout permitted, in units of 10 ms, i.e. 32 s. */ +/**@} */ + + +/**@defgroup BLE_GAP_DEVNAME GAP device name defines. + * @{ */ +#define BLE_GAP_DEVNAME_DEFAULT "nRF5x" /**< Default device name value. */ +#define BLE_GAP_DEVNAME_DEFAULT_LEN 31 /**< Default number of octets in device name. */ +#define BLE_GAP_DEVNAME_MAX_LEN 248 /**< Maximum number of octets in device name. */ +/**@} */ + + +/**@brief Disable RSSI events for connections */ +#define BLE_GAP_RSSI_THRESHOLD_INVALID 0xFF + +/**@defgroup BLE_GAP_PHYS GAP PHYs + * @{ */ +#define BLE_GAP_PHY_AUTO 0x00 /**< Automatic PHY selection. Refer @ref sd_ble_gap_phy_update for more information.*/ +#define BLE_GAP_PHY_1MBPS 0x01 /**< 1 Mbps PHY. */ +#define BLE_GAP_PHY_2MBPS 0x02 /**< 2 Mbps PHY. */ +#define BLE_GAP_PHY_CODED 0x04 /**< Coded PHY. */ +#define BLE_GAP_PHY_NOT_SET 0xFF /**< PHY is not configured. */ + +/**@brief Supported PHYs in connections, for scanning, and for advertising. */ +#define BLE_GAP_PHYS_SUPPORTED (BLE_GAP_PHY_1MBPS | BLE_GAP_PHY_2MBPS | BLE_GAP_PHY_CODED) /**< All PHYs are supported. */ + +/**@} */ + +/**@defgroup BLE_GAP_CONN_SEC_MODE_SET_MACROS GAP attribute security requirement setters + * + * See @ref ble_gap_conn_sec_mode_t. + * @{ */ +/**@brief Set sec_mode pointed to by ptr to have no access rights.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(ptr) do {(ptr)->sm = 0; (ptr)->lv = 0;} while(0) +/**@brief Set sec_mode pointed to by ptr to require no protection, open link.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_OPEN(ptr) do {(ptr)->sm = 1; (ptr)->lv = 1;} while(0) +/**@brief Set sec_mode pointed to by ptr to require encryption, but no MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(ptr) do {(ptr)->sm = 1; (ptr)->lv = 2;} while(0) +/**@brief Set sec_mode pointed to by ptr to require encryption and MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(ptr) do {(ptr)->sm = 1; (ptr)->lv = 3;} while(0) +/**@brief Set sec_mode pointed to by ptr to require LESC encryption and MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(ptr) do {(ptr)->sm = 1; (ptr)->lv = 4;} while(0) +/**@brief Set sec_mode pointed to by ptr to require signing or encryption, no MITM protection needed.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(ptr) do {(ptr)->sm = 2; (ptr)->lv = 1;} while(0) +/**@brief Set sec_mode pointed to by ptr to require signing or encryption with MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(ptr) do {(ptr)->sm = 2; (ptr)->lv = 2;} while(0) +/**@} */ + + +/**@brief GAP Security Random Number Length. */ +#define BLE_GAP_SEC_RAND_LEN 8 + + +/**@brief GAP Security Key Length. */ +#define BLE_GAP_SEC_KEY_LEN 16 + + +/**@brief GAP LE Secure Connections Elliptic Curve Diffie-Hellman P-256 Public Key Length. */ +#define BLE_GAP_LESC_P256_PK_LEN 64 + + +/**@brief GAP LE Secure Connections Elliptic Curve Diffie-Hellman DHKey Length. */ +#define BLE_GAP_LESC_DHKEY_LEN 32 + + +/**@brief GAP Passkey Length. */ +#define BLE_GAP_PASSKEY_LEN 6 + + +/**@brief Maximum amount of addresses in the whitelist. */ +#define BLE_GAP_WHITELIST_ADDR_MAX_COUNT (8) + + +/**@brief Maximum amount of identities in the device identities list. */ +#define BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT (8) + + +/**@brief Default connection count for a configuration. */ +#define BLE_GAP_CONN_COUNT_DEFAULT (1) + + +/**@defgroup BLE_GAP_EVENT_LENGTH GAP event length defines. + * @{ */ +#define BLE_GAP_EVENT_LENGTH_MIN (2) /**< Minimum event length, in 1.25 ms units. */ +#define BLE_GAP_EVENT_LENGTH_CODED_PHY_MIN (6) /**< The shortest event length in 1.25 ms units supporting LE Coded PHY. */ +#define BLE_GAP_EVENT_LENGTH_DEFAULT (3) /**< Default event length, in 1.25 ms units. */ +/**@} */ + + +/**@defgroup BLE_GAP_ROLE_COUNT GAP concurrent connection count defines. + * @{ */ +#define BLE_GAP_ROLE_COUNT_PERIPH_DEFAULT (1) /**< Default maximum number of connections concurrently acting as peripherals. */ +#define BLE_GAP_ROLE_COUNT_CENTRAL_DEFAULT (3) /**< Default maximum number of connections concurrently acting as centrals. */ +#define BLE_GAP_ROLE_COUNT_CENTRAL_SEC_DEFAULT (1) /**< Default number of SMP instances shared between all connections acting as centrals. */ +#define BLE_GAP_ROLE_COUNT_COMBINED_MAX (20) /**< Maximum supported number of concurrent connections in the peripheral and central roles combined. */ + +/**@} */ + +/**@brief Automatic data length parameter. */ +#define BLE_GAP_DATA_LENGTH_AUTO 0 + +/**@defgroup BLE_GAP_AUTH_PAYLOAD_TIMEOUT Authenticated payload timeout defines. + * @{ */ +#define BLE_GAP_AUTH_PAYLOAD_TIMEOUT_MAX (48000) /**< Maximum authenticated payload timeout in 10 ms units, i.e. 8 minutes. */ +#define BLE_GAP_AUTH_PAYLOAD_TIMEOUT_MIN (1) /**< Minimum authenticated payload timeout in 10 ms units, i.e. 10 ms. */ +/**@} */ + +/**@defgroup GAP_SEC_MODES GAP Security Modes + * @{ */ +#define BLE_GAP_SEC_MODE 0x00 /**< No key (may be used to reject). */ +/**@} */ + +/**@brief The total number of channels in Bluetooth Low Energy. */ +#define BLE_GAP_CHANNEL_COUNT (40) + +/**@defgroup BLE_GAP_QOS_CHANNEL_SURVEY_INTERVALS Quality of Service (QoS) Channel survey interval defines + * @{ */ +#define BLE_GAP_QOS_CHANNEL_SURVEY_INTERVAL_CONTINUOUS (0) /**< Continuous channel survey. */ +#define BLE_GAP_QOS_CHANNEL_SURVEY_INTERVAL_MIN_US (7500) /**< Minimum channel survey interval in microseconds (7.5 ms). */ +#define BLE_GAP_QOS_CHANNEL_SURVEY_INTERVAL_MAX_US (4000000) /**< Maximum channel survey interval in microseconds (4 s). */ + /**@} */ + +/** @} */ + +/** @defgroup BLE_GAP_CHAR_INCL_CONFIG GAP Characteristic inclusion configurations + * @{ + */ +#define BLE_GAP_CHAR_INCL_CONFIG_INCLUDE (0) /**< Include the characteristic in the Attribute Table */ +#define BLE_GAP_CHAR_INCL_CONFIG_EXCLUDE_WITH_SPACE (1) /**< Do not include the characteristic in the Attribute table. + The SoftDevice will reserve the attribute handles + which are otherwise used for this characteristic. + By reserving the attribute handles it will be possible + to upgrade the SoftDevice without changing handle of the + Service Changed characteristic. */ +#define BLE_GAP_CHAR_INCL_CONFIG_EXCLUDE_WITHOUT_SPACE (2) /**< Do not include the characteristic in the Attribute table. + The SoftDevice will not reserve the attribute handles + which are otherwise used for this characteristic. */ +/**@} */ + + +/** @defgroup BLE_GAP_CHAR_INCL_CONFIG_DEFAULTS Characteristic inclusion default values + * @{ */ +#define BLE_GAP_PPCP_INCL_CONFIG_DEFAULT (BLE_GAP_CHAR_INCL_CONFIG_INCLUDE) /**< Included by default. */ +#define BLE_GAP_CAR_INCL_CONFIG_DEFAULT (BLE_GAP_CHAR_INCL_CONFIG_INCLUDE) /**< Included by default. */ +/**@} */ + +/**@addtogroup BLE_GAP_STRUCTURES Structures + * @{ */ + +/**@brief Advertising event properties. */ +typedef struct +{ + uint8_t type; /**< Advertising type. See @ref BLE_GAP_ADV_TYPES. */ + uint8_t anonymous : 1; /**< Omit advertiser's address from all PDUs. + @note Anonymous advertising is only available for + @ref BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED and + @ref BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_NONSCANNABLE_DIRECTED. */ + uint8_t include_tx_power : 1; /**< This feature is not supported on this SoftDevice. */ +} ble_gap_adv_properties_t; + + +/**@brief Advertising report type. */ +typedef struct +{ + uint16_t connectable : 1; /**< Connectable advertising event type. */ + uint16_t scannable : 1; /**< Scannable advertising event type. */ + uint16_t directed : 1; /**< Directed advertising event type. */ + uint16_t scan_response : 1; /**< Received a scan response. */ + uint16_t extended_pdu : 1; /**< Received an extended advertising set. */ + uint16_t status : 2; /**< Data status. See @ref BLE_GAP_ADV_DATA_STATUS. */ + uint16_t reserved : 9; /**< Reserved for future use. */ +} ble_gap_adv_report_type_t; + +/**@brief Advertising Auxiliary Pointer. */ +typedef struct +{ + uint16_t aux_offset; /**< Time offset from the beginning of advertising packet to the auxiliary packet in 100 us units. */ + uint8_t aux_phy; /**< Indicates the PHY on which the auxiliary advertising packet is sent. See @ref BLE_GAP_PHYS. */ +} ble_gap_aux_pointer_t; + +/**@brief Bluetooth Low Energy address. */ +typedef struct +{ + uint8_t addr_id_peer : 1; /**< Only valid for peer addresses. + This bit is set by the SoftDevice to indicate whether the address has been resolved from + a Resolvable Private Address (when the peer is using privacy). + If set to 1, @ref addr and @ref addr_type refer to the identity address of the resolved address. + + This bit is ignored when a variable of type @ref ble_gap_addr_t is used as input to API functions. */ + uint8_t addr_type : 7; /**< See @ref BLE_GAP_ADDR_TYPES. */ + uint8_t addr[BLE_GAP_ADDR_LEN]; /**< 48-bit address, LSB format. + @ref addr is not used if @ref addr_type is @ref BLE_GAP_ADDR_TYPE_ANONYMOUS. */ +} ble_gap_addr_t; + + +/**@brief GAP connection parameters. + * + * @note When ble_conn_params_t is received in an event, both min_conn_interval and + * max_conn_interval will be equal to the connection interval set by the central. + * + * @note If both conn_sup_timeout and max_conn_interval are specified, then the following constraint applies: + * conn_sup_timeout * 4 > (1 + slave_latency) * max_conn_interval + * that corresponds to the following Bluetooth Spec requirement: + * The Supervision_Timeout in milliseconds shall be larger than + * (1 + Conn_Latency) * Conn_Interval_Max * 2, where Conn_Interval_Max is given in milliseconds. + */ +typedef struct +{ + uint16_t min_conn_interval; /**< Minimum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/ + uint16_t max_conn_interval; /**< Maximum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/ + uint16_t slave_latency; /**< Slave Latency in number of connection events, see @ref BLE_GAP_CP_LIMITS.*/ + uint16_t conn_sup_timeout; /**< Connection Supervision Timeout in 10 ms units, see @ref BLE_GAP_CP_LIMITS.*/ +} ble_gap_conn_params_t; + + +/**@brief GAP connection security modes. + * + * Security Mode 0 Level 0: No access permissions at all (this level is not defined by the Bluetooth Core specification).\n + * Security Mode 1 Level 1: No security is needed (aka open link).\n + * Security Mode 1 Level 2: Encrypted link required, MITM protection not necessary.\n + * Security Mode 1 Level 3: MITM protected encrypted link required.\n + * Security Mode 1 Level 4: LESC MITM protected encrypted link using a 128-bit strength encryption key required.\n + * Security Mode 2 Level 1: Signing or encryption required, MITM protection not necessary.\n + * Security Mode 2 Level 2: MITM protected signing required, unless link is MITM protected encrypted.\n + */ +typedef struct +{ + uint8_t sm : 4; /**< Security Mode (1 or 2), 0 for no permissions at all. */ + uint8_t lv : 4; /**< Level (1, 2, 3 or 4), 0 for no permissions at all. */ + +} ble_gap_conn_sec_mode_t; + + +/**@brief GAP connection security status.*/ +typedef struct +{ + ble_gap_conn_sec_mode_t sec_mode; /**< Currently active security mode for this connection.*/ + uint8_t encr_key_size; /**< Length of currently active encryption key, 7 to 16 octets (only applicable for bonding procedures). */ +} ble_gap_conn_sec_t; + +/**@brief Identity Resolving Key. */ +typedef struct +{ + uint8_t irk[BLE_GAP_SEC_KEY_LEN]; /**< Array containing IRK. */ +} ble_gap_irk_t; + + +/**@brief Channel mask (40 bits). + * Every channel is represented with a bit positioned as per channel index defined in Bluetooth Core Specification v5.0, + * Vol 6, Part B, Section 1.4.1. The LSB contained in array element 0 represents channel index 0, and bit 39 represents + * channel index 39. If a bit is set to 1, the channel is not used. + */ +typedef uint8_t ble_gap_ch_mask_t[5]; + + +/**@brief GAP advertising parameters. */ +typedef struct +{ + ble_gap_adv_properties_t properties; /**< The properties of the advertising events. */ + ble_gap_addr_t const *p_peer_addr; /**< Address of a known peer. + @note ble_gap_addr_t::addr_type cannot be + @ref BLE_GAP_ADDR_TYPE_ANONYMOUS. + - When privacy is enabled and the local device uses + @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE addresses, + the device identity list is searched for a matching entry. If + the local IRK for that device identity is set, the local IRK + for that device will be used to generate the advertiser address + field in the advertising packet. + - If @ref ble_gap_adv_properties_t::type is directed, this must be + set to the targeted scanner or initiator. If the peer address is + in the device identity list, the peer IRK for that device will be + used to generate @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE + target addresses used in the advertising event PDUs. */ + uint32_t interval; /**< Advertising interval in 625 us units. @sa BLE_GAP_ADV_INTERVALS. + @note If @ref ble_gap_adv_properties_t::type is set to + @ref BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED_HIGH_DUTY_CYCLE + advertising, this parameter is ignored. */ + uint16_t duration; /**< Advertising duration in 10 ms units. When timeout is reached, + an event of type @ref BLE_GAP_EVT_ADV_SET_TERMINATED is raised. + @sa BLE_GAP_ADV_TIMEOUT_VALUES. + @note The SoftDevice will always complete at least one advertising + event even if the duration is set too low. */ + uint8_t max_adv_evts; /**< Maximum advertising events that shall be sent prior to disabling + advertising. Setting the value to 0 disables the limitation. When + the count of advertising events specified by this parameter + (if not 0) is reached, advertising will be automatically stopped + and an event of type @ref BLE_GAP_EVT_ADV_SET_TERMINATED is raised + @note If @ref ble_gap_adv_properties_t::type is set to + @ref BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED_HIGH_DUTY_CYCLE, + this parameter is ignored. */ + ble_gap_ch_mask_t channel_mask; /**< Channel mask for primary and secondary advertising channels. + At least one of the primary channels, that is channel index 37-39, must be used. + Masking away secondary advertising channels is not supported. */ + uint8_t filter_policy; /**< Filter Policy. @sa BLE_GAP_ADV_FILTER_POLICIES. */ + uint8_t primary_phy; /**< Indicates the PHY on which the primary advertising channel packets + are transmitted. If set to @ref BLE_GAP_PHY_AUTO, @ref BLE_GAP_PHY_1MBPS + will be used. + Valid values are @ref BLE_GAP_PHY_1MBPS and @ref BLE_GAP_PHY_CODED. + @note The primary_phy shall indicate @ref BLE_GAP_PHY_1MBPS if + @ref ble_gap_adv_properties_t::type is not an extended advertising type. */ + uint8_t secondary_phy; /**< Indicates the PHY on which the secondary advertising channel packets + are transmitted. + If set to @ref BLE_GAP_PHY_AUTO, @ref BLE_GAP_PHY_1MBPS will be used. + Valid values are + @ref BLE_GAP_PHY_1MBPS, @ref BLE_GAP_PHY_2MBPS, and @ref BLE_GAP_PHY_CODED. + If @ref ble_gap_adv_properties_t::type is an extended advertising type + and connectable, this is the PHY that will be used to establish a + connection and send AUX_ADV_IND packets on. + @note This parameter will be ignored when + @ref ble_gap_adv_properties_t::type is not an extended advertising type. */ + uint8_t set_id:4; /**< The advertising set identifier distinguishes this advertising set from other + advertising sets transmitted by this and other devices. + @note This parameter will be ignored when + @ref ble_gap_adv_properties_t::type is not an extended advertising type. */ + uint8_t scan_req_notification:1; /**< Enable scan request notifications for this advertising set. When a + scan request is received and the scanner address is allowed + by the filter policy, @ref BLE_GAP_EVT_SCAN_REQ_REPORT is raised. + @note This parameter will be ignored when + @ref ble_gap_adv_properties_t::type is a non-scannable + advertising type. */ +} ble_gap_adv_params_t; + + +/**@brief GAP advertising data buffers. + * + * The application must provide the buffers for advertisement. The memory shall reside in application RAM, and + * shall never be modified while advertising. The data shall be kept alive until either: + * - @ref BLE_GAP_EVT_ADV_SET_TERMINATED is raised. + * - @ref BLE_GAP_EVT_CONNECTED is raised with @ref ble_gap_evt_connected_t::adv_handle set to the corresponding + * advertising handle. + * - Advertising is stopped. + * - Advertising data is changed. + * To update advertising data while advertising, provide new buffers to @ref sd_ble_gap_adv_set_configure. */ +typedef struct +{ + ble_data_t adv_data; /**< Advertising data. + @note + Advertising data can only be specified for a @ref ble_gap_adv_properties_t::type + that is allowed to contain advertising data. */ + ble_data_t scan_rsp_data; /**< Scan response data. + @note + Scan response data can only be specified for a @ref ble_gap_adv_properties_t::type + that is scannable. */ +} ble_gap_adv_data_t; + + +/**@brief GAP scanning parameters. */ +typedef struct +{ + uint8_t extended : 1; /**< If 1, the scanner will accept extended advertising packets. + If set to 0, the scanner will not receive advertising packets + on secondary advertising channels, and will not be able + to receive long advertising PDUs. */ + uint8_t report_incomplete_evts : 1; /**< If 1, events of type @ref ble_gap_evt_adv_report_t may have + @ref ble_gap_adv_report_type_t::status set to + @ref BLE_GAP_ADV_DATA_STATUS_INCOMPLETE_MORE_DATA. + This parameter is ignored when used with @ref sd_ble_gap_connect + @note This may be used to abort receiving more packets from an extended + advertising event, and is only available for extended + scanning, see @ref sd_ble_gap_scan_start. + @note This feature is not supported by this SoftDevice. */ + uint8_t active : 1; /**< If 1, perform active scanning by sending scan requests. + This parameter is ignored when used with @ref sd_ble_gap_connect. */ + uint8_t filter_policy : 2; /**< Scanning filter policy. @sa BLE_GAP_SCAN_FILTER_POLICIES. + @note Only @ref BLE_GAP_SCAN_FP_ACCEPT_ALL and + @ref BLE_GAP_SCAN_FP_WHITELIST are valid when used with + @ref sd_ble_gap_connect */ + uint8_t scan_phys; /**< Bitfield of PHYs to scan on. If set to @ref BLE_GAP_PHY_AUTO, + scan_phys will default to @ref BLE_GAP_PHY_1MBPS. + - If @ref ble_gap_scan_params_t::extended is set to 0, the only + supported PHY is @ref BLE_GAP_PHY_1MBPS. + - When used with @ref sd_ble_gap_scan_start, + the bitfield indicates the PHYs the scanner will use for scanning + on primary advertising channels. The scanner will accept + @ref BLE_GAP_PHYS_SUPPORTED as secondary advertising channel PHYs. + - When used with @ref sd_ble_gap_connect, the bitfield indicates + the PHYs the initiator will use for scanning on primary advertising + channels. The initiator will accept connections initiated on either + of the @ref BLE_GAP_PHYS_SUPPORTED PHYs. + If scan_phys contains @ref BLE_GAP_PHY_1MBPS and/or @ref BLE_GAP_PHY_2MBPS, + the primary scan PHY is @ref BLE_GAP_PHY_1MBPS. + If scan_phys also contains @ref BLE_GAP_PHY_CODED, the primary scan + PHY will also contain @ref BLE_GAP_PHY_CODED. If the only scan PHY is + @ref BLE_GAP_PHY_CODED, the primary scan PHY is + @ref BLE_GAP_PHY_CODED only. */ + uint16_t interval; /**< Scan interval in 625 us units. @sa BLE_GAP_SCAN_INTERVALS. */ + uint16_t window; /**< Scan window in 625 us units. @sa BLE_GAP_SCAN_WINDOW. + If scan_phys contains both @ref BLE_GAP_PHY_1MBPS and + @ref BLE_GAP_PHY_CODED interval shall be larger than or + equal to twice the scan window. */ + uint16_t timeout; /**< Scan timeout in 10 ms units. @sa BLE_GAP_SCAN_TIMEOUT. */ + ble_gap_ch_mask_t channel_mask; /**< Channel mask for primary and secondary advertising channels. + At least one of the primary channels, that is channel index 37-39, must be + set to 0. + Masking away secondary channels is not supported. */ +} ble_gap_scan_params_t; + + +/**@brief Privacy. + * + * The privacy feature provides a way for the device to avoid being tracked over a period of time. + * The privacy feature, when enabled, hides the local device identity and replaces it with a private address + * that is automatically refreshed at a specified interval. + * + * If a device still wants to be recognized by other peers, it needs to share it's Identity Resolving Key (IRK). + * With this key, a device can generate a random private address that can only be recognized by peers in possession of that key, + * and devices can establish connections without revealing their real identities. + * + * Both network privacy (@ref BLE_GAP_PRIVACY_MODE_NETWORK_PRIVACY) and device privacy (@ref BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY) + * are supported. + * + * @note If the device IRK is updated, the new IRK becomes the one to be distributed in all + * bonding procedures performed after @ref sd_ble_gap_privacy_set returns. + * The IRK distributed during bonding procedure is the device IRK that is active when @ref sd_ble_gap_sec_params_reply is called. + */ +typedef struct +{ + uint8_t privacy_mode; /**< Privacy mode, see @ref BLE_GAP_PRIVACY_MODES. Default is @ref BLE_GAP_PRIVACY_MODE_OFF. */ + uint8_t private_addr_type; /**< The private address type must be either @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE or @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE. */ + uint16_t private_addr_cycle_s; /**< Private address cycle interval in seconds. Providing an address cycle value of 0 will use the default value defined by @ref BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S. */ + ble_gap_irk_t *p_device_irk; /**< When used as input, pointer to IRK structure that will be used as the default IRK. If NULL, the device default IRK will be used. + When used as output, pointer to IRK structure where the current default IRK will be written to. If NULL, this argument is ignored. + By default, the default IRK is used to generate random private resolvable addresses for the local device unless instructed otherwise. */ +} ble_gap_privacy_params_t; + + +/**@brief PHY preferences for TX and RX + * @note tx_phys and rx_phys are bit fields. Multiple bits can be set in them to indicate multiple preferred PHYs for each direction. + * @code + * p_gap_phys->tx_phys = BLE_GAP_PHY_1MBPS | BLE_GAP_PHY_2MBPS; + * p_gap_phys->rx_phys = BLE_GAP_PHY_1MBPS | BLE_GAP_PHY_2MBPS; + * @endcode + * + */ +typedef struct +{ + uint8_t tx_phys; /**< Preferred transmit PHYs, see @ref BLE_GAP_PHYS. */ + uint8_t rx_phys; /**< Preferred receive PHYs, see @ref BLE_GAP_PHYS. */ +} ble_gap_phys_t; + +/** @brief Keys that can be exchanged during a bonding procedure. */ +typedef struct +{ + uint8_t enc : 1; /**< Long Term Key and Master Identification. */ + uint8_t id : 1; /**< Identity Resolving Key and Identity Address Information. */ + uint8_t sign : 1; /**< Connection Signature Resolving Key. */ + uint8_t link : 1; /**< Derive the Link Key from the LTK. */ +} ble_gap_sec_kdist_t; + + +/**@brief GAP security parameters. */ +typedef struct +{ + uint8_t bond : 1; /**< Perform bonding. */ + uint8_t mitm : 1; /**< Enable Man In The Middle protection. */ + uint8_t lesc : 1; /**< Enable LE Secure Connection pairing. */ + uint8_t keypress : 1; /**< Enable generation of keypress notifications. */ + uint8_t io_caps : 3; /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */ + uint8_t oob : 1; /**< The OOB data flag. + - In LE legacy pairing, this flag is set if a device has out of band authentication data. + The OOB method is used if both of the devices have out of band authentication data. + - In LE Secure Connections pairing, this flag is set if a device has the peer device's out of band authentication data. + The OOB method is used if at least one device has the peer device's OOB data available. */ + uint8_t min_key_size; /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */ + uint8_t max_key_size; /**< Maximum encryption key size in octets between min_key_size and 16. */ + ble_gap_sec_kdist_t kdist_own; /**< Key distribution bitmap: keys that the local device will distribute. */ + ble_gap_sec_kdist_t kdist_peer; /**< Key distribution bitmap: keys that the remote device will distribute. */ +} ble_gap_sec_params_t; + + +/**@brief GAP Encryption Information. */ +typedef struct +{ + uint8_t ltk[BLE_GAP_SEC_KEY_LEN]; /**< Long Term Key. */ + uint8_t lesc : 1; /**< Key generated using LE Secure Connections. */ + uint8_t auth : 1; /**< Authenticated Key. */ + uint8_t ltk_len : 6; /**< LTK length in octets. */ +} ble_gap_enc_info_t; + + +/**@brief GAP Master Identification. */ +typedef struct +{ + uint16_t ediv; /**< Encrypted Diversifier. */ + uint8_t rand[BLE_GAP_SEC_RAND_LEN]; /**< Random Number. */ +} ble_gap_master_id_t; + + +/**@brief GAP Signing Information. */ +typedef struct +{ + uint8_t csrk[BLE_GAP_SEC_KEY_LEN]; /**< Connection Signature Resolving Key. */ +} ble_gap_sign_info_t; + + +/**@brief GAP LE Secure Connections P-256 Public Key. */ +typedef struct +{ + uint8_t pk[BLE_GAP_LESC_P256_PK_LEN]; /**< LE Secure Connections Elliptic Curve Diffie-Hellman P-256 Public Key. Stored in the standard SMP protocol format: {X,Y} both in little-endian. */ +} ble_gap_lesc_p256_pk_t; + + +/**@brief GAP LE Secure Connections DHKey. */ +typedef struct +{ + uint8_t key[BLE_GAP_LESC_DHKEY_LEN]; /**< LE Secure Connections Elliptic Curve Diffie-Hellman Key. Stored in little-endian. */ +} ble_gap_lesc_dhkey_t; + + +/**@brief GAP LE Secure Connections OOB data. */ +typedef struct +{ + ble_gap_addr_t addr; /**< Bluetooth address of the device. */ + uint8_t r[BLE_GAP_SEC_KEY_LEN]; /**< Random Number. */ + uint8_t c[BLE_GAP_SEC_KEY_LEN]; /**< Confirm Value. */ +} ble_gap_lesc_oob_data_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONNECTED. */ +typedef struct +{ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. If the peer_addr resolved: @ref ble_gap_addr_t::addr_id_peer is set to 1 + and the address is the device's identity address. */ + uint8_t role; /**< BLE role for this connection, see @ref BLE_GAP_ROLES */ + ble_gap_conn_params_t conn_params; /**< GAP Connection Parameters. */ + uint8_t adv_handle; /**< Advertising handle in which advertising has ended. + This variable is only set if role is set to @ref BLE_GAP_ROLE_PERIPH. */ + ble_gap_adv_data_t adv_data; /**< Advertising buffers corresponding to the terminated + advertising set. The advertising buffers provided in + @ref sd_ble_gap_adv_set_configure are now released. + This variable is only set if role is set to @ref BLE_GAP_ROLE_PERIPH. */ +} ble_gap_evt_connected_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_DISCONNECTED. */ +typedef struct +{ + uint8_t reason; /**< HCI error code, see @ref BLE_HCI_STATUS_CODES. */ +} ble_gap_evt_disconnected_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONN_PARAM_UPDATE. */ +typedef struct +{ + ble_gap_conn_params_t conn_params; /**< GAP Connection Parameters. */ +} ble_gap_evt_conn_param_update_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_PHY_UPDATE_REQUEST. */ +typedef struct +{ + ble_gap_phys_t peer_preferred_phys; /**< The PHYs the peer prefers to use. */ +} ble_gap_evt_phy_update_request_t; + +/**@brief Event Structure for @ref BLE_GAP_EVT_PHY_UPDATE. */ +typedef struct +{ + uint8_t status; /**< Status of the procedure, see @ref BLE_HCI_STATUS_CODES.*/ + uint8_t tx_phy; /**< TX PHY for this connection, see @ref BLE_GAP_PHYS. */ + uint8_t rx_phy; /**< RX PHY for this connection, see @ref BLE_GAP_PHYS. */ +} ble_gap_evt_phy_update_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST. */ +typedef struct +{ + ble_gap_sec_params_t peer_params; /**< Initiator Security Parameters. */ +} ble_gap_evt_sec_params_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_SEC_INFO_REQUEST. */ +typedef struct +{ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. */ + ble_gap_master_id_t master_id; /**< Master Identification for LTK lookup. */ + uint8_t enc_info : 1; /**< If 1, Encryption Information required. */ + uint8_t id_info : 1; /**< If 1, Identity Information required. */ + uint8_t sign_info : 1; /**< If 1, Signing Information required. */ +} ble_gap_evt_sec_info_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_PASSKEY_DISPLAY. */ +typedef struct +{ + uint8_t passkey[BLE_GAP_PASSKEY_LEN]; /**< 6-digit passkey in ASCII ('0'-'9' digits only). */ + uint8_t match_request : 1; /**< If 1 requires the application to report the match using @ref sd_ble_gap_auth_key_reply + with either @ref BLE_GAP_AUTH_KEY_TYPE_NONE if there is no match or + @ref BLE_GAP_AUTH_KEY_TYPE_PASSKEY if there is a match. */ +} ble_gap_evt_passkey_display_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_KEY_PRESSED. */ +typedef struct +{ + uint8_t kp_not; /**< Keypress notification type, see @ref BLE_GAP_KP_NOT_TYPES. */ +} ble_gap_evt_key_pressed_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_AUTH_KEY_REQUEST. */ +typedef struct +{ + uint8_t key_type; /**< See @ref BLE_GAP_AUTH_KEY_TYPES. */ +} ble_gap_evt_auth_key_request_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_LESC_DHKEY_REQUEST. */ +typedef struct +{ + ble_gap_lesc_p256_pk_t *p_pk_peer; /**< LE Secure Connections remote P-256 Public Key. This will point to the application-supplied memory + inside the keyset during the call to @ref sd_ble_gap_sec_params_reply. */ + uint8_t oobd_req :1; /**< LESC OOB data required. A call to @ref sd_ble_gap_lesc_oob_data_set is required to complete the procedure. */ +} ble_gap_evt_lesc_dhkey_request_t; + + +/**@brief Security levels supported. + * @note See Bluetooth Specification Version 4.2 Volume 3, Part C, Chapter 10, Section 10.2.1. +*/ +typedef struct +{ + uint8_t lv1 : 1; /**< If 1: Level 1 is supported. */ + uint8_t lv2 : 1; /**< If 1: Level 2 is supported. */ + uint8_t lv3 : 1; /**< If 1: Level 3 is supported. */ + uint8_t lv4 : 1; /**< If 1: Level 4 is supported. */ +} ble_gap_sec_levels_t; + + +/**@brief Encryption Key. */ +typedef struct +{ + ble_gap_enc_info_t enc_info; /**< Encryption Information. */ + ble_gap_master_id_t master_id; /**< Master Identification. */ +} ble_gap_enc_key_t; + + +/**@brief Identity Key. */ +typedef struct +{ + ble_gap_irk_t id_info; /**< Identity Resolving Key. */ + ble_gap_addr_t id_addr_info; /**< Identity Address. */ +} ble_gap_id_key_t; + + +/**@brief Security Keys. */ +typedef struct +{ + ble_gap_enc_key_t *p_enc_key; /**< Encryption Key, or NULL. */ + ble_gap_id_key_t *p_id_key; /**< Identity Key, or NULL. */ + ble_gap_sign_info_t *p_sign_key; /**< Signing Key, or NULL. */ + ble_gap_lesc_p256_pk_t *p_pk; /**< LE Secure Connections P-256 Public Key. When in debug mode the application must use the value defined + in the Core Bluetooth Specification v4.2 Vol.3, Part H, Section 2.3.5.6.1 */ +} ble_gap_sec_keys_t; + + +/**@brief Security key set for both local and peer keys. */ +typedef struct +{ + ble_gap_sec_keys_t keys_own; /**< Keys distributed by the local device. For LE Secure Connections the encryption key will be generated locally and will always be stored if bonding. */ + ble_gap_sec_keys_t keys_peer; /**< Keys distributed by the remote device. For LE Secure Connections, p_enc_key must always be NULL. */ +} ble_gap_sec_keyset_t; + + +/**@brief Data Length Update Procedure parameters. */ +typedef struct +{ + uint16_t max_tx_octets; /**< Maximum number of payload octets that a Controller supports for transmission of a single Link Layer Data Channel PDU. */ + uint16_t max_rx_octets; /**< Maximum number of payload octets that a Controller supports for reception of a single Link Layer Data Channel PDU. */ + uint16_t max_tx_time_us; /**< Maximum time, in microseconds, that a Controller supports for transmission of a single Link Layer Data Channel PDU. */ + uint16_t max_rx_time_us; /**< Maximum time, in microseconds, that a Controller supports for reception of a single Link Layer Data Channel PDU. */ +} ble_gap_data_length_params_t; + + +/**@brief Data Length Update Procedure local limitation. */ +typedef struct +{ + uint16_t tx_payload_limited_octets; /**< If > 0, the requested TX packet length is too long by this many octets. */ + uint16_t rx_payload_limited_octets; /**< If > 0, the requested RX packet length is too long by this many octets. */ + uint16_t tx_rx_time_limited_us; /**< If > 0, the requested combination of TX and RX packet lengths is too long by this many microseconds. */ +} ble_gap_data_length_limitation_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_AUTH_STATUS. */ +typedef struct +{ + uint8_t auth_status; /**< Authentication status, see @ref BLE_GAP_SEC_STATUS. */ + uint8_t error_src : 2; /**< On error, source that caused the failure, see @ref BLE_GAP_SEC_STATUS_SOURCES. */ + uint8_t bonded : 1; /**< Procedure resulted in a bond. */ + uint8_t lesc : 1; /**< Procedure resulted in a LE Secure Connection. */ + ble_gap_sec_levels_t sm1_levels; /**< Levels supported in Security Mode 1. */ + ble_gap_sec_levels_t sm2_levels; /**< Levels supported in Security Mode 2. */ + ble_gap_sec_kdist_t kdist_own; /**< Bitmap stating which keys were exchanged (distributed) by the local device. If bonding with LE Secure Connections, the enc bit will be always set. */ + ble_gap_sec_kdist_t kdist_peer; /**< Bitmap stating which keys were exchanged (distributed) by the remote device. If bonding with LE Secure Connections, the enc bit will never be set. */ +} ble_gap_evt_auth_status_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONN_SEC_UPDATE. */ +typedef struct +{ + ble_gap_conn_sec_t conn_sec; /**< Connection security level. */ +} ble_gap_evt_conn_sec_update_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_TIMEOUT. */ +typedef struct +{ + uint8_t src; /**< Source of timeout event, see @ref BLE_GAP_TIMEOUT_SOURCES. */ + union + { + ble_data_t adv_report_buffer; /**< If source is set to @ref BLE_GAP_TIMEOUT_SRC_SCAN, the released + scan buffer is contained in this field. */ + } params; /**< Event Parameters. */ +} ble_gap_evt_timeout_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_RSSI_CHANGED. */ +typedef struct +{ + int8_t rssi; /**< Received Signal Strength Indication in dBm. + @note ERRATA-153 and ERRATA-225 require the rssi sample to be compensated based on a temperature measurement. */ + uint8_t ch_index; /**< Data Channel Index on which the Signal Strength is measured (0-36). */ +} ble_gap_evt_rssi_changed_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_ADV_SET_TERMINATED */ +typedef struct +{ + uint8_t reason; /**< Reason for why the advertising set terminated. See + @ref BLE_GAP_EVT_ADV_SET_TERMINATED_REASON. */ + uint8_t adv_handle; /**< Advertising handle in which advertising has ended. */ + uint8_t num_completed_adv_events; /**< If @ref ble_gap_adv_params_t::max_adv_evts was not set to 0, + this field indicates the number of completed advertising events. */ + ble_gap_adv_data_t adv_data; /**< Advertising buffers corresponding to the terminated + advertising set. The advertising buffers provided in + @ref sd_ble_gap_adv_set_configure are now released. */ +} ble_gap_evt_adv_set_terminated_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_ADV_REPORT. + * + * @note If @ref ble_gap_adv_report_type_t::status is set to @ref BLE_GAP_ADV_DATA_STATUS_INCOMPLETE_MORE_DATA, + * not all fields in the advertising report may be available. + * + * @note When ble_gap_adv_report_type_t::status is not set to @ref BLE_GAP_ADV_DATA_STATUS_INCOMPLETE_MORE_DATA, + * scanning will be paused. To continue scanning, call @ref sd_ble_gap_scan_start. + */ +typedef struct +{ + ble_gap_adv_report_type_t type; /**< Advertising report type. See @ref ble_gap_adv_report_type_t. */ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. If the peer_addr is resolved: + @ref ble_gap_addr_t::addr_id_peer is set to 1 and the address is the + peer's identity address. */ + ble_gap_addr_t direct_addr; /**< Contains the target address of the advertising event if + @ref ble_gap_adv_report_type_t::directed is set to 1. If the + SoftDevice was able to resolve the address, + @ref ble_gap_addr_t::addr_id_peer is set to 1 and the direct_addr + contains the local identity address. If the target address of the + advertising event is @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE, + and the SoftDevice was unable to resolve it, the application may try + to resolve this address to find out if the advertising event was + directed to us. */ + uint8_t primary_phy; /**< Indicates the PHY on which the primary advertising packet was received. + See @ref BLE_GAP_PHYS. */ + uint8_t secondary_phy; /**< Indicates the PHY on which the secondary advertising packet was received. + See @ref BLE_GAP_PHYS. This field is set to @ref BLE_GAP_PHY_NOT_SET if no packets + were received on a secondary advertising channel. */ + int8_t tx_power; /**< TX Power reported by the advertiser in the last packet header received. + This field is set to @ref BLE_GAP_POWER_LEVEL_INVALID if the + last received packet did not contain the Tx Power field. + @note TX Power is only included in extended advertising packets. */ + int8_t rssi; /**< Received Signal Strength Indication in dBm of the last packet received. + @note ERRATA-153 and ERRATA-225 require the rssi sample to be compensated based on a temperature measurement. */ + uint8_t ch_index; /**< Channel Index on which the last advertising packet is received (0-39). */ + uint8_t set_id; /**< Set ID of the received advertising data. Set ID is not present + if set to @ref BLE_GAP_ADV_REPORT_SET_ID_NOT_AVAILABLE. */ + uint16_t data_id:12; /**< The advertising data ID of the received advertising data. Data ID + is not present if @ref ble_gap_evt_adv_report_t::set_id is set to + @ref BLE_GAP_ADV_REPORT_SET_ID_NOT_AVAILABLE. */ + ble_data_t data; /**< Received advertising or scan response data. If + @ref ble_gap_adv_report_type_t::status is not set to + @ref BLE_GAP_ADV_DATA_STATUS_INCOMPLETE_MORE_DATA, the data buffer provided + in @ref sd_ble_gap_scan_start is now released. */ + ble_gap_aux_pointer_t aux_pointer; /**< The offset and PHY of the next advertising packet in this extended advertising + event. @note This field is only set if @ref ble_gap_adv_report_type_t::status + is set to @ref BLE_GAP_ADV_DATA_STATUS_INCOMPLETE_MORE_DATA. */ +} ble_gap_evt_adv_report_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_SEC_REQUEST. */ +typedef struct +{ + uint8_t bond : 1; /**< Perform bonding. */ + uint8_t mitm : 1; /**< Man In The Middle protection requested. */ + uint8_t lesc : 1; /**< LE Secure Connections requested. */ + uint8_t keypress : 1; /**< Generation of keypress notifications requested. */ +} ble_gap_evt_sec_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST. */ +typedef struct +{ + ble_gap_conn_params_t conn_params; /**< GAP Connection Parameters. */ +} ble_gap_evt_conn_param_update_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_SCAN_REQ_REPORT. */ +typedef struct +{ + uint8_t adv_handle; /**< Advertising handle for the advertising set which received the Scan Request */ + int8_t rssi; /**< Received Signal Strength Indication in dBm. + @note ERRATA-153 and ERRATA-225 require the rssi sample to be compensated based on a temperature measurement. */ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. If the peer_addr resolved: @ref ble_gap_addr_t::addr_id_peer is set to 1 + and the address is the device's identity address. */ +} ble_gap_evt_scan_req_report_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST. */ +typedef struct +{ + ble_gap_data_length_params_t peer_params; /**< Peer data length parameters. */ +} ble_gap_evt_data_length_update_request_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_DATA_LENGTH_UPDATE. + * + * @note This event may also be raised after a PHY Update procedure. + */ +typedef struct +{ + ble_gap_data_length_params_t effective_params; /**< The effective data length parameters. */ +} ble_gap_evt_data_length_update_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT. */ +typedef struct +{ + int8_t channel_energy[BLE_GAP_CHANNEL_COUNT]; /**< The measured energy on the Bluetooth Low Energy + channels, in dBm, indexed by Channel Index. + If no measurement is available for the given channel, channel_energy is set to + @ref BLE_GAP_POWER_LEVEL_INVALID. */ +} ble_gap_evt_qos_channel_survey_report_t; + +/**@brief GAP event structure. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which event occurred. */ + union /**< union alternative identified by evt_id in enclosing struct. */ + { + ble_gap_evt_connected_t connected; /**< Connected Event Parameters. */ + ble_gap_evt_disconnected_t disconnected; /**< Disconnected Event Parameters. */ + ble_gap_evt_conn_param_update_t conn_param_update; /**< Connection Parameter Update Parameters. */ + ble_gap_evt_sec_params_request_t sec_params_request; /**< Security Parameters Request Event Parameters. */ + ble_gap_evt_sec_info_request_t sec_info_request; /**< Security Information Request Event Parameters. */ + ble_gap_evt_passkey_display_t passkey_display; /**< Passkey Display Event Parameters. */ + ble_gap_evt_key_pressed_t key_pressed; /**< Key Pressed Event Parameters. */ + ble_gap_evt_auth_key_request_t auth_key_request; /**< Authentication Key Request Event Parameters. */ + ble_gap_evt_lesc_dhkey_request_t lesc_dhkey_request; /**< LE Secure Connections DHKey calculation request. */ + ble_gap_evt_auth_status_t auth_status; /**< Authentication Status Event Parameters. */ + ble_gap_evt_conn_sec_update_t conn_sec_update; /**< Connection Security Update Event Parameters. */ + ble_gap_evt_timeout_t timeout; /**< Timeout Event Parameters. */ + ble_gap_evt_rssi_changed_t rssi_changed; /**< RSSI Event Parameters. */ + ble_gap_evt_adv_report_t adv_report; /**< Advertising Report Event Parameters. */ + ble_gap_evt_adv_set_terminated_t adv_set_terminated; /**< Advertising Set Terminated Event Parameters. */ + ble_gap_evt_sec_request_t sec_request; /**< Security Request Event Parameters. */ + ble_gap_evt_conn_param_update_request_t conn_param_update_request; /**< Connection Parameter Update Parameters. */ + ble_gap_evt_scan_req_report_t scan_req_report; /**< Scan Request Report Parameters. */ + ble_gap_evt_phy_update_request_t phy_update_request; /**< PHY Update Request Event Parameters. */ + ble_gap_evt_phy_update_t phy_update; /**< PHY Update Parameters. */ + ble_gap_evt_data_length_update_request_t data_length_update_request; /**< Data Length Update Request Event Parameters. */ + ble_gap_evt_data_length_update_t data_length_update; /**< Data Length Update Event Parameters. */ + ble_gap_evt_qos_channel_survey_report_t qos_channel_survey_report; /**< Quality of Service (QoS) Channel Survey Report Parameters. */ + } params; /**< Event Parameters. */ +} ble_gap_evt_t; + + +/** + * @brief BLE GAP connection configuration parameters, set with @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_CONN_COUNT The connection count for the connection configurations is zero. + * @retval ::NRF_ERROR_INVALID_PARAM One or more of the following is true: + * - The sum of conn_count for all connection configurations combined exceeds UINT8_MAX. + * - The event length is smaller than @ref BLE_GAP_EVENT_LENGTH_MIN. + */ +typedef struct +{ + uint8_t conn_count; /**< The number of concurrent connections the application can create with this configuration. + The default and minimum value is @ref BLE_GAP_CONN_COUNT_DEFAULT. */ + uint16_t event_length; /**< The time set aside for this connection on every connection interval in 1.25 ms units. + The default value is @ref BLE_GAP_EVENT_LENGTH_DEFAULT, the minimum value is @ref BLE_GAP_EVENT_LENGTH_MIN. + The event length and the connection interval are the primary parameters + for setting the throughput of a connection. + See the SoftDevice Specification for details on throughput. */ +} ble_gap_conn_cfg_t; + + +/** + * @brief Configuration of maximum concurrent connections in the different connected roles, set with + * @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_CONN_COUNT The sum of periph_role_count and central_role_count is too + * large. The maximum supported sum of concurrent connections is + * @ref BLE_GAP_ROLE_COUNT_COMBINED_MAX. + * @retval ::NRF_ERROR_INVALID_PARAM central_sec_count is larger than central_role_count. + * @retval ::NRF_ERROR_RESOURCES The adv_set_count is too large. The maximum + * supported advertising handles is + * @ref BLE_GAP_ADV_SET_COUNT_MAX. + */ +typedef struct +{ + uint8_t adv_set_count; /**< Maximum number of advertising sets. Default value is @ref BLE_GAP_ADV_SET_COUNT_DEFAULT. */ + uint8_t periph_role_count; /**< Maximum number of connections concurrently acting as a peripheral. Default value is @ref BLE_GAP_ROLE_COUNT_PERIPH_DEFAULT. */ + uint8_t central_role_count; /**< Maximum number of connections concurrently acting as a central. Default value is @ref BLE_GAP_ROLE_COUNT_CENTRAL_DEFAULT. */ + uint8_t central_sec_count; /**< Number of SMP instances shared between all connections acting as a central. Default value is @ref BLE_GAP_ROLE_COUNT_CENTRAL_SEC_DEFAULT. */ + uint8_t qos_channel_survey_role_available:1; /**< If set, the Quality of Service (QoS) channel survey module is available to the + application using @ref sd_ble_gap_qos_channel_survey_start. */ +} ble_gap_cfg_role_count_t; + + +/** + * @brief Device name and its properties, set with @ref sd_ble_cfg_set. + * + * @note If the device name is not configured, the default device name will be + * @ref BLE_GAP_DEVNAME_DEFAULT, the maximum device name length will be + * @ref BLE_GAP_DEVNAME_DEFAULT_LEN, vloc will be set to @ref BLE_GATTS_VLOC_STACK and the device name + * will have no write access. + * + * @note If @ref max_len is more than @ref BLE_GAP_DEVNAME_DEFAULT_LEN and vloc is set to @ref BLE_GATTS_VLOC_STACK, + * the attribute table size must be increased to have room for the longer device name (see + * @ref sd_ble_cfg_set and @ref ble_gatts_cfg_attr_tab_size_t). + * + * @note If vloc is @ref BLE_GATTS_VLOC_STACK : + * - p_value must point to non-volatile memory (flash) or be NULL. + * - If p_value is NULL, the device name will initially be empty. + * + * @note If vloc is @ref BLE_GATTS_VLOC_USER : + * - p_value cannot be NULL. + * - If the device name is writable, p_value must point to volatile memory (RAM). + * + * @retval ::NRF_ERROR_INVALID_PARAM One or more of the following is true: + * - Invalid device name location (vloc). + * - Invalid device name security mode. + * @retval ::NRF_ERROR_INVALID_LENGTH One or more of the following is true: + * - The device name length is invalid (must be between 0 and @ref BLE_GAP_DEVNAME_MAX_LEN). + * - The device name length is too long for the given Attribute Table. + * @retval ::NRF_ERROR_NOT_SUPPORTED Device name security mode is not supported. + */ +typedef struct +{ + ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ + uint8_t vloc:2; /**< Value location, see @ref BLE_GATTS_VLOCS.*/ + uint8_t *p_value; /**< Pointer to where the value (device name) is stored or will be stored. */ + uint16_t current_len; /**< Current length in bytes of the memory pointed to by p_value.*/ + uint16_t max_len; /**< Maximum length in bytes of the memory pointed to by p_value.*/ +} ble_gap_cfg_device_name_t; + + +/**@brief Peripheral Preferred Connection Parameters include configuration parameters, set with @ref sd_ble_cfg_set. */ +typedef struct +{ + uint8_t include_cfg; /**< Inclusion configuration of the Peripheral Preferred Connection Parameters characteristic. + See @ref BLE_GAP_CHAR_INCL_CONFIG. Default is @ref BLE_GAP_PPCP_INCL_CONFIG_DEFAULT. */ +} ble_gap_cfg_ppcp_incl_cfg_t; + + +/**@brief Central Address Resolution include configuration parameters, set with @ref sd_ble_cfg_set. */ +typedef struct +{ + uint8_t include_cfg; /**< Inclusion configuration of the Central Address Resolution characteristic. + See @ref BLE_GAP_CHAR_INCL_CONFIG. Default is @ref BLE_GAP_CAR_INCL_CONFIG_DEFAULT. */ +} ble_gap_cfg_car_incl_cfg_t; + + +/**@brief Configuration structure for GAP configurations. */ +typedef union +{ + ble_gap_cfg_role_count_t role_count_cfg; /**< Role count configuration, cfg_id is @ref BLE_GAP_CFG_ROLE_COUNT. */ + ble_gap_cfg_device_name_t device_name_cfg; /**< Device name configuration, cfg_id is @ref BLE_GAP_CFG_DEVICE_NAME. */ + ble_gap_cfg_ppcp_incl_cfg_t ppcp_include_cfg; /**< Peripheral Preferred Connection Parameters characteristic include + configuration, cfg_id is @ref BLE_GAP_CFG_PPCP_INCL_CONFIG. */ + ble_gap_cfg_car_incl_cfg_t car_include_cfg; /**< Central Address Resolution characteristic include configuration, + cfg_id is @ref BLE_GAP_CFG_CAR_INCL_CONFIG. */ +} ble_gap_cfg_t; + + +/**@brief Channel Map option. + * + * @details Used with @ref sd_ble_opt_get to get the current channel map + * or @ref sd_ble_opt_set to set a new channel map. When setting the + * channel map, it applies to all current and future connections. When getting the + * current channel map, it applies to a single connection and the connection handle + * must be supplied. + * + * @note Setting the channel map may take some time, depending on connection parameters. + * The time taken may be different for each connection and the get operation will + * return the previous channel map until the new one has taken effect. + * + * @note After setting the channel map, by spec it can not be set again until at least 1 s has passed. + * See Bluetooth Specification Version 4.1 Volume 2, Part E, Section 7.3.46. + * + * @retval ::NRF_SUCCESS Get or set successful. + * @retval ::NRF_ERROR_INVALID_PARAM One or more of the following is true: + * - Less then two bits in @ref ch_map are set. + * - Bits for primary advertising channels (37-39) are set. + * @retval ::NRF_ERROR_BUSY Channel map was set again before enough time had passed. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied for get. + * + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle (only applicable for get) */ + uint8_t ch_map[5]; /**< Channel Map (37-bit). */ +} ble_gap_opt_ch_map_t; + + +/**@brief Local connection latency option. + * + * @details Local connection latency is a feature which enables the slave to improve + * current consumption by ignoring the slave latency set by the peer. The + * local connection latency can only be set to a multiple of the slave latency, + * and cannot be longer than half of the supervision timeout. + * + * @details Used with @ref sd_ble_opt_set to set the local connection latency. The + * @ref sd_ble_opt_get is not supported for this option, but the actual + * local connection latency (unless set to NULL) is set as a return parameter + * when setting the option. + * + * @note The latency set will be truncated down to the closest slave latency event + * multiple, or the nearest multiple before half of the supervision timeout. + * + * @note The local connection latency is disabled by default, and needs to be enabled for new + * connections and whenever the connection is updated. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_NOT_SUPPORTED Get is not supported. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter. + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle */ + uint16_t requested_latency; /**< Requested local connection latency. */ + uint16_t * p_actual_latency; /**< Pointer to storage for the actual local connection latency (can be set to NULL to skip return value). */ +} ble_gap_opt_local_conn_latency_t; + +/**@brief Disable slave latency + * + * @details Used with @ref sd_ble_opt_set to temporarily disable slave latency of a peripheral connection + * (see @ref ble_gap_conn_params_t::slave_latency). And to re-enable it again. When disabled, the + * peripheral will ignore the slave_latency set by the central. + * + * @note Shall only be called on peripheral links. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_NOT_SUPPORTED Get is not supported. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter. + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle */ + uint8_t disable : 1; /**< Set to 1 to disable slave latency. Set to 0 enable it again.*/ +} ble_gap_opt_slave_latency_disable_t; + +/**@brief Passkey Option. + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_STATIC_PK_MSC} + * @endmscs + * + * @details Structure containing the passkey to be used during pairing. This can be used with @ref + * sd_ble_opt_set to make the SoftDevice use a preprogrammed passkey for authentication + * instead of generating a random one. + * + * @note Repeated pairing attempts using the same preprogrammed passkey makes pairing vulnerable to MITM attacks. + * + * @note @ref sd_ble_opt_get is not supported for this option. + * + */ +typedef struct +{ + uint8_t const * p_passkey; /**< Pointer to 6-digit ASCII string (digit 0..9 only, no NULL termination) passkey to be used during pairing. If this is NULL, the SoftDevice will generate a random passkey if required.*/ +} ble_gap_opt_passkey_t; + + +/**@brief Compatibility mode 1 option. + * + * @details This can be used with @ref sd_ble_opt_set to enable and disable + * compatibility mode 1. Compatibility mode 1 is disabled by default. + * + * @note Compatibility mode 1 enables interoperability with devices that do not support a value of + * 0 for the WinOffset parameter in the Link Layer CONNECT_IND packet. This applies to a + * limited set of legacy peripheral devices from another vendor. Enabling this compatibility + * mode will only have an effect if the local device will act as a central device and + * initiate a connection to a peripheral device. In that case it may lead to the connection + * creation taking up to one connection interval longer to complete for all connections. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_INVALID_STATE When connection creation is ongoing while mode 1 is set. + */ +typedef struct +{ + uint8_t enable : 1; /**< Enable compatibility mode 1.*/ +} ble_gap_opt_compat_mode_1_t; + + +/**@brief Authenticated payload timeout option. + * + * @details This can be used with @ref sd_ble_opt_set to change the Authenticated payload timeout to a value other + * than the default of @ref BLE_GAP_AUTH_PAYLOAD_TIMEOUT_MAX. + * + * @note The authenticated payload timeout event ::BLE_GAP_TIMEOUT_SRC_AUTH_PAYLOAD will be generated + * if auth_payload_timeout time has elapsed without receiving a packet with a valid MIC on an encrypted + * link. + * + * @note The LE ping procedure will be initiated before the timer expires to give the peer a chance + * to reset the timer. In addition the stack will try to prioritize running of LE ping over other + * activities to increase chances of finishing LE ping before timer expires. To avoid side-effects + * on other activities, it is recommended to use high timeout values. + * Recommended timeout > 2*(connInterval * (6 + connSlaveLatency)). + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. auth_payload_timeout was outside of allowed range. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter. + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle */ + uint16_t auth_payload_timeout; /**< Requested timeout in 10 ms unit, see @ref BLE_GAP_AUTH_PAYLOAD_TIMEOUT. */ +} ble_gap_opt_auth_payload_timeout_t; + +/**@brief Option structure for GAP options. */ +typedef union +{ + ble_gap_opt_ch_map_t ch_map; /**< Parameters for the Channel Map option. */ + ble_gap_opt_local_conn_latency_t local_conn_latency; /**< Parameters for the Local connection latency option */ + ble_gap_opt_passkey_t passkey; /**< Parameters for the Passkey option.*/ + ble_gap_opt_compat_mode_1_t compat_mode_1; /**< Parameters for the compatibility mode 1 option.*/ + ble_gap_opt_auth_payload_timeout_t auth_payload_timeout; /**< Parameters for the authenticated payload timeout option.*/ + ble_gap_opt_slave_latency_disable_t slave_latency_disable; /**< Parameters for the Disable slave latency option */ +} ble_gap_opt_t; + +/**@brief Connection event triggering parameters. */ +typedef struct +{ + uint8_t ppi_ch_id; /**< PPI channel to use. This channel should be regarded as reserved until + connection event PPI task triggering is stopped. + The PPI channel ID can not be one of the PPI channels reserved by + the SoftDevice. See @ref NRF_SOC_SD_PPI_CHANNELS_SD_ENABLED_MSK. */ + uint32_t task_endpoint; /**< Task Endpoint to trigger. */ + uint16_t conn_evt_counter_start; /**< The connection event on which the task triggering should start. */ + uint16_t period_in_events; /**< Trigger period. Valid range is [1, 32767]. + If the device is in slave role and slave latency is enabled, + this parameter should be set to a multiple of (slave latency + 1) + to ensure low power operation. */ +} ble_gap_conn_event_trigger_t; +/**@} */ + +/**@addtogroup BLE_GAP_FUNCTIONS Functions + * @{ */ + +/**@brief Set the local Bluetooth identity address. + * + * The local Bluetooth identity address is the address that identifies this device to other peers. + * The address type must be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC. + * + * @note The identity address cannot be changed while advertising, scanning or creating a connection. + * + * @note This address will be distributed to the peer during bonding. + * If the address changes, the address stored in the peer device will not be valid and the ability to + * reconnect using the old address will be lost. + * + * @note By default the SoftDevice will set an address of type @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC upon being + * enabled. The address is a random number populated during the IC manufacturing process and remains unchanged + * for the lifetime of each IC. + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @endmscs + * + * @param[in] p_addr Pointer to address structure. + * + * @retval ::NRF_SUCCESS Address successfully set. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::NRF_ERROR_INVALID_STATE The identity address cannot be changed while advertising, + * scanning or creating a connection. + */ +SVCALL(SD_BLE_GAP_ADDR_SET, uint32_t, sd_ble_gap_addr_set(ble_gap_addr_t const *p_addr)); + + +/**@brief Get local Bluetooth identity address. + * + * @note This will always return the identity address irrespective of the privacy settings, + * i.e. the address type will always be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC. + * + * @param[out] p_addr Pointer to address structure to be filled in. + * + * @retval ::NRF_SUCCESS Address successfully retrieved. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid or NULL pointer supplied. + */ +SVCALL(SD_BLE_GAP_ADDR_GET, uint32_t, sd_ble_gap_addr_get(ble_gap_addr_t *p_addr)); + + +/**@brief Get the Bluetooth device address used by the advertiser. + * + * @note This function will return the local Bluetooth address used in advertising PDUs. When + * using privacy, the SoftDevice will generate a new private address every + * @ref ble_gap_privacy_params_t::private_addr_cycle_s configured using + * @ref sd_ble_gap_privacy_set. Hence depending on when the application calls this API, the + * address returned may not be the latest address that is used in the advertising PDUs. + * + * @param[in] adv_handle The advertising handle to get the address from. + * @param[out] p_addr Pointer to address structure to be filled in. + * + * @retval ::NRF_SUCCESS Address successfully retrieved. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid or NULL pointer supplied. + * @retval ::BLE_ERROR_INVALID_ADV_HANDLE The provided advertising handle was not found. + * @retval ::NRF_ERROR_INVALID_STATE The advertising set is currently not advertising. + */ +SVCALL(SD_BLE_GAP_ADV_ADDR_GET, uint32_t, sd_ble_gap_adv_addr_get(uint8_t adv_handle, ble_gap_addr_t *p_addr)); + + +/**@brief Set the active whitelist in the SoftDevice. + * + * @note Only one whitelist can be used at a time and the whitelist is shared between the BLE roles. + * The whitelist cannot be set if a BLE role is using the whitelist. + * + * @note If an address is resolved using the information in the device identity list, then the whitelist + * filter policy applies to the peer identity address and not the resolvable address sent on air. + * + * @mscs + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_SCAN_PRIVATE_SCAN_MSC} + * @endmscs + * + * @param[in] pp_wl_addrs Pointer to a whitelist of peer addresses, if NULL the whitelist will be cleared. + * @param[in] len Length of the whitelist, maximum @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. + * + * @retval ::NRF_SUCCESS The whitelist is successfully set/cleared. + * @retval ::NRF_ERROR_INVALID_ADDR The whitelist (or one of its entries) provided is invalid. + * @retval ::BLE_ERROR_GAP_WHITELIST_IN_USE The whitelist is in use by a BLE role and cannot be set or cleared. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address type is supplied. + * @retval ::NRF_ERROR_DATA_SIZE The given whitelist size is invalid (zero or too large); this can only return when + * pp_wl_addrs is not NULL. + */ +SVCALL(SD_BLE_GAP_WHITELIST_SET, uint32_t, sd_ble_gap_whitelist_set(ble_gap_addr_t const * const * pp_wl_addrs, uint8_t len)); + + +/**@brief Set device identity list. + * + * @note Only one device identity list can be used at a time and the list is shared between the BLE roles. + * The device identity list cannot be set if a BLE role is using the list. + * + * @param[in] pp_id_keys Pointer to an array of peer identity addresses and peer IRKs, if NULL the device identity list will be cleared. + * @param[in] pp_local_irks Pointer to an array of local IRKs. Each entry in the array maps to the entry in pp_id_keys at the same index. + * To fill in the list with the currently set device IRK for all peers, set to NULL. + * @param[in] len Length of the device identity list, maximum @ref BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT. + * + * @mscs + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_SCAN_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_SCAN_PRIVATE_SCAN_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_DIR_PRIV_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_CONN_PRIV_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_CONN_PRIV_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS The device identity list successfully set/cleared. + * @retval ::NRF_ERROR_INVALID_ADDR The device identity list (or one of its entries) provided is invalid. + * This code may be returned if the local IRK list also has an invalid entry. + * @retval ::BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE The device identity list is in use and cannot be set or cleared. + * @retval ::BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE The device identity list contains multiple entries with the same identity address. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address type is supplied. + * @retval ::NRF_ERROR_DATA_SIZE The given device identity list size invalid (zero or too large); this can + * only return when pp_id_keys is not NULL. + */ +SVCALL(SD_BLE_GAP_DEVICE_IDENTITIES_SET, uint32_t, sd_ble_gap_device_identities_set(ble_gap_id_key_t const * const * pp_id_keys, ble_gap_irk_t const * const * pp_local_irks, uint8_t len)); + + +/**@brief Set privacy settings. + * + * @note Privacy settings cannot be changed while advertising, scanning or creating a connection. + * + * @param[in] p_privacy_params Privacy settings. + * + * @mscs + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_SCAN_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_DIR_PRIV_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address type is supplied. + * @retval ::NRF_ERROR_INVALID_ADDR The pointer to privacy settings is NULL or invalid. + * Otherwise, the p_device_irk pointer in privacy parameter is an invalid pointer. + * @retval ::NRF_ERROR_INVALID_PARAM Out of range parameters are provided. + * @retval ::NRF_ERROR_NOT_SUPPORTED The SoftDevice does not support privacy if the Central Address Resolution + characteristic is not configured to be included and the SoftDevice is configured + to support central roles. + See @ref ble_gap_cfg_car_incl_cfg_t and @ref ble_gap_cfg_role_count_t. + * @retval ::NRF_ERROR_INVALID_STATE Privacy settings cannot be changed while advertising, scanning + * or creating a connection. + */ +SVCALL(SD_BLE_GAP_PRIVACY_SET, uint32_t, sd_ble_gap_privacy_set(ble_gap_privacy_params_t const *p_privacy_params)); + + +/**@brief Get privacy settings. + * + * @note ::ble_gap_privacy_params_t::p_device_irk must be initialized to NULL or a valid address before this function is called. + * If it is initialized to a valid address, the address pointed to will contain the current device IRK on return. + * + * @param[in,out] p_privacy_params Privacy settings. + * + * @retval ::NRF_SUCCESS Privacy settings read. + * @retval ::NRF_ERROR_INVALID_ADDR The pointer given for returning the privacy settings may be NULL or invalid. + * Otherwise, the p_device_irk pointer in privacy parameter is an invalid pointer. + */ +SVCALL(SD_BLE_GAP_PRIVACY_GET, uint32_t, sd_ble_gap_privacy_get(ble_gap_privacy_params_t *p_privacy_params)); + + +/**@brief Configure an advertising set. Set, clear or update advertising and scan response data. + * + * @note The format of the advertising data will be checked by this call to ensure interoperability. + * Limitations imposed by this API call to the data provided include having a flags data type in the scan response data and + * duplicating the local name in the advertising data and scan response data. + * + * @note In order to update advertising data while advertising, new advertising buffers must be provided. + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @param[in,out] p_adv_handle Provide a pointer to a handle containing @ref BLE_GAP_ADV_SET_HANDLE_NOT_SET to configure + * a new advertising set. On success, a new handle is then returned through the pointer. + * Provide a pointer to an existing advertising handle to configure an existing advertising set. + * @param[in] p_adv_data Advertising data. If set to NULL, no advertising data will be used. See @ref ble_gap_adv_data_t. + * @param[in] p_adv_params Advertising parameters. When this function is used to update advertising data while advertising, + * this parameter must be NULL. See @ref ble_gap_adv_params_t. + * + * @retval ::NRF_SUCCESS Advertising set successfully configured. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied: + * - Invalid advertising data configuration specified. See @ref ble_gap_adv_data_t. + * - Invalid configuration of p_adv_params. See @ref ble_gap_adv_params_t. + * - Use of whitelist requested but whitelist has not been set, + * see @ref sd_ble_gap_whitelist_set. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR ble_gap_adv_params_t::p_peer_addr is invalid. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. Either: + * - It is invalid to provide non-NULL advertising set parameters while advertising. + * - It is invalid to provide the same data buffers while advertising. To update + * advertising data, provide new advertising buffers. + * @retval ::BLE_ERROR_GAP_DISCOVERABLE_WITH_WHITELIST Discoverable mode and whitelist incompatible. + * @retval ::BLE_ERROR_INVALID_ADV_HANDLE The provided advertising handle was not found. Use @ref BLE_GAP_ADV_SET_HANDLE_NOT_SET to + * configure a new advertising handle. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_FLAGS Invalid combination of advertising flags supplied. + * @retval ::NRF_ERROR_INVALID_DATA Invalid data type(s) supplied. Check the advertising data format specification + * given in Bluetooth Specification Version 5.0, Volume 3, Part C, Chapter 11. + * @retval ::NRF_ERROR_INVALID_LENGTH Invalid data length(s) supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED Unsupported data length or advertising parameter configuration. + * @retval ::NRF_ERROR_NO_MEM Not enough memory to configure a new advertising handle. Update an + * existing advertising handle instead. + * @retval ::BLE_ERROR_GAP_UUID_LIST_MISMATCH Invalid UUID list supplied. + */ +SVCALL(SD_BLE_GAP_ADV_SET_CONFIGURE, uint32_t, sd_ble_gap_adv_set_configure(uint8_t *p_adv_handle, ble_gap_adv_data_t const *p_adv_data, ble_gap_adv_params_t const *p_adv_params)); + + +/**@brief Start advertising (GAP Discoverable, Connectable modes, Broadcast Procedure). + * + * @note Only one advertiser may be active at any time. + * + * @note If privacy is enabled, the advertiser's private address will be refreshed when this function is called. + * See @ref sd_ble_gap_privacy_set(). + * + * @events + * @event{@ref BLE_GAP_EVT_CONNECTED, Generated after connection has been established through connectable advertising.} + * @event{@ref BLE_GAP_EVT_ADV_SET_TERMINATED, Advertising set has terminated.} + * @event{@ref BLE_GAP_EVT_SCAN_REQ_REPORT, A scan request was received.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_CONN_PRIV_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_DIR_PRIV_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @param[in] adv_handle Advertising handle to advertise on, received from @ref sd_ble_gap_adv_set_configure. + * @param[in] conn_cfg_tag Tag identifying a configuration set by @ref sd_ble_cfg_set or + * @ref BLE_CONN_CFG_TAG_DEFAULT to use the default connection configuration. For non-connectable + * advertising, this is ignored. + * + * @retval ::NRF_SUCCESS The BLE stack has started advertising. + * @retval ::NRF_ERROR_INVALID_STATE adv_handle is not configured or already advertising. + * @retval ::NRF_ERROR_CONN_COUNT The limit of available connections for this connection configuration + * tag has been reached; connectable advertiser cannot be started. + * To increase the number of available connections, + * use @ref sd_ble_cfg_set with @ref BLE_GAP_CFG_ROLE_COUNT or @ref BLE_CONN_CFG_GAP. + * @retval ::BLE_ERROR_INVALID_ADV_HANDLE Advertising handle not found. Configure a new adveriting handle with @ref sd_ble_gap_adv_set_configure. + * @retval ::NRF_ERROR_NOT_FOUND conn_cfg_tag not found. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied: + * - Invalid configuration of p_adv_params. See @ref ble_gap_adv_params_t. + * - Use of whitelist requested but whitelist has not been set, see @ref sd_ble_gap_whitelist_set. + * @retval ::NRF_ERROR_RESOURCES Either: + * - adv_handle is configured with connectable advertising, but the event_length parameter + * associated with conn_cfg_tag is too small to be able to establish a connection on + * the selected advertising phys. Use @ref sd_ble_cfg_set to increase the event length. + * - Not enough BLE role slots available. + Stop one or more currently active roles (Central, Peripheral, Broadcaster or Observer) and try again. + * - p_adv_params is configured with connectable advertising, but the event_length parameter + * associated with conn_cfg_tag is too small to be able to establish a connection on + * the selected advertising phys. Use @ref sd_ble_cfg_set to increase the event length. + */ +SVCALL(SD_BLE_GAP_ADV_START, uint32_t, sd_ble_gap_adv_start(uint8_t adv_handle, uint8_t conn_cfg_tag)); + + +/**@brief Stop advertising (GAP Discoverable, Connectable modes, Broadcast Procedure). + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @param[in] adv_handle The advertising handle that should stop advertising. + * + * @retval ::NRF_SUCCESS The BLE stack has stopped advertising. + * @retval ::BLE_ERROR_INVALID_ADV_HANDLE Invalid advertising handle. + * @retval ::NRF_ERROR_INVALID_STATE The advertising handle is not advertising. + */ +SVCALL(SD_BLE_GAP_ADV_STOP, uint32_t, sd_ble_gap_adv_stop(uint8_t adv_handle)); + + + +/**@brief Update connection parameters. + * + * @details In the central role this will initiate a Link Layer connection parameter update procedure, + * otherwise in the peripheral role, this will send the corresponding L2CAP request and wait for + * the central to perform the procedure. In both cases, and regardless of success or failure, the application + * will be informed of the result with a @ref BLE_GAP_EVT_CONN_PARAM_UPDATE event. + * + * @details This function can be used as a central both to reply to a @ref BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST or to start the procedure unrequested. + * + * @events + * @event{@ref BLE_GAP_EVT_CONN_PARAM_UPDATE, Result of the connection parameter update procedure.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CPU_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_ENC_AUTH_MUTEX_MSC} + * @mmsc{@ref BLE_GAP_MULTILINK_CPU_MSC} + * @mmsc{@ref BLE_GAP_MULTILINK_CTRL_PROC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_CPU_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_conn_params Pointer to desired connection parameters. If NULL is provided on a peripheral role, + * the parameters in the PPCP characteristic of the GAP service will be used instead. + * If NULL is provided on a central role and in response to a @ref BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST, the peripheral request will be rejected + * + * @retval ::NRF_SUCCESS The Connection Update procedure has been started successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check parameter limits and constraints. + * @retval ::NRF_ERROR_INVALID_STATE Disconnection in progress or link has not been established. + * @retval ::NRF_ERROR_BUSY Procedure already in progress, wait for pending procedures to complete and retry. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation. + */ +SVCALL(SD_BLE_GAP_CONN_PARAM_UPDATE, uint32_t, sd_ble_gap_conn_param_update(uint16_t conn_handle, ble_gap_conn_params_t const *p_conn_params)); + + +/**@brief Disconnect (GAP Link Termination). + * + * @details This call initiates the disconnection procedure, and its completion will be communicated to the application + * with a @ref BLE_GAP_EVT_DISCONNECTED event. + * + * @events + * @event{@ref BLE_GAP_EVT_DISCONNECTED, Generated when disconnection procedure is complete.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CONN_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] hci_status_code HCI status code, see @ref BLE_HCI_STATUS_CODES (accepted values are @ref BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION and @ref BLE_HCI_CONN_INTERVAL_UNACCEPTABLE). + * + * @retval ::NRF_SUCCESS The disconnection procedure has been started successfully. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_INVALID_STATE Disconnection in progress or link has not been established. + */ +SVCALL(SD_BLE_GAP_DISCONNECT, uint32_t, sd_ble_gap_disconnect(uint16_t conn_handle, uint8_t hci_status_code)); + + +/**@brief Set the radio's transmit power. + * + * @param[in] role The role to set the transmit power for, see @ref BLE_GAP_TX_POWER_ROLES for + * possible roles. + * @param[in] handle The handle parameter is interpreted depending on role: + * - If role is @ref BLE_GAP_TX_POWER_ROLE_CONN, this value is the specific connection handle. + * - If role is @ref BLE_GAP_TX_POWER_ROLE_ADV, the advertising set identified with the advertising handle, + * will use the specified transmit power, and include it in the advertising packet headers if + * @ref ble_gap_adv_properties_t::include_tx_power set. + * - For all other roles handle is ignored. + * @param[in] tx_power Radio transmit power in dBm (see note for accepted values). + * + * @note Supported tx_power values: -40dBm, -20dBm, -16dBm, -12dBm, -8dBm, -4dBm, 0dBm, +3dBm and +4dBm. + * In addition, on some chips following values are supported: +2dBm, +5dBm, +6dBm, +7dBm and +8dBm. + * Setting these values on a chip that does not support them will result in undefined behaviour. + * @note The initiator will have the same transmit power as the scanner. + * @note When a connection is created it will inherit the transmit power from the initiator or + * advertiser leading to the connection. + * + * @retval ::NRF_SUCCESS Successfully changed the transmit power. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::BLE_ERROR_INVALID_ADV_HANDLE Advertising handle not found. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_TX_POWER_SET, uint32_t, sd_ble_gap_tx_power_set(uint8_t role, uint16_t handle, int8_t tx_power)); + + +/**@brief Set GAP Appearance value. + * + * @param[in] appearance Appearance (16-bit), see @ref BLE_APPEARANCES. + * + * @retval ::NRF_SUCCESS Appearance value set successfully. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + */ +SVCALL(SD_BLE_GAP_APPEARANCE_SET, uint32_t, sd_ble_gap_appearance_set(uint16_t appearance)); + + +/**@brief Get GAP Appearance value. + * + * @param[out] p_appearance Pointer to appearance (16-bit) to be filled in, see @ref BLE_APPEARANCES. + * + * @retval ::NRF_SUCCESS Appearance value retrieved successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + */ +SVCALL(SD_BLE_GAP_APPEARANCE_GET, uint32_t, sd_ble_gap_appearance_get(uint16_t *p_appearance)); + + +/**@brief Set GAP Peripheral Preferred Connection Parameters. + * + * @param[in] p_conn_params Pointer to a @ref ble_gap_conn_params_t structure with the desired parameters. + * + * @retval ::NRF_SUCCESS Peripheral Preferred Connection Parameters set successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED The characteristic is not included in the Attribute Table, + see @ref ble_gap_cfg_ppcp_incl_cfg_t. + */ +SVCALL(SD_BLE_GAP_PPCP_SET, uint32_t, sd_ble_gap_ppcp_set(ble_gap_conn_params_t const *p_conn_params)); + + +/**@brief Get GAP Peripheral Preferred Connection Parameters. + * + * @param[out] p_conn_params Pointer to a @ref ble_gap_conn_params_t structure where the parameters will be stored. + * + * @retval ::NRF_SUCCESS Peripheral Preferred Connection Parameters retrieved successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED The characteristic is not included in the Attribute Table, + see @ref ble_gap_cfg_ppcp_incl_cfg_t. + */ +SVCALL(SD_BLE_GAP_PPCP_GET, uint32_t, sd_ble_gap_ppcp_get(ble_gap_conn_params_t *p_conn_params)); + + +/**@brief Set GAP device name. + * + * @note If the device name is located in application flash memory (see @ref ble_gap_cfg_device_name_t), + * it cannot be changed. Then @ref NRF_ERROR_FORBIDDEN will be returned. + * + * @param[in] p_write_perm Write permissions for the Device Name characteristic, see @ref ble_gap_conn_sec_mode_t. + * @param[in] p_dev_name Pointer to a UTF-8 encoded, non NULL-terminated string. + * @param[in] len Length of the UTF-8, non NULL-terminated string pointed to by p_dev_name in octets (must be smaller or equal than @ref BLE_GAP_DEVNAME_MAX_LEN). + * + * @retval ::NRF_SUCCESS GAP device name and permissions set successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied. + * @retval ::NRF_ERROR_FORBIDDEN Device name is not writable. + */ +SVCALL(SD_BLE_GAP_DEVICE_NAME_SET, uint32_t, sd_ble_gap_device_name_set(ble_gap_conn_sec_mode_t const *p_write_perm, uint8_t const *p_dev_name, uint16_t len)); + + +/**@brief Get GAP device name. + * + * @note If the device name is longer than the size of the supplied buffer, + * p_len will return the complete device name length, + * and not the number of bytes actually returned in p_dev_name. + * The application may use this information to allocate a suitable buffer size. + * + * @param[out] p_dev_name Pointer to an empty buffer where the UTF-8 non NULL-terminated string will be placed. Set to NULL to obtain the complete device name length. + * @param[in,out] p_len Length of the buffer pointed by p_dev_name, complete device name length on output. + * + * @retval ::NRF_SUCCESS GAP device name retrieved successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied. + */ +SVCALL(SD_BLE_GAP_DEVICE_NAME_GET, uint32_t, sd_ble_gap_device_name_get(uint8_t *p_dev_name, uint16_t *p_len)); + + +/**@brief Initiate the GAP Authentication procedure. + * + * @details In the central role, this function will send an SMP Pairing Request (or an SMP Pairing Failed if rejected), + * otherwise in the peripheral role, an SMP Security Request will be sent. + * + * @events + * @event{Depending on the security parameters set and the packet exchanges with the peer\, the following events may be generated:} + * @event{@ref BLE_GAP_EVT_SEC_PARAMS_REQUEST} + * @event{@ref BLE_GAP_EVT_SEC_INFO_REQUEST} + * @event{@ref BLE_GAP_EVT_PASSKEY_DISPLAY} + * @event{@ref BLE_GAP_EVT_KEY_PRESSED} + * @event{@ref BLE_GAP_EVT_AUTH_KEY_REQUEST} + * @event{@ref BLE_GAP_EVT_LESC_DHKEY_REQUEST} + * @event{@ref BLE_GAP_EVT_CONN_SEC_UPDATE} + * @event{@ref BLE_GAP_EVT_AUTH_STATUS} + * @event{@ref BLE_GAP_EVT_TIMEOUT} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_SEC_REQ_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_SEC_REQ_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_ENC_AUTH_MUTEX_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_sec_params Pointer to the @ref ble_gap_sec_params_t structure with the security parameters to be used during the pairing or bonding procedure. + * In the peripheral role, only the bond, mitm, lesc and keypress fields of this structure are used. + * In the central role, this pointer may be NULL to reject a Security Request. + * + * @retval ::NRF_SUCCESS Successfully initiated authentication procedure. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. Either: + * - No link has been established. + * - An encryption is already executing or queued. + * @retval ::NRF_ERROR_NO_MEM The maximum number of authentication procedures that can run in parallel for the given role is reached. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED Setting of sign or link fields in @ref ble_gap_sec_kdist_t not supported. + * Distribution of own Identity Information is only supported if the Central + * Address Resolution characteristic is configured to be included or + * the Softdevice is configured to support peripheral roles only. + * See @ref ble_gap_cfg_car_incl_cfg_t and @ref ble_gap_cfg_role_count_t. + * @retval ::NRF_ERROR_TIMEOUT A SMP timeout has occurred, and further SMP operations on this link is prohibited. + */ +SVCALL(SD_BLE_GAP_AUTHENTICATE, uint32_t, sd_ble_gap_authenticate(uint16_t conn_handle, ble_gap_sec_params_t const *p_sec_params)); + + +/**@brief Reply with GAP security parameters. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST, calling it at other times will result in an @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * + * @events + * @event{This function is used during authentication procedures, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_PK_PERIPH_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_PK_CENTRAL_OOB_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_STATIC_PK_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_CONFIRM_FAIL_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_KS_TOO_SMALL_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_APP_ERROR_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_REMOTE_PAIRING_FAIL_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_TIMEOUT_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] sec_status Security status, see @ref BLE_GAP_SEC_STATUS. + * @param[in] p_sec_params Pointer to a @ref ble_gap_sec_params_t security parameters structure. In the central role this must be set to NULL, as the parameters have + * already been provided during a previous call to @ref sd_ble_gap_authenticate. + * @param[in,out] p_sec_keyset Pointer to a @ref ble_gap_sec_keyset_t security keyset structure. Any keys generated and/or distributed as a result of the ongoing security procedure + * will be stored into the memory referenced by the pointers inside this structure. The keys will be stored and available to the application + * upon reception of a @ref BLE_GAP_EVT_AUTH_STATUS event. + * Note that the SoftDevice expects the application to provide memory for storing the + * peer's keys. So it must be ensured that the relevant pointers inside this structure are not NULL. The pointers to the local key + * can, however, be NULL, in which case, the local key data will not be available to the application upon reception of the + * @ref BLE_GAP_EVT_AUTH_STATUS event. + * + * @retval ::NRF_SUCCESS Successfully accepted security parameter from the application. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Security parameters has not been requested. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED Setting of sign or link fields in @ref ble_gap_sec_kdist_t not supported. + * Distribution of own Identity Information is only supported if the Central + * Address Resolution characteristic is configured to be included or + * the Softdevice is configured to support peripheral roles only. + * See @ref ble_gap_cfg_car_incl_cfg_t and @ref ble_gap_cfg_role_count_t. + */ +SVCALL(SD_BLE_GAP_SEC_PARAMS_REPLY, uint32_t, sd_ble_gap_sec_params_reply(uint16_t conn_handle, uint8_t sec_status, ble_gap_sec_params_t const *p_sec_params, ble_gap_sec_keyset_t const *p_sec_keyset)); + + +/**@brief Reply with an authentication key. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_AUTH_KEY_REQUEST or a @ref BLE_GAP_EVT_PASSKEY_DISPLAY, calling it at other times will result in an @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_PK_CENTRAL_OOB_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] key_type See @ref BLE_GAP_AUTH_KEY_TYPES. + * @param[in] p_key If key type is @ref BLE_GAP_AUTH_KEY_TYPE_NONE, then NULL. + * If key type is @ref BLE_GAP_AUTH_KEY_TYPE_PASSKEY, then a 6-byte ASCII string (digit 0..9 only, no NULL termination) + * or NULL when confirming LE Secure Connections Numeric Comparison. + * If key type is @ref BLE_GAP_AUTH_KEY_TYPE_OOB, then a 16-byte OOB key value in little-endian format. + * + * @retval ::NRF_SUCCESS Authentication key successfully set. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Authentication key has not been requested. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_AUTH_KEY_REPLY, uint32_t, sd_ble_gap_auth_key_reply(uint16_t conn_handle, uint8_t key_type, uint8_t const *p_key)); + + +/**@brief Reply with an LE Secure connections DHKey. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_LESC_DHKEY_REQUEST, calling it at other times will result in an @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_dhkey LE Secure Connections DHKey. + * + * @retval ::NRF_SUCCESS DHKey successfully set. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. Either: + * - The peer is not authenticated. + * - The application has not pulled a @ref BLE_GAP_EVT_LESC_DHKEY_REQUEST event. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_LESC_DHKEY_REPLY, uint32_t, sd_ble_gap_lesc_dhkey_reply(uint16_t conn_handle, ble_gap_lesc_dhkey_t const *p_dhkey)); + + +/**@brief Notify the peer of a local keypress. + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] kp_not See @ref BLE_GAP_KP_NOT_TYPES. + * + * @retval ::NRF_SUCCESS Keypress notification successfully queued for transmission. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. Either: + * - Authentication key not requested. + * - Passkey has not been entered. + * - Keypresses have not been enabled by both peers. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_BUSY The BLE stack is busy. Retry at later time. + */ +SVCALL(SD_BLE_GAP_KEYPRESS_NOTIFY, uint32_t, sd_ble_gap_keypress_notify(uint16_t conn_handle, uint8_t kp_not)); + + +/**@brief Generate a set of OOB data to send to a peer out of band. + * + * @note The @ref ble_gap_addr_t included in the OOB data returned will be the currently active one (or, if a connection has already been established, + * the one used during connection setup). The application may manually overwrite it with an updated value. + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. Can be @ref BLE_CONN_HANDLE_INVALID if a BLE connection has not been established yet. + * @param[in] p_pk_own LE Secure Connections local P-256 Public Key. + * @param[out] p_oobd_own The OOB data to be sent out of band to a peer. + * + * @retval ::NRF_SUCCESS OOB data successfully generated. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_LESC_OOB_DATA_GET, uint32_t, sd_ble_gap_lesc_oob_data_get(uint16_t conn_handle, ble_gap_lesc_p256_pk_t const *p_pk_own, ble_gap_lesc_oob_data_t *p_oobd_own)); + +/**@brief Provide the OOB data sent/received out of band. + * + * @note An authentication procedure with OOB selected as an algorithm must be in progress when calling this function. + * @note A @ref BLE_GAP_EVT_LESC_DHKEY_REQUEST event with the oobd_req set to 1 must have been received prior to calling this function. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_oobd_own The OOB data sent out of band to a peer or NULL if the peer has not received OOB data. + * Must correspond to @ref ble_gap_sec_params_t::oob flag in @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST. + * @param[in] p_oobd_peer The OOB data received out of band from a peer or NULL if none received. + * Must correspond to @ref ble_gap_sec_params_t::oob flag + * in @ref sd_ble_gap_authenticate in the central role or + * in @ref sd_ble_gap_sec_params_reply in the peripheral role. + * + * @retval ::NRF_SUCCESS OOB data accepted. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. Either: + * - Authentication key not requested + * - Not expecting LESC OOB data + * - Have not actually exchanged passkeys. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_LESC_OOB_DATA_SET, uint32_t, sd_ble_gap_lesc_oob_data_set(uint16_t conn_handle, ble_gap_lesc_oob_data_t const *p_oobd_own, ble_gap_lesc_oob_data_t const *p_oobd_peer)); + + +/**@brief Initiate GAP Encryption procedure. + * + * @details In the central role, this function will initiate the encryption procedure using the encryption information provided. + * + * @events + * @event{@ref BLE_GAP_EVT_CONN_SEC_UPDATE, The connection security has been updated.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_ENC_AUTH_MUTEX_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_ENC_MSC} + * @mmsc{@ref BLE_GAP_MULTILINK_CTRL_PROC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_SEC_REQ_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_master_id Pointer to a @ref ble_gap_master_id_t master identification structure. + * @param[in] p_enc_info Pointer to a @ref ble_gap_enc_info_t encryption information structure. + * + * @retval ::NRF_SUCCESS Successfully initiated authentication procedure. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE No link has been established. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::BLE_ERROR_INVALID_ROLE Operation is not supported in the Peripheral role. + * @retval ::NRF_ERROR_BUSY Procedure already in progress or not allowed at this time, wait for pending procedures to complete and retry. + */ +SVCALL(SD_BLE_GAP_ENCRYPT, uint32_t, sd_ble_gap_encrypt(uint16_t conn_handle, ble_gap_master_id_t const *p_master_id, ble_gap_enc_info_t const *p_enc_info)); + + +/**@brief Reply with GAP security information. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_SEC_INFO_REQUEST, calling it at other times will result in @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * @note Data signing is not yet supported, and p_sign_info must therefore be NULL. + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_ENC_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_enc_info Pointer to a @ref ble_gap_enc_info_t encryption information structure. May be NULL to signal none is available. + * @param[in] p_id_info Pointer to a @ref ble_gap_irk_t identity information structure. May be NULL to signal none is available. + * @param[in] p_sign_info Pointer to a @ref ble_gap_sign_info_t signing information structure. May be NULL to signal none is available. + * + * @retval ::NRF_SUCCESS Successfully accepted security information. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. Either: + * - No link has been established. + * - No @ref BLE_GAP_EVT_SEC_INFO_REQUEST pending. + * - Encryption information provided by the app without being requested. See @ref ble_gap_evt_sec_info_request_t::enc_info. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_SEC_INFO_REPLY, uint32_t, sd_ble_gap_sec_info_reply(uint16_t conn_handle, ble_gap_enc_info_t const *p_enc_info, ble_gap_irk_t const *p_id_info, ble_gap_sign_info_t const *p_sign_info)); + + +/**@brief Get the current connection security. + * + * @param[in] conn_handle Connection handle. + * @param[out] p_conn_sec Pointer to a @ref ble_gap_conn_sec_t structure to be filled in. + * + * @retval ::NRF_SUCCESS Current connection security successfully retrieved. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_CONN_SEC_GET, uint32_t, sd_ble_gap_conn_sec_get(uint16_t conn_handle, ble_gap_conn_sec_t *p_conn_sec)); + + +/**@brief Start reporting the received signal strength to the application. + * + * A new event is reported whenever the RSSI value changes, until @ref sd_ble_gap_rssi_stop is called. + * + * @events + * @event{@ref BLE_GAP_EVT_RSSI_CHANGED, New RSSI data available. How often the event is generated is + * dependent on the settings of the threshold_dbm + * and skip_count input parameters.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_RSSI_READ_MSC} + * @mmsc{@ref BLE_GAP_RSSI_FILT_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] threshold_dbm Minimum change in dBm before triggering the @ref BLE_GAP_EVT_RSSI_CHANGED event. Events are disabled if threshold_dbm equals @ref BLE_GAP_RSSI_THRESHOLD_INVALID. + * @param[in] skip_count Number of RSSI samples with a change of threshold_dbm or more before sending a new @ref BLE_GAP_EVT_RSSI_CHANGED event. + * + * @retval ::NRF_SUCCESS Successfully activated RSSI reporting. + * @retval ::NRF_ERROR_INVALID_STATE RSSI reporting is already ongoing. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_RSSI_START, uint32_t, sd_ble_gap_rssi_start(uint16_t conn_handle, uint8_t threshold_dbm, uint8_t skip_count)); + + +/**@brief Stop reporting the received signal strength. + * + * @note An RSSI change detected before the call but not yet received by the application + * may be reported after @ref sd_ble_gap_rssi_stop has been called. + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_RSSI_READ_MSC} + * @mmsc{@ref BLE_GAP_RSSI_FILT_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * + * @retval ::NRF_SUCCESS Successfully deactivated RSSI reporting. + * @retval ::NRF_ERROR_INVALID_STATE RSSI reporting is not ongoing. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_RSSI_STOP, uint32_t, sd_ble_gap_rssi_stop(uint16_t conn_handle)); + + +/**@brief Get the received signal strength for the last connection event. + * + * @ref sd_ble_gap_rssi_start must be called to start reporting RSSI before using this function. @ref NRF_ERROR_NOT_FOUND + * will be returned until RSSI was sampled for the first time after calling @ref sd_ble_gap_rssi_start. + * @note ERRATA-153 and ERRATA-225 require the rssi sample to be compensated based on a temperature measurement. + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_RSSI_READ_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[out] p_rssi Pointer to the location where the RSSI measurement shall be stored. + * @param[out] p_ch_index Pointer to the location where Channel Index for the RSSI measurement shall be stored. + * + * @retval ::NRF_SUCCESS Successfully read the RSSI. + * @retval ::NRF_ERROR_NOT_FOUND No sample is available. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_INVALID_STATE RSSI reporting is not ongoing. + */ +SVCALL(SD_BLE_GAP_RSSI_GET, uint32_t, sd_ble_gap_rssi_get(uint16_t conn_handle, int8_t *p_rssi, uint8_t *p_ch_index)); + + +/**@brief Start or continue scanning (GAP Discovery procedure, Observer Procedure). + * + * @note A call to this function will require the application to keep the memory pointed by + * p_adv_report_buffer alive until the buffer is released. The buffer is released when the scanner is stopped + * or when this function is called with another buffer. + * + * @note The scanner will automatically stop in the following cases: + * - @ref sd_ble_gap_scan_stop is called. + * - @ref sd_ble_gap_connect is called. + * - A @ref BLE_GAP_EVT_TIMEOUT with source set to @ref BLE_GAP_TIMEOUT_SRC_SCAN is received. + * - When a @ref BLE_GAP_EVT_ADV_REPORT event is received and @ref ble_gap_adv_report_type_t::status is not set to + * @ref BLE_GAP_ADV_DATA_STATUS_INCOMPLETE_MORE_DATA. In this case scanning is only paused to let the application + * access received data. The application must call this function to continue scanning, or call @ref sd_ble_gap_scan_stop + * to stop scanning. + * + * @note If a @ref BLE_GAP_EVT_ADV_REPORT event is received with @ref ble_gap_adv_report_type_t::status set to + * @ref BLE_GAP_ADV_DATA_STATUS_INCOMPLETE_MORE_DATA, the scanner will continue scanning, and the application will + * receive more reports from this advertising event. The following reports will include the old and new received data. + * + * @events + * @event{@ref BLE_GAP_EVT_ADV_REPORT, An advertising or scan response packet has been received.} + * @event{@ref BLE_GAP_EVT_TIMEOUT, Scanner has timed out.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_SCAN_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @param[in] p_scan_params Pointer to scan parameters structure. When this function is used to continue + * scanning, this parameter must be NULL. + * @param[in] p_adv_report_buffer Pointer to buffer used to store incoming advertising data. + * The memory pointed to should be kept alive until the scanning is stopped. + * See @ref BLE_GAP_SCAN_BUFFER_SIZE for minimum and maximum buffer size. + * If the scanner receives advertising data larger than can be stored in the buffer, + * a @ref BLE_GAP_EVT_ADV_REPORT will be raised with @ref ble_gap_adv_report_type_t::status + * set to @ref BLE_GAP_ADV_DATA_STATUS_INCOMPLETE_TRUNCATED. + * + * @retval ::NRF_SUCCESS Successfully initiated scanning procedure. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. Either: + * - Scanning is already ongoing and p_scan_params was not NULL + * - Scanning is not running and p_scan_params was NULL. + * - The scanner has timed out when this function is called to continue scanning. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. See @ref ble_gap_scan_params_t. + * @retval ::NRF_ERROR_NOT_SUPPORTED Unsupported parameters supplied. See @ref ble_gap_scan_params_t. + * @retval ::NRF_ERROR_INVALID_LENGTH The provided buffer length is invalid. See @ref BLE_GAP_SCAN_BUFFER_MIN. + * @retval ::NRF_ERROR_RESOURCES Not enough BLE role slots available. + * Stop one or more currently active roles (Central, Peripheral or Broadcaster) and try again + */ +SVCALL(SD_BLE_GAP_SCAN_START, uint32_t, sd_ble_gap_scan_start(ble_gap_scan_params_t const *p_scan_params, ble_data_t const * p_adv_report_buffer)); + + +/**@brief Stop scanning (GAP Discovery procedure, Observer Procedure). + * + * @note The buffer provided in @ref sd_ble_gap_scan_start is released. + * + * @mscs + * @mmsc{@ref BLE_GAP_SCAN_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Successfully stopped scanning procedure. + * @retval ::NRF_ERROR_INVALID_STATE Not in the scanning state. + */ +SVCALL(SD_BLE_GAP_SCAN_STOP, uint32_t, sd_ble_gap_scan_stop(void)); + + +/**@brief Create a connection (GAP Link Establishment). + * + * @note If a scanning procedure is currently in progress it will be automatically stopped when calling this function. + * The scanning procedure will be stopped even if the function returns an error. + * + * @events + * @event{@ref BLE_GAP_EVT_CONNECTED, A connection was established.} + * @event{@ref BLE_GAP_EVT_TIMEOUT, Failed to establish a connection.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_CONN_PRIV_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_CONN_MSC} + * @endmscs + * + * @param[in] p_peer_addr Pointer to peer identity address. If @ref ble_gap_scan_params_t::filter_policy is set to use + * whitelist, then p_peer_addr is ignored. + * @param[in] p_scan_params Pointer to scan parameters structure. + * @param[in] p_conn_params Pointer to desired connection parameters. + * @param[in] conn_cfg_tag Tag identifying a configuration set by @ref sd_ble_cfg_set or + * @ref BLE_CONN_CFG_TAG_DEFAULT to use the default connection configuration. + * + * @retval ::NRF_SUCCESS Successfully initiated connection procedure. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid parameter(s) pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * - Invalid parameter(s) in p_scan_params or p_conn_params. + * - Use of whitelist requested but whitelist has not been set, see @ref sd_ble_gap_whitelist_set. + * - Peer address was not present in the device identity list, see @ref sd_ble_gap_device_identities_set. + * @retval ::NRF_ERROR_NOT_FOUND conn_cfg_tag not found. + * @retval ::NRF_ERROR_INVALID_STATE The SoftDevice is in an invalid state to perform this operation. This may be due to an + * existing locally initiated connect procedure, which must complete before initiating again. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid Peer address. + * @retval ::NRF_ERROR_CONN_COUNT The limit of available connections for this connection configuration tag has been reached. + * To increase the number of available connections, + * use @ref sd_ble_cfg_set with @ref BLE_GAP_CFG_ROLE_COUNT or @ref BLE_CONN_CFG_GAP. + * @retval ::NRF_ERROR_RESOURCES Either: + * - Not enough BLE role slots available. + * Stop one or more currently active roles (Central, Peripheral or Observer) and try again. + * - The event_length parameter associated with conn_cfg_tag is too small to be able to + * establish a connection on the selected @ref ble_gap_scan_params_t::scan_phys. + * Use @ref sd_ble_cfg_set to increase the event length. + */ +SVCALL(SD_BLE_GAP_CONNECT, uint32_t, sd_ble_gap_connect(ble_gap_addr_t const *p_peer_addr, ble_gap_scan_params_t const *p_scan_params, ble_gap_conn_params_t const *p_conn_params, uint8_t conn_cfg_tag)); + + +/**@brief Cancel a connection establishment. + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_CONN_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Successfully canceled an ongoing connection procedure. + * @retval ::NRF_ERROR_INVALID_STATE No locally initiated connect procedure started or connection + * completed occurred. + */ +SVCALL(SD_BLE_GAP_CONNECT_CANCEL, uint32_t, sd_ble_gap_connect_cancel(void)); + + +/**@brief Initiate or respond to a PHY Update Procedure + * + * @details This function is used to initiate or respond to a PHY Update Procedure. It will always + * generate a @ref BLE_GAP_EVT_PHY_UPDATE event if successfully executed. + * If this function is used to initiate a PHY Update procedure and the only option + * provided in @ref ble_gap_phys_t::tx_phys and @ref ble_gap_phys_t::rx_phys is the + * currently active PHYs in the respective directions, the SoftDevice will generate a + * @ref BLE_GAP_EVT_PHY_UPDATE with the current PHYs set and will not initiate the + * procedure in the Link Layer. + * + * If @ref ble_gap_phys_t::tx_phys or @ref ble_gap_phys_t::rx_phys is @ref BLE_GAP_PHY_AUTO, + * then the stack will select PHYs based on the peer's PHY preferences and the local link + * configuration. The PHY Update procedure will for this case result in a PHY combination + * that respects the time constraints configured with @ref sd_ble_cfg_set and the current + * link layer data length. + * + * When acting as a central, the SoftDevice will select the fastest common PHY in each direction. + * + * If the peer does not support the PHY Update Procedure, then the resulting + * @ref BLE_GAP_EVT_PHY_UPDATE event will have a status set to + * @ref BLE_HCI_UNSUPPORTED_REMOTE_FEATURE. + * + * If the PHY Update procedure was rejected by the peer due to a procedure collision, the status + * will be @ref BLE_HCI_STATUS_CODE_LMP_ERROR_TRANSACTION_COLLISION or + * @ref BLE_HCI_DIFFERENT_TRANSACTION_COLLISION. + * If the peer responds to the PHY Update procedure with invalid parameters, the status + * will be @ref BLE_HCI_STATUS_CODE_INVALID_LMP_PARAMETERS. + * If the PHY Update procedure was rejected by the peer for a different reason, the status will + * contain the reason as specified by the peer. + * + * @events + * @event{@ref BLE_GAP_EVT_PHY_UPDATE, Result of the PHY Update Procedure.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_PHY_UPDATE} + * @mmsc{@ref BLE_GAP_PERIPHERAL_PHY_UPDATE} + * @endmscs + * + * @param[in] conn_handle Connection handle to indicate the connection for which the PHY Update is requested. + * @param[in] p_gap_phys Pointer to PHY structure. + * + * @retval ::NRF_SUCCESS Successfully requested a PHY Update. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE No link has been established. + * @retval ::NRF_ERROR_RESOURCES The connection event length configured for this link is not sufficient for the combination of + * @ref ble_gap_phys_t::tx_phys, @ref ble_gap_phys_t::rx_phys, and @ref ble_gap_data_length_params_t. + * The connection event length is configured with @ref BLE_CONN_CFG_GAP using @ref sd_ble_cfg_set. + * @retval ::NRF_ERROR_BUSY Procedure is already in progress or not allowed at this time. Process pending events and wait for the pending procedure to complete and retry. + * + */ +SVCALL(SD_BLE_GAP_PHY_UPDATE, uint32_t, sd_ble_gap_phy_update(uint16_t conn_handle, ble_gap_phys_t const *p_gap_phys)); + + +/**@brief Initiate or respond to a Data Length Update Procedure. + * + * @note If the application uses @ref BLE_GAP_DATA_LENGTH_AUTO for one or more members of + * p_dl_params, the SoftDevice will choose the highest value supported in current + * configuration and connection parameters. + * @note If the link PHY is Coded, the SoftDevice will ensure that the MaxTxTime and/or MaxRxTime + * used in the Data Length Update procedure is at least 2704 us. Otherwise, MaxTxTime and + * MaxRxTime will be limited to maximum 2120 us. + * + * @param[in] conn_handle Connection handle. + * @param[in] p_dl_params Pointer to local parameters to be used in Data Length Update + * Procedure. Set any member to @ref BLE_GAP_DATA_LENGTH_AUTO to let + * the SoftDevice automatically decide the value for that member. + * Set to NULL to use automatic values for all members. + * @param[out] p_dl_limitation Pointer to limitation to be written when local device does not + * have enough resources or does not support the requested Data Length + * Update parameters. Ignored if NULL. + * + * @mscs + * @mmsc{@ref BLE_GAP_DATA_LENGTH_UPDATE_PROCEDURE_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Successfully set Data Length Extension initiation/response parameters. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter supplied. + * @retval ::NRF_ERROR_INVALID_STATE No link has been established. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameters supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED The requested parameters are not supported by the SoftDevice. Inspect + * p_dl_limitation to see which parameter is not supported. + * @retval ::NRF_ERROR_RESOURCES The connection event length configured for this link is not sufficient for the requested parameters. + * Use @ref sd_ble_cfg_set with @ref BLE_CONN_CFG_GAP to increase the connection event length. + * Inspect p_dl_limitation to see where the limitation is. + * @retval ::NRF_ERROR_BUSY Peer has already initiated a Data Length Update Procedure. Process the + * pending @ref BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST event to respond. + */ +SVCALL(SD_BLE_GAP_DATA_LENGTH_UPDATE, uint32_t, sd_ble_gap_data_length_update(uint16_t conn_handle, ble_gap_data_length_params_t const *p_dl_params, ble_gap_data_length_limitation_t *p_dl_limitation)); + +/**@brief Start the Quality of Service (QoS) channel survey module. + * + * @details The channel survey module provides measurements of the energy levels on + * the Bluetooth Low Energy channels. When the module is enabled, @ref BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT + * events will periodically report the measured energy levels for each channel. + * + * @note The measurements are scheduled with lower priority than other Bluetooth Low Energy roles, + * Radio Timeslot API events and Flash API events. + * + * @note The channel survey module will attempt to do measurements so that the average interval + * between measurements will be interval_us. However due to the channel survey module + * having the lowest priority of all roles and modules, this may not be possible. In that + * case fewer than expected channel survey reports may be given. + * + * @note In order to use the channel survey module, @ref ble_gap_cfg_role_count_t::qos_channel_survey_role_available + * must be set. This is done using @ref sd_ble_cfg_set. + * + * @param[in] interval_us Requested average interval for the measurements and reports. See + * @ref BLE_GAP_QOS_CHANNEL_SURVEY_INTERVALS for valid ranges. If set + * to @ref BLE_GAP_QOS_CHANNEL_SURVEY_INTERVAL_CONTINUOUS, the channel + * survey role will be scheduled at every available opportunity. + * + * @retval ::NRF_SUCCESS The module is successfully started. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter supplied. interval_us is out of the + * allowed range. + * @retval ::NRF_ERROR_INVALID_STATE Trying to start the module when already running. + * @retval ::NRF_ERROR_RESOURCES The channel survey module is not available to the application. + * Set @ref ble_gap_cfg_role_count_t::qos_channel_survey_role_available using + * @ref sd_ble_cfg_set. + */ +SVCALL(SD_BLE_GAP_QOS_CHANNEL_SURVEY_START, uint32_t, sd_ble_gap_qos_channel_survey_start(uint32_t interval_us)); + +/**@brief Stop the Quality of Service (QoS) channel survey module. + * + * @note The SoftDevice may generate one @ref BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT event after this + * function is called. + * + * @retval ::NRF_SUCCESS The module is successfully stopped. + * @retval ::NRF_ERROR_INVALID_STATE Trying to stop the module when it is not running. + */ +SVCALL(SD_BLE_GAP_QOS_CHANNEL_SURVEY_STOP, uint32_t, sd_ble_gap_qos_channel_survey_stop(void)); + + +/**@brief Obtain the next connection event counter value. + * + * @details The connection event counter is initialized to zero on the first connection event. The value is incremented + * by one for each connection event. For more information see Bluetooth Core Specification v5.0, Vol 6, Part B, + * Section 4.5.1. + * + * @note The connection event counter obtained through this API will be outdated if this API is called + * at the same time as the connection event counter is incremented. + * + * @note This API will always return the last connection event counter + 1. + * The actual connection event may be multiple connection events later if: + * - Slave latency is enabled and there is no data to transmit or receive. + * - Another role is scheduled with a higher priority at the same time as the next connection event. + * + * @param[in] conn_handle Connection handle. + * @param[out] p_counter Pointer to the variable where the next connection event counter will be written. + * + * @retval ::NRF_SUCCESS The connection event counter was successfully retrieved. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter supplied. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + */ +SVCALL(SD_BLE_GAP_NEXT_CONN_EVT_COUNTER_GET, uint32_t, sd_ble_gap_next_conn_evt_counter_get(uint16_t conn_handle, uint16_t * p_counter)); + + +/**@brief Start triggering a given task on connection event start. + * + * @details When enabled, this feature will trigger a PPI task at the start of connection events. + * The application can configure the SoftDevice to trigger every N connection events starting from + * a given connection event counter. See also @ref ble_gap_conn_event_trigger_t. + * + * @param[in] conn_handle Connection handle. + * @param[in] p_params Connection event trigger parameters. + * + * @retval ::NRF_SUCCESS Success. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter supplied. See @ref ble_gap_conn_event_trigger_t. + * @retval ::NRF_ERROR_INVALID_STATE Either: + * - Trying to start connection event triggering when it is already ongoing. + * - @ref ble_gap_conn_event_trigger_t::conn_evt_counter_start is in the past. + * Use @ref sd_ble_gap_next_conn_evt_counter_get to find a new value + to be used as ble_gap_conn_event_trigger_t::conn_evt_counter_start. + */ +SVCALL(SD_BLE_GAP_CONN_EVT_TRIGGER_START, uint32_t, sd_ble_gap_conn_evt_trigger_start(uint16_t conn_handle, ble_gap_conn_event_trigger_t const * p_params)); + + +/**@brief Stop triggering the task configured using @ref sd_ble_gap_conn_evt_trigger_start. + * + * @param[in] conn_handle Connection handle. + * + * @retval ::NRF_SUCCESS Success. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_INVALID_STATE Trying to stop connection event triggering when it is not enabled. + */ +SVCALL(SD_BLE_GAP_CONN_EVT_TRIGGER_STOP, uint32_t, sd_ble_gap_conn_evt_trigger_stop(uint16_t conn_handle)); + + +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif // BLE_GAP_H__ + +/** + @} +*/ diff --git a/components/softdevice/s140/headers/ble_gatt.h b/components/softdevice/s140/headers/ble_gatt.h new file mode 100644 index 0000000..c392884 --- /dev/null +++ b/components/softdevice/s140/headers/ble_gatt.h @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2013 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @addtogroup BLE_GATT Generic Attribute Profile (GATT) Common + @{ + @brief Common definitions and prototypes for the GATT interfaces. + */ + +#ifndef BLE_GATT_H__ +#define BLE_GATT_H__ + +#include +#include "nrf_svc.h" +#include "nrf_error.h" +#include "ble_hci.h" +#include "ble_ranges.h" +#include "ble_types.h" +#include "ble_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup BLE_GATT_DEFINES Defines + * @{ */ + +/** @brief Default ATT MTU, in bytes. */ +#define BLE_GATT_ATT_MTU_DEFAULT 23 + +/**@brief Invalid Attribute Handle. */ +#define BLE_GATT_HANDLE_INVALID 0x0000 + +/**@brief First Attribute Handle. */ +#define BLE_GATT_HANDLE_START 0x0001 + +/**@brief Last Attribute Handle. */ +#define BLE_GATT_HANDLE_END 0xFFFF + +/** @defgroup BLE_GATT_TIMEOUT_SOURCES GATT Timeout sources + * @{ */ +#define BLE_GATT_TIMEOUT_SRC_PROTOCOL 0x00 /**< ATT Protocol timeout. */ +/** @} */ + +/** @defgroup BLE_GATT_WRITE_OPS GATT Write operations + * @{ */ +#define BLE_GATT_OP_INVALID 0x00 /**< Invalid Operation. */ +#define BLE_GATT_OP_WRITE_REQ 0x01 /**< Write Request. */ +#define BLE_GATT_OP_WRITE_CMD 0x02 /**< Write Command. */ +#define BLE_GATT_OP_SIGN_WRITE_CMD 0x03 /**< Signed Write Command. */ +#define BLE_GATT_OP_PREP_WRITE_REQ 0x04 /**< Prepare Write Request. */ +#define BLE_GATT_OP_EXEC_WRITE_REQ 0x05 /**< Execute Write Request. */ +/** @} */ + +/** @defgroup BLE_GATT_EXEC_WRITE_FLAGS GATT Execute Write flags + * @{ */ +#define BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL 0x00 /**< Cancel prepared write. */ +#define BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE 0x01 /**< Execute prepared write. */ +/** @} */ + +/** @defgroup BLE_GATT_HVX_TYPES GATT Handle Value operations + * @{ */ +#define BLE_GATT_HVX_INVALID 0x00 /**< Invalid Operation. */ +#define BLE_GATT_HVX_NOTIFICATION 0x01 /**< Handle Value Notification. */ +#define BLE_GATT_HVX_INDICATION 0x02 /**< Handle Value Indication. */ +/** @} */ + +/** @defgroup BLE_GATT_STATUS_CODES GATT Status Codes + * @{ */ +#define BLE_GATT_STATUS_SUCCESS 0x0000 /**< Success. */ +#define BLE_GATT_STATUS_UNKNOWN 0x0001 /**< Unknown or not applicable status. */ +#define BLE_GATT_STATUS_ATTERR_INVALID 0x0100 /**< ATT Error: Invalid Error Code. */ +#define BLE_GATT_STATUS_ATTERR_INVALID_HANDLE 0x0101 /**< ATT Error: Invalid Attribute Handle. */ +#define BLE_GATT_STATUS_ATTERR_READ_NOT_PERMITTED 0x0102 /**< ATT Error: Read not permitted. */ +#define BLE_GATT_STATUS_ATTERR_WRITE_NOT_PERMITTED 0x0103 /**< ATT Error: Write not permitted. */ +#define BLE_GATT_STATUS_ATTERR_INVALID_PDU 0x0104 /**< ATT Error: Used in ATT as Invalid PDU. */ +#define BLE_GATT_STATUS_ATTERR_INSUF_AUTHENTICATION 0x0105 /**< ATT Error: Authenticated link required. */ +#define BLE_GATT_STATUS_ATTERR_REQUEST_NOT_SUPPORTED 0x0106 /**< ATT Error: Used in ATT as Request Not Supported. */ +#define BLE_GATT_STATUS_ATTERR_INVALID_OFFSET 0x0107 /**< ATT Error: Offset specified was past the end of the attribute. */ +#define BLE_GATT_STATUS_ATTERR_INSUF_AUTHORIZATION 0x0108 /**< ATT Error: Used in ATT as Insufficient Authorization. */ +#define BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL 0x0109 /**< ATT Error: Used in ATT as Prepare Queue Full. */ +#define BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND 0x010A /**< ATT Error: Used in ATT as Attribute not found. */ +#define BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_LONG 0x010B /**< ATT Error: Attribute cannot be read or written using read/write blob requests. */ +#define BLE_GATT_STATUS_ATTERR_INSUF_ENC_KEY_SIZE 0x010C /**< ATT Error: Encryption key size used is insufficient. */ +#define BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH 0x010D /**< ATT Error: Invalid value size. */ +#define BLE_GATT_STATUS_ATTERR_UNLIKELY_ERROR 0x010E /**< ATT Error: Very unlikely error. */ +#define BLE_GATT_STATUS_ATTERR_INSUF_ENCRYPTION 0x010F /**< ATT Error: Encrypted link required. */ +#define BLE_GATT_STATUS_ATTERR_UNSUPPORTED_GROUP_TYPE 0x0110 /**< ATT Error: Attribute type is not a supported grouping attribute. */ +#define BLE_GATT_STATUS_ATTERR_INSUF_RESOURCES 0x0111 /**< ATT Error: Insufficient resources. */ +#define BLE_GATT_STATUS_ATTERR_RFU_RANGE1_BEGIN 0x0112 /**< ATT Error: Reserved for Future Use range #1 begin. */ +#define BLE_GATT_STATUS_ATTERR_RFU_RANGE1_END 0x017F /**< ATT Error: Reserved for Future Use range #1 end. */ +#define BLE_GATT_STATUS_ATTERR_APP_BEGIN 0x0180 /**< ATT Error: Application range begin. */ +#define BLE_GATT_STATUS_ATTERR_APP_END 0x019F /**< ATT Error: Application range end. */ +#define BLE_GATT_STATUS_ATTERR_RFU_RANGE2_BEGIN 0x01A0 /**< ATT Error: Reserved for Future Use range #2 begin. */ +#define BLE_GATT_STATUS_ATTERR_RFU_RANGE2_END 0x01DF /**< ATT Error: Reserved for Future Use range #2 end. */ +#define BLE_GATT_STATUS_ATTERR_RFU_RANGE3_BEGIN 0x01E0 /**< ATT Error: Reserved for Future Use range #3 begin. */ +#define BLE_GATT_STATUS_ATTERR_RFU_RANGE3_END 0x01FC /**< ATT Error: Reserved for Future Use range #3 end. */ +#define BLE_GATT_STATUS_ATTERR_CPS_WRITE_REQ_REJECTED 0x01FC /**< ATT Common Profile and Service Error: Write request rejected. */ +#define BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR 0x01FD /**< ATT Common Profile and Service Error: Client Characteristic Configuration Descriptor improperly configured. */ +#define BLE_GATT_STATUS_ATTERR_CPS_PROC_ALR_IN_PROG 0x01FE /**< ATT Common Profile and Service Error: Procedure Already in Progress. */ +#define BLE_GATT_STATUS_ATTERR_CPS_OUT_OF_RANGE 0x01FF /**< ATT Common Profile and Service Error: Out Of Range. */ +/** @} */ + + +/** @defgroup BLE_GATT_CPF_FORMATS Characteristic Presentation Formats + * @note Found at http://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorViewer.aspx?u=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml + * @{ */ +#define BLE_GATT_CPF_FORMAT_RFU 0x00 /**< Reserved For Future Use. */ +#define BLE_GATT_CPF_FORMAT_BOOLEAN 0x01 /**< Boolean. */ +#define BLE_GATT_CPF_FORMAT_2BIT 0x02 /**< Unsigned 2-bit integer. */ +#define BLE_GATT_CPF_FORMAT_NIBBLE 0x03 /**< Unsigned 4-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT8 0x04 /**< Unsigned 8-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT12 0x05 /**< Unsigned 12-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT16 0x06 /**< Unsigned 16-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT24 0x07 /**< Unsigned 24-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT32 0x08 /**< Unsigned 32-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT48 0x09 /**< Unsigned 48-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT64 0x0A /**< Unsigned 64-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT128 0x0B /**< Unsigned 128-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT8 0x0C /**< Signed 2-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT12 0x0D /**< Signed 12-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT16 0x0E /**< Signed 16-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT24 0x0F /**< Signed 24-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT32 0x10 /**< Signed 32-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT48 0x11 /**< Signed 48-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT64 0x12 /**< Signed 64-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT128 0x13 /**< Signed 128-bit integer. */ +#define BLE_GATT_CPF_FORMAT_FLOAT32 0x14 /**< IEEE-754 32-bit floating point. */ +#define BLE_GATT_CPF_FORMAT_FLOAT64 0x15 /**< IEEE-754 64-bit floating point. */ +#define BLE_GATT_CPF_FORMAT_SFLOAT 0x16 /**< IEEE-11073 16-bit SFLOAT. */ +#define BLE_GATT_CPF_FORMAT_FLOAT 0x17 /**< IEEE-11073 32-bit FLOAT. */ +#define BLE_GATT_CPF_FORMAT_DUINT16 0x18 /**< IEEE-20601 format. */ +#define BLE_GATT_CPF_FORMAT_UTF8S 0x19 /**< UTF-8 string. */ +#define BLE_GATT_CPF_FORMAT_UTF16S 0x1A /**< UTF-16 string. */ +#define BLE_GATT_CPF_FORMAT_STRUCT 0x1B /**< Opaque Structure. */ +/** @} */ + +/** @defgroup BLE_GATT_CPF_NAMESPACES GATT Bluetooth Namespaces + * @{ + */ +#define BLE_GATT_CPF_NAMESPACE_BTSIG 0x01 /**< Bluetooth SIG defined Namespace. */ +#define BLE_GATT_CPF_NAMESPACE_DESCRIPTION_UNKNOWN 0x0000 /**< Namespace Description Unknown. */ +/** @} */ + +/** @} */ + +/** @addtogroup BLE_GATT_STRUCTURES Structures + * @{ */ + +/** + * @brief BLE GATT connection configuration parameters, set with @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_INVALID_PARAM att_mtu is smaller than @ref BLE_GATT_ATT_MTU_DEFAULT. + */ +typedef struct +{ + uint16_t att_mtu; /**< Maximum size of ATT packet the SoftDevice can send or receive. + The default and minimum value is @ref BLE_GATT_ATT_MTU_DEFAULT. + @mscs + @mmsc{@ref BLE_GATTC_MTU_EXCHANGE} + @mmsc{@ref BLE_GATTS_MTU_EXCHANGE} + @endmscs + */ +} ble_gatt_conn_cfg_t; + +/**@brief GATT Characteristic Properties. */ +typedef struct +{ + /* Standard properties */ + uint8_t broadcast :1; /**< Broadcasting of the value permitted. */ + uint8_t read :1; /**< Reading the value permitted. */ + uint8_t write_wo_resp :1; /**< Writing the value with Write Command permitted. */ + uint8_t write :1; /**< Writing the value with Write Request permitted. */ + uint8_t notify :1; /**< Notification of the value permitted. */ + uint8_t indicate :1; /**< Indications of the value permitted. */ + uint8_t auth_signed_wr :1; /**< Writing the value with Signed Write Command permitted. */ +} ble_gatt_char_props_t; + +/**@brief GATT Characteristic Extended Properties. */ +typedef struct +{ + /* Extended properties */ + uint8_t reliable_wr :1; /**< Writing the value with Queued Write operations permitted. */ + uint8_t wr_aux :1; /**< Writing the Characteristic User Description descriptor permitted. */ +} ble_gatt_char_ext_props_t; + +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif // BLE_GATT_H__ + +/** @} */ diff --git a/components/softdevice/s140/headers/ble_gattc.h b/components/softdevice/s140/headers/ble_gattc.h new file mode 100644 index 0000000..a71b5e1 --- /dev/null +++ b/components/softdevice/s140/headers/ble_gattc.h @@ -0,0 +1,755 @@ +/* + * Copyright (c) 2011 - 2020, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @addtogroup BLE_GATTC Generic Attribute Profile (GATT) Client + @{ + @brief Definitions and prototypes for the GATT Client interface. + */ + +#ifndef BLE_GATTC_H__ +#define BLE_GATTC_H__ + +#include +#include "nrf.h" +#include "nrf_svc.h" +#include "nrf_error.h" +#include "ble_ranges.h" +#include "ble_types.h" +#include "ble_err.h" +#include "ble_gatt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup BLE_GATTC_ENUMERATIONS Enumerations + * @{ */ + +/**@brief GATTC API SVC numbers. */ +enum BLE_GATTC_SVCS +{ + SD_BLE_GATTC_PRIMARY_SERVICES_DISCOVER = BLE_GATTC_SVC_BASE, /**< Primary Service Discovery. */ + SD_BLE_GATTC_RELATIONSHIPS_DISCOVER, /**< Relationship Discovery. */ + SD_BLE_GATTC_CHARACTERISTICS_DISCOVER, /**< Characteristic Discovery. */ + SD_BLE_GATTC_DESCRIPTORS_DISCOVER, /**< Characteristic Descriptor Discovery. */ + SD_BLE_GATTC_ATTR_INFO_DISCOVER, /**< Attribute Information Discovery. */ + SD_BLE_GATTC_CHAR_VALUE_BY_UUID_READ, /**< Read Characteristic Value by UUID. */ + SD_BLE_GATTC_READ, /**< Generic read. */ + SD_BLE_GATTC_CHAR_VALUES_READ, /**< Read multiple Characteristic Values. */ + SD_BLE_GATTC_WRITE, /**< Generic write. */ + SD_BLE_GATTC_HV_CONFIRM, /**< Handle Value Confirmation. */ + SD_BLE_GATTC_EXCHANGE_MTU_REQUEST, /**< Exchange MTU Request. */ +}; + +/** + * @brief GATT Client Event IDs. + */ +enum BLE_GATTC_EVTS +{ + BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP = BLE_GATTC_EVT_BASE, /**< Primary Service Discovery Response event. \n See @ref ble_gattc_evt_prim_srvc_disc_rsp_t. */ + BLE_GATTC_EVT_REL_DISC_RSP, /**< Relationship Discovery Response event. \n See @ref ble_gattc_evt_rel_disc_rsp_t. */ + BLE_GATTC_EVT_CHAR_DISC_RSP, /**< Characteristic Discovery Response event. \n See @ref ble_gattc_evt_char_disc_rsp_t. */ + BLE_GATTC_EVT_DESC_DISC_RSP, /**< Descriptor Discovery Response event. \n See @ref ble_gattc_evt_desc_disc_rsp_t. */ + BLE_GATTC_EVT_ATTR_INFO_DISC_RSP, /**< Attribute Information Response event. \n See @ref ble_gattc_evt_attr_info_disc_rsp_t. */ + BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP, /**< Read By UUID Response event. \n See @ref ble_gattc_evt_char_val_by_uuid_read_rsp_t. */ + BLE_GATTC_EVT_READ_RSP, /**< Read Response event. \n See @ref ble_gattc_evt_read_rsp_t. */ + BLE_GATTC_EVT_CHAR_VALS_READ_RSP, /**< Read multiple Response event. \n See @ref ble_gattc_evt_char_vals_read_rsp_t. */ + BLE_GATTC_EVT_WRITE_RSP, /**< Write Response event. \n See @ref ble_gattc_evt_write_rsp_t. */ + BLE_GATTC_EVT_HVX, /**< Handle Value Notification or Indication event. \n Confirm indication with @ref sd_ble_gattc_hv_confirm. \n See @ref ble_gattc_evt_hvx_t. */ + BLE_GATTC_EVT_EXCHANGE_MTU_RSP, /**< Exchange MTU Response event. \n See @ref ble_gattc_evt_exchange_mtu_rsp_t. */ + BLE_GATTC_EVT_TIMEOUT, /**< Timeout event. \n See @ref ble_gattc_evt_timeout_t. */ + BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE /**< Write without Response transmission complete. \n See @ref ble_gattc_evt_write_cmd_tx_complete_t. */ +}; + +/**@brief GATTC Option IDs. + * IDs that uniquely identify a GATTC option. + */ +enum BLE_GATTC_OPTS +{ + BLE_GATTC_OPT_UUID_DISC = BLE_GATTC_OPT_BASE, /**< UUID discovery. @ref ble_gattc_opt_uuid_disc_t */ +}; + +/** @} */ + +/** @addtogroup BLE_GATTC_DEFINES Defines + * @{ */ + +/** @defgroup BLE_ERRORS_GATTC SVC return values specific to GATTC + * @{ */ +#define BLE_ERROR_GATTC_PROC_NOT_PERMITTED (NRF_GATTC_ERR_BASE + 0x000) /**< Procedure not Permitted. */ +/** @} */ + +/** @defgroup BLE_GATTC_ATTR_INFO_FORMAT Attribute Information Formats + * @{ */ +#define BLE_GATTC_ATTR_INFO_FORMAT_16BIT 1 /**< 16-bit Attribute Information Format. */ +#define BLE_GATTC_ATTR_INFO_FORMAT_128BIT 2 /**< 128-bit Attribute Information Format. */ +/** @} */ + +/** @defgroup BLE_GATTC_DEFAULTS GATT Client defaults + * @{ */ +#define BLE_GATTC_WRITE_CMD_TX_QUEUE_SIZE_DEFAULT 1 /**< Default number of Write without Response that can be queued for transmission. */ +/** @} */ + +/** @} */ + +/** @addtogroup BLE_GATTC_STRUCTURES Structures + * @{ */ + +/** + * @brief BLE GATTC connection configuration parameters, set with @ref sd_ble_cfg_set. + */ +typedef struct +{ + uint8_t write_cmd_tx_queue_size; /**< The guaranteed minimum number of Write without Response that can be queued for transmission. + The default value is @ref BLE_GATTC_WRITE_CMD_TX_QUEUE_SIZE_DEFAULT */ +} ble_gattc_conn_cfg_t; + +/**@brief Operation Handle Range. */ +typedef struct +{ + uint16_t start_handle; /**< Start Handle. */ + uint16_t end_handle; /**< End Handle. */ +} ble_gattc_handle_range_t; + + +/**@brief GATT service. */ +typedef struct +{ + ble_uuid_t uuid; /**< Service UUID. */ + ble_gattc_handle_range_t handle_range; /**< Service Handle Range. */ +} ble_gattc_service_t; + + +/**@brief GATT include. */ +typedef struct +{ + uint16_t handle; /**< Include Handle. */ + ble_gattc_service_t included_srvc; /**< Handle of the included service. */ +} ble_gattc_include_t; + + +/**@brief GATT characteristic. */ +typedef struct +{ + ble_uuid_t uuid; /**< Characteristic UUID. */ + ble_gatt_char_props_t char_props; /**< Characteristic Properties. */ + uint8_t char_ext_props : 1; /**< Extended properties present. */ + uint16_t handle_decl; /**< Handle of the Characteristic Declaration. */ + uint16_t handle_value; /**< Handle of the Characteristic Value. */ +} ble_gattc_char_t; + + +/**@brief GATT descriptor. */ +typedef struct +{ + uint16_t handle; /**< Descriptor Handle. */ + ble_uuid_t uuid; /**< Descriptor UUID. */ +} ble_gattc_desc_t; + + +/**@brief Write Parameters. */ +typedef struct +{ + uint8_t write_op; /**< Write Operation to be performed, see @ref BLE_GATT_WRITE_OPS. */ + uint8_t flags; /**< Flags, see @ref BLE_GATT_EXEC_WRITE_FLAGS. */ + uint16_t handle; /**< Handle to the attribute to be written. */ + uint16_t offset; /**< Offset in bytes. @note For WRITE_CMD and WRITE_REQ, offset must be 0. */ + uint16_t len; /**< Length of data in bytes. */ + uint8_t const *p_value; /**< Pointer to the value data. */ +} ble_gattc_write_params_t; + +/**@brief Attribute Information for 16-bit Attribute UUID. */ +typedef struct +{ + uint16_t handle; /**< Attribute handle. */ + ble_uuid_t uuid; /**< 16-bit Attribute UUID. */ +} ble_gattc_attr_info16_t; + +/**@brief Attribute Information for 128-bit Attribute UUID. */ +typedef struct +{ + uint16_t handle; /**< Attribute handle. */ + ble_uuid128_t uuid; /**< 128-bit Attribute UUID. */ +} ble_gattc_attr_info128_t; + +/**@brief Event structure for @ref BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP. */ +typedef struct +{ + uint16_t count; /**< Service count. */ + ble_gattc_service_t services[1]; /**< Service data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation. + See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */ +} ble_gattc_evt_prim_srvc_disc_rsp_t; + +/**@brief Event structure for @ref BLE_GATTC_EVT_REL_DISC_RSP. */ +typedef struct +{ + uint16_t count; /**< Include count. */ + ble_gattc_include_t includes[1]; /**< Include data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation. + See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */ +} ble_gattc_evt_rel_disc_rsp_t; + +/**@brief Event structure for @ref BLE_GATTC_EVT_CHAR_DISC_RSP. */ +typedef struct +{ + uint16_t count; /**< Characteristic count. */ + ble_gattc_char_t chars[1]; /**< Characteristic data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation. + See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */ +} ble_gattc_evt_char_disc_rsp_t; + +/**@brief Event structure for @ref BLE_GATTC_EVT_DESC_DISC_RSP. */ +typedef struct +{ + uint16_t count; /**< Descriptor count. */ + ble_gattc_desc_t descs[1]; /**< Descriptor data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation. + See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */ +} ble_gattc_evt_desc_disc_rsp_t; + +/**@brief Event structure for @ref BLE_GATTC_EVT_ATTR_INFO_DISC_RSP. */ +typedef struct +{ + uint16_t count; /**< Attribute count. */ + uint8_t format; /**< Attribute information format, see @ref BLE_GATTC_ATTR_INFO_FORMAT. */ + union { + ble_gattc_attr_info16_t attr_info16[1]; /**< Attribute information for 16-bit Attribute UUID. + @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation. + See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */ + ble_gattc_attr_info128_t attr_info128[1]; /**< Attribute information for 128-bit Attribute UUID. + @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation. + See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */ + } info; /**< Attribute information union. */ +} ble_gattc_evt_attr_info_disc_rsp_t; + +/**@brief GATT read by UUID handle value pair. */ +typedef struct +{ + uint16_t handle; /**< Attribute Handle. */ + uint8_t *p_value; /**< Pointer to the Attribute Value, length is available in @ref ble_gattc_evt_char_val_by_uuid_read_rsp_t::value_len. */ +} ble_gattc_handle_value_t; + +/**@brief Event structure for @ref BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP. */ +typedef struct +{ + uint16_t count; /**< Handle-Value Pair Count. */ + uint16_t value_len; /**< Length of the value in Handle-Value(s) list. */ + uint8_t handle_value[1]; /**< Handle-Value(s) list. To iterate through the list use @ref sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter. + @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation. + See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */ +} ble_gattc_evt_char_val_by_uuid_read_rsp_t; + +/**@brief Event structure for @ref BLE_GATTC_EVT_READ_RSP. */ +typedef struct +{ + uint16_t handle; /**< Attribute Handle. */ + uint16_t offset; /**< Offset of the attribute data. */ + uint16_t len; /**< Attribute data length. */ + uint8_t data[1]; /**< Attribute data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation. + See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */ +} ble_gattc_evt_read_rsp_t; + +/**@brief Event structure for @ref BLE_GATTC_EVT_CHAR_VALS_READ_RSP. */ +typedef struct +{ + uint16_t len; /**< Concatenated Attribute values length. */ + uint8_t values[1]; /**< Attribute values. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation. + See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */ +} ble_gattc_evt_char_vals_read_rsp_t; + +/**@brief Event structure for @ref BLE_GATTC_EVT_WRITE_RSP. */ +typedef struct +{ + uint16_t handle; /**< Attribute Handle. */ + uint8_t write_op; /**< Type of write operation, see @ref BLE_GATT_WRITE_OPS. */ + uint16_t offset; /**< Data offset. */ + uint16_t len; /**< Data length. */ + uint8_t data[1]; /**< Data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation. + See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */ +} ble_gattc_evt_write_rsp_t; + +/**@brief Event structure for @ref BLE_GATTC_EVT_HVX. */ +typedef struct +{ + uint16_t handle; /**< Handle to which the HVx operation applies. */ + uint8_t type; /**< Indication or Notification, see @ref BLE_GATT_HVX_TYPES. */ + uint16_t len; /**< Attribute data length. */ + uint8_t data[1]; /**< Attribute data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation. + See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */ +} ble_gattc_evt_hvx_t; + +/**@brief Event structure for @ref BLE_GATTC_EVT_EXCHANGE_MTU_RSP. */ +typedef struct +{ + uint16_t server_rx_mtu; /**< Server RX MTU size. */ +} ble_gattc_evt_exchange_mtu_rsp_t; + +/**@brief Event structure for @ref BLE_GATTC_EVT_TIMEOUT. */ +typedef struct +{ + uint8_t src; /**< Timeout source, see @ref BLE_GATT_TIMEOUT_SOURCES. */ +} ble_gattc_evt_timeout_t; + +/**@brief Event structure for @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE. */ +typedef struct +{ + uint8_t count; /**< Number of write without response transmissions completed. */ +} ble_gattc_evt_write_cmd_tx_complete_t; + +/**@brief GATTC event structure. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which event occurred. */ + uint16_t gatt_status; /**< GATT status code for the operation, see @ref BLE_GATT_STATUS_CODES. */ + uint16_t error_handle; /**< In case of error: The handle causing the error. In all other cases @ref BLE_GATT_HANDLE_INVALID. */ + union + { + ble_gattc_evt_prim_srvc_disc_rsp_t prim_srvc_disc_rsp; /**< Primary Service Discovery Response Event Parameters. */ + ble_gattc_evt_rel_disc_rsp_t rel_disc_rsp; /**< Relationship Discovery Response Event Parameters. */ + ble_gattc_evt_char_disc_rsp_t char_disc_rsp; /**< Characteristic Discovery Response Event Parameters. */ + ble_gattc_evt_desc_disc_rsp_t desc_disc_rsp; /**< Descriptor Discovery Response Event Parameters. */ + ble_gattc_evt_char_val_by_uuid_read_rsp_t char_val_by_uuid_read_rsp; /**< Characteristic Value Read by UUID Response Event Parameters. */ + ble_gattc_evt_read_rsp_t read_rsp; /**< Read Response Event Parameters. */ + ble_gattc_evt_char_vals_read_rsp_t char_vals_read_rsp; /**< Characteristic Values Read Response Event Parameters. */ + ble_gattc_evt_write_rsp_t write_rsp; /**< Write Response Event Parameters. */ + ble_gattc_evt_hvx_t hvx; /**< Handle Value Notification/Indication Event Parameters. */ + ble_gattc_evt_exchange_mtu_rsp_t exchange_mtu_rsp; /**< Exchange MTU Response Event Parameters. */ + ble_gattc_evt_timeout_t timeout; /**< Timeout Event Parameters. */ + ble_gattc_evt_attr_info_disc_rsp_t attr_info_disc_rsp; /**< Attribute Information Discovery Event Parameters. */ + ble_gattc_evt_write_cmd_tx_complete_t write_cmd_tx_complete; /**< Write without Response transmission complete Event Parameters. */ + } params; /**< Event Parameters. @note Only valid if @ref gatt_status == @ref BLE_GATT_STATUS_SUCCESS. */ +} ble_gattc_evt_t; + +/**@brief UUID discovery option. + * + * @details Used with @ref sd_ble_opt_set to enable and disable automatic insertion of discovered 128-bit UUIDs to the + * Vendor Specific UUID table. Disabled by default. + * - When disabled, if a procedure initiated by + * @ref sd_ble_gattc_primary_services_discover, + * @ref sd_ble_gattc_relationships_discover, + * @ref sd_ble_gattc_characteristics_discover, + * @ref sd_ble_gattc_descriptors_discover + * finds a 128-bit UUID which was not added by @ref sd_ble_uuid_vs_add, @ref ble_uuid_t::type will be set + * to @ref BLE_UUID_TYPE_UNKNOWN in the corresponding event. + * - When enabled, all found 128-bit UUIDs will be automatically added. The application can use + * @ref sd_ble_uuid_encode to retrieve the 128-bit UUID from @ref ble_uuid_t received in the corresponding + * event. If the total number of Vendor Specific UUIDs exceeds the table capacity, @ref ble_uuid_t::type will + * be set to @ref BLE_UUID_TYPE_UNKNOWN in the corresponding event. + * See also @ref ble_common_cfg_vs_uuid_t, @ref sd_ble_uuid_vs_remove. + * + * @note @ref sd_ble_opt_get is not supported for this option. + * + * @retval ::NRF_SUCCESS Set successfully. + * + */ +typedef struct +{ + uint8_t auto_add_vs_enable : 1; /**< Set to 1 to enable (or 0 to disable) automatic insertion of discovered 128-bit UUIDs. */ +} ble_gattc_opt_uuid_disc_t; + +/**@brief Option structure for GATTC options. */ +typedef union +{ + ble_gattc_opt_uuid_disc_t uuid_disc; /**< Parameters for the UUID discovery option. */ +} ble_gattc_opt_t; + +/** @} */ + +/** @addtogroup BLE_GATTC_FUNCTIONS Functions + * @{ */ + +/**@brief Initiate or continue a GATT Primary Service Discovery procedure. + * + * @details This function initiates or resumes a Primary Service discovery procedure, starting from the supplied handle. + * If the last service has not been reached, this function must be called again with an updated start handle value to continue the search. + * See also @ref ble_gattc_opt_uuid_disc_t. + * + * @events + * @event{@ref BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GATTC_PRIM_SRVC_DISC_MSC} + * @endmscs + * + * @param[in] conn_handle The connection handle identifying the connection to perform this procedure on. + * @param[in] start_handle Handle to start searching from. + * @param[in] p_srvc_uuid Pointer to the service UUID to be found. If it is NULL, all primary services will be returned. + * + * @retval ::NRF_SUCCESS Successfully started or resumed the Primary Service Discovery procedure. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_BUSY Client procedure already in progress. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTC_PRIMARY_SERVICES_DISCOVER, uint32_t, sd_ble_gattc_primary_services_discover(uint16_t conn_handle, uint16_t start_handle, ble_uuid_t const *p_srvc_uuid)); + + +/**@brief Initiate or continue a GATT Relationship Discovery procedure. + * + * @details This function initiates or resumes the Find Included Services sub-procedure. If the last included service has not been reached, + * this must be called again with an updated handle range to continue the search. + * See also @ref ble_gattc_opt_uuid_disc_t. + * + * @events + * @event{@ref BLE_GATTC_EVT_REL_DISC_RSP} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GATTC_REL_DISC_MSC} + * @endmscs + * + * @param[in] conn_handle The connection handle identifying the connection to perform this procedure on. + * @param[in] p_handle_range A pointer to the range of handles of the Service to perform this procedure on. + * + * @retval ::NRF_SUCCESS Successfully started or resumed the Relationship Discovery procedure. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_BUSY Client procedure already in progress. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTC_RELATIONSHIPS_DISCOVER, uint32_t, sd_ble_gattc_relationships_discover(uint16_t conn_handle, ble_gattc_handle_range_t const *p_handle_range)); + + +/**@brief Initiate or continue a GATT Characteristic Discovery procedure. + * + * @details This function initiates or resumes a Characteristic discovery procedure. If the last Characteristic has not been reached, + * this must be called again with an updated handle range to continue the discovery. + * See also @ref ble_gattc_opt_uuid_disc_t. + * + * @events + * @event{@ref BLE_GATTC_EVT_CHAR_DISC_RSP} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GATTC_CHAR_DISC_MSC} + * @endmscs + * + * @param[in] conn_handle The connection handle identifying the connection to perform this procedure on. + * @param[in] p_handle_range A pointer to the range of handles of the Service to perform this procedure on. + * + * @retval ::NRF_SUCCESS Successfully started or resumed the Characteristic Discovery procedure. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_BUSY Client procedure already in progress. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTC_CHARACTERISTICS_DISCOVER, uint32_t, sd_ble_gattc_characteristics_discover(uint16_t conn_handle, ble_gattc_handle_range_t const *p_handle_range)); + + +/**@brief Initiate or continue a GATT Characteristic Descriptor Discovery procedure. + * + * @details This function initiates or resumes a Characteristic Descriptor discovery procedure. If the last Descriptor has not been reached, + * this must be called again with an updated handle range to continue the discovery. + * See also @ref ble_gattc_opt_uuid_disc_t. + * + * @events + * @event{@ref BLE_GATTC_EVT_DESC_DISC_RSP} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GATTC_DESC_DISC_MSC} + * @endmscs + * + * @param[in] conn_handle The connection handle identifying the connection to perform this procedure on. + * @param[in] p_handle_range A pointer to the range of handles of the Characteristic to perform this procedure on. + * + * @retval ::NRF_SUCCESS Successfully started or resumed the Descriptor Discovery procedure. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_BUSY Client procedure already in progress. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTC_DESCRIPTORS_DISCOVER, uint32_t, sd_ble_gattc_descriptors_discover(uint16_t conn_handle, ble_gattc_handle_range_t const *p_handle_range)); + + +/**@brief Initiate or continue a GATT Read using Characteristic UUID procedure. + * + * @details This function initiates or resumes a Read using Characteristic UUID procedure. If the last Characteristic has not been reached, + * this must be called again with an updated handle range to continue the discovery. + * + * @events + * @event{@ref BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GATTC_READ_UUID_MSC} + * @endmscs + * + * @param[in] conn_handle The connection handle identifying the connection to perform this procedure on. + * @param[in] p_uuid Pointer to a Characteristic value UUID to read. + * @param[in] p_handle_range A pointer to the range of handles to perform this procedure on. + * + * @retval ::NRF_SUCCESS Successfully started or resumed the Read using Characteristic UUID procedure. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_BUSY Client procedure already in progress. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTC_CHAR_VALUE_BY_UUID_READ, uint32_t, sd_ble_gattc_char_value_by_uuid_read(uint16_t conn_handle, ble_uuid_t const *p_uuid, ble_gattc_handle_range_t const *p_handle_range)); + + +/**@brief Initiate or continue a GATT Read (Long) Characteristic or Descriptor procedure. + * + * @details This function initiates or resumes a GATT Read (Long) Characteristic or Descriptor procedure. If the Characteristic or Descriptor + * to be read is longer than ATT_MTU - 1, this function must be called multiple times with appropriate offset to read the + * complete value. + * + * @events + * @event{@ref BLE_GATTC_EVT_READ_RSP} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GATTC_VALUE_READ_MSC} + * @endmscs + * + * @param[in] conn_handle The connection handle identifying the connection to perform this procedure on. + * @param[in] handle The handle of the attribute to be read. + * @param[in] offset Offset into the attribute value to be read. + * + * @retval ::NRF_SUCCESS Successfully started or resumed the Read (Long) procedure. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State. + * @retval ::NRF_ERROR_BUSY Client procedure already in progress. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTC_READ, uint32_t, sd_ble_gattc_read(uint16_t conn_handle, uint16_t handle, uint16_t offset)); + + +/**@brief Initiate a GATT Read Multiple Characteristic Values procedure. + * + * @details This function initiates a GATT Read Multiple Characteristic Values procedure. + * + * @events + * @event{@ref BLE_GATTC_EVT_CHAR_VALS_READ_RSP} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GATTC_READ_MULT_MSC} + * @endmscs + * + * @param[in] conn_handle The connection handle identifying the connection to perform this procedure on. + * @param[in] p_handles A pointer to the handle(s) of the attribute(s) to be read. + * @param[in] handle_count The number of handles in p_handles. + * + * @retval ::NRF_SUCCESS Successfully started the Read Multiple Characteristic Values procedure. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_BUSY Client procedure already in progress. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTC_CHAR_VALUES_READ, uint32_t, sd_ble_gattc_char_values_read(uint16_t conn_handle, uint16_t const *p_handles, uint16_t handle_count)); + + +/**@brief Perform a Write (Characteristic Value or Descriptor, with or without response, signed or not, long or reliable) procedure. + * + * @details This function can perform all write procedures described in GATT. + * + * @note Only one write with response procedure can be ongoing per connection at a time. + * If the application tries to write with response while another write with response procedure is ongoing, + * the function call will return @ref NRF_ERROR_BUSY. + * A @ref BLE_GATTC_EVT_WRITE_RSP event will be issued as soon as the write response arrives from the peer. + * + * @note The number of Write without Response that can be queued is configured by @ref ble_gattc_conn_cfg_t::write_cmd_tx_queue_size + * When the queue is full, the function call will return @ref NRF_ERROR_RESOURCES. + * A @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event will be issued as soon as the transmission of the write without response is complete. + * + * @note The application can keep track of the available queue element count for writes without responses by following the procedure below: + * - Store initial queue element count in a variable. + * - Decrement the variable, which stores the currently available queue element count, by one when a call to this function returns @ref NRF_SUCCESS. + * - Increment the variable, which stores the current available queue element count, by the count variable in @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event. + * + * @events + * @event{@ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE, Write without response transmission complete.} + * @event{@ref BLE_GATTC_EVT_WRITE_RSP, Write response received from the peer.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GATTC_VALUE_WRITE_WITHOUT_RESP_MSC} + * @mmsc{@ref BLE_GATTC_VALUE_WRITE_MSC} + * @mmsc{@ref BLE_GATTC_VALUE_LONG_WRITE_MSC} + * @mmsc{@ref BLE_GATTC_VALUE_RELIABLE_WRITE_MSC} + * @endmscs + * + * @param[in] conn_handle The connection handle identifying the connection to perform this procedure on. + * @param[in] p_write_params A pointer to a write parameters structure. + * + * @retval ::NRF_SUCCESS Successfully started the Write procedure. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied. + * @retval ::NRF_ERROR_BUSY For write with response, procedure already in progress. Wait for a @ref BLE_GATTC_EVT_WRITE_RSP event and retry. + * @retval ::NRF_ERROR_RESOURCES Too many writes without responses queued. + * Wait for a @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event and retry. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTC_WRITE, uint32_t, sd_ble_gattc_write(uint16_t conn_handle, ble_gattc_write_params_t const *p_write_params)); + + +/**@brief Send a Handle Value Confirmation to the GATT Server. + * + * @mscs + * @mmsc{@ref BLE_GATTC_HVI_MSC} + * @endmscs + * + * @param[in] conn_handle The connection handle identifying the connection to perform this procedure on. + * @param[in] handle The handle of the attribute in the indication. + * + * @retval ::NRF_SUCCESS Successfully queued the Handle Value Confirmation for transmission. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State or no Indication pending to be confirmed. + * @retval ::BLE_ERROR_INVALID_ATTR_HANDLE Invalid attribute handle. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTC_HV_CONFIRM, uint32_t, sd_ble_gattc_hv_confirm(uint16_t conn_handle, uint16_t handle)); + +/**@brief Discovers information about a range of attributes on a GATT server. + * + * @events + * @event{@ref BLE_GATTC_EVT_ATTR_INFO_DISC_RSP, Generated when information about a range of attributes has been received.} + * @endevents + * + * @param[in] conn_handle The connection handle identifying the connection to perform this procedure on. + * @param[in] p_handle_range The range of handles to request information about. + * + * @retval ::NRF_SUCCESS Successfully started an attribute information discovery procedure. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid connection state + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_BUSY Client procedure already in progress. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTC_ATTR_INFO_DISCOVER, uint32_t, sd_ble_gattc_attr_info_discover(uint16_t conn_handle, ble_gattc_handle_range_t const * p_handle_range)); + +/**@brief Start an ATT_MTU exchange by sending an Exchange MTU Request to the server. + * + * @details The SoftDevice sets ATT_MTU to the minimum of: + * - The Client RX MTU value, and + * - The Server RX MTU value from @ref BLE_GATTC_EVT_EXCHANGE_MTU_RSP. + * + * However, the SoftDevice never sets ATT_MTU lower than @ref BLE_GATT_ATT_MTU_DEFAULT. + * + * @events + * @event{@ref BLE_GATTC_EVT_EXCHANGE_MTU_RSP} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GATTC_MTU_EXCHANGE} + * @endmscs + * + * @param[in] conn_handle The connection handle identifying the connection to perform this procedure on. + * @param[in] client_rx_mtu Client RX MTU size. + * - The minimum value is @ref BLE_GATT_ATT_MTU_DEFAULT. + * - The maximum value is @ref ble_gatt_conn_cfg_t::att_mtu in the connection configuration + used for this connection. + * - The value must be equal to Server RX MTU size given in @ref sd_ble_gatts_exchange_mtu_reply + * if an ATT_MTU exchange has already been performed in the other direction. + * + * @retval ::NRF_SUCCESS Successfully sent request to the server. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid connection state or an ATT_MTU exchange was already requested once. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid Client RX MTU size supplied. + * @retval ::NRF_ERROR_BUSY Client procedure already in progress. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTC_EXCHANGE_MTU_REQUEST, uint32_t, sd_ble_gattc_exchange_mtu_request(uint16_t conn_handle, uint16_t client_rx_mtu)); + +/**@brief Iterate through Handle-Value(s) list in @ref BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP event. + * + * @param[in] p_gattc_evt Pointer to event buffer containing @ref BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP event. + * @note If the buffer contains different event, behavior is undefined. + * @param[in,out] p_iter Iterator, points to @ref ble_gattc_handle_value_t structure that will be filled in with + * the next Handle-Value pair in each iteration. If the function returns other than + * @ref NRF_SUCCESS, it will not be changed. + * - To start iteration, initialize the structure to zero. + * - To continue, pass the value from previous iteration. + * + * \code + * ble_gattc_handle_value_t iter; + * memset(&iter, 0, sizeof(ble_gattc_handle_value_t)); + * while (sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(&ble_evt.evt.gattc_evt, &iter) == NRF_SUCCESS) + * { + * app_handle = iter.handle; + * memcpy(app_value, iter.p_value, ble_evt.evt.gattc_evt.params.char_val_by_uuid_read_rsp.value_len); + * } + * \endcode + * + * @retval ::NRF_SUCCESS Successfully retrieved the next Handle-Value pair. + * @retval ::NRF_ERROR_NOT_FOUND No more Handle-Value pairs available in the list. + */ +__STATIC_INLINE uint32_t sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(ble_gattc_evt_t *p_gattc_evt, ble_gattc_handle_value_t *p_iter); + +/** @} */ + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE uint32_t sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(ble_gattc_evt_t *p_gattc_evt, ble_gattc_handle_value_t *p_iter) +{ + uint32_t value_len = p_gattc_evt->params.char_val_by_uuid_read_rsp.value_len; + uint8_t *p_first = p_gattc_evt->params.char_val_by_uuid_read_rsp.handle_value; + uint8_t *p_next = p_iter->p_value ? p_iter->p_value + value_len : p_first; + + if ((p_next - p_first) / (sizeof(uint16_t) + value_len) < p_gattc_evt->params.char_val_by_uuid_read_rsp.count) + { + p_iter->handle = (uint16_t)p_next[1] << 8 | p_next[0]; + p_iter->p_value = p_next + sizeof(uint16_t); + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_NOT_FOUND; + } +} + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + +#ifdef __cplusplus +} +#endif +#endif /* BLE_GATTC_H__ */ + +/** + @} +*/ diff --git a/components/softdevice/s140/headers/ble_gatts.h b/components/softdevice/s140/headers/ble_gatts.h new file mode 100644 index 0000000..394d8d1 --- /dev/null +++ b/components/softdevice/s140/headers/ble_gatts.h @@ -0,0 +1,845 @@ +/* + * Copyright (c) 2011 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @addtogroup BLE_GATTS Generic Attribute Profile (GATT) Server + @{ + @brief Definitions and prototypes for the GATTS interface. + */ + +#ifndef BLE_GATTS_H__ +#define BLE_GATTS_H__ + +#include +#include "nrf_svc.h" +#include "nrf_error.h" +#include "ble_hci.h" +#include "ble_ranges.h" +#include "ble_types.h" +#include "ble_err.h" +#include "ble_gatt.h" +#include "ble_gap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup BLE_GATTS_ENUMERATIONS Enumerations + * @{ */ + +/** + * @brief GATTS API SVC numbers. + */ +enum BLE_GATTS_SVCS +{ + SD_BLE_GATTS_SERVICE_ADD = BLE_GATTS_SVC_BASE, /**< Add a service. */ + SD_BLE_GATTS_INCLUDE_ADD, /**< Add an included service. */ + SD_BLE_GATTS_CHARACTERISTIC_ADD, /**< Add a characteristic. */ + SD_BLE_GATTS_DESCRIPTOR_ADD, /**< Add a generic attribute. */ + SD_BLE_GATTS_VALUE_SET, /**< Set an attribute value. */ + SD_BLE_GATTS_VALUE_GET, /**< Get an attribute value. */ + SD_BLE_GATTS_HVX, /**< Handle Value Notification or Indication. */ + SD_BLE_GATTS_SERVICE_CHANGED, /**< Perform a Service Changed Indication to one or more peers. */ + SD_BLE_GATTS_RW_AUTHORIZE_REPLY, /**< Reply to an authorization request for a read or write operation on one or more attributes. */ + SD_BLE_GATTS_SYS_ATTR_SET, /**< Set the persistent system attributes for a connection. */ + SD_BLE_GATTS_SYS_ATTR_GET, /**< Retrieve the persistent system attributes. */ + SD_BLE_GATTS_INITIAL_USER_HANDLE_GET, /**< Retrieve the first valid user handle. */ + SD_BLE_GATTS_ATTR_GET, /**< Retrieve the UUID and/or metadata of an attribute. */ + SD_BLE_GATTS_EXCHANGE_MTU_REPLY /**< Reply to Exchange MTU Request. */ +}; + +/** + * @brief GATT Server Event IDs. + */ +enum BLE_GATTS_EVTS +{ + BLE_GATTS_EVT_WRITE = BLE_GATTS_EVT_BASE, /**< Write operation performed. \n See @ref ble_gatts_evt_write_t. */ + BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST, /**< Read/Write Authorization request. \n Reply with @ref sd_ble_gatts_rw_authorize_reply. \n See @ref ble_gatts_evt_rw_authorize_request_t. */ + BLE_GATTS_EVT_SYS_ATTR_MISSING, /**< A persistent system attribute access is pending. \n Respond with @ref sd_ble_gatts_sys_attr_set. \n See @ref ble_gatts_evt_sys_attr_missing_t. */ + BLE_GATTS_EVT_HVC, /**< Handle Value Confirmation. \n See @ref ble_gatts_evt_hvc_t. */ + BLE_GATTS_EVT_SC_CONFIRM, /**< Service Changed Confirmation. \n No additional event structure applies. */ + BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST, /**< Exchange MTU Request. \n Reply with @ref sd_ble_gatts_exchange_mtu_reply. \n See @ref ble_gatts_evt_exchange_mtu_request_t. */ + BLE_GATTS_EVT_TIMEOUT, /**< Peer failed to respond to an ATT request in time. \n See @ref ble_gatts_evt_timeout_t. */ + BLE_GATTS_EVT_HVN_TX_COMPLETE /**< Handle Value Notification transmission complete. \n See @ref ble_gatts_evt_hvn_tx_complete_t. */ +}; + +/**@brief GATTS Configuration IDs. + * + * IDs that uniquely identify a GATTS configuration. + */ +enum BLE_GATTS_CFGS +{ + BLE_GATTS_CFG_SERVICE_CHANGED = BLE_GATTS_CFG_BASE, /**< Service changed configuration. */ + BLE_GATTS_CFG_ATTR_TAB_SIZE, /**< Attribute table size configuration. */ +}; + +/** @} */ + +/** @addtogroup BLE_GATTS_DEFINES Defines + * @{ */ + +/** @defgroup BLE_ERRORS_GATTS SVC return values specific to GATTS + * @{ */ +#define BLE_ERROR_GATTS_INVALID_ATTR_TYPE (NRF_GATTS_ERR_BASE + 0x000) /**< Invalid attribute type. */ +#define BLE_ERROR_GATTS_SYS_ATTR_MISSING (NRF_GATTS_ERR_BASE + 0x001) /**< System Attributes missing. */ +/** @} */ + +/** @defgroup BLE_GATTS_ATTR_LENS_MAX Maximum attribute lengths + * @{ */ +#define BLE_GATTS_FIX_ATTR_LEN_MAX (510) /**< Maximum length for fixed length Attribute Values. */ +#define BLE_GATTS_VAR_ATTR_LEN_MAX (512) /**< Maximum length for variable length Attribute Values. */ +/** @} */ + +/** @defgroup BLE_GATTS_SRVC_TYPES GATT Server Service Types + * @{ */ +#define BLE_GATTS_SRVC_TYPE_INVALID 0x00 /**< Invalid Service Type. */ +#define BLE_GATTS_SRVC_TYPE_PRIMARY 0x01 /**< Primary Service. */ +#define BLE_GATTS_SRVC_TYPE_SECONDARY 0x02 /**< Secondary Type. */ +/** @} */ + + +/** @defgroup BLE_GATTS_ATTR_TYPES GATT Server Attribute Types + * @{ */ +#define BLE_GATTS_ATTR_TYPE_INVALID 0x00 /**< Invalid Attribute Type. */ +#define BLE_GATTS_ATTR_TYPE_PRIM_SRVC_DECL 0x01 /**< Primary Service Declaration. */ +#define BLE_GATTS_ATTR_TYPE_SEC_SRVC_DECL 0x02 /**< Secondary Service Declaration. */ +#define BLE_GATTS_ATTR_TYPE_INC_DECL 0x03 /**< Include Declaration. */ +#define BLE_GATTS_ATTR_TYPE_CHAR_DECL 0x04 /**< Characteristic Declaration. */ +#define BLE_GATTS_ATTR_TYPE_CHAR_VAL 0x05 /**< Characteristic Value. */ +#define BLE_GATTS_ATTR_TYPE_DESC 0x06 /**< Descriptor. */ +#define BLE_GATTS_ATTR_TYPE_OTHER 0x07 /**< Other, non-GATT specific type. */ +/** @} */ + + +/** @defgroup BLE_GATTS_OPS GATT Server Operations + * @{ */ +#define BLE_GATTS_OP_INVALID 0x00 /**< Invalid Operation. */ +#define BLE_GATTS_OP_WRITE_REQ 0x01 /**< Write Request. */ +#define BLE_GATTS_OP_WRITE_CMD 0x02 /**< Write Command. */ +#define BLE_GATTS_OP_SIGN_WRITE_CMD 0x03 /**< Signed Write Command. */ +#define BLE_GATTS_OP_PREP_WRITE_REQ 0x04 /**< Prepare Write Request. */ +#define BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL 0x05 /**< Execute Write Request: Cancel all prepared writes. */ +#define BLE_GATTS_OP_EXEC_WRITE_REQ_NOW 0x06 /**< Execute Write Request: Immediately execute all prepared writes. */ +/** @} */ + +/** @defgroup BLE_GATTS_VLOCS GATT Value Locations + * @{ */ +#define BLE_GATTS_VLOC_INVALID 0x00 /**< Invalid Location. */ +#define BLE_GATTS_VLOC_STACK 0x01 /**< Attribute Value is located in stack memory, no user memory is required. */ +#define BLE_GATTS_VLOC_USER 0x02 /**< Attribute Value is located in user memory. This requires the user to maintain a valid buffer through the lifetime of the attribute, since the stack + will read and write directly to the memory using the pointer provided in the APIs. There are no alignment requirements for the buffer. */ +/** @} */ + +/** @defgroup BLE_GATTS_AUTHORIZE_TYPES GATT Server Authorization Types + * @{ */ +#define BLE_GATTS_AUTHORIZE_TYPE_INVALID 0x00 /**< Invalid Type. */ +#define BLE_GATTS_AUTHORIZE_TYPE_READ 0x01 /**< Authorize a Read Operation. */ +#define BLE_GATTS_AUTHORIZE_TYPE_WRITE 0x02 /**< Authorize a Write Request Operation. */ +/** @} */ + +/** @defgroup BLE_GATTS_SYS_ATTR_FLAGS System Attribute Flags + * @{ */ +#define BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS (1 << 0) /**< Restrict system attributes to system services only. */ +#define BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS (1 << 1) /**< Restrict system attributes to user services only. */ +/** @} */ + +/** @defgroup BLE_GATTS_SERVICE_CHANGED Service Changed Inclusion Values + * @{ + */ +#define BLE_GATTS_SERVICE_CHANGED_DEFAULT (1) /**< Default is to include the Service Changed characteristic in the Attribute Table. */ +/** @} */ + +/** @defgroup BLE_GATTS_ATTR_TAB_SIZE Attribute Table size + * @{ + */ +#define BLE_GATTS_ATTR_TAB_SIZE_MIN (248) /**< Minimum Attribute Table size */ +#define BLE_GATTS_ATTR_TAB_SIZE_DEFAULT (1408) /**< Default Attribute Table size. */ +/** @} */ + +/** @defgroup BLE_GATTS_DEFAULTS GATT Server defaults + * @{ + */ +#define BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT 1 /**< Default number of Handle Value Notifications that can be queued for transmission. */ +/** @} */ + +/** @} */ + +/** @addtogroup BLE_GATTS_STRUCTURES Structures + * @{ */ + +/** + * @brief BLE GATTS connection configuration parameters, set with @ref sd_ble_cfg_set. + */ +typedef struct +{ + uint8_t hvn_tx_queue_size; /**< Minimum guaranteed number of Handle Value Notifications that can be queued for transmission. + The default value is @ref BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT */ +} ble_gatts_conn_cfg_t; + +/**@brief Attribute metadata. */ +typedef struct +{ + ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */ + ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ + uint8_t vlen :1; /**< Variable length attribute. */ + uint8_t vloc :2; /**< Value location, see @ref BLE_GATTS_VLOCS.*/ + uint8_t rd_auth :1; /**< Read authorization and value will be requested from the application on every read operation. */ + uint8_t wr_auth :1; /**< Write authorization will be requested from the application on every Write Request operation (but not Write Command). */ +} ble_gatts_attr_md_t; + + +/**@brief GATT Attribute. */ +typedef struct +{ + ble_uuid_t const *p_uuid; /**< Pointer to the attribute UUID. */ + ble_gatts_attr_md_t const *p_attr_md; /**< Pointer to the attribute metadata structure. */ + uint16_t init_len; /**< Initial attribute value length in bytes. */ + uint16_t init_offs; /**< Initial attribute value offset in bytes. If different from zero, the first init_offs bytes of the attribute value will be left uninitialized. */ + uint16_t max_len; /**< Maximum attribute value length in bytes, see @ref BLE_GATTS_ATTR_LENS_MAX for maximum values. */ + uint8_t *p_value; /**< Pointer to the attribute data. Please note that if the @ref BLE_GATTS_VLOC_USER value location is selected in the attribute metadata, this will have to point to a buffer + that remains valid through the lifetime of the attribute. This excludes usage of automatic variables that may go out of scope or any other temporary location. + The stack may access that memory directly without the application's knowledge. For writable characteristics, this value must not be a location in flash memory.*/ +} ble_gatts_attr_t; + +/**@brief GATT Attribute Value. */ +typedef struct +{ + uint16_t len; /**< Length in bytes to be written or read. Length in bytes written or read after successful return.*/ + uint16_t offset; /**< Attribute value offset. */ + uint8_t *p_value; /**< Pointer to where value is stored or will be stored. + If value is stored in user memory, only the attribute length is updated when p_value == NULL. + Set to NULL when reading to obtain the complete length of the attribute value */ +} ble_gatts_value_t; + + +/**@brief GATT Characteristic Presentation Format. */ +typedef struct +{ + uint8_t format; /**< Format of the value, see @ref BLE_GATT_CPF_FORMATS. */ + int8_t exponent; /**< Exponent for integer data types. */ + uint16_t unit; /**< Unit from Bluetooth Assigned Numbers. */ + uint8_t name_space; /**< Namespace from Bluetooth Assigned Numbers, see @ref BLE_GATT_CPF_NAMESPACES. */ + uint16_t desc; /**< Namespace description from Bluetooth Assigned Numbers, see @ref BLE_GATT_CPF_NAMESPACES. */ +} ble_gatts_char_pf_t; + + +/**@brief GATT Characteristic metadata. */ +typedef struct +{ + ble_gatt_char_props_t char_props; /**< Characteristic Properties. */ + ble_gatt_char_ext_props_t char_ext_props; /**< Characteristic Extended Properties. */ + uint8_t const *p_char_user_desc; /**< Pointer to a UTF-8 encoded string (non-NULL terminated), NULL if the descriptor is not required. */ + uint16_t char_user_desc_max_size; /**< The maximum size in bytes of the user description descriptor. */ + uint16_t char_user_desc_size; /**< The size of the user description, must be smaller or equal to char_user_desc_max_size. */ + ble_gatts_char_pf_t const *p_char_pf; /**< Pointer to a presentation format structure or NULL if the CPF descriptor is not required. */ + ble_gatts_attr_md_t const *p_user_desc_md; /**< Attribute metadata for the User Description descriptor, or NULL for default values. */ + ble_gatts_attr_md_t const *p_cccd_md; /**< Attribute metadata for the Client Characteristic Configuration Descriptor, or NULL for default values. */ + ble_gatts_attr_md_t const *p_sccd_md; /**< Attribute metadata for the Server Characteristic Configuration Descriptor, or NULL for default values. */ +} ble_gatts_char_md_t; + + +/**@brief GATT Characteristic Definition Handles. */ +typedef struct +{ + uint16_t value_handle; /**< Handle to the characteristic value. */ + uint16_t user_desc_handle; /**< Handle to the User Description descriptor, or @ref BLE_GATT_HANDLE_INVALID if not present. */ + uint16_t cccd_handle; /**< Handle to the Client Characteristic Configuration Descriptor, or @ref BLE_GATT_HANDLE_INVALID if not present. */ + uint16_t sccd_handle; /**< Handle to the Server Characteristic Configuration Descriptor, or @ref BLE_GATT_HANDLE_INVALID if not present. */ +} ble_gatts_char_handles_t; + + +/**@brief GATT HVx parameters. */ +typedef struct +{ + uint16_t handle; /**< Characteristic Value Handle. */ + uint8_t type; /**< Indication or Notification, see @ref BLE_GATT_HVX_TYPES. */ + uint16_t offset; /**< Offset within the attribute value. */ + uint16_t *p_len; /**< Length in bytes to be written, length in bytes written after return. */ + uint8_t const *p_data; /**< Actual data content, use NULL to use the current attribute value. */ +} ble_gatts_hvx_params_t; + +/**@brief GATT Authorization parameters. */ +typedef struct +{ + uint16_t gatt_status; /**< GATT status code for the operation, see @ref BLE_GATT_STATUS_CODES. */ + uint8_t update : 1; /**< If set, data supplied in p_data will be used to update the attribute value. + Please note that for @ref BLE_GATTS_AUTHORIZE_TYPE_WRITE operations this bit must always be set, + as the data to be written needs to be stored and later provided by the application. */ + uint16_t offset; /**< Offset of the attribute value being updated. */ + uint16_t len; /**< Length in bytes of the value in p_data pointer, see @ref BLE_GATTS_ATTR_LENS_MAX. */ + uint8_t const *p_data; /**< Pointer to new value used to update the attribute value. */ +} ble_gatts_authorize_params_t; + +/**@brief GATT Read or Write Authorize Reply parameters. */ +typedef struct +{ + uint8_t type; /**< Type of authorize operation, see @ref BLE_GATTS_AUTHORIZE_TYPES. */ + union { + ble_gatts_authorize_params_t read; /**< Read authorization parameters. */ + ble_gatts_authorize_params_t write; /**< Write authorization parameters. */ + } params; /**< Reply Parameters. */ +} ble_gatts_rw_authorize_reply_params_t; + +/**@brief Service Changed Inclusion configuration parameters, set with @ref sd_ble_cfg_set. */ +typedef struct +{ + uint8_t service_changed : 1; /**< If 1, include the Service Changed characteristic in the Attribute Table. Default is @ref BLE_GATTS_SERVICE_CHANGED_DEFAULT. */ +} ble_gatts_cfg_service_changed_t; + +/**@brief Attribute table size configuration parameters, set with @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_INVALID_LENGTH One or more of the following is true: + * - The specified Attribute Table size is too small. + * The minimum acceptable size is defined by @ref BLE_GATTS_ATTR_TAB_SIZE_MIN. + * - The specified Attribute Table size is not a multiple of 4. + */ +typedef struct +{ + uint32_t attr_tab_size; /**< Attribute table size. Default is @ref BLE_GATTS_ATTR_TAB_SIZE_DEFAULT, minimum is @ref BLE_GATTS_ATTR_TAB_SIZE_MIN. */ +} ble_gatts_cfg_attr_tab_size_t; + +/**@brief Config structure for GATTS configurations. */ +typedef union +{ + ble_gatts_cfg_service_changed_t service_changed; /**< Include service changed characteristic, cfg_id is @ref BLE_GATTS_CFG_SERVICE_CHANGED. */ + ble_gatts_cfg_attr_tab_size_t attr_tab_size; /**< Attribute table size, cfg_id is @ref BLE_GATTS_CFG_ATTR_TAB_SIZE. */ +} ble_gatts_cfg_t; + + +/**@brief Event structure for @ref BLE_GATTS_EVT_WRITE. */ +typedef struct +{ + uint16_t handle; /**< Attribute Handle. */ + ble_uuid_t uuid; /**< Attribute UUID. */ + uint8_t op; /**< Type of write operation, see @ref BLE_GATTS_OPS. */ + uint8_t auth_required; /**< Writing operation deferred due to authorization requirement. Application may use @ref sd_ble_gatts_value_set to finalize the writing operation. */ + uint16_t offset; /**< Offset for the write operation. */ + uint16_t len; /**< Length of the received data. */ + uint8_t data[1]; /**< Received data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation. + See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */ +} ble_gatts_evt_write_t; + +/**@brief Event substructure for authorized read requests, see @ref ble_gatts_evt_rw_authorize_request_t. */ +typedef struct +{ + uint16_t handle; /**< Attribute Handle. */ + ble_uuid_t uuid; /**< Attribute UUID. */ + uint16_t offset; /**< Offset for the read operation. */ +} ble_gatts_evt_read_t; + +/**@brief Event structure for @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST. */ +typedef struct +{ + uint8_t type; /**< Type of authorize operation, see @ref BLE_GATTS_AUTHORIZE_TYPES. */ + union { + ble_gatts_evt_read_t read; /**< Attribute Read Parameters. */ + ble_gatts_evt_write_t write; /**< Attribute Write Parameters. */ + } request; /**< Request Parameters. */ +} ble_gatts_evt_rw_authorize_request_t; + +/**@brief Event structure for @ref BLE_GATTS_EVT_SYS_ATTR_MISSING. */ +typedef struct +{ + uint8_t hint; /**< Hint (currently unused). */ +} ble_gatts_evt_sys_attr_missing_t; + + +/**@brief Event structure for @ref BLE_GATTS_EVT_HVC. */ +typedef struct +{ + uint16_t handle; /**< Attribute Handle. */ +} ble_gatts_evt_hvc_t; + +/**@brief Event structure for @ref BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST. */ +typedef struct +{ + uint16_t client_rx_mtu; /**< Client RX MTU size. */ +} ble_gatts_evt_exchange_mtu_request_t; + +/**@brief Event structure for @ref BLE_GATTS_EVT_TIMEOUT. */ +typedef struct +{ + uint8_t src; /**< Timeout source, see @ref BLE_GATT_TIMEOUT_SOURCES. */ +} ble_gatts_evt_timeout_t; + +/**@brief Event structure for @ref BLE_GATTS_EVT_HVN_TX_COMPLETE. */ +typedef struct +{ + uint8_t count; /**< Number of notification transmissions completed. */ +} ble_gatts_evt_hvn_tx_complete_t; + +/**@brief GATTS event structure. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which the event occurred. */ + union + { + ble_gatts_evt_write_t write; /**< Write Event Parameters. */ + ble_gatts_evt_rw_authorize_request_t authorize_request; /**< Read or Write Authorize Request Parameters. */ + ble_gatts_evt_sys_attr_missing_t sys_attr_missing; /**< System attributes missing. */ + ble_gatts_evt_hvc_t hvc; /**< Handle Value Confirmation Event Parameters. */ + ble_gatts_evt_exchange_mtu_request_t exchange_mtu_request; /**< Exchange MTU Request Event Parameters. */ + ble_gatts_evt_timeout_t timeout; /**< Timeout Event. */ + ble_gatts_evt_hvn_tx_complete_t hvn_tx_complete; /**< Handle Value Notification transmission complete Event Parameters. */ + } params; /**< Event Parameters. */ +} ble_gatts_evt_t; + +/** @} */ + +/** @addtogroup BLE_GATTS_FUNCTIONS Functions + * @{ */ + +/**@brief Add a service declaration to the Attribute Table. + * + * @note Secondary Services are only relevant in the context of the entity that references them, it is therefore forbidden to + * add a secondary service declaration that is not referenced by another service later in the Attribute Table. + * + * @mscs + * @mmsc{@ref BLE_GATTS_ATT_TABLE_POP_MSC} + * @endmscs + * + * @param[in] type Toggles between primary and secondary services, see @ref BLE_GATTS_SRVC_TYPES. + * @param[in] p_uuid Pointer to service UUID. + * @param[out] p_handle Pointer to a 16-bit word where the assigned handle will be stored. + * + * @retval ::NRF_SUCCESS Successfully added a service declaration. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, Vendor Specific UUIDs need to be present in the table. + * @retval ::NRF_ERROR_FORBIDDEN Forbidden value supplied, certain UUIDs are reserved for the stack. + * @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation. + */ +SVCALL(SD_BLE_GATTS_SERVICE_ADD, uint32_t, sd_ble_gatts_service_add(uint8_t type, ble_uuid_t const *p_uuid, uint16_t *p_handle)); + + +/**@brief Add an include declaration to the Attribute Table. + * + * @note It is currently only possible to add an include declaration to the last added service (i.e. only sequential population is supported at this time). + * + * @note The included service must already be present in the Attribute Table prior to this call. + * + * @mscs + * @mmsc{@ref BLE_GATTS_ATT_TABLE_POP_MSC} + * @endmscs + * + * @param[in] service_handle Handle of the service where the included service is to be placed, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially. + * @param[in] inc_srvc_handle Handle of the included service. + * @param[out] p_include_handle Pointer to a 16-bit word where the assigned handle will be stored. + * + * @retval ::NRF_SUCCESS Successfully added an include declaration. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, handle values need to match previously added services. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation, a service context is required. + * @retval ::NRF_ERROR_NOT_SUPPORTED Feature is not supported, service_handle must be that of the last added service. + * @retval ::NRF_ERROR_FORBIDDEN Forbidden value supplied, self inclusions are not allowed. + * @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation. + * @retval ::NRF_ERROR_NOT_FOUND Attribute not found. + */ +SVCALL(SD_BLE_GATTS_INCLUDE_ADD, uint32_t, sd_ble_gatts_include_add(uint16_t service_handle, uint16_t inc_srvc_handle, uint16_t *p_include_handle)); + + +/**@brief Add a characteristic declaration, a characteristic value declaration and optional characteristic descriptor declarations to the Attribute Table. + * + * @note It is currently only possible to add a characteristic to the last added service (i.e. only sequential population is supported at this time). + * + * @note Several restrictions apply to the parameters, such as matching permissions between the user description descriptor and the writable auxiliaries bits, + * readable (no security) and writable (selectable) CCCDs and SCCDs and valid presentation format values. + * + * @note If no metadata is provided for the optional descriptors, their permissions will be derived from the characteristic permissions. + * + * @mscs + * @mmsc{@ref BLE_GATTS_ATT_TABLE_POP_MSC} + * @endmscs + * + * @param[in] service_handle Handle of the service where the characteristic is to be placed, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially. + * @param[in] p_char_md Characteristic metadata. + * @param[in] p_attr_char_value Pointer to the attribute structure corresponding to the characteristic value. + * @param[out] p_handles Pointer to the structure where the assigned handles will be stored. + * + * @retval ::NRF_SUCCESS Successfully added a characteristic. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, service handle, Vendor Specific UUIDs, lengths, and permissions need to adhere to the constraints. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation, a service context is required. + * @retval ::NRF_ERROR_FORBIDDEN Forbidden value supplied, certain UUIDs are reserved for the stack. + * @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation. + * @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied, attribute lengths are restricted by @ref BLE_GATTS_ATTR_LENS_MAX. + */ +SVCALL(SD_BLE_GATTS_CHARACTERISTIC_ADD, uint32_t, sd_ble_gatts_characteristic_add(uint16_t service_handle, ble_gatts_char_md_t const *p_char_md, ble_gatts_attr_t const *p_attr_char_value, ble_gatts_char_handles_t *p_handles)); + + +/**@brief Add a descriptor to the Attribute Table. + * + * @note It is currently only possible to add a descriptor to the last added characteristic (i.e. only sequential population is supported at this time). + * + * @mscs + * @mmsc{@ref BLE_GATTS_ATT_TABLE_POP_MSC} + * @endmscs + * + * @param[in] char_handle Handle of the characteristic where the descriptor is to be placed, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially. + * @param[in] p_attr Pointer to the attribute structure. + * @param[out] p_handle Pointer to a 16-bit word where the assigned handle will be stored. + * + * @retval ::NRF_SUCCESS Successfully added a descriptor. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, characteristic handle, Vendor Specific UUIDs, lengths, and permissions need to adhere to the constraints. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation, a characteristic context is required. + * @retval ::NRF_ERROR_FORBIDDEN Forbidden value supplied, certain UUIDs are reserved for the stack. + * @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation. + * @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied, attribute lengths are restricted by @ref BLE_GATTS_ATTR_LENS_MAX. + */ +SVCALL(SD_BLE_GATTS_DESCRIPTOR_ADD, uint32_t, sd_ble_gatts_descriptor_add(uint16_t char_handle, ble_gatts_attr_t const *p_attr, uint16_t *p_handle)); + +/**@brief Set the value of a given attribute. + * + * @note Values other than system attributes can be set at any time, regardless of whether any active connections exist. + * + * @mscs + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_QUEUE_FULL_MSC} + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_NOAUTH_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. Ignored if the value does not belong to a system attribute. + * @param[in] handle Attribute handle. + * @param[in,out] p_value Attribute value information. + * + * @retval ::NRF_SUCCESS Successfully set the value of the attribute. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_NOT_FOUND Attribute not found. + * @retval ::NRF_ERROR_FORBIDDEN Forbidden handle supplied, certain attributes are not modifiable by the application. + * @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied, attribute lengths are restricted by @ref BLE_GATTS_ATTR_LENS_MAX. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied on a system attribute. + */ +SVCALL(SD_BLE_GATTS_VALUE_SET, uint32_t, sd_ble_gatts_value_set(uint16_t conn_handle, uint16_t handle, ble_gatts_value_t *p_value)); + +/**@brief Get the value of a given attribute. + * + * @note If the attribute value is longer than the size of the supplied buffer, + * @ref ble_gatts_value_t::len will return the total attribute value length (excluding offset), + * and not the number of bytes actually returned in @ref ble_gatts_value_t::p_value. + * The application may use this information to allocate a suitable buffer size. + * + * @note When retrieving system attribute values with this function, the connection handle + * may refer to an already disconnected connection. Refer to the documentation of + * @ref sd_ble_gatts_sys_attr_get for further information. + * + * @param[in] conn_handle Connection handle. Ignored if the value does not belong to a system attribute. + * @param[in] handle Attribute handle. + * @param[in,out] p_value Attribute value information. + * + * @retval ::NRF_SUCCESS Successfully retrieved the value of the attribute. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_NOT_FOUND Attribute not found. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid attribute offset supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied on a system attribute. + * @retval ::BLE_ERROR_GATTS_SYS_ATTR_MISSING System attributes missing, use @ref sd_ble_gatts_sys_attr_set to set them to a known value. + */ +SVCALL(SD_BLE_GATTS_VALUE_GET, uint32_t, sd_ble_gatts_value_get(uint16_t conn_handle, uint16_t handle, ble_gatts_value_t *p_value)); + +/**@brief Notify or Indicate an attribute value. + * + * @details This function checks for the relevant Client Characteristic Configuration descriptor value to verify that the relevant operation + * (notification or indication) has been enabled by the client. It is also able to update the attribute value before issuing the PDU, so that + * the application can atomically perform a value update and a server initiated transaction with a single API call. + * + * @note The local attribute value may be updated even if an outgoing packet is not sent to the peer due to an error during execution. + * The Attribute Table has been updated if one of the following error codes is returned: @ref NRF_ERROR_INVALID_STATE, @ref NRF_ERROR_BUSY, + * @ref NRF_ERROR_FORBIDDEN, @ref BLE_ERROR_GATTS_SYS_ATTR_MISSING and @ref NRF_ERROR_RESOURCES. + * The caller can check whether the value has been updated by looking at the contents of *(@ref ble_gatts_hvx_params_t::p_len). + * + * @note Only one indication procedure can be ongoing per connection at a time. + * If the application tries to indicate an attribute value while another indication procedure is ongoing, + * the function call will return @ref NRF_ERROR_BUSY. + * A @ref BLE_GATTS_EVT_HVC event will be issued as soon as the confirmation arrives from the peer. + * + * @note The number of Handle Value Notifications that can be queued is configured by @ref ble_gatts_conn_cfg_t::hvn_tx_queue_size + * When the queue is full, the function call will return @ref NRF_ERROR_RESOURCES. + * A @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event will be issued as soon as the transmission of the notification is complete. + * + * @note The application can keep track of the available queue element count for notifications by following the procedure below: + * - Store initial queue element count in a variable. + * - Decrement the variable, which stores the currently available queue element count, by one when a call to this function returns @ref NRF_SUCCESS. + * - Increment the variable, which stores the current available queue element count, by the count variable in @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event. + * + * @events + * @event{@ref BLE_GATTS_EVT_HVN_TX_COMPLETE, Notification transmission complete.} + * @event{@ref BLE_GATTS_EVT_HVC, Confirmation received from the peer.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GATTS_HVX_SYS_ATTRS_MISSING_MSC} + * @mmsc{@ref BLE_GATTS_HVN_MSC} + * @mmsc{@ref BLE_GATTS_HVI_MSC} + * @mmsc{@ref BLE_GATTS_HVX_DISABLED_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in,out] p_hvx_params Pointer to an HVx parameters structure. If @ref ble_gatts_hvx_params_t::p_data + * contains a non-NULL pointer the attribute value will be updated with the contents + * pointed by it before sending the notification or indication. If the attribute value + * is updated, @ref ble_gatts_hvx_params_t::p_len is updated by the SoftDevice to + * contain the number of actual bytes written, else it will be set to 0. + * + * @retval ::NRF_SUCCESS Successfully queued a notification or indication for transmission, and optionally updated the attribute value. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE One or more of the following is true: + * - Invalid Connection State + * - Notifications and/or indications not enabled in the CCCD + * - An ATT_MTU exchange is ongoing + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::BLE_ERROR_INVALID_ATTR_HANDLE Invalid attribute handle(s) supplied. Only attributes added directly by the application are available to notify and indicate. + * @retval ::BLE_ERROR_GATTS_INVALID_ATTR_TYPE Invalid attribute type(s) supplied, only characteristic values may be notified and indicated. + * @retval ::NRF_ERROR_NOT_FOUND Attribute not found. + * @retval ::NRF_ERROR_FORBIDDEN The connection's current security level is lower than the one required by the write permissions of the CCCD associated with this characteristic. + * @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied. + * @retval ::NRF_ERROR_BUSY For @ref BLE_GATT_HVX_INDICATION Procedure already in progress. Wait for a @ref BLE_GATTS_EVT_HVC event and retry. + * @retval ::BLE_ERROR_GATTS_SYS_ATTR_MISSING System attributes missing, use @ref sd_ble_gatts_sys_attr_set to set them to a known value. + * @retval ::NRF_ERROR_RESOURCES Too many notifications queued. + * Wait for a @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event and retry. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTS_HVX, uint32_t, sd_ble_gatts_hvx(uint16_t conn_handle, ble_gatts_hvx_params_t const *p_hvx_params)); + +/**@brief Indicate the Service Changed attribute value. + * + * @details This call will send a Handle Value Indication to one or more peers connected to inform them that the Attribute + * Table layout has changed. As soon as the peer has confirmed the indication, a @ref BLE_GATTS_EVT_SC_CONFIRM event will + * be issued. + * + * @note Some of the restrictions and limitations that apply to @ref sd_ble_gatts_hvx also apply here. + * + * @events + * @event{@ref BLE_GATTS_EVT_SC_CONFIRM, Confirmation of attribute table change received from peer.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GATTS_SC_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] start_handle Start of affected attribute handle range. + * @param[in] end_handle End of affected attribute handle range. + * + * @retval ::NRF_SUCCESS Successfully queued the Service Changed indication for transmission. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_NOT_SUPPORTED Service Changed not enabled at initialization. See @ref + * sd_ble_cfg_set and @ref ble_gatts_cfg_service_changed_t. + * @retval ::NRF_ERROR_INVALID_STATE One or more of the following is true: + * - Invalid Connection State + * - Notifications and/or indications not enabled in the CCCD + * - An ATT_MTU exchange is ongoing + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::BLE_ERROR_INVALID_ATTR_HANDLE Invalid attribute handle(s) supplied, handles must be in the range populated by the application. + * @retval ::NRF_ERROR_BUSY Procedure already in progress. + * @retval ::BLE_ERROR_GATTS_SYS_ATTR_MISSING System attributes missing, use @ref sd_ble_gatts_sys_attr_set to set them to a known value. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTS_SERVICE_CHANGED, uint32_t, sd_ble_gatts_service_changed(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle)); + +/**@brief Respond to a Read/Write authorization request. + * + * @note This call should only be used as a response to a @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event issued to the application. + * + * @mscs + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_AUTH_MSC} + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_BUF_AUTH_MSC} + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_NOAUTH_MSC} + * @mmsc{@ref BLE_GATTS_READ_REQ_AUTH_MSC} + * @mmsc{@ref BLE_GATTS_WRITE_REQ_AUTH_MSC} + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_QUEUE_FULL_MSC} + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_PEER_CANCEL_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_rw_authorize_reply_params Pointer to a structure with the attribute provided by the application. + * + * @note @ref ble_gatts_authorize_params_t::p_data is ignored when this function is used to respond + * to a @ref BLE_GATTS_AUTHORIZE_TYPE_READ event if @ref ble_gatts_authorize_params_t::update + * is set to 0. + * + * @retval ::NRF_SUCCESS Successfully queued a response to the peer, and in the case of a write operation, Attribute Table updated. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State or no authorization request pending. + * @retval ::NRF_ERROR_INVALID_PARAM Authorization op invalid, + * handle supplied does not match requested handle, + * or invalid data to be written provided by the application. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTS_RW_AUTHORIZE_REPLY, uint32_t, sd_ble_gatts_rw_authorize_reply(uint16_t conn_handle, ble_gatts_rw_authorize_reply_params_t const *p_rw_authorize_reply_params)); + + +/**@brief Update persistent system attribute information. + * + * @details Supply information about persistent system attributes to the stack, + * previously obtained using @ref sd_ble_gatts_sys_attr_get. + * This call is only allowed for active connections, and is usually + * made immediately after a connection is established with an known bonded device, + * often as a response to a @ref BLE_GATTS_EVT_SYS_ATTR_MISSING. + * + * p_sysattrs may point directly to the application's stored copy of the system attributes + * obtained using @ref sd_ble_gatts_sys_attr_get. + * If the pointer is NULL, the system attribute info is initialized, assuming that + * the application does not have any previously saved system attribute data for this device. + * + * @note The state of persistent system attributes is reset upon connection establishment and then remembered for its duration. + * + * @note If this call returns with an error code different from @ref NRF_SUCCESS, the storage of persistent system attributes may have been completed only partially. + * This means that the state of the attribute table is undefined, and the application should either provide a new set of attributes using this same call or + * reset the SoftDevice to return to a known state. + * + * @note When the @ref BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS is used with this function, only the system attributes included in system services will be modified. + * @note When the @ref BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS is used with this function, only the system attributes included in user services will be modified. + * + * @mscs + * @mmsc{@ref BLE_GATTS_HVX_SYS_ATTRS_MISSING_MSC} + * @mmsc{@ref BLE_GATTS_SYS_ATTRS_UNK_PEER_MSC} + * @mmsc{@ref BLE_GATTS_SYS_ATTRS_BONDED_PEER_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_sys_attr_data Pointer to a saved copy of system attributes supplied to the stack, or NULL. + * @param[in] len Size of data pointed by p_sys_attr_data, in octets. + * @param[in] flags Optional additional flags, see @ref BLE_GATTS_SYS_ATTR_FLAGS + * + * @retval ::NRF_SUCCESS Successfully set the system attribute information. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid flags supplied. + * @retval ::NRF_ERROR_INVALID_DATA Invalid data supplied, the data should be exactly the same as retrieved with @ref sd_ble_gatts_sys_attr_get. + * @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation. + */ +SVCALL(SD_BLE_GATTS_SYS_ATTR_SET, uint32_t, sd_ble_gatts_sys_attr_set(uint16_t conn_handle, uint8_t const *p_sys_attr_data, uint16_t len, uint32_t flags)); + + +/**@brief Retrieve persistent system attribute information from the stack. + * + * @details This call is used to retrieve information about values to be stored persistently by the application + * during the lifetime of a connection or after it has been terminated. When a new connection is established with the same bonded device, + * the system attribute information retrieved with this function should be restored using using @ref sd_ble_gatts_sys_attr_set. + * If retrieved after disconnection, the data should be read before a new connection established. The connection handle for + * the previous, now disconnected, connection will remain valid until a new one is created to allow this API call to refer to it. + * Connection handles belonging to active connections can be used as well, but care should be taken since the system attributes + * may be written to at any time by the peer during a connection's lifetime. + * + * @note When the @ref BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS is used with this function, only the system attributes included in system services will be returned. + * @note When the @ref BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS is used with this function, only the system attributes included in user services will be returned. + * + * @mscs + * @mmsc{@ref BLE_GATTS_SYS_ATTRS_BONDED_PEER_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle of the recently terminated connection. + * @param[out] p_sys_attr_data Pointer to a buffer where updated information about system attributes will be filled in. The format of the data is described + * in @ref BLE_GATTS_SYS_ATTRS_FORMAT. NULL can be provided to obtain the length of the data. + * @param[in,out] p_len Size of application buffer if p_sys_attr_data is not NULL. Unconditionally updated to actual length of system attribute data. + * @param[in] flags Optional additional flags, see @ref BLE_GATTS_SYS_ATTR_FLAGS + * + * @retval ::NRF_SUCCESS Successfully retrieved the system attribute information. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid flags supplied. + * @retval ::NRF_ERROR_DATA_SIZE The system attribute information did not fit into the provided buffer. + * @retval ::NRF_ERROR_NOT_FOUND No system attributes found. + */ +SVCALL(SD_BLE_GATTS_SYS_ATTR_GET, uint32_t, sd_ble_gatts_sys_attr_get(uint16_t conn_handle, uint8_t *p_sys_attr_data, uint16_t *p_len, uint32_t flags)); + + +/**@brief Retrieve the first valid user attribute handle. + * + * @param[out] p_handle Pointer to an integer where the handle will be stored. + * + * @retval ::NRF_SUCCESS Successfully retrieved the handle. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + */ +SVCALL(SD_BLE_GATTS_INITIAL_USER_HANDLE_GET, uint32_t, sd_ble_gatts_initial_user_handle_get(uint16_t *p_handle)); + +/**@brief Retrieve the attribute UUID and/or metadata. + * + * @param[in] handle Attribute handle + * @param[out] p_uuid UUID of the attribute. Use NULL to omit this field. + * @param[out] p_md Metadata of the attribute. Use NULL to omit this field. + * + * @retval ::NRF_SUCCESS Successfully retrieved the attribute metadata, + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameters supplied. Returned when both @c p_uuid and @c p_md are NULL. + * @retval ::NRF_ERROR_NOT_FOUND Attribute was not found. + */ +SVCALL(SD_BLE_GATTS_ATTR_GET, uint32_t, sd_ble_gatts_attr_get(uint16_t handle, ble_uuid_t * p_uuid, ble_gatts_attr_md_t * p_md)); + +/**@brief Reply to an ATT_MTU exchange request by sending an Exchange MTU Response to the client. + * + * @details This function is only used to reply to a @ref BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST event. + * + * @details The SoftDevice sets ATT_MTU to the minimum of: + * - The Client RX MTU value from @ref BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST, and + * - The Server RX MTU value. + * + * However, the SoftDevice never sets ATT_MTU lower than @ref BLE_GATT_ATT_MTU_DEFAULT. + * + * @mscs + * @mmsc{@ref BLE_GATTS_MTU_EXCHANGE} + * @endmscs + * + * @param[in] conn_handle The connection handle identifying the connection to perform this procedure on. + * @param[in] server_rx_mtu Server RX MTU size. + * - The minimum value is @ref BLE_GATT_ATT_MTU_DEFAULT. + * - The maximum value is @ref ble_gatt_conn_cfg_t::att_mtu in the connection configuration + * used for this connection. + * - The value must be equal to Client RX MTU size given in @ref sd_ble_gattc_exchange_mtu_request + * if an ATT_MTU exchange has already been performed in the other direction. + * + * @retval ::NRF_SUCCESS Successfully sent response to the client. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State or no ATT_MTU exchange request pending. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid Server RX MTU size supplied. + * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection. + */ +SVCALL(SD_BLE_GATTS_EXCHANGE_MTU_REPLY, uint32_t, sd_ble_gatts_exchange_mtu_reply(uint16_t conn_handle, uint16_t server_rx_mtu)); +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif // BLE_GATTS_H__ + +/** + @} +*/ diff --git a/components/softdevice/s140/headers/ble_hci.h b/components/softdevice/s140/headers/ble_hci.h new file mode 100644 index 0000000..f0dde9a --- /dev/null +++ b/components/softdevice/s140/headers/ble_hci.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @addtogroup BLE_COMMON + @{ +*/ + + +#ifndef BLE_HCI_H__ +#define BLE_HCI_H__ +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup BLE_HCI_STATUS_CODES Bluetooth status codes + * @{ */ + +#define BLE_HCI_STATUS_CODE_SUCCESS 0x00 /**< Success. */ +#define BLE_HCI_STATUS_CODE_UNKNOWN_BTLE_COMMAND 0x01 /**< Unknown BLE Command. */ +#define BLE_HCI_STATUS_CODE_UNKNOWN_CONNECTION_IDENTIFIER 0x02 /**< Unknown Connection Identifier. */ +/*0x03 Hardware Failure +0x04 Page Timeout +*/ +#define BLE_HCI_AUTHENTICATION_FAILURE 0x05 /**< Authentication Failure. */ +#define BLE_HCI_STATUS_CODE_PIN_OR_KEY_MISSING 0x06 /**< Pin or Key missing. */ +#define BLE_HCI_MEMORY_CAPACITY_EXCEEDED 0x07 /**< Memory Capacity Exceeded. */ +#define BLE_HCI_CONNECTION_TIMEOUT 0x08 /**< Connection Timeout. */ +/*0x09 Connection Limit Exceeded +0x0A Synchronous Connection Limit To A Device Exceeded +0x0B ACL Connection Already Exists*/ +#define BLE_HCI_STATUS_CODE_COMMAND_DISALLOWED 0x0C /**< Command Disallowed. */ +/*0x0D Connection Rejected due to Limited Resources +0x0E Connection Rejected Due To Security Reasons +0x0F Connection Rejected due to Unacceptable BD_ADDR +0x10 Connection Accept Timeout Exceeded +0x11 Unsupported Feature or Parameter Value*/ +#define BLE_HCI_STATUS_CODE_INVALID_BTLE_COMMAND_PARAMETERS 0x12 /**< Invalid BLE Command Parameters. */ +#define BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION 0x13 /**< Remote User Terminated Connection. */ +#define BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES 0x14 /**< Remote Device Terminated Connection due to low resources.*/ +#define BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF 0x15 /**< Remote Device Terminated Connection due to power off. */ +#define BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION 0x16 /**< Local Host Terminated Connection. */ +/* +0x17 Repeated Attempts +0x18 Pairing Not Allowed +0x19 Unknown LMP PDU +*/ +#define BLE_HCI_UNSUPPORTED_REMOTE_FEATURE 0x1A /**< Unsupported Remote Feature. */ +/* +0x1B SCO Offset Rejected +0x1C SCO Interval Rejected +0x1D SCO Air Mode Rejected*/ +#define BLE_HCI_STATUS_CODE_INVALID_LMP_PARAMETERS 0x1E /**< Invalid LMP Parameters. */ +#define BLE_HCI_STATUS_CODE_UNSPECIFIED_ERROR 0x1F /**< Unspecified Error. */ +/*0x20 Unsupported LMP Parameter Value +0x21 Role Change Not Allowed +*/ +#define BLE_HCI_STATUS_CODE_LMP_RESPONSE_TIMEOUT 0x22 /**< LMP Response Timeout. */ +#define BLE_HCI_STATUS_CODE_LMP_ERROR_TRANSACTION_COLLISION 0x23 /**< LMP Error Transaction Collision/LL Procedure Collision. */ +#define BLE_HCI_STATUS_CODE_LMP_PDU_NOT_ALLOWED 0x24 /**< LMP PDU Not Allowed. */ +/*0x25 Encryption Mode Not Acceptable +0x26 Link Key Can Not be Changed +0x27 Requested QoS Not Supported +*/ +#define BLE_HCI_INSTANT_PASSED 0x28 /**< Instant Passed. */ +#define BLE_HCI_PAIRING_WITH_UNIT_KEY_UNSUPPORTED 0x29 /**< Pairing with Unit Key Unsupported. */ +#define BLE_HCI_DIFFERENT_TRANSACTION_COLLISION 0x2A /**< Different Transaction Collision. */ +/* +0x2B Reserved +0x2C QoS Unacceptable Parameter +0x2D QoS Rejected +0x2E Channel Classification Not Supported +0x2F Insufficient Security +*/ +#define BLE_HCI_PARAMETER_OUT_OF_MANDATORY_RANGE 0x30 /**< Parameter Out Of Mandatory Range. */ +/* +0x31 Reserved +0x32 Role Switch Pending +0x33 Reserved +0x34 Reserved Slot Violation +0x35 Role Switch Failed +0x36 Extended Inquiry Response Too Large +0x37 Secure Simple Pairing Not Supported By Host. +0x38 Host Busy - Pairing +0x39 Connection Rejected due to No Suitable Channel Found*/ +#define BLE_HCI_CONTROLLER_BUSY 0x3A /**< Controller Busy. */ +#define BLE_HCI_CONN_INTERVAL_UNACCEPTABLE 0x3B /**< Connection Interval Unacceptable. */ +#define BLE_HCI_DIRECTED_ADVERTISER_TIMEOUT 0x3C /**< Directed Advertisement Timeout. */ +#define BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE 0x3D /**< Connection Terminated due to MIC Failure. */ +#define BLE_HCI_CONN_FAILED_TO_BE_ESTABLISHED 0x3E /**< Connection Failed to be Established. */ + +/** @} */ + + +#ifdef __cplusplus +} +#endif +#endif // BLE_HCI_H__ + +/** @} */ diff --git a/components/softdevice/s140/headers/ble_l2cap.h b/components/softdevice/s140/headers/ble_l2cap.h new file mode 100644 index 0000000..7587350 --- /dev/null +++ b/components/softdevice/s140/headers/ble_l2cap.h @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2011 - 2020, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @addtogroup BLE_L2CAP Logical Link Control and Adaptation Protocol (L2CAP) + @{ + @brief Definitions and prototypes for the L2CAP interface. + */ + +#ifndef BLE_L2CAP_H__ +#define BLE_L2CAP_H__ + +#include +#include "nrf_svc.h" +#include "nrf_error.h" +#include "ble_ranges.h" +#include "ble_types.h" +#include "ble_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@addtogroup BLE_L2CAP_TERMINOLOGY Terminology + * @{ + * @details + * + * L2CAP SDU + * - A data unit that the application can send/receive to/from a peer. + * + * L2CAP PDU + * - A data unit that is exchanged between local and remote L2CAP entities. + * It consists of L2CAP protocol control information and payload fields. + * The payload field can contain an L2CAP SDU or a part of an L2CAP SDU. + * + * L2CAP MTU + * - The maximum length of an L2CAP SDU. + * + * L2CAP MPS + * - The maximum length of an L2CAP PDU payload field. + * + * Credits + * - A value indicating the number of L2CAP PDUs that the receiver of the credit can send to the peer. + * @} */ + +/**@addtogroup BLE_L2CAP_ENUMERATIONS Enumerations + * @{ */ + +/**@brief L2CAP API SVC numbers. */ +enum BLE_L2CAP_SVCS +{ + SD_BLE_L2CAP_CH_SETUP = BLE_L2CAP_SVC_BASE + 0, /**< Set up an L2CAP channel. */ + SD_BLE_L2CAP_CH_RELEASE = BLE_L2CAP_SVC_BASE + 1, /**< Release an L2CAP channel. */ + SD_BLE_L2CAP_CH_RX = BLE_L2CAP_SVC_BASE + 2, /**< Receive an SDU on an L2CAP channel. */ + SD_BLE_L2CAP_CH_TX = BLE_L2CAP_SVC_BASE + 3, /**< Transmit an SDU on an L2CAP channel. */ + SD_BLE_L2CAP_CH_FLOW_CONTROL = BLE_L2CAP_SVC_BASE + 4, /**< Advanced SDU reception flow control. */ +}; + +/**@brief L2CAP Event IDs. */ +enum BLE_L2CAP_EVTS +{ + BLE_L2CAP_EVT_CH_SETUP_REQUEST = BLE_L2CAP_EVT_BASE + 0, /**< L2CAP Channel Setup Request event. + \n Reply with @ref sd_ble_l2cap_ch_setup. + \n See @ref ble_l2cap_evt_ch_setup_request_t. */ + BLE_L2CAP_EVT_CH_SETUP_REFUSED = BLE_L2CAP_EVT_BASE + 1, /**< L2CAP Channel Setup Refused event. + \n See @ref ble_l2cap_evt_ch_setup_refused_t. */ + BLE_L2CAP_EVT_CH_SETUP = BLE_L2CAP_EVT_BASE + 2, /**< L2CAP Channel Setup Completed event. + \n See @ref ble_l2cap_evt_ch_setup_t. */ + BLE_L2CAP_EVT_CH_RELEASED = BLE_L2CAP_EVT_BASE + 3, /**< L2CAP Channel Released event. + \n No additional event structure applies. */ + BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED = BLE_L2CAP_EVT_BASE + 4, /**< L2CAP Channel SDU data buffer released event. + \n See @ref ble_l2cap_evt_ch_sdu_buf_released_t. */ + BLE_L2CAP_EVT_CH_CREDIT = BLE_L2CAP_EVT_BASE + 5, /**< L2CAP Channel Credit received. + \n See @ref ble_l2cap_evt_ch_credit_t. */ + BLE_L2CAP_EVT_CH_RX = BLE_L2CAP_EVT_BASE + 6, /**< L2CAP Channel SDU received. + \n See @ref ble_l2cap_evt_ch_rx_t. */ + BLE_L2CAP_EVT_CH_TX = BLE_L2CAP_EVT_BASE + 7, /**< L2CAP Channel SDU transmitted. + \n See @ref ble_l2cap_evt_ch_tx_t. */ +}; + +/** @} */ + +/**@addtogroup BLE_L2CAP_DEFINES Defines + * @{ */ + +/**@brief Maximum number of L2CAP channels per connection. */ +#define BLE_L2CAP_CH_COUNT_MAX (64) + +/**@brief Minimum L2CAP MTU, in bytes. */ +#define BLE_L2CAP_MTU_MIN (23) + +/**@brief Minimum L2CAP MPS, in bytes. */ +#define BLE_L2CAP_MPS_MIN (23) + +/**@brief Invalid CID. */ +#define BLE_L2CAP_CID_INVALID (0x0000) + +/**@brief Default number of credits for @ref sd_ble_l2cap_ch_flow_control. */ +#define BLE_L2CAP_CREDITS_DEFAULT (1) + +/**@defgroup BLE_L2CAP_CH_SETUP_REFUSED_SRCS L2CAP channel setup refused sources + * @{ */ +#define BLE_L2CAP_CH_SETUP_REFUSED_SRC_LOCAL (0x01) /**< Local. */ +#define BLE_L2CAP_CH_SETUP_REFUSED_SRC_REMOTE (0x02) /**< Remote. */ + /** @} */ + + /** @defgroup BLE_L2CAP_CH_STATUS_CODES L2CAP channel status codes + * @{ */ +#define BLE_L2CAP_CH_STATUS_CODE_SUCCESS (0x0000) /**< Success. */ +#define BLE_L2CAP_CH_STATUS_CODE_LE_PSM_NOT_SUPPORTED (0x0002) /**< LE_PSM not supported. */ +#define BLE_L2CAP_CH_STATUS_CODE_NO_RESOURCES (0x0004) /**< No resources available. */ +#define BLE_L2CAP_CH_STATUS_CODE_INSUFF_AUTHENTICATION (0x0005) /**< Insufficient authentication. */ +#define BLE_L2CAP_CH_STATUS_CODE_INSUFF_AUTHORIZATION (0x0006) /**< Insufficient authorization. */ +#define BLE_L2CAP_CH_STATUS_CODE_INSUFF_ENC_KEY_SIZE (0x0007) /**< Insufficient encryption key size. */ +#define BLE_L2CAP_CH_STATUS_CODE_INSUFF_ENC (0x0008) /**< Insufficient encryption. */ +#define BLE_L2CAP_CH_STATUS_CODE_INVALID_SCID (0x0009) /**< Invalid Source CID. */ +#define BLE_L2CAP_CH_STATUS_CODE_SCID_ALLOCATED (0x000A) /**< Source CID already allocated. */ +#define BLE_L2CAP_CH_STATUS_CODE_UNACCEPTABLE_PARAMS (0x000B) /**< Unacceptable parameters. */ +#define BLE_L2CAP_CH_STATUS_CODE_NOT_UNDERSTOOD (0x8000) /**< Command Reject received instead of LE Credit Based Connection Response. */ +#define BLE_L2CAP_CH_STATUS_CODE_TIMEOUT (0xC000) /**< Operation timed out. */ +/** @} */ + +/** @} */ + +/**@addtogroup BLE_L2CAP_STRUCTURES Structures + * @{ */ + +/** + * @brief BLE L2CAP connection configuration parameters, set with @ref sd_ble_cfg_set. + * + * @note These parameters are set per connection, so all L2CAP channels created on this connection + * will have the same parameters. + * + * @retval ::NRF_ERROR_INVALID_PARAM One or more of the following is true: + * - rx_mps is smaller than @ref BLE_L2CAP_MPS_MIN. + * - tx_mps is smaller than @ref BLE_L2CAP_MPS_MIN. + * - ch_count is greater than @ref BLE_L2CAP_CH_COUNT_MAX. + * @retval ::NRF_ERROR_NO_MEM rx_mps or tx_mps is set too high. + */ +typedef struct +{ + uint16_t rx_mps; /**< The maximum L2CAP PDU payload size, in bytes, that L2CAP shall + be able to receive on L2CAP channels on connections with this + configuration. The minimum value is @ref BLE_L2CAP_MPS_MIN. */ + uint16_t tx_mps; /**< The maximum L2CAP PDU payload size, in bytes, that L2CAP shall + be able to transmit on L2CAP channels on connections with this + configuration. The minimum value is @ref BLE_L2CAP_MPS_MIN. */ + uint8_t rx_queue_size; /**< Number of SDU data buffers that can be queued for reception per + L2CAP channel. The minimum value is one. */ + uint8_t tx_queue_size; /**< Number of SDU data buffers that can be queued for transmission + per L2CAP channel. The minimum value is one. */ + uint8_t ch_count; /**< Number of L2CAP channels the application can create per connection + with this configuration. The default value is zero, the maximum + value is @ref BLE_L2CAP_CH_COUNT_MAX. + @note if this parameter is set to zero, all other parameters in + @ref ble_l2cap_conn_cfg_t are ignored. */ +} ble_l2cap_conn_cfg_t; + +/**@brief L2CAP channel RX parameters. */ +typedef struct +{ + uint16_t rx_mtu; /**< The maximum L2CAP SDU size, in bytes, that L2CAP shall be able to + receive on this L2CAP channel. + - Must be equal to or greater than @ref BLE_L2CAP_MTU_MIN. */ + uint16_t rx_mps; /**< The maximum L2CAP PDU payload size, in bytes, that L2CAP shall be + able to receive on this L2CAP channel. + - Must be equal to or greater than @ref BLE_L2CAP_MPS_MIN. + - Must be equal to or less than @ref ble_l2cap_conn_cfg_t::rx_mps. */ + ble_data_t sdu_buf; /**< SDU data buffer for reception. + - If @ref ble_data_t::p_data is non-NULL, initial credits are + issued to the peer. + - If @ref ble_data_t::p_data is NULL, no initial credits are + issued to the peer. */ +} ble_l2cap_ch_rx_params_t; + +/**@brief L2CAP channel setup parameters. */ +typedef struct +{ + ble_l2cap_ch_rx_params_t rx_params; /**< L2CAP channel RX parameters. */ + uint16_t le_psm; /**< LE Protocol/Service Multiplexer. Used when requesting + setup of an L2CAP channel, ignored otherwise. */ + uint16_t status; /**< Status code, see @ref BLE_L2CAP_CH_STATUS_CODES. + Used when replying to a setup request of an L2CAP + channel, ignored otherwise. */ +} ble_l2cap_ch_setup_params_t; + +/**@brief L2CAP channel TX parameters. */ +typedef struct +{ + uint16_t tx_mtu; /**< The maximum L2CAP SDU size, in bytes, that L2CAP is able to + transmit on this L2CAP channel. */ + uint16_t peer_mps; /**< The maximum L2CAP PDU payload size, in bytes, that the peer is + able to receive on this L2CAP channel. */ + uint16_t tx_mps; /**< The maximum L2CAP PDU payload size, in bytes, that L2CAP is able + to transmit on this L2CAP channel. This is effective tx_mps, + selected by the SoftDevice as + MIN( @ref ble_l2cap_ch_tx_params_t::peer_mps, @ref ble_l2cap_conn_cfg_t::tx_mps ) */ + uint16_t credits; /**< Initial credits given by the peer. */ +} ble_l2cap_ch_tx_params_t; + +/**@brief L2CAP Channel Setup Request event. */ +typedef struct +{ + ble_l2cap_ch_tx_params_t tx_params; /**< L2CAP channel TX parameters. */ + uint16_t le_psm; /**< LE Protocol/Service Multiplexer. */ +} ble_l2cap_evt_ch_setup_request_t; + +/**@brief L2CAP Channel Setup Refused event. */ +typedef struct +{ + uint8_t source; /**< Source, see @ref BLE_L2CAP_CH_SETUP_REFUSED_SRCS */ + uint16_t status; /**< Status code, see @ref BLE_L2CAP_CH_STATUS_CODES */ +} ble_l2cap_evt_ch_setup_refused_t; + +/**@brief L2CAP Channel Setup Completed event. */ +typedef struct +{ + ble_l2cap_ch_tx_params_t tx_params; /**< L2CAP channel TX parameters. */ +} ble_l2cap_evt_ch_setup_t; + +/**@brief L2CAP Channel SDU Data Buffer Released event. */ +typedef struct +{ + ble_data_t sdu_buf; /**< Returned reception or transmission SDU data buffer. The SoftDevice + returns SDU data buffers supplied by the application, which have + not yet been returned previously via a @ref BLE_L2CAP_EVT_CH_RX or + @ref BLE_L2CAP_EVT_CH_TX event. */ +} ble_l2cap_evt_ch_sdu_buf_released_t; + +/**@brief L2CAP Channel Credit received event. */ +typedef struct +{ + uint16_t credits; /**< Additional credits given by the peer. */ +} ble_l2cap_evt_ch_credit_t; + +/**@brief L2CAP Channel received SDU event. */ +typedef struct +{ + uint16_t sdu_len; /**< Total SDU length, in bytes. */ + ble_data_t sdu_buf; /**< SDU data buffer. + @note If there is not enough space in the buffer + (sdu_buf.len < sdu_len) then the rest of the SDU will be + silently discarded by the SoftDevice. */ +} ble_l2cap_evt_ch_rx_t; + +/**@brief L2CAP Channel transmitted SDU event. */ +typedef struct +{ + ble_data_t sdu_buf; /**< SDU data buffer. */ +} ble_l2cap_evt_ch_tx_t; + +/**@brief L2CAP event structure. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which the event occured. */ + uint16_t local_cid; /**< Local Channel ID of the L2CAP channel, or + @ref BLE_L2CAP_CID_INVALID if not present. */ + union + { + ble_l2cap_evt_ch_setup_request_t ch_setup_request; /**< L2CAP Channel Setup Request Event Parameters. */ + ble_l2cap_evt_ch_setup_refused_t ch_setup_refused; /**< L2CAP Channel Setup Refused Event Parameters. */ + ble_l2cap_evt_ch_setup_t ch_setup; /**< L2CAP Channel Setup Completed Event Parameters. */ + ble_l2cap_evt_ch_sdu_buf_released_t ch_sdu_buf_released;/**< L2CAP Channel SDU Data Buffer Released Event Parameters. */ + ble_l2cap_evt_ch_credit_t credit; /**< L2CAP Channel Credit Received Event Parameters. */ + ble_l2cap_evt_ch_rx_t rx; /**< L2CAP Channel SDU Received Event Parameters. */ + ble_l2cap_evt_ch_tx_t tx; /**< L2CAP Channel SDU Transmitted Event Parameters. */ + } params; /**< Event Parameters. */ +} ble_l2cap_evt_t; + +/** @} */ + +/**@addtogroup BLE_L2CAP_FUNCTIONS Functions + * @{ */ + +/**@brief Set up an L2CAP channel. + * + * @details This function is used to: + * - Request setup of an L2CAP channel: sends an LE Credit Based Connection Request packet to a peer. + * - Reply to a setup request of an L2CAP channel (if called in response to a + * @ref BLE_L2CAP_EVT_CH_SETUP_REQUEST event): sends an LE Credit Based Connection + * Response packet to a peer. + * + * @note A call to this function will require the application to keep the SDU data buffer alive + * until the SDU data buffer is returned in @ref BLE_L2CAP_EVT_CH_RX or + * @ref BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED event. + * + * @events + * @event{@ref BLE_L2CAP_EVT_CH_SETUP, Setup successful.} + * @event{@ref BLE_L2CAP_EVT_CH_SETUP_REFUSED, Setup failed.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_L2CAP_CH_SETUP_MSC} + * @endmscs + * + * @param[in] conn_handle Connection Handle. + * @param[in,out] p_local_cid Pointer to a uint16_t containing Local Channel ID of the L2CAP channel: + * - As input: @ref BLE_L2CAP_CID_INVALID when requesting setup of an L2CAP + * channel or local_cid provided in the @ref BLE_L2CAP_EVT_CH_SETUP_REQUEST + * event when replying to a setup request of an L2CAP channel. + * - As output: local_cid for this channel. + * @param[in] p_params L2CAP channel parameters. + * + * @retval ::NRF_SUCCESS Successfully queued request or response for transmission. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_LENGTH Supplied higher rx_mps than has been configured on this link. + * @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (L2CAP channel already set up). + * @retval ::NRF_ERROR_NOT_FOUND CID not found. + * @retval ::NRF_ERROR_RESOURCES The limit has been reached for available L2CAP channels, + * see @ref ble_l2cap_conn_cfg_t::ch_count. + */ +SVCALL(SD_BLE_L2CAP_CH_SETUP, uint32_t, sd_ble_l2cap_ch_setup(uint16_t conn_handle, uint16_t *p_local_cid, ble_l2cap_ch_setup_params_t const *p_params)); + +/**@brief Release an L2CAP channel. + * + * @details This sends a Disconnection Request packet to a peer. + * + * @events + * @event{@ref BLE_L2CAP_EVT_CH_RELEASED, Release complete.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_L2CAP_CH_RELEASE_MSC} + * @endmscs + * + * @param[in] conn_handle Connection Handle. + * @param[in] local_cid Local Channel ID of the L2CAP channel. + * + * @retval ::NRF_SUCCESS Successfully queued request for transmission. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (Setup or release is + * in progress for the L2CAP channel). + * @retval ::NRF_ERROR_NOT_FOUND CID not found. + */ +SVCALL(SD_BLE_L2CAP_CH_RELEASE, uint32_t, sd_ble_l2cap_ch_release(uint16_t conn_handle, uint16_t local_cid)); + +/**@brief Receive an SDU on an L2CAP channel. + * + * @details This may issue additional credits to the peer using an LE Flow Control Credit packet. + * + * @note A call to this function will require the application to keep the memory pointed by + * @ref ble_data_t::p_data alive until the SDU data buffer is returned in @ref BLE_L2CAP_EVT_CH_RX + * or @ref BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED event. + * + * @note The SoftDevice can queue up to @ref ble_l2cap_conn_cfg_t::rx_queue_size SDU data buffers + * for reception per L2CAP channel. + * + * @events + * @event{@ref BLE_L2CAP_EVT_CH_RX, The SDU is received.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_L2CAP_CH_RX_MSC} + * @endmscs + * + * @param[in] conn_handle Connection Handle. + * @param[in] local_cid Local Channel ID of the L2CAP channel. + * @param[in] p_sdu_buf Pointer to the SDU data buffer. + * + * @retval ::NRF_SUCCESS Buffer accepted. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (Setup or release is + * in progress for an L2CAP channel). + * @retval ::NRF_ERROR_NOT_FOUND CID not found. + * @retval ::NRF_ERROR_RESOURCES Too many SDU data buffers supplied. Wait for a + * @ref BLE_L2CAP_EVT_CH_RX event and retry. + */ +SVCALL(SD_BLE_L2CAP_CH_RX, uint32_t, sd_ble_l2cap_ch_rx(uint16_t conn_handle, uint16_t local_cid, ble_data_t const *p_sdu_buf)); + +/**@brief Transmit an SDU on an L2CAP channel. + * + * @note A call to this function will require the application to keep the memory pointed by + * @ref ble_data_t::p_data alive until the SDU data buffer is returned in @ref BLE_L2CAP_EVT_CH_TX + * or @ref BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED event. + * + * @note The SoftDevice can queue up to @ref ble_l2cap_conn_cfg_t::tx_queue_size SDUs for + * transmission per L2CAP channel. + * + * @note The application can keep track of the available credits for transmission by following + * the procedure below: + * - Store initial credits given by the peer in a variable. + * (Initial credits are provided in a @ref BLE_L2CAP_EVT_CH_SETUP event.) + * - Decrement the variable, which stores the currently available credits, by + * ceiling((@ref ble_data_t::len + 2) / tx_mps) when a call to this function returns + * @ref NRF_SUCCESS. (tx_mps is provided in a @ref BLE_L2CAP_EVT_CH_SETUP event.) + * - Increment the variable, which stores the currently available credits, by additional + * credits given by the peer in a @ref BLE_L2CAP_EVT_CH_CREDIT event. + * + * @events + * @event{@ref BLE_L2CAP_EVT_CH_TX, The SDU is transmitted.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_L2CAP_CH_TX_MSC} + * @endmscs + * + * @param[in] conn_handle Connection Handle. + * @param[in] local_cid Local Channel ID of the L2CAP channel. + * @param[in] p_sdu_buf Pointer to the SDU data buffer. + * + * @retval ::NRF_SUCCESS Successfully queued L2CAP SDU for transmission. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (Setup or release is + * in progress for the L2CAP channel). + * @retval ::NRF_ERROR_NOT_FOUND CID not found. + * @retval ::NRF_ERROR_DATA_SIZE Invalid SDU length supplied, must not be more than + * @ref ble_l2cap_ch_tx_params_t::tx_mtu provided in + * @ref BLE_L2CAP_EVT_CH_SETUP event. + * @retval ::NRF_ERROR_RESOURCES Too many SDUs queued for transmission. Wait for a + * @ref BLE_L2CAP_EVT_CH_TX event and retry. + */ +SVCALL(SD_BLE_L2CAP_CH_TX, uint32_t, sd_ble_l2cap_ch_tx(uint16_t conn_handle, uint16_t local_cid, ble_data_t const *p_sdu_buf)); + +/**@brief Advanced SDU reception flow control. + * + * @details Adjust the way the SoftDevice issues credits to the peer. + * This may issue additional credits to the peer using an LE Flow Control Credit packet. + * + * @mscs + * @mmsc{@ref BLE_L2CAP_CH_FLOW_CONTROL_MSC} + * @endmscs + * + * @param[in] conn_handle Connection Handle. + * @param[in] local_cid Local Channel ID of the L2CAP channel or @ref BLE_L2CAP_CID_INVALID to set + * the value that will be used for newly created channels. + * @param[in] credits Number of credits that the SoftDevice will make sure the peer has every + * time it starts using a new reception buffer. + * - @ref BLE_L2CAP_CREDITS_DEFAULT is the default value the SoftDevice will + * use if this function is not called. + * - If set to zero, the SoftDevice will stop issuing credits for new reception + * buffers the application provides or has provided. SDU reception that is + * currently ongoing will be allowed to complete. + * @param[out] p_credits NULL or pointer to a uint16_t. If a valid pointer is provided, it will be + * written by the SoftDevice with the number of credits that is or will be + * available to the peer. If the value written by the SoftDevice is 0 when + * credits parameter was set to 0, the peer will not be able to send more + * data until more credits are provided by calling this function again with + * credits > 0. This parameter is ignored when local_cid is set to + * @ref BLE_L2CAP_CID_INVALID. + * + * @note Application should take care when setting number of credits higher than default value. In + * this case the application must make sure that the SoftDevice always has reception buffers + * available (see @ref sd_ble_l2cap_ch_rx) for that channel. If the SoftDevice does not have + * such buffers available, packets may be NACKed on the Link Layer and all Bluetooth traffic + * on the connection handle may be stalled until the SoftDevice again has an available + * reception buffer. This applies even if the application has used this call to set the + * credits back to default, or zero. + * + * @retval ::NRF_SUCCESS Flow control parameters accepted. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (Setup or release is + * in progress for an L2CAP channel). + * @retval ::NRF_ERROR_NOT_FOUND CID not found. + */ +SVCALL(SD_BLE_L2CAP_CH_FLOW_CONTROL, uint32_t, sd_ble_l2cap_ch_flow_control(uint16_t conn_handle, uint16_t local_cid, uint16_t credits, uint16_t *p_credits)); + +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif // BLE_L2CAP_H__ + +/** + @} +*/ diff --git a/components/softdevice/s140/headers/ble_ranges.h b/components/softdevice/s140/headers/ble_ranges.h new file mode 100644 index 0000000..0935bca --- /dev/null +++ b/components/softdevice/s140/headers/ble_ranges.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @addtogroup BLE_COMMON + @{ + @defgroup ble_ranges Module specific SVC, event and option number subranges + @{ + + @brief Definition of SVC, event and option number subranges for each API module. + + @note + SVCs, event and option numbers are split into subranges for each API module. + Each module receives its entire allocated range of SVC calls, whether implemented or not, + but return BLE_ERROR_NOT_SUPPORTED for unimplemented or undefined calls in its range. + + Note that the symbols BLE__SVC_LAST is the end of the allocated SVC range, + rather than the last SVC function call actually defined and implemented. + + Specific SVC, event and option values are defined in each module's ble_.h file, + which defines names of each individual SVC code based on the range start value. +*/ + +#ifndef BLE_RANGES_H__ +#define BLE_RANGES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_SVC_BASE 0x60 /**< Common BLE SVC base. */ +#define BLE_SVC_LAST 0x6B /**< Common BLE SVC last. */ + +#define BLE_GAP_SVC_BASE 0x6C /**< GAP BLE SVC base. */ +#define BLE_GAP_SVC_LAST 0x9A /**< GAP BLE SVC last. */ + +#define BLE_GATTC_SVC_BASE 0x9B /**< GATTC BLE SVC base. */ +#define BLE_GATTC_SVC_LAST 0xA7 /**< GATTC BLE SVC last. */ + +#define BLE_GATTS_SVC_BASE 0xA8 /**< GATTS BLE SVC base. */ +#define BLE_GATTS_SVC_LAST 0xB7 /**< GATTS BLE SVC last. */ + +#define BLE_L2CAP_SVC_BASE 0xB8 /**< L2CAP BLE SVC base. */ +#define BLE_L2CAP_SVC_LAST 0xBF /**< L2CAP BLE SVC last. */ + + +#define BLE_EVT_INVALID 0x00 /**< Invalid BLE Event. */ + +#define BLE_EVT_BASE 0x01 /**< Common BLE Event base. */ +#define BLE_EVT_LAST 0x0F /**< Common BLE Event last. */ + +#define BLE_GAP_EVT_BASE 0x10 /**< GAP BLE Event base. */ +#define BLE_GAP_EVT_LAST 0x2F /**< GAP BLE Event last. */ + +#define BLE_GATTC_EVT_BASE 0x30 /**< GATTC BLE Event base. */ +#define BLE_GATTC_EVT_LAST 0x4F /**< GATTC BLE Event last. */ + +#define BLE_GATTS_EVT_BASE 0x50 /**< GATTS BLE Event base. */ +#define BLE_GATTS_EVT_LAST 0x6F /**< GATTS BLE Event last. */ + +#define BLE_L2CAP_EVT_BASE 0x70 /**< L2CAP BLE Event base. */ +#define BLE_L2CAP_EVT_LAST 0x8F /**< L2CAP BLE Event last. */ + + +#define BLE_OPT_INVALID 0x00 /**< Invalid BLE Option. */ + +#define BLE_OPT_BASE 0x01 /**< Common BLE Option base. */ +#define BLE_OPT_LAST 0x1F /**< Common BLE Option last. */ + +#define BLE_GAP_OPT_BASE 0x20 /**< GAP BLE Option base. */ +#define BLE_GAP_OPT_LAST 0x3F /**< GAP BLE Option last. */ + +#define BLE_GATT_OPT_BASE 0x40 /**< GATT BLE Option base. */ +#define BLE_GATT_OPT_LAST 0x5F /**< GATT BLE Option last. */ + +#define BLE_GATTC_OPT_BASE 0x60 /**< GATTC BLE Option base. */ +#define BLE_GATTC_OPT_LAST 0x7F /**< GATTC BLE Option last. */ + +#define BLE_GATTS_OPT_BASE 0x80 /**< GATTS BLE Option base. */ +#define BLE_GATTS_OPT_LAST 0x9F /**< GATTS BLE Option last. */ + +#define BLE_L2CAP_OPT_BASE 0xA0 /**< L2CAP BLE Option base. */ +#define BLE_L2CAP_OPT_LAST 0xBF /**< L2CAP BLE Option last. */ + + +#define BLE_CFG_INVALID 0x00 /**< Invalid BLE configuration. */ + +#define BLE_CFG_BASE 0x01 /**< Common BLE configuration base. */ +#define BLE_CFG_LAST 0x1F /**< Common BLE configuration last. */ + +#define BLE_CONN_CFG_BASE 0x20 /**< BLE connection configuration base. */ +#define BLE_CONN_CFG_LAST 0x3F /**< BLE connection configuration last. */ + +#define BLE_GAP_CFG_BASE 0x40 /**< GAP BLE configuration base. */ +#define BLE_GAP_CFG_LAST 0x5F /**< GAP BLE configuration last. */ + +#define BLE_GATT_CFG_BASE 0x60 /**< GATT BLE configuration base. */ +#define BLE_GATT_CFG_LAST 0x7F /**< GATT BLE configuration last. */ + +#define BLE_GATTC_CFG_BASE 0x80 /**< GATTC BLE configuration base. */ +#define BLE_GATTC_CFG_LAST 0x9F /**< GATTC BLE configuration last. */ + +#define BLE_GATTS_CFG_BASE 0xA0 /**< GATTS BLE configuration base. */ +#define BLE_GATTS_CFG_LAST 0xBF /**< GATTS BLE configuration last. */ + +#define BLE_L2CAP_CFG_BASE 0xC0 /**< L2CAP BLE configuration base. */ +#define BLE_L2CAP_CFG_LAST 0xDF /**< L2CAP BLE configuration last. */ + + + + + +#ifdef __cplusplus +} +#endif +#endif /* BLE_RANGES_H__ */ + +/** + @} + @} +*/ diff --git a/components/softdevice/s140/headers/ble_types.h b/components/softdevice/s140/headers/ble_types.h new file mode 100644 index 0000000..88c9318 --- /dev/null +++ b/components/softdevice/s140/headers/ble_types.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @addtogroup BLE_COMMON + @{ + @defgroup ble_types Common types and macro definitions + @{ + + @brief Common types and macro definitions for the BLE SoftDevice. + */ + +#ifndef BLE_TYPES_H__ +#define BLE_TYPES_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup BLE_TYPES_DEFINES Defines + * @{ */ + +/** @defgroup BLE_CONN_HANDLES BLE Connection Handles + * @{ */ +#define BLE_CONN_HANDLE_INVALID 0xFFFF /**< Invalid Connection Handle. */ +#define BLE_CONN_HANDLE_ALL 0xFFFE /**< Applies to all Connection Handles. */ +/** @} */ + + +/** @defgroup BLE_UUID_VALUES Assigned Values for BLE UUIDs + * @{ */ +/* Generic UUIDs, applicable to all services */ +#define BLE_UUID_UNKNOWN 0x0000 /**< Reserved UUID. */ +#define BLE_UUID_SERVICE_PRIMARY 0x2800 /**< Primary Service. */ +#define BLE_UUID_SERVICE_SECONDARY 0x2801 /**< Secondary Service. */ +#define BLE_UUID_SERVICE_INCLUDE 0x2802 /**< Include. */ +#define BLE_UUID_CHARACTERISTIC 0x2803 /**< Characteristic. */ +#define BLE_UUID_DESCRIPTOR_CHAR_EXT_PROP 0x2900 /**< Characteristic Extended Properties Descriptor. */ +#define BLE_UUID_DESCRIPTOR_CHAR_USER_DESC 0x2901 /**< Characteristic User Description Descriptor. */ +#define BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG 0x2902 /**< Client Characteristic Configuration Descriptor. */ +#define BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG 0x2903 /**< Server Characteristic Configuration Descriptor. */ +#define BLE_UUID_DESCRIPTOR_CHAR_PRESENTATION_FORMAT 0x2904 /**< Characteristic Presentation Format Descriptor. */ +#define BLE_UUID_DESCRIPTOR_CHAR_AGGREGATE_FORMAT 0x2905 /**< Characteristic Aggregate Format Descriptor. */ +/* GATT specific UUIDs */ +#define BLE_UUID_GATT 0x1801 /**< Generic Attribute Profile. */ +#define BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED 0x2A05 /**< Service Changed Characteristic. */ +/* GAP specific UUIDs */ +#define BLE_UUID_GAP 0x1800 /**< Generic Access Profile. */ +#define BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME 0x2A00 /**< Device Name Characteristic. */ +#define BLE_UUID_GAP_CHARACTERISTIC_APPEARANCE 0x2A01 /**< Appearance Characteristic. */ +#define BLE_UUID_GAP_CHARACTERISTIC_RECONN_ADDR 0x2A03 /**< Reconnection Address Characteristic. */ +#define BLE_UUID_GAP_CHARACTERISTIC_PPCP 0x2A04 /**< Peripheral Preferred Connection Parameters Characteristic. */ +#define BLE_UUID_GAP_CHARACTERISTIC_CAR 0x2AA6 /**< Central Address Resolution Characteristic. */ +#define BLE_UUID_GAP_CHARACTERISTIC_RPA_ONLY 0x2AC9 /**< Resolvable Private Address Only Characteristic. */ +/** @} */ + + +/** @defgroup BLE_UUID_TYPES Types of UUID + * @{ */ +#define BLE_UUID_TYPE_UNKNOWN 0x00 /**< Invalid UUID type. */ +#define BLE_UUID_TYPE_BLE 0x01 /**< Bluetooth SIG UUID (16-bit). */ +#define BLE_UUID_TYPE_VENDOR_BEGIN 0x02 /**< Vendor UUID types start at this index (128-bit). */ +/** @} */ + + +/** @defgroup BLE_APPEARANCES Bluetooth Appearance values + * @note Retrieved from http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml + * @{ */ +#define BLE_APPEARANCE_UNKNOWN 0 /**< Unknown. */ +#define BLE_APPEARANCE_GENERIC_PHONE 64 /**< Generic Phone. */ +#define BLE_APPEARANCE_GENERIC_COMPUTER 128 /**< Generic Computer. */ +#define BLE_APPEARANCE_GENERIC_WATCH 192 /**< Generic Watch. */ +#define BLE_APPEARANCE_WATCH_SPORTS_WATCH 193 /**< Watch: Sports Watch. */ +#define BLE_APPEARANCE_GENERIC_CLOCK 256 /**< Generic Clock. */ +#define BLE_APPEARANCE_GENERIC_DISPLAY 320 /**< Generic Display. */ +#define BLE_APPEARANCE_GENERIC_REMOTE_CONTROL 384 /**< Generic Remote Control. */ +#define BLE_APPEARANCE_GENERIC_EYE_GLASSES 448 /**< Generic Eye-glasses. */ +#define BLE_APPEARANCE_GENERIC_TAG 512 /**< Generic Tag. */ +#define BLE_APPEARANCE_GENERIC_KEYRING 576 /**< Generic Keyring. */ +#define BLE_APPEARANCE_GENERIC_MEDIA_PLAYER 640 /**< Generic Media Player. */ +#define BLE_APPEARANCE_GENERIC_BARCODE_SCANNER 704 /**< Generic Barcode Scanner. */ +#define BLE_APPEARANCE_GENERIC_THERMOMETER 768 /**< Generic Thermometer. */ +#define BLE_APPEARANCE_THERMOMETER_EAR 769 /**< Thermometer: Ear. */ +#define BLE_APPEARANCE_GENERIC_HEART_RATE_SENSOR 832 /**< Generic Heart rate Sensor. */ +#define BLE_APPEARANCE_HEART_RATE_SENSOR_HEART_RATE_BELT 833 /**< Heart Rate Sensor: Heart Rate Belt. */ +#define BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE 896 /**< Generic Blood Pressure. */ +#define BLE_APPEARANCE_BLOOD_PRESSURE_ARM 897 /**< Blood Pressure: Arm. */ +#define BLE_APPEARANCE_BLOOD_PRESSURE_WRIST 898 /**< Blood Pressure: Wrist. */ +#define BLE_APPEARANCE_GENERIC_HID 960 /**< Human Interface Device (HID). */ +#define BLE_APPEARANCE_HID_KEYBOARD 961 /**< Keyboard (HID Subtype). */ +#define BLE_APPEARANCE_HID_MOUSE 962 /**< Mouse (HID Subtype). */ +#define BLE_APPEARANCE_HID_JOYSTICK 963 /**< Joystick (HID Subtype). */ +#define BLE_APPEARANCE_HID_GAMEPAD 964 /**< Gamepad (HID Subtype). */ +#define BLE_APPEARANCE_HID_DIGITIZERSUBTYPE 965 /**< Digitizer Tablet (HID Subtype). */ +#define BLE_APPEARANCE_HID_CARD_READER 966 /**< Card Reader (HID Subtype). */ +#define BLE_APPEARANCE_HID_DIGITAL_PEN 967 /**< Digital Pen (HID Subtype). */ +#define BLE_APPEARANCE_HID_BARCODE 968 /**< Barcode Scanner (HID Subtype). */ +#define BLE_APPEARANCE_GENERIC_GLUCOSE_METER 1024 /**< Generic Glucose Meter. */ +#define BLE_APPEARANCE_GENERIC_RUNNING_WALKING_SENSOR 1088 /**< Generic Running Walking Sensor. */ +#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_IN_SHOE 1089 /**< Running Walking Sensor: In-Shoe. */ +#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_SHOE 1090 /**< Running Walking Sensor: On-Shoe. */ +#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_HIP 1091 /**< Running Walking Sensor: On-Hip. */ +#define BLE_APPEARANCE_GENERIC_CYCLING 1152 /**< Generic Cycling. */ +#define BLE_APPEARANCE_CYCLING_CYCLING_COMPUTER 1153 /**< Cycling: Cycling Computer. */ +#define BLE_APPEARANCE_CYCLING_SPEED_SENSOR 1154 /**< Cycling: Speed Sensor. */ +#define BLE_APPEARANCE_CYCLING_CADENCE_SENSOR 1155 /**< Cycling: Cadence Sensor. */ +#define BLE_APPEARANCE_CYCLING_POWER_SENSOR 1156 /**< Cycling: Power Sensor. */ +#define BLE_APPEARANCE_CYCLING_SPEED_CADENCE_SENSOR 1157 /**< Cycling: Speed and Cadence Sensor. */ +#define BLE_APPEARANCE_GENERIC_PULSE_OXIMETER 3136 /**< Generic Pulse Oximeter. */ +#define BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP 3137 /**< Fingertip (Pulse Oximeter subtype). */ +#define BLE_APPEARANCE_PULSE_OXIMETER_WRIST_WORN 3138 /**< Wrist Worn(Pulse Oximeter subtype). */ +#define BLE_APPEARANCE_GENERIC_WEIGHT_SCALE 3200 /**< Generic Weight Scale. */ +#define BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS_ACT 5184 /**< Generic Outdoor Sports Activity. */ +#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_DISP 5185 /**< Location Display Device (Outdoor Sports Activity subtype). */ +#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_DISP 5186 /**< Location and Navigation Display Device (Outdoor Sports Activity subtype). */ +#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_POD 5187 /**< Location Pod (Outdoor Sports Activity subtype). */ +#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_POD 5188 /**< Location and Navigation Pod (Outdoor Sports Activity subtype). */ +/** @} */ + +/** @brief Set .type and .uuid fields of ble_uuid_struct to specified UUID value. */ +#define BLE_UUID_BLE_ASSIGN(instance, value) do {\ + instance.type = BLE_UUID_TYPE_BLE; \ + instance.uuid = value;} while(0) + +/** @brief Copy type and uuid members from src to dst ble_uuid_t pointer. Both pointers must be valid/non-null. */ +#define BLE_UUID_COPY_PTR(dst, src) do {\ + (dst)->type = (src)->type; \ + (dst)->uuid = (src)->uuid;} while(0) + +/** @brief Copy type and uuid members from src to dst ble_uuid_t struct. */ +#define BLE_UUID_COPY_INST(dst, src) do {\ + (dst).type = (src).type; \ + (dst).uuid = (src).uuid;} while(0) + +/** @brief Compare for equality both type and uuid members of two (valid, non-null) ble_uuid_t pointers. */ +#define BLE_UUID_EQ(p_uuid1, p_uuid2) \ + (((p_uuid1)->type == (p_uuid2)->type) && ((p_uuid1)->uuid == (p_uuid2)->uuid)) + +/** @brief Compare for difference both type and uuid members of two (valid, non-null) ble_uuid_t pointers. */ +#define BLE_UUID_NEQ(p_uuid1, p_uuid2) \ + (((p_uuid1)->type != (p_uuid2)->type) || ((p_uuid1)->uuid != (p_uuid2)->uuid)) + +/** @} */ + +/** @addtogroup BLE_TYPES_STRUCTURES Structures + * @{ */ + +/** @brief 128 bit UUID values. */ +typedef struct +{ + uint8_t uuid128[16]; /**< Little-Endian UUID bytes. */ +} ble_uuid128_t; + +/** @brief Bluetooth Low Energy UUID type, encapsulates both 16-bit and 128-bit UUIDs. */ +typedef struct +{ + uint16_t uuid; /**< 16-bit UUID value or octets 12-13 of 128-bit UUID. */ + uint8_t type; /**< UUID type, see @ref BLE_UUID_TYPES. If type is @ref BLE_UUID_TYPE_UNKNOWN, the value of uuid is undefined. */ +} ble_uuid_t; + +/**@brief Data structure. */ +typedef struct +{ + uint8_t *p_data; /**< Pointer to the data buffer provided to/from the application. */ + uint16_t len; /**< Length of the data buffer, in bytes. */ +} ble_data_t; + +/** @} */ +#ifdef __cplusplus +} +#endif + +#endif /* BLE_TYPES_H__ */ + +/** + @} + @} +*/ diff --git a/components/softdevice/s140/headers/nrf52/nrf_mbr.h b/components/softdevice/s140/headers/nrf52/nrf_mbr.h new file mode 100644 index 0000000..42e09fc --- /dev/null +++ b/components/softdevice/s140/headers/nrf52/nrf_mbr.h @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2014 - 2017, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @defgroup nrf_mbr_api Master Boot Record API + @{ + + @brief APIs for updating SoftDevice and BootLoader + +*/ + +#ifndef NRF_MBR_H__ +#define NRF_MBR_H__ + +#include "nrf_svc.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup NRF_MBR_DEFINES Defines + * @{ */ + +/**@brief MBR SVC Base number. */ +#define MBR_SVC_BASE (0x18) + +/**@brief Page size in words. */ +#define MBR_PAGE_SIZE_IN_WORDS (1024) + +/** @brief The size that must be reserved for the MBR when a SoftDevice is written to flash. +This is the offset where the first byte of the SoftDevice hex file is written. */ +#define MBR_SIZE (0x1000) + +/** @brief Location (in the flash memory) of the bootloader address. */ +#define MBR_BOOTLOADER_ADDR (0xFF8) + +/** @brief Location (in UICR) of the bootloader address. */ +#define MBR_UICR_BOOTLOADER_ADDR (&(NRF_UICR->NRFFW[0])) + +/** @brief Location (in the flash memory) of the address of the MBR parameter page. */ +#define MBR_PARAM_PAGE_ADDR (0xFFC) + +/** @brief Location (in UICR) of the address of the MBR parameter page. */ +#define MBR_UICR_PARAM_PAGE_ADDR (&(NRF_UICR->NRFFW[1])) + + +/** @} */ + +/** @addtogroup NRF_MBR_ENUMS Enumerations + * @{ */ + +/**@brief nRF Master Boot Record API SVC numbers. */ +enum NRF_MBR_SVCS +{ + SD_MBR_COMMAND = MBR_SVC_BASE, /**< ::sd_mbr_command */ +}; + +/**@brief Possible values for ::sd_mbr_command_t.command */ +enum NRF_MBR_COMMANDS +{ + SD_MBR_COMMAND_COPY_BL, /**< Copy a new BootLoader. @see ::sd_mbr_command_copy_bl_t*/ + SD_MBR_COMMAND_COPY_SD, /**< Copy a new SoftDevice. @see ::sd_mbr_command_copy_sd_t*/ + SD_MBR_COMMAND_INIT_SD, /**< Initialize forwarding interrupts to SD, and run reset function in SD. Does not require any parameters in ::sd_mbr_command_t params.*/ + SD_MBR_COMMAND_COMPARE, /**< This command works like memcmp. @see ::sd_mbr_command_compare_t*/ + SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET, /**< Change the address the MBR starts after a reset. @see ::sd_mbr_command_vector_table_base_set_t*/ + SD_MBR_COMMAND_RESERVED, + SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, /**< Start forwarding all interrupts to this address. @see ::sd_mbr_command_irq_forward_address_set_t*/ +}; + +/** @} */ + +/** @addtogroup NRF_MBR_TYPES Types + * @{ */ + +/**@brief This command copies part of a new SoftDevice + * + * The destination area is erased before copying. + * If dst is in the middle of a flash page, that whole flash page will be erased. + * If (dst+len) is in the middle of a flash page, that whole flash page will be erased. + * + * The user of this function is responsible for setting the BPROT registers. + * + * @retval ::NRF_SUCCESS indicates that the contents of the memory blocks where copied correctly. + * @retval ::NRF_ERROR_INTERNAL indicates that the contents of the memory blocks where not verified correctly after copying. + */ +typedef struct +{ + uint32_t *src; /**< Pointer to the source of data to be copied.*/ + uint32_t *dst; /**< Pointer to the destination where the content is to be copied.*/ + uint32_t len; /**< Number of 32 bit words to copy. Must be a multiple of @ref MBR_PAGE_SIZE_IN_WORDS words.*/ +} sd_mbr_command_copy_sd_t; + + +/**@brief This command works like memcmp, but takes the length in words. + * + * @retval ::NRF_SUCCESS indicates that the contents of both memory blocks are equal. + * @retval ::NRF_ERROR_NULL indicates that the contents of the memory blocks are not equal. + */ +typedef struct +{ + uint32_t *ptr1; /**< Pointer to block of memory. */ + uint32_t *ptr2; /**< Pointer to block of memory. */ + uint32_t len; /**< Number of 32 bit words to compare.*/ +} sd_mbr_command_compare_t; + + +/**@brief This command copies a new BootLoader. + * + * The MBR assumes that either @ref MBR_BOOTLOADER_ADDR or @ref MBR_UICR_BOOTLOADER_ADDR is set to + * the address where the bootloader will be copied. If both addresses are set, the MBR will prioritize + * @ref MBR_BOOTLOADER_ADDR. + * + * The bootloader destination is erased by this function. + * If (destination+bl_len) is in the middle of a flash page, that whole flash page will be erased. + * + * This command requires that @ref MBR_PARAM_PAGE_ADDR or @ref MBR_UICR_PARAM_PAGE_ADDR is set, + * see @ref sd_mbr_command. + * + * This command will use the flash protect peripheral (BPROT or ACL) to protect the flash that is + * not intended to be written. + * + * On success, this function will not return. It will start the new bootloader from reset-vector as normal. + * + * @retval ::NRF_ERROR_INTERNAL indicates an internal error that should not happen. + * @retval ::NRF_ERROR_FORBIDDEN if the bootloader address is not set. + * @retval ::NRF_ERROR_INVALID_LENGTH if parameters attempts to read or write outside flash area. + * @retval ::NRF_ERROR_NO_MEM No MBR parameter page is provided. See @ref sd_mbr_command. + */ +typedef struct +{ + uint32_t *bl_src; /**< Pointer to the source of the bootloader to be be copied.*/ + uint32_t bl_len; /**< Number of 32 bit words to copy for BootLoader. */ +} sd_mbr_command_copy_bl_t; + +/**@brief Change the address the MBR starts after a reset + * + * Once this function has been called, this address is where the MBR will start to forward + * interrupts to after a reset. + * + * To restore default forwarding, this function should be called with @ref address set to 0. If a + * bootloader is present, interrupts will be forwarded to the bootloader. If not, interrupts will + * be forwarded to the SoftDevice. + * + * The location of a bootloader can be specified in @ref MBR_BOOTLOADER_ADDR or + * @ref MBR_UICR_BOOTLOADER_ADDR. If both addresses are set, the MBR will prioritize + * @ref MBR_BOOTLOADER_ADDR. + * + * This command requires that @ref MBR_PARAM_PAGE_ADDR or @ref MBR_UICR_PARAM_PAGE_ADDR is set, + * see @ref sd_mbr_command. + * + * On success, this function will not return. It will reset the device. + * + * @retval ::NRF_ERROR_INTERNAL indicates an internal error that should not happen. + * @retval ::NRF_ERROR_INVALID_ADDR if parameter address is outside of the flash size. + * @retval ::NRF_ERROR_NO_MEM No MBR parameter page is provided. See @ref sd_mbr_command. + */ +typedef struct +{ + uint32_t address; /**< The base address of the interrupt vector table for forwarded interrupts.*/ +} sd_mbr_command_vector_table_base_set_t; + +/**@brief Sets the base address of the interrupt vector table for interrupts forwarded from the MBR + * + * Unlike sd_mbr_command_vector_table_base_set_t, this function does not reset, and it does not + * change where the MBR starts after reset. + * + * @retval ::NRF_SUCCESS + */ +typedef struct +{ + uint32_t address; /**< The base address of the interrupt vector table for forwarded interrupts.*/ +} sd_mbr_command_irq_forward_address_set_t; + +/**@brief Input structure containing data used when calling ::sd_mbr_command + * + * Depending on what command value that is set, the corresponding params value type must also be + * set. See @ref NRF_MBR_COMMANDS for command types and corresponding params value type. If command + * @ref SD_MBR_COMMAND_INIT_SD is set, it is not necessary to set any values under params. + */ +typedef struct +{ + uint32_t command; /**< Type of command to be issued. See @ref NRF_MBR_COMMANDS. */ + union + { + sd_mbr_command_copy_sd_t copy_sd; /**< Parameters for copy SoftDevice.*/ + sd_mbr_command_compare_t compare; /**< Parameters for verify.*/ + sd_mbr_command_copy_bl_t copy_bl; /**< Parameters for copy BootLoader. Requires parameter page. */ + sd_mbr_command_vector_table_base_set_t base_set; /**< Parameters for vector table base set. Requires parameter page.*/ + sd_mbr_command_irq_forward_address_set_t irq_forward_address_set; /**< Parameters for irq forward address set*/ + } params; /**< Command parameters. */ +} sd_mbr_command_t; + +/** @} */ + +/** @addtogroup NRF_MBR_FUNCTIONS Functions + * @{ */ + +/**@brief Issue Master Boot Record commands + * + * Commands used when updating a SoftDevice and bootloader. + * + * The @ref SD_MBR_COMMAND_COPY_BL and @ref SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET requires + * parameters to be retained by the MBR when resetting the IC. This is done in a separate flash + * page. The location of the flash page should be provided by the application in either + * @ref MBR_PARAM_PAGE_ADDR or @ref MBR_UICR_PARAM_PAGE_ADDR. If both addresses are set, the MBR + * will prioritize @ref MBR_PARAM_PAGE_ADDR. This page will be cleared by the MBR and is used to + * store the command before reset. When an address is specified, the page it refers to must not be + * used by the application. If no address is provided by the application, i.e. both + * @ref MBR_PARAM_PAGE_ADDR and @ref MBR_UICR_PARAM_PAGE_ADDR is 0xFFFFFFFF, MBR commands which use + * flash will be unavailable and return @ref NRF_ERROR_NO_MEM. + * + * @param[in] param Pointer to a struct describing the command. + * + * @note For a complete set of return values, see ::sd_mbr_command_copy_sd_t, + * ::sd_mbr_command_copy_bl_t, ::sd_mbr_command_compare_t, + * ::sd_mbr_command_vector_table_base_set_t, ::sd_mbr_command_irq_forward_address_set_t + * + * @retval ::NRF_ERROR_NO_MEM No MBR parameter page provided + * @retval ::NRF_ERROR_INVALID_PARAM if an invalid command is given. +*/ +SVCALL(SD_MBR_COMMAND, uint32_t, sd_mbr_command(sd_mbr_command_t* param)); + +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif // NRF_MBR_H__ + +/** + @} +*/ diff --git a/components/softdevice/s140/headers/nrf_error.h b/components/softdevice/s140/headers/nrf_error.h new file mode 100644 index 0000000..6badee9 --- /dev/null +++ b/components/softdevice/s140/headers/nrf_error.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014 - 2017, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + /** + @defgroup nrf_error SoftDevice Global Error Codes + @{ + + @brief Global Error definitions +*/ + +/* Header guard */ +#ifndef NRF_ERROR_H__ +#define NRF_ERROR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup NRF_ERRORS_BASE Error Codes Base number definitions + * @{ */ +#define NRF_ERROR_BASE_NUM (0x0) ///< Global error base +#define NRF_ERROR_SDM_BASE_NUM (0x1000) ///< SDM error base +#define NRF_ERROR_SOC_BASE_NUM (0x2000) ///< SoC error base +#define NRF_ERROR_STK_BASE_NUM (0x3000) ///< STK error base +/** @} */ + +#define NRF_SUCCESS (NRF_ERROR_BASE_NUM + 0) ///< Successful command +#define NRF_ERROR_SVC_HANDLER_MISSING (NRF_ERROR_BASE_NUM + 1) ///< SVC handler is missing +#define NRF_ERROR_SOFTDEVICE_NOT_ENABLED (NRF_ERROR_BASE_NUM + 2) ///< SoftDevice has not been enabled +#define NRF_ERROR_INTERNAL (NRF_ERROR_BASE_NUM + 3) ///< Internal Error +#define NRF_ERROR_NO_MEM (NRF_ERROR_BASE_NUM + 4) ///< No Memory for operation +#define NRF_ERROR_NOT_FOUND (NRF_ERROR_BASE_NUM + 5) ///< Not found +#define NRF_ERROR_NOT_SUPPORTED (NRF_ERROR_BASE_NUM + 6) ///< Not supported +#define NRF_ERROR_INVALID_PARAM (NRF_ERROR_BASE_NUM + 7) ///< Invalid Parameter +#define NRF_ERROR_INVALID_STATE (NRF_ERROR_BASE_NUM + 8) ///< Invalid state, operation disallowed in this state +#define NRF_ERROR_INVALID_LENGTH (NRF_ERROR_BASE_NUM + 9) ///< Invalid Length +#define NRF_ERROR_INVALID_FLAGS (NRF_ERROR_BASE_NUM + 10) ///< Invalid Flags +#define NRF_ERROR_INVALID_DATA (NRF_ERROR_BASE_NUM + 11) ///< Invalid Data +#define NRF_ERROR_DATA_SIZE (NRF_ERROR_BASE_NUM + 12) ///< Invalid Data size +#define NRF_ERROR_TIMEOUT (NRF_ERROR_BASE_NUM + 13) ///< Operation timed out +#define NRF_ERROR_NULL (NRF_ERROR_BASE_NUM + 14) ///< Null Pointer +#define NRF_ERROR_FORBIDDEN (NRF_ERROR_BASE_NUM + 15) ///< Forbidden Operation +#define NRF_ERROR_INVALID_ADDR (NRF_ERROR_BASE_NUM + 16) ///< Bad Memory Address +#define NRF_ERROR_BUSY (NRF_ERROR_BASE_NUM + 17) ///< Busy +#define NRF_ERROR_CONN_COUNT (NRF_ERROR_BASE_NUM + 18) ///< Maximum connection count exceeded. +#define NRF_ERROR_RESOURCES (NRF_ERROR_BASE_NUM + 19) ///< Not enough resources for operation + +#ifdef __cplusplus +} +#endif +#endif // NRF_ERROR_H__ + +/** + @} +*/ diff --git a/components/softdevice/s140/headers/nrf_error_sdm.h b/components/softdevice/s140/headers/nrf_error_sdm.h new file mode 100644 index 0000000..530959b --- /dev/null +++ b/components/softdevice/s140/headers/nrf_error_sdm.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + /** + @addtogroup nrf_sdm_api + @{ + @defgroup nrf_sdm_error SoftDevice Manager Error Codes + @{ + + @brief Error definitions for the SDM API +*/ + +/* Header guard */ +#ifndef NRF_ERROR_SDM_H__ +#define NRF_ERROR_SDM_H__ + +#include "nrf_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_ERROR_SDM_LFCLK_SOURCE_UNKNOWN (NRF_ERROR_SDM_BASE_NUM + 0) ///< Unknown LFCLK source. +#define NRF_ERROR_SDM_INCORRECT_INTERRUPT_CONFIGURATION (NRF_ERROR_SDM_BASE_NUM + 1) ///< Incorrect interrupt configuration (can be caused by using illegal priority levels, or having enabled SoftDevice interrupts). +#define NRF_ERROR_SDM_INCORRECT_CLENR0 (NRF_ERROR_SDM_BASE_NUM + 2) ///< Incorrect CLENR0 (can be caused by erroneous SoftDevice flashing). + +#ifdef __cplusplus +} +#endif +#endif // NRF_ERROR_SDM_H__ + +/** + @} + @} +*/ diff --git a/components/softdevice/s140/headers/nrf_error_soc.h b/components/softdevice/s140/headers/nrf_error_soc.h new file mode 100644 index 0000000..1e784b8 --- /dev/null +++ b/components/softdevice/s140/headers/nrf_error_soc.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @addtogroup nrf_soc_api + @{ + @defgroup nrf_soc_error SoC Library Error Codes + @{ + + @brief Error definitions for the SoC library + +*/ + +/* Header guard */ +#ifndef NRF_ERROR_SOC_H__ +#define NRF_ERROR_SOC_H__ + +#include "nrf_error.h" +#ifdef __cplusplus +extern "C" { +#endif + +/* Mutex Errors */ +#define NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN (NRF_ERROR_SOC_BASE_NUM + 0) ///< Mutex already taken + +/* NVIC errors */ +#define NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE (NRF_ERROR_SOC_BASE_NUM + 1) ///< NVIC interrupt not available +#define NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED (NRF_ERROR_SOC_BASE_NUM + 2) ///< NVIC interrupt priority not allowed +#define NRF_ERROR_SOC_NVIC_SHOULD_NOT_RETURN (NRF_ERROR_SOC_BASE_NUM + 3) ///< NVIC should not return + +/* Power errors */ +#define NRF_ERROR_SOC_POWER_MODE_UNKNOWN (NRF_ERROR_SOC_BASE_NUM + 4) ///< Power mode unknown +#define NRF_ERROR_SOC_POWER_POF_THRESHOLD_UNKNOWN (NRF_ERROR_SOC_BASE_NUM + 5) ///< Power POF threshold unknown +#define NRF_ERROR_SOC_POWER_OFF_SHOULD_NOT_RETURN (NRF_ERROR_SOC_BASE_NUM + 6) ///< Power off should not return + +/* Rand errors */ +#define NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES (NRF_ERROR_SOC_BASE_NUM + 7) ///< RAND not enough values + +/* PPI errors */ +#define NRF_ERROR_SOC_PPI_INVALID_CHANNEL (NRF_ERROR_SOC_BASE_NUM + 8) ///< Invalid PPI Channel +#define NRF_ERROR_SOC_PPI_INVALID_GROUP (NRF_ERROR_SOC_BASE_NUM + 9) ///< Invalid PPI Group + +#ifdef __cplusplus +} +#endif +#endif // NRF_ERROR_SOC_H__ +/** + @} + @} +*/ diff --git a/components/softdevice/s140/headers/nrf_nvic.h b/components/softdevice/s140/headers/nrf_nvic.h new file mode 100644 index 0000000..1f79cc3 --- /dev/null +++ b/components/softdevice/s140/headers/nrf_nvic.h @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @defgroup nrf_nvic_api SoftDevice NVIC API + * @{ + * + * @note In order to use this module, the following code has to be added to a .c file: + * \code + * nrf_nvic_state_t nrf_nvic_state = {0}; + * \endcode + * + * @note Definitions and declarations starting with __ (double underscore) in this header file are + * not intended for direct use by the application. + * + * @brief APIs for the accessing NVIC when using a SoftDevice. + * + */ + +#ifndef NRF_NVIC_H__ +#define NRF_NVIC_H__ + +#include +#include "nrf.h" +#include "nrf_svc.h" +#include "nrf_error.h" +#include "nrf_error_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@addtogroup NRF_NVIC_DEFINES Defines + * @{ */ + +/**@defgroup NRF_NVIC_ISER_DEFINES SoftDevice NVIC internal definitions + * @{ */ + +#define __NRF_NVIC_NVMC_IRQn (30) /**< The peripheral ID of the NVMC. IRQ numbers are used to identify peripherals, but the NVMC doesn't have an IRQ number in the MDK. */ + +#define __NRF_NVIC_ISER_COUNT (2) /**< The number of ISER/ICER registers in the NVIC that are used. */ + +/**@brief Interrupt priority levels used by the SoftDevice. */ +#define __NRF_NVIC_SD_IRQ_PRIOS ((uint8_t)( \ + (1U << 0) /**< Priority level high .*/ \ + | (1U << 1) /**< Priority level medium. */ \ + | (1U << 4) /**< Priority level low. */ \ + )) + +/**@brief Interrupt priority levels available to the application. */ +#define __NRF_NVIC_APP_IRQ_PRIOS ((uint8_t)~__NRF_NVIC_SD_IRQ_PRIOS) + +/**@brief Interrupts used by the SoftDevice, with IRQn in the range 0-31. */ +#define __NRF_NVIC_SD_IRQS_0 ((uint32_t)( \ + (1U << POWER_CLOCK_IRQn) \ + | (1U << RADIO_IRQn) \ + | (1U << RTC0_IRQn) \ + | (1U << TIMER0_IRQn) \ + | (1U << RNG_IRQn) \ + | (1U << ECB_IRQn) \ + | (1U << CCM_AAR_IRQn) \ + | (1U << TEMP_IRQn) \ + | (1U << __NRF_NVIC_NVMC_IRQn) \ + | (1U << (uint32_t)SWI5_IRQn) \ + )) + +/**@brief Interrupts used by the SoftDevice, with IRQn in the range 32-63. */ +#define __NRF_NVIC_SD_IRQS_1 ((uint32_t)0) + +/**@brief Interrupts available for to application, with IRQn in the range 0-31. */ +#define __NRF_NVIC_APP_IRQS_0 (~__NRF_NVIC_SD_IRQS_0) + +/**@brief Interrupts available for to application, with IRQn in the range 32-63. */ +#define __NRF_NVIC_APP_IRQS_1 (~__NRF_NVIC_SD_IRQS_1) + +/**@} */ + +/**@} */ + +/**@addtogroup NRF_NVIC_VARIABLES Variables + * @{ */ + +/**@brief Type representing the state struct for the SoftDevice NVIC module. */ +typedef struct +{ + uint32_t volatile __irq_masks[__NRF_NVIC_ISER_COUNT]; /**< IRQs enabled by the application in the NVIC. */ + uint32_t volatile __cr_flag; /**< Non-zero if already in a critical region */ +} nrf_nvic_state_t; + +/**@brief Variable keeping the state for the SoftDevice NVIC module. This must be declared in an + * application source file. */ +extern nrf_nvic_state_t nrf_nvic_state; + +/**@} */ + +/**@addtogroup NRF_NVIC_INTERNAL_FUNCTIONS SoftDevice NVIC internal functions + * @{ */ + +/**@brief Disables IRQ interrupts globally, including the SoftDevice's interrupts. + * + * @retval The value of PRIMASK prior to disabling the interrupts. + */ +__STATIC_INLINE int __sd_nvic_irq_disable(void); + +/**@brief Enables IRQ interrupts globally, including the SoftDevice's interrupts. + */ +__STATIC_INLINE void __sd_nvic_irq_enable(void); + +/**@brief Checks if IRQn is available to application + * @param[in] IRQn IRQ to check + * + * @retval 1 (true) if the IRQ to check is available to the application + */ +__STATIC_INLINE uint32_t __sd_nvic_app_accessible_irq(IRQn_Type IRQn); + +/**@brief Checks if priority is available to application + * @param[in] priority priority to check + * + * @retval 1 (true) if the priority to check is available to the application + */ +__STATIC_INLINE uint32_t __sd_nvic_is_app_accessible_priority(uint32_t priority); + +/**@} */ + +/**@addtogroup NRF_NVIC_FUNCTIONS SoftDevice NVIC public functions + * @{ */ + +/**@brief Enable External Interrupt. + * @note Corresponds to NVIC_EnableIRQ in CMSIS. + * + * @pre IRQn is valid and not reserved by the stack. + * + * @param[in] IRQn See the NVIC_EnableIRQ documentation in CMSIS. + * + * @retval ::NRF_SUCCESS The interrupt was enabled. + * @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE The interrupt is not available for the application. + * @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED The interrupt has a priority not available for the application. + */ +__STATIC_INLINE uint32_t sd_nvic_EnableIRQ(IRQn_Type IRQn); + +/**@brief Disable External Interrupt. + * @note Corresponds to NVIC_DisableIRQ in CMSIS. + * + * @pre IRQn is valid and not reserved by the stack. + * + * @param[in] IRQn See the NVIC_DisableIRQ documentation in CMSIS. + * + * @retval ::NRF_SUCCESS The interrupt was disabled. + * @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE The interrupt is not available for the application. + */ +__STATIC_INLINE uint32_t sd_nvic_DisableIRQ(IRQn_Type IRQn); + +/**@brief Get Pending Interrupt. + * @note Corresponds to NVIC_GetPendingIRQ in CMSIS. + * + * @pre IRQn is valid and not reserved by the stack. + * + * @param[in] IRQn See the NVIC_GetPendingIRQ documentation in CMSIS. + * @param[out] p_pending_irq Return value from NVIC_GetPendingIRQ. + * + * @retval ::NRF_SUCCESS The interrupt is available for the application. + * @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE IRQn is not available for the application. + */ +__STATIC_INLINE uint32_t sd_nvic_GetPendingIRQ(IRQn_Type IRQn, uint32_t * p_pending_irq); + +/**@brief Set Pending Interrupt. + * @note Corresponds to NVIC_SetPendingIRQ in CMSIS. + * + * @pre IRQn is valid and not reserved by the stack. + * + * @param[in] IRQn See the NVIC_SetPendingIRQ documentation in CMSIS. + * + * @retval ::NRF_SUCCESS The interrupt is set pending. + * @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE IRQn is not available for the application. + */ +__STATIC_INLINE uint32_t sd_nvic_SetPendingIRQ(IRQn_Type IRQn); + +/**@brief Clear Pending Interrupt. + * @note Corresponds to NVIC_ClearPendingIRQ in CMSIS. + * + * @pre IRQn is valid and not reserved by the stack. + * + * @param[in] IRQn See the NVIC_ClearPendingIRQ documentation in CMSIS. + * + * @retval ::NRF_SUCCESS The interrupt pending flag is cleared. + * @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE IRQn is not available for the application. + */ +__STATIC_INLINE uint32_t sd_nvic_ClearPendingIRQ(IRQn_Type IRQn); + +/**@brief Set Interrupt Priority. + * @note Corresponds to NVIC_SetPriority in CMSIS. + * + * @pre IRQn is valid and not reserved by the stack. + * @pre Priority is valid and not reserved by the stack. + * + * @param[in] IRQn See the NVIC_SetPriority documentation in CMSIS. + * @param[in] priority A valid IRQ priority for use by the application. + * + * @retval ::NRF_SUCCESS The interrupt and priority level is available for the application. + * @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE IRQn is not available for the application. + * @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED The interrupt priority is not available for the application. + */ +__STATIC_INLINE uint32_t sd_nvic_SetPriority(IRQn_Type IRQn, uint32_t priority); + +/**@brief Get Interrupt Priority. + * @note Corresponds to NVIC_GetPriority in CMSIS. + * + * @pre IRQn is valid and not reserved by the stack. + * + * @param[in] IRQn See the NVIC_GetPriority documentation in CMSIS. + * @param[out] p_priority Return value from NVIC_GetPriority. + * + * @retval ::NRF_SUCCESS The interrupt priority is returned in p_priority. + * @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE - IRQn is not available for the application. + */ +__STATIC_INLINE uint32_t sd_nvic_GetPriority(IRQn_Type IRQn, uint32_t * p_priority); + +/**@brief System Reset. + * @note Corresponds to NVIC_SystemReset in CMSIS. + * + * @retval ::NRF_ERROR_SOC_NVIC_SHOULD_NOT_RETURN + */ +__STATIC_INLINE uint32_t sd_nvic_SystemReset(void); + +/**@brief Enter critical region. + * + * @post Application interrupts will be disabled. + * @note sd_nvic_critical_region_enter() and ::sd_nvic_critical_region_exit() must be called in matching pairs inside each + * execution context + * @sa sd_nvic_critical_region_exit + * + * @param[out] p_is_nested_critical_region If 1, the application is now in a nested critical region. + * + * @retval ::NRF_SUCCESS + */ +__STATIC_INLINE uint32_t sd_nvic_critical_region_enter(uint8_t * p_is_nested_critical_region); + +/**@brief Exit critical region. + * + * @pre Application has entered a critical region using ::sd_nvic_critical_region_enter. + * @post If not in a nested critical region, the application interrupts will restored to the state before ::sd_nvic_critical_region_enter was called. + * + * @param[in] is_nested_critical_region If this is set to 1, the critical region won't be exited. @sa sd_nvic_critical_region_enter. + * + * @retval ::NRF_SUCCESS + */ +__STATIC_INLINE uint32_t sd_nvic_critical_region_exit(uint8_t is_nested_critical_region); + +/**@} */ + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE int __sd_nvic_irq_disable(void) +{ + int pm = __get_PRIMASK(); + __disable_irq(); + return pm; +} + +__STATIC_INLINE void __sd_nvic_irq_enable(void) +{ + __enable_irq(); +} + +__STATIC_INLINE uint32_t __sd_nvic_app_accessible_irq(IRQn_Type IRQn) +{ + if (IRQn < 32) + { + return ((1UL<= (1 << __NVIC_PRIO_BITS)) + || (((1 << priority) & __NRF_NVIC_APP_IRQ_PRIOS) == 0) + ) + { + return 0; + } + return 1; +} + + +__STATIC_INLINE uint32_t sd_nvic_EnableIRQ(IRQn_Type IRQn) +{ + if (!__sd_nvic_app_accessible_irq(IRQn)) + { + return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE; + } + if (!__sd_nvic_is_app_accessible_priority(NVIC_GetPriority(IRQn))) + { + return NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED; + } + + if (nrf_nvic_state.__cr_flag) + { + nrf_nvic_state.__irq_masks[(uint32_t)((int32_t)IRQn) >> 5] |= (uint32_t)(1 << ((uint32_t)((int32_t)IRQn) & (uint32_t)0x1F)); + } + else + { + NVIC_EnableIRQ(IRQn); + } + return NRF_SUCCESS; +} + +__STATIC_INLINE uint32_t sd_nvic_DisableIRQ(IRQn_Type IRQn) +{ + if (!__sd_nvic_app_accessible_irq(IRQn)) + { + return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE; + } + + if (nrf_nvic_state.__cr_flag) + { + nrf_nvic_state.__irq_masks[(uint32_t)((int32_t)IRQn) >> 5] &= ~(1UL << ((uint32_t)(IRQn) & 0x1F)); + } + else + { + NVIC_DisableIRQ(IRQn); + } + + return NRF_SUCCESS; +} + +__STATIC_INLINE uint32_t sd_nvic_GetPendingIRQ(IRQn_Type IRQn, uint32_t * p_pending_irq) +{ + if (__sd_nvic_app_accessible_irq(IRQn)) + { + *p_pending_irq = NVIC_GetPendingIRQ(IRQn); + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE; + } +} + +__STATIC_INLINE uint32_t sd_nvic_SetPendingIRQ(IRQn_Type IRQn) +{ + if (__sd_nvic_app_accessible_irq(IRQn)) + { + NVIC_SetPendingIRQ(IRQn); + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE; + } +} + +__STATIC_INLINE uint32_t sd_nvic_ClearPendingIRQ(IRQn_Type IRQn) +{ + if (__sd_nvic_app_accessible_irq(IRQn)) + { + NVIC_ClearPendingIRQ(IRQn); + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE; + } +} + +__STATIC_INLINE uint32_t sd_nvic_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if (!__sd_nvic_app_accessible_irq(IRQn)) + { + return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE; + } + + if (!__sd_nvic_is_app_accessible_priority(priority)) + { + return NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED; + } + + NVIC_SetPriority(IRQn, (uint32_t)priority); + return NRF_SUCCESS; +} + +__STATIC_INLINE uint32_t sd_nvic_GetPriority(IRQn_Type IRQn, uint32_t * p_priority) +{ + if (__sd_nvic_app_accessible_irq(IRQn)) + { + *p_priority = (NVIC_GetPriority(IRQn) & 0xFF); + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE; + } +} + +__STATIC_INLINE uint32_t sd_nvic_SystemReset(void) +{ + NVIC_SystemReset(); + return NRF_ERROR_SOC_NVIC_SHOULD_NOT_RETURN; +} + +__STATIC_INLINE uint32_t sd_nvic_critical_region_enter(uint8_t * p_is_nested_critical_region) +{ + int was_masked = __sd_nvic_irq_disable(); + if (!nrf_nvic_state.__cr_flag) + { + nrf_nvic_state.__cr_flag = 1; + nrf_nvic_state.__irq_masks[0] = ( NVIC->ICER[0] & __NRF_NVIC_APP_IRQS_0 ); + NVIC->ICER[0] = __NRF_NVIC_APP_IRQS_0; + nrf_nvic_state.__irq_masks[1] = ( NVIC->ICER[1] & __NRF_NVIC_APP_IRQS_1 ); + NVIC->ICER[1] = __NRF_NVIC_APP_IRQS_1; + *p_is_nested_critical_region = 0; + } + else + { + *p_is_nested_critical_region = 1; + } + if (!was_masked) + { + __sd_nvic_irq_enable(); + } + return NRF_SUCCESS; +} + +__STATIC_INLINE uint32_t sd_nvic_critical_region_exit(uint8_t is_nested_critical_region) +{ + if (nrf_nvic_state.__cr_flag && (is_nested_critical_region == 0)) + { + int was_masked = __sd_nvic_irq_disable(); + NVIC->ISER[0] = nrf_nvic_state.__irq_masks[0]; + NVIC->ISER[1] = nrf_nvic_state.__irq_masks[1]; + nrf_nvic_state.__cr_flag = 0; + if (!was_masked) + { + __sd_nvic_irq_enable(); + } + } + + return NRF_SUCCESS; +} + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_NVIC_H__ + +/**@} */ diff --git a/components/softdevice/s140/headers/nrf_sd_def.h b/components/softdevice/s140/headers/nrf_sd_def.h new file mode 100644 index 0000000..3bee1dd --- /dev/null +++ b/components/softdevice/s140/headers/nrf_sd_def.h @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_SD_DEF_H__ +#define NRF_SD_DEF_H__ + +#include +#include "nrf_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef NRF_SOC_SD_PPI_CHANNELS_SD_ENABLED_MSK +#define SD_PPI_CHANNELS_USED NRF_SOC_SD_PPI_CHANNELS_SD_ENABLED_MSK /**< PPI channels utilized by SotfDevice (not available to the application). */ +#else +#define SD_PPI_CHANNELS_USED 0xFFFE0000uL /**< PPI channels utilized by SotfDevice (not available to the application). */ +#endif // NRF_SOC_SD_PPI_CHANNELS_SD_ENABLED_MSK + +#ifdef NRF_SOC_SD_PPI_GROUPS_SD_ENABLED_MSK +#define SD_PPI_GROUPS_USED NRF_SOC_SD_PPI_GROUPS_SD_ENABLED_MSK /**< PPI groups utilized by SoftDevice (not available to the application). */ +#else +#define SD_PPI_GROUPS_USED 0x0000000CuL /**< PPI groups utilized by SoftDevice (not available to the application). */ +#endif // NRF_SOC_SD_PPI_GROUPS_SD_ENABLED_MSK + +#define SD_TIMERS_USED 0x00000001uL /**< Timers used by SoftDevice. */ +#define SD_SWI_USED 0x00000036uL /**< Software interrupts used by SoftDevice */ + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_SD_DEF_H__ */ diff --git a/components/softdevice/s140/headers/nrf_sdm.h b/components/softdevice/s140/headers/nrf_sdm.h new file mode 100644 index 0000000..e4188f9 --- /dev/null +++ b/components/softdevice/s140/headers/nrf_sdm.h @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @defgroup nrf_sdm_api SoftDevice Manager API + @{ + + @brief APIs for SoftDevice management. + +*/ + +#ifndef NRF_SDM_H__ +#define NRF_SDM_H__ + +#include +#include "nrf.h" +#include "nrf_svc.h" +#include "nrf_error.h" +#include "nrf_error_sdm.h" +#include "nrf_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup NRF_SDM_DEFINES Defines + * @{ */ +#ifdef NRFSOC_DOXYGEN +/// Declared in nrf_mbr.h +#define MBR_SIZE 0 +#warning test +#endif + +/** @brief The major version for the SoftDevice binary distributed with this header file. */ +#define SD_MAJOR_VERSION (7) + +/** @brief The minor version for the SoftDevice binary distributed with this header file. */ +#define SD_MINOR_VERSION (2) + +/** @brief The bugfix version for the SoftDevice binary distributed with this header file. */ +#define SD_BUGFIX_VERSION (0) + +/** @brief The SoftDevice variant of this firmware. */ +#define SD_VARIANT_ID 140 + +/** @brief The full version number for the SoftDevice binary this header file was distributed + * with, as a decimal number in the form Mmmmbbb, where: + * - M is major version (one or more digits) + * - mmm is minor version (three digits) + * - bbb is bugfix version (three digits). */ +#define SD_VERSION (SD_MAJOR_VERSION * 1000000 + SD_MINOR_VERSION * 1000 + SD_BUGFIX_VERSION) + +/** @brief SoftDevice Manager SVC Base number. */ +#define SDM_SVC_BASE 0x10 + +/** @brief SoftDevice unique string size in bytes. */ +#define SD_UNIQUE_STR_SIZE 20 + +/** @brief Invalid info field. Returned when an info field does not exist. */ +#define SDM_INFO_FIELD_INVALID (0) + +/** @brief Defines the SoftDevice Information Structure location (address) as an offset from +the start of the SoftDevice (without MBR)*/ +#define SOFTDEVICE_INFO_STRUCT_OFFSET (0x2000) + +/** @brief Defines the absolute SoftDevice Information Structure location (address) when the + * SoftDevice is installed just above the MBR (the usual case). */ +#define SOFTDEVICE_INFO_STRUCT_ADDRESS (SOFTDEVICE_INFO_STRUCT_OFFSET + MBR_SIZE) + +/** @brief Defines the offset for the SoftDevice Information Structure size value relative to the + * SoftDevice base address. The size value is of type uint8_t. */ +#define SD_INFO_STRUCT_SIZE_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET) + +/** @brief Defines the offset for the SoftDevice size value relative to the SoftDevice base address. + * The size value is of type uint32_t. */ +#define SD_SIZE_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x08) + +/** @brief Defines the offset for FWID value relative to the SoftDevice base address. The FWID value + * is of type uint16_t. */ +#define SD_FWID_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x0C) + +/** @brief Defines the offset for the SoftDevice ID relative to the SoftDevice base address. The ID + * is of type uint32_t. */ +#define SD_ID_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x10) + +/** @brief Defines the offset for the SoftDevice version relative to the SoftDevice base address in + * the same format as @ref SD_VERSION, stored as an uint32_t. */ +#define SD_VERSION_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x14) + +/** @brief Defines the offset for the SoftDevice unique string relative to the SoftDevice base address. + * The SD_UNIQUE_STR is stored as an array of uint8_t. The size of array is @ref SD_UNIQUE_STR_SIZE. + */ +#define SD_UNIQUE_STR_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x18) + +/** @brief Defines a macro for retrieving the actual SoftDevice Information Structure size value + * from a given base address. Use @ref MBR_SIZE as the argument when the SoftDevice is + * installed just above the MBR (the usual case). */ +#define SD_INFO_STRUCT_SIZE_GET(baseaddr) (*((uint8_t *) ((baseaddr) + SD_INFO_STRUCT_SIZE_OFFSET))) + +/** @brief Defines a macro for retrieving the actual SoftDevice size value from a given base + * address. Use @ref MBR_SIZE as the argument when the SoftDevice is installed just above + * the MBR (the usual case). */ +#define SD_SIZE_GET(baseaddr) (*((uint32_t *) ((baseaddr) + SD_SIZE_OFFSET))) + +/** @brief Defines the amount of flash that is used by the SoftDevice. + * Add @ref MBR_SIZE to find the first available flash address when the SoftDevice is installed + * just above the MBR (the usual case). + */ +#define SD_FLASH_SIZE 0x26000 + +/** @brief Defines a macro for retrieving the actual FWID value from a given base address. Use + * @ref MBR_SIZE as the argument when the SoftDevice is installed just above the MBR (the usual + * case). */ +#define SD_FWID_GET(baseaddr) (*((uint16_t *) ((baseaddr) + SD_FWID_OFFSET))) + +/** @brief Defines a macro for retrieving the actual SoftDevice ID from a given base address. Use + * @ref MBR_SIZE as the argument when the SoftDevice is installed just above the MBR (the + * usual case). */ +#define SD_ID_GET(baseaddr) ((SD_INFO_STRUCT_SIZE_GET(baseaddr) > (SD_ID_OFFSET - SOFTDEVICE_INFO_STRUCT_OFFSET)) \ + ? (*((uint32_t *) ((baseaddr) + SD_ID_OFFSET))) : SDM_INFO_FIELD_INVALID) + +/** @brief Defines a macro for retrieving the actual SoftDevice version from a given base address. + * Use @ref MBR_SIZE as the argument when the SoftDevice is installed just above the MBR + * (the usual case). */ +#define SD_VERSION_GET(baseaddr) ((SD_INFO_STRUCT_SIZE_GET(baseaddr) > (SD_VERSION_OFFSET - SOFTDEVICE_INFO_STRUCT_OFFSET)) \ + ? (*((uint32_t *) ((baseaddr) + SD_VERSION_OFFSET))) : SDM_INFO_FIELD_INVALID) + +/** @brief Defines a macro for retrieving the address of SoftDevice unique str based on a given base address. + * Use @ref MBR_SIZE as the argument when the SoftDevice is installed just above the MBR + * (the usual case). */ +#define SD_UNIQUE_STR_ADDR_GET(baseaddr) ((SD_INFO_STRUCT_SIZE_GET(baseaddr) > (SD_UNIQUE_STR_OFFSET - SOFTDEVICE_INFO_STRUCT_OFFSET)) \ + ? (((uint8_t *) ((baseaddr) + SD_UNIQUE_STR_OFFSET))) : SDM_INFO_FIELD_INVALID) + +/**@defgroup NRF_FAULT_ID_RANGES Fault ID ranges + * @{ */ +#define NRF_FAULT_ID_SD_RANGE_START 0x00000000 /**< SoftDevice ID range start. */ +#define NRF_FAULT_ID_APP_RANGE_START 0x00001000 /**< Application ID range start. */ +/**@} */ + +/**@defgroup NRF_FAULT_IDS Fault ID types + * @{ */ +#define NRF_FAULT_ID_SD_ASSERT (NRF_FAULT_ID_SD_RANGE_START + 1) /**< SoftDevice assertion. The info parameter is reserved for future used. */ +#define NRF_FAULT_ID_APP_MEMACC (NRF_FAULT_ID_APP_RANGE_START + 1) /**< Application invalid memory access. The info parameter will contain 0x00000000, + in case of SoftDevice RAM access violation. In case of SoftDevice peripheral + register violation the info parameter will contain the sub-region number of + PREGION[0], on whose address range the disallowed write access caused the + memory access fault. */ +/**@} */ + +/** @} */ + +/** @addtogroup NRF_SDM_ENUMS Enumerations + * @{ */ + +/**@brief nRF SoftDevice Manager API SVC numbers. */ +enum NRF_SD_SVCS +{ + SD_SOFTDEVICE_ENABLE = SDM_SVC_BASE, /**< ::sd_softdevice_enable */ + SD_SOFTDEVICE_DISABLE, /**< ::sd_softdevice_disable */ + SD_SOFTDEVICE_IS_ENABLED, /**< ::sd_softdevice_is_enabled */ + SD_SOFTDEVICE_VECTOR_TABLE_BASE_SET, /**< ::sd_softdevice_vector_table_base_set */ + SVC_SDM_LAST /**< Placeholder for last SDM SVC */ +}; + +/** @} */ + +/** @addtogroup NRF_SDM_DEFINES Defines + * @{ */ + +/**@defgroup NRF_CLOCK_LF_ACCURACY Clock accuracy + * @{ */ + +#define NRF_CLOCK_LF_ACCURACY_250_PPM (0) /**< Default: 250 ppm */ +#define NRF_CLOCK_LF_ACCURACY_500_PPM (1) /**< 500 ppm */ +#define NRF_CLOCK_LF_ACCURACY_150_PPM (2) /**< 150 ppm */ +#define NRF_CLOCK_LF_ACCURACY_100_PPM (3) /**< 100 ppm */ +#define NRF_CLOCK_LF_ACCURACY_75_PPM (4) /**< 75 ppm */ +#define NRF_CLOCK_LF_ACCURACY_50_PPM (5) /**< 50 ppm */ +#define NRF_CLOCK_LF_ACCURACY_30_PPM (6) /**< 30 ppm */ +#define NRF_CLOCK_LF_ACCURACY_20_PPM (7) /**< 20 ppm */ +#define NRF_CLOCK_LF_ACCURACY_10_PPM (8) /**< 10 ppm */ +#define NRF_CLOCK_LF_ACCURACY_5_PPM (9) /**< 5 ppm */ +#define NRF_CLOCK_LF_ACCURACY_2_PPM (10) /**< 2 ppm */ +#define NRF_CLOCK_LF_ACCURACY_1_PPM (11) /**< 1 ppm */ + +/** @} */ + +/**@defgroup NRF_CLOCK_LF_SRC Possible LFCLK oscillator sources + * @{ */ + +#define NRF_CLOCK_LF_SRC_RC (0) /**< LFCLK RC oscillator. */ +#define NRF_CLOCK_LF_SRC_XTAL (1) /**< LFCLK crystal oscillator. */ +#define NRF_CLOCK_LF_SRC_SYNTH (2) /**< LFCLK Synthesized from HFCLK. */ + +/** @} */ + +/** @} */ + +/** @addtogroup NRF_SDM_TYPES Types + * @{ */ + +/**@brief Type representing LFCLK oscillator source. */ +typedef struct +{ + uint8_t source; /**< LF oscillator clock source, see @ref NRF_CLOCK_LF_SRC. */ + uint8_t rc_ctiv; /**< Only for ::NRF_CLOCK_LF_SRC_RC: Calibration timer interval in 1/4 second + units (nRF52: 1-32). + @note To avoid excessive clock drift, 0.5 degrees Celsius is the + maximum temperature change allowed in one calibration timer + interval. The interval should be selected to ensure this. + + @note Must be 0 if source is not ::NRF_CLOCK_LF_SRC_RC. */ + uint8_t rc_temp_ctiv; /**< Only for ::NRF_CLOCK_LF_SRC_RC: How often (in number of calibration + intervals) the RC oscillator shall be calibrated if the temperature + hasn't changed. + 0: Always calibrate even if the temperature hasn't changed. + 1: Only calibrate if the temperature has changed (legacy - nRF51 only). + 2-33: Check the temperature and only calibrate if it has changed, + however calibration will take place every rc_temp_ctiv + intervals in any case. + + @note Must be 0 if source is not ::NRF_CLOCK_LF_SRC_RC. + + @note For nRF52, the application must ensure calibration at least once + every 8 seconds to ensure +/-500 ppm clock stability. The + recommended configuration for ::NRF_CLOCK_LF_SRC_RC on nRF52 is + rc_ctiv=16 and rc_temp_ctiv=2. This will ensure calibration at + least once every 8 seconds and for temperature changes of 0.5 + degrees Celsius every 4 seconds. See the Product Specification + for the nRF52 device being used for more information.*/ + uint8_t accuracy; /**< External clock accuracy used in the LL to compute timing + windows, see @ref NRF_CLOCK_LF_ACCURACY.*/ +} nrf_clock_lf_cfg_t; + +/**@brief Fault Handler type. + * + * When certain unrecoverable errors occur within the application or SoftDevice the fault handler will be called back. + * The protocol stack will be in an undefined state when this happens and the only way to recover will be to + * perform a reset, using e.g. CMSIS NVIC_SystemReset(). + * If the application returns from the fault handler the SoftDevice will call NVIC_SystemReset(). + * + * @note It is recommended to either perform a reset in the fault handler or to let the SoftDevice reset the device. + * Otherwise SoC peripherals may behave in an undefined way. For example, the RADIO peripherial may + * continously transmit packets. + * + * @note This callback is executed in HardFault context, thus SVC functions cannot be called from the fault callback. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault. + * @param[in] info Optional additional information regarding the fault. Refer to each Fault identifier for details. + * + * @note When id is set to @ref NRF_FAULT_ID_APP_MEMACC, pc will contain the address of the instruction being executed at the time when + * the fault is detected by the CPU. The CPU program counter may have advanced up to 2 instructions (no branching) after the one that triggered the fault. + */ +typedef void (*nrf_fault_handler_t)(uint32_t id, uint32_t pc, uint32_t info); + +/** @} */ + +/** @addtogroup NRF_SDM_FUNCTIONS Functions + * @{ */ + +/**@brief Enables the SoftDevice and by extension the protocol stack. + * + * @note Some care must be taken if a low frequency clock source is already running when calling this function: + * If the LF clock has a different source then the one currently running, it will be stopped. Then, the new + * clock source will be started. + * + * @note This function has no effect when returning with an error. + * + * @post If return code is ::NRF_SUCCESS + * - SoC library and protocol stack APIs are made available. + * - A portion of RAM will be unavailable (see relevant SDS documentation). + * - Some peripherals will be unavailable or available only through the SoC API (see relevant SDS documentation). + * - Interrupts will not arrive from protected peripherals or interrupts. + * - nrf_nvic_ functions must be used instead of CMSIS NVIC_ functions for reliable usage of the SoftDevice. + * - Interrupt latency may be affected by the SoftDevice (see relevant SDS documentation). + * - Chosen low frequency clock source will be running. + * + * @param p_clock_lf_cfg Low frequency clock source and accuracy. + If NULL the clock will be configured as an RC source with rc_ctiv = 16 and .rc_temp_ctiv = 2 + In the case of XTAL source, the PPM accuracy of the chosen clock source must be greater than or equal to the actual characteristics of your XTAL clock. + * @param fault_handler Callback to be invoked in case of fault, cannot be NULL. + * + * @retval ::NRF_SUCCESS + * @retval ::NRF_ERROR_INVALID_ADDR Invalid or NULL pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE SoftDevice is already enabled, and the clock source and fault handler cannot be updated. + * @retval ::NRF_ERROR_SDM_INCORRECT_INTERRUPT_CONFIGURATION SoftDevice interrupt is already enabled, or an enabled interrupt has an illegal priority level. + * @retval ::NRF_ERROR_SDM_LFCLK_SOURCE_UNKNOWN Unknown low frequency clock source selected. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid clock source configuration supplied in p_clock_lf_cfg. + */ +SVCALL(SD_SOFTDEVICE_ENABLE, uint32_t, sd_softdevice_enable(nrf_clock_lf_cfg_t const * p_clock_lf_cfg, nrf_fault_handler_t fault_handler)); + + +/**@brief Disables the SoftDevice and by extension the protocol stack. + * + * Idempotent function to disable the SoftDevice. + * + * @post SoC library and protocol stack APIs are made unavailable. + * @post All interrupts that was protected by the SoftDevice will be disabled and initialized to priority 0 (highest). + * @post All peripherals used by the SoftDevice will be reset to default values. + * @post All of RAM become available. + * @post All interrupts are forwarded to the application. + * @post LFCLK source chosen in ::sd_softdevice_enable will be left running. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_SOFTDEVICE_DISABLE, uint32_t, sd_softdevice_disable(void)); + +/**@brief Check if the SoftDevice is enabled. + * + * @param[out] p_softdevice_enabled If the SoftDevice is enabled: 1 else 0. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_SOFTDEVICE_IS_ENABLED, uint32_t, sd_softdevice_is_enabled(uint8_t * p_softdevice_enabled)); + +/**@brief Sets the base address of the interrupt vector table for interrupts forwarded from the SoftDevice + * + * This function is only intended to be called when a bootloader is enabled. + * + * @param[in] address The base address of the interrupt vector table for forwarded interrupts. + + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_SOFTDEVICE_VECTOR_TABLE_BASE_SET, uint32_t, sd_softdevice_vector_table_base_set(uint32_t address)); + +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif // NRF_SDM_H__ + +/** + @} +*/ diff --git a/components/softdevice/s140/headers/nrf_soc.h b/components/softdevice/s140/headers/nrf_soc.h new file mode 100644 index 0000000..3751d13 --- /dev/null +++ b/components/softdevice/s140/headers/nrf_soc.h @@ -0,0 +1,1080 @@ +/* + * Copyright (c) 2015 - 2019, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @defgroup nrf_soc_api SoC Library API + * @{ + * + * @brief APIs for the SoC library. + * + */ + +#ifndef NRF_SOC_H__ +#define NRF_SOC_H__ + +#include +#include "nrf.h" +#include "nrf_svc.h" +#include "nrf_error.h" +#include "nrf_error_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@addtogroup NRF_SOC_DEFINES Defines + * @{ */ + +/**@brief The number of the lowest SVC number reserved for the SoC library. */ +#define SOC_SVC_BASE (0x20) /**< Base value for SVCs that are available when the SoftDevice is disabled. */ +#define SOC_SVC_BASE_NOT_AVAILABLE (0x2C) /**< Base value for SVCs that are not available when the SoftDevice is disabled. */ + +/**@brief Guaranteed time for application to process radio inactive notification. */ +#define NRF_RADIO_NOTIFICATION_INACTIVE_GUARANTEED_TIME_US (62) + +/**@brief The minimum allowed timeslot extension time. */ +#define NRF_RADIO_MINIMUM_TIMESLOT_LENGTH_EXTENSION_TIME_US (200) + +/**@brief The maximum processing time to handle a timeslot extension. */ +#define NRF_RADIO_MAX_EXTENSION_PROCESSING_TIME_US (20) + +/**@brief The latest time before the end of a timeslot the timeslot can be extended. */ +#define NRF_RADIO_MIN_EXTENSION_MARGIN_US (82) + +#define SOC_ECB_KEY_LENGTH (16) /**< ECB key length. */ +#define SOC_ECB_CLEARTEXT_LENGTH (16) /**< ECB cleartext length. */ +#define SOC_ECB_CIPHERTEXT_LENGTH (SOC_ECB_CLEARTEXT_LENGTH) /**< ECB ciphertext length. */ + +#define SD_EVT_IRQn (SWI2_IRQn) /**< SoftDevice Event IRQ number. Used for both protocol events and SoC events. */ +#define SD_EVT_IRQHandler (SWI2_IRQHandler) /**< SoftDevice Event IRQ handler. Used for both protocol events and SoC events. + The default interrupt priority for this handler is set to 6 */ +#define RADIO_NOTIFICATION_IRQn (SWI1_IRQn) /**< The radio notification IRQ number. */ +#define RADIO_NOTIFICATION_IRQHandler (SWI1_IRQHandler) /**< The radio notification IRQ handler. + The default interrupt priority for this handler is set to 6 */ +#define NRF_RADIO_LENGTH_MIN_US (100) /**< The shortest allowed radio timeslot, in microseconds. */ +#define NRF_RADIO_LENGTH_MAX_US (100000) /**< The longest allowed radio timeslot, in microseconds. */ + +#define NRF_RADIO_DISTANCE_MAX_US (128000000UL - 1UL) /**< The longest timeslot distance, in microseconds, allowed for the distance parameter (see @ref nrf_radio_request_normal_t) in the request. */ + +#define NRF_RADIO_EARLIEST_TIMEOUT_MAX_US (128000000UL - 1UL) /**< The longest timeout, in microseconds, allowed when requesting the earliest possible timeslot. */ + +#define NRF_RADIO_START_JITTER_US (2) /**< The maximum jitter in @ref NRF_RADIO_CALLBACK_SIGNAL_TYPE_START relative to the requested start time. */ + +/**@brief Mask of PPI channels reserved by the SoftDevice when the SoftDevice is disabled. */ +#define NRF_SOC_SD_PPI_CHANNELS_SD_DISABLED_MSK ((uint32_t)(0)) + +/**@brief Mask of PPI channels reserved by the SoftDevice when the SoftDevice is enabled. */ +#define NRF_SOC_SD_PPI_CHANNELS_SD_ENABLED_MSK ((uint32_t)( \ + (1U << 17) \ + | (1U << 18) \ + | (1U << 19) \ + | (1U << 20) \ + | (1U << 21) \ + | (1U << 22) \ + | (1U << 23) \ + | (1U << 24) \ + | (1U << 25) \ + | (1U << 26) \ + | (1U << 27) \ + | (1U << 28) \ + | (1U << 29) \ + | (1U << 30) \ + | (1U << 31) \ + )) + +/**@brief Mask of PPI groups reserved by the SoftDevice when the SoftDevice is disabled. */ +#define NRF_SOC_SD_PPI_GROUPS_SD_DISABLED_MSK ((uint32_t)(0)) + +/**@brief Mask of PPI groups reserved by the SoftDevice when the SoftDevice is enabled. */ +#define NRF_SOC_SD_PPI_GROUPS_SD_ENABLED_MSK ((uint32_t)( \ + (1U << 4) \ + | (1U << 5) \ + )) + +/**@} */ + +/**@addtogroup NRF_SOC_ENUMS Enumerations + * @{ */ + +/**@brief The SVC numbers used by the SVC functions in the SoC library. */ +enum NRF_SOC_SVCS +{ + SD_PPI_CHANNEL_ENABLE_GET = SOC_SVC_BASE, + SD_PPI_CHANNEL_ENABLE_SET = SOC_SVC_BASE + 1, + SD_PPI_CHANNEL_ENABLE_CLR = SOC_SVC_BASE + 2, + SD_PPI_CHANNEL_ASSIGN = SOC_SVC_BASE + 3, + SD_PPI_GROUP_TASK_ENABLE = SOC_SVC_BASE + 4, + SD_PPI_GROUP_TASK_DISABLE = SOC_SVC_BASE + 5, + SD_PPI_GROUP_ASSIGN = SOC_SVC_BASE + 6, + SD_PPI_GROUP_GET = SOC_SVC_BASE + 7, + SD_FLASH_PAGE_ERASE = SOC_SVC_BASE + 8, + SD_FLASH_WRITE = SOC_SVC_BASE + 9, + SD_PROTECTED_REGISTER_WRITE = SOC_SVC_BASE + 11, + SD_MUTEX_NEW = SOC_SVC_BASE_NOT_AVAILABLE, + SD_MUTEX_ACQUIRE = SOC_SVC_BASE_NOT_AVAILABLE + 1, + SD_MUTEX_RELEASE = SOC_SVC_BASE_NOT_AVAILABLE + 2, + SD_RAND_APPLICATION_POOL_CAPACITY_GET = SOC_SVC_BASE_NOT_AVAILABLE + 3, + SD_RAND_APPLICATION_BYTES_AVAILABLE_GET = SOC_SVC_BASE_NOT_AVAILABLE + 4, + SD_RAND_APPLICATION_VECTOR_GET = SOC_SVC_BASE_NOT_AVAILABLE + 5, + SD_POWER_MODE_SET = SOC_SVC_BASE_NOT_AVAILABLE + 6, + SD_POWER_SYSTEM_OFF = SOC_SVC_BASE_NOT_AVAILABLE + 7, + SD_POWER_RESET_REASON_GET = SOC_SVC_BASE_NOT_AVAILABLE + 8, + SD_POWER_RESET_REASON_CLR = SOC_SVC_BASE_NOT_AVAILABLE + 9, + SD_POWER_POF_ENABLE = SOC_SVC_BASE_NOT_AVAILABLE + 10, + SD_POWER_POF_THRESHOLD_SET = SOC_SVC_BASE_NOT_AVAILABLE + 11, + SD_POWER_POF_THRESHOLDVDDH_SET = SOC_SVC_BASE_NOT_AVAILABLE + 12, + SD_POWER_RAM_POWER_SET = SOC_SVC_BASE_NOT_AVAILABLE + 13, + SD_POWER_RAM_POWER_CLR = SOC_SVC_BASE_NOT_AVAILABLE + 14, + SD_POWER_RAM_POWER_GET = SOC_SVC_BASE_NOT_AVAILABLE + 15, + SD_POWER_GPREGRET_SET = SOC_SVC_BASE_NOT_AVAILABLE + 16, + SD_POWER_GPREGRET_CLR = SOC_SVC_BASE_NOT_AVAILABLE + 17, + SD_POWER_GPREGRET_GET = SOC_SVC_BASE_NOT_AVAILABLE + 18, + SD_POWER_DCDC_MODE_SET = SOC_SVC_BASE_NOT_AVAILABLE + 19, + SD_POWER_DCDC0_MODE_SET = SOC_SVC_BASE_NOT_AVAILABLE + 20, + SD_APP_EVT_WAIT = SOC_SVC_BASE_NOT_AVAILABLE + 21, + SD_CLOCK_HFCLK_REQUEST = SOC_SVC_BASE_NOT_AVAILABLE + 22, + SD_CLOCK_HFCLK_RELEASE = SOC_SVC_BASE_NOT_AVAILABLE + 23, + SD_CLOCK_HFCLK_IS_RUNNING = SOC_SVC_BASE_NOT_AVAILABLE + 24, + SD_RADIO_NOTIFICATION_CFG_SET = SOC_SVC_BASE_NOT_AVAILABLE + 25, + SD_ECB_BLOCK_ENCRYPT = SOC_SVC_BASE_NOT_AVAILABLE + 26, + SD_ECB_BLOCKS_ENCRYPT = SOC_SVC_BASE_NOT_AVAILABLE + 27, + SD_RADIO_SESSION_OPEN = SOC_SVC_BASE_NOT_AVAILABLE + 28, + SD_RADIO_SESSION_CLOSE = SOC_SVC_BASE_NOT_AVAILABLE + 29, + SD_RADIO_REQUEST = SOC_SVC_BASE_NOT_AVAILABLE + 30, + SD_EVT_GET = SOC_SVC_BASE_NOT_AVAILABLE + 31, + SD_TEMP_GET = SOC_SVC_BASE_NOT_AVAILABLE + 32, + SD_POWER_USBPWRRDY_ENABLE = SOC_SVC_BASE_NOT_AVAILABLE + 33, + SD_POWER_USBDETECTED_ENABLE = SOC_SVC_BASE_NOT_AVAILABLE + 34, + SD_POWER_USBREMOVED_ENABLE = SOC_SVC_BASE_NOT_AVAILABLE + 35, + SD_POWER_USBREGSTATUS_GET = SOC_SVC_BASE_NOT_AVAILABLE + 36, + SVC_SOC_LAST = SOC_SVC_BASE_NOT_AVAILABLE + 37 +}; + +/**@brief Possible values of a ::nrf_mutex_t. */ +enum NRF_MUTEX_VALUES +{ + NRF_MUTEX_FREE, + NRF_MUTEX_TAKEN +}; + +/**@brief Power modes. */ +enum NRF_POWER_MODES +{ + NRF_POWER_MODE_CONSTLAT, /**< Constant latency mode. See power management in the reference manual. */ + NRF_POWER_MODE_LOWPWR /**< Low power mode. See power management in the reference manual. */ +}; + + +/**@brief Power failure thresholds */ +enum NRF_POWER_THRESHOLDS +{ + NRF_POWER_THRESHOLD_V17 = 4UL, /**< 1.7 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V18, /**< 1.8 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V19, /**< 1.9 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V20, /**< 2.0 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V21, /**< 2.1 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V22, /**< 2.2 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V23, /**< 2.3 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V24, /**< 2.4 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V25, /**< 2.5 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V26, /**< 2.6 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V27, /**< 2.7 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V28 /**< 2.8 Volts power failure threshold. */ +}; + +/**@brief Power failure thresholds for high voltage */ +enum NRF_POWER_THRESHOLDVDDHS +{ + NRF_POWER_THRESHOLDVDDH_V27, /**< 2.7 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V28, /**< 2.8 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V29, /**< 2.9 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V30, /**< 3.0 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V31, /**< 3.1 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V32, /**< 3.2 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V33, /**< 3.3 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V34, /**< 3.4 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V35, /**< 3.5 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V36, /**< 3.6 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V37, /**< 3.7 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V38, /**< 3.8 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V39, /**< 3.9 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V40, /**< 4.0 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V41, /**< 4.1 Volts power failure threshold. */ + NRF_POWER_THRESHOLDVDDH_V42 /**< 4.2 Volts power failure threshold. */ +}; + + +/**@brief DC/DC converter modes. */ +enum NRF_POWER_DCDC_MODES +{ + NRF_POWER_DCDC_DISABLE, /**< The DCDC is disabled. */ + NRF_POWER_DCDC_ENABLE /**< The DCDC is enabled. */ +}; + +/**@brief Radio notification distances. */ +enum NRF_RADIO_NOTIFICATION_DISTANCES +{ + NRF_RADIO_NOTIFICATION_DISTANCE_NONE = 0, /**< The event does not have a notification. */ + NRF_RADIO_NOTIFICATION_DISTANCE_800US, /**< The distance from the active notification to start of radio activity. */ + NRF_RADIO_NOTIFICATION_DISTANCE_1740US, /**< The distance from the active notification to start of radio activity. */ + NRF_RADIO_NOTIFICATION_DISTANCE_2680US, /**< The distance from the active notification to start of radio activity. */ + NRF_RADIO_NOTIFICATION_DISTANCE_3620US, /**< The distance from the active notification to start of radio activity. */ + NRF_RADIO_NOTIFICATION_DISTANCE_4560US, /**< The distance from the active notification to start of radio activity. */ + NRF_RADIO_NOTIFICATION_DISTANCE_5500US /**< The distance from the active notification to start of radio activity. */ +}; + + +/**@brief Radio notification types. */ +enum NRF_RADIO_NOTIFICATION_TYPES +{ + NRF_RADIO_NOTIFICATION_TYPE_NONE = 0, /**< The event does not have a radio notification signal. */ + NRF_RADIO_NOTIFICATION_TYPE_INT_ON_ACTIVE, /**< Using interrupt for notification when the radio will be enabled. */ + NRF_RADIO_NOTIFICATION_TYPE_INT_ON_INACTIVE, /**< Using interrupt for notification when the radio has been disabled. */ + NRF_RADIO_NOTIFICATION_TYPE_INT_ON_BOTH, /**< Using interrupt for notification both when the radio will be enabled and disabled. */ +}; + +/**@brief The Radio signal callback types. */ +enum NRF_RADIO_CALLBACK_SIGNAL_TYPE +{ + NRF_RADIO_CALLBACK_SIGNAL_TYPE_START, /**< This signal indicates the start of the radio timeslot. */ + NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0, /**< This signal indicates the NRF_TIMER0 interrupt. */ + NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO, /**< This signal indicates the NRF_RADIO interrupt. */ + NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED, /**< This signal indicates extend action failed. */ + NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED /**< This signal indicates extend action succeeded. */ +}; + +/**@brief The actions requested by the signal callback. + * + * This code gives the SOC instructions about what action to take when the signal callback has + * returned. + */ +enum NRF_RADIO_SIGNAL_CALLBACK_ACTION +{ + NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE, /**< Return without action. */ + NRF_RADIO_SIGNAL_CALLBACK_ACTION_EXTEND, /**< Request an extension of the current + timeslot. Maximum execution time for this action: + @ref NRF_RADIO_MAX_EXTENSION_PROCESSING_TIME_US. + This action must be started at least + @ref NRF_RADIO_MIN_EXTENSION_MARGIN_US before + the end of the timeslot. */ + NRF_RADIO_SIGNAL_CALLBACK_ACTION_END, /**< End the current radio timeslot. */ + NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END /**< Request a new radio timeslot and end the current timeslot. */ +}; + +/**@brief Radio timeslot high frequency clock source configuration. */ +enum NRF_RADIO_HFCLK_CFG +{ + NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED, /**< The SoftDevice will guarantee that the high frequency clock source is the + external crystal for the whole duration of the timeslot. This should be the + preferred option for events that use the radio or require high timing accuracy. + @note The SoftDevice will automatically turn on and off the external crystal, + at the beginning and end of the timeslot, respectively. The crystal may also + intentionally be left running after the timeslot, in cases where it is needed + by the SoftDevice shortly after the end of the timeslot. */ + NRF_RADIO_HFCLK_CFG_NO_GUARANTEE /**< This configuration allows for earlier and tighter scheduling of timeslots. + The RC oscillator may be the clock source in part or for the whole duration of the timeslot. + The RC oscillator's accuracy must therefore be taken into consideration. + @note If the application will use the radio peripheral in timeslots with this configuration, + it must make sure that the crystal is running and stable before starting the radio. */ +}; + +/**@brief Radio timeslot priorities. */ +enum NRF_RADIO_PRIORITY +{ + NRF_RADIO_PRIORITY_HIGH, /**< High (equal priority as the normal connection priority of the SoftDevice stack(s)). */ + NRF_RADIO_PRIORITY_NORMAL, /**< Normal (equal priority as the priority of secondary activities of the SoftDevice stack(s)). */ +}; + +/**@brief Radio timeslot request type. */ +enum NRF_RADIO_REQUEST_TYPE +{ + NRF_RADIO_REQ_TYPE_EARLIEST, /**< Request radio timeslot as early as possible. This should always be used for the first request in a session. */ + NRF_RADIO_REQ_TYPE_NORMAL /**< Normal radio timeslot request. */ +}; + +/**@brief SoC Events. */ +enum NRF_SOC_EVTS +{ + NRF_EVT_HFCLKSTARTED, /**< Event indicating that the HFCLK has started. */ + NRF_EVT_POWER_FAILURE_WARNING, /**< Event indicating that a power failure warning has occurred. */ + NRF_EVT_FLASH_OPERATION_SUCCESS, /**< Event indicating that the ongoing flash operation has completed successfully. */ + NRF_EVT_FLASH_OPERATION_ERROR, /**< Event indicating that the ongoing flash operation has timed out with an error. */ + NRF_EVT_RADIO_BLOCKED, /**< Event indicating that a radio timeslot was blocked. */ + NRF_EVT_RADIO_CANCELED, /**< Event indicating that a radio timeslot was canceled by SoftDevice. */ + NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN, /**< Event indicating that a radio timeslot signal callback handler return was invalid. */ + NRF_EVT_RADIO_SESSION_IDLE, /**< Event indicating that a radio timeslot session is idle. */ + NRF_EVT_RADIO_SESSION_CLOSED, /**< Event indicating that a radio timeslot session is closed. */ + NRF_EVT_POWER_USB_POWER_READY, /**< Event indicating that a USB 3.3 V supply is ready. */ + NRF_EVT_POWER_USB_DETECTED, /**< Event indicating that voltage supply is detected on VBUS. */ + NRF_EVT_POWER_USB_REMOVED, /**< Event indicating that voltage supply is removed from VBUS. */ + NRF_EVT_NUMBER_OF_EVTS +}; + +/**@} */ + + +/**@addtogroup NRF_SOC_STRUCTURES Structures + * @{ */ + +/**@brief Represents a mutex for use with the nrf_mutex functions. + * @note Accessing the value directly is not safe, use the mutex functions! + */ +typedef volatile uint8_t nrf_mutex_t; + +/**@brief Parameters for a request for a timeslot as early as possible. */ +typedef struct +{ + uint8_t hfclk; /**< High frequency clock source, see @ref NRF_RADIO_HFCLK_CFG. */ + uint8_t priority; /**< The radio timeslot priority, see @ref NRF_RADIO_PRIORITY. */ + uint32_t length_us; /**< The radio timeslot length (in the range 100 to 100,000] microseconds). */ + uint32_t timeout_us; /**< Longest acceptable delay until the start of the requested timeslot (up to @ref NRF_RADIO_EARLIEST_TIMEOUT_MAX_US microseconds). */ +} nrf_radio_request_earliest_t; + +/**@brief Parameters for a normal radio timeslot request. */ +typedef struct +{ + uint8_t hfclk; /**< High frequency clock source, see @ref NRF_RADIO_HFCLK_CFG. */ + uint8_t priority; /**< The radio timeslot priority, see @ref NRF_RADIO_PRIORITY. */ + uint32_t distance_us; /**< Distance from the start of the previous radio timeslot (up to @ref NRF_RADIO_DISTANCE_MAX_US microseconds). */ + uint32_t length_us; /**< The radio timeslot length (in the range [100..100,000] microseconds). */ +} nrf_radio_request_normal_t; + +/**@brief Radio timeslot request parameters. */ +typedef struct +{ + uint8_t request_type; /**< Type of request, see @ref NRF_RADIO_REQUEST_TYPE. */ + union + { + nrf_radio_request_earliest_t earliest; /**< Parameters for requesting a radio timeslot as early as possible. */ + nrf_radio_request_normal_t normal; /**< Parameters for requesting a normal radio timeslot. */ + } params; /**< Parameter union. */ +} nrf_radio_request_t; + +/**@brief Return parameters of the radio timeslot signal callback. */ +typedef struct +{ + uint8_t callback_action; /**< The action requested by the application when returning from the signal callback, see @ref NRF_RADIO_SIGNAL_CALLBACK_ACTION. */ + union + { + struct + { + nrf_radio_request_t * p_next; /**< The request parameters for the next radio timeslot. */ + } request; /**< Additional parameters for return_code @ref NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END. */ + struct + { + uint32_t length_us; /**< Requested extension of the radio timeslot duration (microseconds) (for minimum time see @ref NRF_RADIO_MINIMUM_TIMESLOT_LENGTH_EXTENSION_TIME_US). */ + } extend; /**< Additional parameters for return_code @ref NRF_RADIO_SIGNAL_CALLBACK_ACTION_EXTEND. */ + } params; /**< Parameter union. */ +} nrf_radio_signal_callback_return_param_t; + +/**@brief The radio timeslot signal callback type. + * + * @note In case of invalid return parameters, the radio timeslot will automatically end + * immediately after returning from the signal callback and the + * @ref NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN event will be sent. + * @note The returned struct pointer must remain valid after the signal callback + * function returns. For instance, this means that it must not point to a stack variable. + * + * @param[in] signal_type Type of signal, see @ref NRF_RADIO_CALLBACK_SIGNAL_TYPE. + * + * @return Pointer to structure containing action requested by the application. + */ +typedef nrf_radio_signal_callback_return_param_t * (*nrf_radio_signal_callback_t) (uint8_t signal_type); + +/**@brief AES ECB parameter typedefs */ +typedef uint8_t soc_ecb_key_t[SOC_ECB_KEY_LENGTH]; /**< Encryption key type. */ +typedef uint8_t soc_ecb_cleartext_t[SOC_ECB_CLEARTEXT_LENGTH]; /**< Cleartext data type. */ +typedef uint8_t soc_ecb_ciphertext_t[SOC_ECB_CIPHERTEXT_LENGTH]; /**< Ciphertext data type. */ + +/**@brief AES ECB data structure */ +typedef struct +{ + soc_ecb_key_t key; /**< Encryption key. */ + soc_ecb_cleartext_t cleartext; /**< Cleartext data. */ + soc_ecb_ciphertext_t ciphertext; /**< Ciphertext data. */ +} nrf_ecb_hal_data_t; + +/**@brief AES ECB block. Used to provide multiple blocks in a single call + to @ref sd_ecb_blocks_encrypt.*/ +typedef struct +{ + soc_ecb_key_t const * p_key; /**< Pointer to the Encryption key. */ + soc_ecb_cleartext_t const * p_cleartext; /**< Pointer to the Cleartext data. */ + soc_ecb_ciphertext_t * p_ciphertext; /**< Pointer to the Ciphertext data. */ +} nrf_ecb_hal_data_block_t; + +/**@} */ + +/**@addtogroup NRF_SOC_FUNCTIONS Functions + * @{ */ + +/**@brief Initialize a mutex. + * + * @param[in] p_mutex Pointer to the mutex to initialize. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_MUTEX_NEW, uint32_t, sd_mutex_new(nrf_mutex_t * p_mutex)); + +/**@brief Attempt to acquire a mutex. + * + * @param[in] p_mutex Pointer to the mutex to acquire. + * + * @retval ::NRF_SUCCESS The mutex was successfully acquired. + * @retval ::NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN The mutex could not be acquired. + */ +SVCALL(SD_MUTEX_ACQUIRE, uint32_t, sd_mutex_acquire(nrf_mutex_t * p_mutex)); + +/**@brief Release a mutex. + * + * @param[in] p_mutex Pointer to the mutex to release. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_MUTEX_RELEASE, uint32_t, sd_mutex_release(nrf_mutex_t * p_mutex)); + +/**@brief Query the capacity of the application random pool. + * + * @param[out] p_pool_capacity The capacity of the pool. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_RAND_APPLICATION_POOL_CAPACITY_GET, uint32_t, sd_rand_application_pool_capacity_get(uint8_t * p_pool_capacity)); + +/**@brief Get number of random bytes available to the application. + * + * @param[out] p_bytes_available The number of bytes currently available in the pool. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_RAND_APPLICATION_BYTES_AVAILABLE_GET, uint32_t, sd_rand_application_bytes_available_get(uint8_t * p_bytes_available)); + +/**@brief Get random bytes from the application pool. + * + * @param[out] p_buff Pointer to unit8_t buffer for storing the bytes. + * @param[in] length Number of bytes to take from pool and place in p_buff. + * + * @retval ::NRF_SUCCESS The requested bytes were written to p_buff. + * @retval ::NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES No bytes were written to the buffer, because there were not enough bytes available. +*/ +SVCALL(SD_RAND_APPLICATION_VECTOR_GET, uint32_t, sd_rand_application_vector_get(uint8_t * p_buff, uint8_t length)); + +/**@brief Gets the reset reason register. + * + * @param[out] p_reset_reason Contents of the NRF_POWER->RESETREAS register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RESET_REASON_GET, uint32_t, sd_power_reset_reason_get(uint32_t * p_reset_reason)); + +/**@brief Clears the bits of the reset reason register. + * + * @param[in] reset_reason_clr_msk Contains the bits to clear from the reset reason register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RESET_REASON_CLR, uint32_t, sd_power_reset_reason_clr(uint32_t reset_reason_clr_msk)); + +/**@brief Sets the power mode when in CPU sleep. + * + * @param[in] power_mode The power mode to use when in CPU sleep, see @ref NRF_POWER_MODES. @sa sd_app_evt_wait + * + * @retval ::NRF_SUCCESS The power mode was set. + * @retval ::NRF_ERROR_SOC_POWER_MODE_UNKNOWN The power mode was unknown. + */ +SVCALL(SD_POWER_MODE_SET, uint32_t, sd_power_mode_set(uint8_t power_mode)); + +/**@brief Puts the chip in System OFF mode. + * + * @retval ::NRF_ERROR_SOC_POWER_OFF_SHOULD_NOT_RETURN + */ +SVCALL(SD_POWER_SYSTEM_OFF, uint32_t, sd_power_system_off(void)); + +/**@brief Enables or disables the power-fail comparator. + * + * Enabling this will give a SoftDevice event (NRF_EVT_POWER_FAILURE_WARNING) when the power failure warning occurs. + * The event can be retrieved with sd_evt_get(); + * + * @param[in] pof_enable True if the power-fail comparator should be enabled, false if it should be disabled. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_POF_ENABLE, uint32_t, sd_power_pof_enable(uint8_t pof_enable)); + +/**@brief Enables or disables the USB power ready event. + * + * Enabling this will give a SoftDevice event (NRF_EVT_POWER_USB_POWER_READY) when a USB 3.3 V supply is ready. + * The event can be retrieved with sd_evt_get(); + * + * @param[in] usbpwrrdy_enable True if the power ready event should be enabled, false if it should be disabled. + * + * @note Calling this function on a chip without USBD peripheral will result in undefined behaviour. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_USBPWRRDY_ENABLE, uint32_t, sd_power_usbpwrrdy_enable(uint8_t usbpwrrdy_enable)); + +/**@brief Enables or disables the power USB-detected event. + * + * Enabling this will give a SoftDevice event (NRF_EVT_POWER_USB_DETECTED) when a voltage supply is detected on VBUS. + * The event can be retrieved with sd_evt_get(); + * + * @param[in] usbdetected_enable True if the power ready event should be enabled, false if it should be disabled. + * + * @note Calling this function on a chip without USBD peripheral will result in undefined behaviour. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_USBDETECTED_ENABLE, uint32_t, sd_power_usbdetected_enable(uint8_t usbdetected_enable)); + +/**@brief Enables or disables the power USB-removed event. + * + * Enabling this will give a SoftDevice event (NRF_EVT_POWER_USB_REMOVED) when a voltage supply is removed from VBUS. + * The event can be retrieved with sd_evt_get(); + * + * @param[in] usbremoved_enable True if the power ready event should be enabled, false if it should be disabled. + * + * @note Calling this function on a chip without USBD peripheral will result in undefined behaviour. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_USBREMOVED_ENABLE, uint32_t, sd_power_usbremoved_enable(uint8_t usbremoved_enable)); + +/**@brief Get USB supply status register content. + * + * @param[out] usbregstatus The content of USBREGSTATUS register. + * + * @note Calling this function on a chip without USBD peripheral will result in undefined behaviour. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_USBREGSTATUS_GET, uint32_t, sd_power_usbregstatus_get(uint32_t * usbregstatus)); + +/**@brief Sets the power failure comparator threshold value. + * + * @note: Power failure comparator threshold setting. This setting applies both for normal voltage + * mode (supply connected to both VDD and VDDH) and high voltage mode (supply connected to + * VDDH only). + * + * @param[in] threshold The power-fail threshold value to use, see @ref NRF_POWER_THRESHOLDS. + * + * @retval ::NRF_SUCCESS The power failure threshold was set. + * @retval ::NRF_ERROR_SOC_POWER_POF_THRESHOLD_UNKNOWN The power failure threshold is unknown. + */ +SVCALL(SD_POWER_POF_THRESHOLD_SET, uint32_t, sd_power_pof_threshold_set(uint8_t threshold)); + +/**@brief Sets the power failure comparator threshold value for high voltage. + * + * @note: Power failure comparator threshold setting for high voltage mode (supply connected to + * VDDH only). This setting does not apply for normal voltage mode (supply connected to both + * VDD and VDDH). + * + * @param[in] threshold The power-fail threshold value to use, see @ref NRF_POWER_THRESHOLDVDDHS. + * + * @retval ::NRF_SUCCESS The power failure threshold was set. + * @retval ::NRF_ERROR_SOC_POWER_POF_THRESHOLD_UNKNOWN The power failure threshold is unknown. + */ +SVCALL(SD_POWER_POF_THRESHOLDVDDH_SET, uint32_t, sd_power_pof_thresholdvddh_set(uint8_t threshold)); + +/**@brief Writes the NRF_POWER->RAM[index].POWERSET register. + * + * @param[in] index Contains the index in the NRF_POWER->RAM[index].POWERSET register to write to. + * @param[in] ram_powerset Contains the word to write to the NRF_POWER->RAM[index].POWERSET register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAM_POWER_SET, uint32_t, sd_power_ram_power_set(uint8_t index, uint32_t ram_powerset)); + +/**@brief Writes the NRF_POWER->RAM[index].POWERCLR register. + * + * @param[in] index Contains the index in the NRF_POWER->RAM[index].POWERCLR register to write to. + * @param[in] ram_powerclr Contains the word to write to the NRF_POWER->RAM[index].POWERCLR register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAM_POWER_CLR, uint32_t, sd_power_ram_power_clr(uint8_t index, uint32_t ram_powerclr)); + +/**@brief Get contents of NRF_POWER->RAM[index].POWER register, indicates power status of RAM[index] blocks. + * + * @param[in] index Contains the index in the NRF_POWER->RAM[index].POWER register to read from. + * @param[out] p_ram_power Content of NRF_POWER->RAM[index].POWER register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAM_POWER_GET, uint32_t, sd_power_ram_power_get(uint8_t index, uint32_t * p_ram_power)); + +/**@brief Set bits in the general purpose retention registers (NRF_POWER->GPREGRET*). + * + * @param[in] gpregret_id 0 for GPREGRET, 1 for GPREGRET2. + * @param[in] gpregret_msk Bits to be set in the GPREGRET register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_GPREGRET_SET, uint32_t, sd_power_gpregret_set(uint32_t gpregret_id, uint32_t gpregret_msk)); + +/**@brief Clear bits in the general purpose retention registers (NRF_POWER->GPREGRET*). + * + * @param[in] gpregret_id 0 for GPREGRET, 1 for GPREGRET2. + * @param[in] gpregret_msk Bits to be clear in the GPREGRET register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_GPREGRET_CLR, uint32_t, sd_power_gpregret_clr(uint32_t gpregret_id, uint32_t gpregret_msk)); + +/**@brief Get contents of the general purpose retention registers (NRF_POWER->GPREGRET*). + * + * @param[in] gpregret_id 0 for GPREGRET, 1 for GPREGRET2. + * @param[out] p_gpregret Contents of the GPREGRET register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_GPREGRET_GET, uint32_t, sd_power_gpregret_get(uint32_t gpregret_id, uint32_t *p_gpregret)); + +/**@brief Enable or disable the DC/DC regulator for the regulator stage 1 (REG1). + * + * @param[in] dcdc_mode The mode of the DCDC, see @ref NRF_POWER_DCDC_MODES. + * + * @retval ::NRF_SUCCESS + * @retval ::NRF_ERROR_INVALID_PARAM The DCDC mode is invalid. + */ +SVCALL(SD_POWER_DCDC_MODE_SET, uint32_t, sd_power_dcdc_mode_set(uint8_t dcdc_mode)); + +/**@brief Enable or disable the DC/DC regulator for the regulator stage 0 (REG0). + * + * For more details on the REG0 stage, please see product specification. + * + * @param[in] dcdc_mode The mode of the DCDC0, see @ref NRF_POWER_DCDC_MODES. + * + * @retval ::NRF_SUCCESS + * @retval ::NRF_ERROR_INVALID_PARAM The dcdc_mode is invalid. + */ +SVCALL(SD_POWER_DCDC0_MODE_SET, uint32_t, sd_power_dcdc0_mode_set(uint8_t dcdc_mode)); + +/**@brief Request the high frequency crystal oscillator. + * + * Will start the high frequency crystal oscillator, the startup time of the crystal varies + * and the ::sd_clock_hfclk_is_running function can be polled to check if it has started. + * + * @see sd_clock_hfclk_is_running + * @see sd_clock_hfclk_release + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_CLOCK_HFCLK_REQUEST, uint32_t, sd_clock_hfclk_request(void)); + +/**@brief Releases the high frequency crystal oscillator. + * + * Will stop the high frequency crystal oscillator, this happens immediately. + * + * @see sd_clock_hfclk_is_running + * @see sd_clock_hfclk_request + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_CLOCK_HFCLK_RELEASE, uint32_t, sd_clock_hfclk_release(void)); + +/**@brief Checks if the high frequency crystal oscillator is running. + * + * @see sd_clock_hfclk_request + * @see sd_clock_hfclk_release + * + * @param[out] p_is_running 1 if the external crystal oscillator is running, 0 if not. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_CLOCK_HFCLK_IS_RUNNING, uint32_t, sd_clock_hfclk_is_running(uint32_t * p_is_running)); + +/**@brief Waits for an application event. + * + * An application event is either an application interrupt or a pended interrupt when the interrupt + * is disabled. + * + * When the application waits for an application event by calling this function, an interrupt that + * is enabled will be taken immediately on pending since this function will wait in thread mode, + * then the execution will return in the application's main thread. + * + * In order to wake up from disabled interrupts, the SEVONPEND flag has to be set in the Cortex-M + * MCU's System Control Register (SCR), CMSIS_SCB. In that case, when a disabled interrupt gets + * pended, this function will return to the application's main thread. + * + * @note The application must ensure that the pended flag is cleared using ::sd_nvic_ClearPendingIRQ + * in order to sleep using this function. This is only necessary for disabled interrupts, as + * the interrupt handler will clear the pending flag automatically for enabled interrupts. + * + * @note If an application interrupt has happened since the last time sd_app_evt_wait was + * called this function will return immediately and not go to sleep. This is to avoid race + * conditions that can occur when a flag is updated in the interrupt handler and processed + * in the main loop. + * + * @post An application interrupt has happened or a interrupt pending flag is set. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_APP_EVT_WAIT, uint32_t, sd_app_evt_wait(void)); + +/**@brief Get PPI channel enable register contents. + * + * @param[out] p_channel_enable The contents of the PPI CHEN register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_CHANNEL_ENABLE_GET, uint32_t, sd_ppi_channel_enable_get(uint32_t * p_channel_enable)); + +/**@brief Set PPI channel enable register. + * + * @param[in] channel_enable_set_msk Mask containing the bits to set in the PPI CHEN register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_CHANNEL_ENABLE_SET, uint32_t, sd_ppi_channel_enable_set(uint32_t channel_enable_set_msk)); + +/**@brief Clear PPI channel enable register. + * + * @param[in] channel_enable_clr_msk Mask containing the bits to clear in the PPI CHEN register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_CHANNEL_ENABLE_CLR, uint32_t, sd_ppi_channel_enable_clr(uint32_t channel_enable_clr_msk)); + +/**@brief Assign endpoints to a PPI channel. + * + * @param[in] channel_num Number of the PPI channel to assign. + * @param[in] evt_endpoint Event endpoint of the PPI channel. + * @param[in] task_endpoint Task endpoint of the PPI channel. + * + * @retval ::NRF_ERROR_SOC_PPI_INVALID_CHANNEL The channel number is invalid. + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_CHANNEL_ASSIGN, uint32_t, sd_ppi_channel_assign(uint8_t channel_num, const volatile void * evt_endpoint, const volatile void * task_endpoint)); + +/**@brief Task to enable a channel group. + * + * @param[in] group_num Number of the channel group. + * + * @retval ::NRF_ERROR_SOC_PPI_INVALID_GROUP The group number is invalid + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_GROUP_TASK_ENABLE, uint32_t, sd_ppi_group_task_enable(uint8_t group_num)); + +/**@brief Task to disable a channel group. + * + * @param[in] group_num Number of the PPI group. + * + * @retval ::NRF_ERROR_SOC_PPI_INVALID_GROUP The group number is invalid. + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_GROUP_TASK_DISABLE, uint32_t, sd_ppi_group_task_disable(uint8_t group_num)); + +/**@brief Assign PPI channels to a channel group. + * + * @param[in] group_num Number of the channel group. + * @param[in] channel_msk Mask of the channels to assign to the group. + * + * @retval ::NRF_ERROR_SOC_PPI_INVALID_GROUP The group number is invalid. + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_GROUP_ASSIGN, uint32_t, sd_ppi_group_assign(uint8_t group_num, uint32_t channel_msk)); + +/**@brief Gets the PPI channels of a channel group. + * + * @param[in] group_num Number of the channel group. + * @param[out] p_channel_msk Mask of the channels assigned to the group. + * + * @retval ::NRF_ERROR_SOC_PPI_INVALID_GROUP The group number is invalid. + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_GROUP_GET, uint32_t, sd_ppi_group_get(uint8_t group_num, uint32_t * p_channel_msk)); + +/**@brief Configures the Radio Notification signal. + * + * @note + * - The notification signal latency depends on the interrupt priority settings of SWI used + * for notification signal. + * - To ensure that the radio notification signal behaves in a consistent way, the radio + * notifications must be configured when there is no protocol stack or other SoftDevice + * activity in progress. It is recommended that the radio notification signal is + * configured directly after the SoftDevice has been enabled. + * - In the period between the ACTIVE signal and the start of the Radio Event, the SoftDevice + * will interrupt the application to do Radio Event preparation. + * - Using the Radio Notification feature may limit the bandwidth, as the SoftDevice may have + * to shorten the connection events to have time for the Radio Notification signals. + * + * @param[in] type Type of notification signal, see @ref NRF_RADIO_NOTIFICATION_TYPES. + * @ref NRF_RADIO_NOTIFICATION_TYPE_NONE shall be used to turn off radio + * notification. Using @ref NRF_RADIO_NOTIFICATION_DISTANCE_NONE is + * recommended (but not required) to be used with + * @ref NRF_RADIO_NOTIFICATION_TYPE_NONE. + * + * @param[in] distance Distance between the notification signal and start of radio activity, see @ref NRF_RADIO_NOTIFICATION_DISTANCES. + * This parameter is ignored when @ref NRF_RADIO_NOTIFICATION_TYPE_NONE or + * @ref NRF_RADIO_NOTIFICATION_TYPE_INT_ON_INACTIVE is used. + * + * @retval ::NRF_ERROR_INVALID_PARAM The group number is invalid. + * @retval ::NRF_ERROR_INVALID_STATE A protocol stack or other SoftDevice is running. Stop all + * running activities and retry. + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_RADIO_NOTIFICATION_CFG_SET, uint32_t, sd_radio_notification_cfg_set(uint8_t type, uint8_t distance)); + +/**@brief Encrypts a block according to the specified parameters. + * + * 128-bit AES encryption. + * + * @note: + * - The application may set the SEVONPEND bit in the SCR to 1 to make the SoftDevice sleep while + * the ECB is running. The SEVONPEND bit should only be cleared (set to 0) from application + * main or low interrupt level. + * + * @param[in, out] p_ecb_data Pointer to the ECB parameters' struct (two input + * parameters and one output parameter). + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_ECB_BLOCK_ENCRYPT, uint32_t, sd_ecb_block_encrypt(nrf_ecb_hal_data_t * p_ecb_data)); + +/**@brief Encrypts multiple data blocks provided as an array of data block structures. + * + * @details: Performs 128-bit AES encryption on multiple data blocks + * + * @note: + * - The application may set the SEVONPEND bit in the SCR to 1 to make the SoftDevice sleep while + * the ECB is running. The SEVONPEND bit should only be cleared (set to 0) from application + * main or low interrupt level. + * + * @param[in] block_count Count of blocks in the p_data_blocks array. + * @param[in,out] p_data_blocks Pointer to the first entry in a contiguous array of + * @ref nrf_ecb_hal_data_block_t structures. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_ECB_BLOCKS_ENCRYPT, uint32_t, sd_ecb_blocks_encrypt(uint8_t block_count, nrf_ecb_hal_data_block_t * p_data_blocks)); + +/**@brief Gets any pending events generated by the SoC API. + * + * The application should keep calling this function to get events, until ::NRF_ERROR_NOT_FOUND is returned. + * + * @param[out] p_evt_id Set to one of the values in @ref NRF_SOC_EVTS, if any events are pending. + * + * @retval ::NRF_SUCCESS An event was pending. The event id is written in the p_evt_id parameter. + * @retval ::NRF_ERROR_NOT_FOUND No pending events. + */ +SVCALL(SD_EVT_GET, uint32_t, sd_evt_get(uint32_t * p_evt_id)); + +/**@brief Get the temperature measured on the chip + * + * This function will block until the temperature measurement is done. + * It takes around 50 us from call to return. + * + * @param[out] p_temp Result of temperature measurement. Die temperature in 0.25 degrees Celsius. + * + * @retval ::NRF_SUCCESS A temperature measurement was done, and the temperature was written to temp + */ +SVCALL(SD_TEMP_GET, uint32_t, sd_temp_get(int32_t * p_temp)); + +/**@brief Flash Write +* +* Commands to write a buffer to flash +* +* If the SoftDevice is enabled: +* This call initiates the flash access command, and its completion will be communicated to the +* application with exactly one of the following events: +* - @ref NRF_EVT_FLASH_OPERATION_SUCCESS - The command was successfully completed. +* - @ref NRF_EVT_FLASH_OPERATION_ERROR - The command could not be started. +* +* If the SoftDevice is not enabled no event will be generated, and this call will return @ref NRF_SUCCESS when the + * write has been completed +* +* @note +* - This call takes control over the radio and the CPU during flash erase and write to make sure that +* they will not interfere with the flash access. This means that all interrupts will be blocked +* for a predictable time (depending on the NVMC specification in the device's Product Specification +* and the command parameters). +* - The data in the p_src buffer should not be modified before the @ref NRF_EVT_FLASH_OPERATION_SUCCESS +* or the @ref NRF_EVT_FLASH_OPERATION_ERROR have been received if the SoftDevice is enabled. +* - This call will make the SoftDevice trigger a hardfault when the page is written, if it is +* protected. +* +* +* @param[in] p_dst Pointer to start of flash location to be written. +* @param[in] p_src Pointer to buffer with data to be written. +* @param[in] size Number of 32-bit words to write. Maximum size is the number of words in one +* flash page. See the device's Product Specification for details. +* +* @retval ::NRF_ERROR_INVALID_ADDR Tried to write to a non existing flash address, or p_dst or p_src was unaligned. +* @retval ::NRF_ERROR_BUSY The previous command has not yet completed. +* @retval ::NRF_ERROR_INVALID_LENGTH Size was 0, or higher than the maximum allowed size. +* @retval ::NRF_ERROR_FORBIDDEN Tried to write to an address outside the application flash area. +* @retval ::NRF_SUCCESS The command was accepted. +*/ +SVCALL(SD_FLASH_WRITE, uint32_t, sd_flash_write(uint32_t * p_dst, uint32_t const * p_src, uint32_t size)); + + +/**@brief Flash Erase page +* +* Commands to erase a flash page +* If the SoftDevice is enabled: +* This call initiates the flash access command, and its completion will be communicated to the +* application with exactly one of the following events: +* - @ref NRF_EVT_FLASH_OPERATION_SUCCESS - The command was successfully completed. +* - @ref NRF_EVT_FLASH_OPERATION_ERROR - The command could not be started. +* +* If the SoftDevice is not enabled no event will be generated, and this call will return @ref NRF_SUCCESS when the +* erase has been completed +* +* @note +* - This call takes control over the radio and the CPU during flash erase and write to make sure that +* they will not interfere with the flash access. This means that all interrupts will be blocked +* for a predictable time (depending on the NVMC specification in the device's Product Specification +* and the command parameters). +* - This call will make the SoftDevice trigger a hardfault when the page is erased, if it is +* protected. +* +* +* @param[in] page_number Page number of the page to erase +* +* @retval ::NRF_ERROR_INTERNAL If a new session could not be opened due to an internal error. +* @retval ::NRF_ERROR_INVALID_ADDR Tried to erase to a non existing flash page. +* @retval ::NRF_ERROR_BUSY The previous command has not yet completed. +* @retval ::NRF_ERROR_FORBIDDEN Tried to erase a page outside the application flash area. +* @retval ::NRF_SUCCESS The command was accepted. +*/ +SVCALL(SD_FLASH_PAGE_ERASE, uint32_t, sd_flash_page_erase(uint32_t page_number)); + + + +/**@brief Opens a session for radio timeslot requests. + * + * @note Only one session can be open at a time. + * @note p_radio_signal_callback(@ref NRF_RADIO_CALLBACK_SIGNAL_TYPE_START) will be called when the radio timeslot + * starts. From this point the NRF_RADIO and NRF_TIMER0 peripherals can be freely accessed + * by the application. + * @note p_radio_signal_callback(@ref NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0) is called whenever the NRF_TIMER0 + * interrupt occurs. + * @note p_radio_signal_callback(@ref NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO) is called whenever the NRF_RADIO + * interrupt occurs. + * @note p_radio_signal_callback() will be called at ARM interrupt priority level 0. This + * implies that none of the sd_* API calls can be used from p_radio_signal_callback(). + * + * @param[in] p_radio_signal_callback The signal callback. + * + * @retval ::NRF_ERROR_INVALID_ADDR p_radio_signal_callback is an invalid function pointer. + * @retval ::NRF_ERROR_BUSY If session cannot be opened. + * @retval ::NRF_ERROR_INTERNAL If a new session could not be opened due to an internal error. + * @retval ::NRF_SUCCESS Otherwise. + */ + SVCALL(SD_RADIO_SESSION_OPEN, uint32_t, sd_radio_session_open(nrf_radio_signal_callback_t p_radio_signal_callback)); + +/**@brief Closes a session for radio timeslot requests. + * + * @note Any current radio timeslot will be finished before the session is closed. + * @note If a radio timeslot is scheduled when the session is closed, it will be canceled. + * @note The application cannot consider the session closed until the @ref NRF_EVT_RADIO_SESSION_CLOSED + * event is received. + * + * @retval ::NRF_ERROR_FORBIDDEN If session not opened. + * @retval ::NRF_ERROR_BUSY If session is currently being closed. + * @retval ::NRF_SUCCESS Otherwise. + */ + SVCALL(SD_RADIO_SESSION_CLOSE, uint32_t, sd_radio_session_close(void)); + +/**@brief Requests a radio timeslot. + * + * @note The request type is determined by p_request->request_type, and can be one of @ref NRF_RADIO_REQ_TYPE_EARLIEST + * and @ref NRF_RADIO_REQ_TYPE_NORMAL. The first request in a session must always be of type @ref NRF_RADIO_REQ_TYPE_EARLIEST. + * @note For a normal request (@ref NRF_RADIO_REQ_TYPE_NORMAL), the start time of a radio timeslot is specified by + * p_request->distance_us and is given relative to the start of the previous timeslot. + * @note A too small p_request->distance_us will lead to a @ref NRF_EVT_RADIO_BLOCKED event. + * @note Timeslots scheduled too close will lead to a @ref NRF_EVT_RADIO_BLOCKED event. + * @note See the SoftDevice Specification for more on radio timeslot scheduling, distances and lengths. + * @note If an opportunity for the first radio timeslot is not found before 100 ms after the call to this + * function, it is not scheduled, and instead a @ref NRF_EVT_RADIO_BLOCKED event is sent. + * The application may then try to schedule the first radio timeslot again. + * @note Successful requests will result in nrf_radio_signal_callback_t(@ref NRF_RADIO_CALLBACK_SIGNAL_TYPE_START). + * Unsuccessful requests will result in a @ref NRF_EVT_RADIO_BLOCKED event, see @ref NRF_SOC_EVTS. + * @note The jitter in the start time of the radio timeslots is +/- @ref NRF_RADIO_START_JITTER_US us. + * @note The nrf_radio_signal_callback_t(@ref NRF_RADIO_CALLBACK_SIGNAL_TYPE_START) call has a latency relative to the + * specified radio timeslot start, but this does not affect the actual start time of the timeslot. + * @note NRF_TIMER0 is reset at the start of the radio timeslot, and is clocked at 1MHz from the high frequency + * (16 MHz) clock source. If p_request->hfclk_force_xtal is true, the high frequency clock is + * guaranteed to be clocked from the external crystal. + * @note The SoftDevice will neither access the NRF_RADIO peripheral nor the NRF_TIMER0 peripheral + * during the radio timeslot. + * + * @param[in] p_request Pointer to the request parameters. + * + * @retval ::NRF_ERROR_FORBIDDEN Either: + * - The session is not open. + * - The session is not IDLE. + * - This is the first request and its type is not @ref NRF_RADIO_REQ_TYPE_EARLIEST. + * - The request type was set to @ref NRF_RADIO_REQ_TYPE_NORMAL after a + * @ref NRF_RADIO_REQ_TYPE_EARLIEST request was blocked. + * @retval ::NRF_ERROR_INVALID_ADDR If the p_request pointer is invalid. + * @retval ::NRF_ERROR_INVALID_PARAM If the parameters of p_request are not valid. + * @retval ::NRF_SUCCESS Otherwise. + */ + SVCALL(SD_RADIO_REQUEST, uint32_t, sd_radio_request(nrf_radio_request_t const * p_request)); + +/**@brief Write register protected by the SoftDevice + * + * This function writes to a register that is write-protected by the SoftDevice. Please refer to your + * SoftDevice Specification for more details about which registers that are protected by SoftDevice. + * This function can write to the following protected peripheral: + * - ACL + * + * @note Protected registers may be read directly. + * @note Register that are write-once will return @ref NRF_SUCCESS on second set, even the value in + * the register has not changed. See the Product Specification for more details about register + * properties. + * + * @param[in] p_register Pointer to register to be written. + * @param[in] value Value to be written to the register. + * + * @retval ::NRF_ERROR_INVALID_ADDR This function can not write to the reguested register. + * @retval ::NRF_SUCCESS Value successfully written to register. + * + */ +SVCALL(SD_PROTECTED_REGISTER_WRITE, uint32_t, sd_protected_register_write(volatile uint32_t * p_register, uint32_t value)); + +/**@} */ + +#ifdef __cplusplus +} +#endif +#endif // NRF_SOC_H__ + +/**@} */ diff --git a/components/softdevice/s140/headers/nrf_svc.h b/components/softdevice/s140/headers/nrf_svc.h new file mode 100644 index 0000000..231a54f --- /dev/null +++ b/components/softdevice/s140/headers/nrf_svc.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2012 - 2019, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NRF_SVC__ +#define NRF_SVC__ + +#include "stdint.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Supervisor call declaration. + * + * A call to a function marked with @ref SVCALL, will trigger a Supervisor Call (SVC) Exception. + * The SVCs with SVC numbers 0x00-0x0F are forwared to the application. All other SVCs are handled by the SoftDevice. + * + * @param[in] number The SVC number to be used. + * @param[in] return_type The return type of the SVC function. + * @param[in] signature Function signature. The function can have at most four arguments. + */ + +#ifdef SVCALL_AS_NORMAL_FUNCTION +#define SVCALL(number, return_type, signature) return_type signature +#else + +#ifndef SVCALL +#if defined (__CC_ARM) +#define SVCALL(number, return_type, signature) return_type __svc(number) signature +#elif defined (__GNUC__) +#ifdef __cplusplus +#define GCC_CAST_CPP (uint16_t) +#else +#define GCC_CAST_CPP +#endif +#define SVCALL(number, return_type, signature) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wreturn-type\"") \ + __attribute__((naked)) \ + __attribute__((unused)) \ + static return_type signature \ + { \ + __asm( \ + "svc %0\n" \ + "bx r14" : : "I" (GCC_CAST_CPP number) : "r0" \ + ); \ + } \ + _Pragma("GCC diagnostic pop") + +#elif defined (__ICCARM__) +#define PRAGMA(x) _Pragma(#x) +#define SVCALL(number, return_type, signature) \ +PRAGMA(swi_number = (number)) \ + __swi return_type signature; +#else +#define SVCALL(number, return_type, signature) return_type signature +#endif +#endif // SVCALL + +#endif // SVCALL_AS_NORMAL_FUNCTION + +#ifdef __cplusplus +} +#endif +#endif // NRF_SVC__ diff --git a/components/softdevice/s140/hex/s140_nrf52_7.2.0_licence-agreement.txt b/components/softdevice/s140/hex/s140_nrf52_7.2.0_licence-agreement.txt new file mode 100644 index 0000000..8ac5192 --- /dev/null +++ b/components/softdevice/s140/hex/s140_nrf52_7.2.0_licence-agreement.txt @@ -0,0 +1,35 @@ +Copyright (c) 2007 - 2020, Nordic Semiconductor ASA +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form, except as embedded into a Nordic + Semiconductor ASA integrated circuit in a product or a software update for + such product, must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +3. Neither the name of Nordic Semiconductor ASA nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +4. This software, with or without modification, must only be used with a + Nordic Semiconductor ASA integrated circuit. + +5. Any software provided in binary form under this license must not be reverse + engineered, decompiled, modified and/or disassembled. + +THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/data/260311 VesiScan-Basic_VB0HW0100_Firmware Dev 버전 개발 사양.md b/data/260311 VesiScan-Basic_VB0HW0100_Firmware Dev 버전 개발 사양.md new file mode 100644 index 0000000..0a372bf --- /dev/null +++ b/data/260311 VesiScan-Basic_VB0HW0100_Firmware Dev 버전 개발 사양.md @@ -0,0 +1,342 @@ +# VB0HW0100 — Firmware Dev. 버전 개발 사양서 + +## 1. 시스템 개요 + +### 1-1. 보드 기능 + +초음파 방광 모니터링을 위한 웨어러블 디바이스. +6채널 Piezo 트랜스듀서를 순차 구동하여 A-mode 초음파 측정을 수행하고, BLE를 통해 데이터를 전송한다. +Dev. 버전은 모든 명령이 앱에서 내려지도록 개발. + +### 1-2. 기능 블록 구분 + +| 블록 | 명칭 | 주요 IC | 역할 | +|------|------|---------|------| +| 제어부 | Control | nRF52840 (U26) | MCU, BLE, 전체 제어 | +| | | W25Q32 (U16) | Flash Memory (데이터 저장) | +| | | ICM-42670 (U10) | IMU 센서 (6축) | +| TX | Transmit | MD1822 (U27) | MOSFET Driver | +| | | TC7920 (U30) | MOSFET (고전압 스위칭) | +| | | MAX14778 (U31) | 8채널 MUX (채널 선택) | +| | | Misc | TMP235 (U22) | 온도 센서 | +| RX | Receive | MD0100 (U34) | T/R 스위치 (수신 보호) | +| | | OPA2836 (U2) | 2단 수신 증폭기 | +| | | ADL5513 (U23) | 로그 디텍터 (AGC) | +| | | ADC121S051 (U37) | 12비트 SPI ADC | +| 전원 | Power | MIC5528 (U5) | LDO → +3.3V_M (제어부) | +| | | MIC5528 (U42) | LDO → +3.3V_PZT_TX (TX) | +| | | MIC5528 (U41) | LDO → +3.3V_PZT_RX (RX) | +| | | LT3463 (U32) | DC-DC → ±25V (펄서 전원) | +| | | MCP1804 (U33) | LDO → +10V | +| | | LM27762 (U38) | Charge Pump → ±2.75V (Op-Amp 전원) | +| | | MCP73838 (U3) | 배터리 충전 IC | + +### 1-3. 신호 흐름 + +``` +[TX 경로] +nRF52840 → MD1822 (Driver) → TC7920 (MOSFET) → MAX14778 (MUX) → Piezo (6ch 중 1개) + +[RX 경로] +Piezo (6ch 중 1개) → MAX14778 (MUX) → MD0100 (T/R 보호) → OPA2836 (2단 증폭) → ADL5513 (로그 디텍터) → ADC121S051 → nRF52840 +``` + +--- + +## 2. 전원 시퀀싱 + +### 2-1. 전원 도메인 + +| 도메인 | 전원넷 | LDO | Enable 신호 | 공급 대상 | +|--------|--------|-----|-------------|-----------| +| 제어부 | +3.3V_M | U5 (MIC5528) | PWR_MCU_EN | nRF52840, W25Q32, ICM-42670 | +| TX | +3.3V_PZT_TX | U42 (MIC5528) | PZT_PWR_EN | 펄서 관련 회로 (MD1822, TC7920 등) | +| RX | +3.3V_PZT_RX | U41 (MIC5528) | PZT_PWR_EN | 수신 회로 (OPA2836, ADC121S051 등) | + +- TX와 RX는 **동일한 PZT_PWR_EN** 신호로 동시에 ON/OFF + +### 2-2. 전원 켜기 (Power ON) + +1. 사용자가 **SW2**를 누름 +2. PWR_MCU_EN = **High** → U5 활성화 → +3.3V_M 출력 +3. nRF52840 부팅 시작 +4. MCU가 SW2 눌림 상태를 확인하며 **2초간** 유지 여부 판단 +5. 조건 충족 시 MCU가 **PWR_HOLD = High** 출력 → 자기유지 (Self-Latch) +6. 이후 SW2를 놓아도 전원 유지됨 + +### 2-3. 전원 끄기 (Power OFF) + +1. MCU는 **BUTTON_CHECK** 핀으로 SW2 상태를 상시 감시 +2. SW2가 **3초간** 눌림 유지 감지 +3. MCU가 **PWR_HOLD = Low** 출력 +4. U5 이네이블 해제 → +3.3V_M 차단 → 전체 전원 OFF + +### 2-4. 동작 모드 + +| 모드 | 제어부 (+3.3V_M) | TX (+3.3V_PZT_TX) | RX (+3.3V_PZT_RX) | 설명 | +|------|:-:|:-:|:-:|------| +| **Sleep Mode** | ON | OFF | OFF | 모든 IC 저전력 모드 동작, MCU BLE 유지, 명령 대기 | +| **Active Mode** | ON | ON | ON | 초음파 측정 가능 상태 | + +- Sleep → Active: MCU가 **PZT_PWR_EN = High** +- Active → Sleep: MCU가 **PZT_PWR_EN = Low** +- 기본 상태는 항상 **Sleep Mode** +- W25Q32와 ICM-42670는 초기설정을 **Deep Power-Down** 모드로 세팅 +- 모든 측정 후에는 항상 **Sleep Mode**로 복귀 +--- + +## 3. 측정 명령 + +### 3-1. 측정 명령 종류 + +| 측정 명령 | 측정 대상 | 필요 모드 | 비고 | +|-----------|-----------|:-:|------| +| 배터리 전압 측정 | ADC_BAT | Sleep | +3.3V_M 도메인, Active 전환 불필요 | +| IMU 측정 | ICM-42670 (I2C) | Sleep | +3.3V_M 도메인, Active 전환 불필요 | +| 온도 측정 | TMP235 (ADC_TEMP) | **Active** | TX/RX 전원 필요 | +| 초음파 측정 | Piezo 6ch | **Active** | TX/RX 전원 필요 | +| 모두 측정 | 전체 | **Active** | TX/RX 전원 필요 | + +- + +### 3-2. 명령별 동작 흐름 + +**Sleep Mode에서 처리 (Active 전환 불필요)** + +``` +배터리 측정 명령 → 동작모드 전환 → ADC_BAT 읽기 → BLE 전송 → Deep Power-Down 모드 전환 +IMU 측정 명령 → 동작모드 전환 → I2C로 ICM-42670 읽기 → BLE 전송 → Deep Power-Down 모드 또는 필요 모드 전환 +``` + +**Active Mode 필요** + +``` +온도 측정 명령 → Active 진입 → ADC_TEMP 읽기 → BLE 전송 → Sleep 복귀 +초음파 측정 명령 → Active 진입 → 6ch 스캔 → BLE 전송 → Sleep 복귀 +모두 측정 명령 → Active 진입 → 배터리 + IMU + 온도 + 초음파 → BLE 전송 → Sleep 복귀 +``` + +--- + +## 4. Piezo 초음파 측정 + +### 4-1. 측정 파라미터 + +| 파라미터 | 범위 | 설명 | +|----------|------|------| +| Frequency | 1.8 / 1.9 / 2.0 / 2.1 / 2.2 MHz | 송신 펄스 주파수 | +| Cycle | 3 ~ 7 | 송신 펄스 사이클 수 | +| 평균화 수 (Avg) | 1 ~ 10 | 채널당 반복 측정 횟수 | +| 측정 Channel 개수 (N) | 1 ~ 6 | 측정 대상 채널 수 | +| 대기 시간 (Delay) | 0~30 (default: 10) | TX 펄수 출력 후 ADC 시작 시까지 대기 시간 (μs) | +| 측정 샘플 수 (Num_samples) | 80 ~ 140 | 측정 ADC 샘플 개수 | + +### 4-2. 채널 정의 + +- 총 **6채널**: CH0, CH1, CH2, CH3, CH4, CH5 +- Channel 개수 = N이면 **CH0 ~ CH(N-1)** 을 순차 측정 +- 예: N=4 → CH0, CH1, CH2, CH3만 측정 + +### 4-3. 평균화 동작 + +각 채널별로 평균화 수(Avg)만큼 반복 측정한 후, 평균값을 해당 채널의 최종 측정값으로 사용한다. + +예: Avg=5, N=3인 경우 + +``` +CH0: 측정①②③④⑤ → 평균 → CH0 최종값 +CH1: 측정①②③④⑤ → 평균 → CH1 최종값 +CH2: 측정①②③④⑤ → 평균 → CH2 최종값 +``` + +### 4-4. TX 송신 절차 + +1. **MAX14778 (MUX)** 채널 선택 (해당 Piezo 연결) +2. **1.3ms 대기** (MAX14778 채널 스위칭 안정화 시간) +3. **PZT_PE = High** (펄서 활성화) +4. **MD1822**에 설정된 Frequency / Cycle로 펄스 신호 입력 +5. **TC7920 (MOSFET)** 이 ±25V 펄스를 Piezo에 인가 + +| 관련 핀/넷 | 연결 | +|------------|------| +| PZT_CH_SEL0 | U26.A20 → U31 (MUX 채널 선택 비트 0) | +| PZT_CH_SEL1 | U26.B11 → U31 (MUX 채널 선택 비트 1) | +| PZT_EN_MUXA | U26.AC17 → U31 (MUX A 활성화) | +| PZT_EN_MUXB | U26.AC19 → U31 (MUX B 활성화) | +| PZT_PE | U26.AC21 → U27.15 (펄서 이네이블) | +| PZT_P_PULSE | U26.P23 → R30 (48.7Ω) → U27 (양의 펄스) | +| PZT_N_PULSE | U26.R24 → R40 (48.7Ω) → U27 (음의 펄스) | +| PZT_DMP | U26.AD22 → R12 (48.7Ω) → U27 (댐핑 제어) | + +### 4-5. RX 수신 절차 + +1. TX 펄스 출력 후 약 **10μs 대기** (근거리 잔향 회피) +2. 에코 신호 경로: + Piezo → MAX14778 (MUX) → MD0100 (T/R 보호) → OPA2836 (2단 증폭, 총 ~40dB) → ADL5513 (로그 디텍터) +3. **ADC121S051**에서 약 **300μs 동안** ADC 값 연속 수집 +4. MCU가 SPI를 통해 ADC 데이터 읽기 + +| 관련 핀/넷 | 연결 | +|------------|------| +| \PZT_SPI_CS | U26.AC15 → U37 (ADC 칩셀렉트) | +| SPI_SCK | U26.AC9 (Flash와 공유) | +| SPI_MISO | U26.AD10 (Flash와 공유) | + +### 4-6. 단일 측정 타이밍 + +``` +|←── TX ──→|← 10μs →|←─────── 300μs RX 수집 ───────→| + 펄스 출력 대기 ADC121S051 연속 샘플링 +``` + +### 4-7. 전체 스캔 시퀀스 (예: Avg=5, N=3) + +``` +측정 명령 수신 +│ +▼ +Active Mode 진입 (PZT_PWR_EN = High) +│ +├─ CH0 선택 (MUX → A0) → 1.3ms 대기 +│ ├─ 1회: TX → 10μs → 300μs RX +│ ├─ 2회: TX → 10μs → 300μs RX +│ ├─ 3회: TX → 10μs → 300μs RX +│ ├─ 4회: TX → 10μs → 300μs RX +│ └─ 5회: TX → 10μs → 300μs RX +│ → CH0 평균값 산출 +│ +├─ CH1 선택 (MUX → A1) → 1.3ms 대기 +│ └─ 5회 반복 → CH1 평균값 산출 +│ +├─ CH2 선택 (MUX → A2) → 1.3ms 대기 +│ └─ 5회 반복 → CH2 평균값 산출 +│ +▼ +BLE 전송 +│ +▼ +Sleep Mode 복귀 (PZT_PWR_EN = Low) +``` + +--- + +## 5. 참고 사항 + +### 5-1. 배터리 전압 측정 + +- R28 (806kΩ) / R29 (2MΩ) 분압 → ADC_BAT +- 분압비: 2M / (806k + 2M) ≈ 0.713 +- nRF52840 내장 ADC로 읽기 + +### 5-2. 충전 / 동작 상태 표시 LED + +| LED | 색상 | 연결 네트 | 상태 | 표시 | +|-----|------|------|------|------| +| LED1 | 오렌지 | U3.STAT1 | 충전중 | 상시 점등 | +| LED2 | 블루 | U3.STAT2 | 충전 완료 | 상시 점등 | +| LED3 | 초록 | LED_BLE | BLE Advertising | 1초 간격 점멸 | +| LED3 | 초록 | LED_BLE | BLE 연결 후, Piezo 초음파 측정 후 복부 부착으로 감지된 경우 | 소등 | +| LED3 | 초록 | LED_BLE | Piezo 초음파 측정 후 탈착으로 감지된 경우 | 점등 1초 소등 3초 반복 | +| LED4 | 오렌지 | FUNCTION_LED | 기기 정렬모드에서 방광위치를 탐지하지 못하고 있을 경우 | 1초 간격 점멸 | +| LED3 | 초록 | LED_BLE | 기기 정렬모드에서 방광위치를 탐지하고 있을 경우 | 점등 3초 소등 1초 반복 | + +- 기기 정렬 모드 : 빠른 주기로 초음파 측정 +- 복부 부착, 탈착, 방광위치 탐지 유무는 앱에서 판단, LED 동작 모드 명령 송신 + +### 5-3. 펄서 고전압 전원 + +| 전원 | 생성 IC | 전압 | 용도 | +|------|---------|------|------| +| PZT_+25V | LT3463 (U32) | +25V | 양의 펄스 전압 | +| PZT_-25V | LT3463 (U32) | -25V | 음의 펄스 전압 | +| PZT_+10V | MCP1804 (U33) | +10V | MD1822 공급 전원 | + +### 5-4. 수신부 아날로그 전원 + +| 전원 | 생성 IC | 전압 | 용도 | +|------|---------|------|------| +| +2.75V_CP | LM27762 (U38) | +2.75V | OPA2836 양전원 | +| -2.75V_CP | LM27762 (U38) | -2.75V | OPA2836 음전원 | + +### 5-5. DFU 관련 주의사항 + +- nRF52840 DFU(Device Firmware Update) 부트로더에서 **P0.25를 사용하지 않도록** 수정 필요 +- 기본 DFU 부트로더가 P0.25를 버튼 입력 등으로 사용할 수 있으므로, 커스텀 DFU 빌드 시 해당 핀 설정을 제거 또는 변경할 것 + +### 5-6. MAX14778 채널 스위칭 지연 + +- MAX14778 채널 전환 후 신호 경로가 안정되기까지 **1.3ms delay** 필요 +- MUX_SelectChannel() 호출 후 반드시 1.3ms 대기 후 TX 펄스를 출력할 것 +- 동일 채널 내 반복 측정 시에는 추가 delay 불필요 (채널 전환 시에만 적용) + +--- + +## 6. 전력 절감 방안 + +### 6-1. Sleep Mode 소비 전류 줄이기 + +Sleep Mode에서 +3.3V_M에 상시 전원을 받는 IC는 3개이며, 각각에 대해 저전력 제어가 가능하다. + +**nRF52840 (MCU)** + +- BLE 연결 유지를 위해 System ON 슬립 상태를 사용 +- 사용하지 않는 peripheral 클럭을 모두 비활성화 +- RAM 리텐션 영역을 최소한으로 설정 +- 위 조치를 통해 수 μA 수준까지 소비 전류 절감 가능 + +**W25Q32 (Flash Memory)** + +- 대기 상태에서도 수 μA 소모 +- 측정/저장 시에만 깨우고, 평소에는 **Deep Power-Down** 모드 사용 +- Deep Power-Down 진입: SPI로 0xB9 커맨드 전송 → 소비 전류 약 1μA 이하 +- 복귀: 0xAB 커맨드 전송 후 수 μs 대기 +- \SPI_CS_FLASH를 High로 유지하는 것만으로는 불충분하며, 명시적으로 커맨드를 전송해야 함 + +| 상태 | 소비 전류 (대략) | 진입 방법 | +|------|:-:|------| +| Normal Standby | ~수 μA | 기본 상태 | +| Deep Power-Down | ~1μA 이하 | SPI 커맨드 0xB9 | + +**ICM-42670 (IMU Sensor)** + +- IMU를 상시 켜둘 필요 없음 +- 측정 명령이 올 때만 Wake → 측정 → 다시 Sleep 시키는 방식 사용 +- I2C로 슬립 모드 진입 또는 ODR(Output Data Rate)을 최소로 설정 + +| 상태 | 소비 전류 (대략) | 비고 | +|------|:-:|------| +| Full Rate 동작 | ~수백 μA | 가속도 + 자이로 활성 | +| Low Power / Sleep | ~수 μA 이하 | 측정 시에만 Wake | + +### 6-2. Active Mode 체류 시간 최소화 + +Active Mode에서는 TX/RX LDO(U42, U41)뿐 아니라 LT3463(±25V), MCP1804(+10V), LM27762(±2.75V) 등 고전압/아날로그 전원이 모두 켜지므로 소비 전류가 크게 증가한다. 따라서 Active Mode 체류 시간을 최소화하는 것이 전력 절감에 가장 효과적이다. + +**원칙: 측정 직전에 Active 진입, 측정 직후 즉시 Sleep 복귀** + +**전원 안정화 시간 관리** + +- PZT_PWR_EN = High 후 LDO/DC-DC 출력이 안정될 때까지 대기 필요 +- 이 안정화 시간을 실측하여 필요 최소한으로 설정 +- 불필요하게 긴 마진을 두지 않도록 주의 + +**스캔 시간 분석** + +| 항목 | 시간 | +|------|------| +| MUX 채널 스위칭 안정화 | 1.3ms (채널 전환 시 1회) | +| 1회 측정 (TX + 10μs 대기 + 300μs RX) | ~310μs | +| 1채널 (Avg=5) | 1.3ms + 5 × 310μs ≈ 2.85ms | +| 6채널 전체 (Avg=5, N=6) | 6 × 2.85ms ≈ 17.1ms | + +- 6채널 전체 스캔 자체는 약 17ms 이내로 완료 가능 +- 전원 안정화 대기 시간이 오히려 더 큰 비중을 차지할 수 있음 +- 채널 전환 → TX → RX를 타이트하게 구성하여 불필요한 간격 제거 + +**측정 파라미터에 의한 시간 절감** + +| 파라미터 조절 | 효과 | +|--------------|------| +| Channel 개수 줄이기 | 측정 채널 수에 비례하여 Active 시간 단축 | +| 평균화 수 줄이기 | 반복 횟수에 비례하여 Active 시간 단축 | +| 간헐 측정 (측정 주기 늘리기) | Active 진입 빈도 자체를 줄임 | diff --git a/data/CODE_REVIEW.pdf b/data/CODE_REVIEW.pdf new file mode 100644 index 0000000..6775cd9 --- /dev/null +++ b/data/CODE_REVIEW.pdf @@ -0,0 +1,37662 @@ +%PDF-1.4 +% +1 0 obj +<< +/CreationDate (D:20260315144824+00'00') +/Creator (Mozilla/5.0 \(Windows NT 10.0; Win64; x64\) AppleWebKit/537.36 \(KHTML, like Gecko\) HeadlessChrome/146.0.0.0 Safari/537.36) +/ModDate (D:20260315235841+09'00') +/Producer (Skia/PDF m146) +/Title (VesiScan-Basic Code Review) +>> +endobj +2 0 obj +<< +/Lang (ko-KR) +/MarkInfo << +/Marked true +/Type /MarkInfo +>> +/Metadata 3 0 R +/Pages 4 0 R +/StructTreeRoot 5 0 R +/Type /Catalog +/ViewerPreferences << +/DisplayDocTitle true +/Type /ViewerPreferences +>> +>> +endobj +3 0 obj +<< +/Length 3179 +/Subtype /XML +/Type /Metadata +>> +stream + + + + + 2026-03-15T23:48:24+09:00 + Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/146.0.0.0 Safari/537.36 + 2026-03-15T23:58:41+09:00 + Skia/PDF m146 + + + VesiScan-Basic Code Review + + + application/pdf + uuid:4492ca9f-5c53-4179-9f6e-262fe3986128 + uuid:96cf39a2-e447-49b5-a795-404e6b67e4df + + + + + + + + + + + + + + + + + + + + + + + + + +endstream +endobj +4 0 obj +<< +/Count 13 +/Kids [6 0 R 7 0 R] +/Type /Pages +>> +endobj +5 0 obj +<< +/IDTree 8 0 R +/K 9 0 R +/ParentTree 10 0 R +/ParentTreeNextKey 13 +/Type /StructTreeRoot +>> +endobj +6 0 obj +<< +/Count 8 +/Kids [11 0 R 12 0 R 13 0 R 14 0 R 15 0 R 16 0 R 17 0 R 18 0 R] +/Parent 4 0 R +/Type /Pages +>> +endobj +7 0 obj +<< +/Count 5 +/Kids [19 0 R 20 0 R 21 0 R 22 0 R 23 0 R] +/Parent 4 0 R +/Type /Pages +>> +endobj +8 0 obj +<< +/Kids [24 0 R] +>> +endobj +9 0 obj +<< +/K [25 0 R 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R 36 0 R 37 0 R 38 0 R 39 0 R 40 0 R +41 0 R 42 0 R 43 0 R 44 0 R 45 0 R 46 0 R 47 0 R 48 0 R 49 0 R 50 0 R 51 0 R 52 0 R 53 0 R 54 0 R 55 0 R 56 0 R +57 0 R 58 0 R 59 0 R 60 0 R 61 0 R 62 0 R 63 0 R 64 0 R 65 0 R 66 0 R 67 0 R 68 0 R 69 0 R 70 0 R 71 0 R 72 0 R +73 0 R 74 0 R 75 0 R 76 0 R 77 0 R 78 0 R 79 0 R 80 0 R 81 0 R 82 0 R 83 0 R 84 0 R 85 0 R 86 0 R 87 0 R 88 0 R +89 0 R 90 0 R 91 0 R 92 0 R 93 0 R 94 0 R 95 0 R 96 0 R 97 0 R 98 0 R 99 0 R 100 0 R 101 0 R 102 0 R 103 0 R 104 0 R +105 0 R 106 0 R 107 0 R 108 0 R 109 0 R 110 0 R 111 0 R 112 0 R 113 0 R 114 0 R 115 0 R 116 0 R 117 0 R 118 0 R 119 0 R 120 0 R +121 0 R 122 0 R 123 0 R 124 0 R 125 0 R 126 0 R 127 0 R 128 0 R 129 0 R 130 0 R 131 0 R 132 0 R 133 0 R 134 0 R 135 0 R 136 0 R +137 0 R 138 0 R 139 0 R 140 0 R 141 0 R 142 0 R 143 0 R 144 0 R 145 0 R 146 0 R 147 0 R 148 0 R 149 0 R 150 0 R 151 0 R 152 0 R +153 0 R 154 0 R 155 0 R 156 0 R 157 0 R 158 0 R 159 0 R 160 0 R 161 0 R 162 0 R 163 0 R 164 0 R 165 0 R 166 0 R 167 0 R 168 0 R +169 0 R 170 0 R 171 0 R 172 0 R 173 0 R 174 0 R 175 0 R 176 0 R 177 0 R 178 0 R 179 0 R 180 0 R 181 0 R 182 0 R 183 0 R 184 0 R +185 0 R 186 0 R 187 0 R 188 0 R 189 0 R 190 0 R 191 0 R 192 0 R 193 0 R 194 0 R 195 0 R 196 0 R 197 0 R 198 0 R 199 0 R 200 0 R +201 0 R 202 0 R 203 0 R 204 0 R 205 0 R 206 0 R 207 0 R] +/Lang (ko-KR) +/P 5 0 R +/S /Document +/Type /StructElem +>> +endobj +10 0 obj +<< +/Nums [0 208 0 R 1 209 0 R 2 210 0 R 3 211 0 R 4 212 0 R 5 213 0 R 6 214 0 R 7 215 0 R +8 216 0 R 9 217 0 R 10 218 0 R 11 219 0 R 12 220 0 R] +/Type /ParentTree +>> +endobj +11 0 obj +<< +/Annots [221 0 R 222 0 R] +/Contents 223 0 R +/MediaBox [0 0 612 792] +/Parent 6 0 R +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Font << +/F4 225 0 R +/F5 226 0 R +/F6 227 0 R +/F7 228 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/StructParents 0 +/Tabs /S +/Type /Page +>> +endobj +12 0 obj +<< +/Contents 229 0 R +/MediaBox [0 0 612 792] +/Parent 6 0 R +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Font << +/F4 225 0 R +/F5 226 0 R +/F7 228 0 R +/F10 230 0 R +/F11 231 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/StructParents 1 +/Tabs /S +/Type /Page +>> +endobj +13 0 obj +<< +/Contents 232 0 R +/MediaBox [0 0 612 792] +/Parent 6 0 R +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Font << +/F4 225 0 R +/F5 226 0 R +/F6 227 0 R +/F7 228 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/StructParents 2 +/Tabs /S +/Type /Page +>> +endobj +14 0 obj +<< +/Contents 233 0 R +/MediaBox [0 0 612 792] +/Parent 6 0 R +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Font << +/F4 225 0 R +/F5 226 0 R +/F7 228 0 R +/F10 230 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/StructParents 3 +/Tabs /S +/Type /Page +>> +endobj +15 0 obj +<< +/Contents 234 0 R +/MediaBox [0 0 612 792] +/Parent 6 0 R +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Font << +/F4 225 0 R +/F5 226 0 R +/F7 228 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/StructParents 4 +/Tabs /S +/Type /Page +>> +endobj +16 0 obj +<< +/Contents 235 0 R +/MediaBox [0 0 612 792] +/Parent 6 0 R +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Font << +/F4 225 0 R +/F5 226 0 R +/F7 228 0 R +/F10 230 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/StructParents 5 +/Tabs /S +/Type /Page +>> +endobj +17 0 obj +<< +/Contents 236 0 R +/MediaBox [0 0 612 792] +/Parent 6 0 R +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Font << +/F4 225 0 R +/F5 226 0 R +/F7 228 0 R +/F11 231 0 R +/F22 237 0 R +/F23 238 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/StructParents 6 +/Tabs /S +/Type /Page +>> +endobj +18 0 obj +<< +/Contents 239 0 R +/MediaBox [0 0 612 792] +/Parent 6 0 R +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Font << +/F4 225 0 R +/F5 226 0 R +/F7 228 0 R +/F10 230 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/StructParents 7 +/Tabs /S +/Type /Page +>> +endobj +19 0 obj +<< +/Contents 240 0 R +/MediaBox [0 0 612 792] +/Parent 7 0 R +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Font << +/F4 225 0 R +/F5 226 0 R +/F6 227 0 R +/F7 228 0 R +/F10 230 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/StructParents 8 +/Tabs /S +/Type /Page +>> +endobj +20 0 obj +<< +/Contents 241 0 R +/MediaBox [0 0 612 792] +/Parent 7 0 R +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Font << +/F4 225 0 R +/F5 226 0 R +/F7 228 0 R +/F10 230 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/StructParents 9 +/Tabs /S +/Type /Page +>> +endobj +21 0 obj +<< +/Contents 242 0 R +/MediaBox [0 0 612 792] +/Parent 7 0 R +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Font << +/F4 225 0 R +/F5 226 0 R +/F7 228 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/StructParents 10 +/Tabs /S +/Type /Page +>> +endobj +22 0 obj +<< +/Contents 243 0 R +/MediaBox [0 0 612 792] +/Parent 7 0 R +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Font << +/F4 225 0 R +/F5 226 0 R +/F7 228 0 R +/F10 230 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/StructParents 11 +/Tabs /S +/Type /Page +>> +endobj +23 0 obj +<< +/Contents 244 0 R +/MediaBox [0 0 612 792] +/Parent 7 0 R +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Font << +/F4 225 0 R +/F7 228 0 R +/F10 230 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/StructParents 12 +/Tabs /S +/Type /Page +>> +endobj +24 0 obj +<< +/Limits [(node00001886) (node00003590)] +/Names [(node00001886) 245 0 R (node00001887) 246 0 R (node00001888) 247 0 R (node00001889) 248 0 R (node00001890) 249 0 R (node00001944) 250 0 R (node00001945) 251 0 R (node00001946) 252 0 R +(node00001947) 253 0 R (node00002266) 254 0 R (node00002267) 255 0 R (node00002268) 256 0 R (node00002269) 257 0 R (node00002359) 258 0 R (node00002360) 259 0 R (node00002361) 260 0 R +(node00002435) 261 0 R (node00002436) 262 0 R (node00002437) 263 0 R (node00002458) 264 0 R (node00002459) 265 0 R (node00002460) 266 0 R (node00002504) 267 0 R (node00002505) 268 0 R +(node00002506) 269 0 R (node00002507) 270 0 R (node00002548) 271 0 R (node00002549) 272 0 R (node00002550) 273 0 R (node00002551) 274 0 R (node00002641) 275 0 R (node00002642) 276 0 R +(node00002643) 277 0 R (node00002673) 278 0 R (node00002674) 279 0 R (node00002675) 280 0 R (node00003027) 281 0 R (node00003028) 282 0 R (node00003029) 283 0 R (node00003171) 284 0 R +(node00003172) 285 0 R (node00003173) 286 0 R (node00003174) 287 0 R (node00003385) 288 0 R (node00003386) 289 0 R (node00003387) 290 0 R (node00003465) 291 0 R (node00003466) 292 0 R +(node00003467) 293 0 R (node00003491) 294 0 R (node00003492) 295 0 R (node00003493) 296 0 R (node00003494) 297 0 R (node00003521) 298 0 R (node00003522) 299 0 R (node00003523) 300 0 R +(node00003557) 301 0 R (node00003558) 302 0 R (node00003559) 303 0 R (node00003589) 304 0 R (node00003590) 305 0 R] +>> +endobj +25 0 obj +<< +/K [306 0 R 0] +/P 9 0 R +/Pg 11 0 R +/S /H1 +/Type /StructElem +>> +endobj +26 0 obj +<< +/K [307 0 R 1] +/P 9 0 R +/Pg 11 0 R +/S /BlockQuote +/Type /StructElem +>> +endobj +27 0 obj +<< +/K 2 +/P 9 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +28 0 obj +<< +/K [308 0 R 3] +/P 9 0 R +/Pg 11 0 R +/S /H2 +/Type /StructElem +>> +endobj +29 0 obj +<< +/K [309 0 R 310 0 R 311 0 R 312 0 R 313 0 R 314 0 R 315 0 R 316 0 R] +/P 9 0 R +/S /L +/Type /StructElem +>> +endobj +30 0 obj +<< +/K 4 +/P 9 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +31 0 obj +<< +/K [317 0 R 5] +/P 9 0 R +/Pg 11 0 R +/S /H2 +/Type /StructElem +>> +endobj +32 0 obj +<< +/K 318 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +33 0 obj +<< +/K [319 0 R 320 0 R 321 0 R 322 0 R 323 0 R 324 0 R 325 0 R 326 0 R 327 0 R 328 0 R 329 0 R 330 0 R 331 0 R 332 0 R 333 0 R 334 0 R +335 0 R 336 0 R 337 0 R 338 0 R 339 0 R 340 0 R 341 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +34 0 obj +<< +/K 342 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +35 0 obj +<< +/K [343 0 R 344 0 R 345 0 R 346 0 R 347 0 R 348 0 R 349 0 R 14] +/P 9 0 R +/Pg 11 0 R +/S /Table +/Type /StructElem +>> +endobj +36 0 obj +<< +/K 350 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +37 0 obj +<< +/K [351 0 R 352 0 R 353 0 R 354 0 R 355 0 R 356 0 R 357 0 R 358 0 R 359 0 R 360 0 R 361 0 R 22 << +/MCID 6 +/Pg 12 0 R +/Type /MCR +>>] +/P 9 0 R +/Pg 11 0 R +/S /Table +/Type /StructElem +>> +endobj +38 0 obj +<< +/K 362 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +39 0 obj +<< +/K [363 0 R 364 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +40 0 obj +<< +/K [365 0 R 7] +/P 9 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +41 0 obj +<< +/K [366 0 R 367 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +42 0 obj +<< +/K [368 0 R 8] +/P 9 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +43 0 obj +<< +/K [369 0 R 370 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +44 0 obj +<< +/K [371 0 R 9] +/P 9 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +45 0 obj +<< +/K [372 0 R 373 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +46 0 obj +<< +/K [374 0 R 10] +/P 9 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +47 0 obj +<< +/K 11 +/P 9 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +48 0 obj +<< +/K [375 0 R 12] +/P 9 0 R +/Pg 12 0 R +/S /H2 +/Type /StructElem +>> +endobj +49 0 obj +<< +/K [376 0 R 377 0 R] +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +50 0 obj +<< +/K [378 0 R 379 0 R 380 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +51 0 obj +<< +/K 381 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +52 0 obj +<< +/K [382 0 R 383 0 R 384 0 R 385 0 R 386 0 R 387 0 R 388 0 R 389 0 R 390 0 R 18 << +/MCID 7 +/Pg 13 0 R +/Type /MCR +>>] +/P 9 0 R +/Pg 12 0 R +/S /Table +/Type /StructElem +>> +endobj +53 0 obj +<< +/K 391 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +54 0 obj +<< +/K [392 0 R 393 0 R 394 0 R 395 0 R 396 0 R 397 0 R] +/P 9 0 R +/S /L +/Type /StructElem +>> +endobj +55 0 obj +<< +/K 398 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +56 0 obj +<< +/K 399 0 R +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +57 0 obj +<< +/K [400 0 R 401 0 R 402 0 R 403 0 R 404 0 R 405 0 R 406 0 R 407 0 R 408 0 R 409 0 R 410 0 R 411 0 R 16] +/P 9 0 R +/Pg 13 0 R +/S /Table +/Type /StructElem +>> +endobj +58 0 obj +<< +/K [412 0 R 17] +/P 9 0 R +/Pg 13 0 R +/S /BlockQuote +/Type /StructElem +>> +endobj +59 0 obj +<< +/K 413 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +60 0 obj +<< +/K [414 0 R 415 0 R 416 0 R 21 << +/MCID 4 +/Pg 14 0 R +/Type /MCR +>>] +/P 9 0 R +/Pg 13 0 R +/S /Table +/Type /StructElem +>> +endobj +61 0 obj +<< +/K 5 +/P 9 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +62 0 obj +<< +/K [417 0 R 6] +/P 9 0 R +/Pg 14 0 R +/S /H2 +/Type /StructElem +>> +endobj +63 0 obj +<< +/K 418 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +64 0 obj +<< +/K 419 0 R +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +65 0 obj +<< +/K 420 0 R +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +66 0 obj +<< +/K [421 0 R 422 0 R 423 0 R 424 0 R 425 0 R 426 0 R 427 0 R 13] +/P 9 0 R +/Pg 14 0 R +/S /Table +/Type /StructElem +>> +endobj +67 0 obj +<< +/K 428 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +68 0 obj +<< +/K [429 0 R 430 0 R 431 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +69 0 obj +<< +/K [432 0 R 433 0 R 434 0 R 435 0 R 19] +/P 9 0 R +/Pg 14 0 R +/S /Table +/Type /StructElem +>> +endobj +70 0 obj +<< +/K [436 0 R 437 0 R 438 0 R 439 0 R 440 0 R 441 0 R 442 0 R 443 0 R 444 0 R 445 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +71 0 obj +<< +/K [446 0 R 447 0 R 448 0 R 449 0 R 450 0 R 451 0 R 452 0 R 453 0 R 454 0 R 455 0 R 456 0 R 457 0 R 458 0 R 459 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +72 0 obj +<< +/K 460 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +73 0 obj +<< +/K [461 0 R 462 0 R 463 0 R 464 0 R 465 0 R 466 0 R 467 0 R 468 0 R 469 0 R 470 0 R 471 0 R 472 0 R 473 0 R 28 << +/MCID 6 +/Pg 15 0 R +/Type /MCR +>>] +/P 9 0 R +/Pg 14 0 R +/S /Table +/Type /StructElem +>> +endobj +74 0 obj +<< +/K 474 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +75 0 obj +<< +/K [475 0 R 476 0 R 477 0 R 478 0 R 479 0 R 12] +/P 9 0 R +/Pg 15 0 R +/S /Table +/Type /StructElem +>> +endobj +76 0 obj +<< +/K 13 +/P 9 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +77 0 obj +<< +/K [480 0 R 14] +/P 9 0 R +/Pg 15 0 R +/S /H2 +/Type /StructElem +>> +endobj +78 0 obj +<< +/K [481 0 R 482 0 R 483 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +79 0 obj +<< +/K 484 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +80 0 obj +<< +/K [485 0 R 486 0 R 487 0 R 488 0 R 489 0 R 490 0 R 21] +/P 9 0 R +/Pg 15 0 R +/S /Table +/Type /StructElem +>> +endobj +81 0 obj +<< +/K 491 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +82 0 obj +<< +/K [492 0 R 22] +/P 9 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +83 0 obj +<< +/K 493 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +84 0 obj +<< +/K [494 0 R 495 0 R 496 0 R 497 0 R] +/P 9 0 R +/S /L +/Type /StructElem +>> +endobj +85 0 obj +<< +/K 0 +/P 9 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +86 0 obj +<< +/K [498 0 R 1] +/P 9 0 R +/Pg 16 0 R +/S /H2 +/Type /StructElem +>> +endobj +87 0 obj +<< +/K 499 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +88 0 obj +<< +/K [500 0 R 501 0 R 502 0 R 503 0 R 504 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +89 0 obj +<< +/K [505 0 R 2] +/P 9 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +90 0 obj +<< +/K 506 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +91 0 obj +<< +/K 507 0 R +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +92 0 obj +<< +/K 3 +/P 9 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +93 0 obj +<< +/K [508 0 R 4] +/P 9 0 R +/Pg 16 0 R +/S /H2 +/Type /StructElem +>> +endobj +94 0 obj +<< +/K 509 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +95 0 obj +<< +/K 510 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +96 0 obj +<< +/K [511 0 R 512 0 R 513 0 R 514 0 R 515 0 R 516 0 R 517 0 R 518 0 R 519 0 R 520 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +97 0 obj +<< +/K [521 0 R 522 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +98 0 obj +<< +/K 523 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +99 0 obj +<< +/K [524 0 R 525 0 R 526 0 R 527 0 R 528 0 R 529 0 R 530 0 R 531 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +100 0 obj +<< +/K [532 0 R 5] +/P 9 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +101 0 obj +<< +/K [533 0 R 534 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +102 0 obj +<< +/K 535 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +103 0 obj +<< +/K [536 0 R 537 0 R 538 0 R 539 0 R 540 0 R 541 0 R 542 0 R 543 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +104 0 obj +<< +/K [544 0 R 545 0 R 546 0 R 547 0 R 548 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +105 0 obj +<< +/K 549 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +106 0 obj +<< +/K [550 0 R 551 0 R 552 0 R 553 0 R 554 0 R 555 0 R 556 0 R 557 0 R 558 0 R 559 0 R 560 0 R 561 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +107 0 obj +<< +/K [562 0 R 563 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +108 0 obj +<< +/K [564 0 R 0] +/P 9 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +109 0 obj +<< +/K [565 0 R 1] +/P 9 0 R +/Pg 17 0 R +/S /BlockQuote +/Type /StructElem +>> +endobj +110 0 obj +<< +/K [566 0 R 567 0 R] +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +111 0 obj +<< +/K 568 0 R +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +112 0 obj +<< +/K 569 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +113 0 obj +<< +/K 570 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +114 0 obj +<< +/K [571 0 R 572 0 R 573 0 R 574 0 R 575 0 R 576 0 R 577 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +115 0 obj +<< +/K 578 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +116 0 obj +<< +/K [579 0 R 580 0 R 581 0 R 582 0 R 583 0 R 584 0 R 585 0 R 586 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +117 0 obj +<< +/K 587 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +118 0 obj +<< +/K [588 0 R 589 0 R 590 0 R 591 0 R 592 0 R 593 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +119 0 obj +<< +/K 594 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +120 0 obj +<< +/K [595 0 R 596 0 R 597 0 R 598 0 R 599 0 R 600 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +121 0 obj +<< +/K [601 0 R 602 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +122 0 obj +<< +/K [603 0 R 604 0 R] +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +123 0 obj +<< +/K 605 0 R +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +124 0 obj +<< +/K 606 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +125 0 obj +<< +/K [607 0 R 608 0 R 609 0 R] +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +126 0 obj +<< +/K [610 0 R 611 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +127 0 obj +<< +/K 612 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +128 0 obj +<< +/K [613 0 R 614 0 R 615 0 R 616 0 R 617 0 R 618 0 R 619 0 R 620 0 R 621 0 R 622 0 R 623 0 R 624 0 R 625 0 R 626 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +129 0 obj +<< +/K 627 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +130 0 obj +<< +/K [628 0 R 629 0 R 630 0 R 631 0 R 632 0 R 633 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +131 0 obj +<< +/K 2 +/P 9 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +132 0 obj +<< +/K [634 0 R 0] +/P 9 0 R +/Pg 18 0 R +/S /H2 +/Type /StructElem +>> +endobj +133 0 obj +<< +/K 635 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +134 0 obj +<< +/K [636 0 R 637 0 R 638 0 R 639 0 R 640 0 R 641 0 R 6] +/P 9 0 R +/Pg 18 0 R +/S /Table +/Type /StructElem +>> +endobj +135 0 obj +<< +/K 642 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +136 0 obj +<< +/K 643 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +137 0 obj +<< +/K [644 0 R 645 0 R 646 0 R 647 0 R 648 0 R 649 0 R 650 0 R 651 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +138 0 obj +<< +/K [652 0 R 7] +/P 9 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +139 0 obj +<< +/K 653 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +140 0 obj +<< +/K [654 0 R 655 0 R 656 0 R 657 0 R 658 0 R 659 0 R 660 0 R 661 0 R 662 0 R 663 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +141 0 obj +<< +/K [664 0 R 8] +/P 9 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +142 0 obj +<< +/K 665 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +143 0 obj +<< +/K [666 0 R 667 0 R 668 0 R 669 0 R 670 0 R 671 0 R 672 0 R 673 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +144 0 obj +<< +/K [674 0 R 9] +/P 9 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +145 0 obj +<< +/K 675 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +146 0 obj +<< +/K [676 0 R 677 0 R 678 0 R 679 0 R 680 0 R 681 0 R 682 0 R 683 0 R 684 0 R 685 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +147 0 obj +<< +/K [686 0 R 10] +/P 9 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +148 0 obj +<< +/K 687 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +149 0 obj +<< +/K [688 0 R 689 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +150 0 obj +<< +/K [690 0 R 691 0 R 692 0 R 693 0 R 694 0 R 695 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +151 0 obj +<< +/K [696 0 R 0] +/P 9 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +152 0 obj +<< +/K 697 0 R +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +153 0 obj +<< +/K 698 0 R +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +154 0 obj +<< +/K [699 0 R 700 0 R 701 0 R 702 0 R 703 0 R 7] +/P 9 0 R +/Pg 19 0 R +/S /Table +/Type /StructElem +>> +endobj +155 0 obj +<< +/K [704 0 R 705 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +156 0 obj +<< +/K 706 0 R +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +157 0 obj +<< +/K [707 0 R 708 0 R 709 0 R 710 0 R 711 0 R 712 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +158 0 obj +<< +/K [713 0 R 8] +/P 9 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +159 0 obj +<< +/K 714 0 R +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +160 0 obj +<< +/K 715 0 R +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +161 0 obj +<< +/K [716 0 R 717 0 R 718 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +162 0 obj +<< +/K [719 0 R 9 << +/MCID 0 +/Pg 20 0 R +/Type /MCR +>>] +/P 9 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +163 0 obj +<< +/K [720 0 R 721 0 R 722 0 R 723 0 R 724 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +164 0 obj +<< +/K 725 0 R +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +165 0 obj +<< +/K [726 0 R 727 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +166 0 obj +<< +/K [728 0 R 1] +/P 9 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +167 0 obj +<< +/K 729 0 R +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +168 0 obj +<< +/K 730 0 R +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +169 0 obj +<< +/K 731 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +170 0 obj +<< +/K [732 0 R 733 0 R 734 0 R 735 0 R 736 0 R 737 0 R 738 0 R 739 0 R 740 0 R 741 0 R 742 0 R 743 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +171 0 obj +<< +/K 744 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +172 0 obj +<< +/K [745 0 R 746 0 R 747 0 R 748 0 R 749 0 R 750 0 R 751 0 R 752 0 R 753 0 R 754 0 R 9] +/P 9 0 R +/Pg 20 0 R +/S /Table +/Type /StructElem +>> +endobj +173 0 obj +<< +/K 10 +/P 9 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +174 0 obj +<< +/K [755 0 R 11] +/P 9 0 R +/Pg 20 0 R +/S /H2 +/Type /StructElem +>> +endobj +175 0 obj +<< +/K 756 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +176 0 obj +<< +/K 757 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +177 0 obj +<< +/K [758 0 R 759 0 R 760 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +178 0 obj +<< +/K 761 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +179 0 obj +<< +/K [762 0 R 763 0 R 764 0 R 765 0 R 766 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +180 0 obj +<< +/K 767 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +181 0 obj +<< +/K [768 0 R 769 0 R 770 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +182 0 obj +<< +/K 771 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +183 0 obj +<< +/K [772 0 R 773 0 R 774 0 R 775 0 R 776 0 R 777 0 R 778 0 R 779 0 R 780 0 R 781 0 R] +/P 9 0 R +/S /P +/Type /StructElem +>> +endobj +184 0 obj +<< +/K 782 0 R +/P 9 0 R +/S /H4 +/Type /StructElem +>> +endobj +185 0 obj +<< +/K [783 0 R 784 0 R 785 0 R 786 0 R] +/P 9 0 R +/S /L +/Type /StructElem +>> +endobj +186 0 obj +<< +/K 787 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +187 0 obj +<< +/K [788 0 R 789 0 R 790 0 R 791 0 R 792 0 R 5] +/P 9 0 R +/Pg 21 0 R +/S /Table +/Type /StructElem +>> +endobj +188 0 obj +<< +/K 6 +/P 9 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +189 0 obj +<< +/K [793 0 R 7] +/P 9 0 R +/Pg 21 0 R +/S /H2 +/Type /StructElem +>> +endobj +190 0 obj +<< +/K 794 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +191 0 obj +<< +/K [795 0 R 796 0 R 797 0 R 798 0 R 799 0 R 14] +/P 9 0 R +/Pg 21 0 R +/S /Table +/Type /StructElem +>> +endobj +192 0 obj +<< +/K 800 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +193 0 obj +<< +/K [801 0 R 802 0 R 803 0 R 804 0 R 805 0 R 806 0 R 807 0 R 808 0 R 21] +/P 9 0 R +/Pg 21 0 R +/S /Table +/Type /StructElem +>> +endobj +194 0 obj +<< +/K 809 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +195 0 obj +<< +/K [810 0 R 811 0 R 812 0 R 813 0 R 814 0 R 815 0 R 816 0 R 26 << +/MCID 5 +/Pg 22 0 R +/Type /MCR +>>] +/P 9 0 R +/Pg 21 0 R +/S /Table +/Type /StructElem +>> +endobj +196 0 obj +<< +/K 817 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +197 0 obj +<< +/K [818 0 R 819 0 R 820 0 R 821 0 R 822 0 R 10] +/P 9 0 R +/Pg 22 0 R +/S /Table +/Type /StructElem +>> +endobj +198 0 obj +<< +/K 11 +/P 9 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +199 0 obj +<< +/K [823 0 R 12] +/P 9 0 R +/Pg 22 0 R +/S /H2 +/Type /StructElem +>> +endobj +200 0 obj +<< +/K 824 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +201 0 obj +<< +/K [825 0 R 13] +/P 9 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +202 0 obj +<< +/K 826 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +203 0 obj +<< +/K [827 0 R 14] +/P 9 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +204 0 obj +<< +/K 828 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +205 0 obj +<< +/K [829 0 R 0] +/P 9 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +206 0 obj +<< +/K 830 0 R +/P 9 0 R +/S /H3 +/Type /StructElem +>> +endobj +207 0 obj +<< +/K [831 0 R 1] +/P 9 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +208 0 obj +[25 0 R 26 0 R 27 0 R 28 0 R 30 0 R 31 0 R 245 0 R 246 0 R 247 0 R 248 0 R 249 0 R 345 0 R 347 0 R 349 0 R 35 0 R 250 0 R +251 0 R 252 0 R 253 0 R 353 0 R 355 0 R 357 0 R 37 0 R 306 0 R 832 0 R 833 0 R 834 0 R 835 0 R 836 0 R 837 0 R 838 0 R 839 0 R +308 0 R 840 0 R 841 0 R 842 0 R 843 0 R 844 0 R 845 0 R 846 0 R 847 0 R 848 0 R 849 0 R 850 0 R 851 0 R 852 0 R 853 0 R 854 0 R +855 0 R 317 0 R 318 0 R 319 0 R 856 0 R 321 0 R 857 0 R 323 0 R 858 0 R 325 0 R 859 0 R 327 0 R 860 0 R 329 0 R 861 0 R 331 0 R +862 0 R 333 0 R 863 0 R 335 0 R 864 0 R 337 0 R 865 0 R 339 0 R 866 0 R 341 0 R 342 0 R 867 0 R 868 0 R 869 0 R 870 0 R 871 0 R +872 0 R 873 0 R 874 0 R 875 0 R 876 0 R 877 0 R 878 0 R 879 0 R 880 0 R 881 0 R 882 0 R 883 0 R 884 0 R 885 0 R 886 0 R 887 0 R +888 0 R 889 0 R 890 0 R 891 0 R 892 0 R 893 0 R 894 0 R 895 0 R 896 0 R 897 0 R 898 0 R 899 0 R 900 0 R 901 0 R 902 0 R 903 0 R +904 0 R 905 0 R 906 0 R 907 0 R 350 0 R 908 0 R 909 0 R 910 0 R 911 0 R 912 0 R 913 0 R 914 0 R 915 0 R 916 0 R 917 0 R 918 0 R +919 0 R 920 0 R 921 0 R 922 0 R 923 0 R 924 0 R 925 0 R 926 0 R 927 0 R 928 0 R 929 0 R 930 0 R 931 0 R 932 0 R 933 0 R 934 0 R +935 0 R 936 0 R 937 0 R 938 0 R 939 0 R 940 0 R 941 0 R] +endobj +209 0 obj +[250 0 R 251 0 R 252 0 R 253 0 R 359 0 R 361 0 R 37 0 R 40 0 R 42 0 R 44 0 R 46 0 R 47 0 R 48 0 R 254 0 R 255 0 R 256 0 R +257 0 R 384 0 R 52 0 R 908 0 R 909 0 R 910 0 R 911 0 R 942 0 R 943 0 R 944 0 R 945 0 R 946 0 R 947 0 R 948 0 R 949 0 R 950 0 R +951 0 R 952 0 R 953 0 R 954 0 R 955 0 R 956 0 R 957 0 R 958 0 R 959 0 R 960 0 R 961 0 R 362 0 R 363 0 R 962 0 R 364 0 R 963 0 R +964 0 R 965 0 R 966 0 R 967 0 R 968 0 R 969 0 R 970 0 R 971 0 R 972 0 R 973 0 R 974 0 R 975 0 R 976 0 R 977 0 R 978 0 R 979 0 R +980 0 R 981 0 R 982 0 R 983 0 R 984 0 R 985 0 R 986 0 R 987 0 R 988 0 R 989 0 R 990 0 R 991 0 R 992 0 R 993 0 R 994 0 R 995 0 R +996 0 R 997 0 R 998 0 R 999 0 R 1000 0 R 1001 0 R 1002 0 R 1003 0 R 1004 0 R 1005 0 R 1006 0 R 1007 0 R 1008 0 R 1009 0 R 1010 0 R 1011 0 R +1012 0 R 1013 0 R 1014 0 R 1015 0 R 1016 0 R 1017 0 R 1018 0 R 1019 0 R 1020 0 R 1021 0 R 1022 0 R 1023 0 R 1024 0 R 1025 0 R 1026 0 R 1027 0 R +1028 0 R 1029 0 R 1030 0 R 1031 0 R 1032 0 R 1033 0 R 1034 0 R 1035 0 R 1036 0 R 1037 0 R 1038 0 R 1039 0 R 1040 0 R 1041 0 R 1042 0 R 1043 0 R +1044 0 R 1045 0 R 1046 0 R 1047 0 R 1048 0 R 1049 0 R 1050 0 R 1051 0 R 1052 0 R 1053 0 R 1054 0 R 1055 0 R 1056 0 R 1057 0 R 1058 0 R 1059 0 R +1060 0 R 1061 0 R 1062 0 R 1063 0 R 1064 0 R 1065 0 R 1066 0 R 1067 0 R 1068 0 R 1069 0 R 1070 0 R 1071 0 R 1072 0 R 1073 0 R 1074 0 R 1075 0 R +1076 0 R 1077 0 R 1078 0 R 1079 0 R 1080 0 R 1081 0 R 1082 0 R 1083 0 R 1084 0 R 1085 0 R 1086 0 R 1087 0 R 1088 0 R 1089 0 R 1090 0 R 1091 0 R +1092 0 R 366 0 R 1093 0 R 367 0 R 1094 0 R 1095 0 R 1096 0 R 1097 0 R 1098 0 R 1099 0 R 1100 0 R 1101 0 R 1102 0 R 1103 0 R 1104 0 R 1105 0 R +1106 0 R 1107 0 R 1108 0 R 1109 0 R 1110 0 R 1111 0 R 1112 0 R 1113 0 R 1114 0 R 1115 0 R 1116 0 R 1117 0 R 1118 0 R 1119 0 R 1120 0 R 1121 0 R +1122 0 R 1123 0 R 1124 0 R 1125 0 R 1126 0 R 1127 0 R 1128 0 R 1129 0 R 1130 0 R 1131 0 R 1132 0 R 369 0 R 1133 0 R 370 0 R 1134 0 R 1135 0 R +1136 0 R 1137 0 R 1138 0 R 1139 0 R 1140 0 R 1141 0 R 1142 0 R 1143 0 R 1144 0 R 1145 0 R 1146 0 R 1147 0 R 1148 0 R 1149 0 R 1150 0 R 1151 0 R +1152 0 R 1153 0 R 1154 0 R 1155 0 R 1156 0 R 1157 0 R 1158 0 R 1159 0 R 1160 0 R 1161 0 R 1162 0 R 1163 0 R 1164 0 R 1165 0 R 1166 0 R 1167 0 R +1168 0 R 1169 0 R 372 0 R 1170 0 R 373 0 R 1171 0 R 1172 0 R 1173 0 R 1174 0 R 1175 0 R 1176 0 R 1177 0 R 1178 0 R 1179 0 R 1180 0 R 1181 0 R +1182 0 R 1183 0 R 1184 0 R 1185 0 R 1186 0 R 1187 0 R 1188 0 R 1189 0 R 1190 0 R 1191 0 R 1192 0 R 1193 0 R 1194 0 R 1195 0 R 1196 0 R 375 0 R +376 0 R 1197 0 R 378 0 R 1198 0 R 380 0 R 381 0 R 1199 0 R 1200 0 R 1201 0 R 1202 0 R 1203 0 R 1204 0 R 1205 0 R 1206 0 R 1207 0 R 1208 0 R +1209 0 R 1210 0 R 1211 0 R 1212 0 R 1213 0 R 1214 0 R 1215 0 R 1216 0 R 1217 0 R] +endobj +210 0 obj +[254 0 R 255 0 R 256 0 R 257 0 R 386 0 R 388 0 R 390 0 R 52 0 R 258 0 R 259 0 R 260 0 R 402 0 R 404 0 R 406 0 R 408 0 R 410 0 R +57 0 R 58 0 R 261 0 R 262 0 R 263 0 R 60 0 R 1199 0 R 1200 0 R 1201 0 R 1202 0 R 1218 0 R 1219 0 R 1220 0 R 1221 0 R 1222 0 R 1223 0 R +1224 0 R 1225 0 R 1226 0 R 1227 0 R 1228 0 R 1229 0 R 1230 0 R 1231 0 R 1232 0 R 1233 0 R 1234 0 R 1235 0 R 1236 0 R 1237 0 R 1238 0 R 1239 0 R +1240 0 R 1241 0 R 1242 0 R 1243 0 R 1244 0 R 1245 0 R 1246 0 R 1247 0 R 1248 0 R 1249 0 R 1250 0 R 1251 0 R 1252 0 R 1253 0 R 1254 0 R 1255 0 R +1256 0 R 391 0 R 1257 0 R 1258 0 R 1259 0 R 1260 0 R 1261 0 R 1262 0 R 1263 0 R 1264 0 R 1265 0 R 1266 0 R 1267 0 R 1268 0 R 1269 0 R 1270 0 R +1271 0 R 1272 0 R 1273 0 R 1274 0 R 1275 0 R 1276 0 R 1277 0 R 1278 0 R 1279 0 R 1280 0 R 1281 0 R 1282 0 R 1283 0 R 1284 0 R 1285 0 R 1286 0 R +1287 0 R 1288 0 R 1289 0 R 1290 0 R 1291 0 R 1292 0 R 1293 0 R 1294 0 R 1295 0 R 1296 0 R 1297 0 R 398 0 R 399 0 R 1298 0 R 1299 0 R 1300 0 R +1301 0 R 1302 0 R 1303 0 R 1304 0 R 1305 0 R 1306 0 R 1307 0 R 1308 0 R 1309 0 R 1310 0 R 1311 0 R 1312 0 R 1313 0 R 1314 0 R 1315 0 R 1316 0 R +1317 0 R 1318 0 R 1319 0 R 1320 0 R 1319 0 R 1320 0 R 1321 0 R 1322 0 R 1323 0 R 1324 0 R 1325 0 R 1326 0 R 1327 0 R 1328 0 R 1329 0 R 1330 0 R +1329 0 R 1330 0 R 1331 0 R 1332 0 R 1333 0 R 1334 0 R 1335 0 R 1336 0 R 1337 0 R 1338 0 R 1339 0 R 1340 0 R 1341 0 R 1342 0 R 1343 0 R 1344 0 R +1345 0 R 1346 0 R 1347 0 R 1348 0 R 1349 0 R 1348 0 R 1349 0 R 1350 0 R 1351 0 R 1352 0 R 1353 0 R 1354 0 R 1355 0 R 1356 0 R 1357 0 R 1358 0 R +1359 0 R 1360 0 R 1361 0 R 1362 0 R 413 0 R 1363 0 R 1364 0 R 1365 0 R 1366 0 R 1367 0 R 1368 0 R 1369 0 R] +endobj +211 0 obj +[261 0 R 262 0 R 263 0 R 416 0 R 60 0 R 61 0 R 62 0 R 264 0 R 265 0 R 266 0 R 423 0 R 425 0 R 427 0 R 66 0 R 267 0 R 268 0 R +269 0 R 270 0 R 434 0 R 69 0 R 271 0 R 272 0 R 273 0 R 274 0 R 463 0 R 465 0 R 467 0 R 469 0 R 73 0 R 1363 0 R 1364 0 R 1365 0 R +1370 0 R 1371 0 R 1372 0 R 1373 0 R 417 0 R 418 0 R 1374 0 R 420 0 R 1375 0 R 1376 0 R 1377 0 R 1378 0 R 1379 0 R 1380 0 R 1381 0 R 1382 0 R +1383 0 R 1384 0 R 1385 0 R 1386 0 R 1387 0 R 1388 0 R 1389 0 R 1390 0 R 1391 0 R 1392 0 R 1393 0 R 1394 0 R 1395 0 R 1396 0 R 1397 0 R 1398 0 R +1399 0 R 1400 0 R 1401 0 R 1402 0 R 1403 0 R 428 0 R 429 0 R 1404 0 R 431 0 R 1405 0 R 1406 0 R 1407 0 R 1408 0 R 1409 0 R 1410 0 R 1411 0 R +1412 0 R 1413 0 R 1414 0 R 1415 0 R 1416 0 R 1417 0 R 1418 0 R 1419 0 R 1420 0 R 1421 0 R 1422 0 R 1423 0 R 1424 0 R 1425 0 R 1426 0 R 1427 0 R +1428 0 R 1429 0 R 1430 0 R 437 0 R 1431 0 R 439 0 R 440 0 R 1432 0 R 441 0 R 442 0 R 1433 0 R 443 0 R 444 0 R 1434 0 R 445 0 R 1435 0 R +447 0 R 448 0 R 1436 0 R 449 0 R 450 0 R 1437 0 R 451 0 R 452 0 R 1438 0 R 453 0 R 454 0 R 1439 0 R 455 0 R 456 0 R 1440 0 R 457 0 R +458 0 R 1441 0 R 458 0 R 1441 0 R 459 0 R 460 0 R 1442 0 R 1443 0 R 1444 0 R 1445 0 R 1446 0 R 1447 0 R 1448 0 R 1449 0 R 1450 0 R 1451 0 R +1452 0 R 1453 0 R 1454 0 R 1455 0 R 1456 0 R 1457 0 R 1458 0 R 1459 0 R 1460 0 R 1461 0 R 1462 0 R 1463 0 R 1464 0 R 1465 0 R 1466 0 R 1467 0 R +1468 0 R 1469 0 R 1470 0 R 1471 0 R 1472 0 R 1473 0 R 1474 0 R 1475 0 R 1476 0 R 1477 0 R 1478 0 R 1479 0 R 1480 0 R 1481 0 R 1482 0 R 1483 0 R +1484 0 R 1485 0 R] +endobj +212 0 obj +[271 0 R 272 0 R 273 0 R 274 0 R 471 0 R 473 0 R 73 0 R 275 0 R 276 0 R 277 0 R 477 0 R 479 0 R 75 0 R 76 0 R 77 0 R 278 0 R +279 0 R 280 0 R 1486 0 R 487 0 R 489 0 R 80 0 R 82 0 R 1442 0 R 1443 0 R 1444 0 R 1445 0 R 1487 0 R 1488 0 R 1489 0 R 1490 0 R 1491 0 R +1492 0 R 1493 0 R 1494 0 R 1495 0 R 1496 0 R 1497 0 R 1498 0 R 1499 0 R 1500 0 R 1501 0 R 1502 0 R 1503 0 R 1504 0 R 1505 0 R 1506 0 R 474 0 R +1507 0 R 1508 0 R 1509 0 R 1510 0 R 1511 0 R 1512 0 R 1513 0 R 1514 0 R 1515 0 R 1516 0 R 1517 0 R 1518 0 R 1519 0 R 1520 0 R 1521 0 R 480 0 R +481 0 R 482 0 R 1522 0 R 483 0 R 484 0 R 1523 0 R 1524 0 R 1525 0 R 1526 0 R 1527 0 R 1528 0 R 1529 0 R 1530 0 R 1531 0 R 1532 0 R 1533 0 R +1534 0 R 1535 0 R 1536 0 R 1537 0 R 1538 0 R 1539 0 R 1540 0 R 1541 0 R 1542 0 R 1543 0 R 1544 0 R 1545 0 R 1546 0 R 1547 0 R 1548 0 R 491 0 R +1549 0 R 1550 0 R 1551 0 R 1552 0 R 1553 0 R 1554 0 R 1555 0 R 1556 0 R 1557 0 R 1558 0 R 1559 0 R 1560 0 R 1561 0 R 1562 0 R 1563 0 R 1564 0 R +1565 0 R 1566 0 R 1567 0 R 1568 0 R 1569 0 R 1570 0 R 1571 0 R 1572 0 R 1573 0 R 1574 0 R 1575 0 R 1576 0 R 1577 0 R 1578 0 R 1579 0 R 1580 0 R +1581 0 R 1582 0 R 1583 0 R 1584 0 R 1585 0 R 1586 0 R 1587 0 R 1588 0 R 1589 0 R 1590 0 R 1591 0 R 1592 0 R 1593 0 R 1594 0 R 1595 0 R 1596 0 R +1597 0 R 1598 0 R 1599 0 R 1600 0 R 1601 0 R 1602 0 R 1603 0 R 1604 0 R 1605 0 R 1606 0 R 1607 0 R 1608 0 R 1609 0 R 1610 0 R 1611 0 R 1612 0 R +1613 0 R 1614 0 R 1615 0 R 1616 0 R 1617 0 R 1618 0 R 1619 0 R 1620 0 R 1621 0 R 1622 0 R 1623 0 R 1624 0 R 1625 0 R 1626 0 R 1627 0 R 1628 0 R +1629 0 R 1630 0 R 1631 0 R 1632 0 R 1633 0 R 1634 0 R 1635 0 R 1636 0 R 1637 0 R 1638 0 R 1639 0 R 1640 0 R 1641 0 R 1642 0 R 1643 0 R 1644 0 R +1645 0 R 1646 0 R 1647 0 R 1648 0 R 1649 0 R 1650 0 R 1651 0 R 1652 0 R 1653 0 R 1654 0 R 1655 0 R 1656 0 R 1657 0 R 1658 0 R 493 0 R 1659 0 R +1660 0 R 1661 0 R 1662 0 R 1663 0 R 1664 0 R 1665 0 R 1666 0 R 1667 0 R 1668 0 R 1669 0 R 1670 0 R 1671 0 R 1672 0 R 1673 0 R 1674 0 R 1675 0 R +1676 0 R] +endobj +213 0 obj +[85 0 R 86 0 R 89 0 R 92 0 R 93 0 R 100 0 R 498 0 R 499 0 R 500 0 R 501 0 R 1677 0 R 502 0 R 503 0 R 1678 0 R 504 0 R 1679 0 R +506 0 R 507 0 R 508 0 R 509 0 R 510 0 R 1680 0 R 512 0 R 1681 0 R 514 0 R 515 0 R 1682 0 R 516 0 R 517 0 R 1683 0 R 518 0 R 519 0 R +1684 0 R 520 0 R 1685 0 R 522 0 R 523 0 R 1686 0 R 525 0 R 1687 0 R 527 0 R 528 0 R 1688 0 R 529 0 R 1689 0 R 531 0 R 1690 0 R 1691 0 R +1692 0 R 1693 0 R 1694 0 R 1695 0 R 1696 0 R 1697 0 R 1698 0 R 1699 0 R 1700 0 R 1701 0 R 1702 0 R 1703 0 R 1704 0 R 1705 0 R 1706 0 R 1707 0 R +1708 0 R 1709 0 R 1710 0 R 1711 0 R 1712 0 R 1713 0 R 1714 0 R 1715 0 R 1716 0 R 1717 0 R 1718 0 R 1719 0 R 1720 0 R 1721 0 R 1722 0 R 1723 0 R +1724 0 R 1725 0 R 1726 0 R 1727 0 R 1728 0 R 1729 0 R 1730 0 R 1731 0 R 1732 0 R 1733 0 R 1734 0 R 1735 0 R 534 0 R 535 0 R 1736 0 R 537 0 R +1737 0 R 539 0 R 540 0 R 1738 0 R 541 0 R 542 0 R 1739 0 R 543 0 R 1740 0 R 545 0 R 546 0 R 1741 0 R 547 0 R 548 0 R 1742 0 R] +endobj +214 0 obj +[108 0 R 109 0 R 131 0 R 549 0 R 1743 0 R 551 0 R 1744 0 R 553 0 R 554 0 R 1745 0 R 555 0 R 556 0 R 1746 0 R 557 0 R 558 0 R 1747 0 R +559 0 R 560 0 R 1748 0 R 561 0 R 1749 0 R 563 0 R 1750 0 R 1751 0 R 1752 0 R 1753 0 R 1754 0 R 1755 0 R 1756 0 R 1757 0 R 1758 0 R 1759 0 R +1760 0 R 1761 0 R 1762 0 R 1763 0 R 1764 0 R 1765 0 R 1766 0 R 1767 0 R 1768 0 R 1769 0 R 1770 0 R 1771 0 R 1772 0 R 1773 0 R 1774 0 R 1775 0 R +1776 0 R 1777 0 R 1778 0 R 566 0 R 1779 0 R 568 0 R 569 0 R 570 0 R 1780 0 R 572 0 R 1781 0 R 574 0 R 575 0 R 1782 0 R 576 0 R 577 0 R +1783 0 R 578 0 R 1784 0 R 580 0 R 1785 0 R 582 0 R 583 0 R 1786 0 R 584 0 R 585 0 R 1787 0 R 586 0 R 587 0 R 1788 0 R 589 0 R 1789 0 R +591 0 R 592 0 R 1790 0 R 593 0 R 594 0 R 1791 0 R 596 0 R 1792 0 R 598 0 R 599 0 R 1793 0 R 600 0 R 1794 0 R 602 0 R 603 0 R 1795 0 R +605 0 R 606 0 R 607 0 R 608 0 R 1796 0 R 609 0 R 1797 0 R 611 0 R 612 0 R 1798 0 R 614 0 R 1799 0 R 616 0 R 617 0 R 1800 0 R 618 0 R +619 0 R 1801 0 R 620 0 R 621 0 R 1802 0 R 622 0 R 623 0 R 1803 0 R 624 0 R 625 0 R 1804 0 R 626 0 R 627 0 R 1805 0 R 629 0 R 1806 0 R +631 0 R 632 0 R 1807 0 R 633 0 R] +endobj +215 0 obj +[132 0 R 281 0 R 282 0 R 283 0 R 638 0 R 640 0 R 134 0 R 138 0 R 141 0 R 144 0 R 147 0 R 634 0 R 635 0 R 1808 0 R 1809 0 R 1810 0 R +1811 0 R 1812 0 R 1813 0 R 1814 0 R 1815 0 R 1816 0 R 1817 0 R 1818 0 R 1819 0 R 1820 0 R 1821 0 R 1822 0 R 1823 0 R 1824 0 R 1825 0 R 642 0 R +643 0 R 1826 0 R 645 0 R 1827 0 R 647 0 R 1828 0 R 649 0 R 650 0 R 1829 0 R 651 0 R 1830 0 R 1831 0 R 1832 0 R 1833 0 R 1834 0 R 653 0 R +1835 0 R 655 0 R 1836 0 R 657 0 R 658 0 R 1837 0 R 659 0 R 1838 0 R 661 0 R 662 0 R 1839 0 R 663 0 R 1840 0 R 1841 0 R 1842 0 R 1843 0 R +1844 0 R 1845 0 R 1846 0 R 665 0 R 1847 0 R 667 0 R 1848 0 R 669 0 R 670 0 R 1849 0 R 671 0 R 1850 0 R 673 0 R 1851 0 R 1852 0 R 1853 0 R +1854 0 R 1855 0 R 1856 0 R 1857 0 R 1858 0 R 1859 0 R 1860 0 R 1861 0 R 1862 0 R 1863 0 R 1864 0 R 1865 0 R 1866 0 R 1867 0 R 1868 0 R 1869 0 R +1870 0 R 1871 0 R 1872 0 R 1873 0 R 1874 0 R 1875 0 R 1876 0 R 1877 0 R 1878 0 R 1879 0 R 1880 0 R 1881 0 R 1882 0 R 1883 0 R 1884 0 R 1885 0 R +1886 0 R 1887 0 R 1888 0 R 1889 0 R 1890 0 R 1891 0 R 675 0 R 1892 0 R 677 0 R 1893 0 R 679 0 R 680 0 R 1894 0 R 681 0 R 1895 0 R 683 0 R +1896 0 R 685 0 R 1897 0 R 1898 0 R 1899 0 R 1900 0 R 1901 0 R 1902 0 R] +endobj +216 0 obj +[151 0 R 284 0 R 285 0 R 286 0 R 287 0 R 701 0 R 703 0 R 154 0 R 158 0 R 162 0 R 687 0 R 1903 0 R 689 0 R 1904 0 R 691 0 R 692 0 R +1905 0 R 693 0 R 694 0 R 1906 0 R 695 0 R 1907 0 R 1908 0 R 1909 0 R 1910 0 R 1911 0 R 1912 0 R 1913 0 R 1914 0 R 1915 0 R 1916 0 R 1917 0 R +1918 0 R 1919 0 R 1920 0 R 1921 0 R 1922 0 R 1923 0 R 1924 0 R 1925 0 R 1926 0 R 1927 0 R 1928 0 R 1929 0 R 1930 0 R 1931 0 R 1932 0 R 1933 0 R +1934 0 R 1935 0 R 705 0 R 1936 0 R 707 0 R 1937 0 R 708 0 R 709 0 R 1938 0 R 710 0 R 711 0 R 1939 0 R 712 0 R 1940 0 R 1941 0 R 1942 0 R +1943 0 R 1944 0 R 1945 0 R 1946 0 R 1947 0 R 1948 0 R 1949 0 R 1950 0 R 1951 0 R 1952 0 R 1953 0 R 1954 0 R 1955 0 R 714 0 R 1956 0 R 716 0 R +717 0 R 1957 0 R 718 0 R 1958 0 R 1959 0 R 1960 0 R 1961 0 R 1962 0 R 1963 0 R 1964 0 R 1965 0 R 1966 0 R 1967 0 R 1968 0 R 1969 0 R 1970 0 R +1971 0 R 1972 0 R 1973 0 R 1974 0 R 1975 0 R 1976 0 R 1977 0 R 1978 0 R 1979 0 R 1980 0 R 1981 0 R 1982 0 R 1983 0 R 1984 0 R 1985 0 R 1986 0 R +1987 0 R 1988 0 R 1989 0 R 1990 0 R 1991 0 R 1992 0 R 1993 0 R 1994 0 R 1995 0 R 1996 0 R 1997 0 R 1998 0 R 1999 0 R 2000 0 R 2001 0 R 2002 0 R +2003 0 R 2004 0 R 2005 0 R 2006 0 R 2007 0 R 2008 0 R 2009 0 R 2010 0 R 2011 0 R 2012 0 R 2013 0 R 2014 0 R] +endobj +217 0 obj +[162 0 R 166 0 R 288 0 R 289 0 R 290 0 R 747 0 R 749 0 R 751 0 R 753 0 R 172 0 R 173 0 R 174 0 R 2015 0 R 2016 0 R 2017 0 R 2018 0 R +2019 0 R 2020 0 R 720 0 R 721 0 R 2021 0 R 722 0 R 2022 0 R 724 0 R 2023 0 R 726 0 R 2024 0 R 727 0 R 2025 0 R 2026 0 R 2027 0 R 2028 0 R +2029 0 R 2030 0 R 2031 0 R 2032 0 R 2033 0 R 2034 0 R 2035 0 R 2036 0 R 2037 0 R 2038 0 R 2039 0 R 2040 0 R 2041 0 R 2042 0 R 2043 0 R 2044 0 R +2045 0 R 2046 0 R 2047 0 R 2048 0 R 2049 0 R 2050 0 R 2051 0 R 2052 0 R 2053 0 R 2054 0 R 2055 0 R 2056 0 R 2057 0 R 2058 0 R 2059 0 R 2060 0 R +2061 0 R 2062 0 R 2063 0 R 2064 0 R 2065 0 R 2066 0 R 2067 0 R 2068 0 R 2069 0 R 2070 0 R 2071 0 R 2072 0 R 2073 0 R 2074 0 R 2075 0 R 2076 0 R +2077 0 R 2078 0 R 2079 0 R 2080 0 R 2081 0 R 2082 0 R 2083 0 R 2084 0 R 2085 0 R 729 0 R 730 0 R 731 0 R 2086 0 R 733 0 R 2087 0 R 735 0 R +2088 0 R 737 0 R 738 0 R 2089 0 R 739 0 R 2090 0 R 741 0 R 742 0 R 2091 0 R 743 0 R 744 0 R 2092 0 R 2093 0 R 2094 0 R 2095 0 R 2096 0 R +2097 0 R 2098 0 R 2099 0 R 2100 0 R 2101 0 R 2102 0 R 2103 0 R 2104 0 R 2105 0 R 2106 0 R 2107 0 R 2108 0 R 2109 0 R 2110 0 R 2111 0 R 2112 0 R +2113 0 R 2114 0 R 2115 0 R 2116 0 R 2117 0 R 2118 0 R 2119 0 R 2120 0 R 2121 0 R 755 0 R 756 0 R 757 0 R 758 0 R 759 0 R 2122 0 R 760 0 R +761 0 R 762 0 R 763 0 R 2123 0 R 764 0 R 765 0 R 2124 0 R 766 0 R 767 0 R 768 0 R 769 0 R 2125 0 R 770 0 R] +endobj +218 0 obj +[291 0 R 292 0 R 293 0 R 790 0 R 792 0 R 187 0 R 188 0 R 189 0 R 294 0 R 295 0 R 296 0 R 297 0 R 797 0 R 799 0 R 191 0 R 298 0 R +299 0 R 300 0 R 803 0 R 805 0 R 807 0 R 193 0 R 301 0 R 302 0 R 303 0 R 812 0 R 195 0 R 771 0 R 772 0 R 2126 0 R 773 0 R 774 0 R +2127 0 R 775 0 R 776 0 R 2128 0 R 777 0 R 778 0 R 2129 0 R 779 0 R 780 0 R 2130 0 R 781 0 R 782 0 R 2131 0 R 2132 0 R 2133 0 R 2134 0 R +2135 0 R 2136 0 R 2137 0 R 2138 0 R 2139 0 R 2140 0 R 2141 0 R 2142 0 R 2143 0 R 2144 0 R 2145 0 R 2146 0 R 2147 0 R 2148 0 R 2149 0 R 2150 0 R +2151 0 R 2152 0 R 2153 0 R 2154 0 R 2155 0 R 2156 0 R 2157 0 R 2158 0 R 2159 0 R 787 0 R 2160 0 R 2161 0 R 2162 0 R 2163 0 R 2164 0 R 2165 0 R +2166 0 R 2167 0 R 2168 0 R 2169 0 R 2170 0 R 2171 0 R 2172 0 R 2173 0 R 2174 0 R 793 0 R 794 0 R 2175 0 R 2176 0 R 2177 0 R 2178 0 R 2179 0 R +2180 0 R 2181 0 R 2182 0 R 2183 0 R 2184 0 R 2185 0 R 2186 0 R 2187 0 R 2188 0 R 2189 0 R 2190 0 R 2191 0 R 2192 0 R 2193 0 R 2194 0 R 800 0 R +2195 0 R 2196 0 R 2197 0 R 2198 0 R 2199 0 R 2200 0 R 2201 0 R 2202 0 R 2203 0 R 2204 0 R 2205 0 R 2206 0 R 2207 0 R 2208 0 R 2209 0 R 2210 0 R +2211 0 R 2212 0 R 2213 0 R 2214 0 R 2215 0 R 2216 0 R 2217 0 R 2218 0 R 809 0 R 2219 0 R 2220 0 R 2221 0 R 2222 0 R 2223 0 R 2224 0 R 2225 0 R +2226 0 R 2227 0 R] +endobj +219 0 obj +[301 0 R 302 0 R 303 0 R 814 0 R 816 0 R 195 0 R 304 0 R 305 0 R 820 0 R 822 0 R 197 0 R 198 0 R 199 0 R 201 0 R 203 0 R 2219 0 R +2220 0 R 2221 0 R 2228 0 R 2229 0 R 2230 0 R 2231 0 R 2232 0 R 2233 0 R 2234 0 R 2235 0 R 2236 0 R 2237 0 R 2238 0 R 2239 0 R 817 0 R 2240 0 R +2241 0 R 2242 0 R 2243 0 R 2244 0 R 2245 0 R 2246 0 R 2247 0 R 2248 0 R 2249 0 R 823 0 R 824 0 R 2250 0 R 826 0 R 2251 0 R] +endobj +220 0 obj +[205 0 R 207 0 R 828 0 R 2252 0 R 2253 0 R 2254 0 R 2255 0 R 2256 0 R 2257 0 R 2258 0 R 2259 0 R 2260 0 R 2261 0 R 2262 0 R 2263 0 R 2264 0 R +2265 0 R 2266 0 R 2267 0 R 2268 0 R 2269 0 R 2270 0 R 2271 0 R 2272 0 R 2273 0 R 2274 0 R 2275 0 R 2276 0 R 2277 0 R 2278 0 R 2279 0 R 2280 0 R +2281 0 R 2282 0 R 2283 0 R 2284 0 R 2285 0 R 2286 0 R 2287 0 R 2288 0 R 2289 0 R 2290 0 R 2291 0 R 2292 0 R 2293 0 R 2294 0 R 2295 0 R 2296 0 R +2297 0 R 2298 0 R 2299 0 R 2300 0 R 2301 0 R 2302 0 R 2303 0 R 2304 0 R 2305 0 R 2306 0 R 2307 0 R 2308 0 R 2309 0 R 2310 0 R 2311 0 R 2312 0 R +2313 0 R 2314 0 R 2315 0 R 2316 0 R 2317 0 R 2318 0 R 2319 0 R 2320 0 R 2321 0 R 2322 0 R 2323 0 R 2324 0 R 2325 0 R 2326 0 R 2327 0 R 2328 0 R +2329 0 R 2330 0 R 2331 0 R 2332 0 R 2333 0 R 2334 0 R 2335 0 R 2336 0 R 2337 0 R 2338 0 R 2339 0 R 2340 0 R 2341 0 R 2342 0 R 2343 0 R 2344 0 R +2345 0 R 2346 0 R 2347 0 R 2348 0 R 2349 0 R 2350 0 R 2351 0 R 2352 0 R 2353 0 R 2354 0 R 2355 0 R 2356 0 R 2357 0 R 2358 0 R 2359 0 R 2360 0 R +2361 0 R 2362 0 R 2363 0 R 2364 0 R 2365 0 R 2366 0 R 2367 0 R 2368 0 R 2369 0 R 2370 0 R 2371 0 R 2372 0 R 2373 0 R 2374 0 R 2375 0 R 2376 0 R +2377 0 R 2378 0 R 2379 0 R 2380 0 R 2381 0 R 2382 0 R 2383 0 R 2384 0 R 2385 0 R 2386 0 R 2387 0 R 2388 0 R 2389 0 R 2390 0 R 2391 0 R 2392 0 R +2393 0 R 2394 0 R 2395 0 R 2396 0 R 2397 0 R 2398 0 R 830 0 R 2399 0 R 2400 0 R 2401 0 R 2402 0 R 2403 0 R 2404 0 R 2405 0 R 2406 0 R 2407 0 R +2408 0 R 2409 0 R 2410 0 R 2411 0 R 2412 0 R 2413 0 R 2414 0 R 2415 0 R 2416 0 R 2417 0 R 2418 0 R 2419 0 R 2420 0 R 2421 0 R 2422 0 R 2423 0 R +2424 0 R 2425 0 R 2426 0 R 2427 0 R 2428 0 R 2429 0 R 2430 0 R 2431 0 R 2432 0 R 2433 0 R 2434 0 R 2435 0 R 2436 0 R 2437 0 R 2438 0 R 2439 0 R +2440 0 R 2441 0 R 2442 0 R 2443 0 R 2444 0 R 2445 0 R 2446 0 R 2447 0 R 2448 0 R 2449 0 R 2450 0 R 2451 0 R 2452 0 R 2453 0 R] +endobj +221 0 obj +<< +/AP << +/N 2454 0 R +>> +/C [1 0.933 0.345] +/CreationDate (D:20260315234914+09'00') +/F 4 +/M (D:20260315234914+09'00') +/NM (1e5fa9cc-b41f-44a2-a3730b5470b09b9e) +/P 11 0 R +/QuadPoints [53.999996 692.912842 145.636917 692.912842 53.999996 682.937256 145.636917 682.937256] +/Rect [51.933987 682.937256 147.702927 692.912842] +/Subj (p \\) +/Subtype /Highlight +/T (lifew) +/Type /Annot +>> +endobj +222 0 obj +<< +/AP << +/N 2455 0 R +>> +/C [1 0.933 0.345] +/CreationDate (D:20260315234916+09'00') +/F 4 +/M (D:20260315234916+09'00') +/NM (43450254-1366-4805-93dfa341e476cefa) +/P 11 0 R +/QuadPoints [149.914261 692.912842 213.491974 692.912842 149.914261 682.937256 213.491974 682.937256] +/Rect [147.848251 682.937256 215.557983 692.912842] +/Subj (p \\) +/Subtype /Highlight +/T (lifew) +/Type /Annot +>> +endobj +223 0 obj +<< +/Filter /FlateDecode +/Length 7459 +>> +stream +x][+q~ׯ-x+`a@Ҍq; 9>ɬ?Q8bHSCu#?VZ-?Hv/'c_E@dPӿ_N륷nO]wO}Wf~}_r=YX_"Ei%𴬖ҲZ(}ʹtz/?M8҂ B7/w!֞?_ۗmXM:,ʶPp̹5b`聜WL2k?jf>,ź4ƥ6һmSi6JhmJ)4uݦs(mbanfbo{+!@QBȽB +b UIDBb ydU܌l>mGfY:\S&i4GF 8RDBsl!LXclÒ4Xcl斲ԦO6e}[g݈11$H@;1$F@cõ6b mD Y^F1FjbmI:6b mD n4141Phch#b$c:3`clb%wcl`%Ԧ/J^[1+ƕIJŔqb۷++"X w }orcsq 枣ym8-*@F\m؍bZ#q8hsqD"3GQ$=-STғS"6(Ha~ @6,n86pF$ō0ű ȍ&F¢Ca1 xʍaql#lX df6y* 3GdL3Shdql,rű,&,n9rn&űCaѹE3,:ܰ(<4h&3)JEpC(w7LjO&' CO` _p{w@~7 pG(} B`닌irRɢ_VRΐlwt0ȉYDvb>}' 0 CyhhpWcypxwe2no )Y1D|pWWqOZ}f6dByt@T>y7KYk Ypvߘpm]5)u8'T`cP"]9kjM0e&Zх Lw4T4\+8M,F"ŮW Vl S#Pw B]@[^[b5hs0㊜VW=Jc>_Ywh+iaoEܞ٢["7{.2:[?ޏ Zn]VP ߽W5&Tu+9/w`@ a僔t%+fy+$g\Q=݃e8`nhAaVEj J']# +5< 꺏]]ؼ.|\]I iL=Vcs By?G BJ/#=xl6&~ bDb-=CCLjFא䖀7><4tE6/..>=C+59\+58-WסR*򄺽Mnߺ >irb>qKzT1D-+&9be@(B3_u114h r-/,̷.$|z.'wAJZ̤ab8T =l!o!xh2}< C(o9r! z# D- ξ9 +dW.X `+ +3iZoJ,9L=~0-ZOWA2ˤ\H#CzIf:>Qy=zGŝgCL 㥰b l ;0m:Yznjѡvɭ^T˪.Rej`k6W XGj{pq۫]Y^5֌Rقo%%k[;Ci$ԓ-G8K8`*6۸-rڢG>d++\> +~.!JTSSr]slN"B-gdD ̾k)a$~ijX,M3|6ƶ{,yS*(xv|SO8'Q1/۵5&kЫpӖMJ$v,97"6E[?ǹcy!f` 6my(G.%|GT8?OzWɓ1p|3䗋x;>7Bߏdae7TMu'2d0 (\'-> AŃB$ʆrQH:#EKNcll2"q;C\s9=O]oM":?9VMvi;| +1f 4kz5ydiP"}g174HH) $DO҂p#Ӹkϴ 4kdƒPM/Bqu|9cߤ ȫ>8P7.0>jrPODA` _5Lu`R`cTcb&X;hd+QYe=cؖ?o'ݐ EwIIT1Iɗ+DED$ZiQkl*+b}N[&2/&۰ڊ6-ݜXqF^0N!2\z]Z>ZoEޖ"Jla0Xa00`G#5F xjv` 2iA.N gd L Sg rG^x +nCmim}2c,٤8cb S"2`FW yM^D4hQѭ[Ϙl[L6I7`K+QEhL.8e`]U\\"jo`ƲA,d9AXy3akuzUU$KhrLUvGAd!rD٠M3φH:l8dDz(l!ҙ-D:؃H'+EB^=v i H[DڃH-DʅQy)4BdVև^pz5ou1 ᤩECdSHi (aH;F!EHoBz ;.Bzl͜L ![3>;hjd咍IMJ>ԜTK)]Mj5[˜~@ +7=A.=j(C#GҷSZ2wC\T|pVYu͆#.@Y|&PXvz:PFv<2͉P#XOݍ)hP@34CܤW6WC!_M +4Ck^Pj/5ߢf{5RP35JЫN3MJZ1M165l*]klfh'`R&،a6c؉,cnƴ1fL;.nƴ,cҸf7[3@;jjd唍IMJ>ԴTK)]f5c!˼~p!pF(pk<1j, x3:3F3po[|#-72[|#72{FfoyrJ2vJTCu@ +3P"hnq` J!d+latS`Zf3sg\/p`:{c} Ser0)/]]7Lk!2Ftm3I Ss '$'y" o4VKzgݟ:C ݗnh*HOf>+}G KrYr|a'\PwGrgB9lEÁv~@|*OGkWd75Xb=8<] jeG'-+1 vFD[jekeMis4ZNL ;`6Ӷ` Gꌍ=87fƦ?䙖&a잘65;'N&ͩdagyĴyĴ)#K^߽񻂶I|F"3_F+'5-á],֤m猉%E0탖eIJ' +4B,kS:(yn!8\{1I7DSwOK45^`. B͙p%ښ W#ݓRb=)"S1I =.=fZw'w4˕}:4YSUҹVS!sS8%O:)MyiN=4J:)[yČqlך)j)WSC+l\*m(7WtMե_9Cfl3dOøB÷ajw/Z0@xyKyNƽ.{I˧?&W5W̫ǗsqE<8dV\<Pl E?Zt[@nE܋"nbۘ-=@vE٢݋٢Zhі%~˗wUP3eBΙ*"-*QKUŘk3/un?Um+JDz8lkO/ tsP_xE1?^D)QGRae"ݽR$̟. 6a͞.J{(Eiv9좴vQڢ%A)J5L!Й<\TqeMZS4\S,6bu3,*a'_Rҁ^ >d hYdbFX$ZbX|,ۥ'#%J֎E&oL$#Xdr)X$c3H RYw]w4=rwdw.Mwr-x MC}tM٥u! խX&@00 r|-P=g s{ZՃUS=k5v+_nQR_,*B_Knb3`ٰ Mo*Na氊,a氊i۰3`f/'e;ƜW7^U&̘c*l)&R"dԛ*0M⩦8#4bS>-&2WM0ߡ\*0>\* w ^`P&Tc(1+c81c0V8bSb*piL9GNW9\P9fDzՍMj(]YV&c]ς#w3azi@BW^o:laYqh|i߀)@r鸯Y: +zXA~[9"ovb,N1^SisŴm dy m|WQr\;1!֣2^1Lg)M(yARaU +f51`2L &mʟf~;vl)U`+5I-%(&HiV_5pJY%` B+`ÆRo Bޟr*5rʤ&g%sw5=DRVSE̠4(> +endobj +225 0 obj +<< +/BaseFont /AAAAAA+MalgunGothicBold +/DescendantFonts [2456 0 R] +/Encoding /Identity-H +/Subtype /Type0 +/ToUnicode 2457 0 R +/Type /Font +>> +endobj +226 0 obj +<< +/BaseFont /BAAAAA+MalgunGothic +/DescendantFonts [2458 0 R] +/Encoding /Identity-H +/Subtype /Type0 +/ToUnicode 2459 0 R +/Type /Font +>> +endobj +227 0 obj +<< +/CharProcs << +/g0 2460 0 R +/gF4C 2461 0 R +/gF7C 2462 0 R +/gFA2 2463 0 R +>> +/CIDToGIDMap /Identity +/Encoding << +/Differences [0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /gF4C /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /gF7C /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 +/g0 /g0 /gFA2] +/Type /Encoding +>> +/FirstChar 0 +/FontBBox [166 328 2460 -1763] +/FontDescriptor 2464 0 R +/FontMatrix [0.00048828125 0 0 -0.00048828125 0 0] +/LastChar 177 +/Resources << +/XObject << +/XgF4C 2465 0 R +/XgF7C 2466 0 R +/XgFA2 2467 0 R +>> +>> +/Subtype /Type3 +/ToUnicode 2468 0 R +/Type /Font +/Widths [1322 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 2812 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 2812 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 2812] +>> +endobj +228 0 obj +<< +/BaseFont /DAAAAA+Consolas +/DescendantFonts [2469 0 R] +/Encoding /Identity-H +/Subtype /Type0 +/ToUnicode 2470 0 R +/Type /Font +>> +endobj +229 0 obj +<< +/Filter /FlateDecode +/Length 10108 +>> +stream +x}[$;n{|6*}n۞ŢAR*";Y]tF1E%(m +WfL1lµ}øR ֧?\܆6}jk*A)l#]7#oy/{wZb W]u*hԲT:&aQWz )z٭dWtmOkk_v,j% 2BdV+Y-`[NK9i)cK9L-m9wr>-xPyظ 2b"BI[9JVþ*[P}! ,JldunPn/vC{%:x (K>(hWLyu{JQ~P=B9P׹NŔאNא9cQ׹ګ?:S^?:6폼8Cn3m7dJjf:n]UK~\lXo>¼P1с)+ǂt~!$i+pT/| x%0aHD~F9 wpْ +]MNs̶"~I~lečjjz`X,wLA3e>'5ʇP#KPҐ8s[0D)L.93QEWN],OLQgbR`KHC&kɹd@W(xHۥŌQ#-ߪlC<:e1!,cHC +uSzm&<O4xhYemf,̨0bliݐQ+ucCC.X#xL?`OL SdaTkJr5H)S:b;=F0`[~0b414ajrFD1uZ3*Fe͹鵙C(#B##f##F0FG`# ]1"`QF0L=`Du|VGs3>mf,̨0bliݐQ+ucCC.X#Q[4E#% !%ljT`FF0FTglk*I0/To)Uňb?M1JUYCw{#k"]X֘X Xʲ!F >W3HD$"؃D| &@w@"b: #v0"bK1یQDt̘0a;lliX1P+rcC="X!XBD}9"4bղM&ޙE0y?`AӄAQAۼU;{7хe-I}~1emBĖcLW/---HīlϭQ:t4w&<#]QG9Υ?Ƿȳ\- ]9~A_Jc~oC' +Rr' +SḺ~*v*ͪ n]ޣG +а>Ttf.]BS(g˙WFlIi͓>fvi")Iy%qxeK JI -&}lAbIerKm(#@|/mEswϓ_T_/@_UHBw)jfXVj+[淆[V6lٍ)VQa\H"Nݹ9a EĤDB=( DIfesޙ1WPE1,rLBtxဿCI"s'/LJ$N!3sV0~u(]INW]_0yJXS cg]Ld1xdj+tɾV$Ĵe+J&3r9Z qLU:>.(y*%/˜ڧOᶼRI\M(lSG_'r? *.Or+}‰v芢p%n<vP3aYvmc]BրTTgΙ79^[){;g;bG1.k1Mָȭ!6XjlU]/_ʂ{)Ksp֥P;ϾKݚ;dȷ/seN<'PbL%_=@uX2fҾ gD" {wB*+wb9) L0;0ƻ0F qȰg!"0;0;00;0uQP@?Q~2F T0ƹU3t5APDpLgʉJ,~VWBU+JQ<[élmgM#&.Rꋎ +eWhpVv)7iwh%:LyIk_B*W󕽤`N; vvn``,K̚ +wTayLwbBM`Ywz1b]̕ˏ +!};k};k,yJ>+~ `e7eǨޓU_EG7䔿څ 5?Xwg!Xdy:AnzXy׃,x ,AEV%t" \oU]% $9u''u913%+QYLdjm]Y?:>.,@454\ 8ܸh<3=`<15"! DUMvL@^ԺT4Zaj_+2hU4y@ը @ۨC3Gg ؞kR2f5jLJߘP1Ն_El/^05cA'\y@v=VkMN6~kW{=zY5-C _5_` d~];I dd? +LcT;W^[7z +y!w[M}MPC7a-i~g(zMPJn3ryS}o ES%cw)1E%]NA$j5#AvT>_r|\cԒc_yNedS_(.WUC<9dN}fES_ d"#yyJrc{45/1Mi˪?) +[hTUF`Zj:UP C}L>}\఻L(g3jq<uZ3Ue͸+yIzII +Jd5SɑҜz,ڬ7d bCJ# Ljŕ+=Ь{P:̼x07|$w%^1+ mU7\-?\df"Rƍ$h&_5)lKW[5%64g>Q9V`x2#E260ӓ3Z~l51*]Lg!leWh#`ǦI E4ɹ((ŕVJeWn!.k $IzlHiNMRն$+F 2xlZHH⫀74Ǭ'$-L{>,@& :ɓ0M}kQ<6M]YV*@HcS g$V A9?6IpzFd32xlZHB: *A]K`[#&~=AA\^ +s}՝:~}Sh}F t&;qSN47\7G~f_:_ȫD[j?~c4Ѡi(ެ^3"-r^*Waܙm<:H۫;7Lvyq0Sb8 +/&\]>T7Yl!xؒ7oCdƝ߄uŞ7<~/ ~77=BY1 AޜIC=Ee}-vd4ctAeix +TL/ DN~r^bJ7be0bdM7*dSs%`af[4Crpg(| 932L&Qv v)ʈI:zd|!Pns:p zGMMP+'ԃY{)HL|J1Gp!g0~Mf`.cd]FS^ !d4y%2g^μ&63}t[ %Ln H JdF&#ra#ͯ̒&vفqKj 6g*ml);p}btd92ŏ~_(;y?Zm#VDsZ F8bq~V ۺ6bYh=Z16ˢ18׋pjX=նkϘ·3k)~'=f/{1K~563lObq~> .bh;V[W.l2-6[4{ix`Kbc<dl@i؀0 i؂3 X= ulA%b`<= +WyQ>| + iW8,._ߐSXֺ̦ēj}wb0"=|4lF7p%ӷ1 %ߵB0BؚpIݶ^BXG7xy+n1"Th^{ak&LtO,‹\lBak_@§DžOr$1`JiT'ֳGm݃;>=Q\?[qC̋G0[74)&9O.M~Sa +4U2Qây)I=jXe[MaY#p^#V&j`}IU]֫ +Qέ+K_4G1j!!W[pW9}2ȐU7*`-9]U+Nե!T,y? C4''* *}tAebcAe @escA /Ro, [x9I˓QkPYɺ +*DKNrΨCGE%bCDP;{(#BI6BۉFʽÊ\ghw02RE*{˧= U] +OɩMu'=T] >Y$gpD!Y1ɓ Fs;Q/Nx4+Z$bv-vl,euHsY$m3Z,r^M3_$mc +ĩH\5 CX*qw}B +*weJ)Uy ^Onv5r_%M|o岥*;-_lXr|\9O/_]z y /{Sv?d1 e;s?%үMu _˗.8_2DC.JT:8 mڤM^jgɛZKͻ<%ofzՐ;!dC|[:9=é`$:[^>~h382s5",uV +x,p( P0RA! /|6w-Cv]?S(ۺY Fѳj|Tܢ Eyjy#[@J'91 +BZx)|3\^ypaGY{٠`*рCڤ\/gz3owpsV3*,M7®wp~8^=D*KpӋiI `c +|[o՗o߽^*<'VrY֗gJ~s](w=2"|wQ^^$yK2ka*P92Lw;I)Pm *>j}Q2٫dkl=V t\Sd^4M}z%d LA`A6*3Av+8Xr^Q '۬XrA@ sL0 Ũ_wxY2M޺> +endobj +231 0 obj +<< +/BaseFont /FAAAAA+MalgunGothicBold +/DescendantFonts [2473 0 R] +/Encoding /Identity-H +/Subtype /Type0 +/ToUnicode 2474 0 R +/Type /Font +>> +endobj +232 0 obj +<< +/Filter /FlateDecode +/Length 14868 +>> +stream +x}]m}}]}Ng,d\''m{8IzNUO͌m`o%R%C;ӯkw/|>K'/{8EWן~/w_ه̵ɗկ jJ=p??廿w?oɝ~˧O| +%B"?-emQ +Z8)Qk_-Gnʞ{s;Q?Yi-8?VVHJIu'&O-elTn)ElTnIt͈RԒҎ-hɧ[OD>kOrވ&[UrtSj|K4H)k1rX +}cXԬ*|㬵$>aUhSFq+uv,vr,v13ʦc؁C1Uj[y=#^5Β(nu-ż&^#K15ם3iL);k)浔ץJy] lnyN;P\x="^ؑ׵ʵx]1Tqֱ6:^f[bk:5j: +"VTalq~t EU۵lwRؗ(@C^_G˨Vʜ8ܪ Pm+}UKĎ=ܪX-UUݕj%j1f) Xrkf]T-Z_XB_fo'fJnLJuiZc bӨNf4O4Hp,R}dYmM=\(q.#[l.(vb-\pm.)q"Ewb-Gp{bod勚=rRL??rYq6.(vb-\pm.F(q7ڎ\mx-mC>m\F#[ KlTn#R};rc.WǑR>:(qɵ;\nv.9v:ŏi.ge0 S<ǐv"_(LcHݣ}t1[ҡ̥or(J?,Zv Lcs{݇,*4M'+9[IJbٹ iL.Ξ%O؈__<凗?Nj5IV߽|o._1ީџsm>Bŗtq\^f)sq=6܅*\L@R N?{w.;碫ɵ;]=MJJb%vyՊ=~g 8Uow' iw/N/yEVO]-WOP!V-z96{jj:GA;sTeΧ//ѿڅ{%k$р&UN}OEh'RkBugkd' }9ڼ\곖'`ms}(km}H샏~'Q B|՗J8sю:4"zx%@/Y#jsճOU.=3Lj^}!0^r FVJa*1{z րR//1?̱ Q7Y`xxمJ.5F۽nݘ ޤ0g%N-/ѵbR08 +y8.7.K~@!mt įt?յ3\a +cW\H+ .ģ+d +B&,`Wԃ+d{7!pD:EwiA uG-9Qȕ11+ys +D9@Λ2]3Y? ,uB1L1W8;#~]z9NLÏcdz&TJL, 7Q>5f1ı"eTII8E h&!HiV$}bJs|31>bi̓\u RQzrR^NкW< . fwpmq~,vG96q:\|`L8d6d*>0#E|`)wVg=TF氶Hd%/<+QPAM}є2Qk u05_R/?^dnXan4;sM+˼L%1F G5Uř#D'kyN-^]aWqh8f8 O!س`* 4#Ԕ8ڞmTu,W0ןP-%y.Ϳfi2kI]X-V>yt͇մvV#}qa58ʼnhNƣOJhʞ!}_łBdjjN|W-Z:v7ZZX˻kescՍ"3Eܭ\ucȢ䢿VkU=X⼴UIS[*Ҕ3ZjS5V$ǵBf'8Ɏxt{#:G0Lh+x@vaGhvhwPs&E(ڝh8d+*%oVkT$W«Yy.Jּ8H[;Ld^Q*Ȑga7 r04A:}?^w~)TJD^Q<*2f}^WDl AUZDȕ2?*Q +." Nzrka|ׂDc8aDs0r0ơL4`3&C.6ء)4v,\wq;7` n*>~3nu.ֵޜIAO +!9sQw$5Y(Bi B{x}{k:A0A!ok\D;qj힍-X}6?`p;vlD78$D S5}~Ч ˖BzhvD0g>#sDlt@/gL(( Q=ɐ@D栾L0@=RI􏗥hԉu9U@^W1φ<J+uʀ:sʀe|N _ŽNkuoZV#.^;8>wYz>wA}`T8w<`8[|зe{N@w D&u%!"ç|2~.Ѣ_)Pkդ$v8*('QVP F@bUz>p"Ud)% M4 P]{D_edJ J'@JT2%Bp]D@r:-6櫷r]Ḓ(A[S><Thf9^4S}1DNtl a@D(Y7Ԛ(5)\.Nj!0-@k8``MƼX8,Csnhո&tzB nL Boό.;Njs%K4 jzv{4Eis >~\>v% -wwUP -<犁)v̴㚖ZG9_̴-J,&"'s>4HqZk=Ue~Eb"q"$׋ȸ6z!jW*`9YQ'ZmY3( })U{-^df򑍄xB9ʆ_.[U6U#ʓvby5r8\:Wa"T +i*"ZӔ7]MjrR~|_,9jpF[\-=q{WqYYz&.EvJ֏K$"2/FKdz&"RxsBDJoCDq|.ˈmDP.̋B$v%*6fU%fZMKڕt@n"*yK"f#&TR33un b.EJ2/̪/R`XD0!d"XE})-JUT3|P`\F" }e1ںDbB2TMahԦZ'i#~:VT #ᴄR5/8^?NJO~^n݃ʴe^]},KO 퓖ꗯ!xLPp@+2 ISRkӘQzlS=Xd&g͂Kql]ѶElOE&87sYlKgF_T:䘆Ca֥46Fk;ml9z+K1],h:&?kq֒Ofw s:wWVs_S}>?vH:!9iREz9Z:1l)ϏͽKO-NY!ϭ=w;كox槩YkwP:;i YsLg n̘yuB[@dIq "J3;:kv"->gf#4(JZ-A>PdʟiY.`U -y8ЪR{2(9׼62ݡ#¤)"e)ŕUF3"I7{xQ2,EPgpOVEЧl8?Pe5lEf pQR/8Fج,[A>eچdqQcGu G>ądE}k>Iaxd i;!q?I69)5U2X(k|q'.T.[d юx;@H>Qid `J'Dmy~+H͈F~-ؒE)4i0INVMLAf{DW1tT@LQD%@ + l"fGhz-+ XR+TsŦe# +E b +R +%>q uS2Uq,hI3Z!4Cev6 +MEF5E֧A+U%=? QMD 1놨7T%_JA{7]:/͵ZM#r蚃X_;͒x%,-%,f@,gx͒{w9 ^䞵p%,>xhEw^"<TS8H+Ec|Z,][9I[]Y\ơX˂C_7a3+X#VVMF + -(!bx(Cե0)d@3$l2TCyCf4%AT? QC9ԳlL"#2PR&=jj >ؕ}9BrqW!xRxOLZ=q +O2rdv! 5"Rۤxv +xK!@ +<=-A3D<-ArDt6KIv+T}dZ-:Dg{D8 z\mU*i);"zJi`ژݩhJD/XƱ58ޠm:>&5=KMcz]-|j ǚ#HyTSg||ya]WqsT9NQ={QW*є2Z-S,}PQB P+ahy{D]˔Ņ7sg9L8wZםv؟G.Ons.;{SY6ҳiZx +\Si[2 WF7i/i+De1$_^krAe'[؀{%c' ݮilK٦ nwIOѾq1 X5v7,F$>! e[^`oJ=&(PJqdރvzLѬ.#" *cŪQ 3`Z`DCgaXFL|`M h;S اN-I^.511zog&4؝T,,L70Q{!ZucC9~9}dPz粬+ENJ-͈:BFk +MރIJ' 4K,O# +M!F%קMq [-hnWEF9g c&3L?f}/qfAieFz袤TwsL +w\pN]gCR]޽ݜұR-ڬ^<',:CFOB120)(%NY f3:.[4Oog $;Rhmmqyv#> =DIZT';7|19thmCs\-ytf~l mlK; K^7%U[pN^|M'oD5m14Mc;Y7BdQSX"j{vRȲ0t#J(*{]#&JaWBADP.{D_GȜe)IhcH4 +"qR(@9LIhŐh$?^d# juA۱YpH36Ѡ߱[H(}cSGz(0M|%k=U8 2te!.W (TPDS_R*lIwW=<ިrc@3KG9>E}8yZJ)vwY0"wW?+1%sKε;@B, Jxm?9i> K +*ݛ{:+2;- h]ܙ +Hv.{{w/]Rt5@{I"8K#g}uq̌\)W\KMNqrq(. +ed1r~wٽ^J[-/K]AߞM~|P~컡cx|\tJwk7kN,uxq} +yYō{R=i,=)$+m'ew:e]Gd!W$YHOxuO劕̼%%șY ) #Z g1HUC;0hPF_-恞Ug3i)3m:vnLL;hT$xi6Ǭ8m?9&k:ux昽.afs ᔠS%h*ǔu gVJ!(^KWruѢ⸚MT&qjgpL>W᠍ њT/h?gv97~<CR;$u]9y$݃n}KbgKikXcK&z"f\Ͼ{4aDL[ZnGc|$|4=}n̟@_# f)JKJkzzU*U}fp;.lAqnƑ<?Ӽw0u6䑏h'sW#>8Lo<^!1>.\ztWcccm1qvne~1kD_G4fՄ5nqlcD=t:nċUęBE7rPM}F5&V"<8mho>77>'>-)!ϠO(IOV4r<}<|-FI|-AM8T&qZg`dC |RL`S q> XpXSeo+Ѳ>y.G" giI1b̗O} d4Hp "7- ! +1̄hŰu5!10(2pȦQY=(E9D=b>F4j#ڈ[ADѦ* )(`{u3'uJEBXPTF)zB%A8@K@a@ͦq)8B/8gqԫ|:T`FShoKUYpO)H6DUG˸Sh9C۶L-Z*D=dvxxSqIXi!Jւ8X>Ue#S h&!HiV4#)wߴ%'ϊ\gD18[cǗ|Ϲs7E|o^N Hd]g:(+3ݗ/o3uq8E4.OW@ڵ8<=m)myCP8! +uW8,%V>9Tg.R'p!\r{ܵ.mhr@Ur0mc}9z$2~}p^bjG߈S7Ưa@'+ydH`/!|&g:@j6IӜZT62'Ҹn|ƥv, q+[Ʌzxn<T$ #^9EOTaIzfos@۴(3)2rao5)a39-UQEjvr3̿Ǘ &N9'_nݚ׹ߦa ܭ}V귝tTtTtTweV>wNn񒹴]w$h-8DZxhj#(ަ1DU3o[&m +B.&[p6v||6ځ͏jl~LlB\07-|w"(G Hő"oqntL崨gL}->H:k0ӂ8d>[e#V k4؉, +g5[~ .><3~ە}dypvwc̭wsQ9..IAcw)`0Q)(4Ba' qjPS\4H1NՍiꢺE$՝W Z 8/"]AuSxF ъ(4R&0QV]QW +֨xmOdB.ð7u (!O, +|1F/ʕ;}X-&Zk6PѪ}q={AKQ9IMjon4_p{5'%<`y?$vzRSgSw-3kD:Y+sD=D;Dbj"cj:J%e3.Y6%f=#/ 0C[BO:)R5Z+UZrOuEan8zhm3O@&C_2xGyͭ1(knTzVzZh+2<ϾXWrx6< +O}v&w7.*<2^WCޘ(#2ߍy &A䱴t8u֗/U~0>/Z|!>mOMD-` :zBpr-zf{w#^n7]2㣲9/33IAc`?&p`3 =Lxً)rpa:4M8]f +J +J~_5rz +|Qe8#-}%M64r&8`҈Um;uɮK*`7D&dR1 ;XݞR9*ʢ'jQ{uD|-Fk5aLpվFPT577k~/ȷWp2<]­pR}S' _ |fqtݒr-)WvKʕݒRҥOxz%nI[R햔+%e얔lq4P {YV4=.y@bi2D,^Sؓ4k9U/\}-yEX2K{]۵(=mkE׶Eѵa]mߤM}zeߤ^xıZk&ʾI$BDS}Î~ˮ .c䫱3]z5d~ η/L;&qlwy}Jpw[.ǝz}KFNL"UɅ}ttw ,z޸9~+ߪN)pGtpmѻE٢OۡGnW.WOu[ݯnoب Zs²>{Po2`B'_dJcWՓz-R⵪ 4$u7KԧoUN NAMN>Nm[Dd~: VFC ZAh<`}{mg4(iSÒn,ȇ ^?\$s5|髼yjzs]艤8L%T!69"qrTCez2D:z/Cԣey"L G+o;Zl_zvܘ#M8>2O(y~b:^W=ZOz^טD B.8ᅽ; /OǻPqBaG;ޅjxIvOulqh}8f8G9M6`!&C%6X7YO(1eS#_󃎧 Nv.ۥU.ew4ᤲjUF:l1\H{x1no?F* 9%Bг?A2ג}属%V{P|ulʕ>{e<3mi* 5W|fy—n8Vq|FtLڍ8D=iImFFI-'[TjoQaKok`D;mKw$ײߢB o'U~L]Iy薖e\7"/Wt]WrQ#|!Я;e}<S}^Gi[K%, 2CQ#"YO#_tMDD`{$1(pY蓏^-EH[*m#0FFҭ6R4[FR"6%4K[xF^[I+1xX4l'ׯ!`WQLec葂|?0n\D[,#=P3;<њg#.ȷ~;c|x,֍+ + OQz HTٖim4=V%MO +kgxuP%'/F9krh9 i:^-Bk\糲4m-n5^1҃B +#C&+ x#"aW{[KdtT4DOјF^•ED&BC7gM}e)Ö:Y^ۗf}ʱtZזϓnPФʧA6eəxZ4D|O*|.ZǑXx 8C8g(TJh;*N)x4G*S{,|3%|ք1מ΅@yCDQEi5\q(JT~y1JfXFCVXm0ʯC"Tո㨯,_go gxp>leX=x+{xw 92;^&8x D /.1S/&)ԘV6MOE&Ρ/~l pdTBIk<>6&P)>0V }aPP3Laj }s)`"{KՙC4ϧv40{Wy刽E{spGBUݻzZ9pS N4fKK0ی]Մ$i`D +DyD21hJ4@h4#[; tDrN+Ҕi)6v~>,'ǵ,)UN]v!#m$qF˕m3QqCUZK.3ҊXR +TŦ# +oVn+ +R %uAО׺8_2見cF+5aLpFP T7hC槁+vQL2s:>'6}- 8>YY1i\Knyi B.ٝgɢbghc-}Df'Wȧr/.^o9nQ]\odnWNU=7; ҡ^/Ա{+L9]UۋV躧})9ڛtQVGcX+5GrSA<&0GgZ>% @vBV7aq}T>_w.6G.v|o'"M^fma*?Oڼ^ Oman!)Vn2'!hٖ'?ؕ +endstream +endobj +233 0 obj +<< +/Filter /FlateDecode +/Length 12571 +>> +stream +x}[,q{z6@yyXb#Cc_D#1fN;ӝ"qHbοۏϗY˥ѕӟO翞v2&Ou?}tɇ3?ğr/yx~O9T1sH¿u)G٘aNJP2[OU~+}R;?矍,8X9sRRbg<-b΃Kl f|]խmf- TAmUO;mm[MVۦ͞i߁K+'qGT52U|>ޥR VE*J_x1SG_9f5: +Ҿ,Gn"1oʬ| "ODj PZkQk7jnjk%V"B >͐o + uWjQW.۶*VMz-wTboG0ҎZj1.Z %q추L,L,ńwL웬eG{&RC,L,E&vMFwL1r~č&Je7Lc"=uľwAwmV'Ù<104dFX]ZP.qpѰM7-hQ nQjCp.7 Inn x]EDņ=kg¶Xo r^8kBZHB[ڌ6 + I$-6\B&nu)6\bnnuYv[(Ȯny] 1TjZyb[^bYYw,ƭ d6@ 0m6ˁ+8pkt :I5*">-[q=U*B(+8Q xBșFꂜd=lAbR]q9/f_]ЇiW?Fz.աiM9bz\NL$Ri>*KbweB^]t>nJuC(Izms ~_@9+n7p%Vv3\͖NF >'WϟA%\9/^#Z4bfR4 +N_bsHk}~iʴD.i<"-GEGqrBheOlքj&e_ {Rۉfjy{m/=]jsgsZTCd||i}^z%P|r)ǖAt\jEcBClLm ^EN3uL]熭:IrSlE/{Y:+={W?}"p_ԌpOhZECvASZ2=De4NzAT;#Zidug(|.BysGpx+q6΃Wzq/ͥG3T&&hޒ"Uؓ>r+䲏=cO.:@4Ef):H4Y'=Q.}&u䎈 t{F CDZADǔ7maFաITL_JRTRJSx\-MtViJWp^U.E 7AT9VT*ȞEi\n ZV67FT6ъ?h*$&z<}W>~P\ÕJѸD19ײs=\/#N]]~|s9R0F˱!c#U(_l|OȨ2zԐ&d-CFBFűc- +-CF T_ܷӕFMĠ@ g1]6C{*U `Oq/சY€PD1zFoDoDnFnDnD Z1z"؞e(} ڌhe1 ZV&7FT6ш?h*$t&:<]W.~Th#F1Dc#0=DЈQö>0b#>"F~ѻ] 6bDoD n"#v#bu1dm15.f) .~> +R$Q (5ۘ#bKOC\XJ4B!V@mR.ˌmFIVi)KDHKIKˁj-+R?CWEM#2eEK#2 +&5m +OV78 +D5%kfС?C C <#0xڇޅ^@$X|=ʓ<ȥ1pv`eAĺ~dDnSD~Kh  vHەouDbM;"q'oB$'nP &XiE l$Q 9"8zK17t.l;&C"90A3L$ fP/Q4L_R4=ޥ46/̦żt++ Tg`q6EJc{}Qj\HI7i .iao5:~:n؛~$>;MKy^Rz&!cCnS~fhOw|p!пz\xI9KbdDOoo[HK2j +ꪋ E}_pCo3)<,1GN8]7"w-䰦^ +ܒW%S"6Fk3=\/]W>Ι\y`v#kHj&]/0{Si|CaR*sq>nBu,.4zqC\ Cq_  '=0R*D[zl3ri +qFnp2,@g9׉XK ?p/&X +20MƄv+C',YXk% h&[k"+Uաuh.ӃXGAW[GԱEZc+AZyN| +b/ZbZyBet1WbڳQaoEU=k4 ̶Ks4*۝ZwRMkPlGX%뱂sSv @4+E "2:vTʟ҈x;qh92_)2b@N]ȩ7vmL Tz'_"; 9rЖ5FpAtDC2Q̴ֲD_ +XR]kǖ'4 "D&Q=a +S2($V5[F TR+hӳh*#Ӕ7Sg~|h0PW`xŏ& ;_9UVnҼ`}G6׻ 5&>|+_%\ֻٖ.Z&%u_<$De޻ ߻b^ aCme~%FnmⰥ(qZ9zom?zoCn[1zomi<(]+} hMFS#Q !>)c̫r!UDSĞ&"P +Ƙ\XlGqi)/Vl&O&*"}v:I:dC$Y$/&oN+6=rUA߭(Չ5[+46\?hot:G V4>*l_Ƈ{oAcЕC- z!d3LK&dmo0. 2g~3W@L lp4 K +u8R<їa5q4GSAIHo׍q:|T"5QLjT# \+t `CU`B4A`MTVL";ZQzɸ<=g4oH*8/=c=M2b\+9}h?6I(5rEDiu@?l/ &Q KM@aA3x7Axa$fLޙ  # C(ڍՉ&5h!4q; =i =ԩN~Plvƕz})o3?lg *#2 ̧axa 8`Q8&@`I U +y02hAb(\APL˸S-cї>'=j5VfZ{D$Ƃj)Q"Ʉh:dVNBȋJ `FkvEbyd$ƒP8<yT(`'|P +p( EMPvDV FSВh2Z!lmPyD[վU^|OTPSyPՠQ qy}94~j{.|x?CHZd[:4ݱ.av8[N2c %5 !ݑz<SxDl09ʒ$a{w/FJ%/i-cr{-W2SwKz_XU-t΃jwÌK^p260͹ڶJ8bBC9q%xUNm,ep+^%2-1 5(%҉_N^F1bxhdKѿyA4&0휋wv*JG[쇤:YLvV QY'I״1-]%*Ͳ2Ȅh:SMWJ>QT_Gc!>v4VKc6#fzw6Q$yqcT#PYy.", u%FF4&kNYDԞ.p/TASjtHUAd(OjGiw煅_t|M uVj 呑ĸC2 CדG孰 x) ;a+F"a$,} a 1g:NFcUK .{>7vfG a"!H5MǃSD텡 &Y="hi*A5T%h4G0YHUxŀ0&і1뀮Aq`+|%WRsX[k¸悮H0t,qlNkuK*/d Ս'kϮ{OAv.\9ΏYvkUz]\$yÎcgV}H֦/w? g >TJ$kv< Df@5ٷ@)dyG[~VWk/B}X1LP]a¿ +%&Tx1̀2 =C1Z +"^j>ϟ|8 <2Zﺣ镎Fx/y3J +Oq6o`=2uKDQm8h0A}GW0K#^Cm|$m$Q(Ά59 x"B 6ЂLhAZ{ +-( -(2B *aB jKblsU!Ҳ-xF4hނi.)i +1.em+qM1\z#c-G1.>Yԇ9KӸ ޅTC݅D4 ZjHGWUi"I8v Q.!*$B"*iB۩'y)\䀄^#HlKc[qrĶwm{_=D-[-}pK}RR7ZJx$#$(YhEMU3H d:LddCD!*C"f[wTucƧC%GȽyqmسM&cO )WN-~H$7L|w`H]nNx^(DW5;UhZGkD+=*h!wpz}kJPުT>*֥ry< Vb_y&=s$]l<,xȷ)ҋJY^StьI]VDy+1H!ޚA#^jO=& +#dH4,&aB0D J<-E[ +leD(lUPj#@aZ +ߚ(Uk#@T[E4>F[ĵuOoD;mL-X>{N2BQaM;mUއ'b-$gq!*??eSQ)2Q'N7Jۄ(mBTsƢ Q7&"mM!щ6j 1 QD܆(yR~ySs~3oy[E8M`ߘianlpbb2I '<Ƨ&==lGyq\݇q?ij>ݚ4Y^D94ޗDtkDdy uLxTdrF48FB}?P)8ѱEE觪IbR~uvlcB= lS )oTdZ)ҩlS5NrZlmm*nݦjئ"vhm*٦bnS$sD7QHˡ$Ah+hԳ`*t"Ӕ7jS5~|Xz<7jѲH#%_R-%ߍ<(U9uv}*RwO|_NْT-tF#΋a1^U-6ԡH}|j\[KF8egy^YfaES3ZޤfO 6t+]($v[DEl'!q] ԤuϭOhJ\溬f +K*؁.+d!.] +{˥3u?'CSYPG3!?OXhrTW49.39X,]).39S49X49^,GUSF6( l zZ^'gXuhXVrZiO0);[ߣ^ybU09c$e"_Raz]y~VUү)XYS:䌊^j80=97+KLW0A",18'1~͍>MhdoK04Ԭk.SRv+oMB8"R$1uTvimҚ߇wᵹ[mBݤJ!.}ruҪ$4>W E-NJp2{k9R3[[і`@c[c&Ǥ} 6[9&D6"mc[wrLmD6b;1Nt=?~ңb$f-H=b!hϜ7p%.(n.CdCD "&C"jqY*i#kɣ,5cczM2^yM2A ddr+$( u-5T5DŽ55DŽgю>d6L} tsLLeViCI35DŽj,?>>`Xd}_`ZYRدK{h({z~h<ʞnFFpi-uP]> +stream +x}],;n~6Z3s/ k$%USU}novN5[-Q% +UwzqKۏ__1-ҭyɵ-@nOחۿKXfOW.$usǗM? -T7FQp>+Xc._o)6mCk[q4^*C?uVԲjS(63T`Ri(e:PZp77)l3@K !e;X厕2ox7ZaEq]__`Jٶje]kV"hF (C\Y4{Hm{xټn wX42T˞Es_&{MavEuJPf3۾T3 nPݴ2]EbQZv}թUSkأG,+l|͂ u52DhsoZH_7qNq'xo _+񄗍؏]y߫w +귘nv+&XCC,:\@+S}jSkV`;C8Io3ĕ dxM Cbt{J̭&%fƆ!9 GbnH0푘L;$vC$ش +GbnH0H2N& -sb]1?ןZ#8堄%g]-}DG4} 0ii7vK֑ao_ m~k4h@V[5U(H}R7qCJjC1jCj3b p٘IcpXҶmm3fԙ x IYEl 175 2^L uiw=]Vy͜@tٴÎw0qcc{\Vk{\fujfurSI&\fN6N ׽1K&wέ״mml;I-muKmtK`KM6o_;Gcx0t|hBK̕n J&N ca|B$(1D.,$XJ67K#\`*d0,(P^JMUZR5"X7"EKY`B_RS 7 +00aRS}U.!U׋RK,@CL`1 1LS- AP%b (פ1:vL +qU~Bײp\U Y )@h#7 &"() pQ`yr ,h(+uTkM7el1Q`4lb[]pIIꘋi7k'>NI29j;k\q9xוqC~yG/ƛ$^kL_~}=//_{KA.u7<8iA׳a!<${}@ǿqW6SLj%%# 0X8 +r]C٠CbQ@\8[RE~In-H'1,08a`DE8pBId%(ۏDOy\$ؾ!A#CӐNDWȲ4e3pʊM'3P bV`)CRk qX~/SBt,HG/` ӂKhÏ9Zy$*D@#j%scʬBvy +Ld]d*%>_t^z^lh2iٱܧe}SN#;^V{}4y|,`*j + ` 2|78;~g&z ґ/q lb +êDt[0ov಻(WʧTD;daH ;pd fdߥi}*:D^b7/ȏy@"2 l 2bbo߀"pޟyXsw9%m%JYg%HK7Q4=#geyFݶt'KIxFJ3r2jJQC!^Z8'P1a&0KU@\*U&>i"@y9~ cXGkG ;Y&p2Z6\ڀ 񯥹?79TnѮr}bܨWvW^Hz^^:^>L$sv"߉5C{FSL~s^~ jR4x2C{n~V;iooնX>NddWdj~ }~˟"6gOljr<#y;ys@ng e ﭬVSrYd~8^]*IZHPyϽ[yϽ[+/1B+>Gs":D`xgĖ@I1%ȅ_8}^ﹼZ63wfšw- [9A*b^b gnoD*lzc 5 8~q$S]jV%_M ᯦J S]L^!!SF), M:Fs@m BQ I-]EX( +ZI"P$r mkbze>?ՂMKgOCxd-LAa[Z$3T-8NbGl1M`j@ n*c}|Iȉf}tm뫗b3{1/<ܺnx)!y#횽?g08ĸ(rgqvn`aMI"0#`W\*/_MZo)z}Yt/__ߚņv&|U"#sviNU E"7q}߹( +,rE"oC0w7yl'pDZNg \S# +]Rw9R*< XYiĂ~{ ìf۟v8ngS>o(AFMTM@D1p&.VL'"F5=M~2]1ק6`p.Uu[[M\` t}_s{u)eZ~@N^@wvpUgtj_qRANFvVNȐeFn1Z F~1ZN +L3#qd/Y.-ƞ1G6$8'M ~R嘸%b,' Ydj. (d%#O4m#4:=)О ',PN=ė{lF-6H(xspO (%Qb^Ǡ#}FN[yF G#?OFz9h +rm"k3gq23+씺qq1,a +o5+пv6 bcfDl^gDj8æ";}Wd7)i?Ȝ P4>cGXҳz|ң=ZԫazPKL`( O*P90RUfKW Nzz: ToE8(؝sN c'M?_f2cfY,ݱ o~6Aw ywQ= h>ړM~#k~R272ll%1FWkmOw|]l3mqٻ~-hQS|+~&@gb>|z` `fڥ1_r}w09twbx^tUOvp%3"2OE'3v c̬ɱ7=-9Aj2[Nr|i|/7zM5@><>_i,Ԙ8d!'0V6ݮ=;qPI^KʘE벝z:>um9Md~]ec6/Kӂ[ Z p}\ȯ-~> +nۏk%KimDnK7HmGmJ~}gk=Q6G!mBfO;<^* GwZE[e/ȫ&I9mtcSxs'wa>SxgS2ut'FcޱIμ>"+$MWten,vf l$$v݊.N֟a)裔#r/cz"^Pt%uLm,^Pox5I4s]FӑO<ɲ_\2pONSnzBA~|5' `D@h ߒ3ţ?9:>$cUcS>fuNJztlxah!'ڼ&VWy{.6Dpm|]Ͼ7=ϟ$eFME :[zAgut\zAgGwG+>fݧC"(\e䉻uߺ31@ 'iܰAtrXFX!N1#3>[o6D%4q$b'Чc ݡ[K6^C +Eߜbuԑt-r*%c3/p`[nVi}YSk/k))/%[7!ŗ?u[d"IQ;n LϚ &.K'"6'\.1(eEr+MaQvDY% [vlx)9LXz%Р޼.[Uo|_Ux,Ԝ}'esyT#R^m\'ĩp*bDáqx2,"}_#s^@Vv;LVg|+, +rc!(Vg&ZR(. ;d]g*׃&V[[ rTR]KS9vDž\S^_l0~$ dldqM ӃA21N]]?ۥ&q/kn}RNvm7]LӺZ슨b/aTmVЋ; HzɻL[(aᢅ2=ժVH LdduI2Aj_yr}c{c;!:aPrMj3 @=p~7ƭdX<'0{㝧@jf9"2Oȸ[h{LѪ`S2<)Ye ?"J!9W#=%S[͞)Ϟ;)[=2@[EsezR^zC/5C/_^;^bdlvJukJq7^O;>?'w(+xVҴ{^O}Nk[it`**ccjsXc,c\X1ܬXXW8X%ɓ|/ʼ2+M5]y7b.pQQ\,3Gf5v;L+gtbe`^>{!VN+}%K]>ʝibN>rxKk6 )}qյӬ痆*e*TKHT_){a 7Ow;`ZPj`ҪدЪdՄ~'k=><z6֣T-ӗ &jVEE,F_I)goAqBڲ'@6CL`R5~:MU $"Jx '2 TuƉ)_'d|-  ZU6(oo/HrXJ/~6+ܼKqP 툎%[=Kha=oJhac_ -lSbO/^zC/3C/\cd/E/}*^I{ uj%׾]\2Tۂ9Oi+aӊӸ3$ۛQGDWN +Ҫz$zq0Aj@5Үt]X7JI"]I9$[f1)w܁`ul|ͮ56V5XbL&Ui +WMV5Xɪ+ʎ! +mƸ`Vշ*{^ćM7~ޫS,Oa> +stream +x]_km8rHlLڇH@>ME17A/HJ:=ǞE sLIERc-}/_8kB^CZSDH闿/85 +7{M`Ģ/_kI)/χ~ÿo/ˏ?,a`ɀK/\/?^>8X"Ģr"vÍ7cW}!U\PVJ5@BkB@(|9 RjZkbj#1%Z0!hɗ6Ry͕YsEHFcHeAnh1˷q\cr"'Rڂ/=گr+pu\\FX!U1VP1SU(B&Rl!dZ:&j#hZddqq1J-4}nW E(ĘV&& "7F5d/pJ:M5B-*&x{3+L-98nn83iRt o_7/|C?_Ypz*|#7JgJW ++t^ `pOhLJ]B/ +v _B@8kU|ɣ/ldpqsv7:s Y! CxCt}8PjSJ uT=W|_9+5|ELh1a r,W&K5 Xiro h2.ɼ6OU4m'!~2@%:c3`*AqƟj6PWV7 + x8n?CIDQA:2^y(PC2<M%:4!VdMh]@&22CTE6< E:0Ǫs4{,hj2 mB(0sBDf]"ЮYȬK~:275{}B^v0ǽO2/Îx]327L5m6~"7݄v3pt17ݘqV2gCݒ&GNi +v“86T>:MtrO t/?@z!dCഢ6:Yp>4lXWu2HP֐B V$$5#J^CyhӗFk̝ ;фkA)c5gO8 kbڣ8 F[K}"5Ce٘H&ʕ]?$^eaC=XY܆ 5Sײh4ta&iƦ?\7EQ^1?=ڸ[j[·-Qy)uLgTӫIQpK9˿ƹk?e2w:f8nt~8>wqbw}?mI D;+uO[\ymn9hw ;ϵ cOtyu|P5H4wmzk}mAyPߦ^ѭ %ʘzT,c<=CmpG9UÏc-juWuf`D1ѿx|03xyDZ+e33oS.5<3xkr\oN߇PsNCZo/qb81Y,s5YU9 +݈.ZX@ 9 hslslad(w"T"1l3NnlSč6%P._ccQzw[F6Zm]~ӟ" JL>RsrH*x:kBSdKpܧP E-l1Ic;cŋ[# @6JrC"QxjϻY +Uo,'-b>G:Bޒ&,S#i5F\6d)&L6@8 "ڏ|3@$B^k | MT=21I"\~SˌuY#/kHWFBB\L-6ވM"6!L>iV 7Unś XIwcB| oC'C3طi:Q-pXyx4@U-yǤ&#yǤQ/ ْwL`DKIN"i(IJJTݸْw=i"4K1kvUSBCiLˁKˣDr|hdrT I̵)Tp D Qpb,TF'P19! +-ʐP+FsWҬc%d*:aza]5N h->&X9X%::1IbN)X;Il4ʆbR] +5&Y0ͅ4k:i\ݜ&m4OЅ4MdbC56 vkx1;.%nSq+s1;vQgsBۭCj+wiϯɾ->mwn쎭*Ba{gnyHK3+wJOc1z랻u{5Xuwĵ#~͑GBDtSX+P0QmÝ;,i(۾BROc]jDV^+afӶiQ'`Z>~SoUel)K0w9W/דg4|mI?(e[6(6J$$)&hURU_lY1&?} X{MZ +e䄦дh%&srx! +]5Cea*=O5(Ė=XX +eRT&W/=EwYōN!JkxWd{T_x{3'K+z9YѷsOT^lM?-ǭTr%Ҥ%yy.}wE˭ӴksJu񳡿gMhG?_XFmJ3Mjv{~J_oDa-Cn+=FnVcqb+u~aoOJ`sۖ#($rRz+K#[=k쩐ٯUhjVՕ-#)E"֥hVVL6zPRNPR#bDKgETj8&m!&EuOK@gtBNE +\ Qf\61hiJ c26h3ԨsaJ'a YRE + jEX8ֿZ鞧Cۗ +H}W+mTVP$,JZ n@ʒQ!J5^uF{z?_tӨ3m4e蘭}4~o6eYN!toC=de? #`ԁh{KާҽoG޹2 po{w/npT +l2Gڿ_amਤcz`T7C@uҶ:Es0GzK(˼W4qmS_-*[f胮Ժ9?QK6hx|=CA[vv/uN}Nf,iRhU?-[6cTh\G"堇dd&E1!*nd~:Nyﷻ˃7]_')o!cIky +xq_46^w~yC'eX yжV XƑ !ׇeLC:bټI=+4s;{!$ Fș:g Nt{*A>f6mGٴkS⿱d]0^pTvM(V+.Tq^Fiݔz6d?7 9ĩ4#, r)ynR\ztA$Vl5wtg!0CZMCJG!:ؾ$>pq]qZv%W v~YO̐Yym_ i%)P%{*87ʷA `z\o[/&i<FH|۠%:8r˔GO˔dSr˔@0Jzcn1kit;creO2t&;L7񽦛2U8?`nnzh}tӣ{ՙlwutmս|ۗ2`w8SoXlۆ=Mz[t\[to9G|_ o1iki4m!o:?h*- O; &w?Rq zZ[f]ѻ<%@^-fBP:<};hkǔwq . &)bDgL=K 0|oW8,G"zs#|{򸾍r{ ($6ygpR%^ׁ嫖>W<>WL>dK 4[rwuaf~4fL<'ܝӻs +N]?<>ȱ>TVZ|^kGOy uqUj@uZ=i8Ǻf+a[ֳ̠֢ +^tPhߝ]er_9j*7΋di6WyYNSlkiMS|d]Ll4'?cd]ŸTVw $Vm!njj?QǷ$:wᴍ7靎' ~*_,0>W|TM]l9>)s%RWV,!e;4G?1Ij,3:cnA'j?D5,\z[uP DO!f㐞jd)~lǶ4 S(S&E> w(nsV&;u"wc6`vFh2cojwb<ƮA=f0ؽ m ҷ=,wL? 4:xAv"xuӁiV4+c2WiYNSl4'c4kp>Bd5]gSl)r sﯗEXst8|/A +endstream +endobj +236 0 obj +<< +/Filter /FlateDecode +/Length 9368 +>> +stream +x}َ$ɑ{~E> dVU.@`$Hj) vEVuFvB TWUv]2p-_tSJgKj[3 4O_>l)#&W?gFGju9?~r9_ow/ _~2t]! [m33l R`}8`jC`qrʰ!:A6lu*k眶,SU"EO>34!rΙՊ +Lom,rιЃ*Y94.7,inPgh`X@[z 2F0_8%qz`Q!bn0H6{;U`bYgA>1$KqE?AViՂMlf!05a3(lB[)"SJ>C+"up{# =ZԡraiD Z)0B K1WFvv '}{[vG$w2!t~?'-vK}ӬF]5͆Yp7z8̓ˍ0|D;d)2=ڋ|GFFD^soY"b(ne τYzs<^y* f*3i\'3i)_ڧ3GGq`\/O5tҷ!Ztߐ>5e*i&=WvϩϭT,+dN +F.:(- S[%Spo:ܑ~nܺBriu{\r*s5KO_Y yKn!R;45) pF)ӱ"yy"Wglfj8San_YD[C^]SR_[k[/L;E<졕C귣Ɔq)mJ f,a]!VAXsãVԏc D8c xjOʜ|/щrG==.oaX)9~/3m D'5X\sۼk :{,y3?˼:bXtYa= +<cV7cUGfX'xI̷,bˊ"G|},+FC>`E'>6o%c9-NT>c._}ooo[n/ٟn!:!~BHܩ ϧ\ +_,ka\~z_ +e xiإZ'jnS}!Ex1^<"0$6 !.¬h!Cf i2bM5ҕ +Q4+^E)8rݪD8wMt_cPvyn߮޴zJsn88 ʘ`Nϩ^ -,mp-Рkd +uuGATmjDaZ\fN(NNj?\7#//j`RE/lZQDVLcԁQOyl;6Xz|6wBxɟQh'JIgbQ +k`mV0[VrMW/[v7ZÕbcĄt݌h #iMwϾ{^2WW3wv8-w|r\nO>w;'cxF&!`"T+:nPnL.Oɫp8K.i:\f`rO`1S0BA01S0B@5SPWpٽRm=dr"e]=PJu6j@03̕:Z`TT6w,0q-oWI*fc9Iem;gYulr8;}MCLGBٹl][d" ںwPE.O;>GwcMkƹcXЎw`8ډ!s'^ ;Q4h$85AgT +ӏuMp% x@g%C$-bUI$菝]fn Xoj޾U ӏX y&v k]|ڻ)sde^{ js) .Ѩ^JldRX#V/;VLA V-}ASZ[KLڲvLHbVv1 wq,v2Ɓ0~%NPR{%`LE,^3L¡N7=kQ3]e{e"U[P B{&̺Or 6`_iw,;O+xvc9Ѯ5g6_f&:B!o. j^7B޲9X4%"ǁ?@qm@9M_Yڜ+|"%m>|ZG#AW6' "ބE=$ŗS(}ENk[;ey+KJvG M$Hnr","[ Gp,QqF +؎脉t~5i[:Hruiԕ*1`>o1d5dž{rW a!m񸲳6TM7|A +a6X&hF~4vb]CT#lJz0h4U]9RŔ"7&m>ҢA?\+`=mO6Q4Qc(Z}mDeY ҪE^4?m{ |O7[Ѽ3mһ8@ľmKAK%dwA%fN A֊sed k /l<LP-ۃ"J%c>Oԅ +KE{$&}lӤ!w QH0-t&:8aQ0$Wn9v}yQ$8Oq=[ [Pɞ5<@0#(q@%׳w"i o#78wlkڱN M;1|LP<vkt!qG{2)X-טbp5bepAҘUs`?G~0QzK𐾿&C!V›nQ/R$AIW-ۗ1 T)owL]{8;ALbNcm!r֣5^!ӂ nI}+X08.WUkf\2̔` *EXۛhZQ(@tmS|h!̃S.cT'}&t.V9Crּⅉ"#ě+&^2B^{nBC`daфK VM4[ƖG#s ARRܓX^FovY_l{ d!Y:j`w+l{ {ÖLN|!~ǰ\{ǰMƍ-L|pr}Vgp}4 "!yA|ŇV9w4ZUϧGqIqՓk/ q6خ=A9ǃgU,q6j՗#gQN'㝠E +"I>9[!*끑ɺdw+I70DMt"}qC@ƀCyneHr ! M>r@[|A +cZYGP1鮛8)4?"3Y "Z1kmufެہh!)r=]GƴAFDV_2a(cBXhRt4~s(~.o1*N!&Di+hm')y`ꄭQ#>^5.piُGfp-O5mqSX$q6U,mRQ| y_qи,wc;R5wcu)ʫFi'*{?&D8F?fU]3 +D{Np|Ο ^oK^JuRsY^hWü88*h-G)tDy52d?JQ-y^hM#ȩ׏=wBfWnc!5U[^P8-${6 +j8j^u^~}j3@uVSz |D+:κ TB@ƨ Fl"eV'Z=iFɷD>:-PrI,4YuHk7[Mz;Mdhbթ5@>V='hٳ0Ն`ۋ) }S#O{7 +9=h$&ѭ~%OM3Į]1s1g4Xď)FSݮ=#]LFҙBb]DwGN'#Xȃ6ȫ6kґ =QN AQ.Q@|.OS؏.YA +J=ip|={/A]7kpƱN#EjN 6~6 Ma'lv i~ѿ лO06 >aC0:IS%0VY tO, %\AbyelaTWH19lI1ЪxG`@6+2X]b47z(A+#}*0֬2L5 (h}Uqtѩm]Òպ%#M[Wiކ|ۆmփpuLd`M5(%;(c Q@Aj&Oӷ#\,5K% -ը~*ԃ~W?~R"iQoH#V8˹%sEQbvk;"QX<ׄ=as,`f }V]ɪ +O*ߖqC?rڈCjvM;ZƴtԯP=G*cnbZuk+Тl;0Jרk2Oì:5* tMPi@6Wiӣ;6G#xV }]X;.#A ֒f-NABq-zq>Y}ՠlI\zӍq|GG JܳC?Jq6ۈEvʁN= +ԓzH^[L9OjgQ3ήZjYV;qʡWM5ޜd}wtep0a+$ u(yL{+;Sybg Q5^52cT\jOZ4ɋ}'-0¼0䶙b2GCN=mQlڑI.10+4w-Uc`W׌b "z1 TA+.[vG +8?[d>#+m_牽S9rmPH,kqmg  w>O ;Wo p՚QЪjᴨ־*őժİ+\J_^`t=oOqygKlfqv;(& +3]xpՕ9 +'&|*lbt<=ms0!*jw_=$n;&\XKqWDJ +IMW?RQSs0=||^+zYӬd +LC; :EMci&}"amPFKq +,TJsLJ/3|`jt:'6<İ|Li9C_f[CM<2vo_X32q9; +y< {ۆ-](һeU+C~O,GՆK֣jCT.GՆ1R: s1%),JFS"ԭw. +)U +#W+Lҋ3b`w`Ce`WL`0  * T A4*B;gh> +/CIDToGIDMap /Identity +/Encoding << +/Differences [0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 +/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /gF4C] +/Type /Encoding +>> +/FirstChar 0 +/FontBBox [134 287 2460 -1517] +/FontDescriptor 2477 0 R +/FontMatrix [0.00048828125 0 0 -0.00048828125 0 0] +/LastChar 91 +/Resources << +/XObject << +/XgF4C 2478 0 R +>> +>> +/Subtype /Type3 +/ToUnicode 2479 0 R +/Type /Font +/Widths [1322 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 2812] +>> +endobj +238 0 obj +<< +/BaseFont /HAAAAA+Consolas-Bold +/DescendantFonts [2480 0 R] +/Encoding /Identity-H +/Subtype /Type0 +/ToUnicode 2481 0 R +/Type /Font +>> +endobj +239 0 obj +<< +/Filter /FlateDecode +/Length 6713 +>> +stream +x][$m~_\DQ L΃8YslKQUU36N7jWQBW(K"0-H?\~O?_z [o!?]t_]p_~5]<BpM]Qe)v<ç_NwT8\)+-bkơ5fK_w zutWz'z +:t|^*5+ !\\avM\WmG(s*w@oƼk65͘"0?@\o7Pl*D[YlZ)&YlMd֘v縉ZU*ٖYB'-1 1cP1TnM=QSYUBvֹiVu5fYgf4Ng v|SYTe%BWc!p)Y1JXL9\?_IE]`biGWYb(P˸pL)*JeE[)b )_BoRe+m)ߟ/>¦m,Xh`TaEe1L +B:jBQ,X1 +WhY\rNڢSUW[XJXp8\#w -@WH%2BM`]8%,eb K,(KXR6SL K.+AykUlj>^Zj_+Fiy6r;IwUVsvu'|Ͼ*{|v4fw +,+ +Ŕ!ĸ49b(g9^+ +"`r69wGY `Yc.;vN=6N'Rv3,JC+T1Xb5\+I1 zW,|^Tb}^\+|'֧GC?ndgFgg֎kC>OG9;q.:t]R{B578'WT*pz~"W!@ w{}~m^᜽œ]8V 8sܴkyP92^=} +i)&+)+#} +eFz^э+z}м^& ׏׻ ^Q;8/rt$iƹ_wCGdL9U^%.Kbh/!l^+z zŶ^z2{~vz}naS 8p:_Bq>e眯 yCΙ%3,xM~lŬxWd>Sڹb[Wln +nIsџs{7Ajǵ!&MΝ 8\~AùuǞ0}x5֥fˏ @[G\2[/#fİތFE\^ >'Ϩ*`h񭽓z=EB u:Î5cvf ַC Wqp6Vcb))^(W@U% o pQӒ~ ff;eRsdoxƏ2 + :F\3@X $۩|PchCh?]SNP;> +禸,O$g0K>e:L씙}$:Wfl\'ȷU I&ePV TŶ1Hm5SkEu! +|]0ZO'[z6r1) ؀mvpb w[Mr& dwF汖|S|{ mo0d٦51?04OA64aB_#ʭM/gH/0G@K E+pCy?ˡc$NEMbړД?HX]_~Ƃ#aL%i,$͛bG̨)C5"BeɚlҎb.XQ.ICXR ˌY*F$lVJ䊂~[9 ߾F K(+1W(brXRxQQFfGB9Tu8 )O*5$9(PrSL +ZBiİU~_] +&@@ѨNAWNjb9:hGJ[1P-ZtgMdi7S>^)dF͸ ę9s!գVi;jqڵ7\Ny8-8e7CIX&%eF[?D!ZĞu?g-SOlsԅ A0[NI$|lOa]T1;?_ؤh[QNH0$ML%o?P!|%ײBg[zd@,Y!qg+JYB` j+f\$'LW$KJꭘB.5W̲tfBum| iAVБqxu=#-kG $) d1ܾڐ. 3uHZD=9h(Hsme/I[O *b r:Sȩr)}sg-:-#uZf:ǂz"e $^'/ss]΃[TG[MyH^BNe<5`3rpc1s_*#TF}R8yc۩ms=FГKs7}puV-wܻrQ3E!u'Alee!B-ǑZ aZ;he%-ey@5RK}ט,Vخ@BmNbQTL#I[}*[6F5*c}Zh[7:5 aSQ%GbOˎ "]cE (qBTLuk䭨:j kE]DM׋ob!!K/9s݀9V8}Kyp{?/E.ue*U3\bxnj܊'cM'}N&ﭱ:mh2&lH~Ǯs.iSK0di~Ah kk=8r=T;[q]w&&Zr[CuM 6 +ֽQK0̰cEoQ`zWc7KOụͬʋ{1`= aGCxje/l{'G'ҚZwr8IKmV.nK깅a,HWLҦԖ6{:&ThKqBc= +QuVbOT#HY[hjW'0uڦgڳEJ~DE5^9RcX jv~hD5G X&a+l29S bK}UJsSb֐{hZx֐QL  i"/,I-hyJji $U*Ĵ\l.?VQۛXav*wv{BZ]һؐšMݵza[5䞕jvFQ Z`|J.z9 )`\Z0yoýNwOߜ%9Y-'WF]S +蓲 fI'xa6wA]_Vm..)ؔr\BtĥNkup*rzhiIrNSfZO`^$B>-]J}`U'eUJ𕹭\I{.gJ )ɷcqYcyLsbΥN<[9Ӛ +Y9i띿Ng.wEt#ytf >#,u䬗Zq#_t}֐]<<^+9IȴZ%mK?D,KAk3Z+ɏ-Z^aUzZO9Iif!vWnʐ6A2ۺ\c7  +Sd$msFb[sj6,``MlؖCӥx$5.&+\ۜ{*Q֔`:*\FRcerw +A}| T^_vd~jU@@\,yRQ +GbhpJ%ǰZӔl-+9!*ERyjưn: ?_꣥}Kȗ:t0oCk6x(5y{(q:r^>1ʬQgkjP{\N{1Mrխe7t2db;v&_yܡir.Ɇ':2? [|Mz$gUr/k8R:][vv3%|MgI!-9Axs:H! 7|f 9Mg 3rcEp| zMK $knc]T>ZjD#0^&*w8*44:44WNGA`og/f3 PmΊ8mݵӭĦ_T,ۢjحFҷ/omYmnhE|4"pGy98Cos;5Lg i +a? +qw̍jXWZa>NPKM?C8w8BE_:)E7JPϵ+?V2wJ $C~P_#Y|R> +stream +x}ێ,9n{~E<h$ + *>؀=Q=<ujS,E.QRR7f1&r &a) ԧ_x׿rϋ|V[#fdz^ɇ4-?_~{7.?_/?c=I >p`8D0sH4ȉ|O +r8L.!*Tk˘ +o}Èo98TZByn"dW`\ԷI seĉ63l%}i yK.@!LaC3 P#L43Ea2/fWߖ$C +R[$*R72Z*`b`ΰܮt]S! &S00!ʴ їj Ѱ7d3tȰ2'FMO?9&rN-?^iK8|mƆ1Siz9 dc[vl-e +ZTi +v`z"~''=/{sn7>?dE3['(hR nӪ I5ڢCjbSe!,)dHkftf:(آv PT_ +K\= _hUƘuѬ ;=2Bm @dCUV_5VւlI벙/eCxC}]ꦶ7|'lVh}O( W4[LldOs Hĵ,iIN2leFHdOd/<({zad/0dOa9wIIgOt,&0ݙfr>3Qy&2l6YIrRɞzq 7k;:V䖩ޤz +cOh0J8xMЦz +dmU jer5ӧEڙDc3h`hji3f;J:=~ër1٥̸y߱dl^\y!l{ؼ6{66+lc +\ۼN룵ylc1*h3 3J` Jg1Jh܂{KeJv4}qOg9Ԝads4wlevmvE[Uh-4VzV V[HZ![o̱vҘ,jO5XmU~=u0HNwqrHP\r +s[H\e>c|8pn[GAgxAEa| {󜁹`s`{.By~䚼@ʅ_:#I&f) i&͎Uy|^aҪ~BĜ_ D!Ďf#&va d:o?%Bt+,b ~/ 3[@.<{C*cDǝ_,ƛBM~T!D0?T|bJ&Kte$rRX|匪2A>.%eo=<5}eOiï{:gfkN"J +lF/joї%NA$?d3NwIBL/ЃXhFZafx%Kˎ80s_IU:uɱKN(ttr Ȝ$MfǏ 5IYmIOEHvK4Mqu/D1ab_560E&Dnh?GkJ\fDT $;4K$QQG쎵ce>ء*tZPmX)w9A[(ԱB/P(C ++GIN/T^f.V͖wfW `1B^RQ8܎`C!"lPM9O +Q#vĎ*td +KD_c%ޞ QȽ_ +k$0ę[+S-tr~ɝ@AhNw x?O_!x{݈ 6_[J98lHq͂_ڤ~&x0Ҡ i~1kR:ץه7òsui.@ 8zHu8C{wEF 7O0ȭgÕb DR{h*mt{Z'7u!ۃwTm5=ԑUcM:nc-qc 4;ucJ#a#Yrc.b`N5;6?P_IPy.) U7 aej*n"*U.a yOT)P,VjCeRKS2.2PZ +|Z@K 6G j aK4ҨMZ\dCu=3 (3Qh.*PkD +X>d`)+!b՘pi*8uE-ߵN#i1(8IKHN, 3`9RL]KK(wJhbT>50Z}[lTZnñ>Fn̢ZOcvkM@p }Q .3%y6c‘$D#̯M<}d[ꃖ9jYdQ/];D0c؆#iYQGlh*^3@39 _{Bnv4;7Rq=^߮CAX":6!jH%eH%MHU:d!UMHMYHMiRSچԔԔ EH %qy}%q +wn]7b3ajHf)}I~1r-SRѩ.҂)S#rKH%?nȰJC(a+[ӷcA,ZG9>*,%q!&,* gW>-gkf#3ze5 4bt (㍵CkM\}65;a$H-tp6"P$"litH:XHpx"N}@"JYm/opoϱ)&i_|׹'C(AHaҚPJ#FfT[ڎ(*T#s +Uޑ*.[p$@ݴHxc=mZ3tstve; G$Cag33P ?P5CVpw(Ph0 ,6?:2D"b} ?.P#むЃ5pTqy#Y[C +"=X+\c!Ӳ1uKxKx'Kx'KxKx/]sscZBPٝwm%Cҟ#m?+q)c![=Y26Ã0*kꢊ&(JKx&(B:+DhH{|FBǫ i'[a%:P`%ݹJ%e[ +'}J +4g z^X#K(V6VAR`5!Ѫ̹ +Qi>ôh0?~c +QD|Xt`FC:1Г}M3GmsQmİ[-Atb)q~?.L5Hjc 3|%{scŮ=#1b,c4+|ƣr9S>-~*粹<}\zp)PCc5mhugujƛa5ֺv{mlvEɎwNgNveT) LćN-ŋ%IaaEʲ^@ҳoI C+e->;7=~0!RNOհL:2/xtW.\8َu:Ed<L'd#yA˗i|ІA͇Cmnc3T۷1iCe71!̨/i.p&kČTrS|fsv 2EjݯU)㪍 nt6Vqʈ@ƨl28"[|k]yc=8q孬+Ӹ0 5!}j,%fեG+~֕uoJ֛9-N}'  E+E=^ s oʅ[Y;(f-| +K o=l?\Ó:@q08'Tku@OBe' ++" )lAZ.ZȰEhMnz}S1{P۲,=Rߎ9 +;S:{: I6?uB8 |>;P_0sbsZw\U /Wo.N8R__8U1YN8SN>d:kz"/HщaSBJca7 &H1~6!CUbC(~AP?{8gusl!=Bb*-Fjg@oqWN_j>=ǨI+'KqV"DF/cݽ=N$M|p2s1:{A`7?{zm }{cz{8E"nl _4!"m?oOZV%nx6(vU®t2úb!8B{dB]i'mbv|1$6;^"rn?|^mx&(P8byCx=1ya%޵Y&e# bsʏŃ]:v_Me_W@9oz{пR!-c K}E-{oaOR~OR(,G^ou1Oc)QUXKmR`KU΅Ev_p"_4I[ojscvD}߫jTpS`ǁ>ݲf +n;k;wXkv˼C%E×mC1^4Mb4oKqKto-EZj7-XVvfμ]زn"лHC*qi_7deC[]/i*Hmg7٨:܆c}EcҰKke {Zmd/*bX2rV1Z^#rym[K64?!Z\*S;-C9뢅=p*1<-H\]!4+⃣(>0j_fŚRO[{ JzQo0V)鷕7+)=4<4Yj!:|eAa^:LZe&wQl[[Мk,PAA0^L] Xb CcxM*=DzNWטݿU{'Ee"x'HIs=Y?S +Y*WnDxa*5=f7p:Q5s/Ɖk9nߨki1AEQ\v'vTi0͙SBv&lCvb?nmzyylfL1[D]A]wzn8sr ݝ<' 7vOm"Zqoy!Ru{J +endstream +endobj +241 0 obj +<< +/Filter /FlateDecode +/Length 7682 +>> +stream +x][o,9n~_Qn$0X! dA Hg 9v5(^D^1Xo?_B^ ZqP/_-%fOf0ҷ/+‹X_t__e/ QMiyTcMV]Rš#EhĔWHJ)S4JF7}71hIi)\*JHFX k1FK,oJ2Zm^!An%ݥZ=|`#]0p.rh%[-RKش'bPg֜JIza 5䊛"K꤂fT'=5BJ6rFX8Xu= @0*ek*Dk)(TLij7LqZz-{-T`n$ZBC7hbM,NL`-vCv"AZ朑Ɯ18w]u2iϹsͮCmojBxu䭯+e }]iO3J{u|]"<%,ehOGii'Ӧ}OL/R=e^wcSLO6:cX>,1%,>HV6R˜ễS+\b+,neW&H>0j͞] Ɩc˚'?WZ\1¾R!*AWZJ% +*4aW*]Bү1C/o #VmR5) b%bjJU3]nF_6+7IXφd|mHĆU(a/M)^b̀N&#%ؖR&3bfx=RM1cyľɜvanKyobD;Mg+c=vLԺcbdg+I7m)eB=3-fC &J s[ʘanmg4D_;&0uD{fbdJhσfe+RSRgU5:"'u?4^| tXWqy~גJ +LPy)G% Id(J(5QFtJ+b$2KאdVlmIX7T[\ Kc,yٷЊ!>qZrʾkXI].}ݨS~o(3( ƴZ$.0BYkc3Io.I{LOldͳ35<0;#{ AZf3'hNOqq&h}}G.Ma %%^~#DOqy5Ú3@^gZl3n!7!bfT|\y +?U 9+yr}9ۡSHPX~X(]iSXI.85E#L7V&pw^X,B?KoLAJjr!şOfw,?wLSq1u 4qDS?\ C7 +G++ERHw-M^nnU?snھ& +_=\~xYHhRA RnB۾ +ߩ9&Hhj6%Nkʰ^8Zw/nEOësY8SUg{$%KƮ")LyZ   %3a j$٨0i-2ҨRL5J]֐Q3-Q+(FCY߮+L70,Ե{{DRMȵV#J0!MB:XEP6jщEh%0'>H):(IuEGŕdV+G6!n.C>beoq +BZPLA +H\hB6uyqS+I>$ +Ƿ3^̨Yk芳liCZ?e9s:qy쳰\N|Q<w_n 8rW!gez(s/'>1_dqzdnu$>)\V`ؗ'[ c!L~L +c%+&s,ư{*,XԳ}V's?JSlɸꮖS*T'S=OqLc|*P3o3S'¹df4W8yb)[᳑G3N*',nb=V8p: œؓncvG}ǐOn mZ1]НY7Cy;Xˎ rLJȞxjn|x[z?n@95BWܷIh<+BL+\_%$tfҽiQY>ZxV95\oP43Py rVRU~f' KOh +9 UPF)DiO\LJ1m]|k_cѶ9[%U1Ⱦ7%V`G5{ 4 y)hk?!&KTÞ +z9z+zk=v==K{Js)n{]1G7pORy,8B9HB>juI +M7O.#ˤGPܓ+~Ѝx-n sSj5&B}}(@ EVt^!ҧ14|9_VA#XFY^,CSg+|J UP_|\ +5_E"Nԁ +5-0M 6"SAQ H0G:Fl*c\44!hlĎ]F8k6bENREpdt6eӦnٱ'4zD;. Up#ɚ&17ꈎM7J{)Y^)/Ykٺk58o[Pz 블B|]o*5 wvMd4!7'״cD5;,YRh7ec/m67vXlƺg7Х.F^SOlWp/N9V@u;D]$׳89MJ\mғᴅUYE4 2Ob?-k +r/YDj'Q[>HٌrNGN[VJHJ%HpԞώ=}3$B*3ib' > *)SNOyiK0ExtKP Pz|R)3y)g'e$Z^5h5[>, +ep2} x-TTwSO9+.ikI@SCN̓g P0mzHo:D>OvDx!mCeIFSrxpRbxO[89j[z<T|ȥ9z+Mq]Em,]]x ^J $YM˖=#{X,^}!ͫsA+ǓoSӌD=!; Tpz H{5~LhcWc^Fx=/Y7lk1*ԳNS)7_+ޫ|HcSTG,cpHv>ϸéSF\_?Ix(UM=֘]OΊxUi9}Eǿ=O.=E 5~)``XVJ6 @@rﲐ?hitymPę x<%Өص *);fwC%G cIv߀4eZR@iZ-/B l7NIrThz FvwB2Z:Khwl!*MEvM5aQ9z`A,ʎ9!jF]/$̛ Y򴁜l (DFBd )F: QMoMь-m+oö7hnh;7?7{@o0 烽r]ZԬ]\LY-H+̨m6--w.;]Ǧн7vxU瓃 hZU\tkW e(fjwa@I̺Cz{#}3]hSL+pvly,qbE\S[#>[} qb7qp=*ΓyN M'@]3gKXT}Jm^ M-qT R.Ɋpyi ӄS:µ/n)ڎWM|Tƶx=IdLsHP5AJPIh:HrkHM:e}.Lm3+PiBݍF`, T!<͑Qo$y|~Rlo&m.q!צ\`'DA3qqqV,vՔ +)Di$ƍܣP˦' )m<࿩[MWPǝ={rM.c;^Cx4=miZqQp0.wܲo}"A83nM{Ha N`jp&4C@O *9H5HK&7n.ܝ#b9 pnhpC2p4D4]0l;nuC#\}d+Y1 EɛR8)zQj4oM]42 vL{-s<}xèo%Gp/9{bWc)]7^Yͨok`芳liCV x2*=vv9EF| g?Ǻ$ cYRJSdD\he)gϧ_<[u-t%d,SDj+K#/O?z +ڊTw6 k)b-li%0`*ϭu{륅`_!}+g=_ƕ?JEX\Zw-WVCV6/zɫ r)f [-X`GkkbwTXW%9n [\q9Sf\۲}F2סGyS [dGƽ%p/ۯz7:t7?PC)Z +endstream +endobj +242 0 obj +<< +/Filter /FlateDecode +/Length 8346 +>> +stream +x][%m~?XvsA oP%gؙ֑(^>TP ,j5ǟn9Vi}pb)~ ?_~ &O_HL{]Kt~˞_n:,w_~|w}~x``d-03SL 30s02f&׌H}hGT?GhZ+.?o|l>ři]--Ak0ϊ1܅)'DmP4 e&f&ap㋩hӂFc~4GT+or LJ{Ѿ9w7 kjCWamppGbs418 ܉c6ma"M6DRܓNS+r&g)Odn<5-w$ڱ<X5X6=,ϭ_X 熳N,֖e&l ]ЊʒNn](hcxp\[s3|Z'se kS-~/}LK_?e5îJIb߂YB[T`5tklR eax;lT#4}x37.6%V&s+[me2ksѰi_;NV q2k$8`X%⎓p­vL'|eYعpR,vn8){0lu-o9[UNj-'s;896LbVI<ع]$XѰ[/3-?[65$8BFɉ|kg[~Zk9+Ͳ8gS"Z'7reK$D.]Y| 54oD_uҼ'5&Z$:ZH~'դY&SYL-IcG|V5r{|}9盓Bx/?ݾy!{_"HkN>ן@?,_qu<˗?.8Bz\ϐ2 //_nkIXwu-Q?JFZ~T+kg&pseyC"њ2bۥB5SF*L5[]*%mk\+1 {.߼_+u ~~ER]a5^>c\)0mtiu1CthRd´qu"<U#'{ȋq/49"yVlo7%_ Ѹ6y1 (T"vB1Bi ~(Vk(7S*9#e%~!LC2,wLd3hf\>=&WpF4Lp ["ۦJܪй(Li*.N_.?`$.I88M +SJmh'*X5ڑvg-nlLSy1>m}B%d}GEilH*jR`1SX$\=>B:2*f1ch.:A{IyЇqLd<{U۳X">`|ڣ%MfH>ɪgGL&G`Jcf9=^5".h; ::]CQe XSήNvV VN&e߁2eIcI3AIe1f!|:@9v|47htѨOѱ*d ҚMњܚcn5r3w]Lu8[J۵~Y`Ny^#,=@026 +44[s $˹cf}tmgr\56ir\#N!9J90T㜠2Yg*PM,hX/8K5ܒB;%WSi{\al)dj?-"Lc jH7+JlaHe38)'m˞&3\̦f&4)dO]Mk?͙ u*4Ơ0il.{?,ۮ:2|e,7ëo`t|ŭzs $K玛F~>_ah9nq 4jM Hu!T+HXl%iɳfa1il>`„*346hpillR4vVx PAcK7~4ʟGt5-2mJχ\ʘc#Mmi{e6ҬˊUiGS;ph˥B+!+I'+dV; +yF EAEA1f;c\c\kʡV1g*)*ERCT1GUݛ? @;e%Lsg9Www8|4g.5 O4ֻb( +AnQ!$o] ? 3'ٛJ2Υ/QzbN.CmG}.g(s=?ios1-?b+c%0-.ʴrH[},+E)3W^%B^z.gVZ~{D,BQ,+8i4-1B1ձ<Ш%Rw*o RiTmf̓ZrAp-G +Mrr2HV$H쓐qUG:P|o؟F>`.ꃏ2,%T PikgJXCp/>Y\]uQ4ݼLJ MA?T]5?Akf b-qc Q&ggm[`}@eeUVo;Z˲ԞvKvht.v<X]BMu,HY=A!f/P o 6RemGzF'۲ÙQrF* y5*y|u}[ ɺuѹcnri8O}C̘ɺ܅DBdb5IL=Jl%KYv1Ӣu4@Qs3&.TmV$7~F\ˤ..`SF ٺcWXrFJM2kϦf vY#[T& lPYQYZ?b-U"fl .F$q1rM^}EÏcj$޶ 6tRfáYp% d,EQ0FƘ>>cK3jia'Ģ%83$S[ٹcZKI,$fLmin Z:܅ȴ8i3]1&\`HN1=ֺml{xR}F{‹,6 +Nn5(ZkMƎl;[7u ku0NMΨk䶺f/ryv/q=s{2)aJ[|r{j)+-՟ =g^Ѧw\B#@|Gf6L&gSXm +~¢?Ja1SX Q +MaÚ#nSX k}y bܤÑ3.Lre3YXgdk}֙$]t&4B6gWG:P|ؤ),Gd4[=SXq0^9(mrVhNa9NKbCm sX351eǚm.*0/CֳT e,oObI,&)oD$6>v؆KbS]$6$6}>MGj'm$MuMF)oý#ILVch4p!)3=F:L6r.o&yQ^TShR{lzx;$R wHmNEvʘ{4bŃm6A4smBC[2i" +Ƣ)+MʊsXCZ+T4]PX?Q!Zⶾ>*T_+tUM&–ZdxYmJeR٧5Or9]Ͱa)] e7gm[9]st5>]06pG GL2Ygߤpf&"1IaIMՑ&6*eRާU}Jq%:HW*>]%:HW*h s5c1&16F;g xA|v%??!]-6]AUJtRڤ&]הvj4rMiNW6]pNW9]{JtU)*߹NzG٪ő\pcj=k8cZekfH.WiL0 ]FvL1NRfj.>"]oEo72rsq4vhS1c\rlu@ \'s4r,LJj2G,Vy9FjMY{eq *Vu&֪ǜp? i[SXU'RpfkKRH^>L&G"h y"KGK%zڜ6?Y':b +n"ڴ] +7 + +moo:((?g +E^Wyc] fΖ 2:&15qKoL$dlbt6JG^%#"WȫăȫYwgJ<J^%6mMU`!/3;֙&.qwZJKU)4_\J$ "z ixuM5|hHA +Qq˸5*j6jgWCK Nnjfuc@xWuc<)x^I/'HnFHDr)Er)[wL+RQȬ2#9ŞnK#2u LkS0dnLn163Q1s45}u>>Ξ:85ngd`}B!&-CTlJas(r!빣&2 hv ٍmn2[>fw ,\vWѲ{+V^\EZ\VˬZq@_V}J_O@T=v9|8zܺz|87% +@aLLk-rhԡR +4*S@6\\jf̀P+G8^_e0d%v}?%l~&*Dʯ2cr ɉ4,:(gzƮ 8YۊLn0n[ -^i^`E +{֬AVݯ? *b@ I緅=,6/۫a{eUYrwwަ_ 7Cn_Mwt%o @m\2.Wi#hA"Be"|tAhwI;p\s=ڄΗIH}Tzェ]|܁p\Uλ& 9Ã_u-PWUf +Gxm&ハЯϾ{=7 aw,z1)j9!(H+`oL"G] +i8/`Ȃ~8~RgN/'U%*P]s5:/N9vU^ +A\}|qqMx ]{Vp_3$l +62堁e +/r@~M^tαjxt[5ófs\[_@S>nsJyh7aҨLTΑѪ| AzU;5EW򂜸V֏b o`{Yǂ>WBN ‡'Sρ:Lk  A佾^:t</飡s<5^?J:wX`ζ O{5PrȦKq0f{Mi>mXC{+>"_:U3(v^ ?Ν#|lbXis(9/;$+kO^RpU;ٲBq3LԶ?Wy1@ǶF["s[39~tr0rKr " [ +_c #G8>nJҒQF>.s :&_%vA~D0Gk<`9=,'0r)g9/g94(%^]goo)`{5LQg.e@d{ +7 y+&ⅡOf!@Hgp\2|*V֝caS].-P#4^s9l8P(|EfH )RV_`qg>H|[:բ +endstream +endobj +243 0 obj +<< +/Filter /FlateDecode +/Length 3442 +>> +stream +x[]+}ׯBW"`PkFI@ ynE0voůfwku`l_K*qnR|M0+7|ߟvB N(L/y')AՏ:}C +\V^O.14^w~էL_.}`r"$0 >ŪMLU9Dhx߳[U?t\28h6hX5 ʀ-,`Sæt 6~m\;a۟ c4DvժV eCى;ʶWH{--VѪ[p{=Nfu7؊`gJܰdR nXr"Y*DaJZ%7݊tgJްdCoX6msD3w$c(S RYILG,@=@?Fz27lx"{1tg-Z)vuFFXECӪ6WJw`[6ZŌn6XwJ7:^DVZn% T$NeN2?U8d")T7vݰ~C @"@R4@;&=0}_.tz;aryYDes*ˊO.@dY\L7&ԄCFD!"\b⬛b"* `XB \ +ɷ yS EhyQ.>"j~ks!] + h( +A3p$&kjj5 @^H_A#"pģp8xD¢`޶E!k`AKts(5"z-0.^o֟8I $z0^. l.ۂ +!ld.t~X)pbUf=$6_{2?? +< I+3(5E'_x 0?O)p4${l,E>}=Ww֞\+ Ģ%f6ShyxWT-}X{Cg$'iD(+ VC O3}ݘ.$IeYDώKݵF!b5RL )φ~^YQ^:` fG|LbL:B:GH{BE@N-ƈyJbAa'2RMH1!_Gڡd{Yb^2fbШCqqX^*عմG Bod__r-Q LA0zb\Πue~w<'kȌ-Gg$l73ql& ^!^ ۅ+A^Dgr6; + ?q`Q?IYmUm(wL<<8J*t٫/hN.yBcb.'d*g|H&{}!dwMH^e遼#kGp8; q_E<6"9n8` q.JkJy0u|$ M|$ošM}_B4Ds1x 2m3o9JriE=J^V1qKr>7Op^5$@@_Lty}}om +җ϶d\q>Hsצד!Kq; ;oqByvɐ3Ȑ.9%>t\$R4VD_#>trtGE_LƏ ]q$+>rVd;왅KpGΐ/rˡl l1"s/(s.:EH[ra9z$Δ#n8 ?t6 fѕzuQ&\uWd)ac$DqcΞW^dg"s]|̲Etј%Kԗ߶o~o4tjO/V[[8^_]ˈR>{ +p`k'G3Sl=vOXg`uINݗ $#B4 0GZs;V +z<86.s3z@eѝ:1C{fۗŬ NkR]qԥ'6E2<>8 +endstream +endobj +244 0 obj +<< +/Filter /FlateDecode +/Length 3635 +>> +stream +x\[ ~_1"# i M8Ehf=A w!)#EQK7wN"41r4venrwW#T=w?N~czݏ?_'|&D8}/#rB1Y)`q"0h1e!!NOA>dr4K ,DgL@$1@v&d!ljX/8$d /#O3q)`,/8ˀbU":@`K-a"Znj.)ZnWrQ"Z^\!O(j-G3N7Q/"<\E='R"+Y֢U&ZT[ #,&,"t_mk&Z CW&G n4Ӓ!'JŖ˗S5I֟Tn(,-3wtޔ~mM6cUU}|yHxfiڟA]]韧_N/+ -P +"@AX9㬕Z= +gME&4*Pd=P$DE|]E&4oaLT{E(6]7n\jQ|5+G-_:Ho!w< Hy\z,HeҢ {HD$bxh!(],;HPQ|AZY"]Pe iZOUzWe5VRYkuj^vu, 2TR +X98{ΉDN$"O:7hM0}MD4L<9-]sfrpӁ n!-DsO+ % VRR<*a8ѬOE4!Fi >0ZCNF) c0ԉ& fAOn %\O& ;IŘGCȭwU41E4ko)u^jR + `B`J .ɿ[ ^Af3)Xh6#n7n K-6@oϏK?I$8&88g3@d 4}ZcM +VEwQ.hBt +Se*Pҳ4 q1+cŚ#Mܼqw* 5b_iVy}}q})r+/}51+frUch AL}Q8-ŽX#wl | J<" LJa‘;*="u;;0ސũSG.|8_ +OjnG}#/:I| s +l n2f(j䵉g%-vZ'5k-Y^H̲<9^x$^R?рIJ-Qc(1Cf +?{cqe}h%/@^K:pū pZ4!ģh~F̾s9ÍJO`i-<`#%xbt9{/|+GV' NkO_"Uf*$Y0=Q umM²12VIcc<`#6 +Oڢ*lQU[kAy}eե~ʾA*[ˁE2Xcw}ǵˆJwH++FJCRA̜!煺ƺs#_p]r`᲏RcP姖Q+ T~Vv#?wMVw`-H&kJm[\J +@)DjD9Z~<+%e9YŔ'g=G0_xPXe[>݀I%>jՀ}A bJrP@%O${r_r*/rDn%W1d姯&%xX~TH^2i#-,կL)(#aUwG(qt:kzh}_\: gsTx)o]cl ڃoej̕DucKT?0PJ<[Q-4lX%3RJ/mA=OeU\X K>ꉒ*pبJ(LҠDCJ<,B )Kp@,R% H/t!brM=!hFTEx}h^+X#m4 }dg=$yO*"wԼHLEZ*$ƹ6 ;r݌>^ Y8Si%zt|$"S ԭUQF(a0VG Ù+lRVdmiߣ;ҼZ 沫dP v6lFE o  Uf"= Ueɴ֓S{#FSjZ^ Ug=$p`wҚkdzDdF;Pi6'b>bf8%ԦK[gvQke|,@sQPϣVIX9%PSiȜ5#2j!n/s +j4Rbak*t^ȫe^^/QivA돊miZ*-?gz?_HPkqТ2Te:M~|S/OF記ZF.oI1L5fuZ=Vۻ-jl-]Wt9vrFGyx l2yxrm> r{ +ϟS29;1gx~&1-CRNէGcS❱RzL<`ܜI>_rm9|.BNխwAM<ߦF*AB/ )$m\ɂȸ=5g17X"9ovpէJ}szmyd~Ҫ[jNuo<S lۓ0Gg-F򴍔7Bu1c*mUtS__s"T|O׬o{ӗ*(s*+e}]k\v57ڼx%s0r?z ^KeRRưU} :[kkNk'CX$&XsD7e`ͫ:=x *9RMf^[Z,R~uVtQkdRƑ ()y˪0MZQ: + ެOdo.o?xo7Jkb7NooxSiM:hlzJﻍk]V{ccG`#lIy >^JM%a/:s!9r&j#r&z\HlnJWu|{lR2l:Қ`B6/EϕOarODI@6/lIil8APϗ%t$is$~|I41nN^IDGI;`|)ۆ[ 1$ZPkL<S<L}[o ) +endstream +endobj +245 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00001886) +/K [867 0 R 6] +/P 343 0 R +/Pg 11 0 R +/S /TH +/Type /StructElem +>> +endobj +246 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00001887) +/K [868 0 R 7] +/P 343 0 R +/Pg 11 0 R +/S /TH +/Type /StructElem +>> +endobj +247 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00001888) +/K [869 0 R 8] +/P 343 0 R +/Pg 11 0 R +/S /TH +/Type /StructElem +>> +endobj +248 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00001889) +/K [870 0 R 9] +/P 343 0 R +/Pg 11 0 R +/S /TH +/Type /StructElem +>> +endobj +249 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00001890) +/K [871 0 R 10] +/P 343 0 R +/Pg 11 0 R +/S /TH +/Type /StructElem +>> +endobj +250 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00001944) +/K [908 0 R 15 << +/MCID 0 +/Pg 12 0 R +/Type /MCR +>>] +/P 351 0 R +/Pg 11 0 R +/S /TH +/Type /StructElem +>> +endobj +251 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00001945) +/K [909 0 R 16 << +/MCID 1 +/Pg 12 0 R +/Type /MCR +>>] +/P 351 0 R +/Pg 11 0 R +/S /TH +/Type /StructElem +>> +endobj +252 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00001946) +/K [910 0 R 17 << +/MCID 2 +/Pg 12 0 R +/Type /MCR +>>] +/P 351 0 R +/Pg 11 0 R +/S /TH +/Type /StructElem +>> +endobj +253 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00001947) +/K [911 0 R 18 << +/MCID 3 +/Pg 12 0 R +/Type /MCR +>>] +/P 351 0 R +/Pg 11 0 R +/S /TH +/Type /StructElem +>> +endobj +254 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002266) +/K [1199 0 R 13 << +/MCID 0 +/Pg 13 0 R +/Type /MCR +>>] +/P 382 0 R +/Pg 12 0 R +/S /TH +/Type /StructElem +>> +endobj +255 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002267) +/K [1200 0 R 14 << +/MCID 1 +/Pg 13 0 R +/Type /MCR +>>] +/P 382 0 R +/Pg 12 0 R +/S /TH +/Type /StructElem +>> +endobj +256 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002268) +/K [1201 0 R 15 << +/MCID 2 +/Pg 13 0 R +/Type /MCR +>>] +/P 382 0 R +/Pg 12 0 R +/S /TH +/Type /StructElem +>> +endobj +257 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002269) +/K [1202 0 R 16 << +/MCID 3 +/Pg 13 0 R +/Type /MCR +>>] +/P 382 0 R +/Pg 12 0 R +/S /TH +/Type /StructElem +>> +endobj +258 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002359) +/K [1298 0 R 8] +/P 400 0 R +/Pg 13 0 R +/S /TH +/Type /StructElem +>> +endobj +259 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002360) +/K [1299 0 R 9] +/P 400 0 R +/Pg 13 0 R +/S /TH +/Type /StructElem +>> +endobj +260 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002361) +/K [1300 0 R 10] +/P 400 0 R +/Pg 13 0 R +/S /TH +/Type /StructElem +>> +endobj +261 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002435) +/K [1363 0 R 18 << +/MCID 0 +/Pg 14 0 R +/Type /MCR +>>] +/P 414 0 R +/Pg 13 0 R +/S /TH +/Type /StructElem +>> +endobj +262 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002436) +/K [1364 0 R 19 << +/MCID 1 +/Pg 14 0 R +/Type /MCR +>>] +/P 414 0 R +/Pg 13 0 R +/S /TH +/Type /StructElem +>> +endobj +263 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002437) +/K [1365 0 R 20 << +/MCID 2 +/Pg 14 0 R +/Type /MCR +>>] +/P 414 0 R +/Pg 13 0 R +/S /TH +/Type /StructElem +>> +endobj +264 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002458) +/K [1375 0 R 7] +/P 421 0 R +/Pg 14 0 R +/S /TH +/Type /StructElem +>> +endobj +265 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002459) +/K [1376 0 R 8] +/P 421 0 R +/Pg 14 0 R +/S /TH +/Type /StructElem +>> +endobj +266 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002460) +/K [1377 0 R 9] +/P 421 0 R +/Pg 14 0 R +/S /TH +/Type /StructElem +>> +endobj +267 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002504) +/K [1405 0 R 14] +/P 432 0 R +/Pg 14 0 R +/S /TH +/Type /StructElem +>> +endobj +268 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002505) +/K [1406 0 R 15] +/P 432 0 R +/Pg 14 0 R +/S /TH +/Type /StructElem +>> +endobj +269 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002506) +/K [1407 0 R 16] +/P 432 0 R +/Pg 14 0 R +/S /TH +/Type /StructElem +>> +endobj +270 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002507) +/K [1408 0 R 17] +/P 432 0 R +/Pg 14 0 R +/S /TH +/Type /StructElem +>> +endobj +271 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002548) +/K [1442 0 R 20 << +/MCID 0 +/Pg 15 0 R +/Type /MCR +>>] +/P 461 0 R +/Pg 14 0 R +/S /TH +/Type /StructElem +>> +endobj +272 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002549) +/K [1443 0 R 21 << +/MCID 1 +/Pg 15 0 R +/Type /MCR +>>] +/P 461 0 R +/Pg 14 0 R +/S /TH +/Type /StructElem +>> +endobj +273 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002550) +/K [1444 0 R 22 << +/MCID 2 +/Pg 15 0 R +/Type /MCR +>>] +/P 461 0 R +/Pg 14 0 R +/S /TH +/Type /StructElem +>> +endobj +274 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002551) +/K [1445 0 R 23 << +/MCID 3 +/Pg 15 0 R +/Type /MCR +>>] +/P 461 0 R +/Pg 14 0 R +/S /TH +/Type /StructElem +>> +endobj +275 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002641) +/K [1507 0 R 7] +/P 475 0 R +/Pg 15 0 R +/S /TH +/Type /StructElem +>> +endobj +276 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002642) +/K [1508 0 R 8] +/P 475 0 R +/Pg 15 0 R +/S /TH +/Type /StructElem +>> +endobj +277 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002643) +/K [1509 0 R 9] +/P 475 0 R +/Pg 15 0 R +/S /TH +/Type /StructElem +>> +endobj +278 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002673) +/K [1523 0 R 15] +/P 485 0 R +/Pg 15 0 R +/S /TH +/Type /StructElem +>> +endobj +279 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002674) +/K [1524 0 R 16] +/P 485 0 R +/Pg 15 0 R +/S /TH +/Type /StructElem +>> +endobj +280 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00002675) +/K [1525 0 R 17] +/P 485 0 R +/Pg 15 0 R +/S /TH +/Type /StructElem +>> +endobj +281 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003027) +/K [1808 0 R 1] +/P 636 0 R +/Pg 18 0 R +/S /TH +/Type /StructElem +>> +endobj +282 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003028) +/K [1809 0 R 2] +/P 636 0 R +/Pg 18 0 R +/S /TH +/Type /StructElem +>> +endobj +283 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003029) +/K [1810 0 R 3] +/P 636 0 R +/Pg 18 0 R +/S /TH +/Type /StructElem +>> +endobj +284 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003171) +/K [1910 0 R 1] +/P 699 0 R +/Pg 19 0 R +/S /TH +/Type /StructElem +>> +endobj +285 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003172) +/K [1911 0 R 2] +/P 699 0 R +/Pg 19 0 R +/S /TH +/Type /StructElem +>> +endobj +286 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003173) +/K [1912 0 R 3] +/P 699 0 R +/Pg 19 0 R +/S /TH +/Type /StructElem +>> +endobj +287 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003174) +/K [1913 0 R 4] +/P 699 0 R +/Pg 19 0 R +/S /TH +/Type /StructElem +>> +endobj +288 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003385) +/K [2092 0 R 2] +/P 745 0 R +/Pg 20 0 R +/S /TH +/Type /StructElem +>> +endobj +289 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003386) +/K [2093 0 R 3] +/P 745 0 R +/Pg 20 0 R +/S /TH +/Type /StructElem +>> +endobj +290 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003387) +/K [2094 0 R 4] +/P 745 0 R +/Pg 20 0 R +/S /TH +/Type /StructElem +>> +endobj +291 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003465) +/K [2160 0 R 0] +/P 788 0 R +/Pg 21 0 R +/S /TH +/Type /StructElem +>> +endobj +292 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003466) +/K [2161 0 R 1] +/P 788 0 R +/Pg 21 0 R +/S /TH +/Type /StructElem +>> +endobj +293 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003467) +/K [2162 0 R 2] +/P 788 0 R +/Pg 21 0 R +/S /TH +/Type /StructElem +>> +endobj +294 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003491) +/K [2175 0 R 8] +/P 795 0 R +/Pg 21 0 R +/S /TH +/Type /StructElem +>> +endobj +295 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003492) +/K [2176 0 R 9] +/P 795 0 R +/Pg 21 0 R +/S /TH +/Type /StructElem +>> +endobj +296 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003493) +/K [2177 0 R 10] +/P 795 0 R +/Pg 21 0 R +/S /TH +/Type /StructElem +>> +endobj +297 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003494) +/K [2178 0 R 11] +/P 795 0 R +/Pg 21 0 R +/S /TH +/Type /StructElem +>> +endobj +298 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003521) +/K [2195 0 R 15] +/P 801 0 R +/Pg 21 0 R +/S /TH +/Type /StructElem +>> +endobj +299 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003522) +/K [2196 0 R 16] +/P 801 0 R +/Pg 21 0 R +/S /TH +/Type /StructElem +>> +endobj +300 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003523) +/K [2197 0 R 17] +/P 801 0 R +/Pg 21 0 R +/S /TH +/Type /StructElem +>> +endobj +301 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003557) +/K [2219 0 R 22 << +/MCID 0 +/Pg 22 0 R +/Type /MCR +>>] +/P 810 0 R +/Pg 21 0 R +/S /TH +/Type /StructElem +>> +endobj +302 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003558) +/K [2220 0 R 23 << +/MCID 1 +/Pg 22 0 R +/Type /MCR +>>] +/P 810 0 R +/Pg 21 0 R +/S /TH +/Type /StructElem +>> +endobj +303 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003559) +/K [2221 0 R 24 << +/MCID 2 +/Pg 22 0 R +/Type /MCR +>>] +/P 810 0 R +/Pg 21 0 R +/S /TH +/Type /StructElem +>> +endobj +304 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003589) +/K [2240 0 R 6] +/P 818 0 R +/Pg 22 0 R +/S /TH +/Type /StructElem +>> +endobj +305 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/ID (node00003590) +/K [2241 0 R 7] +/P 818 0 R +/Pg 22 0 R +/S /TH +/Type /StructElem +>> +endobj +306 0 obj +<< +/K 23 +/P 25 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +307 0 obj +<< +/K [2482 0 R 833 0 R 2483 0 R 835 0 R 2484 0 R 837 0 R 2485 0 R 839 0 R] +/P 26 0 R +/S /P +/Type /StructElem +>> +endobj +308 0 obj +<< +/K 32 +/P 28 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +309 0 obj +<< +/K [840 0 R 2486 0 R] +/P 29 0 R +/S /LI +/Type /StructElem +>> +endobj +310 0 obj +<< +/K [842 0 R 2487 0 R] +/P 29 0 R +/S /LI +/Type /StructElem +>> +endobj +311 0 obj +<< +/K [844 0 R 2488 0 R] +/P 29 0 R +/S /LI +/Type /StructElem +>> +endobj +312 0 obj +<< +/K [846 0 R 2489 0 R] +/P 29 0 R +/S /LI +/Type /StructElem +>> +endobj +313 0 obj +<< +/K [848 0 R 2490 0 R] +/P 29 0 R +/S /LI +/Type /StructElem +>> +endobj +314 0 obj +<< +/K [850 0 R 2491 0 R] +/P 29 0 R +/S /LI +/Type /StructElem +>> +endobj +315 0 obj +<< +/K [852 0 R 2492 0 R] +/P 29 0 R +/S /LI +/Type /StructElem +>> +endobj +316 0 obj +<< +/K [854 0 R 2493 0 R] +/P 29 0 R +/S /LI +/Type /StructElem +>> +endobj +317 0 obj +<< +/K 49 +/P 31 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +318 0 obj +<< +/K 50 +/P 32 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +319 0 obj +<< +/K 51 +/P 33 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +320 0 obj +<< +/K 856 0 R +/P 33 0 R +/S /Strong +/Type /StructElem +>> +endobj +321 0 obj +<< +/K 53 +/P 33 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +322 0 obj +<< +/K 857 0 R +/P 33 0 R +/S /Strong +/Type /StructElem +>> +endobj +323 0 obj +<< +/K 55 +/P 33 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +324 0 obj +<< +/K 858 0 R +/P 33 0 R +/S /Strong +/Type /StructElem +>> +endobj +325 0 obj +<< +/K 57 +/P 33 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +326 0 obj +<< +/K 859 0 R +/P 33 0 R +/S /Strong +/Type /StructElem +>> +endobj +327 0 obj +<< +/K 59 +/P 33 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +328 0 obj +<< +/K 860 0 R +/P 33 0 R +/S /Strong +/Type /StructElem +>> +endobj +329 0 obj +<< +/K 61 +/P 33 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +330 0 obj +<< +/K 861 0 R +/P 33 0 R +/S /Strong +/Type /StructElem +>> +endobj +331 0 obj +<< +/K 63 +/P 33 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +332 0 obj +<< +/K 862 0 R +/P 33 0 R +/S /Strong +/Type /StructElem +>> +endobj +333 0 obj +<< +/K 65 +/P 33 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +334 0 obj +<< +/K 863 0 R +/P 33 0 R +/S /Strong +/Type /StructElem +>> +endobj +335 0 obj +<< +/K 67 +/P 33 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +336 0 obj +<< +/K 864 0 R +/P 33 0 R +/S /Strong +/Type /StructElem +>> +endobj +337 0 obj +<< +/K 69 +/P 33 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +338 0 obj +<< +/K 865 0 R +/P 33 0 R +/S /Strong +/Type /StructElem +>> +endobj +339 0 obj +<< +/K 71 +/P 33 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +340 0 obj +<< +/K 866 0 R +/P 33 0 R +/S /Strong +/Type /StructElem +>> +endobj +341 0 obj +<< +/K 73 +/P 33 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +342 0 obj +<< +/K 74 +/P 34 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +343 0 obj +<< +/K [245 0 R 246 0 R 247 0 R 248 0 R 249 0 R] +/P 35 0 R +/S /TR +/Type /StructElem +>> +endobj +344 0 obj +<< +/K [2494 0 R 2495 0 R 2496 0 R 2497 0 R 2498 0 R] +/P 35 0 R +/S /TR +/Type /StructElem +>> +endobj +345 0 obj +<< +/K [2499 0 R 2500 0 R 2501 0 R 2502 0 R 2503 0 R 11] +/P 35 0 R +/Pg 11 0 R +/S /TR +/Type /StructElem +>> +endobj +346 0 obj +<< +/K [2504 0 R 2505 0 R 2506 0 R 2507 0 R 2508 0 R] +/P 35 0 R +/S /TR +/Type /StructElem +>> +endobj +347 0 obj +<< +/K [2509 0 R 2510 0 R 2511 0 R 2512 0 R 2513 0 R 12] +/P 35 0 R +/Pg 11 0 R +/S /TR +/Type /StructElem +>> +endobj +348 0 obj +<< +/K [2514 0 R 2515 0 R 2516 0 R 2517 0 R 2518 0 R] +/P 35 0 R +/S /TR +/Type /StructElem +>> +endobj +349 0 obj +<< +/K [2519 0 R 2520 0 R 2521 0 R 2522 0 R 2523 0 R 13] +/P 35 0 R +/Pg 11 0 R +/S /TR +/Type /StructElem +>> +endobj +350 0 obj +<< +/K 116 +/P 36 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +351 0 obj +<< +/K [250 0 R 251 0 R 252 0 R 253 0 R] +/P 37 0 R +/S /TR +/Type /StructElem +>> +endobj +352 0 obj +<< +/K [2524 0 R 2525 0 R 2526 0 R 2527 0 R] +/P 37 0 R +/S /TR +/Type /StructElem +>> +endobj +353 0 obj +<< +/K [2528 0 R 2529 0 R 2530 0 R 2531 0 R 19] +/P 37 0 R +/Pg 11 0 R +/S /TR +/Type /StructElem +>> +endobj +354 0 obj +<< +/K [2532 0 R 2533 0 R 2534 0 R 2535 0 R] +/P 37 0 R +/S /TR +/Type /StructElem +>> +endobj +355 0 obj +<< +/K [2536 0 R 2537 0 R 2538 0 R 2539 0 R 20] +/P 37 0 R +/Pg 11 0 R +/S /TR +/Type /StructElem +>> +endobj +356 0 obj +<< +/K [2540 0 R 2541 0 R 2542 0 R 2543 0 R] +/P 37 0 R +/S /TR +/Type /StructElem +>> +endobj +357 0 obj +<< +/K [2544 0 R 2545 0 R 2546 0 R 2547 0 R 21] +/P 37 0 R +/Pg 11 0 R +/S /TR +/Type /StructElem +>> +endobj +358 0 obj +<< +/K [2548 0 R 2549 0 R 2550 0 R 2551 0 R] +/P 37 0 R +/S /TR +/Type /StructElem +>> +endobj +359 0 obj +<< +/K [2552 0 R 2553 0 R 2554 0 R 2555 0 R 4] +/P 37 0 R +/Pg 12 0 R +/S /TR +/Type /StructElem +>> +endobj +360 0 obj +<< +/K [2556 0 R 2557 0 R 2558 0 R 2559 0 R] +/P 37 0 R +/S /TR +/Type /StructElem +>> +endobj +361 0 obj +<< +/K [2560 0 R 2561 0 R 2562 0 R 2563 0 R 5] +/P 37 0 R +/Pg 12 0 R +/S /TR +/Type /StructElem +>> +endobj +362 0 obj +<< +/K 43 +/P 38 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +363 0 obj +<< +/K [962 0 R 44] +/P 39 0 R +/Pg 12 0 R +/S /Code +/Type /StructElem +>> +endobj +364 0 obj +<< +/K 46 +/P 39 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +365 0 obj +<< +/K [963 0 R 964 0 R 965 0 R 966 0 R 967 0 R 968 0 R 969 0 R 970 0 R 971 0 R 972 0 R 973 0 R 974 0 R 975 0 R 976 0 R 977 0 R 978 0 R +979 0 R 980 0 R 981 0 R 982 0 R 983 0 R 984 0 R 985 0 R 986 0 R 987 0 R 988 0 R 989 0 R 990 0 R 991 0 R 992 0 R 993 0 R 994 0 R +995 0 R 996 0 R 997 0 R 998 0 R 999 0 R 1000 0 R 1001 0 R 1002 0 R 1003 0 R 1004 0 R 1005 0 R 1006 0 R 1007 0 R 1008 0 R 1009 0 R 1010 0 R +1011 0 R 1012 0 R 1013 0 R 1014 0 R 1015 0 R 1016 0 R 1017 0 R 1018 0 R 1019 0 R 1020 0 R 1021 0 R 1022 0 R 1023 0 R 1024 0 R 1025 0 R 1026 0 R +1027 0 R 1028 0 R 1029 0 R 1030 0 R 1031 0 R 1032 0 R 1033 0 R 1034 0 R 1035 0 R 1036 0 R 1037 0 R 1038 0 R 1039 0 R 1040 0 R 1041 0 R 1042 0 R +1043 0 R 1044 0 R 1045 0 R 1046 0 R 1047 0 R 1048 0 R 1049 0 R 1050 0 R 1051 0 R 1052 0 R 1053 0 R 1054 0 R 1055 0 R 1056 0 R 1057 0 R 1058 0 R +1059 0 R 1060 0 R 1061 0 R 1062 0 R 1063 0 R 1064 0 R 1065 0 R 1066 0 R 1067 0 R 1068 0 R 1069 0 R 1070 0 R 1071 0 R 1072 0 R 1073 0 R 1074 0 R +1075 0 R 1076 0 R 1077 0 R 1078 0 R 1079 0 R 1080 0 R 1081 0 R 1082 0 R 1083 0 R 1084 0 R 1085 0 R 1086 0 R 1087 0 R 1088 0 R 1089 0 R 1090 0 R +1091 0 R 1092 0 R] +/P 40 0 R +/S /Code +/Type /StructElem +>> +endobj +366 0 obj +<< +/K [1093 0 R 177] +/P 41 0 R +/Pg 12 0 R +/S /Code +/Type /StructElem +>> +endobj +367 0 obj +<< +/K 179 +/P 41 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +368 0 obj +<< +/K [1094 0 R 1095 0 R 1096 0 R 1097 0 R 1098 0 R 1099 0 R 1100 0 R 1101 0 R 1102 0 R 1103 0 R 1104 0 R 1105 0 R 1106 0 R 1107 0 R 1108 0 R 1109 0 R +1110 0 R 1111 0 R 1112 0 R 1113 0 R 1114 0 R 1115 0 R 1116 0 R 1117 0 R 1118 0 R 1119 0 R 1120 0 R 1121 0 R 1122 0 R 1123 0 R 1124 0 R 1125 0 R +1126 0 R 1127 0 R 1128 0 R 1129 0 R 1130 0 R 1131 0 R 1132 0 R] +/P 42 0 R +/S /Code +/Type /StructElem +>> +endobj +369 0 obj +<< +/K [1133 0 R 219] +/P 43 0 R +/Pg 12 0 R +/S /Code +/Type /StructElem +>> +endobj +370 0 obj +<< +/K 221 +/P 43 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +371 0 obj +<< +/K [1134 0 R 1135 0 R 1136 0 R 1137 0 R 1138 0 R 1139 0 R 1140 0 R 1141 0 R 1142 0 R 1143 0 R 1144 0 R 1145 0 R 1146 0 R 1147 0 R 1148 0 R 1149 0 R +1150 0 R 1151 0 R 1152 0 R 1153 0 R 1154 0 R 1155 0 R 1156 0 R 1157 0 R 1158 0 R 1159 0 R 1160 0 R 1161 0 R 1162 0 R 1163 0 R 1164 0 R 1165 0 R +1166 0 R 1167 0 R 1168 0 R 1169 0 R] +/P 44 0 R +/S /Code +/Type /StructElem +>> +endobj +372 0 obj +<< +/K [1170 0 R 258] +/P 45 0 R +/Pg 12 0 R +/S /Code +/Type /StructElem +>> +endobj +373 0 obj +<< +/K 260 +/P 45 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +374 0 obj +<< +/K [1171 0 R 1172 0 R 1173 0 R 1174 0 R 1175 0 R 1176 0 R 1177 0 R 1178 0 R 1179 0 R 1180 0 R 1181 0 R 1182 0 R 1183 0 R 1184 0 R 1185 0 R 1186 0 R +1187 0 R 1188 0 R 1189 0 R 1190 0 R 1191 0 R 1192 0 R 1193 0 R 1194 0 R 1195 0 R 1196 0 R] +/P 46 0 R +/S /Code +/Type /StructElem +>> +endobj +375 0 obj +<< +/K 287 +/P 48 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +376 0 obj +<< +/K 288 +/P 49 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +377 0 obj +<< +/K 1197 0 R +/P 49 0 R +/S /Strong +/Type /StructElem +>> +endobj +378 0 obj +<< +/K 290 +/P 50 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +379 0 obj +<< +/K 1198 0 R +/P 50 0 R +/S /Strong +/Type /StructElem +>> +endobj +380 0 obj +<< +/K 292 +/P 50 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +381 0 obj +<< +/K 293 +/P 51 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +382 0 obj +<< +/K [254 0 R 255 0 R 256 0 R 257 0 R] +/P 52 0 R +/S /TR +/Type /StructElem +>> +endobj +383 0 obj +<< +/K [2564 0 R 2565 0 R 2566 0 R 2567 0 R] +/P 52 0 R +/S /TR +/Type /StructElem +>> +endobj +384 0 obj +<< +/K [2568 0 R 2569 0 R 2570 0 R 2571 0 R 17] +/P 52 0 R +/Pg 12 0 R +/S /TR +/Type /StructElem +>> +endobj +385 0 obj +<< +/K [2572 0 R 2573 0 R 2574 0 R 2575 0 R] +/P 52 0 R +/S /TR +/Type /StructElem +>> +endobj +386 0 obj +<< +/K [2576 0 R 2577 0 R 2578 0 R 2579 0 R 4] +/P 52 0 R +/Pg 13 0 R +/S /TR +/Type /StructElem +>> +endobj +387 0 obj +<< +/K [2580 0 R 2581 0 R 2582 0 R 2583 0 R] +/P 52 0 R +/S /TR +/Type /StructElem +>> +endobj +388 0 obj +<< +/K [2584 0 R 2585 0 R 2586 0 R 2587 0 R 5] +/P 52 0 R +/Pg 13 0 R +/S /TR +/Type /StructElem +>> +endobj +389 0 obj +<< +/K [2588 0 R 2589 0 R 2590 0 R 2591 0 R] +/P 52 0 R +/S /TR +/Type /StructElem +>> +endobj +390 0 obj +<< +/K [2592 0 R 2593 0 R 2594 0 R 2595 0 R 6] +/P 52 0 R +/Pg 13 0 R +/S /TR +/Type /StructElem +>> +endobj +391 0 obj +<< +/K 65 +/P 53 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +392 0 obj +<< +/K [1257 0 R 2596 0 R 1259 0 R] +/P 54 0 R +/S /LI +/Type /StructElem +>> +endobj +393 0 obj +<< +/K [1260 0 R 2597 0 R 1262 0 R 1263 0 R 1265 0 R 1266 0 R 1268 0 R 1269 0 R 1271 0 R 1272 0 R 1274 0 R 1275 0 R 1277 0 R] +/P 54 0 R +/S /LI +/Type /StructElem +>> +endobj +394 0 obj +<< +/K [1278 0 R 2598 0 R 1280 0 R 1281 0 R 1283 0 R 1284 0 R] +/P 54 0 R +/S /LI +/Type /StructElem +>> +endobj +395 0 obj +<< +/K [1286 0 R 2599 0 R 1288 0 R] +/P 54 0 R +/S /LI +/Type /StructElem +>> +endobj +396 0 obj +<< +/K [1289 0 R 2600 0 R 1291 0 R] +/P 54 0 R +/S /LI +/Type /StructElem +>> +endobj +397 0 obj +<< +/K [1292 0 R 2601 0 R 1294 0 R 1295 0 R 1297 0 R] +/P 54 0 R +/S /LI +/Type /StructElem +>> +endobj +398 0 obj +<< +/K 107 +/P 55 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +399 0 obj +<< +/K 108 +/P 56 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +400 0 obj +<< +/K [258 0 R 259 0 R 260 0 R] +/P 57 0 R +/S /TR +/Type /StructElem +>> +endobj +401 0 obj +<< +/K [2602 0 R 2603 0 R 2604 0 R] +/P 57 0 R +/S /TR +/Type /StructElem +>> +endobj +402 0 obj +<< +/K [2605 0 R 2606 0 R 2607 0 R 11] +/P 57 0 R +/Pg 13 0 R +/S /TR +/Type /StructElem +>> +endobj +403 0 obj +<< +/K [2608 0 R 2609 0 R 2610 0 R] +/P 57 0 R +/S /TR +/Type /StructElem +>> +endobj +404 0 obj +<< +/K [2611 0 R 2612 0 R 2613 0 R 12] +/P 57 0 R +/Pg 13 0 R +/S /TR +/Type /StructElem +>> +endobj +405 0 obj +<< +/K [2614 0 R 2615 0 R 2616 0 R] +/P 57 0 R +/S /TR +/Type /StructElem +>> +endobj +406 0 obj +<< +/K [2617 0 R 2618 0 R 2619 0 R 13] +/P 57 0 R +/Pg 13 0 R +/S /TR +/Type /StructElem +>> +endobj +407 0 obj +<< +/K [2620 0 R 2621 0 R 2622 0 R] +/P 57 0 R +/S /TR +/Type /StructElem +>> +endobj +408 0 obj +<< +/K [2623 0 R 2624 0 R 2625 0 R 14] +/P 57 0 R +/Pg 13 0 R +/S /TR +/Type /StructElem +>> +endobj +409 0 obj +<< +/K [2626 0 R 2627 0 R 2628 0 R] +/P 57 0 R +/S /TR +/Type /StructElem +>> +endobj +410 0 obj +<< +/K [2629 0 R 2630 0 R 2631 0 R 15] +/P 57 0 R +/Pg 13 0 R +/S /TR +/Type /StructElem +>> +endobj +411 0 obj +<< +/K [2632 0 R 2633 0 R 2634 0 R] +/P 57 0 R +/S /TR +/Type /StructElem +>> +endobj +412 0 obj +<< +/K [2635 0 R 1353 0 R 1354 0 R 1356 0 R 1357 0 R 1359 0 R 1360 0 R 1362 0 R] +/P 58 0 R +/S /P +/Type /StructElem +>> +endobj +413 0 obj +<< +/K 180 +/P 59 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +414 0 obj +<< +/K [261 0 R 262 0 R 263 0 R] +/P 60 0 R +/S /TR +/Type /StructElem +>> +endobj +415 0 obj +<< +/K [2636 0 R 2637 0 R 2638 0 R] +/P 60 0 R +/S /TR +/Type /StructElem +>> +endobj +416 0 obj +<< +/K [2639 0 R 2640 0 R 2641 0 R 3] +/P 60 0 R +/Pg 14 0 R +/S /TR +/Type /StructElem +>> +endobj +417 0 obj +<< +/K 36 +/P 62 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +418 0 obj +<< +/K 37 +/P 63 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +419 0 obj +<< +/K 1374 0 R +/P 64 0 R +/S /Strong +/Type /StructElem +>> +endobj +420 0 obj +<< +/K 39 +/P 65 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +421 0 obj +<< +/K [264 0 R 265 0 R 266 0 R] +/P 66 0 R +/S /TR +/Type /StructElem +>> +endobj +422 0 obj +<< +/K [2642 0 R 2643 0 R 2644 0 R] +/P 66 0 R +/S /TR +/Type /StructElem +>> +endobj +423 0 obj +<< +/K [2645 0 R 2646 0 R 2647 0 R 10] +/P 66 0 R +/Pg 14 0 R +/S /TR +/Type /StructElem +>> +endobj +424 0 obj +<< +/K [2648 0 R 2649 0 R 2650 0 R] +/P 66 0 R +/S /TR +/Type /StructElem +>> +endobj +425 0 obj +<< +/K [2651 0 R 2652 0 R 2653 0 R 11] +/P 66 0 R +/Pg 14 0 R +/S /TR +/Type /StructElem +>> +endobj +426 0 obj +<< +/K [2654 0 R 2655 0 R 2656 0 R] +/P 66 0 R +/S /TR +/Type /StructElem +>> +endobj +427 0 obj +<< +/K [2657 0 R 2658 0 R 2659 0 R 12] +/P 66 0 R +/Pg 14 0 R +/S /TR +/Type /StructElem +>> +endobj +428 0 obj +<< +/K 69 +/P 67 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +429 0 obj +<< +/K 70 +/P 68 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +430 0 obj +<< +/K 1404 0 R +/P 68 0 R +/S /Strong +/Type /StructElem +>> +endobj +431 0 obj +<< +/K 72 +/P 68 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +432 0 obj +<< +/K [267 0 R 268 0 R 269 0 R 270 0 R] +/P 69 0 R +/S /TR +/Type /StructElem +>> +endobj +433 0 obj +<< +/K [2660 0 R 2661 0 R 2662 0 R 2663 0 R] +/P 69 0 R +/S /TR +/Type /StructElem +>> +endobj +434 0 obj +<< +/K [2664 0 R 2665 0 R 2666 0 R 2667 0 R 18] +/P 69 0 R +/Pg 14 0 R +/S /TR +/Type /StructElem +>> +endobj +435 0 obj +<< +/K [2668 0 R 2669 0 R 2670 0 R 2671 0 R] +/P 69 0 R +/S /TR +/Type /StructElem +>> +endobj +436 0 obj +<< +/K 1430 0 R +/P 70 0 R +/S /Strong +/Type /StructElem +>> +endobj +437 0 obj +<< +/K 99 +/P 70 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +438 0 obj +<< +/K 1431 0 R +/P 70 0 R +/S /Strong +/Type /StructElem +>> +endobj +439 0 obj +<< +/K 101 +/P 70 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +440 0 obj +<< +/K [1432 0 R 102] +/P 70 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +441 0 obj +<< +/K 104 +/P 70 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +442 0 obj +<< +/K [1433 0 R 105] +/P 70 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +443 0 obj +<< +/K 107 +/P 70 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +444 0 obj +<< +/K [1434 0 R 108] +/P 70 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +445 0 obj +<< +/K 110 +/P 70 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +446 0 obj +<< +/K 1435 0 R +/P 71 0 R +/S /Strong +/Type /StructElem +>> +endobj +447 0 obj +<< +/K 112 +/P 71 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +448 0 obj +<< +/K [1436 0 R 113] +/P 71 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +449 0 obj +<< +/K 115 +/P 71 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +450 0 obj +<< +/K [1437 0 R 116] +/P 71 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +451 0 obj +<< +/K 118 +/P 71 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +452 0 obj +<< +/K [1438 0 R 119] +/P 71 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +453 0 obj +<< +/K 121 +/P 71 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +454 0 obj +<< +/K [1439 0 R 122] +/P 71 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +455 0 obj +<< +/K 124 +/P 71 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +456 0 obj +<< +/K [1440 0 R 125] +/P 71 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +457 0 obj +<< +/K 127 +/P 71 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +458 0 obj +<< +/K [1441 0 R 128 130] +/P 71 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +459 0 obj +<< +/K 132 +/P 71 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +460 0 obj +<< +/K 133 +/P 72 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +461 0 obj +<< +/K [271 0 R 272 0 R 273 0 R 274 0 R] +/P 73 0 R +/S /TR +/Type /StructElem +>> +endobj +462 0 obj +<< +/K [2672 0 R 2673 0 R 2674 0 R 2675 0 R] +/P 73 0 R +/S /TR +/Type /StructElem +>> +endobj +463 0 obj +<< +/K [2676 0 R 2677 0 R 2678 0 R 2679 0 R 24] +/P 73 0 R +/Pg 14 0 R +/S /TR +/Type /StructElem +>> +endobj +464 0 obj +<< +/K [2680 0 R 2681 0 R 2682 0 R 2683 0 R] +/P 73 0 R +/S /TR +/Type /StructElem +>> +endobj +465 0 obj +<< +/K [2684 0 R 2685 0 R 2686 0 R 2687 0 R 25] +/P 73 0 R +/Pg 14 0 R +/S /TR +/Type /StructElem +>> +endobj +466 0 obj +<< +/K [2688 0 R 2689 0 R 2690 0 R 2691 0 R] +/P 73 0 R +/S /TR +/Type /StructElem +>> +endobj +467 0 obj +<< +/K [2692 0 R 2693 0 R 2694 0 R 2695 0 R 26] +/P 73 0 R +/Pg 14 0 R +/S /TR +/Type /StructElem +>> +endobj +468 0 obj +<< +/K [2696 0 R 2697 0 R 2698 0 R 2699 0 R] +/P 73 0 R +/S /TR +/Type /StructElem +>> +endobj +469 0 obj +<< +/K [2700 0 R 2701 0 R 2702 0 R 2703 0 R 27] +/P 73 0 R +/Pg 14 0 R +/S /TR +/Type /StructElem +>> +endobj +470 0 obj +<< +/K [2704 0 R 2705 0 R 2706 0 R 2707 0 R] +/P 73 0 R +/S /TR +/Type /StructElem +>> +endobj +471 0 obj +<< +/K [2708 0 R 2709 0 R 2710 0 R 2711 0 R 4] +/P 73 0 R +/Pg 15 0 R +/S /TR +/Type /StructElem +>> +endobj +472 0 obj +<< +/K [2712 0 R 2713 0 R 2714 0 R 2715 0 R] +/P 73 0 R +/S /TR +/Type /StructElem +>> +endobj +473 0 obj +<< +/K [2716 0 R 2717 0 R 2718 0 R 2719 0 R 5] +/P 73 0 R +/Pg 15 0 R +/S /TR +/Type /StructElem +>> +endobj +474 0 obj +<< +/K 47 +/P 74 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +475 0 obj +<< +/K [275 0 R 276 0 R 277 0 R] +/P 75 0 R +/S /TR +/Type /StructElem +>> +endobj +476 0 obj +<< +/K [2720 0 R 2721 0 R 2722 0 R] +/P 75 0 R +/S /TR +/Type /StructElem +>> +endobj +477 0 obj +<< +/K [2723 0 R 2724 0 R 2725 0 R 10] +/P 75 0 R +/Pg 15 0 R +/S /TR +/Type /StructElem +>> +endobj +478 0 obj +<< +/K [2726 0 R 2727 0 R 2728 0 R] +/P 75 0 R +/S /TR +/Type /StructElem +>> +endobj +479 0 obj +<< +/K [2729 0 R 2730 0 R 2731 0 R 11] +/P 75 0 R +/Pg 15 0 R +/S /TR +/Type /StructElem +>> +endobj +480 0 obj +<< +/K 63 +/P 77 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +481 0 obj +<< +/K 64 +/P 78 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +482 0 obj +<< +/K [1522 0 R 65] +/P 78 0 R +/Pg 15 0 R +/S /Code +/Type /StructElem +>> +endobj +483 0 obj +<< +/K 67 +/P 78 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +484 0 obj +<< +/K 68 +/P 79 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +485 0 obj +<< +/K [278 0 R 279 0 R 280 0 R 1486 0 R] +/P 80 0 R +/S /TR +/Type /StructElem +>> +endobj +486 0 obj +<< +/K [2732 0 R 2733 0 R 2734 0 R] +/P 80 0 R +/S /TR +/Type /StructElem +>> +endobj +487 0 obj +<< +/K [2735 0 R 2736 0 R 2737 0 R 19] +/P 80 0 R +/Pg 15 0 R +/S /TR +/Type /StructElem +>> +endobj +488 0 obj +<< +/K [2738 0 R 2739 0 R 2740 0 R] +/P 80 0 R +/S /TR +/Type /StructElem +>> +endobj +489 0 obj +<< +/K [2741 0 R 2742 0 R 2743 0 R 20] +/P 80 0 R +/Pg 15 0 R +/S /TR +/Type /StructElem +>> +endobj +490 0 obj +<< +/K [2744 0 R 2745 0 R 2746 0 R] +/P 80 0 R +/S /TR +/Type /StructElem +>> +endobj +491 0 obj +<< +/K 95 +/P 81 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +492 0 obj +<< +/K [1549 0 R 1550 0 R 1551 0 R 1552 0 R 1553 0 R 1554 0 R 1555 0 R 1556 0 R 1557 0 R 1558 0 R 1559 0 R 1560 0 R 1561 0 R 1562 0 R 1563 0 R 1564 0 R +1565 0 R 1566 0 R 1567 0 R 1568 0 R 1569 0 R 1570 0 R 1571 0 R 1572 0 R 1573 0 R 1574 0 R 1575 0 R 1576 0 R 1577 0 R 1578 0 R 1579 0 R 1580 0 R +1581 0 R 1582 0 R 1583 0 R 1584 0 R 1585 0 R 1586 0 R 1587 0 R 1588 0 R 1589 0 R 1590 0 R 1591 0 R 1592 0 R 1593 0 R 1594 0 R 1595 0 R 1596 0 R +1597 0 R 1598 0 R 1599 0 R 1600 0 R 1601 0 R 1602 0 R 1603 0 R 1604 0 R 1605 0 R 1606 0 R 1607 0 R 1608 0 R 1609 0 R 1610 0 R 1611 0 R 1612 0 R +1613 0 R 1614 0 R 1615 0 R 1616 0 R 1617 0 R 1618 0 R 1619 0 R 1620 0 R 1621 0 R 1622 0 R 1623 0 R 1624 0 R 1625 0 R 1626 0 R 1627 0 R 1628 0 R +1629 0 R 1630 0 R 1631 0 R 1632 0 R 1633 0 R 1634 0 R 1635 0 R 1636 0 R 1637 0 R 1638 0 R 1639 0 R 1640 0 R 1641 0 R 1642 0 R 1643 0 R 1644 0 R +1645 0 R 1646 0 R 1647 0 R 1648 0 R 1649 0 R 1650 0 R 1651 0 R 1652 0 R 1653 0 R 1654 0 R 1655 0 R 1656 0 R 1657 0 R 1658 0 R] +/P 82 0 R +/S /Code +/Type /StructElem +>> +endobj +493 0 obj +<< +/K 206 +/P 83 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +494 0 obj +<< +/K [1659 0 R 1660 0 R 1662 0 R] +/P 84 0 R +/S /LI +/Type /StructElem +>> +endobj +495 0 obj +<< +/K [1663 0 R 1664 0 R 1665 0 R 1667 0 R 1668 0 R 1670 0 R] +/P 84 0 R +/S /LI +/Type /StructElem +>> +endobj +496 0 obj +<< +/K [1671 0 R 1672 0 R] +/P 84 0 R +/S /LI +/Type /StructElem +>> +endobj +497 0 obj +<< +/K [1673 0 R 1674 0 R 1676 0 R] +/P 84 0 R +/S /LI +/Type /StructElem +>> +endobj +498 0 obj +<< +/K 6 +/P 86 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +499 0 obj +<< +/K 7 +/P 87 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +500 0 obj +<< +/K 8 +/P 88 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +501 0 obj +<< +/K [1677 0 R 9] +/P 88 0 R +/Pg 16 0 R +/S /Code +/Type /StructElem +>> +endobj +502 0 obj +<< +/K 11 +/P 88 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +503 0 obj +<< +/K [1678 0 R 12] +/P 88 0 R +/Pg 16 0 R +/S /Code +/Type /StructElem +>> +endobj +504 0 obj +<< +/K 14 +/P 88 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +505 0 obj +<< +/K 1679 0 R +/P 89 0 R +/S /Code +/Type /StructElem +>> +endobj +506 0 obj +<< +/K 16 +/P 90 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +507 0 obj +<< +/K 17 +/P 91 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +508 0 obj +<< +/K 18 +/P 93 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +509 0 obj +<< +/K 19 +/P 94 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +510 0 obj +<< +/K 20 +/P 95 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +511 0 obj +<< +/K 1680 0 R +/P 96 0 R +/S /Strong +/Type /StructElem +>> +endobj +512 0 obj +<< +/K 22 +/P 96 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +513 0 obj +<< +/K 1681 0 R +/P 96 0 R +/S /Strong +/Type /StructElem +>> +endobj +514 0 obj +<< +/K 24 +/P 96 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +515 0 obj +<< +/K [1682 0 R 25] +/P 96 0 R +/Pg 16 0 R +/S /Code +/Type /StructElem +>> +endobj +516 0 obj +<< +/K 27 +/P 96 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +517 0 obj +<< +/K [1683 0 R 28] +/P 96 0 R +/Pg 16 0 R +/S /Code +/Type /StructElem +>> +endobj +518 0 obj +<< +/K 30 +/P 96 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +519 0 obj +<< +/K [1684 0 R 31] +/P 96 0 R +/Pg 16 0 R +/S /Code +/Type /StructElem +>> +endobj +520 0 obj +<< +/K 33 +/P 96 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +521 0 obj +<< +/K 1685 0 R +/P 97 0 R +/S /Strong +/Type /StructElem +>> +endobj +522 0 obj +<< +/K 35 +/P 97 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +523 0 obj +<< +/K 36 +/P 98 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +524 0 obj +<< +/K 1686 0 R +/P 99 0 R +/S /Strong +/Type /StructElem +>> +endobj +525 0 obj +<< +/K 38 +/P 99 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +526 0 obj +<< +/K 1687 0 R +/P 99 0 R +/S /Strong +/Type /StructElem +>> +endobj +527 0 obj +<< +/K 40 +/P 99 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +528 0 obj +<< +/K [1688 0 R 41] +/P 99 0 R +/Pg 16 0 R +/S /Code +/Type /StructElem +>> +endobj +529 0 obj +<< +/K 43 +/P 99 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +530 0 obj +<< +/K 1689 0 R +/P 99 0 R +/S /Strong +/Type /StructElem +>> +endobj +531 0 obj +<< +/K 45 +/P 99 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +532 0 obj +<< +/K [1690 0 R 1691 0 R 1692 0 R 1693 0 R 1694 0 R 1695 0 R 1696 0 R 1697 0 R 1698 0 R 1699 0 R 1700 0 R 1701 0 R 1702 0 R 1703 0 R 1704 0 R 1705 0 R +1706 0 R 1707 0 R 1708 0 R 1709 0 R 1710 0 R 1711 0 R 1712 0 R 1713 0 R 1714 0 R 1715 0 R 1716 0 R 1717 0 R 1718 0 R 1719 0 R 1720 0 R 1721 0 R +1722 0 R 1723 0 R 1724 0 R 1725 0 R 1726 0 R 1727 0 R 1728 0 R 1729 0 R 1730 0 R 1731 0 R 1732 0 R 1733 0 R 1734 0 R] +/P 100 0 R +/S /Code +/Type /StructElem +>> +endobj +533 0 obj +<< +/K 1735 0 R +/P 101 0 R +/S /Strong +/Type /StructElem +>> +endobj +534 0 obj +<< +/K 92 +/P 101 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +535 0 obj +<< +/K 93 +/P 102 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +536 0 obj +<< +/K 1736 0 R +/P 103 0 R +/S /Strong +/Type /StructElem +>> +endobj +537 0 obj +<< +/K 95 +/P 103 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +538 0 obj +<< +/K 1737 0 R +/P 103 0 R +/S /Strong +/Type /StructElem +>> +endobj +539 0 obj +<< +/K 97 +/P 103 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +540 0 obj +<< +/K [1738 0 R 98] +/P 103 0 R +/Pg 16 0 R +/S /Code +/Type /StructElem +>> +endobj +541 0 obj +<< +/K 100 +/P 103 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +542 0 obj +<< +/K [1739 0 R 101] +/P 103 0 R +/Pg 16 0 R +/S /Code +/Type /StructElem +>> +endobj +543 0 obj +<< +/K 103 +/P 103 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +544 0 obj +<< +/K 1740 0 R +/P 104 0 R +/S /Strong +/Type /StructElem +>> +endobj +545 0 obj +<< +/K 105 +/P 104 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +546 0 obj +<< +/K [1741 0 R 106] +/P 104 0 R +/Pg 16 0 R +/S /Code +/Type /StructElem +>> +endobj +547 0 obj +<< +/K 108 +/P 104 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +548 0 obj +<< +/K [1742 0 R 109] +/P 104 0 R +/Pg 16 0 R +/S /Code +/Type /StructElem +>> +endobj +549 0 obj +<< +/K 3 +/P 105 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +550 0 obj +<< +/K 1743 0 R +/P 106 0 R +/S /Strong +/Type /StructElem +>> +endobj +551 0 obj +<< +/K 5 +/P 106 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +552 0 obj +<< +/K 1744 0 R +/P 106 0 R +/S /Strong +/Type /StructElem +>> +endobj +553 0 obj +<< +/K 7 +/P 106 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +554 0 obj +<< +/K [1745 0 R 8] +/P 106 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +555 0 obj +<< +/K 10 +/P 106 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +556 0 obj +<< +/K [1746 0 R 11] +/P 106 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +557 0 obj +<< +/K 13 +/P 106 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +558 0 obj +<< +/K [1747 0 R 14] +/P 106 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +559 0 obj +<< +/K 16 +/P 106 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +560 0 obj +<< +/K [1748 0 R 17] +/P 106 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +561 0 obj +<< +/K 19 +/P 106 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +562 0 obj +<< +/K 1749 0 R +/P 107 0 R +/S /Strong +/Type /StructElem +>> +endobj +563 0 obj +<< +/K 21 +/P 107 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +564 0 obj +<< +/K [1750 0 R 1751 0 R 1752 0 R 1753 0 R 1754 0 R 1755 0 R 1756 0 R 1757 0 R 1758 0 R 1759 0 R 1760 0 R 1761 0 R 1762 0 R 1763 0 R 1764 0 R 1765 0 R +1766 0 R 1767 0 R 1768 0 R 1769 0 R 1770 0 R 1771 0 R 1772 0 R 1773 0 R 1774 0 R 1775 0 R 1776 0 R 1777 0 R] +/P 108 0 R +/S /Code +/Type /StructElem +>> +endobj +565 0 obj +<< +/K 2747 0 R +/P 109 0 R +/S /P +/Type /StructElem +>> +endobj +566 0 obj +<< +/K 51 +/P 110 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +567 0 obj +<< +/K 1779 0 R +/P 110 0 R +/S /Strong +/Type /StructElem +>> +endobj +568 0 obj +<< +/K 53 +/P 111 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +569 0 obj +<< +/K 54 +/P 112 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +570 0 obj +<< +/K 55 +/P 113 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +571 0 obj +<< +/K 1780 0 R +/P 114 0 R +/S /Strong +/Type /StructElem +>> +endobj +572 0 obj +<< +/K 57 +/P 114 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +573 0 obj +<< +/K 1781 0 R +/P 114 0 R +/S /Strong +/Type /StructElem +>> +endobj +574 0 obj +<< +/K 59 +/P 114 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +575 0 obj +<< +/K [1782 0 R 60] +/P 114 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +576 0 obj +<< +/K 62 +/P 114 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +577 0 obj +<< +/K [1783 0 R 63] +/P 114 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +578 0 obj +<< +/K 65 +/P 115 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +579 0 obj +<< +/K 1784 0 R +/P 116 0 R +/S /Strong +/Type /StructElem +>> +endobj +580 0 obj +<< +/K 67 +/P 116 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +581 0 obj +<< +/K 1785 0 R +/P 116 0 R +/S /Strong +/Type /StructElem +>> +endobj +582 0 obj +<< +/K 69 +/P 116 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +583 0 obj +<< +/K [1786 0 R 70] +/P 116 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +584 0 obj +<< +/K 72 +/P 116 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +585 0 obj +<< +/K [1787 0 R 73] +/P 116 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +586 0 obj +<< +/K 75 +/P 116 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +587 0 obj +<< +/K 76 +/P 117 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +588 0 obj +<< +/K 1788 0 R +/P 118 0 R +/S /Strong +/Type /StructElem +>> +endobj +589 0 obj +<< +/K 78 +/P 118 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +590 0 obj +<< +/K 1789 0 R +/P 118 0 R +/S /Strong +/Type /StructElem +>> +endobj +591 0 obj +<< +/K 80 +/P 118 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +592 0 obj +<< +/K [1790 0 R 81] +/P 118 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +593 0 obj +<< +/K 83 +/P 118 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +594 0 obj +<< +/K 84 +/P 119 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +595 0 obj +<< +/K 1791 0 R +/P 120 0 R +/S /Strong +/Type /StructElem +>> +endobj +596 0 obj +<< +/K 86 +/P 120 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +597 0 obj +<< +/K 1792 0 R +/P 120 0 R +/S /Strong +/Type /StructElem +>> +endobj +598 0 obj +<< +/K 88 +/P 120 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +599 0 obj +<< +/K [1793 0 R 89] +/P 120 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +600 0 obj +<< +/K 91 +/P 120 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +601 0 obj +<< +/K 1794 0 R +/P 121 0 R +/S /Strong +/Type /StructElem +>> +endobj +602 0 obj +<< +/K 93 +/P 121 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +603 0 obj +<< +/K 94 +/P 122 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +604 0 obj +<< +/K 1795 0 R +/P 122 0 R +/S /Strong +/Type /StructElem +>> +endobj +605 0 obj +<< +/K 96 +/P 123 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +606 0 obj +<< +/K 97 +/P 124 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +607 0 obj +<< +/K 98 +/P 125 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +608 0 obj +<< +/K [1796 0 R 99] +/P 125 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +609 0 obj +<< +/K 101 +/P 125 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +610 0 obj +<< +/K 1797 0 R +/P 126 0 R +/S /Strong +/Type /StructElem +>> +endobj +611 0 obj +<< +/K 103 +/P 126 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +612 0 obj +<< +/K 104 +/P 127 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +613 0 obj +<< +/K 1798 0 R +/P 128 0 R +/S /Strong +/Type /StructElem +>> +endobj +614 0 obj +<< +/K 106 +/P 128 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +615 0 obj +<< +/K 1799 0 R +/P 128 0 R +/S /Strong +/Type /StructElem +>> +endobj +616 0 obj +<< +/K 108 +/P 128 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +617 0 obj +<< +/K [1800 0 R 109] +/P 128 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +618 0 obj +<< +/K 111 +/P 128 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +619 0 obj +<< +/K [1801 0 R 112] +/P 128 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +620 0 obj +<< +/K 114 +/P 128 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +621 0 obj +<< +/K [1802 0 R 115] +/P 128 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +622 0 obj +<< +/K 117 +/P 128 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +623 0 obj +<< +/K [1803 0 R 118] +/P 128 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +624 0 obj +<< +/K 120 +/P 128 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +625 0 obj +<< +/K [1804 0 R 121] +/P 128 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +626 0 obj +<< +/K 123 +/P 128 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +627 0 obj +<< +/K 124 +/P 129 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +628 0 obj +<< +/K 1805 0 R +/P 130 0 R +/S /Strong +/Type /StructElem +>> +endobj +629 0 obj +<< +/K 126 +/P 130 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +630 0 obj +<< +/K 1806 0 R +/P 130 0 R +/S /Strong +/Type /StructElem +>> +endobj +631 0 obj +<< +/K 128 +/P 130 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +632 0 obj +<< +/K [1807 0 R 129] +/P 130 0 R +/Pg 17 0 R +/S /Code +/Type /StructElem +>> +endobj +633 0 obj +<< +/K 131 +/P 130 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +634 0 obj +<< +/K 11 +/P 132 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +635 0 obj +<< +/K 12 +/P 133 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +636 0 obj +<< +/K [281 0 R 282 0 R 283 0 R] +/P 134 0 R +/S /TR +/Type /StructElem +>> +endobj +637 0 obj +<< +/K [2748 0 R 2749 0 R 2750 0 R] +/P 134 0 R +/S /TR +/Type /StructElem +>> +endobj +638 0 obj +<< +/K [2751 0 R 2752 0 R 2753 0 R 4] +/P 134 0 R +/Pg 18 0 R +/S /TR +/Type /StructElem +>> +endobj +639 0 obj +<< +/K [2754 0 R 2755 0 R 2756 0 R] +/P 134 0 R +/S /TR +/Type /StructElem +>> +endobj +640 0 obj +<< +/K [2757 0 R 2758 0 R 2759 0 R 5] +/P 134 0 R +/Pg 18 0 R +/S /TR +/Type /StructElem +>> +endobj +641 0 obj +<< +/K [2760 0 R 2761 0 R 2762 0 R] +/P 134 0 R +/S /TR +/Type /StructElem +>> +endobj +642 0 obj +<< +/K 31 +/P 135 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +643 0 obj +<< +/K 32 +/P 136 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +644 0 obj +<< +/K 1826 0 R +/P 137 0 R +/S /Strong +/Type /StructElem +>> +endobj +645 0 obj +<< +/K 34 +/P 137 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +646 0 obj +<< +/K 1827 0 R +/P 137 0 R +/S /Strong +/Type /StructElem +>> +endobj +647 0 obj +<< +/K 36 +/P 137 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +648 0 obj +<< +/K 1828 0 R +/P 137 0 R +/S /Strong +/Type /StructElem +>> +endobj +649 0 obj +<< +/K 38 +/P 137 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +650 0 obj +<< +/K [1829 0 R 39] +/P 137 0 R +/Pg 18 0 R +/S /Code +/Type /StructElem +>> +endobj +651 0 obj +<< +/K 41 +/P 137 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +652 0 obj +<< +/K [1830 0 R 1831 0 R 1832 0 R 1833 0 R 1834 0 R] +/P 138 0 R +/S /Code +/Type /StructElem +>> +endobj +653 0 obj +<< +/K 47 +/P 139 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +654 0 obj +<< +/K 1835 0 R +/P 140 0 R +/S /Strong +/Type /StructElem +>> +endobj +655 0 obj +<< +/K 49 +/P 140 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +656 0 obj +<< +/K 1836 0 R +/P 140 0 R +/S /Strong +/Type /StructElem +>> +endobj +657 0 obj +<< +/K 51 +/P 140 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +658 0 obj +<< +/K [1837 0 R 52] +/P 140 0 R +/Pg 18 0 R +/S /Code +/Type /StructElem +>> +endobj +659 0 obj +<< +/K 54 +/P 140 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +660 0 obj +<< +/K 1838 0 R +/P 140 0 R +/S /Strong +/Type /StructElem +>> +endobj +661 0 obj +<< +/K 56 +/P 140 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +662 0 obj +<< +/K [1839 0 R 57] +/P 140 0 R +/Pg 18 0 R +/S /Code +/Type /StructElem +>> +endobj +663 0 obj +<< +/K 59 +/P 140 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +664 0 obj +<< +/K [1840 0 R 1841 0 R 1842 0 R 1843 0 R 1844 0 R 1845 0 R 1846 0 R] +/P 141 0 R +/S /Code +/Type /StructElem +>> +endobj +665 0 obj +<< +/K 67 +/P 142 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +666 0 obj +<< +/K 1847 0 R +/P 143 0 R +/S /Strong +/Type /StructElem +>> +endobj +667 0 obj +<< +/K 69 +/P 143 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +668 0 obj +<< +/K 1848 0 R +/P 143 0 R +/S /Strong +/Type /StructElem +>> +endobj +669 0 obj +<< +/K 71 +/P 143 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +670 0 obj +<< +/K [1849 0 R 72] +/P 143 0 R +/Pg 18 0 R +/S /Code +/Type /StructElem +>> +endobj +671 0 obj +<< +/K 74 +/P 143 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +672 0 obj +<< +/K 1850 0 R +/P 143 0 R +/S /Strong +/Type /StructElem +>> +endobj +673 0 obj +<< +/K 76 +/P 143 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +674 0 obj +<< +/K [1851 0 R 1852 0 R 1853 0 R 1854 0 R 1855 0 R 1856 0 R 1857 0 R 1858 0 R 1859 0 R 1860 0 R 1861 0 R 1862 0 R 1863 0 R 1864 0 R 1865 0 R 1866 0 R +1867 0 R 1868 0 R 1869 0 R 1870 0 R 1871 0 R 1872 0 R 1873 0 R 1874 0 R 1875 0 R 1876 0 R 1877 0 R 1878 0 R 1879 0 R 1880 0 R 1881 0 R 1882 0 R +1883 0 R 1884 0 R 1885 0 R 1886 0 R 1887 0 R 1888 0 R 1889 0 R 1890 0 R 1891 0 R] +/P 144 0 R +/S /Code +/Type /StructElem +>> +endobj +675 0 obj +<< +/K 118 +/P 145 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +676 0 obj +<< +/K 1892 0 R +/P 146 0 R +/S /Strong +/Type /StructElem +>> +endobj +677 0 obj +<< +/K 120 +/P 146 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +678 0 obj +<< +/K 1893 0 R +/P 146 0 R +/S /Strong +/Type /StructElem +>> +endobj +679 0 obj +<< +/K 122 +/P 146 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +680 0 obj +<< +/K [1894 0 R 123] +/P 146 0 R +/Pg 18 0 R +/S /Code +/Type /StructElem +>> +endobj +681 0 obj +<< +/K 125 +/P 146 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +682 0 obj +<< +/K 1895 0 R +/P 146 0 R +/S /Strong +/Type /StructElem +>> +endobj +683 0 obj +<< +/K 127 +/P 146 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +684 0 obj +<< +/K 1896 0 R +/P 146 0 R +/S /Strong +/Type /StructElem +>> +endobj +685 0 obj +<< +/K 129 +/P 146 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +686 0 obj +<< +/K [1897 0 R 1898 0 R 1899 0 R 1900 0 R 1901 0 R 1902 0 R] +/P 147 0 R +/S /Code +/Type /StructElem +>> +endobj +687 0 obj +<< +/K 10 +/P 148 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +688 0 obj +<< +/K 1903 0 R +/P 149 0 R +/S /Strong +/Type /StructElem +>> +endobj +689 0 obj +<< +/K 12 +/P 149 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +690 0 obj +<< +/K 1904 0 R +/P 150 0 R +/S /Strong +/Type /StructElem +>> +endobj +691 0 obj +<< +/K 14 +/P 150 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +692 0 obj +<< +/K [1905 0 R 15] +/P 150 0 R +/Pg 19 0 R +/S /Code +/Type /StructElem +>> +endobj +693 0 obj +<< +/K 17 +/P 150 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +694 0 obj +<< +/K [1906 0 R 18] +/P 150 0 R +/Pg 19 0 R +/S /Code +/Type /StructElem +>> +endobj +695 0 obj +<< +/K 20 +/P 150 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +696 0 obj +<< +/K 1907 0 R +/P 151 0 R +/S /Code +/Type /StructElem +>> +endobj +697 0 obj +<< +/K 1908 0 R +/P 152 0 R +/S /Strong +/Type /StructElem +>> +endobj +698 0 obj +<< +/K 1909 0 R +/P 153 0 R +/S /Strong +/Type /StructElem +>> +endobj +699 0 obj +<< +/K [284 0 R 285 0 R 286 0 R 287 0 R] +/P 154 0 R +/S /TR +/Type /StructElem +>> +endobj +700 0 obj +<< +/K [2763 0 R 2764 0 R 2765 0 R 2766 0 R] +/P 154 0 R +/S /TR +/Type /StructElem +>> +endobj +701 0 obj +<< +/K [2767 0 R 2768 0 R 2769 0 R 2770 0 R 5] +/P 154 0 R +/Pg 19 0 R +/S /TR +/Type /StructElem +>> +endobj +702 0 obj +<< +/K [2771 0 R 2772 0 R 2773 0 R 2774 0 R] +/P 154 0 R +/S /TR +/Type /StructElem +>> +endobj +703 0 obj +<< +/K [2775 0 R 2776 0 R 2777 0 R 2778 0 R 6] +/P 154 0 R +/Pg 19 0 R +/S /TR +/Type /StructElem +>> +endobj +704 0 obj +<< +/K 1935 0 R +/P 155 0 R +/S /Strong +/Type /StructElem +>> +endobj +705 0 obj +<< +/K 50 +/P 155 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +706 0 obj +<< +/K 1936 0 R +/P 156 0 R +/S /Strong +/Type /StructElem +>> +endobj +707 0 obj +<< +/K [1937 0 R 52] +/P 157 0 R +/Pg 19 0 R +/S /Code +/Type /StructElem +>> +endobj +708 0 obj +<< +/K 54 +/P 157 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +709 0 obj +<< +/K [1938 0 R 55] +/P 157 0 R +/Pg 19 0 R +/S /Code +/Type /StructElem +>> +endobj +710 0 obj +<< +/K 57 +/P 157 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +711 0 obj +<< +/K [1939 0 R 58] +/P 157 0 R +/Pg 19 0 R +/S /Code +/Type /StructElem +>> +endobj +712 0 obj +<< +/K 60 +/P 157 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +713 0 obj +<< +/K [1940 0 R 1941 0 R 1942 0 R 1943 0 R 1944 0 R 1945 0 R 1946 0 R 1947 0 R 1948 0 R 1949 0 R 1950 0 R 1951 0 R 1952 0 R 1953 0 R 1954 0 R 1955 0 R] +/P 158 0 R +/S /Code +/Type /StructElem +>> +endobj +714 0 obj +<< +/K 77 +/P 159 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +715 0 obj +<< +/K 1956 0 R +/P 160 0 R +/S /Strong +/Type /StructElem +>> +endobj +716 0 obj +<< +/K 79 +/P 161 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +717 0 obj +<< +/K [1957 0 R 80] +/P 161 0 R +/Pg 19 0 R +/S /Code +/Type /StructElem +>> +endobj +718 0 obj +<< +/K 82 +/P 161 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +719 0 obj +<< +/K [1958 0 R 1959 0 R 1960 0 R 1961 0 R 1962 0 R 1963 0 R 1964 0 R 1965 0 R 1966 0 R 1967 0 R 1968 0 R 1969 0 R 1970 0 R 1971 0 R 1972 0 R 1973 0 R +1974 0 R 1975 0 R 1976 0 R 1977 0 R 1978 0 R 1979 0 R 1980 0 R 1981 0 R 1982 0 R 1983 0 R 1984 0 R 1985 0 R 1986 0 R 1987 0 R 1988 0 R 1989 0 R +1990 0 R 1991 0 R 1992 0 R 1993 0 R 1994 0 R 1995 0 R 1996 0 R 1997 0 R 1998 0 R 1999 0 R 2000 0 R 2001 0 R 2002 0 R 2003 0 R 2004 0 R 2005 0 R +2006 0 R 2007 0 R 2008 0 R 2009 0 R 2010 0 R 2011 0 R 2012 0 R 2013 0 R 2014 0 R 2015 0 R 2016 0 R 2017 0 R 2018 0 R 2019 0 R 2020 0 R] +/P 162 0 R +/S /Code +/Type /StructElem +>> +endobj +720 0 obj +<< +/K 18 +/P 163 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +721 0 obj +<< +/K [2021 0 R 19] +/P 163 0 R +/Pg 20 0 R +/S /Code +/Type /StructElem +>> +endobj +722 0 obj +<< +/K 21 +/P 163 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +723 0 obj +<< +/K 2022 0 R +/P 163 0 R +/S /Strong +/Type /StructElem +>> +endobj +724 0 obj +<< +/K 23 +/P 163 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +725 0 obj +<< +/K 2023 0 R +/P 164 0 R +/S /Strong +/Type /StructElem +>> +endobj +726 0 obj +<< +/K [2024 0 R 25] +/P 165 0 R +/Pg 20 0 R +/S /Code +/Type /StructElem +>> +endobj +727 0 obj +<< +/K 27 +/P 165 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +728 0 obj +<< +/K [2025 0 R 2026 0 R 2027 0 R 2028 0 R 2029 0 R 2030 0 R 2031 0 R 2032 0 R 2033 0 R 2034 0 R 2035 0 R 2036 0 R 2037 0 R 2038 0 R 2039 0 R 2040 0 R +2041 0 R 2042 0 R 2043 0 R 2044 0 R 2045 0 R 2046 0 R 2047 0 R 2048 0 R 2049 0 R 2050 0 R 2051 0 R 2052 0 R 2053 0 R 2054 0 R 2055 0 R 2056 0 R +2057 0 R 2058 0 R 2059 0 R 2060 0 R 2061 0 R 2062 0 R 2063 0 R 2064 0 R 2065 0 R 2066 0 R 2067 0 R 2068 0 R 2069 0 R 2070 0 R 2071 0 R 2072 0 R +2073 0 R 2074 0 R 2075 0 R 2076 0 R 2077 0 R 2078 0 R 2079 0 R 2080 0 R 2081 0 R 2082 0 R 2083 0 R 2084 0 R 2085 0 R] +/P 166 0 R +/S /Code +/Type /StructElem +>> +endobj +729 0 obj +<< +/K 89 +/P 167 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +730 0 obj +<< +/K 90 +/P 168 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +731 0 obj +<< +/K 91 +/P 169 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +732 0 obj +<< +/K 2086 0 R +/P 170 0 R +/S /Strong +/Type /StructElem +>> +endobj +733 0 obj +<< +/K 93 +/P 170 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +734 0 obj +<< +/K 2087 0 R +/P 170 0 R +/S /Strong +/Type /StructElem +>> +endobj +735 0 obj +<< +/K 95 +/P 170 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +736 0 obj +<< +/K 2088 0 R +/P 170 0 R +/S /Strong +/Type /StructElem +>> +endobj +737 0 obj +<< +/K 97 +/P 170 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +738 0 obj +<< +/K [2089 0 R 98] +/P 170 0 R +/Pg 20 0 R +/S /Code +/Type /StructElem +>> +endobj +739 0 obj +<< +/K 100 +/P 170 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +740 0 obj +<< +/K 2090 0 R +/P 170 0 R +/S /Strong +/Type /StructElem +>> +endobj +741 0 obj +<< +/K 102 +/P 170 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +742 0 obj +<< +/K [2091 0 R 103] +/P 170 0 R +/Pg 20 0 R +/S /Code +/Type /StructElem +>> +endobj +743 0 obj +<< +/K 105 +/P 170 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +744 0 obj +<< +/K 106 +/P 171 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +745 0 obj +<< +/K [288 0 R 289 0 R 290 0 R] +/P 172 0 R +/S /TR +/Type /StructElem +>> +endobj +746 0 obj +<< +/K [2779 0 R 2780 0 R 2781 0 R] +/P 172 0 R +/S /TR +/Type /StructElem +>> +endobj +747 0 obj +<< +/K [2782 0 R 2783 0 R 2784 0 R 5] +/P 172 0 R +/Pg 20 0 R +/S /TR +/Type /StructElem +>> +endobj +748 0 obj +<< +/K [2785 0 R 2786 0 R 2787 0 R] +/P 172 0 R +/S /TR +/Type /StructElem +>> +endobj +749 0 obj +<< +/K [2788 0 R 2789 0 R 2790 0 R 6] +/P 172 0 R +/Pg 20 0 R +/S /TR +/Type /StructElem +>> +endobj +750 0 obj +<< +/K [2791 0 R 2792 0 R 2793 0 R] +/P 172 0 R +/S /TR +/Type /StructElem +>> +endobj +751 0 obj +<< +/K [2794 0 R 2795 0 R 2796 0 R 7] +/P 172 0 R +/Pg 20 0 R +/S /TR +/Type /StructElem +>> +endobj +752 0 obj +<< +/K [2797 0 R 2798 0 R 2799 0 R] +/P 172 0 R +/S /TR +/Type /StructElem +>> +endobj +753 0 obj +<< +/K [2800 0 R 2801 0 R 2802 0 R 8] +/P 172 0 R +/Pg 20 0 R +/S /TR +/Type /StructElem +>> +endobj +754 0 obj +<< +/K [2803 0 R 2804 0 R 2805 0 R] +/P 172 0 R +/S /TR +/Type /StructElem +>> +endobj +755 0 obj +<< +/K 137 +/P 174 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +756 0 obj +<< +/K 138 +/P 175 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +757 0 obj +<< +/K 139 +/P 176 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +758 0 obj +<< +/K 140 +/P 177 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +759 0 obj +<< +/K [2122 0 R 141] +/P 177 0 R +/Pg 20 0 R +/S /Code +/Type /StructElem +>> +endobj +760 0 obj +<< +/K 143 +/P 177 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +761 0 obj +<< +/K 144 +/P 178 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +762 0 obj +<< +/K 145 +/P 179 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +763 0 obj +<< +/K [2123 0 R 146] +/P 179 0 R +/Pg 20 0 R +/S /Code +/Type /StructElem +>> +endobj +764 0 obj +<< +/K 148 +/P 179 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +765 0 obj +<< +/K [2124 0 R 149] +/P 179 0 R +/Pg 20 0 R +/S /Code +/Type /StructElem +>> +endobj +766 0 obj +<< +/K 151 +/P 179 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +767 0 obj +<< +/K 152 +/P 180 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +768 0 obj +<< +/K 153 +/P 181 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +769 0 obj +<< +/K [2125 0 R 154] +/P 181 0 R +/Pg 20 0 R +/S /Code +/Type /StructElem +>> +endobj +770 0 obj +<< +/K 156 +/P 181 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +771 0 obj +<< +/K 27 +/P 182 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +772 0 obj +<< +/K [2126 0 R 28] +/P 183 0 R +/Pg 21 0 R +/S /Code +/Type /StructElem +>> +endobj +773 0 obj +<< +/K 30 +/P 183 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +774 0 obj +<< +/K [2127 0 R 31] +/P 183 0 R +/Pg 21 0 R +/S /Code +/Type /StructElem +>> +endobj +775 0 obj +<< +/K 33 +/P 183 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +776 0 obj +<< +/K [2128 0 R 34] +/P 183 0 R +/Pg 21 0 R +/S /Code +/Type /StructElem +>> +endobj +777 0 obj +<< +/K 36 +/P 183 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +778 0 obj +<< +/K [2129 0 R 37] +/P 183 0 R +/Pg 21 0 R +/S /Code +/Type /StructElem +>> +endobj +779 0 obj +<< +/K 39 +/P 183 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +780 0 obj +<< +/K [2130 0 R 40] +/P 183 0 R +/Pg 21 0 R +/S /Code +/Type /StructElem +>> +endobj +781 0 obj +<< +/K 42 +/P 183 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +782 0 obj +<< +/K 43 +/P 184 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +783 0 obj +<< +/K [2131 0 R 2132 0 R 2134 0 R 2135 0 R 2137 0 R] +/P 185 0 R +/S /LI +/Type /StructElem +>> +endobj +784 0 obj +<< +/K [2138 0 R 2139 0 R 2141 0 R 2142 0 R 2144 0 R] +/P 185 0 R +/S /LI +/Type /StructElem +>> +endobj +785 0 obj +<< +/K [2145 0 R 2146 0 R 2148 0 R] +/P 185 0 R +/S /LI +/Type /StructElem +>> +endobj +786 0 obj +<< +/K [2149 0 R 2150 0 R 2151 0 R 2153 0 R 2154 0 R 2156 0 R 2157 0 R 2159 0 R] +/P 185 0 R +/S /LI +/Type /StructElem +>> +endobj +787 0 obj +<< +/K 73 +/P 186 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +788 0 obj +<< +/K [291 0 R 292 0 R 293 0 R] +/P 187 0 R +/S /TR +/Type /StructElem +>> +endobj +789 0 obj +<< +/K [2806 0 R 2807 0 R 2808 0 R] +/P 187 0 R +/S /TR +/Type /StructElem +>> +endobj +790 0 obj +<< +/K [2809 0 R 2810 0 R 2811 0 R 3] +/P 187 0 R +/Pg 21 0 R +/S /TR +/Type /StructElem +>> +endobj +791 0 obj +<< +/K [2812 0 R 2813 0 R 2814 0 R] +/P 187 0 R +/S /TR +/Type /StructElem +>> +endobj +792 0 obj +<< +/K [2815 0 R 2816 0 R 2817 0 R 4] +/P 187 0 R +/Pg 21 0 R +/S /TR +/Type /StructElem +>> +endobj +793 0 obj +<< +/K 89 +/P 189 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +794 0 obj +<< +/K 90 +/P 190 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +795 0 obj +<< +/K [294 0 R 295 0 R 296 0 R 297 0 R] +/P 191 0 R +/S /TR +/Type /StructElem +>> +endobj +796 0 obj +<< +/K [2818 0 R 2819 0 R 2820 0 R 2821 0 R] +/P 191 0 R +/S /TR +/Type /StructElem +>> +endobj +797 0 obj +<< +/K [2822 0 R 2823 0 R 2824 0 R 2825 0 R 12] +/P 191 0 R +/Pg 21 0 R +/S /TR +/Type /StructElem +>> +endobj +798 0 obj +<< +/K [2826 0 R 2827 0 R 2828 0 R 2829 0 R] +/P 191 0 R +/S /TR +/Type /StructElem +>> +endobj +799 0 obj +<< +/K [2830 0 R 2831 0 R 2832 0 R 2833 0 R 13] +/P 191 0 R +/Pg 21 0 R +/S /TR +/Type /StructElem +>> +endobj +800 0 obj +<< +/K 111 +/P 192 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +801 0 obj +<< +/K [298 0 R 299 0 R 300 0 R] +/P 193 0 R +/S /TR +/Type /StructElem +>> +endobj +802 0 obj +<< +/K [2834 0 R 2835 0 R 2836 0 R] +/P 193 0 R +/S /TR +/Type /StructElem +>> +endobj +803 0 obj +<< +/K [2837 0 R 2838 0 R 2839 0 R 18] +/P 193 0 R +/Pg 21 0 R +/S /TR +/Type /StructElem +>> +endobj +804 0 obj +<< +/K [2840 0 R 2841 0 R 2842 0 R] +/P 193 0 R +/S /TR +/Type /StructElem +>> +endobj +805 0 obj +<< +/K [2843 0 R 2844 0 R 2845 0 R 19] +/P 193 0 R +/Pg 21 0 R +/S /TR +/Type /StructElem +>> +endobj +806 0 obj +<< +/K [2846 0 R 2847 0 R 2848 0 R] +/P 193 0 R +/S /TR +/Type /StructElem +>> +endobj +807 0 obj +<< +/K [2849 0 R 2850 0 R 2851 0 R 20] +/P 193 0 R +/Pg 21 0 R +/S /TR +/Type /StructElem +>> +endobj +808 0 obj +<< +/K [2852 0 R 2853 0 R 2854 0 R] +/P 193 0 R +/S /TR +/Type /StructElem +>> +endobj +809 0 obj +<< +/K 136 +/P 194 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +810 0 obj +<< +/K [301 0 R 302 0 R 303 0 R] +/P 195 0 R +/S /TR +/Type /StructElem +>> +endobj +811 0 obj +<< +/K [2855 0 R 2856 0 R 2857 0 R] +/P 195 0 R +/S /TR +/Type /StructElem +>> +endobj +812 0 obj +<< +/K [2858 0 R 2859 0 R 2860 0 R 25] +/P 195 0 R +/Pg 21 0 R +/S /TR +/Type /StructElem +>> +endobj +813 0 obj +<< +/K [2861 0 R 2862 0 R 2863 0 R] +/P 195 0 R +/S /TR +/Type /StructElem +>> +endobj +814 0 obj +<< +/K [2864 0 R 2865 0 R 2866 0 R 3] +/P 195 0 R +/Pg 22 0 R +/S /TR +/Type /StructElem +>> +endobj +815 0 obj +<< +/K [2867 0 R 2868 0 R 2869 0 R] +/P 195 0 R +/S /TR +/Type /StructElem +>> +endobj +816 0 obj +<< +/K [2870 0 R 2871 0 R 2872 0 R 4] +/P 195 0 R +/Pg 22 0 R +/S /TR +/Type /StructElem +>> +endobj +817 0 obj +<< +/K 30 +/P 196 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +818 0 obj +<< +/K [304 0 R 305 0 R] +/P 197 0 R +/S /TR +/Type /StructElem +>> +endobj +819 0 obj +<< +/K [2873 0 R 2874 0 R] +/P 197 0 R +/S /TR +/Type /StructElem +>> +endobj +820 0 obj +<< +/K [2875 0 R 2876 0 R 8] +/P 197 0 R +/Pg 22 0 R +/S /TR +/Type /StructElem +>> +endobj +821 0 obj +<< +/K [2877 0 R 2878 0 R] +/P 197 0 R +/S /TR +/Type /StructElem +>> +endobj +822 0 obj +<< +/K [2879 0 R 2880 0 R 9] +/P 197 0 R +/Pg 22 0 R +/S /TR +/Type /StructElem +>> +endobj +823 0 obj +<< +/K 41 +/P 199 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +824 0 obj +<< +/K 42 +/P 200 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +825 0 obj +<< +/K 2250 0 R +/P 201 0 R +/S /Code +/Type /StructElem +>> +endobj +826 0 obj +<< +/K 44 +/P 202 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +827 0 obj +<< +/K 2251 0 R +/P 203 0 R +/S /Code +/Type /StructElem +>> +endobj +828 0 obj +<< +/K 2 +/P 204 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +829 0 obj +<< +/K [2252 0 R 2253 0 R 2254 0 R 2255 0 R 2256 0 R 2257 0 R 2258 0 R 2259 0 R 2260 0 R 2261 0 R 2262 0 R 2263 0 R 2264 0 R 2265 0 R 2266 0 R 2267 0 R +2268 0 R 2269 0 R 2270 0 R 2271 0 R 2272 0 R 2273 0 R 2274 0 R 2275 0 R 2276 0 R 2277 0 R 2278 0 R 2279 0 R 2280 0 R 2281 0 R 2282 0 R 2283 0 R +2284 0 R 2285 0 R 2286 0 R 2287 0 R 2288 0 R 2289 0 R 2290 0 R 2291 0 R 2292 0 R 2293 0 R 2294 0 R 2295 0 R 2296 0 R 2297 0 R 2298 0 R 2299 0 R +2300 0 R 2301 0 R 2302 0 R 2303 0 R 2304 0 R 2305 0 R 2306 0 R 2307 0 R 2308 0 R 2309 0 R 2310 0 R 2311 0 R 2312 0 R 2313 0 R 2314 0 R 2315 0 R +2316 0 R 2317 0 R 2318 0 R 2319 0 R 2320 0 R 2321 0 R 2322 0 R 2323 0 R 2324 0 R 2325 0 R 2326 0 R 2327 0 R 2328 0 R 2329 0 R 2330 0 R 2331 0 R +2332 0 R 2333 0 R 2334 0 R 2335 0 R 2336 0 R 2337 0 R 2338 0 R 2339 0 R 2340 0 R 2341 0 R 2342 0 R 2343 0 R 2344 0 R 2345 0 R 2346 0 R 2347 0 R +2348 0 R 2349 0 R 2350 0 R 2351 0 R 2352 0 R 2353 0 R 2354 0 R 2355 0 R 2356 0 R 2357 0 R 2358 0 R 2359 0 R 2360 0 R 2361 0 R 2362 0 R 2363 0 R +2364 0 R 2365 0 R 2366 0 R 2367 0 R 2368 0 R 2369 0 R 2370 0 R 2371 0 R 2372 0 R 2373 0 R 2374 0 R 2375 0 R 2376 0 R 2377 0 R 2378 0 R 2379 0 R +2380 0 R 2381 0 R 2382 0 R 2383 0 R 2384 0 R 2385 0 R 2386 0 R 2387 0 R 2388 0 R 2389 0 R 2390 0 R 2391 0 R 2392 0 R 2393 0 R 2394 0 R 2395 0 R +2396 0 R 2397 0 R 2398 0 R] +/P 205 0 R +/S /Code +/Type /StructElem +>> +endobj +830 0 obj +<< +/K 150 +/P 206 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +831 0 obj +<< +/K [2399 0 R 2400 0 R 2401 0 R 2402 0 R 2403 0 R 2404 0 R 2405 0 R 2406 0 R 2407 0 R 2408 0 R 2409 0 R 2410 0 R 2411 0 R 2412 0 R 2413 0 R 2414 0 R +2415 0 R 2416 0 R 2417 0 R 2418 0 R 2419 0 R 2420 0 R 2421 0 R 2422 0 R 2423 0 R 2424 0 R 2425 0 R 2426 0 R 2427 0 R 2428 0 R 2429 0 R 2430 0 R +2431 0 R 2432 0 R 2433 0 R 2434 0 R 2435 0 R 2436 0 R 2437 0 R 2438 0 R 2439 0 R 2440 0 R 2441 0 R 2442 0 R 2443 0 R 2444 0 R 2445 0 R 2446 0 R +2447 0 R 2448 0 R 2449 0 R 2450 0 R 2451 0 R 2452 0 R 2453 0 R] +/P 207 0 R +/S /Code +/Type /StructElem +>> +endobj +832 0 obj +<< +/K 24 +/P 2482 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +833 0 obj +<< +/K 25 +/P 307 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +834 0 obj +<< +/K 26 +/P 2483 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +835 0 obj +<< +/K 27 +/P 307 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +836 0 obj +<< +/K 28 +/P 2484 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +837 0 obj +<< +/K 29 +/P 307 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +838 0 obj +<< +/K 30 +/P 2485 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +839 0 obj +<< +/K 31 +/P 307 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +840 0 obj +<< +/K 33 +/P 309 0 R +/Pg 11 0 R +/S /Lbl +/Type /StructElem +>> +endobj +841 0 obj +<< +/K 34 +/P 2486 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +842 0 obj +<< +/K 35 +/P 310 0 R +/Pg 11 0 R +/S /Lbl +/Type /StructElem +>> +endobj +843 0 obj +<< +/K 36 +/P 2487 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +844 0 obj +<< +/K 37 +/P 311 0 R +/Pg 11 0 R +/S /Lbl +/Type /StructElem +>> +endobj +845 0 obj +<< +/K 38 +/P 2488 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +846 0 obj +<< +/K 39 +/P 312 0 R +/Pg 11 0 R +/S /Lbl +/Type /StructElem +>> +endobj +847 0 obj +<< +/K 40 +/P 2489 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +848 0 obj +<< +/K 41 +/P 313 0 R +/Pg 11 0 R +/S /Lbl +/Type /StructElem +>> +endobj +849 0 obj +<< +/K 42 +/P 2490 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +850 0 obj +<< +/K 43 +/P 314 0 R +/Pg 11 0 R +/S /Lbl +/Type /StructElem +>> +endobj +851 0 obj +<< +/K 44 +/P 2491 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +852 0 obj +<< +/K 45 +/P 315 0 R +/Pg 11 0 R +/S /Lbl +/Type /StructElem +>> +endobj +853 0 obj +<< +/K 46 +/P 2492 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +854 0 obj +<< +/K 47 +/P 316 0 R +/Pg 11 0 R +/S /Lbl +/Type /StructElem +>> +endobj +855 0 obj +<< +/K 48 +/P 2493 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +856 0 obj +<< +/K 52 +/P 320 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +857 0 obj +<< +/K 54 +/P 322 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +858 0 obj +<< +/K 56 +/P 324 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +859 0 obj +<< +/K 58 +/P 326 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +860 0 obj +<< +/K 60 +/P 328 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +861 0 obj +<< +/K 62 +/P 330 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +862 0 obj +<< +/K 64 +/P 332 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +863 0 obj +<< +/K 66 +/P 334 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +864 0 obj +<< +/K 68 +/P 336 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +865 0 obj +<< +/K 70 +/P 338 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +866 0 obj +<< +/K 72 +/P 340 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +867 0 obj +<< +/K 75 +/P 245 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +868 0 obj +<< +/K 76 +/P 246 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +869 0 obj +<< +/K 77 +/P 247 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +870 0 obj +<< +/K 78 +/P 248 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +871 0 obj +<< +/K 79 +/P 249 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +872 0 obj +<< +/K [873 0 R 80] +/P 2494 0 R +/Pg 11 0 R +/S /Code +/Type /StructElem +>> +endobj +873 0 obj +<< +/K 81 +/P 872 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +874 0 obj +<< +/K 82 +/P 2495 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +875 0 obj +<< +/K 83 +/P 2496 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +876 0 obj +<< +/K 84 +/P 2881 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +877 0 obj +<< +/K 85 +/P 2498 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +878 0 obj +<< +/K [879 0 R 86] +/P 2499 0 R +/Pg 11 0 R +/S /Code +/Type /StructElem +>> +endobj +879 0 obj +<< +/K 87 +/P 878 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +880 0 obj +<< +/K 88 +/P 2500 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +881 0 obj +<< +/K 89 +/P 2501 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +882 0 obj +<< +/K 90 +/P 2882 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +883 0 obj +<< +/K 91 +/P 2503 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +884 0 obj +<< +/K [885 0 R 92] +/P 2504 0 R +/Pg 11 0 R +/S /Code +/Type /StructElem +>> +endobj +885 0 obj +<< +/K 93 +/P 884 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +886 0 obj +<< +/K 94 +/P 2505 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +887 0 obj +<< +/K 95 +/P 2506 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +888 0 obj +<< +/K 96 +/P 2883 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +889 0 obj +<< +/K 97 +/P 2508 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +890 0 obj +<< +/K [891 0 R 98] +/P 2509 0 R +/Pg 11 0 R +/S /Code +/Type /StructElem +>> +endobj +891 0 obj +<< +/K 99 +/P 890 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +892 0 obj +<< +/K 100 +/P 2510 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +893 0 obj +<< +/K 101 +/P 2511 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +894 0 obj +<< +/K 102 +/P 2884 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +895 0 obj +<< +/K 103 +/P 2513 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +896 0 obj +<< +/K [897 0 R 104] +/P 2514 0 R +/Pg 11 0 R +/S /Code +/Type /StructElem +>> +endobj +897 0 obj +<< +/K 105 +/P 896 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +898 0 obj +<< +/K 106 +/P 2515 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +899 0 obj +<< +/K 107 +/P 2516 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +900 0 obj +<< +/K 108 +/P 2885 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +901 0 obj +<< +/K 109 +/P 2518 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +902 0 obj +<< +/K [903 0 R 110] +/P 2519 0 R +/Pg 11 0 R +/S /Code +/Type /StructElem +>> +endobj +903 0 obj +<< +/K 111 +/P 902 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +904 0 obj +<< +/K 112 +/P 2520 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +905 0 obj +<< +/K 113 +/P 2521 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +906 0 obj +<< +/K 114 +/P 2886 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +907 0 obj +<< +/K 115 +/P 2523 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +908 0 obj +<< +/K [117 << +/MCID 19 +/Pg 12 0 R +/Type /MCR +>>] +/P 250 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +909 0 obj +<< +/K [118 << +/MCID 20 +/Pg 12 0 R +/Type /MCR +>>] +/P 251 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +910 0 obj +<< +/K [119 << +/MCID 21 +/Pg 12 0 R +/Type /MCR +>>] +/P 252 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +911 0 obj +<< +/K [120 << +/MCID 22 +/Pg 12 0 R +/Type /MCR +>>] +/P 253 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +912 0 obj +<< +/K [913 0 R 121] +/P 2524 0 R +/Pg 11 0 R +/S /Code +/Type /StructElem +>> +endobj +913 0 obj +<< +/K 122 +/P 912 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +914 0 obj +<< +/K 123 +/P 2525 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +915 0 obj +<< +/K 124 +/P 2887 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +916 0 obj +<< +/K 125 +/P 2527 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +917 0 obj +<< +/K [918 0 R 126] +/P 2528 0 R +/Pg 11 0 R +/S /Code +/Type /StructElem +>> +endobj +918 0 obj +<< +/K 127 +/P 917 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +919 0 obj +<< +/K 128 +/P 2529 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +920 0 obj +<< +/K 129 +/P 2888 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +921 0 obj +<< +/K 130 +/P 2531 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +922 0 obj +<< +/K [923 0 R 131] +/P 2532 0 R +/Pg 11 0 R +/S /Code +/Type /StructElem +>> +endobj +923 0 obj +<< +/K 132 +/P 922 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +924 0 obj +<< +/K 133 +/P 2533 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +925 0 obj +<< +/K 134 +/P 2889 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +926 0 obj +<< +/K 135 +/P 2535 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +927 0 obj +<< +/K [928 0 R 136] +/P 2536 0 R +/Pg 11 0 R +/S /Code +/Type /StructElem +>> +endobj +928 0 obj +<< +/K 137 +/P 927 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +929 0 obj +<< +/K 138 +/P 2537 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +930 0 obj +<< +/K 139 +/P 2890 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +931 0 obj +<< +/K 140 +/P 2539 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +932 0 obj +<< +/K [933 0 R 141] +/P 2540 0 R +/Pg 11 0 R +/S /Code +/Type /StructElem +>> +endobj +933 0 obj +<< +/K 142 +/P 932 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +934 0 obj +<< +/K 143 +/P 2541 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +935 0 obj +<< +/K 144 +/P 2891 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +936 0 obj +<< +/K 145 +/P 2543 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +937 0 obj +<< +/K [938 0 R 146] +/P 2544 0 R +/Pg 11 0 R +/S /Code +/Type /StructElem +>> +endobj +938 0 obj +<< +/K 147 +/P 937 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +939 0 obj +<< +/K 148 +/P 2545 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +940 0 obj +<< +/K 149 +/P 2892 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +941 0 obj +<< +/K 150 +/P 2547 0 R +/Pg 11 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +942 0 obj +<< +/K [943 0 R 23] +/P 2548 0 R +/Pg 12 0 R +/S /Code +/Type /StructElem +>> +endobj +943 0 obj +<< +/K 24 +/P 942 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +944 0 obj +<< +/K 25 +/P 2549 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +945 0 obj +<< +/K 26 +/P 2893 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +946 0 obj +<< +/K 27 +/P 2551 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +947 0 obj +<< +/K [948 0 R 28] +/P 2552 0 R +/Pg 12 0 R +/S /Code +/Type /StructElem +>> +endobj +948 0 obj +<< +/K 29 +/P 947 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +949 0 obj +<< +/K 30 +/P 2553 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +950 0 obj +<< +/K 31 +/P 2894 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +951 0 obj +<< +/K 32 +/P 2555 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +952 0 obj +<< +/K [953 0 R 33] +/P 2556 0 R +/Pg 12 0 R +/S /Code +/Type /StructElem +>> +endobj +953 0 obj +<< +/K 34 +/P 952 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +954 0 obj +<< +/K 35 +/P 2557 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +955 0 obj +<< +/K 36 +/P 2895 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +956 0 obj +<< +/K 37 +/P 2559 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +957 0 obj +<< +/K [958 0 R 38] +/P 2560 0 R +/Pg 12 0 R +/S /Code +/Type /StructElem +>> +endobj +958 0 obj +<< +/K 39 +/P 957 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +959 0 obj +<< +/K 40 +/P 2561 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +960 0 obj +<< +/K 41 +/P 2896 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +961 0 obj +<< +/K 42 +/P 2563 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +962 0 obj +<< +/K 45 +/P 363 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +963 0 obj +<< +/K 47 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +964 0 obj +<< +/K 48 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +965 0 obj +<< +/K 49 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +966 0 obj +<< +/K 50 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +967 0 obj +<< +/K 51 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +968 0 obj +<< +/K 52 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +969 0 obj +<< +/K 53 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +970 0 obj +<< +/K 54 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +971 0 obj +<< +/K 55 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +972 0 obj +<< +/K 56 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +973 0 obj +<< +/K 57 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +974 0 obj +<< +/K 58 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +975 0 obj +<< +/K 59 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +976 0 obj +<< +/K 60 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +977 0 obj +<< +/K 61 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +978 0 obj +<< +/K 62 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +979 0 obj +<< +/K 63 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +980 0 obj +<< +/K 64 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +981 0 obj +<< +/K 65 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +982 0 obj +<< +/K 66 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +983 0 obj +<< +/K 67 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +984 0 obj +<< +/K 68 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +985 0 obj +<< +/K 69 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +986 0 obj +<< +/K 70 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +987 0 obj +<< +/K 71 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +988 0 obj +<< +/K 72 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +989 0 obj +<< +/K 73 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +990 0 obj +<< +/K 74 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +991 0 obj +<< +/K 75 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +992 0 obj +<< +/K 76 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +993 0 obj +<< +/K 77 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +994 0 obj +<< +/K 78 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +995 0 obj +<< +/K 79 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +996 0 obj +<< +/K 80 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +997 0 obj +<< +/K 81 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +998 0 obj +<< +/K 82 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +999 0 obj +<< +/K 83 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1000 0 obj +<< +/K 84 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1001 0 obj +<< +/K 85 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1002 0 obj +<< +/K 86 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1003 0 obj +<< +/K 87 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1004 0 obj +<< +/K 88 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1005 0 obj +<< +/K 89 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1006 0 obj +<< +/K 90 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1007 0 obj +<< +/K 91 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1008 0 obj +<< +/K 92 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1009 0 obj +<< +/K 93 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1010 0 obj +<< +/K 94 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1011 0 obj +<< +/K 95 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1012 0 obj +<< +/K 96 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1013 0 obj +<< +/K 97 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1014 0 obj +<< +/K 98 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1015 0 obj +<< +/K 99 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1016 0 obj +<< +/K 100 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1017 0 obj +<< +/K 101 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1018 0 obj +<< +/K 102 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1019 0 obj +<< +/K 103 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1020 0 obj +<< +/K 104 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1021 0 obj +<< +/K 105 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1022 0 obj +<< +/K 106 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1023 0 obj +<< +/K 107 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1024 0 obj +<< +/K 108 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1025 0 obj +<< +/K 109 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1026 0 obj +<< +/K 110 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1027 0 obj +<< +/K 111 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1028 0 obj +<< +/K 112 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1029 0 obj +<< +/K 113 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1030 0 obj +<< +/K 114 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1031 0 obj +<< +/K 115 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1032 0 obj +<< +/K 116 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1033 0 obj +<< +/K 117 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1034 0 obj +<< +/K 118 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1035 0 obj +<< +/K 119 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1036 0 obj +<< +/K 120 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1037 0 obj +<< +/K 121 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1038 0 obj +<< +/K 122 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1039 0 obj +<< +/K 123 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1040 0 obj +<< +/K 124 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1041 0 obj +<< +/K 125 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1042 0 obj +<< +/K 126 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1043 0 obj +<< +/K 127 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1044 0 obj +<< +/K 128 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1045 0 obj +<< +/K 129 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1046 0 obj +<< +/K 130 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1047 0 obj +<< +/K 131 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1048 0 obj +<< +/K 132 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1049 0 obj +<< +/K 133 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1050 0 obj +<< +/K 134 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1051 0 obj +<< +/K 135 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1052 0 obj +<< +/K 136 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1053 0 obj +<< +/K 137 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1054 0 obj +<< +/K 138 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1055 0 obj +<< +/K 139 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1056 0 obj +<< +/K 140 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1057 0 obj +<< +/K 141 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1058 0 obj +<< +/K 142 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1059 0 obj +<< +/K 143 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1060 0 obj +<< +/K 144 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1061 0 obj +<< +/K 145 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1062 0 obj +<< +/K 146 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1063 0 obj +<< +/K 147 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1064 0 obj +<< +/K 148 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1065 0 obj +<< +/K 149 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1066 0 obj +<< +/K 150 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1067 0 obj +<< +/K 151 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1068 0 obj +<< +/K 152 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1069 0 obj +<< +/K 153 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1070 0 obj +<< +/K 154 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1071 0 obj +<< +/K 155 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1072 0 obj +<< +/K 156 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1073 0 obj +<< +/K 157 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1074 0 obj +<< +/K 158 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1075 0 obj +<< +/K 159 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1076 0 obj +<< +/K 160 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1077 0 obj +<< +/K 161 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1078 0 obj +<< +/K 162 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1079 0 obj +<< +/K 163 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1080 0 obj +<< +/K 164 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1081 0 obj +<< +/K 165 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1082 0 obj +<< +/K 166 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1083 0 obj +<< +/K 167 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1084 0 obj +<< +/K 168 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1085 0 obj +<< +/K 169 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1086 0 obj +<< +/K 170 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1087 0 obj +<< +/K 171 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1088 0 obj +<< +/K 172 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1089 0 obj +<< +/K 173 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1090 0 obj +<< +/K 174 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1091 0 obj +<< +/K 175 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1092 0 obj +<< +/K 176 +/P 365 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1093 0 obj +<< +/K 178 +/P 366 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1094 0 obj +<< +/K 180 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1095 0 obj +<< +/K 181 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1096 0 obj +<< +/K 182 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1097 0 obj +<< +/K 183 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1098 0 obj +<< +/K 184 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1099 0 obj +<< +/K 185 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1100 0 obj +<< +/K 186 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1101 0 obj +<< +/K 187 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1102 0 obj +<< +/K 188 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1103 0 obj +<< +/K 189 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1104 0 obj +<< +/K 190 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1105 0 obj +<< +/K 191 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1106 0 obj +<< +/K 192 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1107 0 obj +<< +/K 193 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1108 0 obj +<< +/K 194 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1109 0 obj +<< +/K 195 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1110 0 obj +<< +/K 196 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1111 0 obj +<< +/K 197 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1112 0 obj +<< +/K 198 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1113 0 obj +<< +/K 199 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1114 0 obj +<< +/K 200 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1115 0 obj +<< +/K 201 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1116 0 obj +<< +/K 202 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1117 0 obj +<< +/K 203 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1118 0 obj +<< +/K 204 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1119 0 obj +<< +/K 205 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1120 0 obj +<< +/K 206 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1121 0 obj +<< +/K 207 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1122 0 obj +<< +/K 208 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1123 0 obj +<< +/K 209 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1124 0 obj +<< +/K 210 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1125 0 obj +<< +/K 211 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1126 0 obj +<< +/K 212 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1127 0 obj +<< +/K 213 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1128 0 obj +<< +/K 214 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1129 0 obj +<< +/K 215 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1130 0 obj +<< +/K 216 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1131 0 obj +<< +/K 217 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1132 0 obj +<< +/K 218 +/P 368 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1133 0 obj +<< +/K 220 +/P 369 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1134 0 obj +<< +/K 222 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1135 0 obj +<< +/K 223 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1136 0 obj +<< +/K 224 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1137 0 obj +<< +/K 225 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1138 0 obj +<< +/K 226 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1139 0 obj +<< +/K 227 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1140 0 obj +<< +/K 228 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1141 0 obj +<< +/K 229 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1142 0 obj +<< +/K 230 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1143 0 obj +<< +/K 231 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1144 0 obj +<< +/K 232 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1145 0 obj +<< +/K 233 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1146 0 obj +<< +/K 234 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1147 0 obj +<< +/K 235 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1148 0 obj +<< +/K 236 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1149 0 obj +<< +/K 237 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1150 0 obj +<< +/K 238 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1151 0 obj +<< +/K 239 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1152 0 obj +<< +/K 240 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1153 0 obj +<< +/K 241 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1154 0 obj +<< +/K 242 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1155 0 obj +<< +/K 243 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1156 0 obj +<< +/K 244 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1157 0 obj +<< +/K 245 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1158 0 obj +<< +/K 246 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1159 0 obj +<< +/K 247 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1160 0 obj +<< +/K 248 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1161 0 obj +<< +/K 249 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1162 0 obj +<< +/K 250 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1163 0 obj +<< +/K 251 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1164 0 obj +<< +/K 252 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1165 0 obj +<< +/K 253 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1166 0 obj +<< +/K 254 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1167 0 obj +<< +/K 255 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1168 0 obj +<< +/K 256 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1169 0 obj +<< +/K 257 +/P 371 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1170 0 obj +<< +/K 259 +/P 372 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1171 0 obj +<< +/K 261 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1172 0 obj +<< +/K 262 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1173 0 obj +<< +/K 263 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1174 0 obj +<< +/K 264 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1175 0 obj +<< +/K 265 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1176 0 obj +<< +/K 266 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1177 0 obj +<< +/K 267 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1178 0 obj +<< +/K 268 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1179 0 obj +<< +/K 269 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1180 0 obj +<< +/K 270 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1181 0 obj +<< +/K 271 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1182 0 obj +<< +/K 272 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1183 0 obj +<< +/K 273 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1184 0 obj +<< +/K 274 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1185 0 obj +<< +/K 275 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1186 0 obj +<< +/K 276 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1187 0 obj +<< +/K 277 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1188 0 obj +<< +/K 278 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1189 0 obj +<< +/K 279 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1190 0 obj +<< +/K 280 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1191 0 obj +<< +/K 281 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1192 0 obj +<< +/K 282 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1193 0 obj +<< +/K 283 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1194 0 obj +<< +/K 284 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1195 0 obj +<< +/K 285 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1196 0 obj +<< +/K 286 +/P 374 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1197 0 obj +<< +/K 289 +/P 377 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1198 0 obj +<< +/K 291 +/P 379 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1199 0 obj +<< +/K [294 << +/MCID 22 +/Pg 13 0 R +/Type /MCR +>>] +/P 254 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1200 0 obj +<< +/K [295 << +/MCID 23 +/Pg 13 0 R +/Type /MCR +>>] +/P 255 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1201 0 obj +<< +/K [296 << +/MCID 24 +/Pg 13 0 R +/Type /MCR +>>] +/P 256 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1202 0 obj +<< +/K [297 << +/MCID 25 +/Pg 13 0 R +/Type /MCR +>>] +/P 257 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1203 0 obj +<< +/K [1204 0 R 298] +/P 2564 0 R +/Pg 12 0 R +/S /Code +/Type /StructElem +>> +endobj +1204 0 obj +<< +/K 299 +/P 1203 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1205 0 obj +<< +/K 300 +/P 2564 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1206 0 obj +<< +/K 301 +/P 2565 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1207 0 obj +<< +/K 302 +/P 2897 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1208 0 obj +<< +/K 303 +/P 2566 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1209 0 obj +<< +/K 304 +/P 2898 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1210 0 obj +<< +/K [1211 0 R 305] +/P 2568 0 R +/Pg 12 0 R +/S /Code +/Type /StructElem +>> +endobj +1211 0 obj +<< +/K 306 +/P 1210 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1212 0 obj +<< +/K 307 +/P 2568 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1213 0 obj +<< +/K [1214 0 R 308] +/P 2568 0 R +/Pg 12 0 R +/S /Code +/Type /StructElem +>> +endobj +1214 0 obj +<< +/K 309 +/P 1213 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1215 0 obj +<< +/K 310 +/P 2569 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1216 0 obj +<< +/K 311 +/P 2570 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1217 0 obj +<< +/K 312 +/P 2899 0 R +/Pg 12 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1218 0 obj +<< +/K [1219 0 R 26] +/P 2572 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1219 0 obj +<< +/K 27 +/P 1218 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1220 0 obj +<< +/K 28 +/P 2573 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1221 0 obj +<< +/K 29 +/P 2574 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1222 0 obj +<< +/K 30 +/P 2900 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1223 0 obj +<< +/K [1224 0 R 31] +/P 2576 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1224 0 obj +<< +/K 32 +/P 1223 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1225 0 obj +<< +/K 33 +/P 2577 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1226 0 obj +<< +/K 34 +/P 2578 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1227 0 obj +<< +/K 35 +/P 2901 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1228 0 obj +<< +/K [1229 0 R 36] +/P 2580 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1229 0 obj +<< +/K 37 +/P 1228 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1230 0 obj +<< +/K 38 +/P 2581 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1231 0 obj +<< +/K 39 +/P 2582 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1232 0 obj +<< +/K 40 +/P 2902 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1233 0 obj +<< +/K [1234 0 R 41] +/P 2584 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1234 0 obj +<< +/K 42 +/P 1233 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1235 0 obj +<< +/K 43 +/P 2584 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1236 0 obj +<< +/K [1237 0 R 44] +/P 2584 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1237 0 obj +<< +/K 45 +/P 1236 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1238 0 obj +<< +/K 46 +/P 2585 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1239 0 obj +<< +/K 47 +/P 2586 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1240 0 obj +<< +/K 48 +/P 2903 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1241 0 obj +<< +/K [1242 0 R 49] +/P 2588 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1242 0 obj +<< +/K 50 +/P 1241 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1243 0 obj +<< +/K 51 +/P 2588 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1244 0 obj +<< +/K [1245 0 R 52] +/P 2588 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1245 0 obj +<< +/K 53 +/P 1244 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1246 0 obj +<< +/K 54 +/P 2589 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1247 0 obj +<< +/K 55 +/P 2590 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1248 0 obj +<< +/K 56 +/P 2904 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1249 0 obj +<< +/K [1250 0 R 57] +/P 2592 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1250 0 obj +<< +/K 58 +/P 1249 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1251 0 obj +<< +/K 59 +/P 2592 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1252 0 obj +<< +/K [1253 0 R 60] +/P 2592 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1253 0 obj +<< +/K 61 +/P 1252 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1254 0 obj +<< +/K 62 +/P 2593 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1255 0 obj +<< +/K 63 +/P 2594 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1256 0 obj +<< +/K 64 +/P 2905 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1257 0 obj +<< +/K 66 +/P 392 0 R +/Pg 13 0 R +/S /Lbl +/Type /StructElem +>> +endobj +1258 0 obj +<< +/K 67 +/P 2596 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1259 0 obj +<< +/K 68 +/P 392 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1260 0 obj +<< +/K 69 +/P 393 0 R +/Pg 13 0 R +/S /Lbl +/Type /StructElem +>> +endobj +1261 0 obj +<< +/K 70 +/P 2597 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1262 0 obj +<< +/K 71 +/P 393 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1263 0 obj +<< +/K [1264 0 R 72] +/P 393 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1264 0 obj +<< +/K 73 +/P 1263 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1265 0 obj +<< +/K 74 +/P 393 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1266 0 obj +<< +/K [1267 0 R 75] +/P 393 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1267 0 obj +<< +/K 76 +/P 1266 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1268 0 obj +<< +/K 77 +/P 393 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1269 0 obj +<< +/K [1270 0 R 78] +/P 393 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1270 0 obj +<< +/K 79 +/P 1269 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1271 0 obj +<< +/K 80 +/P 393 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1272 0 obj +<< +/K [1273 0 R 81] +/P 393 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1273 0 obj +<< +/K 82 +/P 1272 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1274 0 obj +<< +/K 83 +/P 393 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1275 0 obj +<< +/K [1276 0 R 84] +/P 393 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1276 0 obj +<< +/K 85 +/P 1275 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1277 0 obj +<< +/K 86 +/P 393 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1278 0 obj +<< +/K 87 +/P 394 0 R +/Pg 13 0 R +/S /Lbl +/Type /StructElem +>> +endobj +1279 0 obj +<< +/K 88 +/P 2598 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1280 0 obj +<< +/K 89 +/P 394 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1281 0 obj +<< +/K [1282 0 R 90] +/P 394 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1282 0 obj +<< +/K 91 +/P 1281 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1283 0 obj +<< +/K 92 +/P 394 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1284 0 obj +<< +/K [1285 0 R 93] +/P 394 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1285 0 obj +<< +/K 94 +/P 1284 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1286 0 obj +<< +/K 95 +/P 395 0 R +/Pg 13 0 R +/S /Lbl +/Type /StructElem +>> +endobj +1287 0 obj +<< +/K 96 +/P 2599 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1288 0 obj +<< +/K 97 +/P 395 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1289 0 obj +<< +/K 98 +/P 396 0 R +/Pg 13 0 R +/S /Lbl +/Type /StructElem +>> +endobj +1290 0 obj +<< +/K 99 +/P 2600 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1291 0 obj +<< +/K 100 +/P 396 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1292 0 obj +<< +/K 101 +/P 397 0 R +/Pg 13 0 R +/S /Lbl +/Type /StructElem +>> +endobj +1293 0 obj +<< +/K 102 +/P 2601 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1294 0 obj +<< +/K 103 +/P 397 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1295 0 obj +<< +/K [1296 0 R 104] +/P 397 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1296 0 obj +<< +/K 105 +/P 1295 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1297 0 obj +<< +/K 106 +/P 397 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1298 0 obj +<< +/K 109 +/P 258 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1299 0 obj +<< +/K 110 +/P 259 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1300 0 obj +<< +/K 111 +/P 260 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1301 0 obj +<< +/K [1302 0 R 112] +/P 2602 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1302 0 obj +<< +/K 113 +/P 1301 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1303 0 obj +<< +/K 114 +/P 2603 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1304 0 obj +<< +/K 115 +/P 2906 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1305 0 obj +<< +/K 116 +/P 2604 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1306 0 obj +<< +/K [1307 0 R 117] +/P 2605 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1307 0 obj +<< +/K 118 +/P 1306 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1308 0 obj +<< +/K 119 +/P 2606 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1309 0 obj +<< +/K [1310 0 R 120] +/P 2607 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1310 0 obj +<< +/K 121 +/P 1309 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1311 0 obj +<< +/K [1312 0 R 122] +/P 2608 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1312 0 obj +<< +/K 123 +/P 1311 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1313 0 obj +<< +/K 124 +/P 2609 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1314 0 obj +<< +/K [1315 0 R 125] +/P 2610 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1315 0 obj +<< +/K 126 +/P 1314 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1316 0 obj +<< +/K [1317 0 R 127] +/P 2611 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1317 0 obj +<< +/K 128 +/P 1316 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1318 0 obj +<< +/K 129 +/P 2612 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1319 0 obj +<< +/K [1320 0 R 130 132] +/P 2613 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1320 0 obj +<< +/K [131 133] +/P 1319 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1321 0 obj +<< +/K [1322 0 R 134] +/P 2614 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1322 0 obj +<< +/K 135 +/P 1321 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1323 0 obj +<< +/K 136 +/P 2615 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1324 0 obj +<< +/K [1325 0 R 137] +/P 2616 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1325 0 obj +<< +/K 138 +/P 1324 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1326 0 obj +<< +/K [1327 0 R 139] +/P 2617 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1327 0 obj +<< +/K 140 +/P 1326 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1328 0 obj +<< +/K 141 +/P 2618 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1329 0 obj +<< +/K [1330 0 R 142 144] +/P 2619 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1330 0 obj +<< +/K [143 145] +/P 1329 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1331 0 obj +<< +/K [1332 0 R 146] +/P 2620 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1332 0 obj +<< +/K 147 +/P 1331 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1333 0 obj +<< +/K 148 +/P 2621 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1334 0 obj +<< +/K [1335 0 R 149] +/P 2622 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1335 0 obj +<< +/K 150 +/P 1334 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1336 0 obj +<< +/K [1337 0 R 151] +/P 2623 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1337 0 obj +<< +/K 152 +/P 1336 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1338 0 obj +<< +/K 153 +/P 2624 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1339 0 obj +<< +/K 154 +/P 2625 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1340 0 obj +<< +/K [1341 0 R 155] +/P 2626 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1341 0 obj +<< +/K 156 +/P 1340 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1342 0 obj +<< +/K 157 +/P 2627 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1343 0 obj +<< +/K 158 +/P 2628 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1344 0 obj +<< +/K [1345 0 R 159] +/P 2629 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1345 0 obj +<< +/K 160 +/P 1344 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1346 0 obj +<< +/K 161 +/P 2630 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1347 0 obj +<< +/K 162 +/P 2631 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1348 0 obj +<< +/K [1349 0 R 163 165] +/P 2632 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1349 0 obj +<< +/K [164 166] +/P 1348 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1350 0 obj +<< +/K 167 +/P 2633 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1351 0 obj +<< +/K 168 +/P 2634 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1352 0 obj +<< +/K 169 +/P 2635 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1353 0 obj +<< +/K 170 +/P 412 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1354 0 obj +<< +/K [1355 0 R 171] +/P 412 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1355 0 obj +<< +/K 172 +/P 1354 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1356 0 obj +<< +/K 173 +/P 412 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1357 0 obj +<< +/K [1358 0 R 174] +/P 412 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1358 0 obj +<< +/K 175 +/P 1357 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1359 0 obj +<< +/K 176 +/P 412 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1360 0 obj +<< +/K [1361 0 R 177] +/P 412 0 R +/Pg 13 0 R +/S /Code +/Type /StructElem +>> +endobj +1361 0 obj +<< +/K 178 +/P 1360 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1362 0 obj +<< +/K 179 +/P 412 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1363 0 obj +<< +/K [181 << +/MCID 29 +/Pg 14 0 R +/Type /MCR +>>] +/P 261 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1364 0 obj +<< +/K [182 << +/MCID 30 +/Pg 14 0 R +/Type /MCR +>>] +/P 262 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1365 0 obj +<< +/K [183 << +/MCID 31 +/Pg 14 0 R +/Type /MCR +>>] +/P 263 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1366 0 obj +<< +/K 184 +/P 2636 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1367 0 obj +<< +/K 185 +/P 2637 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1368 0 obj +<< +/K 186 +/P 2907 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1369 0 obj +<< +/K 187 +/P 2638 0 R +/Pg 13 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1370 0 obj +<< +/K 32 +/P 2639 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1371 0 obj +<< +/K 33 +/P 2640 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1372 0 obj +<< +/K 34 +/P 2908 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1373 0 obj +<< +/K 35 +/P 2641 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1374 0 obj +<< +/K 38 +/P 419 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1375 0 obj +<< +/K 40 +/P 264 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1376 0 obj +<< +/K 41 +/P 265 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1377 0 obj +<< +/K 42 +/P 266 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1378 0 obj +<< +/K [1379 0 R 43] +/P 2642 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1379 0 obj +<< +/K 44 +/P 1378 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1380 0 obj +<< +/K 45 +/P 2642 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1381 0 obj +<< +/K 46 +/P 2643 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1382 0 obj +<< +/K 47 +/P 2909 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1383 0 obj +<< +/K [1384 0 R 48] +/P 2645 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1384 0 obj +<< +/K 49 +/P 1383 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1385 0 obj +<< +/K 50 +/P 2645 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1386 0 obj +<< +/K 51 +/P 2646 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1387 0 obj +<< +/K 52 +/P 2910 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1388 0 obj +<< +/K [1389 0 R 53] +/P 2648 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1389 0 obj +<< +/K 54 +/P 1388 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1390 0 obj +<< +/K 55 +/P 2649 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1391 0 obj +<< +/K 56 +/P 2911 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1392 0 obj +<< +/K [1393 0 R 57] +/P 2651 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1393 0 obj +<< +/K 58 +/P 1392 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1394 0 obj +<< +/K 59 +/P 2652 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1395 0 obj +<< +/K 60 +/P 2912 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1396 0 obj +<< +/K [1397 0 R 61] +/P 2654 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1397 0 obj +<< +/K 62 +/P 1396 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1398 0 obj +<< +/K 63 +/P 2655 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1399 0 obj +<< +/K 64 +/P 2913 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1400 0 obj +<< +/K [1401 0 R 65] +/P 2657 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1401 0 obj +<< +/K 66 +/P 1400 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1402 0 obj +<< +/K 67 +/P 2658 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1403 0 obj +<< +/K 68 +/P 2914 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1404 0 obj +<< +/K 71 +/P 430 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1405 0 obj +<< +/K 73 +/P 267 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1406 0 obj +<< +/K 74 +/P 268 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1407 0 obj +<< +/K 75 +/P 269 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1408 0 obj +<< +/K 76 +/P 270 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1409 0 obj +<< +/K 77 +/P 2660 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1410 0 obj +<< +/K [1411 0 R 78] +/P 2661 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1411 0 obj +<< +/K 79 +/P 1410 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1412 0 obj +<< +/K 80 +/P 2661 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1413 0 obj +<< +/K [1414 0 R 81] +/P 2662 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1414 0 obj +<< +/K 82 +/P 1413 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1415 0 obj +<< +/K 83 +/P 2663 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1416 0 obj +<< +/K 84 +/P 2664 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1417 0 obj +<< +/K [1418 0 R 85] +/P 2665 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1418 0 obj +<< +/K 86 +/P 1417 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1419 0 obj +<< +/K 87 +/P 2665 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1420 0 obj +<< +/K [1421 0 R 88] +/P 2666 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1421 0 obj +<< +/K 89 +/P 1420 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1422 0 obj +<< +/K 90 +/P 2667 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1423 0 obj +<< +/K 91 +/P 2668 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1424 0 obj +<< +/K [1425 0 R 92] +/P 2669 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1425 0 obj +<< +/K 93 +/P 1424 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1426 0 obj +<< +/K 94 +/P 2669 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1427 0 obj +<< +/K [1428 0 R 95] +/P 2670 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1428 0 obj +<< +/K 96 +/P 1427 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1429 0 obj +<< +/K 97 +/P 2671 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1430 0 obj +<< +/K 98 +/P 436 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1431 0 obj +<< +/K 100 +/P 438 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1432 0 obj +<< +/K 103 +/P 440 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1433 0 obj +<< +/K 106 +/P 442 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1434 0 obj +<< +/K 109 +/P 444 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1435 0 obj +<< +/K 111 +/P 446 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1436 0 obj +<< +/K 114 +/P 448 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1437 0 obj +<< +/K 117 +/P 450 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1438 0 obj +<< +/K 120 +/P 452 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1439 0 obj +<< +/K 123 +/P 454 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1440 0 obj +<< +/K 126 +/P 456 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1441 0 obj +<< +/K [129 131] +/P 458 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1442 0 obj +<< +/K [134 << +/MCID 23 +/Pg 15 0 R +/Type /MCR +>>] +/P 271 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1443 0 obj +<< +/K [135 << +/MCID 24 +/Pg 15 0 R +/Type /MCR +>>] +/P 272 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1444 0 obj +<< +/K [136 << +/MCID 25 +/Pg 15 0 R +/Type /MCR +>>] +/P 273 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1445 0 obj +<< +/K [137 << +/MCID 26 +/Pg 15 0 R +/Type /MCR +>>] +/P 274 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1446 0 obj +<< +/K [1447 0 R 138] +/P 2672 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1447 0 obj +<< +/K 139 +/P 1446 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1448 0 obj +<< +/K 140 +/P 2673 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1449 0 obj +<< +/K 141 +/P 2915 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1450 0 obj +<< +/K 142 +/P 2675 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1451 0 obj +<< +/K [1452 0 R 143] +/P 2676 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1452 0 obj +<< +/K 144 +/P 1451 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1453 0 obj +<< +/K 145 +/P 2677 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1454 0 obj +<< +/K 146 +/P 2916 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1455 0 obj +<< +/K 147 +/P 2679 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1456 0 obj +<< +/K [1457 0 R 148] +/P 2680 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1457 0 obj +<< +/K 149 +/P 1456 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1458 0 obj +<< +/K 150 +/P 2681 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1459 0 obj +<< +/K 151 +/P 2917 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1460 0 obj +<< +/K 152 +/P 2683 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1461 0 obj +<< +/K [1462 0 R 153] +/P 2684 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1462 0 obj +<< +/K 154 +/P 1461 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1463 0 obj +<< +/K 155 +/P 2685 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1464 0 obj +<< +/K 156 +/P 2918 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1465 0 obj +<< +/K 157 +/P 2687 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1466 0 obj +<< +/K [1467 0 R 158] +/P 2688 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1467 0 obj +<< +/K 159 +/P 1466 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1468 0 obj +<< +/K 160 +/P 2689 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1469 0 obj +<< +/K 161 +/P 2919 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1470 0 obj +<< +/K 162 +/P 2691 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1471 0 obj +<< +/K [1472 0 R 163] +/P 2692 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1472 0 obj +<< +/K 164 +/P 1471 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1473 0 obj +<< +/K 165 +/P 2693 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1474 0 obj +<< +/K 166 +/P 2920 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1475 0 obj +<< +/K 167 +/P 2695 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1476 0 obj +<< +/K [1477 0 R 168] +/P 2696 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1477 0 obj +<< +/K 169 +/P 1476 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1478 0 obj +<< +/K 170 +/P 2697 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1479 0 obj +<< +/K 171 +/P 2921 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1480 0 obj +<< +/K 172 +/P 2699 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1481 0 obj +<< +/K [1482 0 R 173] +/P 2700 0 R +/Pg 14 0 R +/S /Code +/Type /StructElem +>> +endobj +1482 0 obj +<< +/K 174 +/P 1481 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1483 0 obj +<< +/K 175 +/P 2701 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1484 0 obj +<< +/K 176 +/P 2922 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1485 0 obj +<< +/K 177 +/P 2703 0 R +/Pg 14 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1486 0 obj +<< +/A [<< +/O /Table +/Scope /Column +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1526 0 R 18] +/P 485 0 R +/Pg 15 0 R +/S /TH +/Type /StructElem +>> +endobj +1487 0 obj +<< +/K [1488 0 R 27] +/P 2704 0 R +/Pg 15 0 R +/S /Code +/Type /StructElem +>> +endobj +1488 0 obj +<< +/K 28 +/P 1487 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1489 0 obj +<< +/K 29 +/P 2705 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1490 0 obj +<< +/K 30 +/P 2923 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1491 0 obj +<< +/K 31 +/P 2707 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1492 0 obj +<< +/K [1493 0 R 32] +/P 2708 0 R +/Pg 15 0 R +/S /Code +/Type /StructElem +>> +endobj +1493 0 obj +<< +/K 33 +/P 1492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1494 0 obj +<< +/K 34 +/P 2709 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1495 0 obj +<< +/K 35 +/P 2924 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1496 0 obj +<< +/K 36 +/P 2711 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1497 0 obj +<< +/K [1498 0 R 37] +/P 2712 0 R +/Pg 15 0 R +/S /Code +/Type /StructElem +>> +endobj +1498 0 obj +<< +/K 38 +/P 1497 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1499 0 obj +<< +/K 39 +/P 2713 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1500 0 obj +<< +/K 40 +/P 2925 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1501 0 obj +<< +/K 41 +/P 2715 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1502 0 obj +<< +/K [1503 0 R 42] +/P 2716 0 R +/Pg 15 0 R +/S /Code +/Type /StructElem +>> +endobj +1503 0 obj +<< +/K 43 +/P 1502 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1504 0 obj +<< +/K 44 +/P 2717 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1505 0 obj +<< +/K 45 +/P 2926 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1506 0 obj +<< +/K 46 +/P 2719 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1507 0 obj +<< +/K 48 +/P 275 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1508 0 obj +<< +/K 49 +/P 276 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1509 0 obj +<< +/K 50 +/P 277 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1510 0 obj +<< +/K 51 +/P 2720 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1511 0 obj +<< +/K 52 +/P 2721 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1512 0 obj +<< +/K 53 +/P 2927 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1513 0 obj +<< +/K 54 +/P 2723 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1514 0 obj +<< +/K 55 +/P 2724 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1515 0 obj +<< +/K 56 +/P 2928 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1516 0 obj +<< +/K 57 +/P 2726 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1517 0 obj +<< +/K 58 +/P 2727 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1518 0 obj +<< +/K 59 +/P 2929 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1519 0 obj +<< +/K 60 +/P 2729 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1520 0 obj +<< +/K 61 +/P 2730 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1521 0 obj +<< +/K 62 +/P 2930 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1522 0 obj +<< +/K 66 +/P 482 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1523 0 obj +<< +/K 69 +/P 278 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1524 0 obj +<< +/K 70 +/P 279 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1525 0 obj +<< +/K 71 +/P 280 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1526 0 obj +<< +/K 72 +/P 1486 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1527 0 obj +<< +/K 73 +/P 2732 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1528 0 obj +<< +/K [1529 0 R 74] +/P 2733 0 R +/Pg 15 0 R +/S /Code +/Type /StructElem +>> +endobj +1529 0 obj +<< +/K 75 +/P 1528 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1530 0 obj +<< +/K 76 +/P 2733 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1531 0 obj +<< +/K 77 +/P 2931 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1532 0 obj +<< +/K 78 +/P 2734 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1533 0 obj +<< +/K 79 +/P 2735 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1534 0 obj +<< +/K [1535 0 R 80] +/P 2736 0 R +/Pg 15 0 R +/S /Code +/Type /StructElem +>> +endobj +1535 0 obj +<< +/K 81 +/P 1534 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1536 0 obj +<< +/K 82 +/P 2736 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1537 0 obj +<< +/K 83 +/P 2932 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1538 0 obj +<< +/K 84 +/P 2737 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1539 0 obj +<< +/K 85 +/P 2738 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1540 0 obj +<< +/K 86 +/P 2739 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1541 0 obj +<< +/K 87 +/P 2933 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1542 0 obj +<< +/K 88 +/P 2741 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1543 0 obj +<< +/K 89 +/P 2742 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1544 0 obj +<< +/K 90 +/P 2934 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1545 0 obj +<< +/K 91 +/P 2744 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1546 0 obj +<< +/K 92 +/P 2745 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1547 0 obj +<< +/K 93 +/P 2935 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1548 0 obj +<< +/K 94 +/P 2746 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1549 0 obj +<< +/K 96 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1550 0 obj +<< +/K 97 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1551 0 obj +<< +/K 98 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1552 0 obj +<< +/K 99 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1553 0 obj +<< +/K 100 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1554 0 obj +<< +/K 101 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1555 0 obj +<< +/K 102 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1556 0 obj +<< +/K 103 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1557 0 obj +<< +/K 104 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1558 0 obj +<< +/K 105 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1559 0 obj +<< +/K 106 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1560 0 obj +<< +/K 107 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1561 0 obj +<< +/K 108 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1562 0 obj +<< +/K 109 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1563 0 obj +<< +/K 110 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1564 0 obj +<< +/K 111 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1565 0 obj +<< +/K 112 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1566 0 obj +<< +/K 113 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1567 0 obj +<< +/K 114 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1568 0 obj +<< +/K 115 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1569 0 obj +<< +/K 116 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1570 0 obj +<< +/K 117 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1571 0 obj +<< +/K 118 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1572 0 obj +<< +/K 119 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1573 0 obj +<< +/K 120 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1574 0 obj +<< +/K 121 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1575 0 obj +<< +/K 122 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1576 0 obj +<< +/K 123 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1577 0 obj +<< +/K 124 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1578 0 obj +<< +/K 125 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1579 0 obj +<< +/K 126 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1580 0 obj +<< +/K 127 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1581 0 obj +<< +/K 128 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1582 0 obj +<< +/K 129 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1583 0 obj +<< +/K 130 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1584 0 obj +<< +/K 131 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1585 0 obj +<< +/K 132 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1586 0 obj +<< +/K 133 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1587 0 obj +<< +/K 134 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1588 0 obj +<< +/K 135 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1589 0 obj +<< +/K 136 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1590 0 obj +<< +/K 137 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1591 0 obj +<< +/K 138 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1592 0 obj +<< +/K 139 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1593 0 obj +<< +/K 140 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1594 0 obj +<< +/K 141 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1595 0 obj +<< +/K 142 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1596 0 obj +<< +/K 143 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1597 0 obj +<< +/K 144 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1598 0 obj +<< +/K 145 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1599 0 obj +<< +/K 146 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1600 0 obj +<< +/K 147 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1601 0 obj +<< +/K 148 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1602 0 obj +<< +/K 149 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1603 0 obj +<< +/K 150 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1604 0 obj +<< +/K 151 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1605 0 obj +<< +/K 152 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1606 0 obj +<< +/K 153 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1607 0 obj +<< +/K 154 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1608 0 obj +<< +/K 155 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1609 0 obj +<< +/K 156 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1610 0 obj +<< +/K 157 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1611 0 obj +<< +/K 158 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1612 0 obj +<< +/K 159 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1613 0 obj +<< +/K 160 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1614 0 obj +<< +/K 161 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1615 0 obj +<< +/K 162 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1616 0 obj +<< +/K 163 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1617 0 obj +<< +/K 164 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1618 0 obj +<< +/K 165 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1619 0 obj +<< +/K 166 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1620 0 obj +<< +/K 167 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1621 0 obj +<< +/K 168 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1622 0 obj +<< +/K 169 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1623 0 obj +<< +/K 170 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1624 0 obj +<< +/K 171 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1625 0 obj +<< +/K 172 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1626 0 obj +<< +/K 173 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1627 0 obj +<< +/K 174 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1628 0 obj +<< +/K 175 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1629 0 obj +<< +/K 176 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1630 0 obj +<< +/K 177 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1631 0 obj +<< +/K 178 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1632 0 obj +<< +/K 179 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1633 0 obj +<< +/K 180 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1634 0 obj +<< +/K 181 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1635 0 obj +<< +/K 182 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1636 0 obj +<< +/K 183 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1637 0 obj +<< +/K 184 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1638 0 obj +<< +/K 185 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1639 0 obj +<< +/K 186 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1640 0 obj +<< +/K 187 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1641 0 obj +<< +/K 188 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1642 0 obj +<< +/K 189 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1643 0 obj +<< +/K 190 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1644 0 obj +<< +/K 191 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1645 0 obj +<< +/K 192 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1646 0 obj +<< +/K 193 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1647 0 obj +<< +/K 194 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1648 0 obj +<< +/K 195 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1649 0 obj +<< +/K 196 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1650 0 obj +<< +/K 197 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1651 0 obj +<< +/K 198 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1652 0 obj +<< +/K 199 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1653 0 obj +<< +/K 200 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1654 0 obj +<< +/K 201 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1655 0 obj +<< +/K 202 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1656 0 obj +<< +/K 203 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1657 0 obj +<< +/K 204 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1658 0 obj +<< +/K 205 +/P 492 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1659 0 obj +<< +/K 207 +/P 494 0 R +/Pg 15 0 R +/S /Lbl +/Type /StructElem +>> +endobj +1660 0 obj +<< +/K [1661 0 R 208] +/P 494 0 R +/Pg 15 0 R +/S /Code +/Type /StructElem +>> +endobj +1661 0 obj +<< +/K 209 +/P 1660 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1662 0 obj +<< +/K 210 +/P 494 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1663 0 obj +<< +/K 211 +/P 495 0 R +/Pg 15 0 R +/S /Lbl +/Type /StructElem +>> +endobj +1664 0 obj +<< +/K 212 +/P 495 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1665 0 obj +<< +/K [1666 0 R 213] +/P 495 0 R +/Pg 15 0 R +/S /Code +/Type /StructElem +>> +endobj +1666 0 obj +<< +/K 214 +/P 1665 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1667 0 obj +<< +/K 215 +/P 495 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1668 0 obj +<< +/K [1669 0 R 216] +/P 495 0 R +/Pg 15 0 R +/S /Code +/Type /StructElem +>> +endobj +1669 0 obj +<< +/K 217 +/P 1668 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1670 0 obj +<< +/K 218 +/P 495 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1671 0 obj +<< +/K 219 +/P 496 0 R +/Pg 15 0 R +/S /Lbl +/Type /StructElem +>> +endobj +1672 0 obj +<< +/K 220 +/P 496 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1673 0 obj +<< +/K 221 +/P 497 0 R +/Pg 15 0 R +/S /Lbl +/Type /StructElem +>> +endobj +1674 0 obj +<< +/K [1675 0 R 222] +/P 497 0 R +/Pg 15 0 R +/S /Code +/Type /StructElem +>> +endobj +1675 0 obj +<< +/K 223 +/P 1674 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1676 0 obj +<< +/K 224 +/P 497 0 R +/Pg 15 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1677 0 obj +<< +/K 10 +/P 501 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1678 0 obj +<< +/K 13 +/P 503 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1679 0 obj +<< +/K 15 +/P 505 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1680 0 obj +<< +/K 21 +/P 511 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1681 0 obj +<< +/K 23 +/P 513 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1682 0 obj +<< +/K 26 +/P 515 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1683 0 obj +<< +/K 29 +/P 517 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1684 0 obj +<< +/K 32 +/P 519 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1685 0 obj +<< +/K 34 +/P 521 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1686 0 obj +<< +/K 37 +/P 524 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1687 0 obj +<< +/K 39 +/P 526 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1688 0 obj +<< +/K 42 +/P 528 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1689 0 obj +<< +/K 44 +/P 530 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1690 0 obj +<< +/K 46 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1691 0 obj +<< +/K 47 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1692 0 obj +<< +/K 48 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1693 0 obj +<< +/K 49 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1694 0 obj +<< +/K 50 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1695 0 obj +<< +/K 51 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1696 0 obj +<< +/K 52 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1697 0 obj +<< +/K 53 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1698 0 obj +<< +/K 54 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1699 0 obj +<< +/K 55 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1700 0 obj +<< +/K 56 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1701 0 obj +<< +/K 57 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1702 0 obj +<< +/K 58 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1703 0 obj +<< +/K 59 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1704 0 obj +<< +/K 60 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1705 0 obj +<< +/K 61 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1706 0 obj +<< +/K 62 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1707 0 obj +<< +/K 63 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1708 0 obj +<< +/K 64 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1709 0 obj +<< +/K 65 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1710 0 obj +<< +/K 66 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1711 0 obj +<< +/K 67 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1712 0 obj +<< +/K 68 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1713 0 obj +<< +/K 69 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1714 0 obj +<< +/K 70 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1715 0 obj +<< +/K 71 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1716 0 obj +<< +/K 72 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1717 0 obj +<< +/K 73 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1718 0 obj +<< +/K 74 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1719 0 obj +<< +/K 75 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1720 0 obj +<< +/K 76 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1721 0 obj +<< +/K 77 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1722 0 obj +<< +/K 78 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1723 0 obj +<< +/K 79 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1724 0 obj +<< +/K 80 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1725 0 obj +<< +/K 81 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1726 0 obj +<< +/K 82 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1727 0 obj +<< +/K 83 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1728 0 obj +<< +/K 84 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1729 0 obj +<< +/K 85 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1730 0 obj +<< +/K 86 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1731 0 obj +<< +/K 87 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1732 0 obj +<< +/K 88 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1733 0 obj +<< +/K 89 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1734 0 obj +<< +/K 90 +/P 532 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1735 0 obj +<< +/K 91 +/P 533 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1736 0 obj +<< +/K 94 +/P 536 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1737 0 obj +<< +/K 96 +/P 538 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1738 0 obj +<< +/K 99 +/P 540 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1739 0 obj +<< +/K 102 +/P 542 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1740 0 obj +<< +/K 104 +/P 544 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1741 0 obj +<< +/K 107 +/P 546 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1742 0 obj +<< +/K 110 +/P 548 0 R +/Pg 16 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1743 0 obj +<< +/K 4 +/P 550 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1744 0 obj +<< +/K 6 +/P 552 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1745 0 obj +<< +/K 9 +/P 554 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1746 0 obj +<< +/K 12 +/P 556 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1747 0 obj +<< +/K 15 +/P 558 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1748 0 obj +<< +/K 18 +/P 560 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1749 0 obj +<< +/K 20 +/P 562 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1750 0 obj +<< +/K 22 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1751 0 obj +<< +/K 23 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1752 0 obj +<< +/K 24 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1753 0 obj +<< +/K 25 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1754 0 obj +<< +/K 26 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1755 0 obj +<< +/K 27 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1756 0 obj +<< +/K 28 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1757 0 obj +<< +/K 29 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1758 0 obj +<< +/K 30 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1759 0 obj +<< +/K 31 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1760 0 obj +<< +/K 32 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1761 0 obj +<< +/K 33 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1762 0 obj +<< +/K 34 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1763 0 obj +<< +/K 35 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1764 0 obj +<< +/K 36 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1765 0 obj +<< +/K 37 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1766 0 obj +<< +/K 38 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1767 0 obj +<< +/K 39 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1768 0 obj +<< +/K 40 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1769 0 obj +<< +/K 41 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1770 0 obj +<< +/K 42 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1771 0 obj +<< +/K 43 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1772 0 obj +<< +/K 44 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1773 0 obj +<< +/K 45 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1774 0 obj +<< +/K 46 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1775 0 obj +<< +/K 47 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1776 0 obj +<< +/K 48 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1777 0 obj +<< +/K 49 +/P 564 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1778 0 obj +<< +/K 50 +/P 2747 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1779 0 obj +<< +/K 52 +/P 567 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1780 0 obj +<< +/K 56 +/P 571 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1781 0 obj +<< +/K 58 +/P 573 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1782 0 obj +<< +/K 61 +/P 575 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1783 0 obj +<< +/K 64 +/P 577 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1784 0 obj +<< +/K 66 +/P 579 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1785 0 obj +<< +/K 68 +/P 581 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1786 0 obj +<< +/K 71 +/P 583 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1787 0 obj +<< +/K 74 +/P 585 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1788 0 obj +<< +/K 77 +/P 588 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1789 0 obj +<< +/K 79 +/P 590 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1790 0 obj +<< +/K 82 +/P 592 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1791 0 obj +<< +/K 85 +/P 595 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1792 0 obj +<< +/K 87 +/P 597 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1793 0 obj +<< +/K 90 +/P 599 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1794 0 obj +<< +/K 92 +/P 601 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1795 0 obj +<< +/K 95 +/P 604 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1796 0 obj +<< +/K 100 +/P 608 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1797 0 obj +<< +/K 102 +/P 610 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1798 0 obj +<< +/K 105 +/P 613 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1799 0 obj +<< +/K 107 +/P 615 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1800 0 obj +<< +/K 110 +/P 617 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1801 0 obj +<< +/K 113 +/P 619 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1802 0 obj +<< +/K 116 +/P 621 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1803 0 obj +<< +/K 119 +/P 623 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1804 0 obj +<< +/K 122 +/P 625 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1805 0 obj +<< +/K 125 +/P 628 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1806 0 obj +<< +/K 127 +/P 630 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1807 0 obj +<< +/K 130 +/P 632 0 R +/Pg 17 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1808 0 obj +<< +/K 13 +/P 281 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1809 0 obj +<< +/K 14 +/P 282 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1810 0 obj +<< +/K 15 +/P 283 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1811 0 obj +<< +/K 16 +/P 2748 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1812 0 obj +<< +/K 17 +/P 2749 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1813 0 obj +<< +/K 18 +/P 2750 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1814 0 obj +<< +/K 19 +/P 2751 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1815 0 obj +<< +/K 20 +/P 2752 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1816 0 obj +<< +/K 21 +/P 2753 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1817 0 obj +<< +/K 22 +/P 2754 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1818 0 obj +<< +/K 23 +/P 2755 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1819 0 obj +<< +/K 24 +/P 2756 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1820 0 obj +<< +/K 25 +/P 2757 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1821 0 obj +<< +/K 26 +/P 2758 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1822 0 obj +<< +/K 27 +/P 2759 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1823 0 obj +<< +/K 28 +/P 2760 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1824 0 obj +<< +/K 29 +/P 2761 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1825 0 obj +<< +/K 30 +/P 2762 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1826 0 obj +<< +/K 33 +/P 644 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1827 0 obj +<< +/K 35 +/P 646 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1828 0 obj +<< +/K 37 +/P 648 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1829 0 obj +<< +/K 40 +/P 650 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1830 0 obj +<< +/K 42 +/P 652 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1831 0 obj +<< +/K 43 +/P 652 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1832 0 obj +<< +/K 44 +/P 652 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1833 0 obj +<< +/K 45 +/P 652 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1834 0 obj +<< +/K 46 +/P 652 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1835 0 obj +<< +/K 48 +/P 654 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1836 0 obj +<< +/K 50 +/P 656 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1837 0 obj +<< +/K 53 +/P 658 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1838 0 obj +<< +/K 55 +/P 660 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1839 0 obj +<< +/K 58 +/P 662 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1840 0 obj +<< +/K 60 +/P 664 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1841 0 obj +<< +/K 61 +/P 664 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1842 0 obj +<< +/K 62 +/P 664 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1843 0 obj +<< +/K 63 +/P 664 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1844 0 obj +<< +/K 64 +/P 664 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1845 0 obj +<< +/K 65 +/P 664 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1846 0 obj +<< +/K 66 +/P 664 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1847 0 obj +<< +/K 68 +/P 666 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1848 0 obj +<< +/K 70 +/P 668 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1849 0 obj +<< +/K 73 +/P 670 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1850 0 obj +<< +/K 75 +/P 672 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1851 0 obj +<< +/K 77 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1852 0 obj +<< +/K 78 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1853 0 obj +<< +/K 79 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1854 0 obj +<< +/K 80 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1855 0 obj +<< +/K 81 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1856 0 obj +<< +/K 82 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1857 0 obj +<< +/K 83 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1858 0 obj +<< +/K 84 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1859 0 obj +<< +/K 85 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1860 0 obj +<< +/K 86 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1861 0 obj +<< +/K 87 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1862 0 obj +<< +/K 88 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1863 0 obj +<< +/K 89 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1864 0 obj +<< +/K 90 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1865 0 obj +<< +/K 91 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1866 0 obj +<< +/K 92 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1867 0 obj +<< +/K 93 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1868 0 obj +<< +/K 94 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1869 0 obj +<< +/K 95 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1870 0 obj +<< +/K 96 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1871 0 obj +<< +/K 97 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1872 0 obj +<< +/K 98 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1873 0 obj +<< +/K 99 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1874 0 obj +<< +/K 100 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1875 0 obj +<< +/K 101 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1876 0 obj +<< +/K 102 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1877 0 obj +<< +/K 103 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1878 0 obj +<< +/K 104 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1879 0 obj +<< +/K 105 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1880 0 obj +<< +/K 106 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1881 0 obj +<< +/K 107 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1882 0 obj +<< +/K 108 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1883 0 obj +<< +/K 109 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1884 0 obj +<< +/K 110 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1885 0 obj +<< +/K 111 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1886 0 obj +<< +/K 112 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1887 0 obj +<< +/K 113 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1888 0 obj +<< +/K 114 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1889 0 obj +<< +/K 115 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1890 0 obj +<< +/K 116 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1891 0 obj +<< +/K 117 +/P 674 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1892 0 obj +<< +/K 119 +/P 676 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1893 0 obj +<< +/K 121 +/P 678 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1894 0 obj +<< +/K 124 +/P 680 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1895 0 obj +<< +/K 126 +/P 682 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1896 0 obj +<< +/K 128 +/P 684 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1897 0 obj +<< +/K 130 +/P 686 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1898 0 obj +<< +/K 131 +/P 686 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1899 0 obj +<< +/K 132 +/P 686 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1900 0 obj +<< +/K 133 +/P 686 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1901 0 obj +<< +/K 134 +/P 686 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1902 0 obj +<< +/K 135 +/P 686 0 R +/Pg 18 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1903 0 obj +<< +/K 11 +/P 688 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1904 0 obj +<< +/K 13 +/P 690 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1905 0 obj +<< +/K 16 +/P 692 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1906 0 obj +<< +/K 19 +/P 694 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1907 0 obj +<< +/K 21 +/P 696 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1908 0 obj +<< +/K 22 +/P 697 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1909 0 obj +<< +/K 23 +/P 698 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1910 0 obj +<< +/K 24 +/P 284 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1911 0 obj +<< +/K 25 +/P 285 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1912 0 obj +<< +/K 26 +/P 286 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1913 0 obj +<< +/K 27 +/P 287 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1914 0 obj +<< +/K [1915 0 R 28] +/P 2763 0 R +/Pg 19 0 R +/S /Code +/Type /StructElem +>> +endobj +1915 0 obj +<< +/K 29 +/P 1914 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1916 0 obj +<< +/K 30 +/P 2763 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1917 0 obj +<< +/K 31 +/P 2764 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1918 0 obj +<< +/K 32 +/P 2765 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1919 0 obj +<< +/K 33 +/P 2766 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1920 0 obj +<< +/K [1921 0 R 34] +/P 2767 0 R +/Pg 19 0 R +/S /Code +/Type /StructElem +>> +endobj +1921 0 obj +<< +/K 35 +/P 1920 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1922 0 obj +<< +/K 36 +/P 2768 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1923 0 obj +<< +/K 37 +/P 2769 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1924 0 obj +<< +/K 38 +/P 2770 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1925 0 obj +<< +/K 39 +/P 2771 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1926 0 obj +<< +/K 40 +/P 2772 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1927 0 obj +<< +/K 41 +/P 2773 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1928 0 obj +<< +/K 42 +/P 2774 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1929 0 obj +<< +/K [1930 0 R 43] +/P 2775 0 R +/Pg 19 0 R +/S /Code +/Type /StructElem +>> +endobj +1930 0 obj +<< +/K 44 +/P 1929 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1931 0 obj +<< +/K 45 +/P 2775 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1932 0 obj +<< +/K 46 +/P 2776 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1933 0 obj +<< +/K 47 +/P 2777 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1934 0 obj +<< +/K 48 +/P 2778 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1935 0 obj +<< +/K 49 +/P 704 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1936 0 obj +<< +/K 51 +/P 706 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1937 0 obj +<< +/K 53 +/P 707 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1938 0 obj +<< +/K 56 +/P 709 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1939 0 obj +<< +/K 59 +/P 711 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1940 0 obj +<< +/K 61 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1941 0 obj +<< +/K 62 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1942 0 obj +<< +/K 63 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1943 0 obj +<< +/K 64 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1944 0 obj +<< +/K 65 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1945 0 obj +<< +/K 66 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1946 0 obj +<< +/K 67 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1947 0 obj +<< +/K 68 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1948 0 obj +<< +/K 69 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1949 0 obj +<< +/K 70 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1950 0 obj +<< +/K 71 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1951 0 obj +<< +/K 72 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1952 0 obj +<< +/K 73 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1953 0 obj +<< +/K 74 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1954 0 obj +<< +/K 75 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1955 0 obj +<< +/K 76 +/P 713 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1956 0 obj +<< +/K 78 +/P 715 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1957 0 obj +<< +/K 81 +/P 717 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1958 0 obj +<< +/K 83 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1959 0 obj +<< +/K 84 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1960 0 obj +<< +/K 85 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1961 0 obj +<< +/K 86 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1962 0 obj +<< +/K 87 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1963 0 obj +<< +/K 88 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1964 0 obj +<< +/K 89 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1965 0 obj +<< +/K 90 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1966 0 obj +<< +/K 91 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1967 0 obj +<< +/K 92 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1968 0 obj +<< +/K 93 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1969 0 obj +<< +/K 94 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1970 0 obj +<< +/K 95 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1971 0 obj +<< +/K 96 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1972 0 obj +<< +/K 97 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1973 0 obj +<< +/K 98 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1974 0 obj +<< +/K 99 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1975 0 obj +<< +/K 100 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1976 0 obj +<< +/K 101 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1977 0 obj +<< +/K 102 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1978 0 obj +<< +/K 103 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1979 0 obj +<< +/K 104 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1980 0 obj +<< +/K 105 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1981 0 obj +<< +/K 106 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1982 0 obj +<< +/K 107 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1983 0 obj +<< +/K 108 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1984 0 obj +<< +/K 109 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1985 0 obj +<< +/K 110 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1986 0 obj +<< +/K 111 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1987 0 obj +<< +/K 112 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1988 0 obj +<< +/K 113 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1989 0 obj +<< +/K 114 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1990 0 obj +<< +/K 115 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1991 0 obj +<< +/K 116 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1992 0 obj +<< +/K 117 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1993 0 obj +<< +/K 118 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1994 0 obj +<< +/K 119 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1995 0 obj +<< +/K 120 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1996 0 obj +<< +/K 121 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1997 0 obj +<< +/K 122 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1998 0 obj +<< +/K 123 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +1999 0 obj +<< +/K 124 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2000 0 obj +<< +/K 125 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2001 0 obj +<< +/K 126 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2002 0 obj +<< +/K 127 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2003 0 obj +<< +/K 128 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2004 0 obj +<< +/K 129 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2005 0 obj +<< +/K 130 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2006 0 obj +<< +/K 131 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2007 0 obj +<< +/K 132 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2008 0 obj +<< +/K 133 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2009 0 obj +<< +/K 134 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2010 0 obj +<< +/K 135 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2011 0 obj +<< +/K 136 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2012 0 obj +<< +/K 137 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2013 0 obj +<< +/K 138 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2014 0 obj +<< +/K 139 +/P 719 0 R +/Pg 19 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2015 0 obj +<< +/K 12 +/P 719 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2016 0 obj +<< +/K 13 +/P 719 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2017 0 obj +<< +/K 14 +/P 719 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2018 0 obj +<< +/K 15 +/P 719 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2019 0 obj +<< +/K 16 +/P 719 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2020 0 obj +<< +/K 17 +/P 719 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2021 0 obj +<< +/K 20 +/P 721 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2022 0 obj +<< +/K 22 +/P 723 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2023 0 obj +<< +/K 24 +/P 725 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2024 0 obj +<< +/K 26 +/P 726 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2025 0 obj +<< +/K 28 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2026 0 obj +<< +/K 29 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2027 0 obj +<< +/K 30 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2028 0 obj +<< +/K 31 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2029 0 obj +<< +/K 32 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2030 0 obj +<< +/K 33 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2031 0 obj +<< +/K 34 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2032 0 obj +<< +/K 35 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2033 0 obj +<< +/K 36 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2034 0 obj +<< +/K 37 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2035 0 obj +<< +/K 38 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2036 0 obj +<< +/K 39 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2037 0 obj +<< +/K 40 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2038 0 obj +<< +/K 41 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2039 0 obj +<< +/K 42 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2040 0 obj +<< +/K 43 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2041 0 obj +<< +/K 44 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2042 0 obj +<< +/K 45 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2043 0 obj +<< +/K 46 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2044 0 obj +<< +/K 47 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2045 0 obj +<< +/K 48 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2046 0 obj +<< +/K 49 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2047 0 obj +<< +/K 50 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2048 0 obj +<< +/K 51 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2049 0 obj +<< +/K 52 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2050 0 obj +<< +/K 53 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2051 0 obj +<< +/K 54 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2052 0 obj +<< +/K 55 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2053 0 obj +<< +/K 56 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2054 0 obj +<< +/K 57 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2055 0 obj +<< +/K 58 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2056 0 obj +<< +/K 59 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2057 0 obj +<< +/K 60 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2058 0 obj +<< +/K 61 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2059 0 obj +<< +/K 62 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2060 0 obj +<< +/K 63 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2061 0 obj +<< +/K 64 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2062 0 obj +<< +/K 65 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2063 0 obj +<< +/K 66 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2064 0 obj +<< +/K 67 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2065 0 obj +<< +/K 68 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2066 0 obj +<< +/K 69 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2067 0 obj +<< +/K 70 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2068 0 obj +<< +/K 71 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2069 0 obj +<< +/K 72 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2070 0 obj +<< +/K 73 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2071 0 obj +<< +/K 74 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2072 0 obj +<< +/K 75 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2073 0 obj +<< +/K 76 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2074 0 obj +<< +/K 77 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2075 0 obj +<< +/K 78 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2076 0 obj +<< +/K 79 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2077 0 obj +<< +/K 80 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2078 0 obj +<< +/K 81 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2079 0 obj +<< +/K 82 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2080 0 obj +<< +/K 83 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2081 0 obj +<< +/K 84 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2082 0 obj +<< +/K 85 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2083 0 obj +<< +/K 86 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2084 0 obj +<< +/K 87 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2085 0 obj +<< +/K 88 +/P 728 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2086 0 obj +<< +/K 92 +/P 732 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2087 0 obj +<< +/K 94 +/P 734 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2088 0 obj +<< +/K 96 +/P 736 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2089 0 obj +<< +/K 99 +/P 738 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2090 0 obj +<< +/K 101 +/P 740 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2091 0 obj +<< +/K 104 +/P 742 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2092 0 obj +<< +/K 107 +/P 288 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2093 0 obj +<< +/K 108 +/P 289 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2094 0 obj +<< +/K 109 +/P 290 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2095 0 obj +<< +/K 110 +/P 2779 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2096 0 obj +<< +/K 111 +/P 2780 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2097 0 obj +<< +/K 112 +/P 2781 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2098 0 obj +<< +/K 113 +/P 2782 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2099 0 obj +<< +/K 114 +/P 2783 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2100 0 obj +<< +/K 115 +/P 2784 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2101 0 obj +<< +/K 116 +/P 2785 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2102 0 obj +<< +/K 117 +/P 2786 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2103 0 obj +<< +/K 118 +/P 2787 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2104 0 obj +<< +/K 119 +/P 2788 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2105 0 obj +<< +/K 120 +/P 2789 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2106 0 obj +<< +/K 121 +/P 2790 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2107 0 obj +<< +/K 122 +/P 2791 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2108 0 obj +<< +/K 123 +/P 2792 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2109 0 obj +<< +/K 124 +/P 2793 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2110 0 obj +<< +/K 125 +/P 2794 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2111 0 obj +<< +/K 126 +/P 2795 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2112 0 obj +<< +/K 127 +/P 2796 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2113 0 obj +<< +/K 128 +/P 2797 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2114 0 obj +<< +/K 129 +/P 2798 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2115 0 obj +<< +/K 130 +/P 2799 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2116 0 obj +<< +/K 131 +/P 2800 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2117 0 obj +<< +/K 132 +/P 2801 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2118 0 obj +<< +/K 133 +/P 2802 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2119 0 obj +<< +/K 134 +/P 2936 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2120 0 obj +<< +/K 135 +/P 2937 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2121 0 obj +<< +/K 136 +/P 2805 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2122 0 obj +<< +/K 142 +/P 759 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2123 0 obj +<< +/K 147 +/P 763 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2124 0 obj +<< +/K 150 +/P 765 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2125 0 obj +<< +/K 155 +/P 769 0 R +/Pg 20 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2126 0 obj +<< +/K 29 +/P 772 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2127 0 obj +<< +/K 32 +/P 774 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2128 0 obj +<< +/K 35 +/P 776 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2129 0 obj +<< +/K 38 +/P 778 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2130 0 obj +<< +/K 41 +/P 780 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2131 0 obj +<< +/K 44 +/P 783 0 R +/Pg 21 0 R +/S /Lbl +/Type /StructElem +>> +endobj +2132 0 obj +<< +/K [2133 0 R 45] +/P 783 0 R +/Pg 21 0 R +/S /Code +/Type /StructElem +>> +endobj +2133 0 obj +<< +/K 46 +/P 2132 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2134 0 obj +<< +/K 47 +/P 783 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2135 0 obj +<< +/K [2136 0 R 48] +/P 783 0 R +/Pg 21 0 R +/S /Code +/Type /StructElem +>> +endobj +2136 0 obj +<< +/K 49 +/P 2135 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2137 0 obj +<< +/K 50 +/P 783 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2138 0 obj +<< +/K 51 +/P 784 0 R +/Pg 21 0 R +/S /Lbl +/Type /StructElem +>> +endobj +2139 0 obj +<< +/K [2140 0 R 52] +/P 784 0 R +/Pg 21 0 R +/S /Code +/Type /StructElem +>> +endobj +2140 0 obj +<< +/K 53 +/P 2139 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2141 0 obj +<< +/K 54 +/P 784 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2142 0 obj +<< +/K [2143 0 R 55] +/P 784 0 R +/Pg 21 0 R +/S /Code +/Type /StructElem +>> +endobj +2143 0 obj +<< +/K 56 +/P 2142 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2144 0 obj +<< +/K 57 +/P 784 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2145 0 obj +<< +/K 58 +/P 785 0 R +/Pg 21 0 R +/S /Lbl +/Type /StructElem +>> +endobj +2146 0 obj +<< +/K [2147 0 R 59] +/P 785 0 R +/Pg 21 0 R +/S /Code +/Type /StructElem +>> +endobj +2147 0 obj +<< +/K 60 +/P 2146 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2148 0 obj +<< +/K 61 +/P 785 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2149 0 obj +<< +/K 62 +/P 786 0 R +/Pg 21 0 R +/S /Lbl +/Type /StructElem +>> +endobj +2150 0 obj +<< +/K 63 +/P 786 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2151 0 obj +<< +/K [2152 0 R 64] +/P 786 0 R +/Pg 21 0 R +/S /Code +/Type /StructElem +>> +endobj +2152 0 obj +<< +/K 65 +/P 2151 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2153 0 obj +<< +/K 66 +/P 786 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2154 0 obj +<< +/K [2155 0 R 67] +/P 786 0 R +/Pg 21 0 R +/S /Code +/Type /StructElem +>> +endobj +2155 0 obj +<< +/K 68 +/P 2154 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2156 0 obj +<< +/K 69 +/P 786 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2157 0 obj +<< +/K [2158 0 R 70] +/P 786 0 R +/Pg 21 0 R +/S /Code +/Type /StructElem +>> +endobj +2158 0 obj +<< +/K 71 +/P 2157 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2159 0 obj +<< +/K 72 +/P 786 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2160 0 obj +<< +/K 74 +/P 291 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2161 0 obj +<< +/K 75 +/P 292 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2162 0 obj +<< +/K 76 +/P 293 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2163 0 obj +<< +/K 77 +/P 2806 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2164 0 obj +<< +/K 78 +/P 2807 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2165 0 obj +<< +/K 79 +/P 2808 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2166 0 obj +<< +/K 80 +/P 2809 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2167 0 obj +<< +/K 81 +/P 2810 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2168 0 obj +<< +/K 82 +/P 2811 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2169 0 obj +<< +/K 83 +/P 2812 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2170 0 obj +<< +/K 84 +/P 2813 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2171 0 obj +<< +/K 85 +/P 2814 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2172 0 obj +<< +/K 86 +/P 2815 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2173 0 obj +<< +/K 87 +/P 2816 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2174 0 obj +<< +/K 88 +/P 2817 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2175 0 obj +<< +/K 91 +/P 294 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2176 0 obj +<< +/K 92 +/P 295 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2177 0 obj +<< +/K 93 +/P 296 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2178 0 obj +<< +/K 94 +/P 297 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2179 0 obj +<< +/K 95 +/P 2818 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2180 0 obj +<< +/K 96 +/P 2819 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2181 0 obj +<< +/K 97 +/P 2938 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2182 0 obj +<< +/K 98 +/P 2821 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2183 0 obj +<< +/K 99 +/P 2822 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2184 0 obj +<< +/K 100 +/P 2823 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2185 0 obj +<< +/K 101 +/P 2824 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2186 0 obj +<< +/K 102 +/P 2825 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2187 0 obj +<< +/K 103 +/P 2826 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2188 0 obj +<< +/K 104 +/P 2827 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2189 0 obj +<< +/K 105 +/P 2828 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2190 0 obj +<< +/K 106 +/P 2829 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2191 0 obj +<< +/K 107 +/P 2830 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2192 0 obj +<< +/K 108 +/P 2831 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2193 0 obj +<< +/K 109 +/P 2832 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2194 0 obj +<< +/K 110 +/P 2833 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2195 0 obj +<< +/K 112 +/P 298 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2196 0 obj +<< +/K 113 +/P 299 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2197 0 obj +<< +/K 114 +/P 300 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2198 0 obj +<< +/K 115 +/P 2834 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2199 0 obj +<< +/K 116 +/P 2835 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2200 0 obj +<< +/K 117 +/P 2836 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2201 0 obj +<< +/K 118 +/P 2837 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2202 0 obj +<< +/K 119 +/P 2838 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2203 0 obj +<< +/K 120 +/P 2839 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2204 0 obj +<< +/K 121 +/P 2840 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2205 0 obj +<< +/K 122 +/P 2841 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2206 0 obj +<< +/K 123 +/P 2842 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2207 0 obj +<< +/K 124 +/P 2843 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2208 0 obj +<< +/K 125 +/P 2844 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2209 0 obj +<< +/K 126 +/P 2845 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2210 0 obj +<< +/K 127 +/P 2846 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2211 0 obj +<< +/K 128 +/P 2847 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2212 0 obj +<< +/K 129 +/P 2848 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2213 0 obj +<< +/K 130 +/P 2849 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2214 0 obj +<< +/K 131 +/P 2850 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2215 0 obj +<< +/K 132 +/P 2851 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2216 0 obj +<< +/K 133 +/P 2852 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2217 0 obj +<< +/K 134 +/P 2853 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2218 0 obj +<< +/K 135 +/P 2854 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2219 0 obj +<< +/K [137 << +/MCID 15 +/Pg 22 0 R +/Type /MCR +>>] +/P 301 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2220 0 obj +<< +/K [138 << +/MCID 16 +/Pg 22 0 R +/Type /MCR +>>] +/P 302 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2221 0 obj +<< +/K [139 << +/MCID 17 +/Pg 22 0 R +/Type /MCR +>>] +/P 303 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2222 0 obj +<< +/K 140 +/P 2855 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2223 0 obj +<< +/K 141 +/P 2856 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2224 0 obj +<< +/K 142 +/P 2857 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2225 0 obj +<< +/K 143 +/P 2858 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2226 0 obj +<< +/K 144 +/P 2859 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2227 0 obj +<< +/K 145 +/P 2860 0 R +/Pg 21 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2228 0 obj +<< +/K 18 +/P 2861 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2229 0 obj +<< +/K 19 +/P 2862 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2230 0 obj +<< +/K 20 +/P 2863 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2231 0 obj +<< +/K 21 +/P 2864 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2232 0 obj +<< +/K 22 +/P 2865 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2233 0 obj +<< +/K 23 +/P 2866 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2234 0 obj +<< +/K 24 +/P 2867 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2235 0 obj +<< +/K 25 +/P 2868 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2236 0 obj +<< +/K 26 +/P 2869 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2237 0 obj +<< +/K 27 +/P 2870 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2238 0 obj +<< +/K 28 +/P 2871 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2239 0 obj +<< +/K 29 +/P 2872 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2240 0 obj +<< +/K 31 +/P 304 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2241 0 obj +<< +/K 32 +/P 305 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2242 0 obj +<< +/K 33 +/P 2873 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2243 0 obj +<< +/K 34 +/P 2874 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2244 0 obj +<< +/K 35 +/P 2875 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2245 0 obj +<< +/K 36 +/P 2876 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2246 0 obj +<< +/K 37 +/P 2877 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2247 0 obj +<< +/K 38 +/P 2878 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2248 0 obj +<< +/K 39 +/P 2879 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2249 0 obj +<< +/K 40 +/P 2880 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2250 0 obj +<< +/K 43 +/P 825 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2251 0 obj +<< +/K 45 +/P 827 0 R +/Pg 22 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2252 0 obj +<< +/K 3 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2253 0 obj +<< +/K 4 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2254 0 obj +<< +/K 5 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2255 0 obj +<< +/K 6 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2256 0 obj +<< +/K 7 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2257 0 obj +<< +/K 8 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2258 0 obj +<< +/K 9 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2259 0 obj +<< +/K 10 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2260 0 obj +<< +/K 11 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2261 0 obj +<< +/K 12 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2262 0 obj +<< +/K 13 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2263 0 obj +<< +/K 14 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2264 0 obj +<< +/K 15 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2265 0 obj +<< +/K 16 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2266 0 obj +<< +/K 17 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2267 0 obj +<< +/K 18 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2268 0 obj +<< +/K 19 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2269 0 obj +<< +/K 20 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2270 0 obj +<< +/K 21 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2271 0 obj +<< +/K 22 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2272 0 obj +<< +/K 23 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2273 0 obj +<< +/K 24 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2274 0 obj +<< +/K 25 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2275 0 obj +<< +/K 26 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2276 0 obj +<< +/K 27 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2277 0 obj +<< +/K 28 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2278 0 obj +<< +/K 29 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2279 0 obj +<< +/K 30 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2280 0 obj +<< +/K 31 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2281 0 obj +<< +/K 32 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2282 0 obj +<< +/K 33 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2283 0 obj +<< +/K 34 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2284 0 obj +<< +/K 35 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2285 0 obj +<< +/K 36 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2286 0 obj +<< +/K 37 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2287 0 obj +<< +/K 38 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2288 0 obj +<< +/K 39 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2289 0 obj +<< +/K 40 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2290 0 obj +<< +/K 41 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2291 0 obj +<< +/K 42 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2292 0 obj +<< +/K 43 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2293 0 obj +<< +/K 44 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2294 0 obj +<< +/K 45 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2295 0 obj +<< +/K 46 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2296 0 obj +<< +/K 47 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2297 0 obj +<< +/K 48 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2298 0 obj +<< +/K 49 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2299 0 obj +<< +/K 50 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2300 0 obj +<< +/K 51 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2301 0 obj +<< +/K 52 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2302 0 obj +<< +/K 53 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2303 0 obj +<< +/K 54 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2304 0 obj +<< +/K 55 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2305 0 obj +<< +/K 56 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2306 0 obj +<< +/K 57 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2307 0 obj +<< +/K 58 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2308 0 obj +<< +/K 59 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2309 0 obj +<< +/K 60 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2310 0 obj +<< +/K 61 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2311 0 obj +<< +/K 62 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2312 0 obj +<< +/K 63 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2313 0 obj +<< +/K 64 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2314 0 obj +<< +/K 65 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2315 0 obj +<< +/K 66 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2316 0 obj +<< +/K 67 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2317 0 obj +<< +/K 68 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2318 0 obj +<< +/K 69 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2319 0 obj +<< +/K 70 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2320 0 obj +<< +/K 71 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2321 0 obj +<< +/K 72 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2322 0 obj +<< +/K 73 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2323 0 obj +<< +/K 74 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2324 0 obj +<< +/K 75 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2325 0 obj +<< +/K 76 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2326 0 obj +<< +/K 77 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2327 0 obj +<< +/K 78 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2328 0 obj +<< +/K 79 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2329 0 obj +<< +/K 80 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2330 0 obj +<< +/K 81 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2331 0 obj +<< +/K 82 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2332 0 obj +<< +/K 83 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2333 0 obj +<< +/K 84 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2334 0 obj +<< +/K 85 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2335 0 obj +<< +/K 86 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2336 0 obj +<< +/K 87 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2337 0 obj +<< +/K 88 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2338 0 obj +<< +/K 89 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2339 0 obj +<< +/K 90 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2340 0 obj +<< +/K 91 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2341 0 obj +<< +/K 92 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2342 0 obj +<< +/K 93 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2343 0 obj +<< +/K 94 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2344 0 obj +<< +/K 95 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2345 0 obj +<< +/K 96 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2346 0 obj +<< +/K 97 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2347 0 obj +<< +/K 98 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2348 0 obj +<< +/K 99 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2349 0 obj +<< +/K 100 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2350 0 obj +<< +/K 101 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2351 0 obj +<< +/K 102 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2352 0 obj +<< +/K 103 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2353 0 obj +<< +/K 104 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2354 0 obj +<< +/K 105 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2355 0 obj +<< +/K 106 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2356 0 obj +<< +/K 107 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2357 0 obj +<< +/K 108 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2358 0 obj +<< +/K 109 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2359 0 obj +<< +/K 110 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2360 0 obj +<< +/K 111 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2361 0 obj +<< +/K 112 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2362 0 obj +<< +/K 113 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2363 0 obj +<< +/K 114 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2364 0 obj +<< +/K 115 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2365 0 obj +<< +/K 116 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2366 0 obj +<< +/K 117 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2367 0 obj +<< +/K 118 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2368 0 obj +<< +/K 119 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2369 0 obj +<< +/K 120 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2370 0 obj +<< +/K 121 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2371 0 obj +<< +/K 122 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2372 0 obj +<< +/K 123 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2373 0 obj +<< +/K 124 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2374 0 obj +<< +/K 125 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2375 0 obj +<< +/K 126 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2376 0 obj +<< +/K 127 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2377 0 obj +<< +/K 128 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2378 0 obj +<< +/K 129 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2379 0 obj +<< +/K 130 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2380 0 obj +<< +/K 131 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2381 0 obj +<< +/K 132 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2382 0 obj +<< +/K 133 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2383 0 obj +<< +/K 134 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2384 0 obj +<< +/K 135 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2385 0 obj +<< +/K 136 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2386 0 obj +<< +/K 137 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2387 0 obj +<< +/K 138 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2388 0 obj +<< +/K 139 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2389 0 obj +<< +/K 140 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2390 0 obj +<< +/K 141 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2391 0 obj +<< +/K 142 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2392 0 obj +<< +/K 143 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2393 0 obj +<< +/K 144 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2394 0 obj +<< +/K 145 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2395 0 obj +<< +/K 146 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2396 0 obj +<< +/K 147 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2397 0 obj +<< +/K 148 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2398 0 obj +<< +/K 149 +/P 829 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2399 0 obj +<< +/K 151 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2400 0 obj +<< +/K 152 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2401 0 obj +<< +/K 153 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2402 0 obj +<< +/K 154 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2403 0 obj +<< +/K 155 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2404 0 obj +<< +/K 156 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2405 0 obj +<< +/K 157 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2406 0 obj +<< +/K 158 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2407 0 obj +<< +/K 159 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2408 0 obj +<< +/K 160 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2409 0 obj +<< +/K 161 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2410 0 obj +<< +/K 162 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2411 0 obj +<< +/K 163 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2412 0 obj +<< +/K 164 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2413 0 obj +<< +/K 165 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2414 0 obj +<< +/K 166 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2415 0 obj +<< +/K 167 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2416 0 obj +<< +/K 168 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2417 0 obj +<< +/K 169 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2418 0 obj +<< +/K 170 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2419 0 obj +<< +/K 171 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2420 0 obj +<< +/K 172 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2421 0 obj +<< +/K 173 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2422 0 obj +<< +/K 174 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2423 0 obj +<< +/K 175 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2424 0 obj +<< +/K 176 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2425 0 obj +<< +/K 177 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2426 0 obj +<< +/K 178 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2427 0 obj +<< +/K 179 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2428 0 obj +<< +/K 180 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2429 0 obj +<< +/K 181 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2430 0 obj +<< +/K 182 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2431 0 obj +<< +/K 183 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2432 0 obj +<< +/K 184 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2433 0 obj +<< +/K 185 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2434 0 obj +<< +/K 186 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2435 0 obj +<< +/K 187 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2436 0 obj +<< +/K 188 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2437 0 obj +<< +/K 189 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2438 0 obj +<< +/K 190 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2439 0 obj +<< +/K 191 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2440 0 obj +<< +/K 192 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2441 0 obj +<< +/K 193 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2442 0 obj +<< +/K 194 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2443 0 obj +<< +/K 195 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2444 0 obj +<< +/K 196 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2445 0 obj +<< +/K 197 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2446 0 obj +<< +/K 198 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2447 0 obj +<< +/K 199 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2448 0 obj +<< +/K 200 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2449 0 obj +<< +/K 201 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2450 0 obj +<< +/K 202 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2451 0 obj +<< +/K 203 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2452 0 obj +<< +/K 204 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2453 0 obj +<< +/K 205 +/P 831 0 R +/Pg 23 0 R +/S /NonStruct +/Type /StructElem +>> +endobj +2454 0 obj +<< +/BBox [51.933987 682.937256 147.702927 692.912842] +/Filter /FlateDecode +/Group << +/I false +/K false +/S /Transparency +>> +/Length 28 +/Matrix [1 0 0 1 -51.933987 -682.937256] +/Resources << +/ExtGState << +/GS0 2939 0 R +>> +/XObject << +/Fm0 2940 0 R +>> +>> +/Subtype /Form +/Type /XObject +>> +stream +xw6PH/V(w5Pp +5V +endstream +endobj +2455 0 obj +<< +/BBox [147.848251 682.937256 215.557983 692.912842] +/Filter /FlateDecode +/Group << +/I false +/K false +/S /Transparency +>> +/Length 28 +/Matrix [1 0 0 1 -147.848251 -682.937256] +/Resources << +/ExtGState << +/GS0 2941 0 R +>> +/XObject << +/Fm0 2942 0 R +>> +>> +/Subtype /Form +/Type /XObject +>> +stream +xw6PH/V(w5Pp +5V +endstream +endobj +2456 0 obj +<< +/BaseFont /AAAAAA+MalgunGothicBold +/CIDSystemInfo << +/Ordering (Identity) +/Registry (Adobe) +/Supplement 0 +>> +/CIDToGIDMap /Identity +/DW 1000 +/FontDescriptor 2943 0 R +/Subtype /CIDFontType2 +/Type /Font +/W [0 [662.59766 0 0 351.5625 0 607.91016] 10 11 357.91016 13 [719.23828 261.71875 413.57422 261.71875 438.96484] 18 27 579.58984 28 [261.71875] 35 [703.61328 637.20703 638.67188 745.60547 538.57422 524.41406 722.16797 769.53125 310.05859 0 645.01953 512.20703 964.35547 797.85156 776.36719 614.74609 +776.36719 653.80859 565.91797 582.51953 730.95703 670.89844 1009.76563 653.32031 606.44531] 65 [425.78125 0 542.96875 626.46484 487.30469 625.97656 549.80469 372.55859 625.97656 606.93359 274.41406 279.29688 555.17578 274.41406 923.33984 608.39844 +619.62891 626.46484 0 393.55469 461.91406 384.27734 608.39844 536.62109 795.41016 538.57422 535.64453] +96 [719.23828] 283 [1025.87891]] +>> +endobj +2457 0 obj +<< +/Filter /FlateDecode +/Length 1404 +>> +stream +x]n9z>&@V \fx˂? rO,b{_t^mz>M_ygx:ׇ>vwwӴk{9߮ߦeq=ne>~^.n6~:nϻ}6q;No>ǟl 6v/Ot~vw""ݺn;Y7"~I ȯ t2OwiN&͠rf%REJD-قkٓ\p,^rBƵՓJ_hi³ +UAF;-: 5P$q_N3[{|43זbv~99${B@7Whq!U%+Cb(Sgt1ؖ@g8b z>q9fj)+"~ ސV!-$Т62(P1$O-Ұ`/)KԀ;]*!NqǂpsWn0\caIVz<4B ^l̨&%u}6zi&Sp*9um=ʹ٬p1&WxfY/#Rs!<+1> +/CIDToGIDMap /Identity +/DW 1000 +/FontDescriptor 2944 0 R +/Subtype /CIDFontType2 +/Type /Font +/W [0 [662.59766 0 0 351.5625 289.0625 395.01953 606.44531 0 0 817.87109 0 304.6875 304.6875 0 700.68359 218.75 +410.15625 218.75 395.99609] 19 28 550.78125 29 [218.75 0 0 700.68359 0 459.96094 0 658.20313 583.49609 634.76563 717.28516 517.08984 498.53516 701.66016 724.60938 270.01953 +359.86328 590.33203 479.98047 916.99219 765.13672 773.4375 570.80078 773.4375 609.86328 542.96875 533.69141 702.63672 634.27734 953.61328 601.07422] 66 [425.78125 0 520.01953 600.58594 472.65625 602.05078 535.15625 316.40625 602.05078 578.61328 246.09375 246.09375 505.85938 246.09375 879.88281 578.125 +599.12109 600.58594 602.05078 353.51563 433.10547 344.72656 578.125 487.30469 736.32813 464.84375 492.67578 461.91406 0 0 0 700.68359] 280 [1025.87891] 336 [700.68359] 539 [589.84375] 549 +551 950.19531] +>> +endobj +2459 0 obj +<< +/Filter /FlateDecode +/Length 1795 +>> +stream +xen9u>4D&w@%a@V=%,?N9X%F]׏?oo/Orۿ}O.$}~Ƿ|zyz^_οџ~==}u~|?ߞu?io?xϋآeߞ_ӽ1}~Mޘ%>m"(ZQZ6?c( erpe}KڍVD ABE-Ո2q^D} +ґee@ Vn9aqxi2W>n4sF s-C JC]+ٰz`_9lo@K3)Ջ*j/Q#lNm! +*/Z[6}B. B:A4)CKST K/)ǭR!N~*Vӛ (VRKX >{K(8Y!8N$%wdfBԾ&ie\RN(ywKsH!BFJG|TZVP8aY$:iSYc{h.B B[G榸nۜ}n2+WmQ޺ ܉h" u)DR@#zeXɩY"ѱ'Y72+CX +Jn}5hu@~RXͮaC7 + *~uv¾-B d,ԡ "b<þI b%B9tYsʛP%R\DyMzz2:u` be/P ONn6VInڗ sۤ +IJ֋ӣN˜ 4|"IFY#e| [|kXIdߠӉ}Xf(/q3K;JӢ$I2Ӵ(E)\Rg󈳜us+D"Dzzx5sE +47Iն lNDHb@ +51/"oYl(Rl<DE)AҥN--zM+X۹͢7l(;ҥ`(#BJ낞}=|"ǿBqYqCuP\V޲IԨFGoR7T*U.97D^IEDPW52ì:vFO8F'sevjNꢦEz.  MS;aesМJGծ B>Ik7}><#Mӛ"7ID dm 1EfdCj 2p[g QڂR9*#/qGLDmn0qZ8-RqZDLÈ zD#Afg`Ѡ`g\QcOƠ0[ũQUDKf3iv R ? 5q}L4@lRD؞Ar1DQ W;>{9W f޵4W7-"ru,:A}l 2A9$w UW)Bi,M>hS-3 YWYTWâ42B i|;\'^߈a_?C~9~y~: ~ +endstream +endobj +2460 0 obj +<< +/Filter /FlateDecode +/Length 84 +>> +stream +xU;0 C ԡSA6xXnS `qV$o=x>[|y;C.~ +endstream +endobj +2461 0 obj +<< +/Length 35 +>> +stream +2812 0 d0 +1 0 0 1 0 0 cm +/XgF4C Do + +endstream +endobj +2462 0 obj +<< +/Length 35 +>> +stream +2812 0 d0 +1 0 0 1 0 0 cm +/XgF7C Do + +endstream +endobj +2463 0 obj +<< +/Length 35 +>> +stream +2812 0 d0 +1 0 0 1 0 0 cm +/XgFA2 Do + +endstream +endobj +2464 0 obj +<< +/CapHeight 1434 +/Flags 4 +/FontFamily (Segoe UI Emoji) +/FontName /CAAAAA+SegoeUIEmoji +/FontStretch /Normal +/FontWeight 400 +/ItalicAngle 0 +/StemV 109 +/Type /FontDescriptor +/XHeight 1024 +>> +endobj +2465 0 obj +<< +/BBox [0 0 2091 1804] +/Filter /FlateDecode +/Group << +/I true +/S /Transparency +/Type /Group +>> +/Length 851 +/Matrix [1 0 0 1 369 -1517] +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Pattern << +/P2917 2945 0 R +/P2922 2946 0 R +/P2927 2947 0 R +/P2932 2948 0 R +/P2937 2949 0 R +/P2942 2950 0 R +/P2947 2951 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +xUnI +ߏ؁}>;H}؎d{kIYUynE@ +/_gxje +Q*wBn 5J36I4JnQȭ15O;,XaL%(2*}ީ ikĶg$ ZU9ꗯr}Lͳ*-:=BCqvȝ٫{el,f90+f6 + u {3]VlW_bo;^ڹzj81 +endstream +endobj +2466 0 obj +<< +/BBox [0 0 2050 2050] +/Filter /FlateDecode +/Group << +/I true +/S /Transparency +/Type /Group +>> +/Length 749 +/Matrix [1 0 0 1 369 -1763] +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Pattern << +/P2950 2952 0 R +/P2955 2953 0 R +/P2960 2954 0 R +/P2965 2955 0 R +/P2970 2956 0 R +/P2975 2957 0 R +/P2980 2958 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +xTnFSjޏڅ؅$@RdAΞyۂhi^axYX"+PyQPi@BsW(n␾[Ĵvru!Fܘ9'8T쁢m8_(s~i Np7,+F^Q"7a(sB1RteWTt|G *cTRBկz11mh\+oD.ucH_?>§o~<~2o~߬uy,+@F9_O)퐲R>|Rc+O)ߵV>|Rc+ǹO)ߵV>|Rc+ʿ[0?jƒx /KLVZ@g9C6ps6xhXA/KsbA3<4BpAblRQ(B !u>wPOY:NlQU|If5Btu" +(:YfO҈K!fdwP*U))NhTp+bv-EQE.W +endstream +endobj +2467 0 obj +<< +/BBox [0 0 2091 2091] +/Filter /FlateDecode +/Group << +/I true +/S /Transparency +/Type /Group +>> +/Length 720 +/Matrix [1 0 0 1 369 -1763] +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Pattern << +/P2983 2959 0 R +/P2988 2960 0 R +/P2993 2961 0 R +/P2998 2962 0 R +/P3003 2963 0 R +/P3008 2964 0 R +/P3013 2965 0 R +/P3018 2966 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +x헹0 @{}C:E`-R&)& D&u`DD| !(-eSQK@ǺTKdK{@(7*yh|,"9-k1IKD2 ٴ#whUΖTass AN->eSV#eڲi#o{7T" q:\%-BVFl'jZ"VJ)+-)-/iˮ8 N`곁i4p) `i4p8 Jhುi4p- p賁i4p/ l2痐 +endstream +endobj +2468 0 obj +<< +/Filter /FlateDecode +/Length 244 +>> +stream +x]Pj0W19n B@>+%!}RaYvf]&Iy}`Z;oMaNyTu&թ]L}' niޓl9g@:鑐NYewkMk,MQJYyopUt (7OJ) ǺGY> +/CIDToGIDMap /Identity +/DW 0 +/FontDescriptor 2967 0 R +/Subtype /CIDFontType2 +/Type /Font +/W [0 869 549.80469] +>> +endobj +2470 0 obj +<< +/Filter /FlateDecode +/Length 414 +>> +stream +x]n@}LJɆ qECRܠ6>GߓHssQ57&ϳ<ݖI2;q ĿuXETwMmtye)e.mt=藟"YD}]?JnJT,ǰ$#{&rۼ=^4݌DuBTJJm۶ 7g7Ncn+Y*eT%J2%f# +z5Liٖ)K` 3JL9<crSl9(ЙL"+DfR4^,+a! W0G`P!mW0@ j *hnJASOnK +ï gҲ :11f0mx#=gG_˺{%9 +endstream +endobj +2471 0 obj +<< +/BaseFont /EAAAAA+GulimChe +/CIDSystemInfo << +/Ordering (Identity) +/Registry (Adobe) +/Supplement 0 +>> +/CIDToGIDMap /Identity +/DW 1000 +/FontDescriptor 2968 0 R +/Subtype /CIDFontType2 +/Type /Font +>> +endobj +2472 0 obj +<< +/Filter /FlateDecode +/Length 952 +>> +stream +x]n9E^&@|6I@@@|,=-AUL6pt.VZvu帟y98OyYi3zֲ[/f_1|ʧyvoe]W:/A4?up;|],}\59^Npoe^mRj;lZkmoV~OFW&RN^2@"iPNEvKvæh:ֵbӤʊEeEY?HjyDqQF@UHsFAM",e,H!!f2&hBO A#*|1 _Ɠ*=t 22 -yJTWQbGeerVPYTZfXJYYW> +/CIDToGIDMap /Identity +/DW 1000 +/FontDescriptor 2969 0 R +/Subtype /CIDFontType2 +/Type /Font +/W [0 [662.59766 0 0 351.5625] 43 [310.05859] 54 [582.51953 0 0 1009.76563]] +>> +endobj +2474 0 obj +<< +/Filter /FlateDecode +/Length 354 +>> +stream +x]K0{~C1>R$q VǮe҅=(|da&iN7-z';87#> +stream +xeM09p&H}:zmF&~ 2t@XP0_v8L-%`rb੭ᰬV.`" @V9E +,b-y?Y\<^Z֛Y8D,`ZFF *?%^ŁWi6Ռ?·"6me> ֆm1 +endstream +endobj +2476 0 obj +<< +/Length 35 +>> +stream +2812 0 d0 +1 0 0 1 0 0 cm +/XgF4C Do + +endstream +endobj +2477 0 obj +<< +/CapHeight 1434 +/Flags 4 +/FontFamily (Segoe UI Emoji) +/FontName /GAAAAA+SegoeUIEmoji +/FontStretch /Normal +/FontWeight 400 +/ItalicAngle 0 +/StemV 109 +/Type /FontDescriptor +/XHeight 1024 +>> +endobj +2478 0 obj +<< +/BBox [0 0 2091 1804] +/Filter /FlateDecode +/Group << +/I true +/S /Transparency +/Type /Group +>> +/Length 851 +/Matrix [1 0 0 1 369 -1517] +/Resources << +/ExtGState << +/G3 224 0 R +>> +/Pattern << +/P2917 2945 0 R +/P2922 2946 0 R +/P2927 2947 0 R +/P2932 2948 0 R +/P2937 2949 0 R +/P2942 2950 0 R +/P2947 2951 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +xUnI +ߏ؁}>;H}؎d{kIYUynE@ +/_gxje +Q*wBn 5J36I4JnQȭ15O;,XaL%(2*}ީ ikĶg$ ZU9ꗯr}Lͳ*-:=BCqvȝ٫{el,f90+f6 + u {3]VlW_bo;^ڹzj81 +endstream +endobj +2479 0 obj +<< +/Filter /FlateDecode +/Length 227 +>> +stream +x]Pj0 +tli;@Raݘpl%5,qC~  CKuQ3 'pK=رmPv2q.z3N89vgz3&O#RK8!ehXׁÁqfL!e]?ڊnlp8Gc1@\Crv$&NT6-i.)!Z(=C1Ģ*n +endstream +endobj +2480 0 obj +<< +/BaseFont /HAAAAA+Consolas-Bold +/CIDSystemInfo << +/Ordering (Identity) +/Registry (Adobe) +/Supplement 0 +>> +/CIDToGIDMap /Identity +/DW 0 +/FontDescriptor 2970 0 R +/Subtype /CIDFontType2 +/Type /Font +/W [0 591 549.80469] +>> +endobj +2481 0 obj +<< +/Filter /FlateDecode +/Length 295 +>> +stream +x]j0 ~ +Cm +!Х ?,8!o?lu`OOx՜=7=(tsኃ6,IAio9v9qlL?8ٻVG5]qS`u5ox,AaxٷnD1m(4^es?yi䄺v]gdBPu] k/:yVB!.- Qi/Hd[EJ2H[Wz,%u#)){uRVcfw& >h'J +endstream +endobj +2482 0 obj +<< +/K 832 0 R +/P 307 0 R +/S /Strong +/Type /StructElem +>> +endobj +2483 0 obj +<< +/K 834 0 R +/P 307 0 R +/S /Strong +/Type /StructElem +>> +endobj +2484 0 obj +<< +/K 836 0 R +/P 307 0 R +/S /Strong +/Type /StructElem +>> +endobj +2485 0 obj +<< +/K 838 0 R +/P 307 0 R +/S /Strong +/Type /StructElem +>> +endobj +2486 0 obj +<< +/K 841 0 R +/P 309 0 R +/S /Link +/Type /StructElem +>> +endobj +2487 0 obj +<< +/K 843 0 R +/P 310 0 R +/S /Link +/Type /StructElem +>> +endobj +2488 0 obj +<< +/K 845 0 R +/P 311 0 R +/S /Link +/Type /StructElem +>> +endobj +2489 0 obj +<< +/K 847 0 R +/P 312 0 R +/S /Link +/Type /StructElem +>> +endobj +2490 0 obj +<< +/K 849 0 R +/P 313 0 R +/S /Link +/Type /StructElem +>> +endobj +2491 0 obj +<< +/K 851 0 R +/P 314 0 R +/S /Link +/Type /StructElem +>> +endobj +2492 0 obj +<< +/K 853 0 R +/P 315 0 R +/S /Link +/Type /StructElem +>> +endobj +2493 0 obj +<< +/K 855 0 R +/P 316 0 R +/S /Link +/Type /StructElem +>> +endobj +2494 0 obj +<< +/A [<< +/Headers [(node00001886)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 872 0 R +/P 344 0 R +/S /TD +/Type /StructElem +>> +endobj +2495 0 obj +<< +/A [<< +/Headers [(node00001887)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 874 0 R +/P 344 0 R +/S /TD +/Type /StructElem +>> +endobj +2496 0 obj +<< +/A [<< +/Headers [(node00001888)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 875 0 R +/P 344 0 R +/S /TD +/Type /StructElem +>> +endobj +2497 0 obj +<< +/A [<< +/Headers [(node00001889)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2881 0 R +/P 344 0 R +/S /TD +/Type /StructElem +>> +endobj +2498 0 obj +<< +/A [<< +/Headers [(node00001890)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 877 0 R +/P 344 0 R +/S /TD +/Type /StructElem +>> +endobj +2499 0 obj +<< +/A [<< +/Headers [(node00001886)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 878 0 R +/P 345 0 R +/S /TD +/Type /StructElem +>> +endobj +2500 0 obj +<< +/A [<< +/Headers [(node00001887)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 880 0 R +/P 345 0 R +/S /TD +/Type /StructElem +>> +endobj +2501 0 obj +<< +/A [<< +/Headers [(node00001888)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 881 0 R +/P 345 0 R +/S /TD +/Type /StructElem +>> +endobj +2502 0 obj +<< +/A [<< +/Headers [(node00001889)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2882 0 R +/P 345 0 R +/S /TD +/Type /StructElem +>> +endobj +2503 0 obj +<< +/A [<< +/Headers [(node00001890)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 883 0 R +/P 345 0 R +/S /TD +/Type /StructElem +>> +endobj +2504 0 obj +<< +/A [<< +/Headers [(node00001886)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 884 0 R +/P 346 0 R +/S /TD +/Type /StructElem +>> +endobj +2505 0 obj +<< +/A [<< +/Headers [(node00001887)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 886 0 R +/P 346 0 R +/S /TD +/Type /StructElem +>> +endobj +2506 0 obj +<< +/A [<< +/Headers [(node00001888)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 887 0 R +/P 346 0 R +/S /TD +/Type /StructElem +>> +endobj +2507 0 obj +<< +/A [<< +/Headers [(node00001889)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2883 0 R +/P 346 0 R +/S /TD +/Type /StructElem +>> +endobj +2508 0 obj +<< +/A [<< +/Headers [(node00001890)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 889 0 R +/P 346 0 R +/S /TD +/Type /StructElem +>> +endobj +2509 0 obj +<< +/A [<< +/Headers [(node00001886)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 890 0 R +/P 347 0 R +/S /TD +/Type /StructElem +>> +endobj +2510 0 obj +<< +/A [<< +/Headers [(node00001887)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 892 0 R +/P 347 0 R +/S /TD +/Type /StructElem +>> +endobj +2511 0 obj +<< +/A [<< +/Headers [(node00001888)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 893 0 R +/P 347 0 R +/S /TD +/Type /StructElem +>> +endobj +2512 0 obj +<< +/A [<< +/Headers [(node00001889)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2884 0 R +/P 347 0 R +/S /TD +/Type /StructElem +>> +endobj +2513 0 obj +<< +/A [<< +/Headers [(node00001890)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 895 0 R +/P 347 0 R +/S /TD +/Type /StructElem +>> +endobj +2514 0 obj +<< +/A [<< +/Headers [(node00001886)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 896 0 R +/P 348 0 R +/S /TD +/Type /StructElem +>> +endobj +2515 0 obj +<< +/A [<< +/Headers [(node00001887)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 898 0 R +/P 348 0 R +/S /TD +/Type /StructElem +>> +endobj +2516 0 obj +<< +/A [<< +/Headers [(node00001888)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 899 0 R +/P 348 0 R +/S /TD +/Type /StructElem +>> +endobj +2517 0 obj +<< +/A [<< +/Headers [(node00001889)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2885 0 R +/P 348 0 R +/S /TD +/Type /StructElem +>> +endobj +2518 0 obj +<< +/A [<< +/Headers [(node00001890)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 901 0 R +/P 348 0 R +/S /TD +/Type /StructElem +>> +endobj +2519 0 obj +<< +/A [<< +/Headers [(node00001886)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 902 0 R +/P 349 0 R +/S /TD +/Type /StructElem +>> +endobj +2520 0 obj +<< +/A [<< +/Headers [(node00001887)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 904 0 R +/P 349 0 R +/S /TD +/Type /StructElem +>> +endobj +2521 0 obj +<< +/A [<< +/Headers [(node00001888)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 905 0 R +/P 349 0 R +/S /TD +/Type /StructElem +>> +endobj +2522 0 obj +<< +/A [<< +/Headers [(node00001889)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2886 0 R +/P 349 0 R +/S /TD +/Type /StructElem +>> +endobj +2523 0 obj +<< +/A [<< +/Headers [(node00001890)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 907 0 R +/P 349 0 R +/S /TD +/Type /StructElem +>> +endobj +2524 0 obj +<< +/A [<< +/Headers [(node00001944)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 912 0 R +/P 352 0 R +/S /TD +/Type /StructElem +>> +endobj +2525 0 obj +<< +/A [<< +/Headers [(node00001945)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 914 0 R +/P 352 0 R +/S /TD +/Type /StructElem +>> +endobj +2526 0 obj +<< +/A [<< +/Headers [(node00001946)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2887 0 R +/P 352 0 R +/S /TD +/Type /StructElem +>> +endobj +2527 0 obj +<< +/A [<< +/Headers [(node00001947)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 916 0 R +/P 352 0 R +/S /TD +/Type /StructElem +>> +endobj +2528 0 obj +<< +/A [<< +/Headers [(node00001944)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 917 0 R +/P 353 0 R +/S /TD +/Type /StructElem +>> +endobj +2529 0 obj +<< +/A [<< +/Headers [(node00001945)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 919 0 R +/P 353 0 R +/S /TD +/Type /StructElem +>> +endobj +2530 0 obj +<< +/A [<< +/Headers [(node00001946)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2888 0 R +/P 353 0 R +/S /TD +/Type /StructElem +>> +endobj +2531 0 obj +<< +/A [<< +/Headers [(node00001947)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 921 0 R +/P 353 0 R +/S /TD +/Type /StructElem +>> +endobj +2532 0 obj +<< +/A [<< +/Headers [(node00001944)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 922 0 R +/P 354 0 R +/S /TD +/Type /StructElem +>> +endobj +2533 0 obj +<< +/A [<< +/Headers [(node00001945)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 924 0 R +/P 354 0 R +/S /TD +/Type /StructElem +>> +endobj +2534 0 obj +<< +/A [<< +/Headers [(node00001946)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2889 0 R +/P 354 0 R +/S /TD +/Type /StructElem +>> +endobj +2535 0 obj +<< +/A [<< +/Headers [(node00001947)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 926 0 R +/P 354 0 R +/S /TD +/Type /StructElem +>> +endobj +2536 0 obj +<< +/A [<< +/Headers [(node00001944)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 927 0 R +/P 355 0 R +/S /TD +/Type /StructElem +>> +endobj +2537 0 obj +<< +/A [<< +/Headers [(node00001945)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 929 0 R +/P 355 0 R +/S /TD +/Type /StructElem +>> +endobj +2538 0 obj +<< +/A [<< +/Headers [(node00001946)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2890 0 R +/P 355 0 R +/S /TD +/Type /StructElem +>> +endobj +2539 0 obj +<< +/A [<< +/Headers [(node00001947)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 931 0 R +/P 355 0 R +/S /TD +/Type /StructElem +>> +endobj +2540 0 obj +<< +/A [<< +/Headers [(node00001944)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 932 0 R +/P 356 0 R +/S /TD +/Type /StructElem +>> +endobj +2541 0 obj +<< +/A [<< +/Headers [(node00001945)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 934 0 R +/P 356 0 R +/S /TD +/Type /StructElem +>> +endobj +2542 0 obj +<< +/A [<< +/Headers [(node00001946)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2891 0 R +/P 356 0 R +/S /TD +/Type /StructElem +>> +endobj +2543 0 obj +<< +/A [<< +/Headers [(node00001947)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 936 0 R +/P 356 0 R +/S /TD +/Type /StructElem +>> +endobj +2544 0 obj +<< +/A [<< +/Headers [(node00001944)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 937 0 R +/P 357 0 R +/S /TD +/Type /StructElem +>> +endobj +2545 0 obj +<< +/A [<< +/Headers [(node00001945)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 939 0 R +/P 357 0 R +/S /TD +/Type /StructElem +>> +endobj +2546 0 obj +<< +/A [<< +/Headers [(node00001946)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2892 0 R +/P 357 0 R +/S /TD +/Type /StructElem +>> +endobj +2547 0 obj +<< +/A [<< +/Headers [(node00001947)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 941 0 R +/P 357 0 R +/S /TD +/Type /StructElem +>> +endobj +2548 0 obj +<< +/A [<< +/Headers [(node00001944)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 942 0 R +/P 358 0 R +/S /TD +/Type /StructElem +>> +endobj +2549 0 obj +<< +/A [<< +/Headers [(node00001945)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 944 0 R +/P 358 0 R +/S /TD +/Type /StructElem +>> +endobj +2550 0 obj +<< +/A [<< +/Headers [(node00001946)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2893 0 R +/P 358 0 R +/S /TD +/Type /StructElem +>> +endobj +2551 0 obj +<< +/A [<< +/Headers [(node00001947)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 946 0 R +/P 358 0 R +/S /TD +/Type /StructElem +>> +endobj +2552 0 obj +<< +/A [<< +/Headers [(node00001944)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 947 0 R +/P 359 0 R +/S /TD +/Type /StructElem +>> +endobj +2553 0 obj +<< +/A [<< +/Headers [(node00001945)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 949 0 R +/P 359 0 R +/S /TD +/Type /StructElem +>> +endobj +2554 0 obj +<< +/A [<< +/Headers [(node00001946)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2894 0 R +/P 359 0 R +/S /TD +/Type /StructElem +>> +endobj +2555 0 obj +<< +/A [<< +/Headers [(node00001947)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 951 0 R +/P 359 0 R +/S /TD +/Type /StructElem +>> +endobj +2556 0 obj +<< +/A [<< +/Headers [(node00001944)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 952 0 R +/P 360 0 R +/S /TD +/Type /StructElem +>> +endobj +2557 0 obj +<< +/A [<< +/Headers [(node00001945)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 954 0 R +/P 360 0 R +/S /TD +/Type /StructElem +>> +endobj +2558 0 obj +<< +/A [<< +/Headers [(node00001946)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2895 0 R +/P 360 0 R +/S /TD +/Type /StructElem +>> +endobj +2559 0 obj +<< +/A [<< +/Headers [(node00001947)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 956 0 R +/P 360 0 R +/S /TD +/Type /StructElem +>> +endobj +2560 0 obj +<< +/A [<< +/Headers [(node00001944)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 957 0 R +/P 361 0 R +/S /TD +/Type /StructElem +>> +endobj +2561 0 obj +<< +/A [<< +/Headers [(node00001945)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 959 0 R +/P 361 0 R +/S /TD +/Type /StructElem +>> +endobj +2562 0 obj +<< +/A [<< +/Headers [(node00001946)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2896 0 R +/P 361 0 R +/S /TD +/Type /StructElem +>> +endobj +2563 0 obj +<< +/A [<< +/Headers [(node00001947)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 961 0 R +/P 361 0 R +/S /TD +/Type /StructElem +>> +endobj +2564 0 obj +<< +/A [<< +/Headers [(node00002266)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1203 0 R 1205 0 R] +/P 383 0 R +/S /TD +/Type /StructElem +>> +endobj +2565 0 obj +<< +/A [<< +/Headers [(node00002267)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1206 0 R +/P 383 0 R +/S /TD +/Type /StructElem +>> +endobj +2566 0 obj +<< +/A [<< +/Headers [(node00002268)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [2897 0 R 1208 0 R] +/P 383 0 R +/S /TD +/Type /StructElem +>> +endobj +2567 0 obj +<< +/A [<< +/Headers [(node00002269)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2898 0 R +/P 383 0 R +/S /TD +/Type /StructElem +>> +endobj +2568 0 obj +<< +/A [<< +/Headers [(node00002266)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1210 0 R 1212 0 R 1213 0 R] +/P 384 0 R +/S /TD +/Type /StructElem +>> +endobj +2569 0 obj +<< +/A [<< +/Headers [(node00002267)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1215 0 R +/P 384 0 R +/S /TD +/Type /StructElem +>> +endobj +2570 0 obj +<< +/A [<< +/Headers [(node00002268)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1216 0 R +/P 384 0 R +/S /TD +/Type /StructElem +>> +endobj +2571 0 obj +<< +/A [<< +/Headers [(node00002269)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2899 0 R +/P 384 0 R +/S /TD +/Type /StructElem +>> +endobj +2572 0 obj +<< +/A [<< +/Headers [(node00002266)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1218 0 R +/P 385 0 R +/S /TD +/Type /StructElem +>> +endobj +2573 0 obj +<< +/A [<< +/Headers [(node00002267)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1220 0 R +/P 385 0 R +/S /TD +/Type /StructElem +>> +endobj +2574 0 obj +<< +/A [<< +/Headers [(node00002268)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1221 0 R +/P 385 0 R +/S /TD +/Type /StructElem +>> +endobj +2575 0 obj +<< +/A [<< +/Headers [(node00002269)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2900 0 R +/P 385 0 R +/S /TD +/Type /StructElem +>> +endobj +2576 0 obj +<< +/A [<< +/Headers [(node00002266)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1223 0 R +/P 386 0 R +/S /TD +/Type /StructElem +>> +endobj +2577 0 obj +<< +/A [<< +/Headers [(node00002267)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1225 0 R +/P 386 0 R +/S /TD +/Type /StructElem +>> +endobj +2578 0 obj +<< +/A [<< +/Headers [(node00002268)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1226 0 R +/P 386 0 R +/S /TD +/Type /StructElem +>> +endobj +2579 0 obj +<< +/A [<< +/Headers [(node00002269)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2901 0 R +/P 386 0 R +/S /TD +/Type /StructElem +>> +endobj +2580 0 obj +<< +/A [<< +/Headers [(node00002266)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1228 0 R +/P 387 0 R +/S /TD +/Type /StructElem +>> +endobj +2581 0 obj +<< +/A [<< +/Headers [(node00002267)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1230 0 R +/P 387 0 R +/S /TD +/Type /StructElem +>> +endobj +2582 0 obj +<< +/A [<< +/Headers [(node00002268)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1231 0 R +/P 387 0 R +/S /TD +/Type /StructElem +>> +endobj +2583 0 obj +<< +/A [<< +/Headers [(node00002269)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2902 0 R +/P 387 0 R +/S /TD +/Type /StructElem +>> +endobj +2584 0 obj +<< +/A [<< +/Headers [(node00002266)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1233 0 R 1235 0 R 1236 0 R] +/P 388 0 R +/S /TD +/Type /StructElem +>> +endobj +2585 0 obj +<< +/A [<< +/Headers [(node00002267)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1238 0 R +/P 388 0 R +/S /TD +/Type /StructElem +>> +endobj +2586 0 obj +<< +/A [<< +/Headers [(node00002268)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1239 0 R +/P 388 0 R +/S /TD +/Type /StructElem +>> +endobj +2587 0 obj +<< +/A [<< +/Headers [(node00002269)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2903 0 R +/P 388 0 R +/S /TD +/Type /StructElem +>> +endobj +2588 0 obj +<< +/A [<< +/Headers [(node00002266)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1241 0 R 1243 0 R 1244 0 R] +/P 389 0 R +/S /TD +/Type /StructElem +>> +endobj +2589 0 obj +<< +/A [<< +/Headers [(node00002267)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1246 0 R +/P 389 0 R +/S /TD +/Type /StructElem +>> +endobj +2590 0 obj +<< +/A [<< +/Headers [(node00002268)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1247 0 R +/P 389 0 R +/S /TD +/Type /StructElem +>> +endobj +2591 0 obj +<< +/A [<< +/Headers [(node00002269)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2904 0 R +/P 389 0 R +/S /TD +/Type /StructElem +>> +endobj +2592 0 obj +<< +/A [<< +/Headers [(node00002266)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1249 0 R 1251 0 R 1252 0 R] +/P 390 0 R +/S /TD +/Type /StructElem +>> +endobj +2593 0 obj +<< +/A [<< +/Headers [(node00002267)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1254 0 R +/P 390 0 R +/S /TD +/Type /StructElem +>> +endobj +2594 0 obj +<< +/A [<< +/Headers [(node00002268)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1255 0 R +/P 390 0 R +/S /TD +/Type /StructElem +>> +endobj +2595 0 obj +<< +/A [<< +/Headers [(node00002269)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2905 0 R +/P 390 0 R +/S /TD +/Type /StructElem +>> +endobj +2596 0 obj +<< +/K 1258 0 R +/P 392 0 R +/S /Strong +/Type /StructElem +>> +endobj +2597 0 obj +<< +/K 1261 0 R +/P 393 0 R +/S /Strong +/Type /StructElem +>> +endobj +2598 0 obj +<< +/K 1279 0 R +/P 394 0 R +/S /Strong +/Type /StructElem +>> +endobj +2599 0 obj +<< +/K 1287 0 R +/P 395 0 R +/S /Strong +/Type /StructElem +>> +endobj +2600 0 obj +<< +/K 1290 0 R +/P 396 0 R +/S /Strong +/Type /StructElem +>> +endobj +2601 0 obj +<< +/K 1293 0 R +/P 397 0 R +/S /Strong +/Type /StructElem +>> +endobj +2602 0 obj +<< +/A [<< +/Headers [(node00002359)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1301 0 R +/P 401 0 R +/S /TD +/Type /StructElem +>> +endobj +2603 0 obj +<< +/A [<< +/Headers [(node00002360)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1303 0 R +/P 401 0 R +/S /TD +/Type /StructElem +>> +endobj +2604 0 obj +<< +/A [<< +/Headers [(node00002361)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [2906 0 R 1305 0 R] +/P 401 0 R +/S /TD +/Type /StructElem +>> +endobj +2605 0 obj +<< +/A [<< +/Headers [(node00002359)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1306 0 R +/P 402 0 R +/S /TD +/Type /StructElem +>> +endobj +2606 0 obj +<< +/A [<< +/Headers [(node00002360)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1308 0 R +/P 402 0 R +/S /TD +/Type /StructElem +>> +endobj +2607 0 obj +<< +/A [<< +/Headers [(node00002361)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1309 0 R +/P 402 0 R +/S /TD +/Type /StructElem +>> +endobj +2608 0 obj +<< +/A [<< +/Headers [(node00002359)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1311 0 R +/P 403 0 R +/S /TD +/Type /StructElem +>> +endobj +2609 0 obj +<< +/A [<< +/Headers [(node00002360)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1313 0 R +/P 403 0 R +/S /TD +/Type /StructElem +>> +endobj +2610 0 obj +<< +/A [<< +/Headers [(node00002361)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1314 0 R +/P 403 0 R +/S /TD +/Type /StructElem +>> +endobj +2611 0 obj +<< +/A [<< +/Headers [(node00002359)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1316 0 R +/P 404 0 R +/S /TD +/Type /StructElem +>> +endobj +2612 0 obj +<< +/A [<< +/Headers [(node00002360)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1318 0 R +/P 404 0 R +/S /TD +/Type /StructElem +>> +endobj +2613 0 obj +<< +/A [<< +/Headers [(node00002361)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1319 0 R +/P 404 0 R +/S /TD +/Type /StructElem +>> +endobj +2614 0 obj +<< +/A [<< +/Headers [(node00002359)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1321 0 R +/P 405 0 R +/S /TD +/Type /StructElem +>> +endobj +2615 0 obj +<< +/A [<< +/Headers [(node00002360)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1323 0 R +/P 405 0 R +/S /TD +/Type /StructElem +>> +endobj +2616 0 obj +<< +/A [<< +/Headers [(node00002361)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1324 0 R +/P 405 0 R +/S /TD +/Type /StructElem +>> +endobj +2617 0 obj +<< +/A [<< +/Headers [(node00002359)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1326 0 R +/P 406 0 R +/S /TD +/Type /StructElem +>> +endobj +2618 0 obj +<< +/A [<< +/Headers [(node00002360)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1328 0 R +/P 406 0 R +/S /TD +/Type /StructElem +>> +endobj +2619 0 obj +<< +/A [<< +/Headers [(node00002361)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1329 0 R +/P 406 0 R +/S /TD +/Type /StructElem +>> +endobj +2620 0 obj +<< +/A [<< +/Headers [(node00002359)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1331 0 R +/P 407 0 R +/S /TD +/Type /StructElem +>> +endobj +2621 0 obj +<< +/A [<< +/Headers [(node00002360)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1333 0 R +/P 407 0 R +/S /TD +/Type /StructElem +>> +endobj +2622 0 obj +<< +/A [<< +/Headers [(node00002361)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1334 0 R +/P 407 0 R +/S /TD +/Type /StructElem +>> +endobj +2623 0 obj +<< +/A [<< +/Headers [(node00002359)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1336 0 R +/P 408 0 R +/S /TD +/Type /StructElem +>> +endobj +2624 0 obj +<< +/A [<< +/Headers [(node00002360)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1338 0 R +/P 408 0 R +/S /TD +/Type /StructElem +>> +endobj +2625 0 obj +<< +/A [<< +/Headers [(node00002361)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1339 0 R +/P 408 0 R +/S /TD +/Type /StructElem +>> +endobj +2626 0 obj +<< +/A [<< +/Headers [(node00002359)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1340 0 R +/P 409 0 R +/S /TD +/Type /StructElem +>> +endobj +2627 0 obj +<< +/A [<< +/Headers [(node00002360)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1342 0 R +/P 409 0 R +/S /TD +/Type /StructElem +>> +endobj +2628 0 obj +<< +/A [<< +/Headers [(node00002361)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1343 0 R +/P 409 0 R +/S /TD +/Type /StructElem +>> +endobj +2629 0 obj +<< +/A [<< +/Headers [(node00002359)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1344 0 R +/P 410 0 R +/S /TD +/Type /StructElem +>> +endobj +2630 0 obj +<< +/A [<< +/Headers [(node00002360)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1346 0 R +/P 410 0 R +/S /TD +/Type /StructElem +>> +endobj +2631 0 obj +<< +/A [<< +/Headers [(node00002361)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1347 0 R +/P 410 0 R +/S /TD +/Type /StructElem +>> +endobj +2632 0 obj +<< +/A [<< +/Headers [(node00002359)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1348 0 R +/P 411 0 R +/S /TD +/Type /StructElem +>> +endobj +2633 0 obj +<< +/A [<< +/Headers [(node00002360)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1350 0 R +/P 411 0 R +/S /TD +/Type /StructElem +>> +endobj +2634 0 obj +<< +/A [<< +/Headers [(node00002361)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1351 0 R +/P 411 0 R +/S /TD +/Type /StructElem +>> +endobj +2635 0 obj +<< +/K 1352 0 R +/P 412 0 R +/S /Strong +/Type /StructElem +>> +endobj +2636 0 obj +<< +/A [<< +/Headers [(node00002435)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1366 0 R +/P 415 0 R +/S /TD +/Type /StructElem +>> +endobj +2637 0 obj +<< +/A [<< +/Headers [(node00002436)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1367 0 R +/P 415 0 R +/S /TD +/Type /StructElem +>> +endobj +2638 0 obj +<< +/A [<< +/Headers [(node00002437)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [2907 0 R 1369 0 R] +/P 415 0 R +/S /TD +/Type /StructElem +>> +endobj +2639 0 obj +<< +/A [<< +/Headers [(node00002435)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1370 0 R +/P 416 0 R +/S /TD +/Type /StructElem +>> +endobj +2640 0 obj +<< +/A [<< +/Headers [(node00002436)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1371 0 R +/P 416 0 R +/S /TD +/Type /StructElem +>> +endobj +2641 0 obj +<< +/A [<< +/Headers [(node00002437)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [2908 0 R 1373 0 R] +/P 416 0 R +/S /TD +/Type /StructElem +>> +endobj +2642 0 obj +<< +/A [<< +/Headers [(node00002458)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1378 0 R 1380 0 R] +/P 422 0 R +/S /TD +/Type /StructElem +>> +endobj +2643 0 obj +<< +/A [<< +/Headers [(node00002459)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1381 0 R +/P 422 0 R +/S /TD +/Type /StructElem +>> +endobj +2644 0 obj +<< +/A [<< +/Headers [(node00002460)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2909 0 R +/P 422 0 R +/S /TD +/Type /StructElem +>> +endobj +2645 0 obj +<< +/A [<< +/Headers [(node00002458)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1383 0 R 1385 0 R] +/P 423 0 R +/S /TD +/Type /StructElem +>> +endobj +2646 0 obj +<< +/A [<< +/Headers [(node00002459)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1386 0 R +/P 423 0 R +/S /TD +/Type /StructElem +>> +endobj +2647 0 obj +<< +/A [<< +/Headers [(node00002460)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2910 0 R +/P 423 0 R +/S /TD +/Type /StructElem +>> +endobj +2648 0 obj +<< +/A [<< +/Headers [(node00002458)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1388 0 R +/P 424 0 R +/S /TD +/Type /StructElem +>> +endobj +2649 0 obj +<< +/A [<< +/Headers [(node00002459)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1390 0 R +/P 424 0 R +/S /TD +/Type /StructElem +>> +endobj +2650 0 obj +<< +/A [<< +/Headers [(node00002460)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2911 0 R +/P 424 0 R +/S /TD +/Type /StructElem +>> +endobj +2651 0 obj +<< +/A [<< +/Headers [(node00002458)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1392 0 R +/P 425 0 R +/S /TD +/Type /StructElem +>> +endobj +2652 0 obj +<< +/A [<< +/Headers [(node00002459)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1394 0 R +/P 425 0 R +/S /TD +/Type /StructElem +>> +endobj +2653 0 obj +<< +/A [<< +/Headers [(node00002460)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2912 0 R +/P 425 0 R +/S /TD +/Type /StructElem +>> +endobj +2654 0 obj +<< +/A [<< +/Headers [(node00002458)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1396 0 R +/P 426 0 R +/S /TD +/Type /StructElem +>> +endobj +2655 0 obj +<< +/A [<< +/Headers [(node00002459)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1398 0 R +/P 426 0 R +/S /TD +/Type /StructElem +>> +endobj +2656 0 obj +<< +/A [<< +/Headers [(node00002460)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2913 0 R +/P 426 0 R +/S /TD +/Type /StructElem +>> +endobj +2657 0 obj +<< +/A [<< +/Headers [(node00002458)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1400 0 R +/P 427 0 R +/S /TD +/Type /StructElem +>> +endobj +2658 0 obj +<< +/A [<< +/Headers [(node00002459)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1402 0 R +/P 427 0 R +/S /TD +/Type /StructElem +>> +endobj +2659 0 obj +<< +/A [<< +/Headers [(node00002460)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2914 0 R +/P 427 0 R +/S /TD +/Type /StructElem +>> +endobj +2660 0 obj +<< +/A [<< +/Headers [(node00002504)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1409 0 R +/P 433 0 R +/S /TD +/Type /StructElem +>> +endobj +2661 0 obj +<< +/A [<< +/Headers [(node00002505)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1410 0 R 1412 0 R] +/P 433 0 R +/S /TD +/Type /StructElem +>> +endobj +2662 0 obj +<< +/A [<< +/Headers [(node00002506)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1413 0 R +/P 433 0 R +/S /TD +/Type /StructElem +>> +endobj +2663 0 obj +<< +/A [<< +/Headers [(node00002507)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1415 0 R +/P 433 0 R +/S /TD +/Type /StructElem +>> +endobj +2664 0 obj +<< +/A [<< +/Headers [(node00002504)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1416 0 R +/P 434 0 R +/S /TD +/Type /StructElem +>> +endobj +2665 0 obj +<< +/A [<< +/Headers [(node00002505)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1417 0 R 1419 0 R] +/P 434 0 R +/S /TD +/Type /StructElem +>> +endobj +2666 0 obj +<< +/A [<< +/Headers [(node00002506)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1420 0 R +/P 434 0 R +/S /TD +/Type /StructElem +>> +endobj +2667 0 obj +<< +/A [<< +/Headers [(node00002507)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1422 0 R +/P 434 0 R +/S /TD +/Type /StructElem +>> +endobj +2668 0 obj +<< +/A [<< +/Headers [(node00002504)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1423 0 R +/P 435 0 R +/S /TD +/Type /StructElem +>> +endobj +2669 0 obj +<< +/A [<< +/Headers [(node00002505)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1424 0 R 1426 0 R] +/P 435 0 R +/S /TD +/Type /StructElem +>> +endobj +2670 0 obj +<< +/A [<< +/Headers [(node00002506)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1427 0 R +/P 435 0 R +/S /TD +/Type /StructElem +>> +endobj +2671 0 obj +<< +/A [<< +/Headers [(node00002507)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1429 0 R +/P 435 0 R +/S /TD +/Type /StructElem +>> +endobj +2672 0 obj +<< +/A [<< +/Headers [(node00002548)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1446 0 R +/P 462 0 R +/S /TD +/Type /StructElem +>> +endobj +2673 0 obj +<< +/A [<< +/Headers [(node00002549)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1448 0 R +/P 462 0 R +/S /TD +/Type /StructElem +>> +endobj +2674 0 obj +<< +/A [<< +/Headers [(node00002550)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2915 0 R +/P 462 0 R +/S /TD +/Type /StructElem +>> +endobj +2675 0 obj +<< +/A [<< +/Headers [(node00002551)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1450 0 R +/P 462 0 R +/S /TD +/Type /StructElem +>> +endobj +2676 0 obj +<< +/A [<< +/Headers [(node00002548)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1451 0 R +/P 463 0 R +/S /TD +/Type /StructElem +>> +endobj +2677 0 obj +<< +/A [<< +/Headers [(node00002549)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1453 0 R +/P 463 0 R +/S /TD +/Type /StructElem +>> +endobj +2678 0 obj +<< +/A [<< +/Headers [(node00002550)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2916 0 R +/P 463 0 R +/S /TD +/Type /StructElem +>> +endobj +2679 0 obj +<< +/A [<< +/Headers [(node00002551)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1455 0 R +/P 463 0 R +/S /TD +/Type /StructElem +>> +endobj +2680 0 obj +<< +/A [<< +/Headers [(node00002548)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1456 0 R +/P 464 0 R +/S /TD +/Type /StructElem +>> +endobj +2681 0 obj +<< +/A [<< +/Headers [(node00002549)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1458 0 R +/P 464 0 R +/S /TD +/Type /StructElem +>> +endobj +2682 0 obj +<< +/A [<< +/Headers [(node00002550)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2917 0 R +/P 464 0 R +/S /TD +/Type /StructElem +>> +endobj +2683 0 obj +<< +/A [<< +/Headers [(node00002551)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1460 0 R +/P 464 0 R +/S /TD +/Type /StructElem +>> +endobj +2684 0 obj +<< +/A [<< +/Headers [(node00002548)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1461 0 R +/P 465 0 R +/S /TD +/Type /StructElem +>> +endobj +2685 0 obj +<< +/A [<< +/Headers [(node00002549)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1463 0 R +/P 465 0 R +/S /TD +/Type /StructElem +>> +endobj +2686 0 obj +<< +/A [<< +/Headers [(node00002550)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2918 0 R +/P 465 0 R +/S /TD +/Type /StructElem +>> +endobj +2687 0 obj +<< +/A [<< +/Headers [(node00002551)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1465 0 R +/P 465 0 R +/S /TD +/Type /StructElem +>> +endobj +2688 0 obj +<< +/A [<< +/Headers [(node00002548)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1466 0 R +/P 466 0 R +/S /TD +/Type /StructElem +>> +endobj +2689 0 obj +<< +/A [<< +/Headers [(node00002549)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1468 0 R +/P 466 0 R +/S /TD +/Type /StructElem +>> +endobj +2690 0 obj +<< +/A [<< +/Headers [(node00002550)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2919 0 R +/P 466 0 R +/S /TD +/Type /StructElem +>> +endobj +2691 0 obj +<< +/A [<< +/Headers [(node00002551)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1470 0 R +/P 466 0 R +/S /TD +/Type /StructElem +>> +endobj +2692 0 obj +<< +/A [<< +/Headers [(node00002548)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1471 0 R +/P 467 0 R +/S /TD +/Type /StructElem +>> +endobj +2693 0 obj +<< +/A [<< +/Headers [(node00002549)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1473 0 R +/P 467 0 R +/S /TD +/Type /StructElem +>> +endobj +2694 0 obj +<< +/A [<< +/Headers [(node00002550)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2920 0 R +/P 467 0 R +/S /TD +/Type /StructElem +>> +endobj +2695 0 obj +<< +/A [<< +/Headers [(node00002551)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1475 0 R +/P 467 0 R +/S /TD +/Type /StructElem +>> +endobj +2696 0 obj +<< +/A [<< +/Headers [(node00002548)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1476 0 R +/P 468 0 R +/S /TD +/Type /StructElem +>> +endobj +2697 0 obj +<< +/A [<< +/Headers [(node00002549)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1478 0 R +/P 468 0 R +/S /TD +/Type /StructElem +>> +endobj +2698 0 obj +<< +/A [<< +/Headers [(node00002550)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2921 0 R +/P 468 0 R +/S /TD +/Type /StructElem +>> +endobj +2699 0 obj +<< +/A [<< +/Headers [(node00002551)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1480 0 R +/P 468 0 R +/S /TD +/Type /StructElem +>> +endobj +2700 0 obj +<< +/A [<< +/Headers [(node00002548)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1481 0 R +/P 469 0 R +/S /TD +/Type /StructElem +>> +endobj +2701 0 obj +<< +/A [<< +/Headers [(node00002549)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1483 0 R +/P 469 0 R +/S /TD +/Type /StructElem +>> +endobj +2702 0 obj +<< +/A [<< +/Headers [(node00002550)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2922 0 R +/P 469 0 R +/S /TD +/Type /StructElem +>> +endobj +2703 0 obj +<< +/A [<< +/Headers [(node00002551)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1485 0 R +/P 469 0 R +/S /TD +/Type /StructElem +>> +endobj +2704 0 obj +<< +/A [<< +/Headers [(node00002548)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1487 0 R +/P 470 0 R +/S /TD +/Type /StructElem +>> +endobj +2705 0 obj +<< +/A [<< +/Headers [(node00002549)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1489 0 R +/P 470 0 R +/S /TD +/Type /StructElem +>> +endobj +2706 0 obj +<< +/A [<< +/Headers [(node00002550)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2923 0 R +/P 470 0 R +/S /TD +/Type /StructElem +>> +endobj +2707 0 obj +<< +/A [<< +/Headers [(node00002551)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1491 0 R +/P 470 0 R +/S /TD +/Type /StructElem +>> +endobj +2708 0 obj +<< +/A [<< +/Headers [(node00002548)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1492 0 R +/P 471 0 R +/S /TD +/Type /StructElem +>> +endobj +2709 0 obj +<< +/A [<< +/Headers [(node00002549)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1494 0 R +/P 471 0 R +/S /TD +/Type /StructElem +>> +endobj +2710 0 obj +<< +/A [<< +/Headers [(node00002550)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2924 0 R +/P 471 0 R +/S /TD +/Type /StructElem +>> +endobj +2711 0 obj +<< +/A [<< +/Headers [(node00002551)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1496 0 R +/P 471 0 R +/S /TD +/Type /StructElem +>> +endobj +2712 0 obj +<< +/A [<< +/Headers [(node00002548)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1497 0 R +/P 472 0 R +/S /TD +/Type /StructElem +>> +endobj +2713 0 obj +<< +/A [<< +/Headers [(node00002549)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1499 0 R +/P 472 0 R +/S /TD +/Type /StructElem +>> +endobj +2714 0 obj +<< +/A [<< +/Headers [(node00002550)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2925 0 R +/P 472 0 R +/S /TD +/Type /StructElem +>> +endobj +2715 0 obj +<< +/A [<< +/Headers [(node00002551)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1501 0 R +/P 472 0 R +/S /TD +/Type /StructElem +>> +endobj +2716 0 obj +<< +/A [<< +/Headers [(node00002548)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1502 0 R +/P 473 0 R +/S /TD +/Type /StructElem +>> +endobj +2717 0 obj +<< +/A [<< +/Headers [(node00002549)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1504 0 R +/P 473 0 R +/S /TD +/Type /StructElem +>> +endobj +2718 0 obj +<< +/A [<< +/Headers [(node00002550)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2926 0 R +/P 473 0 R +/S /TD +/Type /StructElem +>> +endobj +2719 0 obj +<< +/A [<< +/Headers [(node00002551)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1506 0 R +/P 473 0 R +/S /TD +/Type /StructElem +>> +endobj +2720 0 obj +<< +/A [<< +/Headers [(node00002641)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1510 0 R +/P 476 0 R +/S /TD +/Type /StructElem +>> +endobj +2721 0 obj +<< +/A [<< +/Headers [(node00002642)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1511 0 R +/P 476 0 R +/S /TD +/Type /StructElem +>> +endobj +2722 0 obj +<< +/A [<< +/Headers [(node00002643)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2927 0 R +/P 476 0 R +/S /TD +/Type /StructElem +>> +endobj +2723 0 obj +<< +/A [<< +/Headers [(node00002641)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1513 0 R +/P 477 0 R +/S /TD +/Type /StructElem +>> +endobj +2724 0 obj +<< +/A [<< +/Headers [(node00002642)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1514 0 R +/P 477 0 R +/S /TD +/Type /StructElem +>> +endobj +2725 0 obj +<< +/A [<< +/Headers [(node00002643)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2928 0 R +/P 477 0 R +/S /TD +/Type /StructElem +>> +endobj +2726 0 obj +<< +/A [<< +/Headers [(node00002641)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1516 0 R +/P 478 0 R +/S /TD +/Type /StructElem +>> +endobj +2727 0 obj +<< +/A [<< +/Headers [(node00002642)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1517 0 R +/P 478 0 R +/S /TD +/Type /StructElem +>> +endobj +2728 0 obj +<< +/A [<< +/Headers [(node00002643)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2929 0 R +/P 478 0 R +/S /TD +/Type /StructElem +>> +endobj +2729 0 obj +<< +/A [<< +/Headers [(node00002641)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1519 0 R +/P 479 0 R +/S /TD +/Type /StructElem +>> +endobj +2730 0 obj +<< +/A [<< +/Headers [(node00002642)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1520 0 R +/P 479 0 R +/S /TD +/Type /StructElem +>> +endobj +2731 0 obj +<< +/A [<< +/Headers [(node00002643)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2930 0 R +/P 479 0 R +/S /TD +/Type /StructElem +>> +endobj +2732 0 obj +<< +/A [<< +/Headers [(node00002673)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1527 0 R +/P 486 0 R +/S /TD +/Type /StructElem +>> +endobj +2733 0 obj +<< +/A [<< +/Headers [(node00002674)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1528 0 R 1530 0 R] +/P 486 0 R +/S /TD +/Type /StructElem +>> +endobj +2734 0 obj +<< +/A [<< +/Headers [(node00002675)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [2931 0 R 1532 0 R] +/P 486 0 R +/S /TD +/Type /StructElem +>> +endobj +2735 0 obj +<< +/A [<< +/Headers [(node00002673)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1533 0 R +/P 487 0 R +/S /TD +/Type /StructElem +>> +endobj +2736 0 obj +<< +/A [<< +/Headers [(node00002674)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1534 0 R 1536 0 R] +/P 487 0 R +/S /TD +/Type /StructElem +>> +endobj +2737 0 obj +<< +/A [<< +/Headers [(node00002675)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [2932 0 R 1538 0 R] +/P 487 0 R +/S /TD +/Type /StructElem +>> +endobj +2738 0 obj +<< +/A [<< +/Headers [(node00002673)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1539 0 R +/P 488 0 R +/S /TD +/Type /StructElem +>> +endobj +2739 0 obj +<< +/A [<< +/Headers [(node00002674)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1540 0 R +/P 488 0 R +/S /TD +/Type /StructElem +>> +endobj +2740 0 obj +<< +/A [<< +/Headers [(node00002675)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2933 0 R +/P 488 0 R +/S /TD +/Type /StructElem +>> +endobj +2741 0 obj +<< +/A [<< +/Headers [(node00002673)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1542 0 R +/P 489 0 R +/S /TD +/Type /StructElem +>> +endobj +2742 0 obj +<< +/A [<< +/Headers [(node00002674)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1543 0 R +/P 489 0 R +/S /TD +/Type /StructElem +>> +endobj +2743 0 obj +<< +/A [<< +/Headers [(node00002675)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2934 0 R +/P 489 0 R +/S /TD +/Type /StructElem +>> +endobj +2744 0 obj +<< +/A [<< +/Headers [(node00002673)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1545 0 R +/P 490 0 R +/S /TD +/Type /StructElem +>> +endobj +2745 0 obj +<< +/A [<< +/Headers [(node00002674)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1546 0 R +/P 490 0 R +/S /TD +/Type /StructElem +>> +endobj +2746 0 obj +<< +/A [<< +/Headers [(node00002675)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [2935 0 R 1548 0 R] +/P 490 0 R +/S /TD +/Type /StructElem +>> +endobj +2747 0 obj +<< +/K 1778 0 R +/P 565 0 R +/S /Strong +/Type /StructElem +>> +endobj +2748 0 obj +<< +/A [<< +/Headers [(node00003027)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1811 0 R +/P 637 0 R +/S /TD +/Type /StructElem +>> +endobj +2749 0 obj +<< +/A [<< +/Headers [(node00003028)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1812 0 R +/P 637 0 R +/S /TD +/Type /StructElem +>> +endobj +2750 0 obj +<< +/A [<< +/Headers [(node00003029)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1813 0 R +/P 637 0 R +/S /TD +/Type /StructElem +>> +endobj +2751 0 obj +<< +/A [<< +/Headers [(node00003027)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1814 0 R +/P 638 0 R +/S /TD +/Type /StructElem +>> +endobj +2752 0 obj +<< +/A [<< +/Headers [(node00003028)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1815 0 R +/P 638 0 R +/S /TD +/Type /StructElem +>> +endobj +2753 0 obj +<< +/A [<< +/Headers [(node00003029)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1816 0 R +/P 638 0 R +/S /TD +/Type /StructElem +>> +endobj +2754 0 obj +<< +/A [<< +/Headers [(node00003027)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1817 0 R +/P 639 0 R +/S /TD +/Type /StructElem +>> +endobj +2755 0 obj +<< +/A [<< +/Headers [(node00003028)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1818 0 R +/P 639 0 R +/S /TD +/Type /StructElem +>> +endobj +2756 0 obj +<< +/A [<< +/Headers [(node00003029)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1819 0 R +/P 639 0 R +/S /TD +/Type /StructElem +>> +endobj +2757 0 obj +<< +/A [<< +/Headers [(node00003027)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1820 0 R +/P 640 0 R +/S /TD +/Type /StructElem +>> +endobj +2758 0 obj +<< +/A [<< +/Headers [(node00003028)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1821 0 R +/P 640 0 R +/S /TD +/Type /StructElem +>> +endobj +2759 0 obj +<< +/A [<< +/Headers [(node00003029)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1822 0 R +/P 640 0 R +/S /TD +/Type /StructElem +>> +endobj +2760 0 obj +<< +/A [<< +/Headers [(node00003027)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1823 0 R +/P 641 0 R +/S /TD +/Type /StructElem +>> +endobj +2761 0 obj +<< +/A [<< +/Headers [(node00003028)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1824 0 R +/P 641 0 R +/S /TD +/Type /StructElem +>> +endobj +2762 0 obj +<< +/A [<< +/Headers [(node00003029)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1825 0 R +/P 641 0 R +/S /TD +/Type /StructElem +>> +endobj +2763 0 obj +<< +/A [<< +/Headers [(node00003171)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1914 0 R 1916 0 R] +/P 700 0 R +/S /TD +/Type /StructElem +>> +endobj +2764 0 obj +<< +/A [<< +/Headers [(node00003172)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1917 0 R +/P 700 0 R +/S /TD +/Type /StructElem +>> +endobj +2765 0 obj +<< +/A [<< +/Headers [(node00003173)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1918 0 R +/P 700 0 R +/S /TD +/Type /StructElem +>> +endobj +2766 0 obj +<< +/A [<< +/Headers [(node00003174)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1919 0 R +/P 700 0 R +/S /TD +/Type /StructElem +>> +endobj +2767 0 obj +<< +/A [<< +/Headers [(node00003171)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1920 0 R +/P 701 0 R +/S /TD +/Type /StructElem +>> +endobj +2768 0 obj +<< +/A [<< +/Headers [(node00003172)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1922 0 R +/P 701 0 R +/S /TD +/Type /StructElem +>> +endobj +2769 0 obj +<< +/A [<< +/Headers [(node00003173)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1923 0 R +/P 701 0 R +/S /TD +/Type /StructElem +>> +endobj +2770 0 obj +<< +/A [<< +/Headers [(node00003174)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1924 0 R +/P 701 0 R +/S /TD +/Type /StructElem +>> +endobj +2771 0 obj +<< +/A [<< +/Headers [(node00003171)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1925 0 R +/P 702 0 R +/S /TD +/Type /StructElem +>> +endobj +2772 0 obj +<< +/A [<< +/Headers [(node00003172)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1926 0 R +/P 702 0 R +/S /TD +/Type /StructElem +>> +endobj +2773 0 obj +<< +/A [<< +/Headers [(node00003173)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1927 0 R +/P 702 0 R +/S /TD +/Type /StructElem +>> +endobj +2774 0 obj +<< +/A [<< +/Headers [(node00003174)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1928 0 R +/P 702 0 R +/S /TD +/Type /StructElem +>> +endobj +2775 0 obj +<< +/A [<< +/Headers [(node00003171)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K [1929 0 R 1931 0 R] +/P 703 0 R +/S /TD +/Type /StructElem +>> +endobj +2776 0 obj +<< +/A [<< +/Headers [(node00003172)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1932 0 R +/P 703 0 R +/S /TD +/Type /StructElem +>> +endobj +2777 0 obj +<< +/A [<< +/Headers [(node00003173)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1933 0 R +/P 703 0 R +/S /TD +/Type /StructElem +>> +endobj +2778 0 obj +<< +/A [<< +/Headers [(node00003174)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 1934 0 R +/P 703 0 R +/S /TD +/Type /StructElem +>> +endobj +2779 0 obj +<< +/A [<< +/Headers [(node00003385)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2095 0 R +/P 746 0 R +/S /TD +/Type /StructElem +>> +endobj +2780 0 obj +<< +/A [<< +/Headers [(node00003386)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2096 0 R +/P 746 0 R +/S /TD +/Type /StructElem +>> +endobj +2781 0 obj +<< +/A [<< +/Headers [(node00003387)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2097 0 R +/P 746 0 R +/S /TD +/Type /StructElem +>> +endobj +2782 0 obj +<< +/A [<< +/Headers [(node00003385)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2098 0 R +/P 747 0 R +/S /TD +/Type /StructElem +>> +endobj +2783 0 obj +<< +/A [<< +/Headers [(node00003386)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2099 0 R +/P 747 0 R +/S /TD +/Type /StructElem +>> +endobj +2784 0 obj +<< +/A [<< +/Headers [(node00003387)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2100 0 R +/P 747 0 R +/S /TD +/Type /StructElem +>> +endobj +2785 0 obj +<< +/A [<< +/Headers [(node00003385)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2101 0 R +/P 748 0 R +/S /TD +/Type /StructElem +>> +endobj +2786 0 obj +<< +/A [<< +/Headers [(node00003386)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2102 0 R +/P 748 0 R +/S /TD +/Type /StructElem +>> +endobj +2787 0 obj +<< +/A [<< +/Headers [(node00003387)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2103 0 R +/P 748 0 R +/S /TD +/Type /StructElem +>> +endobj +2788 0 obj +<< +/A [<< +/Headers [(node00003385)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2104 0 R +/P 749 0 R +/S /TD +/Type /StructElem +>> +endobj +2789 0 obj +<< +/A [<< +/Headers [(node00003386)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2105 0 R +/P 749 0 R +/S /TD +/Type /StructElem +>> +endobj +2790 0 obj +<< +/A [<< +/Headers [(node00003387)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2106 0 R +/P 749 0 R +/S /TD +/Type /StructElem +>> +endobj +2791 0 obj +<< +/A [<< +/Headers [(node00003385)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2107 0 R +/P 750 0 R +/S /TD +/Type /StructElem +>> +endobj +2792 0 obj +<< +/A [<< +/Headers [(node00003386)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2108 0 R +/P 750 0 R +/S /TD +/Type /StructElem +>> +endobj +2793 0 obj +<< +/A [<< +/Headers [(node00003387)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2109 0 R +/P 750 0 R +/S /TD +/Type /StructElem +>> +endobj +2794 0 obj +<< +/A [<< +/Headers [(node00003385)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2110 0 R +/P 751 0 R +/S /TD +/Type /StructElem +>> +endobj +2795 0 obj +<< +/A [<< +/Headers [(node00003386)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2111 0 R +/P 751 0 R +/S /TD +/Type /StructElem +>> +endobj +2796 0 obj +<< +/A [<< +/Headers [(node00003387)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2112 0 R +/P 751 0 R +/S /TD +/Type /StructElem +>> +endobj +2797 0 obj +<< +/A [<< +/Headers [(node00003385)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2113 0 R +/P 752 0 R +/S /TD +/Type /StructElem +>> +endobj +2798 0 obj +<< +/A [<< +/Headers [(node00003386)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2114 0 R +/P 752 0 R +/S /TD +/Type /StructElem +>> +endobj +2799 0 obj +<< +/A [<< +/Headers [(node00003387)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2115 0 R +/P 752 0 R +/S /TD +/Type /StructElem +>> +endobj +2800 0 obj +<< +/A [<< +/Headers [(node00003385)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2116 0 R +/P 753 0 R +/S /TD +/Type /StructElem +>> +endobj +2801 0 obj +<< +/A [<< +/Headers [(node00003386)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2117 0 R +/P 753 0 R +/S /TD +/Type /StructElem +>> +endobj +2802 0 obj +<< +/A [<< +/Headers [(node00003387)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2118 0 R +/P 753 0 R +/S /TD +/Type /StructElem +>> +endobj +2803 0 obj +<< +/A [<< +/Headers [(node00003385)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2936 0 R +/P 754 0 R +/S /TD +/Type /StructElem +>> +endobj +2804 0 obj +<< +/A [<< +/Headers [(node00003386)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2937 0 R +/P 754 0 R +/S /TD +/Type /StructElem +>> +endobj +2805 0 obj +<< +/A [<< +/Headers [(node00003387)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2121 0 R +/P 754 0 R +/S /TD +/Type /StructElem +>> +endobj +2806 0 obj +<< +/A [<< +/Headers [(node00003465)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2163 0 R +/P 789 0 R +/S /TD +/Type /StructElem +>> +endobj +2807 0 obj +<< +/A [<< +/Headers [(node00003466)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2164 0 R +/P 789 0 R +/S /TD +/Type /StructElem +>> +endobj +2808 0 obj +<< +/A [<< +/Headers [(node00003467)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2165 0 R +/P 789 0 R +/S /TD +/Type /StructElem +>> +endobj +2809 0 obj +<< +/A [<< +/Headers [(node00003465)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2166 0 R +/P 790 0 R +/S /TD +/Type /StructElem +>> +endobj +2810 0 obj +<< +/A [<< +/Headers [(node00003466)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2167 0 R +/P 790 0 R +/S /TD +/Type /StructElem +>> +endobj +2811 0 obj +<< +/A [<< +/Headers [(node00003467)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2168 0 R +/P 790 0 R +/S /TD +/Type /StructElem +>> +endobj +2812 0 obj +<< +/A [<< +/Headers [(node00003465)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2169 0 R +/P 791 0 R +/S /TD +/Type /StructElem +>> +endobj +2813 0 obj +<< +/A [<< +/Headers [(node00003466)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2170 0 R +/P 791 0 R +/S /TD +/Type /StructElem +>> +endobj +2814 0 obj +<< +/A [<< +/Headers [(node00003467)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2171 0 R +/P 791 0 R +/S /TD +/Type /StructElem +>> +endobj +2815 0 obj +<< +/A [<< +/Headers [(node00003465)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2172 0 R +/P 792 0 R +/S /TD +/Type /StructElem +>> +endobj +2816 0 obj +<< +/A [<< +/Headers [(node00003466)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2173 0 R +/P 792 0 R +/S /TD +/Type /StructElem +>> +endobj +2817 0 obj +<< +/A [<< +/Headers [(node00003467)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2174 0 R +/P 792 0 R +/S /TD +/Type /StructElem +>> +endobj +2818 0 obj +<< +/A [<< +/Headers [(node00003491)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2179 0 R +/P 796 0 R +/S /TD +/Type /StructElem +>> +endobj +2819 0 obj +<< +/A [<< +/Headers [(node00003492)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2180 0 R +/P 796 0 R +/S /TD +/Type /StructElem +>> +endobj +2820 0 obj +<< +/A [<< +/Headers [(node00003493)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2938 0 R +/P 796 0 R +/S /TD +/Type /StructElem +>> +endobj +2821 0 obj +<< +/A [<< +/Headers [(node00003494)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2182 0 R +/P 796 0 R +/S /TD +/Type /StructElem +>> +endobj +2822 0 obj +<< +/A [<< +/Headers [(node00003491)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2183 0 R +/P 797 0 R +/S /TD +/Type /StructElem +>> +endobj +2823 0 obj +<< +/A [<< +/Headers [(node00003492)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2184 0 R +/P 797 0 R +/S /TD +/Type /StructElem +>> +endobj +2824 0 obj +<< +/A [<< +/Headers [(node00003493)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2185 0 R +/P 797 0 R +/S /TD +/Type /StructElem +>> +endobj +2825 0 obj +<< +/A [<< +/Headers [(node00003494)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2186 0 R +/P 797 0 R +/S /TD +/Type /StructElem +>> +endobj +2826 0 obj +<< +/A [<< +/Headers [(node00003491)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2187 0 R +/P 798 0 R +/S /TD +/Type /StructElem +>> +endobj +2827 0 obj +<< +/A [<< +/Headers [(node00003492)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2188 0 R +/P 798 0 R +/S /TD +/Type /StructElem +>> +endobj +2828 0 obj +<< +/A [<< +/Headers [(node00003493)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2189 0 R +/P 798 0 R +/S /TD +/Type /StructElem +>> +endobj +2829 0 obj +<< +/A [<< +/Headers [(node00003494)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2190 0 R +/P 798 0 R +/S /TD +/Type /StructElem +>> +endobj +2830 0 obj +<< +/A [<< +/Headers [(node00003491)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2191 0 R +/P 799 0 R +/S /TD +/Type /StructElem +>> +endobj +2831 0 obj +<< +/A [<< +/Headers [(node00003492)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2192 0 R +/P 799 0 R +/S /TD +/Type /StructElem +>> +endobj +2832 0 obj +<< +/A [<< +/Headers [(node00003493)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2193 0 R +/P 799 0 R +/S /TD +/Type /StructElem +>> +endobj +2833 0 obj +<< +/A [<< +/Headers [(node00003494)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2194 0 R +/P 799 0 R +/S /TD +/Type /StructElem +>> +endobj +2834 0 obj +<< +/A [<< +/Headers [(node00003521)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2198 0 R +/P 802 0 R +/S /TD +/Type /StructElem +>> +endobj +2835 0 obj +<< +/A [<< +/Headers [(node00003522)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2199 0 R +/P 802 0 R +/S /TD +/Type /StructElem +>> +endobj +2836 0 obj +<< +/A [<< +/Headers [(node00003523)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2200 0 R +/P 802 0 R +/S /TD +/Type /StructElem +>> +endobj +2837 0 obj +<< +/A [<< +/Headers [(node00003521)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2201 0 R +/P 803 0 R +/S /TD +/Type /StructElem +>> +endobj +2838 0 obj +<< +/A [<< +/Headers [(node00003522)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2202 0 R +/P 803 0 R +/S /TD +/Type /StructElem +>> +endobj +2839 0 obj +<< +/A [<< +/Headers [(node00003523)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2203 0 R +/P 803 0 R +/S /TD +/Type /StructElem +>> +endobj +2840 0 obj +<< +/A [<< +/Headers [(node00003521)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2204 0 R +/P 804 0 R +/S /TD +/Type /StructElem +>> +endobj +2841 0 obj +<< +/A [<< +/Headers [(node00003522)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2205 0 R +/P 804 0 R +/S /TD +/Type /StructElem +>> +endobj +2842 0 obj +<< +/A [<< +/Headers [(node00003523)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2206 0 R +/P 804 0 R +/S /TD +/Type /StructElem +>> +endobj +2843 0 obj +<< +/A [<< +/Headers [(node00003521)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2207 0 R +/P 805 0 R +/S /TD +/Type /StructElem +>> +endobj +2844 0 obj +<< +/A [<< +/Headers [(node00003522)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2208 0 R +/P 805 0 R +/S /TD +/Type /StructElem +>> +endobj +2845 0 obj +<< +/A [<< +/Headers [(node00003523)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2209 0 R +/P 805 0 R +/S /TD +/Type /StructElem +>> +endobj +2846 0 obj +<< +/A [<< +/Headers [(node00003521)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2210 0 R +/P 806 0 R +/S /TD +/Type /StructElem +>> +endobj +2847 0 obj +<< +/A [<< +/Headers [(node00003522)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2211 0 R +/P 806 0 R +/S /TD +/Type /StructElem +>> +endobj +2848 0 obj +<< +/A [<< +/Headers [(node00003523)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2212 0 R +/P 806 0 R +/S /TD +/Type /StructElem +>> +endobj +2849 0 obj +<< +/A [<< +/Headers [(node00003521)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2213 0 R +/P 807 0 R +/S /TD +/Type /StructElem +>> +endobj +2850 0 obj +<< +/A [<< +/Headers [(node00003522)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2214 0 R +/P 807 0 R +/S /TD +/Type /StructElem +>> +endobj +2851 0 obj +<< +/A [<< +/Headers [(node00003523)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2215 0 R +/P 807 0 R +/S /TD +/Type /StructElem +>> +endobj +2852 0 obj +<< +/A [<< +/Headers [(node00003521)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2216 0 R +/P 808 0 R +/S /TD +/Type /StructElem +>> +endobj +2853 0 obj +<< +/A [<< +/Headers [(node00003522)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2217 0 R +/P 808 0 R +/S /TD +/Type /StructElem +>> +endobj +2854 0 obj +<< +/A [<< +/Headers [(node00003523)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2218 0 R +/P 808 0 R +/S /TD +/Type /StructElem +>> +endobj +2855 0 obj +<< +/A [<< +/Headers [(node00003557)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2222 0 R +/P 811 0 R +/S /TD +/Type /StructElem +>> +endobj +2856 0 obj +<< +/A [<< +/Headers [(node00003558)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2223 0 R +/P 811 0 R +/S /TD +/Type /StructElem +>> +endobj +2857 0 obj +<< +/A [<< +/Headers [(node00003559)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2224 0 R +/P 811 0 R +/S /TD +/Type /StructElem +>> +endobj +2858 0 obj +<< +/A [<< +/Headers [(node00003557)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2225 0 R +/P 812 0 R +/S /TD +/Type /StructElem +>> +endobj +2859 0 obj +<< +/A [<< +/Headers [(node00003558)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2226 0 R +/P 812 0 R +/S /TD +/Type /StructElem +>> +endobj +2860 0 obj +<< +/A [<< +/Headers [(node00003559)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2227 0 R +/P 812 0 R +/S /TD +/Type /StructElem +>> +endobj +2861 0 obj +<< +/A [<< +/Headers [(node00003557)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2228 0 R +/P 813 0 R +/S /TD +/Type /StructElem +>> +endobj +2862 0 obj +<< +/A [<< +/Headers [(node00003558)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2229 0 R +/P 813 0 R +/S /TD +/Type /StructElem +>> +endobj +2863 0 obj +<< +/A [<< +/Headers [(node00003559)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2230 0 R +/P 813 0 R +/S /TD +/Type /StructElem +>> +endobj +2864 0 obj +<< +/A [<< +/Headers [(node00003557)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2231 0 R +/P 814 0 R +/S /TD +/Type /StructElem +>> +endobj +2865 0 obj +<< +/A [<< +/Headers [(node00003558)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2232 0 R +/P 814 0 R +/S /TD +/Type /StructElem +>> +endobj +2866 0 obj +<< +/A [<< +/Headers [(node00003559)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2233 0 R +/P 814 0 R +/S /TD +/Type /StructElem +>> +endobj +2867 0 obj +<< +/A [<< +/Headers [(node00003557)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2234 0 R +/P 815 0 R +/S /TD +/Type /StructElem +>> +endobj +2868 0 obj +<< +/A [<< +/Headers [(node00003558)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2235 0 R +/P 815 0 R +/S /TD +/Type /StructElem +>> +endobj +2869 0 obj +<< +/A [<< +/Headers [(node00003559)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2236 0 R +/P 815 0 R +/S /TD +/Type /StructElem +>> +endobj +2870 0 obj +<< +/A [<< +/Headers [(node00003557)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2237 0 R +/P 816 0 R +/S /TD +/Type /StructElem +>> +endobj +2871 0 obj +<< +/A [<< +/Headers [(node00003558)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2238 0 R +/P 816 0 R +/S /TD +/Type /StructElem +>> +endobj +2872 0 obj +<< +/A [<< +/Headers [(node00003559)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2239 0 R +/P 816 0 R +/S /TD +/Type /StructElem +>> +endobj +2873 0 obj +<< +/A [<< +/Headers [(node00003589)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2242 0 R +/P 819 0 R +/S /TD +/Type /StructElem +>> +endobj +2874 0 obj +<< +/A [<< +/Headers [(node00003590)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2243 0 R +/P 819 0 R +/S /TD +/Type /StructElem +>> +endobj +2875 0 obj +<< +/A [<< +/Headers [(node00003589)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2244 0 R +/P 820 0 R +/S /TD +/Type /StructElem +>> +endobj +2876 0 obj +<< +/A [<< +/Headers [(node00003590)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2245 0 R +/P 820 0 R +/S /TD +/Type /StructElem +>> +endobj +2877 0 obj +<< +/A [<< +/Headers [(node00003589)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2246 0 R +/P 821 0 R +/S /TD +/Type /StructElem +>> +endobj +2878 0 obj +<< +/A [<< +/Headers [(node00003590)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2247 0 R +/P 821 0 R +/S /TD +/Type /StructElem +>> +endobj +2879 0 obj +<< +/A [<< +/Headers [(node00003589)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2248 0 R +/P 822 0 R +/S /TD +/Type /StructElem +>> +endobj +2880 0 obj +<< +/A [<< +/Headers [(node00003590)] +/O /Table +>> << +/O /Table +/RowSpan 1 +>> << +/ColSpan 1 +/O /Table +>>] +/K 2249 0 R +/P 822 0 R +/S /TD +/Type /StructElem +>> +endobj +2881 0 obj +<< +/K 876 0 R +/P 2497 0 R +/S /Strong +/Type /StructElem +>> +endobj +2882 0 obj +<< +/K 882 0 R +/P 2502 0 R +/S /Strong +/Type /StructElem +>> +endobj +2883 0 obj +<< +/K 888 0 R +/P 2507 0 R +/S /Strong +/Type /StructElem +>> +endobj +2884 0 obj +<< +/K 894 0 R +/P 2512 0 R +/S /Strong +/Type /StructElem +>> +endobj +2885 0 obj +<< +/K 900 0 R +/P 2517 0 R +/S /Strong +/Type /StructElem +>> +endobj +2886 0 obj +<< +/K 906 0 R +/P 2522 0 R +/S /Strong +/Type /StructElem +>> +endobj +2887 0 obj +<< +/K 915 0 R +/P 2526 0 R +/S /Strong +/Type /StructElem +>> +endobj +2888 0 obj +<< +/K 920 0 R +/P 2530 0 R +/S /Strong +/Type /StructElem +>> +endobj +2889 0 obj +<< +/K 925 0 R +/P 2534 0 R +/S /Strong +/Type /StructElem +>> +endobj +2890 0 obj +<< +/K 930 0 R +/P 2538 0 R +/S /Strong +/Type /StructElem +>> +endobj +2891 0 obj +<< +/K 935 0 R +/P 2542 0 R +/S /Strong +/Type /StructElem +>> +endobj +2892 0 obj +<< +/K 940 0 R +/P 2546 0 R +/S /Strong +/Type /StructElem +>> +endobj +2893 0 obj +<< +/K 945 0 R +/P 2550 0 R +/S /Strong +/Type /StructElem +>> +endobj +2894 0 obj +<< +/K 950 0 R +/P 2554 0 R +/S /Strong +/Type /StructElem +>> +endobj +2895 0 obj +<< +/K 955 0 R +/P 2558 0 R +/S /Strong +/Type /StructElem +>> +endobj +2896 0 obj +<< +/K 960 0 R +/P 2562 0 R +/S /Strong +/Type /StructElem +>> +endobj +2897 0 obj +<< +/K 1207 0 R +/P 2566 0 R +/S /Strong +/Type /StructElem +>> +endobj +2898 0 obj +<< +/K 1209 0 R +/P 2567 0 R +/S /Strong +/Type /StructElem +>> +endobj +2899 0 obj +<< +/K 1217 0 R +/P 2571 0 R +/S /Strong +/Type /StructElem +>> +endobj +2900 0 obj +<< +/K 1222 0 R +/P 2575 0 R +/S /Strong +/Type /StructElem +>> +endobj +2901 0 obj +<< +/K 1227 0 R +/P 2579 0 R +/S /Strong +/Type /StructElem +>> +endobj +2902 0 obj +<< +/K 1232 0 R +/P 2583 0 R +/S /Strong +/Type /StructElem +>> +endobj +2903 0 obj +<< +/K 1240 0 R +/P 2587 0 R +/S /Strong +/Type /StructElem +>> +endobj +2904 0 obj +<< +/K 1248 0 R +/P 2591 0 R +/S /Strong +/Type /StructElem +>> +endobj +2905 0 obj +<< +/K 1256 0 R +/P 2595 0 R +/S /Strong +/Type /StructElem +>> +endobj +2906 0 obj +<< +/K 1304 0 R +/P 2604 0 R +/S /Strong +/Type /StructElem +>> +endobj +2907 0 obj +<< +/K 1368 0 R +/P 2638 0 R +/S /Strong +/Type /StructElem +>> +endobj +2908 0 obj +<< +/K 1372 0 R +/P 2641 0 R +/S /Strong +/Type /StructElem +>> +endobj +2909 0 obj +<< +/K 1382 0 R +/P 2644 0 R +/S /Strong +/Type /StructElem +>> +endobj +2910 0 obj +<< +/K 1387 0 R +/P 2647 0 R +/S /Strong +/Type /StructElem +>> +endobj +2911 0 obj +<< +/K 1391 0 R +/P 2650 0 R +/S /Strong +/Type /StructElem +>> +endobj +2912 0 obj +<< +/K 1395 0 R +/P 2653 0 R +/S /Strong +/Type /StructElem +>> +endobj +2913 0 obj +<< +/K 1399 0 R +/P 2656 0 R +/S /Strong +/Type /StructElem +>> +endobj +2914 0 obj +<< +/K 1403 0 R +/P 2659 0 R +/S /Strong +/Type /StructElem +>> +endobj +2915 0 obj +<< +/K 1449 0 R +/P 2674 0 R +/S /Strong +/Type /StructElem +>> +endobj +2916 0 obj +<< +/K 1454 0 R +/P 2678 0 R +/S /Strong +/Type /StructElem +>> +endobj +2917 0 obj +<< +/K 1459 0 R +/P 2682 0 R +/S /Strong +/Type /StructElem +>> +endobj +2918 0 obj +<< +/K 1464 0 R +/P 2686 0 R +/S /Strong +/Type /StructElem +>> +endobj +2919 0 obj +<< +/K 1469 0 R +/P 2690 0 R +/S /Strong +/Type /StructElem +>> +endobj +2920 0 obj +<< +/K 1474 0 R +/P 2694 0 R +/S /Strong +/Type /StructElem +>> +endobj +2921 0 obj +<< +/K 1479 0 R +/P 2698 0 R +/S /Strong +/Type /StructElem +>> +endobj +2922 0 obj +<< +/K 1484 0 R +/P 2702 0 R +/S /Strong +/Type /StructElem +>> +endobj +2923 0 obj +<< +/K 1490 0 R +/P 2706 0 R +/S /Strong +/Type /StructElem +>> +endobj +2924 0 obj +<< +/K 1495 0 R +/P 2710 0 R +/S /Strong +/Type /StructElem +>> +endobj +2925 0 obj +<< +/K 1500 0 R +/P 2714 0 R +/S /Strong +/Type /StructElem +>> +endobj +2926 0 obj +<< +/K 1505 0 R +/P 2718 0 R +/S /Strong +/Type /StructElem +>> +endobj +2927 0 obj +<< +/K 1512 0 R +/P 2722 0 R +/S /Strong +/Type /StructElem +>> +endobj +2928 0 obj +<< +/K 1515 0 R +/P 2725 0 R +/S /Strong +/Type /StructElem +>> +endobj +2929 0 obj +<< +/K 1518 0 R +/P 2728 0 R +/S /Strong +/Type /StructElem +>> +endobj +2930 0 obj +<< +/K 1521 0 R +/P 2731 0 R +/S /Strong +/Type /StructElem +>> +endobj +2931 0 obj +<< +/K 1531 0 R +/P 2734 0 R +/S /Strong +/Type /StructElem +>> +endobj +2932 0 obj +<< +/K 1537 0 R +/P 2737 0 R +/S /Strong +/Type /StructElem +>> +endobj +2933 0 obj +<< +/K 1541 0 R +/P 2740 0 R +/S /Strong +/Type /StructElem +>> +endobj +2934 0 obj +<< +/K 1544 0 R +/P 2743 0 R +/S /Strong +/Type /StructElem +>> +endobj +2935 0 obj +<< +/K 1547 0 R +/P 2746 0 R +/S /Strong +/Type /StructElem +>> +endobj +2936 0 obj +<< +/K 2119 0 R +/P 2803 0 R +/S /Strong +/Type /StructElem +>> +endobj +2937 0 obj +<< +/K 2120 0 R +/P 2804 0 R +/S /Strong +/Type /StructElem +>> +endobj +2938 0 obj +<< +/K 2181 0 R +/P 2820 0 R +/S /Strong +/Type /StructElem +>> +endobj +2939 0 obj +<< +/BM /Multiply +/Type /ExtGState +>> +endobj +2940 0 obj +<< +/BBox [51.933987 682.937256 147.702927 692.912842] +/Filter /FlateDecode +/Length 96 +/Resources << +>> +/Subtype /Form +/Type /XObject +>> +stream +xڅ9 +@}EќyςJ@NVчec#KYb8B@F8Yot*v,6OZiǛn> +endobj +2942 0 obj +<< +/BBox [147.848251 682.937256 215.557983 692.912842] +/Filter /FlateDecode +/Length 98 +/Resources << +>> +/Subtype /Form +/Type /XObject +>> +stream +xڅ;B1'O6y"4ܿyچr,m"ȉcXD) ahҍ6w,9`;y jl' +endstream +endobj +2943 0 obj +<< +/Ascent 1088.37891 +/CapHeight 717.77344 +/Descent 241.69922 +/Flags 4 +/FontBBox [-1014.16016 -245.60547 1236.81641 956.05469] +/FontFile2 2971 0 R +/FontName /AAAAAA+MalgunGothicBold +/ItalicAngle 0 +/StemV 76.171875 +/Type /FontDescriptor +>> +endobj +2944 0 obj +<< +/Ascent 1088.37891 +/CapHeight 718.26172 +/Descent 241.69922 +/Flags 4 +/FontBBox [-976.5625 -248.04688 1198.73047 931.15234] +/FontFile2 2972 0 R +/FontName /BAAAAA+MalgunGothic +/ItalicAngle 0 +/StemV 45.898438 +/Type /FontDescriptor +>> +endobj +2945 0 obj +<< +/Matrix [2048 0 0 2048 -369 1517] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.68652344 -0.72607422 0.68652344 0.140136719] +/Extend [true true] +/Function << +/C0 [1 0.8431 0.3451] +/C1 [1 0.6627 0.3373] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +2946 0 obj +<< +/BBox [22 30 2061 1804] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2921 2973 0 R +>> +/Pattern << +/P2918 2974 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2041 +/YStep 1776 +>> +stream +/G2921 gs +/Pattern CS/Pattern cs/P2918 SCN/P2918 scn +22 30 2039 1774 re +f* + +endstream +endobj +2947 0 obj +<< +/BBox [22 30 2061 1804] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2926 2975 0 R +>> +/Pattern << +/P2923 2976 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2041 +/YStep 1776 +>> +stream +/G2926 gs +/Pattern CS/Pattern cs/P2923 SCN/P2923 scn +22 30 2039 1774 re +f* + +endstream +endobj +2948 0 obj +<< +/BBox [22 30 2061 1804] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2931 2977 0 R +>> +/Pattern << +/P2928 2978 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2041 +/YStep 1776 +>> +stream +/G2931 gs +/Pattern CS/Pattern cs/P2928 SCN/P2928 scn +22 30 2039 1774 re +f* + +endstream +endobj +2949 0 obj +<< +/BBox [22 30 2061 1804] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2936 2979 0 R +>> +/Pattern << +/P2933 2980 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2041 +/YStep 1776 +>> +stream +/G2936 gs +/Pattern CS/Pattern cs/P2933 SCN/P2933 scn +22 30 2039 1774 re +f* + +endstream +endobj +2950 0 obj +<< +/BBox [22 30 2061 1804] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2941 2981 0 R +>> +/Pattern << +/P2938 2982 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2041 +/YStep 1776 +>> +stream +/G2941 gs +/Pattern CS/Pattern cs/P2938 SCN/P2938 scn +22 30 2039 1774 re +f* + +endstream +endobj +2951 0 obj +<< +/BBox [22 30 2061 1804] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2946 2983 0 R +>> +/Pattern << +/P2943 2984 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2041 +/YStep 1776 +>> +stream +/G2946 gs +/Pattern CS/Pattern cs/P2943 SCN/P2943 scn +22 30 2039 1774 re +f* + +endstream +endobj +2952 0 obj +<< +/Matrix [2048 0 0 2048 -369 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.68652344 -0.84521484 0.68652344 0.140136719] +/Extend [true true] +/Function << +/C0 [0.349 0.8471 0.5608] +/C1 [0.3333 0.8078 0.5373] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +2953 0 obj +<< +/BBox [28 32 2046 2050] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2954 2985 0 R +>> +/Pattern << +/P2951 2986 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2020 +/YStep 2020 +>> +stream +/G2954 gs +/Pattern CS/Pattern cs/P2951 SCN/P2951 scn +28 32 2018 2018 re +f* + +endstream +endobj +2954 0 obj +<< +/BBox [28 32 2046 2050] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2959 2987 0 R +>> +/Pattern << +/P2956 2988 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2020 +/YStep 2020 +>> +stream +/G2959 gs +/Pattern CS/Pattern cs/P2956 SCN/P2956 scn +28 32 2018 2018 re +f* + +endstream +endobj +2955 0 obj +<< +/BBox [28 32 2046 2050] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2964 2989 0 R +>> +/Pattern << +/P2961 2990 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2020 +/YStep 2020 +>> +stream +/G2964 gs +/Pattern CS/Pattern cs/P2961 SCN/P2961 scn +28 32 2018 2018 re +f* + +endstream +endobj +2956 0 obj +<< +/BBox [28 32 2046 2050] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2969 2991 0 R +>> +/Pattern << +/P2966 2992 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2020 +/YStep 2020 +>> +stream +/G2969 gs +/Pattern CS/Pattern cs/P2966 SCN/P2966 scn +28 32 2018 2018 re +f* + +endstream +endobj +2957 0 obj +<< +/BBox [28 32 2046 2050] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2974 2993 0 R +>> +/Pattern << +/P2971 2994 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2020 +/YStep 2020 +>> +stream +/G2974 gs +/Pattern CS/Pattern cs/P2971 SCN/P2971 scn +28 32 2018 2018 re +f* + +endstream +endobj +2958 0 obj +<< +/BBox [28 32 2046 2050] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2979 2995 0 R +>> +/Pattern << +/P2976 2996 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2020 +/YStep 2020 +>> +stream +/G2979 gs +/Pattern CS/Pattern cs/P2976 SCN/P2976 scn +28 32 2018 2018 re +f* + +endstream +endobj +2959 0 obj +<< +/Matrix [2048 0 0 2048 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.69189453 -0.84521484 0.69189453 0.138183594] +/Extend [true true] +/Function << +/C0 [0.8784 0.1725 0.4196] +/C1 [1 0.2078 0.3059] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +2960 0 obj +<< +/BBox [40 32 2055 2046] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2987 2997 0 R +>> +/Pattern << +/P2984 2998 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2017 +/YStep 2016 +>> +stream +/G2987 gs +/Pattern CS/Pattern cs/P2984 SCN/P2984 scn +40 32 2015 2014 re +f* + +endstream +endobj +2961 0 obj +<< +/BBox [40 32 2055 2046] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2992 2999 0 R +>> +/Pattern << +/P2989 3000 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2017 +/YStep 2016 +>> +stream +/G2992 gs +/Pattern CS/Pattern cs/P2989 SCN/P2989 scn +40 32 2015 2014 re +f* + +endstream +endobj +2962 0 obj +<< +/BBox [40 32 2055 2046] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G2997 3001 0 R +>> +/Pattern << +/P2994 3002 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2017 +/YStep 2016 +>> +stream +/G2997 gs +/Pattern CS/Pattern cs/P2994 SCN/P2994 scn +40 32 2015 2014 re +f* + +endstream +endobj +2963 0 obj +<< +/BBox [40 32 2055 2046] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G3002 3003 0 R +>> +/Pattern << +/P2999 3004 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2017 +/YStep 2016 +>> +stream +/G3002 gs +/Pattern CS/Pattern cs/P2999 SCN/P2999 scn +40 32 2015 2014 re +f* + +endstream +endobj +2964 0 obj +<< +/BBox [40 32 2055 2046] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G3007 3005 0 R +>> +/Pattern << +/P3004 3006 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2017 +/YStep 2016 +>> +stream +/G3007 gs +/Pattern CS/Pattern cs/P3004 SCN/P3004 scn +40 32 2015 2014 re +f* + +endstream +endobj +2965 0 obj +<< +/BBox [40 32 2055 2046] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G3012 3007 0 R +>> +/Pattern << +/P3009 3008 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2017 +/YStep 2016 +>> +stream +/G3012 gs +/Pattern CS/Pattern cs/P3009 SCN/P3009 scn +40 32 2015 2014 re +f* + +endstream +endobj +2966 0 obj +<< +/BBox [40 32 2055 2046] +/Length 75 +/PaintType 1 +/PatternType 1 +/Resources << +/ExtGState << +/G3017 3009 0 R +>> +/Pattern << +/P3014 3010 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/TilingType 1 +/Type /Pattern +/XStep 2017 +/YStep 2016 +>> +stream +/G3017 gs +/Pattern CS/Pattern cs/P3014 SCN/P3014 scn +40 32 2015 2014 re +f* + +endstream +endobj +2967 0 obj +<< +/Ascent 919.92188 +/CapHeight 638.18359 +/Descent 250.97656 +/Flags 4 +/FontBBox [-432.12891 -302.24609 677.24609 1011.23047] +/FontFile2 3011 0 R +/FontName /DAAAAA+Consolas +/ItalicAngle 0 +/StemV 68.847656 +/Type /FontDescriptor +>> +endobj +2968 0 obj +<< +/Ascent 858.39844 +/CapHeight 734.375 +/Descent 141.601563 +/Flags 4 +/FontBBox [0 -150.390625 1000 863.28125] +/FontFile2 3012 0 R +/FontName /EAAAAA+GulimChe +/ItalicAngle 0 +/StemV 61.523438 +/Type /FontDescriptor +>> +endobj +2969 0 obj +<< +/Ascent 1088.37891 +/CapHeight 717.77344 +/Descent 241.69922 +/Flags 4 +/FontBBox [-1014.16016 -245.60547 1236.81641 956.05469] +/FontFile2 3013 0 R +/FontName /FAAAAA+MalgunGothicBold +/ItalicAngle 0 +/StemV 76.171875 +/Type /FontDescriptor +>> +endobj +2970 0 obj +<< +/Ascent 919.92188 +/CapHeight 638.18359 +/Descent 250.97656 +/Flags 4 +/FontBBox [-476.07422 -296.38672 700.19531 968.75] +/FontFile2 3014 0 R +/FontName /HAAAAA+Consolas-Bold +/ItalicAngle 0 +/StemV 83.984375 +/Type /FontDescriptor +>> +endobj +2971 0 obj +<< +/Filter /FlateDecode +/Length 62355 +/Length1 124516 +>> +stream +x} @Tevfl 0(36ȈR,;& +K˞mR`f咕e\{ z{پs =p]b@N9k}C{о{;З=i+Z=E-^ #4J1E _`!>Ů*gʂ'XJ| /S|xo<(8R ^*-?^t}?3_"&NzN`6 +hq\f$zCUJ߇];pkn1-Q.,NWe؊OK.kx/`6 Y\@LӘW&`>E8 9<)yxc%6`; ~ ^VdO׃-{[l}||_[l l 2,ȣG-6r>a9|C&s]}@I68>ĭq?JI2>]$iIZ@'q@]@<7B)i\VprbeŌEbYԮ-aa@CG8$}B)3rFt)= :)W.!Hf3#p zdK'iEϺHT (DT$V$T0B9UqG飖TdإKTbE>4JѐSd}z57+ _QBL4*l>o gc]:9qstq_Ote砠3`Vj?춝vnϤʜ1Η1yŌsl9w63q.fzxO_TvC|*G(Jlv[X-—Xm— _b >Z|.|uy=v_;/]_tވ.la'6c[O؉/6v3|-v|#8 @ʰ ;؅CB2OB9∰91s/v|_ N +-ʅ8r3|_mm8g8363VV9a~9a+G?㢰pQ؂_pI،6| lF9xa~%6M8Ma3~# g#lĿ+lD!lY6Q +>y$l$|$HV | +1'zab6z@Z{3q=68m|D>g1Y,/_&hnMȚ5MDxkJל][vکkO3KYשRo 66ؐ > $!ɁO~䦔Mi}ӄM+6lڼiצM7͊ 6lln.|l Ŷ--)[:m2r˘-L2u-onYle*귚ۚu֊mئ6mۆmmq2Eeϗaߑ+cא]V*_Ň_fwkvs}Խ^ޔY{؛Cw>f_ܾ=}oUWAGq1htA_ H ėqJҾLە#mLZNZfooJ"mKRJZ?5<)SRHy+6!KZ +-+Zi-nvNo޽w)ގi''$swB6q[ŶtǴvռiƍF5pDm[BC,fѠt ZTe,CSH7$9+aohrWHqp6ӝ]^vve7N/^SFRxⲽ2YQV[2Q{6̲;}͛yÒvRQtmȲ ғ^ddGcE=Ef~mvvuDkȼLjBS0-G/bq"饢8//1zvx< +OO9jMMһvDtwk׬jU#y*y3HTNv$^#)C Jf)EPf^Hnx$uYl6v 3[a}R9jxV}X$b7SM1P3Rv- R IHҠmKG][n:łӧ$Լdo +☰:JzKK2z=}SzĔܔl_t+za.(򚜜}y3RSRTr!3.?&!Y]V?һ9һ ?˒۳ZBe͛wϝ>~z%BQ?sL_LO͵I#-Vϰz?rHlLޖo,8]]'8ʓ2iMN6o$g٭y)NY\8Lm^*_Y׋nY^*:;*nY +#ڽ͛QAޢY{Yrf{\12CL)L\#_BqJ y@ OTfпDV$=RX£h ʺj( kH.-3%hc(xNqkD9;;;I E^*9KDgM^[6tNlh^(;.2~"Fb$$L$ rSDBbV0'md-{PRV.C?au x?;T*h'jeD#ճ5CMEPgjmm|REEҹ bV?P22bU hh"ࡖVZVB_DX^X^ON7Coա>BL_Cö\A_GU8r 5(QN^ UFTxh|$̍Z|-G#mZGOGϽ¹!N":7pߺХC6CVu|nn`уAX񿈞mzsϟzW"!֌^z5굦*z=*r}6;*lք~eW0bЛWcp} ///!C?KG:^G61Iaȿ@g 6k$7rգV??c$z887?>~*l>& &n.|ELB&3%DKb1T0){a"S,'seFєEL:.b:^>ou"N"?Mp' A7w_0E&@<<|_̪ +׶x6;TD~"uJkBc5e [i?ivp=\ %]p=zkJS~JM|Rpnu{&[g._+(pWPGgZ +kI_SC]סw+W]G]C]7gjN#UٞVVrַ[ѵVumvģz tݬ|i9H kVMCuU.yV @n:ovWT2U [y]s?66,_&ϟD;duxuQV֯Jjw5V+nL_w=CtNZ^mi=7cQ{Q*seפK3kuRCGJWmS#_]ރu.#5{.*w۸-W˹ǻ<{9Ϭ|QSޛfmv^+7۾._U~=ƕߤ< X>^ֻ˹=K!ޥ7H╛LhM-wtvK1ߺ׶?hı.;˷'ey? D:y"g23J8<Rɰ˪.*)/z/!iGͤ LL#Jm`rQBQYfe-7~1ґ_F"9"?ww3xtx"T,KAC4i®d +Pr +DĸrrKLqŴ&vCoz;YMfFfL\j_ p 4ꯤ$AQhE H F2}C.x7=Fj>h?"/RK\x\bvjo'Ղ*gd -UeKaIBp!}떭1fٰ~:-J39G@=ǖFZ+ȓ8=-I: G,v?iZQ5 yPn-Gbyb9Fv^<7^Yb=Q[Hèc3T8zRKMe׻rrǣ<":nǶlժuV-:"~k)LFޢ+3G]~uİۖ|ؾK/\Ɓ 9Q>;F{ +i,<-TqD{۩vbGb CcRPy]JrvQI+.GF''+r^*׻]n6cZŶ;bݶؖı`qD6Si|~ѓcI_y<ĖVt~uVѕj3_L$[0try^CF7 ^IqI6]C\nWV)ֱ~戢6v;1`|1gtE_W|n5ufq7rwQ&ݏ`gԫ`-lļq +3,CRLyJ}+II,$4tDRf_ ሄ8b,$9"ea~!{h.H~x?pá|?GI[2iRrG QCs#[ +"=(2FDIQ`0cLϚ\Gv_؆|_4I1 e2AD'*j9CKsZVqFDDL ptƍUCW<>>`v$%7shZjݰ8F1J tY2c3~Q{7S%ꉏjmý{g +hCtã7O=gQ?gGB(,9<24^`b,,,aj)6O+_rI˥x469"ؖpHlTo?6e)gIء_/,~t#8%W 0ǿG)}fMWEݔ| jX %FJ/.Y%N{J` +YM B^`,(OtIn?+I=9R{-NR ۥYţ"Ű4MwfK/zҀ& l)88=fਠ JV(Ң4UR.sKnݪ56;9 +RjI)wfisG}zq-03iUaBG՜-_R`KaE/O,j-D\8Z0}a ̈́s9L.>aZ Htr9e9U/MQDE(Ȯo!ؿ`H H}Գjdf~(]\$˩7&s;&taB Ϻ='el)cafV1YiRE+/K?^dC|`V+4e>ߨa?MFF3 +ՊgҊ{7zJ1Gj1& .f+40(9UomI9"L26oǒf߭O6@%"YHz 㿑`;EcHCcI6A5I!Ej5Zр5k_U6 h8(|٤Rα ZF5Ymd*6RV@6!87 +q*&<1\rbo$s#d8%ol\5_ˈm̖€0$y" E5BBMBNdR(iE@%6t8]$ۙxmw¿qwGθHL9/E[0X8J<>|:v{klh=MK0 K]:(%ZQNEsvN>>'G\J޳@UeSFloefSE#=ǩOM'f~6z5099̲[~O%1ۃ;g"fW=m \ ,UHJD;Wz~_$}fߛԜ]Qf!)gSF (TuB&&ʭE46ޮGloo-OZH=7KX خH +9E "/Z伎V4R".)&LZ;[lW%~=OH,0+eL8%w45r^xYH˚&C!F4"4O5̣֦ɌVtIC6"'qZL$xƻ2Q}E2H1`fdVⰊuˤX.*Ji!H{~Eϱ22DmMmEώ7q|,*-nW\RQҖIUg5,;v=w?fxȿtCya ڝ[9H)$ /?KߚOI;Kf =FL"ĨQLRjbQlfvS.3(n_qi ';2o|c^:q4A:Y?&4Swciz~Lt@0 fGyzh׮g#% dT<2fR^  `љubSC4h*udeٯ}tpA3ъ:Xdo0-IM`$hUob`"&geh\"~7/TI1%YP{N_FI[.>Yƴp4XK}=K&Q~*=eN֫Wr'yɃMm3|Xaz_\xi :P%$I UDS^ N*XS#$*i*l:㡉ףX?; 0(=iiӅMf{DirvRZJutuN$&Z w 9QAEY$怲AZd?B0}.7!-E< 2Y҂5ԋ/jgN-r +rrrk${WIUI-%Àԧ${h6NN*~> SDoXNsGp6]jqb׼q h*L#=@PZ7Q02b#g4굲bZRuz"1 WLe%s_71:k?_[jω=|D Gtᥚ$:ZS(r!L}qv~&l;/\CPc}o3FQEi&B+ZGebʻ#ɤzrVW4׳o%\ XaE'<$P&#tJeTVYAiVcu%{wYL9nx3%Oqeu]`/ +a#?~#iW/H7hJK +9] L͊NO(c۴t'R|12)CAӎŒnPSE:,~A%AA*iՒwK*wqO/J +Wێ׾U_(da̖ŌW4mhI⿤ۘt +2M"*P Ұ5Z0dG>{ײDDwo%]_B:[_!;O~B+ߋ~31|尭&ޫe*\ds6f3֚Lʵ* JEӛLz7E?8ŗEEӇ:4vl&Onߞ {gv˹Otd"V2B!YGFp\.BvEMAޖ:zA\*H.ɴttppń[10n+ݮr酥IJZ͑2yVj}fg|JmJi%3VNo?&d{WV*][JSBxA4))D߂ *bzp,gX]@-S")rWNpx7!\9D?I1F߬R**˜5OkЪ$4b])B'yD'`<14ihݞ|5ѩ&jXBڬ0QI0<rR=뻘֛Sd"&! :iB$rz^‘]8z#uc8Wqr. + +ĝ@(DF6%Uc$ߔ27YX`~cyL +h7M$& t +Ms4ah2~^AӁgX>6^Mj Fhhi6Q;S@+uA+]]==2+-_Kp8s +v?p宂N^Fds9YLD;p40#BȂ} >Oӛ|C}lJ!*,n¨0#?~X4h$ Dusgwe.uuz՜ai i),bcfkFbQG!dV 9r: ) +9„pS=I%zKOEzJ wJ֯+G\huqk5Vdz{@ix~DE{ 悯5;NmŒ"7iin6F3GӰa]ܽ>hg"S$XIt$cm('0tfP6ԣէY4c`h ȥI(E]j*QMCXZlY ^. VдE1;A͢(/EQEqƉES)4_#5e%`9沌d`Yzm"׼̈Ni̚NZ<褜-ҜȨ48,nNJN𜂜9\Y*u]΂Qn9-N zwY0\Lucf"oH&odfllE|>ﻐ }9vpG|~S'w1&/y>K*_;7s{|s4iٗHkn=;D&[IB 3\t06eJR$ÔdؔJJԙ͢$LfL̔ ''|9%gXm Yl)LѬ!qFěVߒY??B1=ߟ//;X1JK9?Z3kuL@_0\`D< +i@Qii}KllhuD='zlR G.TT.uzddp @fYNNACgɋ7 =߀WB8snjѲ|/ (g7h ̔^g+=^T"j\5|4YET*Tx`].4M\sؑ,hAz veYfYQ}zn''pln;ȝNyEq'wVN\ Ɩ9Q+q]d9g$%KP)ϾViɣ/`0Jv2QBG9S4mWy'2QEEAE%*J%fU(Ѣ+"+gp!Qdk ] } 3 4m ErBY*dXYN[\KrX$V;8`,DGU*&|W\®$7/jc|{ ߉8[ӳ䝮D|OCN&#g|Sw&>F?L^yMڛQ]y["[mEvT|`DCx8BJLL3heĐLC 0A/ & 1 ;I$g!~snUĨYV{sHi $+Aؠkv]W(0lҵP|eRO,MWXڊYuYBGYlwĻB0  )HQGuUD*- -nPits=t5T,J\D,`'Ibs.5fMՐ(Z820=HÝP h,drYeݷ'K`C7o-';"-O(Q3DMՍnR.J\0v͸XEk]0r\yXjuz\˥FT ʥk8f]q3q +nb}7y6 #QRn~O=c+X/ i= +-0yM#pAGSQhKh{'jDG3Q1LiCp"HOZh0QV U +#++`bNW@)^jڤn_IiIw{Ӓ4腄m +mxO|,O{1<3h +B$Zɤ!ųSt ZX[Z^+98$R q67//7gt6,Dأ/bd=8o5?9-7Tk"'0?de~ !T4=MOͺOw7;玲v7u}kPGHl"@*NwSspĸU<VhzbcXmpl&&[*cib1bez^4 e7^7Jj%]bxUZ-~_?~Ӕѐfu{3L6cd3V2/v+ r~ybAʲo +sưBBjޝ 3]nۓljeӦ&}i^jY|TfGi ikz8V>˕KrPJ*T*T*T*T*Z-SRR4$I礼d)$4JLU7,\q?Y^[i(9rm(Ql٠1K64 +`|n43~ѣ~-ۓ'llvߞ>pGϼȾ#t'>OYN:i`Q!⁍z8)4N[(ShX{=>̳i"Π3s(|>}=iscqaG@:N,֫mꐚWńGu1Sj,]AEv+O\jZYboP]Hq|=ùHS p+Dۥ{'&nssCB_@o/0ٕN"*yHQumy;Uq{o&Sv:hNu(mwL+B8$vR [}vU-/VmEaQf¯bYjXaM'+oL7>FwA𓌐8%vXO"qO#5+wdVJ˲ #j85d [MΝ^@YNцkXR6uʒ:2UE[6ǘTfO9/WYDYn,_a|r^Ֆ&0V@@OHc5(zxm1䪔cY+PV^Xr)uVe2e<7e'-#v`&Go4#)OOw]ү9sqm'(mN; NUE:-ΈUDx\<*NȻ6Hf~rv5VX.UW/Y[iC*n3o /\Vµ2TA儱_n&xTRȧSHx*n`*ʄBS +"ڌ;Ke!XXŲxr.+ɨ3ny Wn4CȔ_:`-Vy0#RA~;"pmäf*v;pXT"g +X=PI*UPU3P c۰ڜ#X]|(t )3(PN]٩3=>f5npZeqOz }0ߣ˒rw[ϐjH4F] k qiSJIk\ymp˥3P3Zڒ~UJlEV/c(8&EqCkm=gs'[:;K b!l2LFeL͞:ǎ;Ǭp&-k)~`#ǫ~S}"-v.2@(aud+ό# j',ap oxGlw{{+b}wUv/x=\_Jx`g&=uȢuX'ow]!&\tWvGds5 Iyz$r0klU:*MK3.暴d3ChHv+$^ًBqƟ 5}Jo糑JBﴝ,fKKF!H&@pT,mUڕ#ʰ"&ZGWe[<z)eT*^=o0CN d9$|n-jt:?,*tH`YEyn6 ;a=l76Y4Q\56F7w&1A6,:#3/$zՒ"+ݟ3n~7 #ln=IэoA,}Wn_Iws!4~LmG.Ek-V!(9C(]:a+tM̛ތWDnZ]>πBz `tI8)8`c a@бlqbY_ʜ )/ (tA]jzRC* +͛y>[KQWkK +M66Ӹ36Osp1X?E$KٕC=E!g lxbA^}>Ie!7WM[ UJ^l~QE]%AxVZZ&LyrU}\mձHH SgeU^[ybdY67cẀ͠ƣp3=vb~ҸȉǠ118k6%mD&*1tهbdUZ{bRRH$[tJ:#1I/O%an{T`ZQqNF{_^ +`F`/ruPJCtgdaX;A6Ħc4ãj@Yo=XypsKs$qGgh|e޻?˲mƂ=+Bo7ZOmuL:Q(?#8F" . ty`gJɃj,6}ةWJ !sPP␂4n!)8%+㬞6ms /$ kj0^r+D<|LJD=((8l> +0~d6:~?h񏓓{_7ʫ? + Ƿm +uVϵ +pmHUZQZyqCd7OUGlj#wAxG֡[:h;@L G&2!vЮJ5ėd<<=[f«Y;'=.%/^;]nFmS̊=p/Dz O!iόz \q}y*rIN*1I40ǁq)^I.B TIxstXJĕbĜYswY[Gd_m_yۯ(>DF1K!Cwnþ GKXLR襰B QzR!^˒-&_4"A@}<]*Ի\5袍.q3^77'Hjf\؏͚_Xg^X[;1~~ga-,D7dҸ1.N7}Xo_+v̋4M">> +T;.֩ kTFݮTkk=z<t&PDA0 P&΍%81:p杂̞rCǙp6:iI. %ځ c(ծ^L%\P-1Ȟ]PslDX c]$YQrW!%`%5?>A8-.rd">BN!5G%I_QNaq؃ÛX<-E}* HA6`E_A*hMa55 nK"WS|h;s{Cdd0uV/ +u;lگi*!*$TF:͹^Y˳]YF@! /L{g4i/zS=``(08dwc 'rӈD( \REGB$a4KUl*ψs r4resx揢D'ހ2cc2WM9NrYtE}d {iBQi(ѕ`8kAO0Ƙ>4pEa>/DpPPi:&zUP[lEz ߵf]2` XŸHWu^l<8]=i=hVZl"-w!@|X[#po%,_gQNL0I3.jec˶MX/DvfD*ry vbXOl0G-g׳_ FA7;f:3Q̤j[2 +2Wc,wv ?5A*C02=xD`b(1m%0J`2.õmb8(J)Lļ(DV +mfQ}>~򓧆~Bwu:y?յs*JE^ zXmJ^Qt5*= +UԄBZP̷H7x_y"r#f#n4١؏ڧ킝9.K0Fe%%SN?e7_Ӹ2d肿=Wi=Ic]3~(F_=s"A'AaDDH& 0Ϟ$,mz(|$8#e$E^y$WWQ,5(=72tS5>ɪUiAPts>Ƅ Q>i>\F^/fb(Lm5L\Pgx%֕(\MC?/ 's}_6bpطp;=NamՑ~Ƹc~8.L0> ""h: !h^=2\f%7BuczfLTsT*ao,PAێcc^:;U2~xgUiգ\C׸%Ћ +X dMf/C8q\c y #a>Ea$Q9s€ +-^p ?x` &aud!Kݼ}=qÝWp`_N6zEՏ-4wr+w?; ~wc> a|/؋/-ZgM 177z 7|3KxqHNX#HyT֤D`zdAU,vʶLe7ːLe9 mxaG+BwD"{#.2}Gҳ:Ϗ?Ja>͕X>AdI0aGH^. YrDx9%0;f}ܘح1[^267掤96y1GWZ'߳1#_k67ޅœ~ω%B;2Pxz$X|q(8I/pȫN/ ب/֔StjZ0c1>@qi]A& #ӠusX*7ǰTT U 5Uݢ\GUi)BgE/^/6rUktws_e}^;ʳ)\ld/'saΔU;ȻvҝC1DX,!ÙKaA(UD _vwa0  cZH CiQ7- 32HQY]58,D9ik/Fy~ߎ4.[r+jZV'/̥ggR~H{衹[q +,5r}p7FǤ9V*d9EvR|ikN_Bӈ$ҡ?I!^!sa.;]1s 2ŗSnS]yfycp:1+LfbTzqT ؍<yFnZZ)O_! +C| تT,Dմ!"91QL3ði7W<ݕf_vKjjF'߂e +ko{Sf@6%& RCp~HU3RE,[R(l& +v$< qÁhEB/CBҢxZ^6^Ƙ(+ (L"(h5GZګ{Y5+5*6p*w rk%&&@䛲|T4i1C}'"9$ 456W}oɭ}MÙwO=F=>zr>hQ?RN!ADSihw;hr88 ^Vs,RCb# 0ERE EP"UH%c BtNg!>WM'tv xxh@oDOmɲ2vt=Re,Vu--ceek=qVoӝqPu[;[%zDANϸ2.~Wkkk˶z5utZqe, 5x,'{f`Rf,lhMJ\f$<#vn8x~vdfE G`Le~ &s%\ SgNEԐˏ?:+Nov@QSU?.„ˠfah wÂOU*OҫzvWWT٪xû&]U'.xR~&WaR~&WaR~?+'J ϴ&U)mw[ff%faEo 3AO~̴Kr XfexȽWz3ch30Ͽ˯yǪmoegO>Il?om5Jݶ+| MD'х$ lJ"*X6RrLeJr#3YCk~XbZ]BBYE_4eF&e2wc_yy" }k3QDq@.K]BK >zES`2WN+]9PyX;i@TA!&% لclH\ w9+V!A"44Y 1cr^Y*c+ΐTYE3iր&~u]^Q{+J*v>̈.?Gsv%|mۇ⿗e0@/Ac[ Gf:羌+ŒaA`8BY6㵉\2!.jT6[!yL>'e9% %j"(;xIHBi/#+`uݛ́c>17!?Y/uŰ)[s}K[Cvk n >'0$%)HoE}<.OnQ؞RTGڪQrqJZQZ0$  o(~/K:D٩xv d2>i3ĖܻNf;&'s;r V:!QugjU֎ ai CQ;25#WJF@kŠU\mW/Mc OWAaljU:|0l4f_H!2}@: N M&1+3q|vtRS&WýGU3- $uChKMjeگAFF4 +д"(zgX"X9)w:LDμOEXD_JG0"K^CIm@۫jMܢj Ǟ&]p%h<bVdi̓lC*ހggԓ;==8tB\Ѝ]Db:\E= +-4)XDqf '`9Q(;e<%aNBQ>d?DՐ̘~;f#Lm|F,Ĵh zctMlOpqDēM{b@e-dx2|iB&$ǨJҠ VW׮(3 +S ++x[:Nq0JuZѓ#6۲%uonjZx&pF>,1iFHacrÇFBn<X;y}g?@ |xI"n-{L y}pZ R+ALӾpG"d9!7"u _ BbŪ`L3oKI#'٭=tX5A"k}? xa7n jƔK /z֫{w{Y8K="QzdLNZpjjRo';REeaI(sӐ +gֱ)"}Rei#䧺3HeTi]]B ğVn`wwI^ɫ*!8}:珩LҐ(*  U&G) GL%̨ᢷͿ1Wr"qŜz`in@mI &7qvtxn.(šHpt6*(NeKRXd^Y^d)F>׭c[M1q +blȴͣC Ca5 +s+Z2ڠs.l \3AD'-P-*)f *qym}>Gi(Z.ft,, a_;:Fe݃%|474F2o;Ps(f6ZU [b47lE5$}2wÓc~.85$n=Sfw94]2Em5لYk*K$>PJRȡf 7pLs$ O^^π +SLdU5`^b}(P_.d~ɞm:k)>sr2n11#Evpd<;jB t[l&OEލ믦.H,r"OZ a YBP1S% E}̈́l}54BٹG5c | iz M 9 +r2{ hcuȼz EL/2;,}/!s c+bi C>e ov/ _|Avw.:lTg|GG'᧐CIҪ"6{rUDI49G\EV. 0Th;p*L0saqqўYTyʋy})_U_GMߖ >܅gP#"@h$tT04(PyH"4D; +y=UVڦ-s +phs27-] (ڥӏ11 ~-{^'d ~.=Y}%NB5;|yu?ig2u&.:b;2gy3𘱝}14Xjj*{ z*5ݓD$'M'B?-N/IRڅhR 8L^pFaoL4e}Q荂F"3ſ=i A z53d=YemaMl'pc4pI jzyY@1puqqNj.Su!7w<&XOx󡣳d[R\z|7nǟS)b,4{ygNe7">"?2jVrI{X9),#}A- ŝ>GEq +F2&d9GbjJq P)5MNE| ̸tZP\ b05ssBͅAPQ/e*hPrҪ9F+M. OWyaw/xP4)։DY܅)X =$kϲ l/;h@;΄&s+`J I6z1Etb}c>iim|r-Y\lY!W[ uvֳH]ӟD\Hx%列xak!o0ʷ bK +agEo +VV]&n*"ʴNY;>;12pIH ^j^_FItr1'/% +nso37}ggsA{v%[#x +'qJjR­(#ĸmu6lPOqY Y0(" jŏ8OȞ\bXXbn%%5k+@Qf@tD{SRFb[=GJ$Kalwݴ^< FKD0͟is/Ͽ?⇤XB#S![H/MׄzC܃VHNvK /nht&P9e "("&(#{ ɧ-{`侅aDƢuzn01W5Q &a?nq!hԯA֯ icڄ&jCڄ6 Z֣1#Sy>#g|I@?Cn噔Uiׂ|fu*UHPMM~G' 9b3vGs:h١'L)EA qe2WVV4h-ZvNkCsh̳9RHE|NBAPG3ܗp LZRpR(!:UWB4EEQp;H;x0煿An wDNN6PGjHݶT0tCYؼ x^ y6e5ejʥ2(;RqcaKk +`EX`$p8`ۡ ZFN)[m +;@ҧQMQC`%m7fʡw^>f{ݣ5a [1?ó q5PL0MW:"i/M4I.hb_Xav;Ml{^,Ss Mta֋WNm~GqZ{"(qXi*X:ʳIw&0,e +; {$560$n0|$LD#4"[YQ(p\R <^*ыJw^gˆOakpsgqCsD(&fn6$Le#B[Ϯo}dO]|+̵ũ HWݎ~ǔCp_38 +(].Vjp]B#>h73hOt7W Bh?稍 \x\AaG<=@ -i{Jרճ6apA=򌑎34B)sG;]ƫbˬh=WiIA5 !ᷤd_1&}+#Y2ndfw%c~pÁGg^dO8!x`*5s0GZ_.x=\4cT;)9;m $"h5NO:q57w^7u;ҥ3 +L)aOP*ˁ .+lT?ηN0Ǜ"*̏i ӠR*&.ã"ÂX+;V7 T4÷7tXVҩmhiJ["Wwyx}#/{~xW߬n!qp]”akj߳kaWWQ>=đR~eP%♻B !z&CscNpyS^@ +L@$XOX"+kb< +="eION|J˥Ch,[99/\(4CBJHGaO3Y#9i58ua fxt!g}K3TL_;`-?S'/0/4B<ִwlvqF1Aq8e.q~;K3qJ I ph"Ý +9Z8n.םwO+-<(Yf3\KM# ]Gln6{Nh3lO.էښxp_&ZMĿeIiFS~ېmv&m`W\h +w:pЊ!|Tyq[G5p%y`Ĭ_2>fdhÉo&-XuZ~99C"w~w f2;jc;G~V@XWDLvF!-zqp uޭm^J;5e0]6SFih:e4}H;Fm6mwצZ@+.*t v& $f@K{$o*Sr& V]x7XrK=Q=twO~=+0ٷwR%jox7{j#;n0~X2?7 bd5oɀ _oow'Wm;`;p$c%0!<)!vL 1q&i?YR-XB5U'm}G_>LgP @P~+_\0׵'1;f%7WssӼcy6x6z<<=6oZyk>x=y yRIJ;ǵ4Я$TcJ^|')xJxΖ|\~HO3}MϏA=ڒdEA FWר vOlF:吆u䭤:@-$*S|'gxmaxa0P7,V^$XSb@QD38ctd,U~ƥ <:q /M6M2r{'?ػ[/oD~crC%\J<-q)ߪ7zoP4|0pU&t7w5߳qja!T#w{?#a LCZ/g񆼔z[#d[MyyFwy{CތJu^EHm$_:#=+p.R jQEEBעEt"[OYrS07h޼E KT$N3?S :%ZɐCi0Y/HTVbj(U-f ?Ԭs3$sTA-?AqfUe)ۢ~se l1D.XT^w\4Q^*tD;G $ ]{[[ssmh<'&*o=p썱ɇpa-CT~kX qRpP>>ofp @|lO4c8y:9uj'Aҡ`Fn Flkqz[l˺-N'gzZ%Zi ^^#fKl/7שb1(CNq»rW$쭞JNWOO|_߳_qߑ)?rXk8^*g:OH#ۏL7ʤ@UaGO<͞͞}>A1τG@f.\эQzF!^ܕh(ЎEף0Jlt|sK; I|oxD䣻Ap8bllrsw-1k:Oi7g6!8AxSUarRXcuh-eq6l15c{xS;GP ,^2 F&xJ0$\]hc0w6pd4{xlavl*s"m”eA(҉ :N>E`zTkrW:c<<=p3?eJ~?̯ë*_O{;ڎ7stϞIqL|M8aYH‹#9FcR|䁆1|>mBf|Vw@%YB+]~wOA)-_ؐ ܂ĆHrl^Y5k,ztf60k,: |ђ5kVa[m[k}ն6>if +}K`ǒ}K\|+Jז6;J奫Jהn,S!d0EhQ#:j-)E_^G"ÚfFc+RPW a ++Qqt!ePО7Me +a/L!YO&Ҭ͠uyͫH,\T5Z}>'S*.>tVGQ)5*&{L0ה5bQjQU}!:_>6G>쐼fϞ.s|^ wP>*p|W>&K>17RVg1e7|'S. +(te +,Pl h g%HX%Xxb-†Y*-Tk4fTh0P-Qo z@I!=gc:+2U+5AEЦ Y9Fefk7-FMv{60w%CX Nĉ}Ϳ ɻ PĻ/}BG!?&KmoowOYR`:DxzwQ"./Pȭ)pwB6B!.^5(HbhWTB't QFFe%Yr4Qp^z8lJy%>|^??vxPwߺլpMa ,FOwrM`~{ 4J") [IjbI` Oju:U*UNYSP1ݎJo^{%9 ~v}'4kg ?ErdoKyKFyJQT%ۼp "3 +DY+ +h@,((0_ :Xg&:g.D3LvYJPZ !bZ )CaĠ/A 1ur碀>0W6-97RJ +) Uu& #I9%Ѱ$fUxlb,/pS-\+/&>񏓓KoKW cwS0OnmmMo7qw o.q綣>~_wC\~yMe'by VxIyIQR|%[)-D5czZ`$J cf<Tr *j¡d/9h  jQBjF)Y +0;U!,u>YX,WSBqx ígD-%ȿ"9qr/N⇟rϤ?Se&EjL~OmxK)'?>`厼x SP>`xm ( V|VhЎj6`s +Xй!N `߳ o+Ysɷ`'$qvy1 \dUUd I4 aVaFvˏj3[ ߜrwvqW:Q hXA}²akg7>6;6alel +} (M-\е`h! 8X7C7!4$B$C + +sDgH+MLjIK.g ,um.ˆ.a"e9UCIY4z~R?Ia<> m/h{# +*[n|yϞ{ٵ둿 GkyfM{Ɖ==l}իi:FOsѴ7.J1*{ޞv + @k:8^h׈epa*1# + +sDh#ڬQ1 + QV'Aa.\_y<_̞=Kb//u]ݺuOK_Ao?p@QqJY$Jr>V{ȇh?YJwWګŎ(k044*I:?qC]JBwvNdB +l/%RauphPWPZ8\~9iU`b-tR4ag{ת x"$?ݗ#Kꖜ'TiHǹ{&ܲx>t-@`.YY)N]̇UgtA% YdrJB9+,,X. Ra_#?g[W^܎:^Εѳy?t07o~?&]ܐƺW$f02[ӗaf%>s%4)=eh4a ـtr\m%8SKN D_n%"|{ I % }a 5 $pX po3$+ `W)[{ntCeM^QASVvM'䢱lYό0",؄z(nsU;E.ռxwx=ƋW_uj<C{0t!3}\5d<_n*!)CgAb㐨eT\;0b6Su4DaZaN|<.j +EP#/o㏿?}\!rIܹ@;ٮg eå߰?dmL@[7(|EfN[Ap /Ț Α.wX,@C}H1'X B"OiOh0p׺r׻[M;`q:\#qp)>?hwvXn"{zbCb0V0 h̀w +!\I@~ȩTTXìO1ParMh`Tӛ`F,mSO% <’c[^n$ؤM9 r/K:T˖ Oְj^W3=vMc-Lã ; ++s{h)r1!֊bG7bJ +s +zS#7'(2<|Q|s||D-'v2mJ]<ٳU>eO"!狐7j-Æ#3J=( ƾ~V3AxwwZuag/kO|6yiOny`/C-;++kmN1\\pNV8iCصZ0G/=0L6uz> 5\Aab;k5%;CaM|`fHp/$/z`fEP#"T 3e.c$N* +!"+ +4{#` $ +A TS d!"4YNi2BVi p }"Imj4Ⱦ\bqɪͦ4tZ0\C0461tDG-u?k[n_$แɄO~,})C_6֦o;y 54 fThߗcXbt_p5TE@™sN@U6@g@ \8ʮ|su!_B]!Q$s~!nzܾܖ{0\- 1rpdl0*͞7+$`8|zH=ߜ485>]=)YS! V*ƍN+  #t!(T|ʭ%9kUGF"|$J8K0 3 u +j"W\/9%U֗Р=+_s)HfzK +aYc +b?C} ÈZj{?O[?^8q̯Vϭ:;;7WEkQnEF!MDi4Rǹ9_s\_$YiGEVD:";""H f>'pLR:Uo}xl63QlW6 ]oSϕa~_.jp=H!^pA+PpU5A9+jLft-m;1*r uDE>9͎J@ZڊLjceajke ,5в&L&iXpT!G)m)Mߘ;a|PDwLR~+V7"_v =/Ð9}^G}@|>Cl[ۗ|ks?9OL;Ja-IM 2-a3E}I\e\>ș{f2XcL?4,%~:>PO +uzB hI9\WGjG/Vu`_ݲE&'0SU qGLg, m^(dx||@^>P_,_ +}5|(B@/1 Y@aU&=K#m>w}PK)J^>hKFzSDQ`< mHBş jIkQft@sQVTZ Dc.7sq9WYY^f\c}xЩ&þjd]lV:Mjegrw<\/_|biJzn?Z>.ya"<J]"YmaH!Fm:c*A`n5zоPޯO%"CV{0\aSӣadmPM'6rec&凃,?x%FB!FCdBlR6# +Fa<,yL9nDEh*P"#[G7<'Fv~G (/ed!l+xyR*nGdJKDK"eRuײ:O4U˨S)`%1SRԫȍKfS٫R=ҶWG:s7ǫxs)KSɓSzAg9\f1h e +PP n I2XE@Ts-zU?r䮀Z}( s dAgl*Q%⪀r ')Bb,q,}O . +(_k}=8M ~⁁ 771[(JG d3}dB`!&7ؒf`7g6eCpeFC G,V8ʁG!9@r p;MLw9 )2zJ8p[.9[a={rylxO}FKy񳺿>VG#M^Fod)k5Y|Wr;jE? ĬyeIΰV`eҲBoKv?%hP=B ,h_댎D3QMA1R%ʒ rPk  __R*I܈ `U<؂dv&3H5_o[}ْ2E8Ai41F5blfV^3!w~xxbg-֦bkG5qg -{1E3dY6375TZ`"(ĽIy“ gy6߷kr kJ֨SdD* C!.JE!DhOWv渐qs\;]P.Y]G^?0f.s͓.y"uw|yt|41?fw2)J w w w w Jȗ&vtZ\+rhpvsQGkP 6s좛]Ŷ( +ݽUkoIg&]WTZ IQ! (kO.р֊UW +SP1nfԧ?~Jw\>($=5*p.ہ[.w v-, F>GtKtlik7L3l[nyp@TٖY^|hmݎi tBX>AxEd'b=sP9k~ݦi"XzJ_Mm096 f:Hȱ@"9 +-M'I A&W< v^apYlu]t탃;vݳS*cF󉏼1>DbGa= &9Ʀ&E9R}<_/o|ppA8v -aN~E;ʤPۑt+t@b:0\Ftpt-p1蚵mZ\ ǵ`+mf8ΏC\.ҵb&r"LG-ZaY:,aYX6X6Zmr.'"dH #h4f:n-/[v%EskZiXJkgX.+4X[Ԛ#LJ/pF5ҖcnhnWڭ|Ħ{/?L2!̕l_(>  9L3,Yfp%=K@E»zxŸ 5=ӯՁAV׬tNo +Sh (5Pq:)]jBAKH!!_]F-ihjIi%jTLr +Ugt}VS-"SG)0o͒OUsL.ܚʆ#"?k{n}|c +~GI> )o=vgˇehI.}#N8KZc.ϊT"xE0..)'6@l@Tva-}J rP uC B"-IRƆc|#_` jnQP%&n8+,`5 oQ.Kʿ2UNa|zV+4Z%+*BǍ)O(3GIŹsWavqP_7/n<*;IveLf2*Jҝs_ aOgw"+sbsNs!JA`v>VuhA:B_O[p8^BhHa5V]sqOw}L +ipЮZfaŧq˝6) +(Ϛ2Oe5x2{ض(o}v'u:VUc" + W'DAqL$ Zty-!`deؘD#NI` s6):'ie6A7Pka\%cV X-`K|"KQGE0y!!o~+2xH&[yqeÙRSCcΥCiexg"x]ZDlwW!y7_wm=G'X>WGx]Z|ف,yIz;qpE2+5.;?"""z'B>~+Rْm=E|(Tr q.?Ȭˮ +`1TJb.M2^Qv2V`aZ 'wMc3%۝SAmNfTr^5yP34~Tu?n0w+G]~s~z~?lǝ*-iAl, +C/jdÎè+RHZŲKz|<)KIdps-M +%Ch4 +EO}Gwk?0YH7,)VvH֩:.fڝӅn*gnjkfȰ3Fq`?k{aQ Vn-ē gص`ҾEL~M@* 7wW)w`_X(zޢt6=J$H&s0WN܋NN sbz+srf 4@EٵfτGx:1Qq?/os ~<~h5EN#XacE~AxۨQ qzj6 +)#wiNU`FG3\[(x. p_Iz@9 epߧhew|rWmUe9Lo][pt[q&BJӥ+:*@@u!H$ Gb+C%~ 4v/Cn)[ݴ 0x5хY],< ̂Y,U8M"v&<=~:TQ?%(B1 3π}uj6CW EbhThQjaР(>>4iTI㍪9/.+|Қ)>c_ϳlҚrU4M(99grq޿u|nz NgOҊ*?ɥ0Ua$SW/h=(@ 1."&YGBnPZQntТQ{tZ87%ܲZy0o~^|eߺcŽmi K*7\)|)O[;u곖23$wD%N+,y҆:6)gF6s" + OV; N#ňJNLhʵ%: +FvvTKSؑ\C~)⠄Bqő"φ'<&=zh'mܑAzz7pݻjoc̶-xHΒȣw-rq&b W8)$>WUVih7h ڍmZgœZ-gdThMǔ1.P)B:M4I$MÕ4~)_B `2kGZ~@ ʚR*c9fAl`:T/)CFfD\=$d*=t?tTI+y|6N\xhށ˾:(%'9qr#Gֱ]`%=MLy$ 9h(CwB_(.Y#TPHLPU 0P܏NTCE~ #v ;H |SK&gCWsxB/⫲=J-7 'ONYicW tPHYA0OX- +$1㧇0 tYTq\f͙yy<86N4TY<+A|JtZ!#ש񋄾ON=@ARr+:U?(TI$-Xde.q~bd14 2y."BzuXͬR3m$@fIV X6oG ;~gqpFp6I*$]愄J3;Z%֊t%n(qorS-1|Z  fgp)yB<sUzEoԔ[4xcVrjT˳jӓ)IOEw]@ă_pWVyЂv s[#_ٵ]ğ/~rczp㣗0zGSe:B;9KE`[4&@/}m- cj +*ە6Ά]F#n'umS`Yzyf +qxR*Y&tUF,׭]O l٨'0kRq~_h+/vDL8;;ңKܖtWrgLj46Ѡ/+N} ʗr|yπґ@">\fCѓa/9lF`&֭c:8+ML79LGM\̴ıUI@πZ/8\̻wW$^Й\P!dUbBa ;X!jUܕBP/&>d2CL(Y_(MZd|xn(1lzIVY8#xJOd\tGe#ޤ׀LG{*=/C +R/ӕ{/Yևc{x+{QXȺO`}>$0,mR>8A'U)aJM+QE[F)تujg|Gw}鱁ɬb&[;_m6 !nUXk1p!C! uغ>gtiB<@F`uq vw[R= b4vfqں '5 +ᢢ@eJ6V #YSCx5k슚K\M26f;%Op%Gܜ{*-Ѧ/#.? ۵,ȘƇ <OMUbϷ/cG~Yrx_뵲":u]8:7RD J[@U_wada3̼7 y S%q7&6mæl+!ƶi+MZYu&ق)c4DucDq]4IjCc7@>^88{X[I+cmv>mgZ+;a:+*Va{m7#;Z~FmГV}/}\ݦu*E7df@v]*db+=R@>}C?O + & E{nfsSKcnttk#qP 㮑fORBTylKݞ국E4CyhmfGjDHd-.MWߍLrh*Q=eH<\s<<+-JuSߣE +؂GJ"^ПRdJx$@XJ2! I#;gsvZPnC8FL%S\ +*g( /D ֐BE0F-TKUe-ʛ8 u|QIBvN.=Ȓ87L{̙3gN>^;G1f=L3Exg+A(_ +Q}Q +(ɟhA^腸g+n_t@Xe>#Fb4iFn=ޜ ^N^)QM7GWUɩ͗uWI(bV#^9 Γ[9w#TG cd"ʏV"{5}?>Lrn;UH I d0 2M͡ ;Hj8XaU|w|;#~ߔf,D2;e2.O `3. D6[C(k:"Bz(ԖHCq;k(i5\Kycʄl5!W/%2ō[Qt_)[n`xop$Q,\GB6CL`ֳp< {j=vW%g`tv=qPsg*鳐6RT;>f^z>.0F_أVTz=a6\R& +kѳ/.<&@x*w@3͝ }0†%C̀9\bG[gZK@ڄNW`1sӕ3siBRnmF${\b%t-Kh fiɒzkݑP *l*8@䯫`5Y~S6T>2:x:H>ӟ)[ c˵Ke_|$6RF R&dg"qre +HJ!ApD$ȉC.R'hAB!Ȑ?F1~5$$!9L=v&“a2p^_+.g <[m>RʩS|pR]JM&Uy(Y>P'y &UkᘒR3Vf*_A,Ssnn{bEh&?J ЬBJQ #t`$¡VOwlKDrrʶ$J܂ %TVU4/Jeծ.EϼC5WԹ`0(ߴu{PjYȋG@ys_>ALkW|k_ZR|o"zq,ncl ':l668t0Wz 7#PKVX֊k+)-v=35M@ϦT'b7EԎ @q7 I1R$ ) %8(n<*$xXH 5P'D첹h)lu:Wc\VWʼnפM!jeg˳K]IFjxƔƽ}zԏ?Qpa^.],YЃmO""ZHN* \ʰnPx7T +S Hɳ0 O|?ܼ}۽NK??k{Xz;_;7gxf܍Yu51Ud\r9YH9,.'|ǝrR^| ݃ ˑyz~ HH0)A[$ZBB-BPh.D=]!hŎda{̸3he\ԧa gZͺW )3.;]"vhn7YX]}ZQ_qh_WqTP_WIT aaI:rrNjO'Fm 8|E ~7[&B{Un7e"Tn _^_\t*yձ9gm駜 ϽlڧӿBV؁dw:>^rۜ=gK2™EfaHrlkگ;E(30'܆ @;w TRdY2'G<'@?IhE&: Gˆu<̇`9᰽er B2@ `E.$ uѦ(\˜F%YŚ%EէӣZ=סZSD{>4㊠'tWUJ[*iR d*FծXM_5.rETԀF&Ɗ.sZ%t߬KO}}: +U/CތM:>tY-0Kha, k{C>:E۲-+?~APrk{{_濩8>!(3ݚnW1aja8^(qxXdA xpv6#Րa6[,_ ]r]`nYVC5)bDp=ѳTtڵu5( PPV$DC:hlﵳ~{}~>eQY 'XmlUbyN|:cTL'W@uŊ +R]1^AUlUTf(Ѯ(7(EiIFޚHM_)(uFhvx%?\d dց:TΧ4󨧷TF8Њ#SQ"a7h諲~8tmY=x 9xx^a[*tWtl)y}L_t}G٬gOsRvVjqkӧǔY@n,5.).C3-pʊu܍Yf<[̩-b)Q̱m)^D%kJȚ%lIID6|ҙ?O5OC#KD~>P5W6;e\6egmلؓlxrgr(73%[X\Ʊ,r>Sfi~m.I]0dU|I2cW7R3)Ԁk`?qws?HifLblƼa?y3#W F2a pL;b~s!\oGAQn1+;p\d.b' B?W$?5#Gt[~ ݳw0gVB2.tž-'H&?/x2rA53Og/ݥa j^pdRRV-0ϊσe^Z-0aI ,K>A*99ƫ} o &3jt-u E ƫ$̦q5L@O/Y"iV aWy{^>}x4O <[jkn]vsB:E1<_)RߋDd,qK2aEKe+pY"qgsi8CѴ#noֱdr`$ML4?6e`%&wyiIY5t2옯v)c;ST#Kl;:"%cz6ޡd4{/E`eQw?MS\7-R !=M)IvFlfc9,A1_G @by 3sɵ抹u\knGnO.+G.G:]wM>`@dͺis}~`?J\ee8'Y WLuEo" *C $c߭zU\&RR.gz*z޴__ژTWJҾJL{V9{l'S)Eia-өEk> Or6}챿[4X_^ +endstream +endobj +2972 0 obj +<< +/Filter /FlateDecode +/Length 71525 +/Length1 143232 +>> +stream +x}@mW:P<)z' r4bo+XјX&рAFIkLLz(vbA%1Ŗ(ށ'o3w73o޼C@@;v5-.@ G|> @_jD{m@r&x!U f ^@>d]r0yjafOO&P0ձ4`(!@G Hk _M0Rd@н v2rĘg8Jt +᠃|hc` 8a$Ob`8 )!ca1<` & +<7]Ё?(-x{{tgRra0 @CFsȍG߁?Q5> T)v |SCnu3X%rZ^Q?Ÿu A. 1F6%[So@ =v@ 3a(L1&"0zAb' ` `5` tPe)̈́iL 0^0zB? =XcJvdF#Ra07a +(#z@* 6La1| %\͘\3凋nߖ{5MD߸{H7w#ܽ_yMkƾxxxJWkO98Oqz*o7>~OQ Qs9P ?#7qA?0"T`D72䓽7ݘ'4 yRcܘcreƮ(ӦqT0fMeGFQ6iFa5IM4~F@AVU#RX"eB)IR@Tا13TF1@@@ chCi`'JA*#Q?Xzv~@H2Q_Xz(8p ) R@*R@&Rɧa*r@`ArDr H ;!%0)a8_S0Rm #;((#;F؈QLJxHY_9lge䈲e\]: Ⅲmm #mE6ND9"D[#Lxx!BKlHrQ&&e2BF"-!r]%0qT@_TèQQ((M2J%b(d$HkU$Hk5 +H]k1*+yBXF+1A7+5nVe\^gOB`MJ:+hg5ٚY/s@5Uk5Vƌ/kwQ1c0}}ӳҬ ΕGAuhF'u} "&Y]N^$.INRC뜼"KHᾐ!8D l s6 pe +2 d @ + @  TܹO!wwxqq s@ >/z/  __>{{ {{F@wA'4'!! Mp.; +0C4HH6Cs6D@wHh݆ЊZ@4;DA,;8wh-X5w b%KMD&C[&$@wZCw^v H h:s7 :sprssסCgHCHCWH~nЋ Co7}e +=R_'~^]0}`w `tB:w`w +wp + ׸+0FpW`@:.P]a0 X2 q%xs5>&p]Q& /0I/: dglp?o` +#L܏0 s?u2`:w2!awREȂY0fs?Txޅ90 pa.=@=̀<̄ 0 s=X]ٰ;s`wra1wއ%yr`.,A徃,|;XX3sg`X3lNj1lN'; k`3w +>) +S9r  +X ۸X_r%J +;oaEܷ vqf͝-; _^$lI(I(7 q5 l#7Nr'q'`n8=}/>;;w 3Qa8#p; +p+=wQ8b8?rG+ W %%0+8 W#pq;} g:wA)wC)5\!nr} 6w~A rg;Ar2x;!~2n?6\rnDn!#?;H탻H? B.x\r )=`CJn7H)]x3x7(@V04!K :}|ȧ|Mgw~P3_ͿGZikgڲu,X[[[XZ7[n8wꍿlƻoi}{s惛/lͿoQoiz}뭭aoA@AdAQG +&-P8pJa~W +)fFnmOle;,v]]cFCO>}Gۋ~w2;H-Z[d-Ut®zt ++iWY=v{w_w{k_}mu7rߤ}ۿJwg?p'쟻?XhwcL80X} :HTwp,;8}hɡ]:xّG6 {/.hѱG9zwu;xÏ=>DOt:Ėo +~>)=prə''ߍ?1~|ɱo$+3-VW̽;1\6fŶcfL3&oLۘИ1cT1q(t#JtFZu!èQ(mE~-pm!m!nA6/l9rCK"#G$20Q!;ҫYI"~XIć"b#ZDx?z8 +;v*dްa; +öm[QXNX^aâÚè0)tCMw7W?ys)ݺoԶMKbc,ѭZFh,"<94$$(ظQoCCΧ~=oFR*2WD, +" 0j rUV{ZA3R +$S4K2E:XI_m+k| mZ$ Sڊ@W\^V·mtNzBd|p?5kLBdkhJJULpErqVPoOVbF++B_H}ۊTVio$cU z L}ԧ=r$+Zg:zs87H|lK q`Fn@V҄Z| ZfZ _C^ +pE34T +gؙ ZҬ0C!(gf z'[ɴ @&wz'ul%}𕚮u9xj%} xK>( J5ZEqEZ2.yZUa.o%sSZ=)A SsrZtsRs +ܐA*g>J+Z[LSQ@]ν֥ٕEALWT]cYqVg9AVi\^kKw*o +ݓ 0YfVBg +0rz#5%(PshFꭙqnɘb%RqNQy;,ϩx<ՠ +5ʴ<( J]^uK.7 +9[Lj GВ8$6(5#7rK.F ++(QP5шg +?n8܊ ʊxN7"UrR,00Y)_*Sk/Pp *͡}[㹤KMb}lu߂ڸd&X3%`[uH:'pSK%"ZXh]Ij/33SқZ-A0+JgKdG/5:f7^,/d&u{,T/׬bwK6cd:G+e)N8Gt8I(KFBȗZ2\O +i4 +{Nȏ'dPKyi +i|6nEL[EJ 'm-m@` L" \27,Z{L!3y\b9Ju"ܟdyȱězHc3ڌ~"dhE%& -įGJӉ*42c3pA`XXK8FLA4GtR,w/J̒~ߥQtK.߸q%s -{˧ɋEkŧJwK%_UTCX=u +455m8t <bx6起:hêW;굯'Q?O3^j} +iRVCCC!Ͱ2N~a2Gmwrt(;<_ Ai|$4k:&@VF%|6mݺ+M{5a]+kد-19߃fU[̌lޘ=;Z8ZR-׶-+FLo'?+OǝJʑ0%aJ9s^j1/] m6uCkkvTѶhZwhK;:&uLvvtubbr*t$}8L3=js=ν<Ɇ:bFJK0zSmն=2Ɏj~K0RR>{vϷc{ضJl`ߠ}<C0 #yz;jaQ(^ }%ݯy'>bK02`g6c|*0#_ ǿ<܄O 7W7T_xkO̷cR7&x{#d wFk%Ƙ O~tV?3L)WZivz +;DάY3jgee}l/̾0gpoX}'>YseOGȋ[?/up65~5NX[d>]v,i_ q.Uje-|VNcZށ :q|X6}ˎ5NfΧ ?=M??Wڸqk uZwjZ%Na_ |_/nasS9wKo/c[((QvmS/n__ջ;z=N}$vu|*g=&W8xCkscq8nw]`QgAy:3&#a61q^7P0h]!JT:a*r*V;}tHҡ?._^7:jO{(!m^#h{AM4=a?=T2M%^h+:}WB}B>yQ'`W@>\0%kbȧC>up9['0b7Rayd/E7;ȍ`pM/3/#? ^iqG@_,\g}/ɼ\SZuYUDSgcw҂jr +g/߫U_ 2wMv::Y+:ΧYݳ^h99g !@#UU̮2)^~Sŕ5ŝO5ϋB=]8g{Ѳ&(q**8+5{y+vGZShGb! ?ڗׂ:HBtF7Oɯ:QE|/5Щ]5ӫ)ZE-p99{|^U}-_Kצ|-\PoI#^7g'':5+Ny<`#=\gvSgg.OuꞢG?.RO^/Ne;ww/vMOƾkkྲྀr)=᧖_=~P3W0|vV[jA{kFN){vu՗]g=M\{#DZa&|TfcQ~f{V^m9NivcPyՔWMF.{H<'f^ͳ S>;N7τَ 6{LMc]Ƌeִy9h<-#gnD?0Cuvl>~ZsL7朞XK^ 3a#iER@$%;1Hԉdb;=i QHd?BGa0p Z-AI1#;jq%**ZQE\URRzj҂ۛчB73b<ϸy{yի/-ܕ&Yi2RfedYj*6]sMihO22d0奡fshhH0I@OT/3/E}쏽&dٗ'&7ȭ{Qo@d=c& !B55V5=$L2`hS- { |5T)M7T7J##KKJC}}ar_04npESFNC#4|5 kghhϟa4j7t=tu5DDZkXB֝{ΰo25}ꜭ+?E!dnYE+'ovzzw#;Q}zkL0+Mbв,hGKl'-WMu"qH$ @sZa*Oq>!AVx*+D\BB%r["QWd<]?LQ0=v&$hA/HHŬS)DG8ѱ1AA1ɦS`\ '%[""H;g6j..k +πc,z*:[&SKJN!' \S&:̕^@1+b7zͱ3QhDL F4@H"eMjT(V&9$XoP0 ,<zi R7>"D*bܢM\.Gr@.{gӴ[Tj{ +:ѥyT)Plf  afrZQSSo_X48{.w˾b/\<:S4^Ymb9nu.)(œ$*e.!F&e֜];Yv{ D-X}㲦5kEE E$")-3o !3acTaz[12%~Q\Ҹ+>%o6cB]T>>@,{/pl@,{B/ȮpخPFFKX4 ËiuwQ9>|a;lu\ 'V˞aͭa‰B ]ۿdC|n1yZʜ96{ +3{zDp D"@_ }=R3mRӴU*Ѐk +8"}6l|k"#c?M|ďWL^5z EnGWlL(Y`5ԁ + C=LfըDVRάP=Nku'wILL򕇀-e%'v"w0 APhW;l"Oоe"wޱ>;_F4 4hy6{}Gm-x[lnG>DPwQ %zwh?f7k2074OK1ɐ"@EH͟}F0yR8iъ+Hjև.#r0ho[ĸ:&H<} +3b]˫+̅pE&bcƢakFK$$MCXw Ғb1$aCd +3ad{X+Ev[rIJ )I*þ62mVɭ6 ++][s >QB@$w\*A7 'WJ%Yfq$/-h}M# MpF 7w +Pٸ6,hᒓH3FN 退W?i颇(>3Š$(ŤHip5H HЈ$4E 3D>򍈜]pxgy\JG~ee"&IJtR]8fTXIⰡGo(eٯw?C^=Dg h ;-`22{]7ңDvCsRxlj,ȕJ$䒤`\ 1:W1XR5/&h +4*"?+ܲ]Il'OwCϜq33 oX"uUKRxrVM_"l=^N 4=oheɘ\F(BJR+"*eg} CP+Q̈_ ^|Xn T{Nyp&U$ߧ}tJ7[]^6Mre26wMD^Z/EP.RJ +d\ 0۳:m"թԹ2JiP֛DӾI4Ա6]Uo]w+"{Y[ v ϶VPLϏ@,aҾw_ Z$^vNs=,˒ZxdD{PBJ`&% + +ౖ -W=ȤLш9!/Ń?|R)̊A-[ܖyA-[Ex>*|y@TQ(']UF1+w*JHI*<ҒQ}9̛k^T f20jq~[Jz_8J\>Z"FyihX%G_"q +)BCoڊMtC؀M#O-[F]߰Jt22?K(Q m6YՌfC]B򍪱byYv)ky C%j4. T{Â\V\B`)b.|ןZwmYz !ϻA=3 +/z#N@7F()9\d .'oT98H 2e˨%'4f2=;b+ ]!)3`E. 4}AguD^}792he<\'fQT&K&Ĉ/Ծ +b 嬾ǯ_?l^5cNOwiucZh33m*"FН@ f:ۢnbPE-kfS 5+"A޶"rR$fl5XB و0mG$0yR򵊔nrP&+16^Hc0wQKeDEX/>@@ JGh$2Rfp񻭊Sv6my5 iWJ[V֭EVxЇ5`u'42F+C恲J&rlfIi$bslZ\}0oy)EX{1%]̽ YWpMe?7 iBj~1>}҂ +-R$QR#Ѩd.2$. B"Tl߹Tl 08B= +sI.b^NL_!#j{RIJƋZ( +2YOK\"m{!0+CZ"`ha魒Ie\%X,Uehh،g♴LI}5:±e@e3RxI;؊*ZB(v4W0YvD׆ 2҂EF@2 +$*N=> 5HON,c;@r&r@vO"PcUB-jXX8ނ !2Z +jp^ebާޥM>5;Ҟ a _[ݻϠ>oP\6WUv0 niT}@K A#"I$@$!1I @ňbRf_FO 5h$_!PB֗]~eWC)O_vE}U}Q/Ի +~P* 1,4PN%2{xnY*YLJwfm.6W~z?0wjp')Iҥc2еGo/> zޗr%@ @p%E"]3Bd L^GMvsK~L^=wx5gf?^z$͘W ?˫`J) .z9y߾Sh? ek[&x):EkQ=v`%29&(q@<0u*[EJ[8ϼ $}w܇}i5x(ؐ|O2(q0 hh%0^:{`N +pTڬ o^/ήmZζG3x}۳f}oӧ>s*-|&Ϣ`g[Yue3.HGIXWNS.xd\/bxdMNǃƱR]~GUTaSXh: V)3"pyב"$2}ʠ u& J0 A"HҰ$YjzR%5jZUT:8jNJkBr5}pt:4zL={cSRN2eTU2e2X~MR\PP< fR]Ϟ0>pluvA+?)C +d֡*3.ΛW c5Iupxlɭ i/>ɪ46鎧mtp:'gج y~5|[~[supb/?+|cDQgh *LۣVHŨ #36aAf:8Oߌxܜ. aP +7܃)AtRvBa׌P./IRI*O.Nȿ>[j+* S(&|^%on,{)_~.9p-^ykz}x6@.zjNܵ^;ؼ;,ZD$V~D^_*krڊl p,f/ `OHfJ~Bu&XRJf[*'DzM!v1n}\x`.cϞ·x(۠ ԏ!etk&%6r6h߸9?@KWh!ʾBBSZ AzVyIFz~P`9,Id +'R{'AϵRVC +p؀_V^Z2Yky%Ý]}P~r,^{\3F~+2+o؎E +x򈸤EqW4FBJW+BIB+Tj +_?c 7z67D +z<'[`))(PlUN)#T&a+aI ++qMrGFiїZ_j[k5pZܢ95D^ouQ{-0'¬d[gglßfwsI^~zt~F<#FaGnuߥՀ!U +DzL8x g,r`7H"+*LʱW`p-qcd3.H$sgeԓ5l6<x,X9WbJH!KAa?o뉠!mh1Nu*H)dCVA*5 D8ax a + +#*kv3Lv-0̷oiwd=hka?3^ٌ={*"Vl>ʯ +":PPT( !~a\HX6WhLV(H XgK10kiu]:N[lYMkq +yT}ՕeGQ{cÌRdDM)VŲŅ2(OsPӯ|G_&Xۃz cX]lyl0&bu-1bņbb|y9i)rliuz4|J-0xxhSR[$ B\)@+ɊQhD_ +eVC]`VB( ]k׬5smD5Fo Fam{B=<о,E=P/*g#hP ?_ +ηOr ?[M3Aoi%P8²C4P,yȬ~㄁'Ȁ`O>& RP5 V7-:F5 +RSXRA,RGvRl)ТlPpң`+E^AHD!Lh 䪀qVZDv^2^%Pmm0 ^}#^a2` NQ|`vWݔu ڦ#W<_xs֯y;@GEBr%)Q5 J ?4GJ((a tRJ^DґHKn L ՔH0 F7 \h]5 D +b.XjY0;>a~];sld]Sg-90ڈv*mry98I<eaXfˇTÉRܒW950#h6Vȵۦd諣3s]'8av2؁ﱿM.sm`%JXذ2]!d_TU%^Hp~Š&=-Э5!2=~&!d`P9*ϗr(/p>ݛRD=^^/?} +vW*RUP(,wn潡 xT >j^ӽ҄p8)KqY=L:CʌHyH&.r7˝bV#e@Lΰ/Wpy&WUk_ftXaO|Q1&?(p G 7B~h(]Ldߴi>9D@H:uJhMG-ў(mnDOEߌJ^hp7x$zvX +YVaaMZÂ0]ʴ$wֳW, W#Wo[oD~4Lޔ[6GvG^:3f;,/Q^yH8UTd=0 1Q]BaT5ºXHV$x2RVAN|6 1Awô% =06pX6” *NְO,0kVr,/ }s `^Jzi(G3tB?Z$"mXVV7!;l)>ɮ_v Ⱦ5('@kW5sO{[EN'QV9,cJrD ++a`':OW2 X;+#g)N'=:X< +C2<· poVJ<^+A•aIUzWCCC0҅PuגM\bKftʌf9u>8fp}w7TW$^_@ot=#5]zE?șj4#ãld侁g3H`)b^_Oa/Gq8Ӵ/d{W#~Gp+P!N).+ a\<V( !a*5v*G1VQqE}CR{γ`ot7[MggOӧe:E,`O|0+p {HҳS}'FZ}1hBȑ!?\Β2Kz]Gnf(t;>EHtFm}o[ @K6y#W#]dD*4!2 +LB50F 0XW7u}*<>)BC6BHP搆]$K ԋ +RjpG{ Z[]S[|fw5!8N +>٫M/q,wF̾E0/wW/mU­X;aصNQR>WR:ƒT3ЂA""#W'E"P.жZ" ZVYҴ"`I<Id lESѺ(!F4j"<-n?w\qD>{A^T&2/fq7H`[/`~}mz"exH)/RQb#۽{3?P9ہ?Ͼw+#44E&F![wtqB+Ƞr"!S)aEÚ"d;־pPhqZUSBK񄏊ē{saQ!P/\4ӑdwJ컴7 YIG:vAo>#|?%2W=']sTP1X&ҸO) +V!UVف"95ULl|3gٰ \g RTL7R仑L±F +>SI4)$ɇ|~Y?P- Šۃ>^R9mjc>at>ܗagr_S%rC'TMTq+:Xg= ԤOyrW4Mxcpd9N:6]yx̅_[v\]kپmx:%3(9ЄIӚ8yD~L!#( +/Dk,2:"*ss!4E6"0 pZŴKDjJtA" ^_[AtUJ—7րY$Ɖ֬%m1%^[Ubݷut_rߺLTzޖe[I3qo'");ML pBH8Q}QVG='3.h[kT`28 +ҺEo(XѺPl>lj|>Z'+/Hű.ZϼšeC; ,E~H]ٷs]0ݖs1FvƎ-sfv +M;nQ_[Ds19ClXq!^/q l © N}K4,A}qcνt.cx]}^\rvv:ɝt-M-6d}c M%t8O{O(Ur/KщP%@4ZbS1:{ӇO̼lQ~qq,F`t%P{)Y["$fP깮u/;,{/,jvֹso?;Yֳ E̮_۽5{--D~Pq`=@5Qd#TPGDIY:PH~EY(e \@}t%PtI]\k>,vR=,/׳neo.8ڸ.2R=}Q_'vr!TM}aOaR-LEPc\Z*G +Vi\=! +QTzX +lUn)'Pt] D+^(qI!G=8 +# +hL ;L؞k%[ qIrdv'>`_kŠZs*"Kw84NFV"Sp6)MSٚ`I 7$yD|4'q0B3 pRfa !!C!lA]DER_tA(^f9.гciN8P5u reluNn='c<'D&{?}ԍ w*JIȋt Ci$ݧtQU Vz2T@W +N){ܫq6ހ@_?'ޛǢ޻&M@ +2{]49ꓙ<w,Ú;:$^Ȯ[6Qܼu\:7_I?JJRGD\B`^jQؠlUz7E䉽 ! P1QB}^Xi)FZ=Yn#{/ep|b?&̰ݙLOSOlSW˿[_'ZMp'@dÉXyA+XIN(R sU?ĭ";;>0lyx`/I6-ditya=]G|G Qge_Б(~gzAIw8&nTsj} + +n*zݧ||`ux9&TWJ-QD<4*D/B\$db/=gs9u=o/6ڻ2}(w`׸̳ >7,ƙBB"lhJ"8{"?D H;涬y/gs dp>Ca5- 0u|7ıţ7}XCS!wxX"^.UEnW^%#UXA=$[m~+չC^g3a"3ddo׏fUyo,bZ&G+K1'ؤ3iR)GѺ(գ5 +=(n/x&{I$AN5jD4v G%Ry)`[~U +u-ىV{){~u6L׳ 6;ގYOH@6>}S"Ùx'W'w8m5޷\ɒ`C] IƅBU ]cg/FqçcEk1y9]NWaKi#˟|]ߜ̦;؄0xK?h0?^MJ[M(B>Y'D6oGT"TjB0,wˆ)oeNZ%dQڐlgn=`o"m/dwo3`8NeC"h!PWrEW+#W}HIRdNU$(Eg:t߆BYo@R3Wu]v–l~|߽#gter00?߭$r}$pFA=4Z9*.)$'>W| {IQ`C `{ *xHS\J FeHd07ˡ7;v> + 'Z$7Fɞك5Ixn7 +#5?i?C Ls/:D'ehQàϓ L +4W4)4ԹSR%]O讈PIpbl;l$vdәR&ʌkǐ"hCǞ頡A U50 JjnK8}9B^Zj u`9FQ\E!BHOJ%TB+K׵gIP yE)#-Ct_\R~Pf0i h+^RHn9E%e-5qx<;͠HuV /Pѝa:={9Vk3i-e[5l=/nؓoêzPiTCsڼg$8c$ޣ; *c˂Cgў92~lDn]Ɉ3>G&qI®EiD MQ4>Oԃt\:}9gCUz0/,GWqP hDX" 4kq\z2Eu30W-)[GedÛ;X{=ёیeB6y+%;HSLOhh~W+Gu^Hy^UzxAR"CuZ)cK_d%?:^C [%س"Ԓoq"n~%2$Qאm $  /$;9vb_A,%~]Wcm30jIM~X\*~"cc΍+Vƍ1h5d6:Vgiv@Wm@;֖2?ƖoCc\y#]PDѫZxŏPGmW *!Oz1VλܛF/pZ8! +A#$0Ҁ8:z1MX8,.U~ө Q~YE(0{E>X)SB.J_˓-I>s QE{nTR ww,H}_!b%<-䣯fr{Ky}24=p7$SŀLi4hR@"wQZ""T 2Ǜ2pu +Ȋ"GTsc_9,4VMd]uEd-";5bFHl 10cz?;DI sYI4xԧ9ML0a]y$I^AAcP`hM +{&IQg#&Ќvg–(p2 +yNEĜ߈>ŇZXs9s-gUZHXYbΝsjTw93MG3n 'E h#kGB99VY[ZM s!BS:`@snJ ӕDGD_EW$Pu\=<g>^BHyqwr{1.&NWs#I:;װ$?Fj ru>NO{[ֳv΁\daE4SJ+|a>"~Gu(??>eq(Υ0noNT6dҔt\–xm^‡g᙭^%l`*J&D7LTY*VK+dnAtYQR|^Dn?{)Α,est}{ jOKs}w+ +q Ai"@Pę+s*<ǵEX.1:7|I)mʐBĠOV?p0(~SLR#vX=vpA\LjDzݣ_gb6=0,Zox/:E{]I{}8>B'd+]w־,f'M&{}P ?ٝ ui9jUٝh[߅n۶M|~]IS -^ls65-c·9QX,ȟAQ> JsVfE!BS +n_Ǎ~*qÁ{S +Y:[]5cK+,8j?v"Ũ%;3DyV35 U"(COk`'OPd bt^XO>jY~`rⲲ"0H예iRPz@tuU/l1ХPH!&)>F2)wBpT[MgyNp+ 7uw~{ [`ノ6AGΌ!eج1Os3b}!] +I$^D*D:{ 9*8'?%jje*^qX!F7a+)h{f2ț٩. 8R8,OJsT\hEDskֺ%@Iޯ@1 p nu6߇}.=96¬p`B×Cf~gdJ# (S1^. +;{JY MaJHš1ǖ諑8śj-ոmrCx,C .@UA_S-'>s "" S>{}n{Ծ4M2`n+Gsq _>rk5lQ4,7ɯ0բ)p'䧐$s\VP9~m{afrz2 /UO54 *'MV +έEzE/U(~ݏx!%vvá?'䩍oü=2'չOy0^i?ݵz=kQm瓉X52A0Cį5W5*x0 zD`]&ŖTTlvHy/I~Qos޸w\mv[+^yNXFvXB/;_i? OOE"f7uC'/t_al#GiczbytӘDA+(0WIUe5eee N仚,? #: A \22*0Rv9BBJhK#Wzܨ1=7cn#;ŎU5q;NpNgvv϶}ӧOvKJ7G!YF@q2#3D?v.~=w!OCz=BB <"*Z+w %=.]=Hӵ ?XYAf߳3ls&{P̀}hP;i2fỊ7Dyfz@;8u.|3)ܑӲoЃ7hȧXfdCʾL}~|jc>raص+Mr8ԯ7ʑ&:j nj h[&BH9{!S1ðDdq1wWKR$> O,8/X("}+ 'nc׼^hk۽2{ a7,}*\_6d9tE+ֺ3,ErxLze@N!Fi~']BT]+on{ +~mve=؆'3B杹q6p]}tDl 7̻a48J!CIgP6 n@gK +Vs$?{cdzb1čFwx ΃=- s4IC*|!vh-hƳ+#҉ѩ?b/2{5s/F_(nIhXig2D grv?6MDĮ3}28812Rg +Z%5Dzk!:)ki|͐AN6I{u㞼GAbP԰gnmqNٽE?՟0\s`\Î~y㳸fJLx~Ӝzo[*v'ޛ73:]gF"|=7q9aR"~] 4rV`]81(HA7WƿKOPLLl[.]~|pxd{XFrqȥq dwL)'{蹏z>ц:k+>6 Wqf4%yZ.t +N@2>ttuzgYCS9:;w#\sн}P9!nܣ`yxCB[,C4S!<Ћ `+\ sjBU9bMNx5A3=#k";:?WʫW\GV +AAaz ++yBbH.`JdC` plw ''d!(*${co⽠{0}\tp0fE[꘦am{Q79;M I f-RfgF6-$2̭=|MbczL)RNpzLISv)}Ʋ2̳@>@Cޠ@@YA;$m/?PMa[mЖזf-\I@[w7i:mž//'8eO}$MpۓĴ9)/2|urfvxzm^R|<*S;u܉YSAZ!bS Yхu;%SaQ-p^:vUGf'W]Tz؇^^2Uun">ND}lj^2kvO Hx-9  ୏ (#_8GFTNZ,9y +7%ҝ(eܽ[̜=v5>{eQ-6Ǒ,9^q="-hG +Z:(~?xd֤_(V=o{w.÷jmKxH>&,q94!4 )*QhѨA> 'Az|>,$ ̭\/?;aFnvXKX_+`A\}qIV> P"Ȇ(>RV&#=R,x}Vy?E!?kF^GK>` DZ/A'0'h<lPj9HMoN<;As܍O_(&͸J8m^+%(C1RT\R]PR^U +^Ԩ[s 3%?~v c~h0F +6Qt.٭08y1"W-Jp'8{, AH})/I_FEݪ,HPR}>U +FLy /( mR ׅh+HډͺwKNlx-l^FsK >IK+ZMD|3h8¤Q3/?qȾ!#H]dydGDr^89G+7r<2GxYP.E1:;jzRTTRAMϺlq2WZ|$(ΖSPmzqgY[b'oWuv?G(av]2U6+ΒY4ν +suYݎ$tpgg(6 5Nf0~#śiNo'[C" +ٙi|]ƞ+X +i$x[ѐsZld96er\R)┥ +$U)4*DTU^E& ;[~kRXS&@VS>e\[\O:o~iSnF9 9Cv7݊؂;UWEt_*qp*FcX3F{=s{h@or+TmY*2032̬J!iVaEXb:4rD[KfwRleZ\JS {gYOJo(yTvZ:3_zp +x]~ >c|N]2׈J qZ B> h4tL L٤/9(w.r8`) 8IK@<~+ak;1c&zC| ,*$,.Fdm+nQhu;Y^$qV(޾ro1|ps=9qQEFRF]z)XW￟LO.kgЊ]\} MPCT^]$HΒ1)&\IR&Z/w&.qg1{,eZT YZmyVmb_BoUhu +RIy䜻D/NE>ad|f>3wnq2ϦDΓamKUW$ +5)3dJSVtVʶ/"dk5Zk#mD.1.b&>#Y +QLd\B!M1: dYM.-'Hޓj闕KJc -id:v^R:"',^B? uEpǷS؜ŢTTR?I0'䨘hRpAN,)R r +]~Ԯ_EZiICe rEeXr9 nå wǬ{EH_'aВD՟ jP j֗\*-=/{!‚ê* +<;1Q 0Z.zV3eF|MҟlsIܹGHoUb`h, odPV(o$ف6dHIjAm֩,\o$ͼ=F,llcӻ=lB;+DHnY\:E'77˦RKj LRKyvTȞ!Qd ҥ "F"N}zFTkb\H:Aӈ:!VŅ|*n«}P#Iĵ^ۨ%l'ވ+-e[pȔ)--اYd L07kH;OhaZZ0֪b }: غIՒQ`p??PsK<~DZ+ѽX{\Kg: +C]ZY6ԩ֩{g9$Ld%Qqu:֕,$TU@|d"Fb"]0P+8.2QJ[_'C-` Ԓ~WLMČv9 F.oL~lqZkmfbVÉ6^h NsNOPZGN%f#f;ef2F%Fc(Z-!K=%UXb6&-Ofk +aIwJHNXѢeerV װn {fM5`Du} ..e{ ő(]KN˧OeePAbHϯ%ryVbX]{Bͬ{$^& U1_ OljNNp׊ntpU` *RoB'u֤ŬWݮɲBƸ3k1Y|:Db]2;Ve1bH>I*˸ I+=WH v^FBofL'Ѥ.xF{'["GB[#REfݹuW{^(PӋa-*+m^!s`aE76Ckj!mPefo&Ht5M] P-IW(_/ERYگχ{>:oѣQιs;;g)ku0=7ɩE2Xcl\/5;6uPܢT7/ =KŰVҁN]Ai3[ +2y(_#hF-&n [O|`>+ Іc?Íto_a|F|dlG}U <lplAO_;w0vdcdl⬨A d:K'#ѭ1k8t5:SDE"}l csa*Hm h^PJ'G#weM(&}'ko|ݻwV޳g3c4^ۄ\00Oڅ;D;x]tz) a0UcةtNjIP)mkFO6K0 >QTzfH1 4B0r>6V6x`4.|@^zLHm *F61 Jb"=r2׹D;:l] \>ʎYdtЮ/KHQSe.4i:«"kG3C-'.AVyg{:M4,ݟ0!a^Cf^QK߱x'|vH@: PtXV䶺BFp&AǺJd%v?=\Pܢј6K-pm+*=0<=F=!YjEoWjlf+Ûn%}I +}Ηc[3Pm).]ǛϏ90G7~?wbZ2/%^A.W=70~G+FF xc6ea%a᷿UiژպjX&Y,Tץ,NӸ,Ͱ)7y3~ 8灭{BOz>7/^9<.JR8ckX'fKd =bbޑWin=ѯfn1[;o;+)y-w SmjxNV}^Mb0U:lX-GHwAÅ\HIY1a$,A'ګŲ$puwuujf(ei==hMKa;Xfo/|3a~;Ǐ?:r."i"ha~%$m(\֊ Q02`1 jBOdy=~KoY ;9S":jԾgaqXRBH٬QB[Aj>lE4!dܾ"|.RZl2~]N_74K\&>?]c|pz&;l8lTIvǃ+pN8mO{2Q;\h7VF)CX֊B]ׁnc Aa8l`36%t)a3N ƫתm'D誵D:mF&\UBBnrOsA\ kYí%DvTBd9BGR6YŲ$sĎ;T$2rX$o:,IGNr6̂^dӡgc;/Yw=ТOE8!y2/$B\"f<7,dsؑ^r.own=ֳsa!Ki')*Cj(a7հZ jbt`ºY/tgu*4,YPI2qe/]󒤩rg"!'2Tg.[;qUt;ɫļR=?φ|,/H`c_~Sps0wO#|طo+}**~dIG£l@?"͎V5 A߯!n[ͷ{ J-gy- L,HxOߪk Ws,Rƿu +B@F ݟ` 66q.*4, hlr(ZΪ͖K'|= ILb}ۙv }=K[.O[Llq.}s|z^;Ěuht7~;jxCJ7UUѱ>Ǒ- D\-\wC\((U/rkP@\W6 3s0Y (^6L +f R$xRQP|sWiap=Wz+B"D0bX/ +U,]lS`gP Ժ١Y@ʫvN\I<8'%K O,JWŰİ3p.(D2iNa.}'9_Vgv6x ޛ걿=qMD`ޮ.~jZ0^=VAZJ%'MD~-xOΟOɡGCR=N^#^7T1=Ru&[5 fY0ZmkZ(^#t +X`x231+ yfe,έ]Ѡc [S!H3z;} /9AqeftO7zĪ'`T}Rk[TDQKmr SBf3ڲYi*qW>_QV.8R䑓!@C;(*]c\msAVѨhV(hQ(,KP̛|Wk&᫬溺uu, $)`%wF΃`YbCvwSjfrK# '/HSI-+d*d0f-k[ZFa +f +(^' (}L u!υؓBM,CJ-Ǻ]Vл  Ci"5sGES0bèQ^5Ai+ٟ7j^CVVc0xLf%h&orH؏@U u,ۨ`"jx lT^JbbBH6; ~exŰ԰ A|E eDOuyyWW~#d]P2z=`X2ށXNDh枙nw6/rHLo ȄyQJ[EgQ[.٢#lI?PܢRه87U& +Dp!'ܪf屲=8aW +hRT1J5p8X,:&/+zHT%%؎\;?Q5%C-EA6Af7s ٣?l}{А|l˛Waݿ??u0eu""(gH[ ȌڀTؠ@)ƽ$BH->4:txuKw$}!ئuh>OQ0{! ULGZH?s2~OGHh/aZYgFjOFfHri$j#yT\KԿPͺ:?.5WⰘ >&d#~j9ڄW +B, 2JW:] +QR׏ xUW ,zwɎyϙ@ yAŘ\7"ΌYg=@ ?k l@نiٳdi_dls4hlP mUgBI2QbRAsG]%^ DˊDuݤGvƠ?FMTlՏBs+<8F\>(6 |ZjUAF e3( 7 |r;q_]Z,3dI3qsY/.>8xgZ ,6E& 앿[=;/>ƗXcmsW']Q)]9{ 5z`wpP^^ ȋh +]>H שWe0 +U˹ ^Ѣ j1RnvwŢK9)?(T]WPYRԥ/bIQצ,/_.K{|nO}U{eec#t_gCgd_J#gGφG_]mz1wG*f屪ŝPCrc7_D ,f H-:.Te]29eL&~R,rрJKIq̻:@y_rSD#ؿ>(p/3O;蟅t/w,8v_T\֩jN)87}Z-1~Ͼ҉9}: lFPX5aM^רk :],PHJ9hŌHtaMazG:!;wcȉXL O0>9Lϒ۷obL5hO6 |B#Q-j4;rJr¸d#/_A;,?g8]Z%\#zBEEdՀb'ie9s5x܏ndЯ/wo/ ?~X_)t2%%"a:iul1S{ KB{3πY2L7t%VY%N)S0t9pƅ 7n`v̍wҿb,[V}'Z:EGh}|6Jmݮ/ݸwь{gY؋'?=gӓgëwGQHvŧ'&{Pv?n[|;?#S\?;#_/x$8$S&s46>h&*OTK[h?$!|OAݝ 6mZ9ᕹn#t(v9!%ֹ[7͛X5Vo!ړ[>*B[W'p.*JCșm~_.B1\p2}@W  UYŁ8/diH^L,S`CSg2'gJ6ɫ/Z~}n.;7: +S rеo ^RU/8Xא= OC25ްqK,bV" g &7sȘzSP z` {(ҋĿYrmm᱑ at*>R"?DA]A^\.p`\vT5lX=E-htF0 +KT1sc&ҵ7~t[t` !k{.<%UB[OWQSKА\ZMZk |o_0sW[5Lvak@æF<jׯcqƧKθ_)4_r!8|D'wo}B :)z`g7}|0JG.,\`޻睷?~jf =<4]Sk:$ X_kZ#PHN7NPӜU959rqrJ h ǡ8r0+U_*p^\nh8f&rҳmإd 0)ͭںq.7/: Վla4n=oӦy7]ӣKH݊ Ch7wv11dR P! d#\y2YakD<ĺ.- b^- ӆCK*1>@W& )8JKR*)UtEK9J Ϣ#/ʋEyPܒݘ<CIĮnL; Ue^jN\LSd}/ԴM?|<~d]0In>H'AO3[i3Y4v#z ^r|;G=u2qE}Q; ܹ+;"Jz, 0"E*"nF2MK8r'a6jCn.4 ov .Rr@ͤx+8;@6`7(n/yyUFl4By\(Kh:4X\䀉ivaabU,)]nIrgeRv`*LYz'獰i'u~R!ڗj9S`t76jj־yvVP;,ȚN>O Ol> +ÝյNxwӛo榋\d/oPr[ti_A#tZƾHY^UԸkaym:->ς\LQ.51Im 5nްfq۠D/X"')1Kr')VtޣwO55Şhx饆^zI꜌'^7<߸) |=O)hb1P#h" s->7{NA"c=" BߢIq 0_rܚZ 1|PWgrE$=G]R/CNӯ/|=Z?os98f5 \/^(RM/AÅ?ՙTf+'kbSQx H8M $:y _)\1ˣ֓^8&!??vUlJ[c6w-qCKգ"6J ЭR(qh隟}un''Kgc3oR/2i.'ysŦ /z}wѻ^ RFl_d۶%KNms_/Hl@oyTek +u>wN~+Π3ȭkd]k}nnj^Fa5I +h'jҘ =Ok2J fT}RvHv+KSsd 0΅hw렆d[I"R=_wXѱa/~= |ʔ?l< zm) m[[2]˷ ŸB ,L'P.ɅPnmn}nߩ;Iyx C H@0T5@rfr[wY^r$M\ŀ?ISJLK`vc_u^\?BP΃MMюE;w.Z{7\RKy9Y #`~|cѕ奋Kt'LxHSy52/ٶ!g*rbDFZAs=dz$"AbeaC`p$}UBi "#L'!AGRzi6#99=3uD,q 2~s7e Jqd$^ZiA+ZScty+ta`DF^LG3=hv+pdl{/%%{<~ +B$;qN_dDp+@JQ +lϧcB"]ڽwvEȁȓOD"O<8C yia`!k8{ߏpٳ ? *9>o[\:|2BZ_'}F_O .( ByB`}9<(+X\gLs,vp_Qd>!J@ghJUݻbdRVYy>9znB7y=N!S)܋fz}^V3{~E:u +;#xU uTX,@$r^ WUjZbLFD~YY6(MNO.ٟ +Uwy%RvOV*ɌAښQyyɺ<>}|;/T6DmP;>Iz]Ԉ<ڠROW[#rl8:7gcIOI43ǫ5~ E|U0> +pq1.׉r<T_nj(!:7Wu"7+%Kj2=#Vj4 hdA^-5VO٬L[cD m@8Æ2t\a IpbF[.P}O7Ë mkaLe"t2xeѣK_>hޯRp=gғ.~:6(oQeZL6 +hJe@K{ _&)=ٜm.7cX5wBeujZ`&_5ߙ}}WNQFJT3%w&lZ8)6(ccD7q?xOu7֫"rnm Bu{7̝ݺi֜ܣy["sE2qE3UM6='(s$f3r侵xt/h&V?Bg^҇)N.LW_s {CH~+lV|HgZ>tv'&>/֋_dCHlq-}l/o/cr>O|- W[Ò5A@KMt;=~NgBid_>9#xƟ~/>?]j 'tI)tmOu\^g*;3-g-vg~Κ7~/̯YUhvt8Jw C(8ܢvyޖĀaH}W:U0b6#8%t+C>C9J;O`Dt$ihu/[_O{i-ɎH#s4$xRцl0yzFSAr}ŪGBAr9 &4X +@C5N"'fb"&cmSE_ۿo 6U뒺b%fX,BfZreFa2dch?; +zgh/iT='r5Ȇ]x +'_˗Z0egyXC95=K+c~}^P-FZ6Vx$ѭ. +χ"(0B:v<ֹr* ( ,$v-BQU*NHY@/dW.{%%FKUL_Q gDUF% OC!?0oy֬s3Ե܉mMBCWGDx +;ګ>~f̞֘1TZ^ȍ*2toBۚ$u=m|.S +/P6E2[qS"Y>ȀA $+&΁Q +.|![yo]Q(Hb/ B0$TWYO/)344ݗ[j2q֫=31y4m{[VL{^1`t%Oʡa,1Uג>w^4緿sq.ސ55#KHN0m<&=(O%kyCrB@>ƣ(8D̡,ρ_e^ǛV.^kS!}g}ʒSk>Jeqjv+$YQJf|g(HҗȮa鐖7E+g%H'u_+g!Rg#_?O\Ł + +?mI&LJs&FP3O>׿>_ͤn992_}yx˫͈zт44Ć=ayÆ֭}8،vMrX\"N31,*ֻmn3^Cn"u.%},K ;nWN:pԩҠMdő;|ȟ~?3cR2vd|tzu~e؇JV3V+ fCuiAHN^{&9;;K8UpMTc){=,Bo6/;#u)*%`<$#xyA@ׯUWhѪ`Е -B&s)͸/jڊhL"ڋBPUz4=VReBkUM\] +$eKBSh!r +R09"F2{'oO<3flF㊋6iFtkv|8ߥ1=밸>c#p 3I1u[zNbmT 7Ncruuj(0O)zU19fJ+? 3T{AصMcĴvμZe(•޼~8?ȗ.2rsZ^b/0M^RckUإMR(IlJq$@W2o^4BDEJ68a%ίx7@4}| h(sȁ +a]D%Cyp(2%_F# +rBa`@Wח%bkk0@c1Tu̱JB,ȁacҰ J H2ƅB;?IRΉͤæ]~ cg'Ghdٸ{yލ> 'V6{庘6(OA&!]=^ARp35KZ<אx乣7ʧ?qt9AGC·}'&C?N{}7zz`MJŎ G(.2yl+jrb^ymX}>d8U64DQ@ttΑVPZoɈGbHx ^o \0dM.~ IMX,ĔE?\BX*Jw\dmPzilnr 7 +堘BkxlGY$RF[=G4nP?IW +N)XNt̫Ϭt 2suZw4M/GZ)%V&:ܬJ)uJw+c5HF$uƲPB19QTS'JuPZ9;HdUF R9}OY/ح>Ae[2dR3zD} +FE߀l"z+liucOV0Y-O 2}߀߈D^*TNfjqOEW6ˆEY+rx^´pX'Efr]tf !%gNX:|vta N.W(^ >%eʴ,3ve)^u$IHKФ L^~/M9fzл=m{oDnBߨJJ'+'3$?hQ*E;,ԓW 8:fBZ]&[Dt>3b)' I]t㴍.6@b JL2aȉ!,fpbY fՔ(rV'~>s +J|)}l{=(&WVLrN4=֝EaU:/3+ԦYۡ +ZߔϥMfeV~Bn"cEְͥk6φ ˆ@6[]ևz/Lc'b'a&5U;:H7]-2._ jșݧ?|~̟hlGV7;ʐEӣ#nեHJz'3tۛ_>q'G +9aI!Tڬ +cFHǧفc1 {ǻ~zE01KBٮEL'I .˪M,TJ\OJ0%GN{Lޝ'[pv,C{)Exul$LB dO D땾֫A[W5~$y&ZףtfONRm5 GBj|ط‡+ӄsV"TWb)`XBM\j-I'-Z, }`L m]:ݙTF_?6>1X4Mdܹѩdx?F'=K?&EUQ?>Oσ*'2tH[_~ } |>DǎBhu!(P`cH,>^y_հd1ʺ똶X]u)4w#?^I;ePDX$:Ʒ$%ȋ?.*m"wz[lr$ՄD7IJQ&M4zHa$FQme Ctx{08.tq7徧±H4#ɷ8胓>1ⰖkO=A8%,5L<@(rM~eQ4,fhy5Go@Y[/ӡ@zRf)34sxf[N2Fލ1o驑!L:$MPol,fQ#˶d+}B)*Yjg[v3W,p?B `c1.4ٝXV_rʄhJ&䉅0z }I=@kM^7>y;tX\Pnji$"'Y%[onQYlO':%[P8LլvM0n73Bu`͢sgg9X2<z)Mӧ;5]Y=E) 4]ollblsB9!Ld+y M8.F)FbH*A1YeQY sB3d- XVּGAصOQf?PicƻGf'A%ZDb%!^(BU(.C`9Bj +?&7 $A-!F<3 :iS̆l) o9ǟ}&_8[7s-P2aWkn(,}JY+(Rq)$bZzbHB96a~1Ëxe]J"k;nѐX=XRl?8inQFҦߘ ;nnc!:` +14BZYlyer:,[xZb.HP(osBˉ}iNⳲZb,wɉON\nu@Ip&F H"VW_fp/]G-Nak'}#NG֢s%6LNKZlaWCCf˂KlKYnmY1eaMvl `ʡV(,&c}4xCJ'W\lw3^an7cy7ˁ!lN1W@OﴎQv_ȘRR#[iͩ{@+7_ӄ0.pL}Ǚ3_LGF"ѧ?71;m[L`c T *Q+]*w6{f޳>LHB jp,(199HCG4ikJ; +ZJ"* +V4Q){%!؞ nFvg2y.Y-ypֳp^#P>>Qζ&qY|=4}b9goT^,زCP_3׹|,Bs^8具gXk=,>B>Y&u% > xƆ)@~dDN:Q@nQqe!C(i°9z4Jn67\uyp$RsNyNrBz6 +M~7'^vXu3{_Hkw ›L &t}2QNY?g,@HhEJz5!6H7m}o{>wTn4>jRteWxz~HS Ց9#CNht6lxL;[3N;ôd|%~;{u;!mf+rnJ 7;WsxA^N/62 S(A~ $a[!_F4|я/_!35=~X~>D>42#ḬgYfŹ(o4?bog{M^,|[Cz!և.t+ZZ-12wEC1yD=uM m.Ŋ:?MHsіЛ"/@{R/$36m|?)O9GFX ͪwj.!!DKREGJ{i ([E)xJ?$E'3P%(ʗ"&XJE!A\a gަV+Ճ݇S]c 1vh?AvlkmDMWnkwsEyt'  [Ju l܄ȑZQЋWوM9NFi"ePژe@eG$IM+{34&P +Tw}~hS_-MTjh|8C:)FѶUY +: )`(/T#V_*U*t:VٺMe~,O&gk27V;ښ=yK*(T\ wol5ѾwڏOy OM[ipMz9K{P+nl}xf3^KY+#K2GVStGo>ݾO;\F rWAӛr ?ƀq NcFDF _k=~/nxzo??GeA-AfOD +`{͐ g\o_rFڹYCàSe43gfH23`,GD402DEc~|c6ԍT.Zvߣl(! ~xoQӳ6lپе!;ۭr,SU"^jG=Ruy̒9K|"_`$S'?V7̶ +<+2.r>eE Ik#~nq3~">kL2_D$2–~ s:CCsmx-/_Ԟ.z:/b/|[ȃT$ZWqKY +)$sE0<>x + 1M-r1"c"Y.Gf_f!h2fvpڕ!@H@;C}9@,CZ)_ک&_Sskpr=bM1yl^/3-zjߠ$->qY,yz!>>64%h9mڠ 6G6ivۺRfѩxبRt [7\P+ˍĔu‰d "sTWT䗍"Scmw-?1Q"#2z,`;T ;! +aKy% s3370usI4E" o6v YkõwJ@ccqf"˓2zXyA`jwe}>|&jm2*!]Nb1-3B_@zoEġ͛`i~tU 67n8nWBC̢YA{/a4'Шŵ:.&jvPU\9IKP+p|s\z4 lĦTEye۰=UR p\Jǎtm-P&;:׷ +oc+cK6j׼'~g;K njC<%7q^Z0 abkh"+ YMWeFE +D7B]ٴc7aØKdli+ hs8g|&T&?i,I_7ke592.}The 0)[bx,Mu7#w!40ˬ"fY,T@>>R5y-iDz3lfrg64IPLjL3%~ZbOLʶ2x&:Ҿՙ}: +g#&^QM&U{/-k}6r>z>\K~=v,ulG!>7-n:Qbj7yTM':v?=UB?4m6i3wЧcCW\C>k8@!z-y,/腁8q=聼0[8v%NS\Gڪ城&+mkoFFL_Aom24Ͱvَ+Ӡ_03P3 fJ?HIoKC@YFhDRnN@Fn7r89uqs g6[[Λ?qS0UQ%O 9,mNgVd"gdܝPSS^'͟S޹fYkՃܔN_=zXE.e^"*ftF4DDF\ebs)%-M߀mЛUYl&ZTUN{Ai]=yXJ^єmq6)Ъ1mf! IlA~iٛY'~²"DtBfMH!/˒u'-!mZo{ IF(햘" Gf K}2.qNn}:jd9Qj7t,ηo[? mO.trP1j{?yL14&-ȇBM= %9^;,d k\!Tt,34Hݍj}JS)I8" +vO$Pש3)֪*' T b&( I@C}3JWep@Fpeseja:;c>8Ǫ} +-ՅmxU Z1;N+-N'՘bZkXjĂ3gGEc:#HHkZ+R`U 99LL Yښ؂`0_IaUt3:^JOt3!2БVlLƓ:k5^[=e;&'KqN "BzR$gHVҀx2}Ys6A` T6o9xN9ngh7V$/caMl) w}06X {$"h} zhքTx.ilX=iKKƈ, 546 2dO8 +4؎i1X"v0?Ny&هQogk1=}GZy5&j-ZBS Vx9-_Z|LCF1U@SZl; +D^Z* +*^D?z\/,Q5*C|Iڢ.UרUAw.jQݭ&"ffz;xDUp"٘%!lV3Ehdj1 儤É( kIìi S760,g?lm'}Aq=uIOpQO~ԍ۩f/fp9iTQTC_zPgxljPaq+vF/OK{MZ0U {1{C"_`[8|Cm0ODѾn<).r{7"%d^:bGYTщ"[l ǖOuP@4Ft7  +3 +WzS0p$a(#6fu<~9v 豳8f:/ҵ3% {֓;WIP;{ q+u1oFMZŴZBD"Y7fE f9r>FCb(z,L49̑[牆s勎V?/T>c&.<۔z'+U~վjw27o%R9yXF%݃K,v{E.gpTқJpX J(] a#rkD$Yn85Np,E@(Qj;&s2t :#J3`ľ,,ԤβGL2ɲcS-Cګp5TC5\"#L{}9z,yl˺u[}qc|Ȃh&ӜKdɄXYm"8#`'0WX,;ӈN5kYȂ`ft;-ٛ>}^ڵcRߴF|osZ9UK\.AflVWQT=̵HP/5J$Ds!cFn#p yeh5D0!sjBˑd.̾gRd#}29`JZ{oD XI?yo'xuV&6!SZ YݟG#!ղVDtL⾕fFv&|VVXPp&  zr Y.nOT?.j+S?gV'_m`T_sx:1 _txy־֭ۿ C;"$HeM:%]i^(eRXΓI~ןn"lnDňL,s%%( 2hB+)dBìX =do} ;\0Mms)q^x4h4//LLn#?Ġ2(ˎ]Pf}4YC7!R*ۜ 34umtB%EKNA8IpCULJB@a4j&i,XLtO/a^=@ǿBżS(McF%;c5]FI ΫKr(.lb~_& 120̐)U5PZg!+/|^7u I0̵ S2tbymuC3GRd{0 )f¬:٥t  +Wd.N9$"b}=20ut,Wb BDw|hPb}e-{pU'|;<9Y'$xLpE(Hs&^ i{Qdke~Yd9ň.Osy%ly-U:E:r5ꢳ Yʉ)sVY5%8'xf5M+ՙ3ObxaXb+8,S$21OYtV(i6 z)+OrlqҢGf'DNLY:'D8Ūb'pāF2$Ɔ9IUe"3#CsA4YgNu +pf\vXcmю|s}wye{ 4%b0WE(nL=Sϻϯ{uϿowws, Al"c&hÒ, \vErKRh;]gez[iZ MP3(}g!R=SE/ +Hu&:JP=sƧe/`:u/hC‡X {3S7[7be"Ѷ"RhfUU7MujR<"wq㜓ZQ"K@HMDX @3k-#(R(ZiigNkDMVyrskM>SZAg {]mN1@(ŒG{[oMb=rC(r|^gpa`rKNB.3\~f/E.W>`Aף30(YrA1iʘ$Y wL0&y(>ġĤ4i: P 3O?+y:ynwy';DNBW!82S]!>?#W! +] +()\,GgM/"  ]'Fcݨy ԍ (ǀY[B;J~Zٻ0v.4v $/Ld37#fcw{ݲӭ۬+pV:(ha`!B+.KWI®v<9?oQ΢7 F^Rg&dTM~~f 񕒇|GJ[Q|+ -[gu扴&7N~v=P.c~}1Ҋ .39-dn^ȟ-v>)'\$`oЩX +xlxlOa[kboq֠fP@#Q;U?g 0s:??$]&'ˉSd9e,_"Ǔx#]}!b3S&:It3 ]K\l^lfyҦެ-2M@QBQk\a/b0c\AaɜC6gRwf *c/+]C@95|ߤ#Mw_ֶU|M72>seUUo!SCX.')NлiD`N?ʧ^~QZg5lm([z=/^ذd լӧLotЪM҂ohGq(D`a*9Bd63*t&\fڙTQ ʲ2| jH5׸q +ܓ݄-B=" 8(C(kHa|&g7`hA/@\*^N%pdƗyZ#-ME_j3ٖԺZlm۷-ێsoe[n1^1~0͠A vrjJS&~^jsyf,i|. Kkˠ,֙7ܴ3|$\KxvNq$Ƌ{¸faƤBFl<0ogLH"GΤ0g܃R0Vdz' ierDTE]) T\5 nY%|bS{@oUG|x6YFgޏQͥMboOӦ~?~\`j7N]з{mp^*[y9Gő:UJy-bIhb|fƐ72*dF\d`QfIzQ2\o!I~L!ږ9Oƞ2lkPEZi Uhs[[ W>fK$ɾhOܪIhVL-2e2a>Z$Υ,cZr%KpmIsɚ{x,1%tFB '!{"-XtU1"%$2v"(VN_x^j4ۖܺ?7/Ze纘%ɸP|~!aX,Yֳ}W=w~Һ +qU(q4zwhգD[.mK9ʖpS8gpn6rRRXĖ㝃a-\f?Gxj*#DˡNZf_k3v;:uz-j:~`xi0Œ/Lf$_ kΝc2WWc;;SSǸSpG_3Uc)ۿ_ oy!Ipvbģ 8T>[=WT13HZ#UÈ8<"2j(=|TP5jmUG[[S&,',@/UU wҲkpi9 609 zgeA+&#O?۵S{nOzWۧu @inNqpT֦NiLa/m-[,يM??Qs߱jm5݆㥬NQZ^12LR PC\U\&,od vδJr:L!?tO"9\[rI*Q$+%U%-KA7 =r0! ڟH^l꫇SO]ZU{?PNc-q +metԅG"3G3l#pY$P<vZMB\7y^\}28R"V0Fhkdd"K%~lHLYnKQ' r!c)=iXbơ㮆4aą{!nhk{7Z}iyr}t,,DkǗʲwSw[ '] |@TNđ:n`DN!]ia.+s%iy`IQY0ndJC?*pzKOfj2UQh1&rbiQ((Hj6.K#)KyIm9صl{%"%$bB͆X82F km .lk\cdʳzCvӆ/΁81Ԟ2|)׌s6h//\֬N6h-d&?Lqgwl?0~! bp+8u'FVO؛~\Ƣr[RUTf+v23lOЪ9<"(Xx  xq\pB:ˀRPE@r¿vϭZm/Զ5SNĻo'.ċ[j+ػVE񸾩p~#i7 ƟDڽQ4=w#n5EpILe8M,F?`&:cCwtΝV#qni&Sg|-!I-.Od@d餄kɡ~@~[/%U>cpڞF(-R\Eț]rkOӻw+{@ GL/+Ñ<\m|^:jG"~EWf\4)@f\( c"[ ǘI(W h798<G''/ej 0 +=-$[O:_FQZ?'h>2}}O4z4?nRvoIvJmq GP>\x7bD)|t^qɪFHžBpi!Q+=1uDIt:/ߧ3>yE&A 7,K.hS0h\R;Kpݓܸ[ײm[KiZSO=Ҳ\lgt͓m×Swkz$!nT Ktj!"z߉<_i$P;T&}zIG~Yg6,) H7fE< {&{𑂓`r. 6% +lbddӄ̡m4Kmuuw;_:QZSdh,Xe}\ηAToD[hg|.|6yhr}9ŒSsPTcg^޶j1ぅg O~͟`|HafGft:#8pU*rU,D\c|dSmcAϣ$R\UJ]s#Ek)uQ-!Wwpt׀fL55M5ЭBXj,vrX^a *P N  W 0F-A\-UP c8yZ0%(⇫",M{rvFkJ2 ^p  >Ygƶ6(LF&A?kv~k/t:8뜗7"RG>T3U0 J&_+bqXG\U>ȫp2]ܿ*X\j\mۗT\Z Pp]O,g/|gr6QGrWY b+W9ŁF*9 CJ(Ow͹k[KuJ؊Px! +;R ? +{eLKjӛ:zs6ܔƽA΋ǎEӇEmȯ~mKM6O]YM4t8f[4l0f0lJ8 dƛ.j RY[Rɜd*yCc 2vL11FGM +T*u +S*=H1fֆ\="4e:.|̤HXG*D g U;#DG=s)Ɍ96g +4 }p8{a޷}vp_% +ҝ668Op;tu-*콤zS{wiu2 F嵷I`j˦57vU{v3ʃDZ{ɚ?~W MӕSZP!bwq*X$5(3P]J)&U(Q\Ho_E֎pK +Be`XԈıcM0=`h0G~Zz'n??d.;6X},ח>]ʍ/tI鋥;K&JP\%U^λ{KR;+'03WߜB#}|F[ W99A:3<}!K{^k )mjzSϦ~l{3{Z׿Z 펫'h-gA!9pG{y}*,go.z=w ?9~vwj_V Fl\F;'(YD F%!:+B BQ)6KH<%nm5,#Yy$nVd]#>u!dYƳ^ȳr6d94tN67=OW J҉083S +~XQ&AއIPp]7|l=uGFsc뼥Z^ fسСV~衻~0K;5>}L5dCtWj(O,+^R0xbU@K1^? dS`kͶb /fMּT U:{*c\2d%^*jAD`ji?{W)9zhkʷm/.oۀO~8;4x\,F5.E NbYUqEEE>006YeH\1B_}(}mG_L7t]I]?[wO]tYTQqߑ'㬝xJc. -BA`7Vꪼ;\m~s~K>CiK@\g@dIjSR]ފ 1ZTmwEy{m+;v۷};X])P +endstream +endobj +2973 0 obj +<< +/SMask << +/G 3015 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +2974 0 obj +<< +/Matrix [2048 0 0 2048 -369 1517] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.68652344 0.107185483 0.68652344 0.140136719] +/Extend [true true] +/Function << +/C0 [0.8863 0.5137 0.3059] +/C1 [0.8863 0.5137 0.3059] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +2975 0 obj +<< +/SMask << +/G 3016 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +2976 0 obj +<< +/Matrix [1322.09375 -1221.5 1389.8125 1504.25 -369 1517] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.055175781 0.22021484 0 0.055175781 0.22021484 0.072498322] +/Extend [true true] +/Function << +/C0 [0.8863 0.5137 0.3059] +/C1 [0.8863 0.5137 0.3059] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +2977 0 obj +<< +/SMask << +/G 3017 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +2978 0 obj +<< +/Matrix [2048 0 0 2048 -369 1517] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.51715827 -0.41607392 0.48547289 -0.43429303] +/Extend [true true] +/Function << +/Bounds [0.99999994] +/Domain [0 1] +/Encode [0 1 0 1] +/Functions [<< +/C0 [0.7922 0.549 0.2627] +/C1 [0.7922 0.549 0.2627] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.7922 0.549 0.2627] +/C1 [0.7922 0.549 0.2627] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +2979 0 obj +<< +/SMask << +/G 3018 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +2980 0 obj +<< +/Matrix [606.3125 1694.8125 -1928.3125 689.84375 -369 1517] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [-0.54394531 -0.87646484 0.0092207491 -0.54394531 -0.87646484 0.052244902] +/Extend [true true] +/Function << +/C0 [0.7922 0.549 0.2627] +/C1 [0.7922 0.549 0.2627] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +2981 0 obj +<< +/SMask << +/G 3019 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +2982 0 obj +<< +/Matrix [2048 0 0 2048 -369 1517] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.87006438 -0.39392689 0.89661062 -0.40923685] +/Extend [true true] +/Function << +/Bounds [0.99999994] +/Domain [0 1] +/Encode [0 1 0 1] +/Functions [<< +/C0 [0.9804 0.9333 0.4275] +/C1 [1 0.949 0.4078] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [1 0.949 0.4078] +/C1 [1 0.949 0.4078] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +2983 0 obj +<< +/SMask << +/G 3020 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +2984 0 obj +<< +/Matrix [-710 -1654.0625 -1881.9375 807.8125 -369 1517] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [-0.68359375 -1.06542969 0.022556543 -0.68359375 -1.06542969 0.072265625] +/Extend [true true] +/Function << +/C0 [0.9804 0.9333 0.4275] +/C1 [0.9804 0.9333 0.4275] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +2985 0 obj +<< +/SMask << +/G 3021 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +2986 0 obj +<< +/Matrix [-1239.875 1239.875 1448.15625 1448.15625 -369 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [-1.58496094 0.23632813 0 -1.58496094 0.23632813 0.145507813] +/Extend [true true] +/Function << +/C0 [0.4353 0.9569 0.6431] +/C1 [0.4353 0.9569 0.6431] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +2987 0 obj +<< +/SMask << +/G 3022 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +2988 0 obj +<< +/Matrix [1331.3125 -1141.125 1332.8125 1554.96875 -369 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.123535156 0.22900391 0 0.123535156 0.22900391 0.18945313] +/Extend [true true] +/Function << +/C0 [0.2196 0.5373 0.3922] +/C1 [0.2196 0.5373 0.3922] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +2989 0 obj +<< +/SMask << +/G 3023 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +2990 0 obj +<< +/Matrix [2048 0 0 2048 -369 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [1.17919922 -0.35253906 1.02099609 -0.35253906] +/Extend [true true] +/Function << +/Bounds [0.47918701] +/Domain [0 1] +/Encode [0 1 0 1] +/Functions [<< +/C0 [0.4353 0.9569 0.6431] +/C1 [0.4353 0.9569 0.6431] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.4353 0.9569 0.6431] +/C1 [0.4353 0.9569 0.6431] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +2991 0 obj +<< +/SMask << +/G 3024 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +2992 0 obj +<< +/Matrix [2048 0 0 2048 -369 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.68652344 -0.84521484 0.68652344 -0.70458984] +/Extend [true true] +/Function << +/Bounds [0.47918701] +/Domain [0 1] +/Encode [0 1 0 1] +/Functions [<< +/C0 [0.4353 0.9569 0.6431] +/C1 [0.4353 0.9569 0.6431] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.4353 0.9569 0.6431] +/C1 [0.4353 0.9569 0.6431] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +2993 0 obj +<< +/SMask << +/G 3025 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +2994 0 obj +<< +/Matrix [2048 0 0 2048 -369 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.68652344 -0.84521484 0.68652344 0.140136719] +/Extend [true true] +/Function << +/Bounds [0.058288574 0.87219238 0.93945313] +/Domain [0 1] +/Encode [0 1 0 1 0 1 0 1] +/Functions [<< +/C0 [0.2196 0.5373 0.3922] +/C1 [0.2196 0.5373 0.3922] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.2196 0.5373 0.3922] +/C1 [0.2196 0.5373 0.3922] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.2196 0.5373 0.3922] +/C1 [0.2196 0.5373 0.3922] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.2196 0.5373 0.3922] +/C1 [0.2196 0.5373 0.3922] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +2995 0 obj +<< +/SMask << +/G 3026 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +2996 0 obj +<< +/Matrix [2048 0 0 2048 -369 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [1.17578125 -0.36132813 0.20361328 -0.36132813] +/Extend [true true] +/Function << +/Bounds [0.058288574 0.87219238 0.93945313] +/Domain [0 1] +/Encode [0 1 0 1 0 1 0 1] +/Functions [<< +/C0 [0.2196 0.5373 0.3922] +/C1 [0.2196 0.5373 0.3922] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.2196 0.5373 0.3922] +/C1 [0.2196 0.5373 0.3922] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.2196 0.5373 0.3922] +/C1 [0.2196 0.5373 0.3922] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.2196 0.5373 0.3922] +/C1 [0.2196 0.5373 0.3922] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +2997 0 obj +<< +/SMask << +/G 3027 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +2998 0 obj +<< +/Matrix [2048 0 0 2048 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.35839844 -0.69238281 0.65429527 -0.39453286] +/Extend [true true] +/Function << +/C0 [0.9333 0.2392 0.5059] +/C1 [0.9333 0.2392 0.5059] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +2999 0 obj +<< +/SMask << +/G 3028 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +3000 0 obj +<< +/Matrix [2048 0 0 2048 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.78857422 -0.6015625 0.94067383 -0.44995198] +/Extend [true true] +/Function << +/Bounds [0.17614746 0.50604248 0.84680176] +/Domain [0 1] +/Encode [0 1 0 1 0 1 0 1] +/Functions [<< +/C0 [0.9922 0.3922 0.5529] +/C1 [0.9922 0.3922 0.5529] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.9922 0.3922 0.5529] +/C1 [0.9922 0.3922 0.5529] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.9922 0.3922 0.5529] +/C1 [0.9922 0.3922 0.5529] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.9922 0.3922 0.5529] +/C1 [0.9922 0.3922 0.5529] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +3001 0 obj +<< +/SMask << +/G 3029 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +3002 0 obj +<< +/Matrix [2048 0 0 2048 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.56689453 -0.62744141 0.41674805 -0.47729492] +/Extend [true true] +/Function << +/Bounds [0.109863281 0.37359619 0.84680176] +/Domain [0 1] +/Encode [0 1 0 1 0 1 0 1] +/Functions [<< +/C0 [0.9922 0.3922 0.5529] +/C1 [0.9922 0.3922 0.5529] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.9922 0.3922 0.5529] +/C1 [0.9922 0.3922 0.5529] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.9922 0.3922 0.5529] +/C1 [0.9922 0.3922 0.5529] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.9922 0.3922 0.5529] +/C1 [0.9922 0.3922 0.5529] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +3003 0 obj +<< +/SMask << +/G 3030 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +3004 0 obj +<< +/Matrix [1434.28125 1461.875 -1461.875 1434.28125 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.88232422 -0.75097656 0 0.88232422 -0.75097656 0.163085938] +/Extend [true true] +/Function << +/C0 [0.8353 0.2157 0.2157] +/C1 [0.8353 0.2157 0.2157] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +3005 0 obj +<< +/SMask << +/G 3031 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +3006 0 obj +<< +/Matrix [-1363.40625 1528.21875 1528.21875 1363.40625 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [-0.077148438 0.24414063 0 -0.077148438 0.24414063 0.150390625] +/Extend [true true] +/Function << +/C0 [0.8353 0.2157 0.2157] +/C1 [0.8353 0.2157 0.2157] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +3007 0 obj +<< +/SMask << +/G 3032 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +3008 0 obj +<< +/Matrix [-1579.75 -1303.3125 -1303.3125 1579.75 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.33837891 -0.77392578 0 0.33837891 -0.77392578 0.114257813] +/Extend [true true] +/Function << +/C0 [0.8784 0.1725 0.4196] +/C1 [0.8784 0.1725 0.4196] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +3009 0 obj +<< +/SMask << +/G 3033 0 R +/S /Luminosity +/Type /Mask +>> +/Type /ExtGState +>> +endobj +3010 0 obj +<< +/Matrix [1448.15625 -1448.15625 1448.15625 1448.15625 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [1.390625 0.24316406 0 1.390625 0.24316406 0.102539063] +/Extend [true true] +/Function << +/C0 [0.9922 0.3922 0.5529] +/C1 [0.9922 0.3922 0.5529] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +3011 0 obj +<< +/Filter /FlateDecode +/Length 18220 +/Length1 33492 +>> +stream +x |SE?̹~m&M&iHK m W.ڦ[(K@EE@ +"*Utu"^V`UDs&t{̙gg3I 1M@avݜW] ύ{ #`sf.T#j -GkP5j|MA*HE t#]ǥd\cF >p*(`dӐgaAϵ.|4\hYwrad@Ys 0 +X8$u ^h0;/ 2a%G\}H) 0\3`&̃f/Fq- fh >F"DZ`{(O_z'=Zƶ,^'y;\OJE">f D\al { p5Q~9p;T>s.hyEFǝp`5'Ʌ`U ax +Z`5aXy\~ic6S uqx6}.[`+lga;쀝ݑ!/˰` lBv1tAu\B"$AQȀh&@#Z0`4sXˡR qmۇri\hGo-\ #eZy^ C + a^/inB[$>. C*!U{:#0 >8 +8|'O WsA\Kpuu$䔎P,G6DHrleUާt}ZmaGPz.B #al}){HlFꃞK Lte WW~x6c Ŷp"/Ġ%SMKt=A` ̗]+F =Q(YC6^XB&!|DE$rwTCTo FΨAQj\~ᄡ%ZuۢۢWk[zE]"Э^g׮GտW^ 9>Wƥq#q?L/yɽ%){L;<[5ϽkNӝw>k ~5S&WWUN𖗕N?dѣ + <#606hk*\*)iEZs06$YGN:s0_@m\g'h墙o3HeEVsXB˫ÅjsR2*X,yr磸ѷ\_s;xh[P4n͐iV\V_6ܹm#l`[-im"Y&bkqjV[B=[<9E3[c|֊F:ުŸ4QPJ&槧QfE#艹Z[ )[ eن(,(6|n.Bk~Š43VíVFDF4zz&VYW[[MP`\۫A66FwmP`\PU86:(0( m5Aq$V̥#*:+G`ߴjV57UAm$<$|#Guk5SG[Pb[Al*b qqI# eA` +l fG*,Cb$!UA&{KEۤrIP<((yb.kVWsg"b*(I2 (1,AmUPE=)zwq-$ JlAmL]py=I/ Jl!|bVH$Tk. Ҷ筋,4+qTbOO*[[E_O@K$C.5y"HpOֱm;ֱ"_w/Hx,f_5e Ba$/[U39#l θtfi1~ bU$k,ۍ@/ +լ.( 76 z:$׶b.l;ߔD,Aʆ\^f6֚b1ly zux*(#)/uCRm +'VuVтêI22aVkkf9&9c5bڏmF.mXdT5)זL9DA=hh&Z{[Z֪ͮ0U$5L[-xF2s3Z-ai$؆#!K36Uh5Id9ު`OeR!A#*^OZs㭲qjsX~ NjFQ!_m6T-N1Qu:*;5f3~x1?÷2?,dø+wR$C:㇨=yNC m9b͏kZ$e+?ɑpWEx7rC1avK{_`pM0$7!?~7\x(#y5G簝~>}D<7D*)|̓<9xr'ɇ<'x>Oy.O~Ǔ<9“wxɓyOMyO^!x +OdO'CVp3 +@rQzSQ`9 OZj̡M-mU{zL%=>2/=D4ϩ{bZ L"o݀`}'|BB|j.35y;<Ӭ3ʆʺJG54Ԝɧ'S++ݕhbzEYrʲ9QFsF7G3UTUzBԝbe*@ўe;7)XVCTsY-,!nOH4(jh +Q!&M:kqvS]%3+~"p~h7:L!wD"@!pN8;B8N>$c'x%p;: M- I x8HP>BO`:h#$n%2""y %p9I`6;N`fh$#@@Z L#0@ )&&PS;n#0@%*x (#PJ`(!0 "PL@!x $0p %"0=w!M`0g{tY"I38 "ޮMi[K%u@ `%HBܮ& U/@,=4 ( ( ڕ%OJ@B@L@D@H@@% P(KLV%5e骲tEYbIYb,1,1,1]Yb^Yb,1]T,1]P+KL%%*KL*KL(KL_+KL_)KLg%/%3StZYb\YbgeO(KL*KLT>QN)KL+ +kH5WxMPxM*^1kzO5^5~*# +ԩVxMo) +ɳMkz]5^UxM^At@5^+ +ikڧ*Ԯ޴G^o-7V^ozY^ozI^f%7(7 7=/7ככvMכMMzyyiV{riɴQdzRd k2=!k2=.k2=&k2=*k25ɚLkeMG&1,7PsbR[_M:έ(h*n_CWhu0^xK)A:hA TNRՆ#ܮo[~KUm%{< >^Q.A{Z,נm*yCQyӓ2%Q7hbbޣxCAP(Fۛoo777yy`u`7Ghssyv{y.ٛUq8rl hQ(> +zCC >t|'C?>w.]C+зC߀} >Y/΀}>>t|s𡿀}>g?ЧC|C'N}>t|C}>t |}~>.z||m >C +>t| +Cjj +-C/z|v=>|h;гC=>|iMCOmz|hC=>(zuCkz||ACj|h%Њ^.ス] +>tO\+EW {%Wz+ݹRmꝽR+@TR+ՙR+UT{jCT{Z+^N^NjMTJWUWz%Z+щJWe,^i^)^q{%+1Oܽ+aRrJiHr{+^) WJYRRFC_]v=Q2 +4T^utT*A: +4owFQ1|J50)I:Oi Q.yTɮ 'Z%Pb +h:O9gz! +@>`r9HmQso +ά(5ۙ@h8]sPg(>|5^:]Qb }5 ^mI@ڱO.HB;BS']K`akخ&y3']7'W,Em1aMsRU;FRWƬzc~xZ5͞>:pPQԲ_}jZ5mo0k uF$cL=p3!<ÐSCVYnBx\+5=3`i".!{dxy*B"|84HFywTL'($8ހ$?BHb&@wFfM`5zHʙNJ&*hm3+'>Ÿx7)G8扙C>8:qӨjkd0/Q́rH$(4 H*-z#(C=*ŔEB@ Rey!6L]NnҹéBSߙӢ^!e ?O d.NiƩjLnt%ω+w_A?>|1ݹmA6A"V"S$vxy-%"av;]{z7rt9.\HL苪w;xD&rXHV;߄W޹,cNځݳXᏩWQ3P8t@2xp^-W<H~̷~M2(c (Y7 @ DMD`Jg~qT<ڬ{-}Yg%M\4!iœ&..M6{)/nϗ׼t7ZǕ94k+_s>C:(g;"k H=+4]<-zXJl@ 5].N=- +\x[b9u<[^ה=s5k7οZq72~6!hEwwXC},ҰFeY\sW !$'Hkݧp9ERa+`|.`H}HJp*8 ɇ/Av' +l +cb#RBɟ p坾-{a8zVYɔϴ#)/}K/*0'-vJ[,_pkIY`cd `T,1C 19_bvcͱ3."'hS..2y< E߅ˀfn3R 'T0*B_GB$D !B 0F2f=YiP==QRZ&a +T":2OvNNF˥rOnJ>xExr3,\z{c_p*[ Fǟx6<5^_Çlߵb&p7zR " Z(@ KhF&%y<:e>Ց,P*J' 93+V_PGx dGM"Z֢s_d's} ++B (!t +QѴT&b,yKEҩ.;Nov\{ɟ + YP8}B܍.enSõ"VBFfmU7&Ϝ\x_:iq;*K)6,oAß|t#|$32]tлRz~-ȺHj:uxTZQV+OX/ɑd&hzͅ}/)YT oׄj2sW[}pnQKJkeMȱ)=cLJ$ر%+FImHJiiY<"Oh-5ouprq=c88gyF,u-?(WX0}~5}s:ɢ!wSzj:A :มLLxY% 9q\T}Xzt,02L%PɣϮ-ZcF%œHǣ/RTiUFɵ6] +SYnˊP^|kk'/,=lN`lm h.Nb(=FT*B,Z^*E"Ds ꉒrpb_y> N}rt?NC"r@TDPS\*f!.T{ $kbttmVYt1> +G_Ch{e_Υ]ׇguZa>%VB +Gmd4FPG~ۀR2o-3)Y O>'/a'hXI6^#n3f}Yc3JMq]tp*eHFj⣥l⮢ߌU]/6-\#=:5gŠQeJʢ$TgȂ$Mw)`2tiaI8DuLePVjӦ!&  6(zb=)XbURZtBZ򧿆W@_~C^2ǎ!b飻o+ȟܽ[RZM۰Z1Y(g[3dF +;ή1]*(Q7< +1#@/ %!4#zTZ.ϻ.t3B倰\KRt)F4%.'Sd'4vD|-:ږAf֯g!:)3>.+)::)+.>3)feɮhHe66 FРW@MU +!$'Q,ό+d|n@SG>#ګNHdR?$meJE|vͭ9,zң.ӨqR[{zҬjT֡:m~&m A: F{B]#R!ͰLE\H{tT!9>biw +Pؖ{L\- &>\RGzU1]~݈wq ^ӿ0^?Ð ;U r!& =\>!ZXo3K r~E\DYb܅>dVץ +.R57'󩈏̢3SG'TPSkB^eNΰlk2P>Q?(ۓu1ܪTu/^-LRhO.^B{U g6^a[F`=)32]\uMX{:[x=C k. +plEWS8۞yKiOo]uyD탋RկV,(<.kz.0: :82{19,cWS(&V$/-t؞2nvQqB(<5 {skxk:FW:t`##C.1p'$g FI2CLV* wi9*FUZOq;ʯ9ՒʘiiɮM۝oD|,\>Œ_ooYqPQPͣkZ$Mwl&Q8Z)\4WpcmgA:dbF>walK8s>D!]:H u%9VfC-*v4LBGUGJIW_ ?vv9BX/HBPq% k6HaDxpKCFz;/yvOZz&k֔Ӷ=lc9yչh[xEeOn5TY<͓䒫jVј7p{eATrb$BH酪dy)\iyӤ'ӈE-~ +<ytʍpӫZ*){=Čvok_9sG*(٣H~0Cl Qһ -B TV*rWA]'4.T^ p1i 5?L|x䑥>Y^^Vݻ# +gޯ5&\|>"(YHHbbѡ?xĴPT.ge9NאďG6]Ih=Jr;# +k!kٹ?^;\;ǯk c[\ YF ɤBD*VhJ* +rSp.;;uuIU2ZrXT*S<+3)r;b(£bDh?T^Jtw~ά:9/B?R +DW\I KF# }'Tn'Ԅgv ?;R FGdr}N)`lAR23Z%4W*Rsh +btfS4&. z%qUe$>~rKG;T]*^ UW1J1n7|2II =C9Ɉ3rFygN7f`p○_=:3fH{Sw ATݽ%=u_}DW'8"5z`>ev dVyL\v }[ +ٶm# ~X[אWe:dMSsA=؉qЦ Ա^Hʞ8"`Hhq8f4šHN#DCzՌ#}ז#1|#D-@mu&wB/\-@ƪsAk(&:^tʣWKF2|Ѳn7fXƸ2ؖkWdK=Ml `MJD@fsGjB5PGb? 7*P[cs^{ HYK"$jhGjVe~;ٴ%#Y1OT_Yg +˰j֌8cv@祗2CF} 7'UϺ~GܓhHf QՀm 83HgEG;l;5z۩@0Dtα7 k2w7⾕ \ߒ([lncaSnnh(sؙ9cyc75%]t& +(-?qtC]`: Ά;7א&$b9Yz\&uLpRd2LFP!ps4?Ĺ`pT4VMlP0uvGgg_ +h g⑹ʦf[@Mz{A!4c "F&H +)K!)%P +ZVcĠrer8X4YY'=)QȰ>2ܒHhX5l͖NڦcÅukc]n +BFXd,O^x0 M:8M_C»Xa?_=4EuQ!H䵂&ڙNBA3|z$"1+@؝z}k`?ФbcB[iy܎x>nG<0F0Nx CkY{Yhdah(7Ĭ)!Ch~TdTI עb4ʨ8758PPJ[E Uy5m3OR:եֹTIK(beQ"bLȍ"1#7 i{g;h3J;- >=n=n'N'>jA/5ד}h}hlx?~ގ'~U=x(DO$Cw! l(Σ'jI$=kl6F'霪*rԖ_m! e!6`ujR2J_6Fq zyqEa t'AyمMRw!JQxzxOmu;»7\i+}.7n\wxidc}GJ+{D3'&[PG#iS LSh/^ V5L^U;t ,_2y؜5ʖOس +fsD5{hVl˒F57Q7'V2Xs^ّx4sh( W%9i GsbỴͥ}3 gH;0{ⓏDQKz6h?kfPE/2Fx&*9C }OeC_7Rĸmx!kIJ +Y^L2h<{ugkC!u)3 +)bQ+~;36zoY#^Wh +mXe)NN[/ x٣glQ=,YN !6 +00DGbTAkCѫ0^]vv4>0>;C1t`bP}1e❋.o;G<_q;I˳ӿ JѶ T+9]EK#Mrr 4Xxgs-_0x֖;9x).kҏYV8եO.=h ]jPƤ=*o \{ۆOjmҤCⳛ^I/ +/-&pF(A"Bz41Gdj| $6tY-q.P{ԩG8|4`l/>uS&tsso޼[l foًV4_ĸw6lh_W݅!ӋƏͷ?m[MhAongI$i-Ih-TR TP Cr&6У7!P$=x+jRz=)zНZ[y̾y߼ofnd_>>/s{m^\zR8K04<]J秆Ԟ/]f`9VU k.xț Y8 Hޘ_~˶a{e`nl4꩒'j,^cy_+SqiPW>d(޾.|f,>E=j2jCZ1}W s?^qBM6M6U7NQʜksޗ|VN'kn0V[ +Ny2׊m{@fz @W_-p'ݱH>vFO:DT֜LEVe'=> +stream +x}|[=IzSe7,˖lKq+*E,B RwѱLD6[}NVPӆ V3' e-Gmشn?!({A㶬]kYަէn#>P՛O ! +!2[F&[OXz?D'BOL䭙Y$NV}r ݷy!dBԏP=l@vQE_RX=E&E@ oA{_kژgGZt%I-b-5?vs*NЛT %Uޠ);z=KnF.z +֚jinjL6&j㱪ʊh,\* >"Kr;6s,C[& +ϘYOHo 8A="qUEUvr];Ӯl7rz6Ɂg$whPL$E?03~`edzNggo8`spN?zF҄!㌵goqճ8wM AQWճ7mPճIt\㌻gLOW A@7zvd-(䌡1|]={[]={!j$-!܌B]={+Үm1 LJeDQtyWޘQt8%7*Hi JqPEX1bxC88ٛ4jr%齙#"ډ,hǷg랝{;jxmo]Oǻ ݯSqϛ};]w_g/?u{x쁧xlypۃ?>>{輇.zև}Go<،.[~|g>~Oy?yѓW>))S?س={ss_ł<> /$_^4XM/ /_~y˫^/_ۯ^iye+=C~AiӵlSW !ڿ9nho0c /# +ȝ  j!GBгxCu$~ߢ}B֣(Nd0yL)KbVJEWC^E[hinjnhμTV{|zϏ +ϻOzq۱XVp?9.+$* Q4-E0_)'26`@8DH٧Mvcϊ`7[ s4 q{$.P%5$v$bu. %T5D|CSsS#b#R Eʙ?]sYOxe"k#cD^M0v)mqDOCV'3?'k;,Ͳ7e',MTegE/=ȄYQK6 t)0e?I` J95 M,ĝ?>gS~+$G\a%ZfϘys_dW SH &3-l$Xhˍt}>44}v$$)͔l'L4*J>_>RJٗ"d"\. R Ř LTbkNn~M/7zcy{2ղक{x?ȲL4gghY,?R̲unuWV]|/>PeZ)KPgG {]q#g>G0Q&Yl:lY +˹YAp.|\WjLܼjH;sR:mڼF*۫>;fI,UYM ǚ-&Yr#j=rʂɲ"6C}/ w]Jܩ:y7E#y(Xh$Ќ&phNX`E~x?r(h7rbVRkC 84'4W}_Yė&.Ka_B^|mEaY;EAษ^[x⸴Rp+AS 뽾j0LkHG&FVxȒn%)Z& L0,q,KX6#w\j( T[-dXI &9R+Ҹ=]VՄ+Y1W8$xYp]-%)DYGE4.@N.<~v:ˡ(,M֣jCG+k,z*eYQ5=,0 +4E*L=(xK1 xX VF#YM#M +RE1RV$ 7R/^~}Rq^?B<*Giwk +r+F X6H\c;Ԩp)|d7<, ]XTcncYC?/zG=a|_acKP5ykwvC4?R(NVJܕ`5a )ePBf==٘W|Q2qcð/!ZV{I+&7qJQ}O6'YawFvz(6u}$`?GIaC70×?uEmw'-'!G5B}/бyRS>yBcySLS85*ΛZyŘiS?Ja -lGb5a5Z֨&e,O\GX2Mk&6Oldm<p'Mv0vvl’MkT +6ԦDM]"a3r$6 +䪢0i c ڪdS-k9ےlFy{ۧ06!97l0ij^^*K KB@Qjf+(2lc8a0o;ĥBwCqB\{k,;Pe񾥫.aINjMNF`ˀ#@-TĊ>ɊQbҪ%< TDT#5.HEn-IT,Ie!&lL4&b!MZٰAy nLxhֹDAmU;X־c͊@5;, @3W՛{&0<[[=abxZj ZYQ}x|p|hUWs7цN_FКs-1nB VՍ5lk^Ȏd-< trG8.&]|f mnO77)tܜ9oᖣon֭뮻- +_pnϪU=^x%uXuxjO|%-koښ[|Ƶ[VοV-*[ F>.^`ηWeOu峦M׵wu[N&ͩkh;.1Lݾ|=]p/9u+9eʑv9sk"p4nm Gv|^ 0p(|hpgL~TCCj媖aC3L&: P:TV- a > 8<'Lv|ĉ[ ttut}m#V[תRnk6ScI8v.isTV&3֬1k͚ mYmo:]411]] zUA?31tѝe yl\Q +ғh2!CTehg&ݾ(=E܌u~0ĺC&A ' ;:<]6O[(ʺ>5CϦzlT2P&Klڔ#tUG%ࢲO\)w2hhVըK.4\+vX -=n +̀#r6>AQ{:EQ5:#+JtiɓYETEk](Z| +f5ܱliYgŎ|r2e7jr=:yP))W`EQ7^W_QK h +\ pP)%rTK}:^$:x.#wO5{/ڍg~U0Yu p +Kauo/ +0kchEaY%( +Ǻ멏GuZ Umއ+:XfER?B + !>&ײSի"iYxߖ[Ͻ>soVCF']/. ;q+g1Ɋ‚r5Im۔;’$+<GHiuozqUHZ 2y;)r6m}ב4mQ%L^AXgU6Vզ-NN_8*%Q];QM:` xbel)-vƐAFe!䮸"ޖӶ4WЗFO?~Yrnn#χ'TzZ1=X:Fg n0]o$xITȶ†bGp +GW`vXUIZv:ebLE;E1`ԋB*u*eP"ة` j v\x%iv&GyA&Tm;'2|>z,L1sD\4cKKl1 /z77b.XM ŘV]wEט:=V/PGjBk;0(b; (C &OUE`soj?X%Tuam]4I#&=6wmg(BIAu8G8] _*Co7Ehv;ж̟c3(_2>W./(/XnQA7C%+% 6*YQK4i:קf|>xܟehzo^|Bf9[d/hgXձTwΜ2 jSԪ5Mf ea:&*&uL5QL>}@[SQb-cĢhb:JE | drY 7aØp ]`(WYͬGBuF[2ȧU͡,[9DpG)&&;Z*7ZIYUtIUQ]&SvJNJG9J*JxCx4}v9lhgf P龳4%wFbh>92P3;I@Qj1WZYb]{ kK6;ـ8(Q]$fL0a52<p~ +\@ckl"wDq钆D".) w0>hpkN>vlhKΝ8qbr\ÄBߧ6(N P7B9b^H[*8N=>Լ^&@ [$Yt zٳ]}zw{{gtOԍ=UE鯯\S__3> +KK 4R)K.1/ Q3%s,K]S;:ytz*ZeH$\PIz\q.\ U5CXS2>ږ̟}>}p1͓0eYh46{Nu4Z2ڟt{u]C~6xGU*]1Mθ "4 iĚJz&Ǯ- oIfe|>鶶;:6/H kZOjLYf X,:A*#H +YQ' ^Ƭò$=DaInt8PL;h[K:7HeهL؂4`/)=x7ܒiY+C4mN:Ğʪ˪*|G|ԧO(AEjDT0ޡƈϙnhkܲsӼxvxtMVUEZX%RURQQҰQ=!y? ʨqHKiSMFRYأ(pD4_"/6w +CTiU=PrpTsqj4[x%[ScӭIbUU G\e|xרּxooZEVZZU_:/g[::hb`rD_~ +8QQ1k4^-܃nREaTh/ ͟g+ .Wd(J[vΎ~i=0]gJG?tdN 9k*[GEҚu/bY+9m؋J.q@J.6-fmFj1hs-e$NhU|:tT1@X^f) ewX[nE!0mC4թ-ǽa٢oU`8E1-smsLM[:)A%W =MoQb՞y@{cYqrCFʗyϮ&IYtl'TK[Dc-zհ4 C|fNin-7(;Fg%K[ܸQu r๬G|E_VwmNzF4Own::D^1xќ}WU ?ӆIzZ٪]NGe׃;^TL}b/@5fҖ˕\OZX,Kܮw YbcӱdDH7?:u)&oIwtAӵ2(wlaY"`2ȵeuu)%!\V҃`iTG,I#qu]K#|+kNm36ǧ_sH3tW +:r۪{auyarN9U89O]jPYQ D1\`zHՉb|aʀb0ʇLlmNN#qaw kΨY;[!ǒ[K: Vb,-im2yO`ZOԜ؈Jj5M8FƨN_b#O+]F݋lu]P? 3fhqT-&a ͸m,C-F ZW5. R R!@tJni B6q>#B\xQVڧMWk޿*$fe8b.0QYN./d3 *X$Y#}F5J?Pwo~wO y=rc|{i G0aP2&{`Q,4|E.w'>p)IKݘq*(159]Ltf{T8ƭ6hvƺ%ۡZ /sɔrR6K?jWLөk#PXXJV2QǐQpg*Ne'{&ejr'*]<&+ԹJ킫[WIb5|9D5iX?DvK-K<V鄨:L,aĠmk]* wn']NOIuR$am[o +@n:2_=n^KOo*bg ^> Lf0,y5e q6qOu3ŤR%RfAӔP~(筌.k\R80.$*N:bE͑$zsD e̲Dq6\9eg~tOvXXKdJE(@n7ZU[VF=r^Pa _ Zr Yh_-O6 k~KkTCdٵo Ca z6\ziY^TYc[Ծ6ήTZϓwHqTflpȎ|Mmj{brrV"rZJ^Ҭ)Y+eAg{ {lw L/ =^iB "$]+,vdbՖx0op'sWw5a* N=Oz ?7^3+s|M]Ka}ߩ>q$׶S NG*09Oc~ |q1Szm M}M|RW^DY l"ϋfgPyar#Mw8^(N_.,|-f+2w*m"3w}+E#̡zp]d +Lb%C9fÙƤ*G# h_f>-^l|}6Fc@@qR{z8] YާإɸBq y2~;D2$m.NV* +8t*=ׇX8= GhȯDj*[s=rCQe)rVǃ=ԿjG@"ӂ!@@/iA{,{@ lQ qOq^$+2yVO4)ո\9'6dEEOn>M\;d?=Y%gѿU#k.M(VvE{q?!K< ^:J\(}q3F4xq)V⸢qi埕S!O݃Jۣ2۶hpkT*P#Cb#N`kRP;6 ,:3sUTh CNx$.,!tj3^V̰ngIl@רw-! ˇpG݄{q,v{ܥM[m{aioyjKWXmlP + R|LZa;b~OHNדA2"NsĔV6WN1Gd.%v"T4EZMfGq٤b7M qbi tCڊv՘<0XE48{`/qq*Uō&*z< + e,<_nwa.=ZA\ԵŰ[$OTV3RәRQty*$+ !N8F?q{N/s]۽pFhj{Q+u;RkAtLeVEf5z-q|0SUzxg<2)KZgtw66`wfeLu?/qюy42Bߢ!\4)]yd1)[@MO4.C%@j\Q /u Yݺ4\QQ4v2 $hkKuXbLxf .m|RrJ_RΛN<1lQDj꓉|' SgPg@tҾ22a|a` X{8&mA' ++Jn,y2we2eE9p- ]] -l54QFvTv/-s.KUU0ќzܸVF5$de]ݩNZ1!ْjwR6Z0AXsK]u)hV鯪J$D.-fm;%Z[Euсq;!4NEf-MN'w+;++:+>oZׇ0jQ`K>F.5k.={ѭMrS)+&k'W K3T/8v`[]m.7o]N~ud_WE:#UUr^ZzDH{x`}ٜ9Ksټyȿ+;:2>|R{2){bʘG6ò-=fܲgŷ\8cM^MP(P?Zv?~1%]Nw܏gYo\~f#)^Pτrfes{6zT=Yޞg/wL/cD/5J}.Uʵz9 i;<}Eۇ7/׾2D}65+cHe }.Cakz sׅŐ*=;㙼_m=CKѦk=FKkzV:<$2Tϔ{tfGꝢQXtyD\(,^ԕ%bg:r)Ԭ7m0Ȉz7yz"skjCݥaI7M0ڤn6#[ϛ{yGQFG0zlF^as(us\T$H,Ðh2򣈱&4,}s҇¢)eYo"QAaq^8g֯]6kzPX\1*+0u1yCgҭXi}s+C:{wdQs?ɿlL6gkFd[G[گgK5"Y#oZZ͖V_ ݙ_PXFH&צԱE'd#l}W[uuȶks6|hԔQpraraj>eA[U2:sXsf[v_^II$#Vcf-m`oZ  +jc)|=*^ve{+;|MŃYŇuTl=dܠ*%hTt8 'LL)ycdqEƿ}tdӞ=|FOF--yyuøV7N߶moL q ~X@9r- +oPƁOփA?xƢ>öq_) +CĞ/8D[x'$.w;lBWvˉr12o1j?qģ4x88e8cUG?>7F#>1y w>X9'~O-_LwaBXg_7iB WL0>TYÔUrļc:VdĸX7Q03f94dBhg(k\8r"?%9җp8d_sj9 QCv?2v>9s2! ?wǏqByM&7!ty r92y89Gi G8au syWs:M=3_ ME>[.}?*r/_?}2~7Gz̺ci˙^_\ ƹ􅮿\==_ ֝ sjw|vH0ѝy5o?sq9+-龍g*C35,ݯc)R1owT={ÉǑrXMٲy}a}AE#$t[~d9;/`ϵbt/l(>~7ȋi@?j.R_ʚ_Tq4%wʗrOGN kFy a"fJCKJK Zc5KkMχKh> +stream +x{ `s沷lvgwMv!Y$nrI $&bJA$Ԋ6BV*ϪWo.Arрw J1{f~_̹̜͞y{ H&J#j//_uå?{0?_[b)]`ɭ<vi׀}`Jnn#1 ^c׾xO5̨OV hhQgj7p_f]d7\3gz/|{ qmݍR ꮝ9tK)l3w^t.n[<'7y7̨3s.dλ%@v=0 zJay'b1 !+ +6ZC], Q`OXK_$C +!=6c{2^ު/eAy~h͌9/~qhDS9,D @8,D.s]ɲ *Uѫ]c0%3jwϮx +x7T!C2ơ?~o>nQ_x{^e쭢T;5~L0&.l~cSJ_E =|w7l@=~>^`:ȏׅ>unM&̄:\1b<4`&c r@3b&:1ߚ'k|fi2򐋡㵶f\UŘf4jeq>d\kp dLL\\hjk3Pub7e_ٷ˨;Ný8.~[jG74?7kl+֩#9ͬ)^w#qSq|p;Xm?,<5&l؁c#֣aa| ɨh,r܋ lfl^t=[ &tyu nvzܜN.﵍N9NwuNZOI^=+%{̔TόMis7~Zh)#|lyq!E(Cq~a_㴃 +.O +I>D(dt8#|xb+( #CBqq<'γcv̶i!޵+9%Lb.XQĊFb#XN$,'6pڈ +"PA v!4_MFΉv HQ@#XX/+kn2+TtO1d&"dSdS/wEHEoE"LuBn4WlBa4Q05xM 2.tidž}+a_k{W&oxt +} +ʽ+呻w w ]+%\Zis\'ʎ?rJG/ ʡEz.Sz*Oz )n)-) [ҢSZ딥,Y ebrb:<>,L5rS@*O82xubV~EΰZ%hJ23/fάĭsʓ"&+!TɕlR .X80P._)t B]!_Š`dQ^9FurO0/ORrX1j !wVAE喆 *UaiCj/bJUŞ,RkQ(J?|rگZcQMT=10wܹ6Jr5j BժNKU>K:SaKU!K?WO7=gs*ϣrY*5NT>Gur*UTX2NEE|GEڣbRauY楤MZcN+.Q*RٰPQVT.KRQ PC%Uؿ} 6mYdPZ?_Z?SM+Fcmrۤ*[i.W_X&T/aɆր5bqkP5|!*tlΖ[>вZ|lMOv޷ ]9]sjEbU[}jd%Z6O.m%V%lӿ^0 d%j/ZR5_&t÷g찭m>0ol_P[]:k ےmӴq\9eu:mVLn?6I5y|>m61.YlɳmΒۖnv|>\:}DTe7ug}wϧ)lb[[)[b]ؒ43(D岊PP\JMWiw>KVYKr;>KMQ$V_NvGNvv*W\uAU]^q'U<1OOiA颶2fܙ㵳p{vTdmkǶնՅi4,֘mf.L^Q^J dTNmr1q +۞rC]Y}3U_4;kd*GKR>3SYeUa 5Պ:T,*99. 071Z1ZaZNOmX;1ͳRrtOetϙ~_N=Mm6].hmQYUC~|U8j&/ɅK&26/UjYlLaVeI;"P%NJ4λU8MݎrR^9&'{ 1kd5!tU%@^ZY#\q5҉Ue r53MZ!Uxz@k3n#bmRB azXN0=ljmր^$ !c%s55C `$Xg&ij+5Ic +# Vo.}UH&ܪr*aR²&UN&1/V+S}}Q@xP\zYI'mQ4 +o#e/t!U547hٲ|6ߣ+#U3~#.v+d"-'-Y[?;7Eo5tRtǝKkHl2-)L +p@^Ǿ Tʞ"x82+fsp9f[*c <"A` ӎ2$#PG9y +?_E''r Ar2"~*?oWv~Wx<_򍼐˫~癘,2L5M]LLHEQp.I&T">lORS"8y##wEקt&'[Mn0k.ܶemmO¹7~ʔۋ$80NǶ/g Թڿ{'S9__oן;;q'茼.^K=f{cKll[m|؄(iSevdew fi6lP2g]="MxEZ%=&=#H<ėH(NJbC}f fb&Ev3h&06sfbf~9恤.M5͚5iLYGFtB<|6a֩5jtG}ܓNVvS7L|tsu4Zo==~9oȨP1ZR-.Vj5 1&Ƨ&. +uu^̥iVE2Ke9f"" v~CP2n1Qb(@@6+O;5qI x_0Rִ;kvGzv"sG^;Med~ggo1`ܚy Z68*`k;\"/[-nbEȭIIBdi/6>~r MYl΋8sz55ͬʴ=7NÇ~C"ۢ{nfK;FwDURI$LGwFP8/:V*:3z}g6pW:|b'rWYV-*HH! xfI6fI7%$NJMHjL'I$DHRNbBeG"쀞uYuY\Jk:C+_Qlx55LoBՀDVukwFV?=z랻Ii&R(_F[IC˗?w\Ν[t ?=g/LF?U".n[d EY  !d0DV5 pY&QSb+FW,ƹ + > >)z뙺@Onzl,|{7;O|ySS_-%ܿxɪOvfyr]߇%*qeWQeǜ:Yq +Nɫ v)dp{2 wO!8qZ$_Q&bde&A2ɦ +SIh485BYkj|5,&(L `RSf)⾓='G%'{oWn:rI +Ɉ8?zWYŢwKN$zޮI( 26s:8ޱS<&UY6 c=)mt7:m6+Vqiiܢ{Ҹi$mźsVV̓rnTkYS*o~QO^idysyqI9 [Ԛo@0i +N Yt~,\RS.]׽-ѓt*1CN o{+*ζǵ$@0m*OE“gFW#t>Mς#@ +CKcpY!`dIhhXRhH,)Ó)2Qxvr8r#{\V'9ItO9F⺗vFiCY&$h]Vj&XW[ۭǬԪVNVjew,^-?לNN\5t:"v_C`.轛qGГܪ?UOn{_꥞Nfizz8I愌vvcH ¤pә"%=CF 7%ܓ5cOhв0 $Wb.7O12 \o^dK̕yfA{T&s! +Pk&;Ż+owwWdCޭ=/=^eO_&{s! +PU%dw;^*ܵVnֹSf^3/خyW2',2C&2_&/N%sH jQ%oXmc|fklYKaRW0 r"q3ܗ|Ã|tvmnAշD#)/RFG\¾H"Y;vޒ̍AF{*8up_o7< !ndp#'=OF!^2 +N-_3:C +'dr, (Stƌ@fKL=sS&:=[IL>''qI$.))٠ j\n\m'WD6\cVѬ` PDK㒓X7yE2Xgk9!;dWF=xn;g#+E +;YT댤ЭFopϙ .^qS肳4v%(A Jй!OP*q+A WߜoC,A2j~ JP0.A:2^x}J>go`Ha&@ $@ p`n9kH 0,0>gY?2@ $@ $Ck;H#~x0@ u $𯇡^CGi&pVDH oJs3]cؿ}%@ $G"%6k>k +endstream +endobj +3014 0 obj +<< +/Filter /FlateDecode +/Length 6587 +/Length1 15048 +>> +stream +x tTdL$ Iɐ H&#3! Y)H APjje@:bDKZۺk+ָH2'a~|No{߽}&0tBڜY<|)BM+;tqjK,*ftrkDzLe >~Jvmkilɝ @B0єJ@ym+.>FN&ߊUM?j \xqG=p W$@W:qwiH|I:O 60D d*̃!鋠QSG4@'ddPsj5?4-}&zgۮqܗwɼn3#XVu +HyR0`Tsk6VA fh4d/h\gԖ'qGmjya4AZK`)r:` FbF1=}Ӵ&hcpy욂6Į5 sbZk8aLZcV `4B'xLnk)D  r!8c.,&XԻ ~MaMq/S@R5С+V B) Xˠ 'Ts@3LPtӷ/EA:NᗦLS kZ֡]=o_/~fX8O+6DhREBn D3u;ԠOu/{5=:>J4SPCǴ%h/Dkº5sߨbuǯˠͰbX +=p\?~ +w5plkV n-p3p`Dax {viSc° v< +<W$8 s0W +'Ϻ[}ޑsp_Se=?ŸUx ^7Mxޅ?{>|'Ssr VґXY6 Q$"Yd2L!EHH6- z`+lG  7~wp_~aH/>{Զc߫' x`x?z~m}* _%5jރ3zGo?To[T<>R/opNB>!8w| 'a Ө)HL{ץNm#:z18bU"n!O$RDfY$ɤrRAfYd!jF:HYKz麼R =>8dt=49я!٠Y7sg_>I= xC49dwu jT͝3{̪reEyYdӦM<0g7{\U÷4Qz +WQ|b@jRm]+ͮ% +)#bW +-_P,jx$Xu÷^4, +1 >Gѧl:%~7ȒFIroc$ڽ 2ͽRm`KFzxMf/(fQ(Ȗ>R[k,)塲`ydKM`Sc)< /i~ Ljz^@zWF58G)B1>G)8ovMJ͆`[o(W$*ԣPQ4*M#T2"_zoH"ߐzCRobEpjxb$]pv ݊Ӡ=Ŕg?!Et75z@]5xf6H3S1yS<|.B]6Jr+A%XT]*Xѧct`o.LG1{6sLY +0ƥxuI8Ei)$jFjvaLKM@Ѧ?fW&fi<Y1MP L~mףcjhs,bG1ѕ ѣX<3y]gbV>Ƌ|b=dP٨t/쑦 g6 +x<3gA$ztÛ-w>1s#EYl㹱V5h _F눋Vo_zh[ak9Vhն׶u_~1j[{|{>dC}oOd 4`&B~pG! ~nc8@. +r0ϩc\z[nnvUCSC%"@|QγHΫ p %CmAO*8JRaA~رh锇' 5E i}޸Kg4M^iqiĻ:חZǗG&7Z6MtޜW6xgbzݞpdP΃>B}}J£3 զZO7%c #CyIrjCǦg8 +IxtcGbbAtM_ݿzգ3OaYUK$.xIyv3K)ݿ͑UXlM@aNU]$B4a+B"EĤMY-HBbMBt^!ya~%%ECy.6JLr84Z?i#=]k^俪uܴceweM]\~M>orUρW\j6O\J-X7GjǦQ-hm B&,ö튋KLm +$av|g)֡8S|iO3ꀣ(7/7c J8i0 O `sY.h-鮨зr]lj8y,tVrTZy^Ҙx6nx:wS.oa֥\`v5Bx 񂐚o:!s\B~ As%XwG|QNQ@#:}>7[CNp;$=Kxm CTc{omd8=وp' MgVرSάcg9>z&Lgsg%'gC'8p`d 6HEAcbF|j/R׻:f%;{|^3As/}gl.<ԩMU1VȫiCIfeߌ|j\'іY0y]2;*֜> 7fPGm?τNuhmbc`50C !֧tb}IIf^ ΁ӣ$oel:M2ܹlRgWM%sO&CCWUOt[ܘ1,l2>Fj^Нcۑl#K3Mf)-NC491ӜQ Tc?4x~DݔK2{c2_щ|3ּPvŴx>"d䘅 {th߁G[yݯQs(̧JLkqV;Ǚ5&YNK8V9GC~ctKWgX6wykehֵ,4}/!+Gd5_{ >|3&w|UaZZaqĴ2Y +2(dpƸ̪B~'pU QpZ\G;A:ci,BdVL^uY; w; ۡ^z++@@@SS7hD/fz9r <A>3f G7A埂n\ Bthpsi]~/\e L7t(a;x^ n + UJO/f ^mzPN>A~S_nD=?ӋSuOשYvvuu5 i)[m[mk65y5X('D/VOG^[,בomsD%jn%!|oM]_'2oi/B/ y/]Ag. &ޕ7YEp[aQb: TY:T2YV HRd:r>2 #Ed22 )D&"H>"9ȄpjP/d!Ld#DA )g ~}Ƚ=]ϐ;"; ;ȏ!w #!" 7#7!?DnDn@'Wن\\\lEz+-f +,\"~F6!C6"K%ȺpҜS"d-҅t"kH +Y@#ˑ6dҊ Hi '֟Z!d Ҁ,B @.@"uȂpBөWGjh#QSoN8>Bf"U DF* +<;ʐRħ~#%t|d2)F)ddRLD +|$Er FH&2@r"!c7"" ICRąA'$" hd8;" 6Ċ!?F 1"D-A(BE!AfN +2R Afdv\}!sAf}&SAf2XG>d6 Afd dAfd w--Afo +2{C^d ? 2 ?2{E,%AfdvDً~+Af9=k6?{gO)gٓ6?{g!=n6?{gmQ[);`Gl~gl~,b_lnYg}X؃6[}vcm`w[]3k~jm`; '[؏ GvG\;=nkgĵMqqƸvvC\;>]ήkg,9%j%*2DHeR5JJ +D})\P!lKٞ`nE}.}D2[eߘoLx7}cdM'/IΐSq;5!gY\&&QI񉲒؟H!5G2O#\Ϯvjw{W&PDX%D lOT, 6f96]o[blmQ#Dm@ȵ kv?[1V/RSϾzEEE>BQ^8תpWCjl%6ؑZtkOkԲ`gŝY;f3?άήYkmgWVWgd7?]YY8z52|.tC Lg;7+ 2Y +endstream +endobj +3015 0 obj +<< +/BBox [22 30 2061 1804] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2919 3034 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2919 SCN/P2919 scn +22 30 2039 1774 re +f* + +endstream +endobj +3016 0 obj +<< +/BBox [22 30 2061 1804] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2924 3035 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2924 SCN/P2924 scn +22 30 2039 1774 re +f* + +endstream +endobj +3017 0 obj +<< +/BBox [22 30 2061 1804] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2929 3036 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2929 SCN/P2929 scn +22 30 2039 1774 re +f* + +endstream +endobj +3018 0 obj +<< +/BBox [22 30 2061 1804] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2934 3037 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2934 SCN/P2934 scn +22 30 2039 1774 re +f* + +endstream +endobj +3019 0 obj +<< +/BBox [22 30 2061 1804] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2939 3038 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2939 SCN/P2939 scn +22 30 2039 1774 re +f* + +endstream +endobj +3020 0 obj +<< +/BBox [22 30 2061 1804] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2944 3039 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2944 SCN/P2944 scn +22 30 2039 1774 re +f* + +endstream +endobj +3021 0 obj +<< +/BBox [28 32 2046 2050] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2952 3040 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2952 SCN/P2952 scn +28 32 2018 2018 re +f* + +endstream +endobj +3022 0 obj +<< +/BBox [28 32 2046 2050] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2957 3041 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2957 SCN/P2957 scn +28 32 2018 2018 re +f* + +endstream +endobj +3023 0 obj +<< +/BBox [28 32 2046 2050] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2962 3042 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2962 SCN/P2962 scn +28 32 2018 2018 re +f* + +endstream +endobj +3024 0 obj +<< +/BBox [28 32 2046 2050] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2967 3043 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2967 SCN/P2967 scn +28 32 2018 2018 re +f* + +endstream +endobj +3025 0 obj +<< +/BBox [28 32 2046 2050] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2972 3044 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2972 SCN/P2972 scn +28 32 2018 2018 re +f* + +endstream +endobj +3026 0 obj +<< +/BBox [28 32 2046 2050] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2977 3045 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2977 SCN/P2977 scn +28 32 2018 2018 re +f* + +endstream +endobj +3027 0 obj +<< +/BBox [40 32 2055 2046] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2985 3046 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2985 SCN/P2985 scn +40 32 2015 2014 re +f* + +endstream +endobj +3028 0 obj +<< +/BBox [40 32 2055 2046] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2990 3047 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2990 SCN/P2990 scn +40 32 2015 2014 re +f* + +endstream +endobj +3029 0 obj +<< +/BBox [40 32 2055 2046] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P2995 3048 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P2995 SCN/P2995 scn +40 32 2015 2014 re +f* + +endstream +endobj +3030 0 obj +<< +/BBox [40 32 2055 2046] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P3000 3049 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P3000 SCN/P3000 scn +40 32 2015 2014 re +f* + +endstream +endobj +3031 0 obj +<< +/BBox [40 32 2055 2046] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P3005 3050 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P3005 SCN/P3005 scn +40 32 2015 2014 re +f* + +endstream +endobj +3032 0 obj +<< +/BBox [40 32 2055 2046] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P3010 3051 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P3010 SCN/P3010 scn +40 32 2015 2014 re +f* + +endstream +endobj +3033 0 obj +<< +/BBox [40 32 2055 2046] +/Group << +/CS /DeviceRGB +/I true +/S /Transparency +/Type /Group +>> +/Length 65 +/Resources << +/Pattern << +/P3015 3052 0 R +>> +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +>> +/Subtype /Form +/Type /XObject +>> +stream +/Pattern CS/Pattern cs/P3015 SCN/P3015 scn +40 32 2015 2014 re +f* + +endstream +endobj +3034 0 obj +<< +/Matrix [2048 0 0 2048 -369 1517] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.68652344 0.107185483 0.68652344 0.140136719] +/Extend [true true] +/Function << +/C0 [0 0 0] +/C1 [1 1 1] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +3035 0 obj +<< +/Matrix [1322.09375 -1221.5 1389.8125 1504.25 -369 1517] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.055175781 0.22021484 0 0.055175781 0.22021484 0.072498322] +/Extend [true true] +/Function << +/C0 [1 1 1] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +3036 0 obj +<< +/Matrix [2048 0 0 2048 -369 1517] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.51715827 -0.41607392 0.48547289 -0.43429303] +/Extend [true true] +/Function << +/Bounds [0.99999994] +/Domain [0 1] +/Encode [0 1 0 1] +/Functions [<< +/C0 [0 0 0] +/C1 [1 1 1] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [1 1 1] +/C1 [1 1 1] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +3037 0 obj +<< +/Matrix [606.3125 1694.8125 -1928.3125 689.84375 -369 1517] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [-0.54394531 -0.87646484 0.0092207491 -0.54394531 -0.87646484 0.052244902] +/Extend [true true] +/Function << +/C0 [1 1 1] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +3038 0 obj +<< +/Matrix [2048 0 0 2048 -369 1517] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.87006438 -0.39392689 0.89661062 -0.40923685] +/Extend [true true] +/Function << +/Bounds [0.99999994] +/Domain [0 1] +/Encode [0 1 0 1] +/Functions [<< +/C0 [0 0 0] +/C1 [1 1 1] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [1 1 1] +/C1 [1 1 1] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +3039 0 obj +<< +/Matrix [-710 -1654.0625 -1881.9375 807.8125 -369 1517] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [-0.68359375 -1.06542969 0.022556543 -0.68359375 -1.06542969 0.072265625] +/Extend [true true] +/Function << +/C0 [1 1 1] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +3040 0 obj +<< +/Matrix [-1239.875 1239.875 1448.15625 1448.15625 -369 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [-1.58496094 0.23632813 0 -1.58496094 0.23632813 0.145507813] +/Extend [true true] +/Function << +/C0 [0.6 0.6 0.6] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +3041 0 obj +<< +/Matrix [1331.3125 -1141.125 1332.8125 1554.96875 -369 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.123535156 0.22900391 0 0.123535156 0.22900391 0.18945313] +/Extend [true true] +/Function << +/C0 [0.7 0.7 0.7] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +3042 0 obj +<< +/Matrix [2048 0 0 2048 -369 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [1.17919922 -0.35253906 1.02099609 -0.35253906] +/Extend [true true] +/Function << +/Bounds [0.47918701] +/Domain [0 1] +/Encode [0 1 0 1] +/Functions [<< +/C0 [0 0 0] +/C1 [0.3 0.3 0.3] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.3 0.3 0.3] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +3043 0 obj +<< +/Matrix [2048 0 0 2048 -369 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.68652344 -0.84521484 0.68652344 -0.70458984] +/Extend [true true] +/Function << +/Bounds [0.47918701] +/Domain [0 1] +/Encode [0 1 0 1] +/Functions [<< +/C0 [0 0 0] +/C1 [0.4 0.4 0.4] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.4 0.4 0.4] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +3044 0 obj +<< +/Matrix [2048 0 0 2048 -369 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.68652344 -0.84521484 0.68652344 0.140136719] +/Extend [true true] +/Function << +/Bounds [0.058288574 0.87219238 0.93945313] +/Domain [0 1] +/Encode [0 1 0 1 0 1 0 1] +/Functions [<< +/C0 [0.35 0.35 0.35] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0 0 0] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0 0 0] +/C1 [0.4386 0.4386 0.4386] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.4386 0.4386 0.4386] +/C1 [1 1 1] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +3045 0 obj +<< +/Matrix [2048 0 0 2048 -369 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [1.17578125 -0.36132813 0.20361328 -0.36132813] +/Extend [true true] +/Function << +/Bounds [0.058288574 0.87219238 0.93945313] +/Domain [0 1] +/Encode [0 1 0 1 0 1 0 1] +/Functions [<< +/C0 [0.35 0.35 0.35] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0 0 0] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0 0 0] +/C1 [0.4386 0.4386 0.4386] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.4386 0.4386 0.4386] +/C1 [1 1 1] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +3046 0 obj +<< +/Matrix [2048 0 0 2048 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.35839844 -0.69238281 0.65429527 -0.39453286] +/Extend [true true] +/Function << +/C0 [1 1 1] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +3047 0 obj +<< +/Matrix [2048 0 0 2048 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.78857422 -0.6015625 0.94067383 -0.44995198] +/Extend [true true] +/Function << +/Bounds [0.17614746 0.50604248 0.84680176] +/Domain [0 1] +/Encode [0 1 0 1 0 1 0 1] +/Functions [<< +/C0 [0 0 0] +/C1 [0.5015 0.5015 0.5015] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.5015 0.5015 0.5015] +/C1 [1 1 1] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [1 1 1] +/C1 [0.4578 0.4578 0.4578] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.4578 0.4578 0.4578] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +3048 0 obj +<< +/Matrix [2048 0 0 2048 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.56689453 -0.62744141 0.41674805 -0.47729492] +/Extend [true true] +/Function << +/Bounds [0.109863281 0.37359619 0.84680176] +/Domain [0 1] +/Encode [0 1 0 1 0 1 0 1] +/Functions [<< +/C0 [0 0 0] +/C1 [0.5015 0.5015 0.5015] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.5015 0.5015 0.5015] +/C1 [1 1 1] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [1 1 1] +/C1 [0.4578 0.4578 0.4578] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> << +/C0 [0.4578 0.4578 0.4578] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>>] +/FunctionType 3 +>> +/ShadingType 2 +>> +/Type /Pattern +>> +endobj +3049 0 obj +<< +/Matrix [1434.28125 1461.875 -1461.875 1434.28125 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.88232422 -0.75097656 0 0.88232422 -0.75097656 0.163085938] +/Extend [true true] +/Function << +/C0 [0.7 0.7 0.7] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +3050 0 obj +<< +/Matrix [-1363.40625 1528.21875 1528.21875 1363.40625 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [-0.077148438 0.24414063 0 -0.077148438 0.24414063 0.150390625] +/Extend [true true] +/Function << +/C0 [0.8 0.8 0.8] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +3051 0 obj +<< +/Matrix [-1579.75 -1303.3125 -1303.3125 1579.75 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [0.33837891 -0.77392578 0 0.33837891 -0.77392578 0.114257813] +/Extend [true true] +/Function << +/C0 [1 1 1] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +3052 0 obj +<< +/Matrix [1448.15625 -1448.15625 1448.15625 1448.15625 -369.07202 1763] +/PatternType 2 +/Shading << +/ColorSpace /DeviceRGB +/Coords [1.390625 0.24316406 0 1.390625 0.24316406 0.102539063] +/Extend [true true] +/Function << +/C0 [1 1 1] +/C1 [0 0 0] +/Domain [0 1] +/FunctionType 2 +/N 1 +>> +/ShadingType 3 +>> +/Type /Pattern +>> +endobj +xref +0 3053 +0000000000 65535 f +0000000015 00000 n +0000000308 00000 n +0000000526 00000 n +0000003787 00000 n +0000003851 00000 n +0000003958 00000 n +0000004079 00000 n +0000004179 00000 n +0000004215 00000 n +0000005684 00000 n +0000005865 00000 n +0000006159 00000 n +0000006441 00000 n +0000006709 00000 n +0000006978 00000 n +0000007234 00000 n +0000007503 00000 n +0000007798 00000 n +0000008067 00000 n +0000008348 00000 n +0000008617 00000 n +0000008874 00000 n +0000009144 00000 n +0000009402 00000 n +0000010876 00000 n +0000010958 00000 n +0000011048 00000 n +0000011127 00000 n +0000011209 00000 n +0000011333 00000 n +0000011412 00000 n +0000011494 00000 n +0000011561 00000 n +0000011805 00000 n +0000011872 00000 n +0000012006 00000 n +0000012073 00000 n +0000012275 00000 n +0000012342 00000 n +0000012418 00000 n +0000012507 00000 n +0000012583 00000 n +0000012672 00000 n +0000012748 00000 n +0000012837 00000 n +0000012913 00000 n +0000013003 00000 n +0000013083 00000 n +0000013166 00000 n +0000013243 00000 n +0000013327 00000 n +0000013394 00000 n +0000013580 00000 n +0000013647 00000 n +0000013755 00000 n +0000013822 00000 n +0000013888 00000 n +0000014062 00000 n +0000014153 00000 n +0000014220 00000 n +0000014358 00000 n +0000014437 00000 n +0000014519 00000 n +0000014586 00000 n +0000014652 00000 n +0000014718 00000 n +0000014852 00000 n +0000014919 00000 n +0000015003 00000 n +0000015113 00000 n +0000015253 00000 n +0000015425 00000 n +0000015492 00000 n +0000015710 00000 n +0000015777 00000 n +0000015895 00000 n +0000015975 00000 n +0000016058 00000 n +0000016142 00000 n +0000016209 00000 n +0000016335 00000 n +0000016402 00000 n +0000016492 00000 n +0000016559 00000 n +0000016651 00000 n +0000016730 00000 n +0000016812 00000 n +0000016879 00000 n +0000016979 00000 n +0000017068 00000 n +0000017135 00000 n +0000017201 00000 n +0000017280 00000 n +0000017362 00000 n +0000017429 00000 n +0000017496 00000 n +0000017636 00000 n +0000017712 00000 n +0000017779 00000 n +0000017903 00000 n +0000017993 00000 n +0000018070 00000 n +0000018138 00000 n +0000018263 00000 n +0000018364 00000 n +0000018432 00000 n +0000018589 00000 n +0000018666 00000 n +0000018756 00000 n +0000018847 00000 n +0000018925 00000 n +0000018992 00000 n +0000019060 00000 n +0000019128 00000 n +0000019245 00000 n +0000019313 00000 n +0000019438 00000 n +0000019506 00000 n +0000019615 00000 n +0000019683 00000 n +0000019792 00000 n +0000019869 00000 n +0000019947 00000 n +0000020014 00000 n +0000020082 00000 n +0000020168 00000 n +0000020245 00000 n +0000020313 00000 n +0000020486 00000 n +0000020554 00000 n +0000020663 00000 n +0000020743 00000 n +0000020826 00000 n +0000020894 00000 n +0000021020 00000 n +0000021088 00000 n +0000021156 00000 n +0000021281 00000 n +0000021371 00000 n +0000021439 00000 n +0000021580 00000 n +0000021670 00000 n +0000021738 00000 n +0000021863 00000 n +0000021953 00000 n +0000022021 00000 n +0000022162 00000 n +0000022253 00000 n +0000022321 00000 n +0000022398 00000 n +0000022507 00000 n +0000022597 00000 n +0000022664 00000 n +0000022731 00000 n +0000022849 00000 n +0000022926 00000 n +0000022993 00000 n +0000023102 00000 n +0000023192 00000 n +0000023259 00000 n +0000023326 00000 n +0000023411 00000 n +0000023537 00000 n +0000023638 00000 n +0000023705 00000 n +0000023782 00000 n +0000023872 00000 n +0000023939 00000 n +0000024006 00000 n +0000024074 00000 n +0000024231 00000 n +0000024299 00000 n +0000024457 00000 n +0000024538 00000 n +0000024622 00000 n +0000024690 00000 n +0000024758 00000 n +0000024843 00000 n +0000024911 00000 n +0000025012 00000 n +0000025080 00000 n +0000025165 00000 n +0000025233 00000 n +0000025374 00000 n +0000025442 00000 n +0000025535 00000 n +0000025603 00000 n +0000025721 00000 n +0000025801 00000 n +0000025884 00000 n +0000025952 00000 n +0000026071 00000 n +0000026139 00000 n +0000026282 00000 n +0000026350 00000 n +0000026521 00000 n +0000026589 00000 n +0000026708 00000 n +0000026789 00000 n +0000026873 00000 n +0000026941 00000 n +0000027032 00000 n +0000027100 00000 n +0000027191 00000 n +0000027259 00000 n +0000027349 00000 n +0000027417 00000 n +0000027507 00000 n +0000028726 00000 n +0000031459 00000 n +0000033140 00000 n +0000034697 00000 n +0000036705 00000 n +0000037673 00000 n +0000038813 00000 n +0000040015 00000 n +0000041266 00000 n +0000042652 00000 n +0000043941 00000 n +0000044355 00000 n +0000046224 00000 n +0000046631 00000 n +0000047041 00000 n +0000054575 00000 n +0000054616 00000 n +0000054772 00000 n +0000054924 00000 n +0000056452 00000 n +0000056600 00000 n +0000066784 00000 n +0000066932 00000 n +0000067088 00000 n +0000082032 00000 n +0000094679 00000 n +0000104139 00000 n +0000111638 00000 n +0000121081 00000 n +0000122020 00000 n +0000122173 00000 n +0000128961 00000 n +0000136993 00000 n +0000144750 00000 n +0000153171 00000 n +0000156688 00000 n +0000160398 00000 n +0000160592 00000 n +0000160786 00000 n +0000160980 00000 n +0000161174 00000 n +0000161369 00000 n +0000161600 00000 n +0000161831 00000 n +0000162062 00000 n +0000162293 00000 n +0000162525 00000 n +0000162757 00000 n +0000162989 00000 n +0000163221 00000 n +0000163416 00000 n +0000163611 00000 n +0000163807 00000 n +0000164039 00000 n +0000164271 00000 n +0000164503 00000 n +0000164698 00000 n +0000164893 00000 n +0000165088 00000 n +0000165284 00000 n +0000165480 00000 n +0000165676 00000 n +0000165872 00000 n +0000166104 00000 n +0000166336 00000 n +0000166568 00000 n +0000166800 00000 n +0000166995 00000 n +0000167190 00000 n +0000167385 00000 n +0000167581 00000 n +0000167777 00000 n +0000167973 00000 n +0000168168 00000 n +0000168363 00000 n +0000168558 00000 n +0000168753 00000 n +0000168948 00000 n +0000169143 00000 n +0000169338 00000 n +0000169533 00000 n +0000169728 00000 n +0000169923 00000 n +0000170118 00000 n +0000170313 00000 n +0000170508 00000 n +0000170703 00000 n +0000170898 00000 n +0000171094 00000 n +0000171290 00000 n +0000171486 00000 n +0000171682 00000 n +0000171878 00000 n +0000172110 00000 n +0000172342 00000 n +0000172574 00000 n +0000172769 00000 n +0000172964 00000 n +0000173046 00000 n +0000173176 00000 n +0000173258 00000 n +0000173338 00000 n +0000173418 00000 n +0000173498 00000 n +0000173578 00000 n +0000173658 00000 n +0000173738 00000 n +0000173818 00000 n +0000173898 00000 n +0000173980 00000 n +0000174062 00000 n +0000174144 00000 n +0000174217 00000 n +0000174299 00000 n +0000174372 00000 n +0000174454 00000 n +0000174527 00000 n +0000174609 00000 n +0000174682 00000 n +0000174764 00000 n +0000174837 00000 n +0000174919 00000 n +0000174992 00000 n +0000175074 00000 n +0000175147 00000 n +0000175229 00000 n +0000175302 00000 n +0000175384 00000 n +0000175457 00000 n +0000175539 00000 n +0000175612 00000 n +0000175694 00000 n +0000175767 00000 n +0000175849 00000 n +0000175931 00000 n +0000176034 00000 n +0000176142 00000 n +0000176264 00000 n +0000176372 00000 n +0000176494 00000 n +0000176602 00000 n +0000176724 00000 n +0000176807 00000 n +0000176902 00000 n +0000177001 00000 n +0000177114 00000 n +0000177213 00000 n +0000177326 00000 n +0000177425 00000 n +0000177538 00000 n +0000177637 00000 n +0000177749 00000 n +0000177848 00000 n +0000177960 00000 n +0000178042 00000 n +0000178129 00000 n +0000178211 00000 n +0000179409 00000 n +0000179498 00000 n +0000179581 00000 n +0000179997 00000 n +0000180086 00000 n +0000180169 00000 n +0000180558 00000 n +0000180647 00000 n +0000180730 00000 n +0000181029 00000 n +0000181112 00000 n +0000181195 00000 n +0000181269 00000 n +0000181352 00000 n +0000181426 00000 n +0000181509 00000 n +0000181592 00000 n +0000181687 00000 n +0000181786 00000 n +0000181899 00000 n +0000181998 00000 n +0000182110 00000 n +0000182209 00000 n +0000182321 00000 n +0000182420 00000 n +0000182532 00000 n +0000182614 00000 n +0000182704 00000 n +0000182884 00000 n +0000183001 00000 n +0000183091 00000 n +0000183181 00000 n +0000183289 00000 n +0000183372 00000 n +0000183455 00000 n +0000183542 00000 n +0000183632 00000 n +0000183736 00000 n +0000183826 00000 n +0000183930 00000 n +0000184020 00000 n +0000184124 00000 n +0000184214 00000 n +0000184318 00000 n +0000184408 00000 n +0000184512 00000 n +0000184602 00000 n +0000184736 00000 n +0000184819 00000 n +0000184906 00000 n +0000184996 00000 n +0000185099 00000 n +0000185181 00000 n +0000185263 00000 n +0000185337 00000 n +0000185419 00000 n +0000185506 00000 n +0000185596 00000 n +0000185700 00000 n +0000185790 00000 n +0000185894 00000 n +0000185984 00000 n +0000186088 00000 n +0000186170 00000 n +0000186252 00000 n +0000186326 00000 n +0000186408 00000 n +0000186503 00000 n +0000186602 00000 n +0000186715 00000 n +0000186814 00000 n +0000186888 00000 n +0000186970 00000 n +0000187044 00000 n +0000187127 00000 n +0000187216 00000 n +0000187299 00000 n +0000187388 00000 n +0000187471 00000 n +0000187560 00000 n +0000187643 00000 n +0000187717 00000 n +0000187800 00000 n +0000187889 00000 n +0000187972 00000 n +0000188061 00000 n +0000188144 00000 n +0000188233 00000 n +0000188316 00000 n +0000188405 00000 n +0000188488 00000 n +0000188577 00000 n +0000188660 00000 n +0000188753 00000 n +0000188836 00000 n +0000188919 00000 n +0000189014 00000 n +0000189113 00000 n +0000189226 00000 n +0000189325 00000 n +0000189438 00000 n +0000189537 00000 n +0000189650 00000 n +0000189749 00000 n +0000189862 00000 n +0000189961 00000 n +0000190073 00000 n +0000190172 00000 n +0000190284 00000 n +0000190366 00000 n +0000190453 00000 n +0000190543 00000 n +0000190647 00000 n +0000190737 00000 n +0000190841 00000 n +0000190923 00000 n +0000191005 00000 n +0000191093 00000 n +0000191175 00000 n +0000191257 00000 n +0000191353 00000 n +0000191443 00000 n +0000191547 00000 n +0000191637 00000 n +0000191741 00000 n +0000191831 00000 n +0000191913 00000 n +0000192968 00000 n +0000193051 00000 n +0000193141 00000 n +0000193258 00000 n +0000193339 00000 n +0000193429 00000 n +0000193510 00000 n +0000193591 00000 n +0000193672 00000 n +0000193759 00000 n +0000193841 00000 n +0000193929 00000 n +0000194011 00000 n +0000194083 00000 n +0000194165 00000 n +0000194247 00000 n +0000194329 00000 n +0000194411 00000 n +0000194493 00000 n +0000194567 00000 n +0000194649 00000 n +0000194723 00000 n +0000194805 00000 n +0000194893 00000 n +0000194975 00000 n +0000195063 00000 n +0000195145 00000 n +0000195233 00000 n +0000195315 00000 n +0000195389 00000 n +0000195471 00000 n +0000195553 00000 n +0000195627 00000 n +0000195709 00000 n +0000195783 00000 n +0000195865 00000 n +0000195953 00000 n +0000196035 00000 n +0000196109 00000 n +0000196191 00000 n +0000196662 00000 n +0000196737 00000 n +0000196820 00000 n +0000196903 00000 n +0000196978 00000 n +0000197061 00000 n +0000197136 00000 n +0000197219 00000 n +0000197308 00000 n +0000197392 00000 n +0000197482 00000 n +0000197566 00000 n +0000197641 00000 n +0000197725 00000 n +0000197815 00000 n +0000197899 00000 n +0000197989 00000 n +0000198071 00000 n +0000198146 00000 n +0000198228 00000 n +0000198303 00000 n +0000198385 00000 n +0000198473 00000 n +0000198556 00000 n +0000198645 00000 n +0000198728 00000 n +0000198817 00000 n +0000198900 00000 n +0000198989 00000 n +0000199072 00000 n +0000199147 00000 n +0000199230 00000 n +0000199548 00000 n +0000199618 00000 n +0000199701 00000 n +0000199776 00000 n +0000199859 00000 n +0000199942 00000 n +0000200025 00000 n +0000200100 00000 n +0000200183 00000 n +0000200258 00000 n +0000200341 00000 n +0000200430 00000 n +0000200513 00000 n +0000200602 00000 n +0000200685 00000 n +0000200760 00000 n +0000200843 00000 n +0000200918 00000 n +0000201001 00000 n +0000201090 00000 n +0000201173 00000 n +0000201262 00000 n +0000201345 00000 n +0000201428 00000 n +0000201503 00000 n +0000201586 00000 n +0000201661 00000 n +0000201744 00000 n +0000201833 00000 n +0000201916 00000 n +0000201999 00000 n +0000202074 00000 n +0000202157 00000 n +0000202232 00000 n +0000202315 00000 n +0000202404 00000 n +0000202487 00000 n +0000202562 00000 n +0000202645 00000 n +0000202728 00000 n +0000202803 00000 n +0000202886 00000 n +0000202969 00000 n +0000203052 00000 n +0000203141 00000 n +0000203225 00000 n +0000203300 00000 n +0000203384 00000 n +0000203468 00000 n +0000203543 00000 n +0000203627 00000 n +0000203702 00000 n +0000203786 00000 n +0000203876 00000 n +0000203960 00000 n +0000204050 00000 n +0000204134 00000 n +0000204224 00000 n +0000204308 00000 n +0000204398 00000 n +0000204482 00000 n +0000204572 00000 n +0000204656 00000 n +0000204740 00000 n +0000204815 00000 n +0000204899 00000 n +0000204974 00000 n +0000205058 00000 n +0000205148 00000 n +0000205232 00000 n +0000205315 00000 n +0000205398 00000 n +0000205486 00000 n +0000205577 00000 n +0000205681 00000 n +0000205772 00000 n +0000205876 00000 n +0000205967 00000 n +0000206050 00000 n +0000206133 00000 n +0000206208 00000 n +0000206291 00000 n +0000206366 00000 n +0000206449 00000 n +0000206524 00000 n +0000206607 00000 n +0000206696 00000 n +0000206779 00000 n +0000206890 00000 n +0000206973 00000 n +0000207048 00000 n +0000207131 00000 n +0000207206 00000 n +0000207289 00000 n +0000207378 00000 n +0000207461 00000 n +0000207536 00000 n +0000207619 00000 n +0000207708 00000 n +0000207791 00000 n +0000207920 00000 n +0000208003 00000 n +0000208078 00000 n +0000208161 00000 n +0000208236 00000 n +0000208319 00000 n +0000208408 00000 n +0000208491 00000 n +0000208566 00000 n +0000208649 00000 n +0000209084 00000 n +0000209168 00000 n +0000209243 00000 n +0000209327 00000 n +0000209402 00000 n +0000209486 00000 n +0000209576 00000 n +0000209660 00000 n +0000209735 00000 n +0000209819 00000 n +0000209894 00000 n +0000209978 00000 n +0000210098 00000 n +0000210181 00000 n +0000210256 00000 n +0000210339 00000 n +0000210414 00000 n +0000210497 00000 n +0000210586 00000 n +0000210669 00000 n +0000210758 00000 n +0000210841 00000 n +0000210914 00000 n +0000210989 00000 n +0000211064 00000 n +0000211160 00000 n +0000211260 00000 n +0000211373 00000 n +0000211473 00000 n +0000211586 00000 n +0000211661 00000 n +0000211744 00000 n +0000211819 00000 n +0000211908 00000 n +0000211991 00000 n +0000212080 00000 n +0000212163 00000 n +0000212252 00000 n +0000212335 00000 n +0000212545 00000 n +0000212628 00000 n +0000212703 00000 n +0000212786 00000 n +0000212875 00000 n +0000212958 00000 n +0000213591 00000 n +0000213674 00000 n +0000213763 00000 n +0000213846 00000 n +0000213921 00000 n +0000214004 00000 n +0000214079 00000 n +0000214168 00000 n +0000214251 00000 n +0000214866 00000 n +0000214949 00000 n +0000215032 00000 n +0000215115 00000 n +0000215190 00000 n +0000215273 00000 n +0000215348 00000 n +0000215431 00000 n +0000215506 00000 n +0000215589 00000 n +0000215678 00000 n +0000215762 00000 n +0000215837 00000 n +0000215921 00000 n +0000216011 00000 n +0000216095 00000 n +0000216179 00000 n +0000216267 00000 n +0000216358 00000 n +0000216462 00000 n +0000216553 00000 n +0000216657 00000 n +0000216748 00000 n +0000216852 00000 n +0000216943 00000 n +0000217047 00000 n +0000217138 00000 n +0000217222 00000 n +0000217306 00000 n +0000217390 00000 n +0000217474 00000 n +0000217564 00000 n +0000217648 00000 n +0000217732 00000 n +0000217816 00000 n +0000217906 00000 n +0000217990 00000 n +0000218080 00000 n +0000218164 00000 n +0000218248 00000 n +0000218332 00000 n +0000218422 00000 n +0000218506 00000 n +0000218589 00000 n +0000218678 00000 n +0000218761 00000 n +0000218850 00000 n +0000218933 00000 n +0000219022 00000 n +0000219105 00000 n +0000219194 00000 n +0000219277 00000 n +0000219366 00000 n +0000219449 00000 n +0000219532 00000 n +0000219641 00000 n +0000219750 00000 n +0000219841 00000 n +0000219977 00000 n +0000220060 00000 n +0000220148 00000 n +0000220239 00000 n +0000220343 00000 n +0000220434 00000 n +0000220538 00000 n +0000220621 00000 n +0000220704 00000 n +0000220800 00000 n +0000220900 00000 n +0000221014 00000 n +0000221114 00000 n +0000221228 00000 n +0000221312 00000 n +0000221400 00000 n +0000221491 00000 n +0000221596 00000 n +0000221687 00000 n +0000221792 00000 n +0000221883 00000 n +0000221988 00000 n +0000222079 00000 n +0000222163 00000 n +0000222251 00000 n +0000222342 00000 n +0000222447 00000 n +0000222538 00000 n +0000222642 00000 n +0000222733 00000 n +0000222837 00000 n +0000222920 00000 n +0000223000 00000 n +0000223082 00000 n +0000223177 00000 n +0000223259 00000 n +0000223354 00000 n +0000223437 00000 n +0000223520 00000 n +0000223593 00000 n +0000223676 00000 n +0000223749 00000 n +0000223831 00000 n +0000225220 00000 n +0000225304 00000 n +0000225865 00000 n +0000225949 00000 n +0000226032 00000 n +0000226116 00000 n +0000226199 00000 n +0000226283 00000 n +0000226366 00000 n +0000226450 00000 n +0000226533 00000 n +0000226610 00000 n +0000226694 00000 n +0000226771 00000 n +0000226855 00000 n +0000226932 00000 n +0000227016 00000 n +0000227093 00000 n +0000227177 00000 n +0000227254 00000 n +0000227338 00000 n +0000227415 00000 n +0000227499 00000 n +0000227576 00000 n +0000227660 00000 n +0000227737 00000 n +0000227821 00000 n +0000227904 00000 n +0000227987 00000 n +0000228070 00000 n +0000228153 00000 n +0000228236 00000 n +0000228319 00000 n +0000228402 00000 n +0000228485 00000 n +0000228568 00000 n +0000228651 00000 n +0000228734 00000 n +0000228817 00000 n +0000228900 00000 n +0000228983 00000 n +0000229066 00000 n +0000229149 00000 n +0000229238 00000 n +0000229321 00000 n +0000229405 00000 n +0000229489 00000 n +0000229573 00000 n +0000229657 00000 n +0000229746 00000 n +0000229829 00000 n +0000229913 00000 n +0000229997 00000 n +0000230081 00000 n +0000230165 00000 n +0000230254 00000 n +0000230337 00000 n +0000230421 00000 n +0000230505 00000 n +0000230589 00000 n +0000230673 00000 n +0000230762 00000 n +0000230845 00000 n +0000230930 00000 n +0000231015 00000 n +0000231100 00000 n +0000231185 00000 n +0000231275 00000 n +0000231359 00000 n +0000231444 00000 n +0000231529 00000 n +0000231614 00000 n +0000231699 00000 n +0000231789 00000 n +0000231873 00000 n +0000231958 00000 n +0000232043 00000 n +0000232128 00000 n +0000232213 00000 n +0000232336 00000 n +0000232459 00000 n +0000232582 00000 n +0000232705 00000 n +0000232795 00000 n +0000232879 00000 n +0000232964 00000 n +0000233049 00000 n +0000233134 00000 n +0000233224 00000 n +0000233308 00000 n +0000233393 00000 n +0000233478 00000 n +0000233563 00000 n +0000233653 00000 n +0000233737 00000 n +0000233822 00000 n +0000233907 00000 n +0000233992 00000 n +0000234082 00000 n +0000234166 00000 n +0000234251 00000 n +0000234336 00000 n +0000234421 00000 n +0000234511 00000 n +0000234595 00000 n +0000234680 00000 n +0000234765 00000 n +0000234850 00000 n +0000234940 00000 n +0000235024 00000 n +0000235109 00000 n +0000235194 00000 n +0000235279 00000 n +0000235368 00000 n +0000235451 00000 n +0000235535 00000 n +0000235619 00000 n +0000235703 00000 n +0000235792 00000 n +0000235875 00000 n +0000235959 00000 n +0000236043 00000 n +0000236127 00000 n +0000236216 00000 n +0000236299 00000 n +0000236383 00000 n +0000236467 00000 n +0000236551 00000 n +0000236640 00000 n +0000236723 00000 n +0000236807 00000 n +0000236891 00000 n +0000236975 00000 n +0000237058 00000 n +0000237141 00000 n +0000237224 00000 n +0000237307 00000 n +0000237390 00000 n +0000237473 00000 n +0000237556 00000 n +0000237639 00000 n +0000237722 00000 n +0000237805 00000 n +0000237888 00000 n +0000237971 00000 n +0000238054 00000 n +0000238137 00000 n +0000238220 00000 n +0000238303 00000 n +0000238386 00000 n +0000238469 00000 n +0000238552 00000 n +0000238635 00000 n +0000238718 00000 n +0000238801 00000 n +0000238884 00000 n +0000238967 00000 n +0000239050 00000 n +0000239133 00000 n +0000239216 00000 n +0000239299 00000 n +0000239382 00000 n +0000239465 00000 n +0000239548 00000 n +0000239631 00000 n +0000239714 00000 n +0000239797 00000 n +0000239880 00000 n +0000239963 00000 n +0000240046 00000 n +0000240129 00000 n +0000240213 00000 n +0000240297 00000 n +0000240381 00000 n +0000240465 00000 n +0000240549 00000 n +0000240633 00000 n +0000240717 00000 n +0000240801 00000 n +0000240885 00000 n +0000240969 00000 n +0000241053 00000 n +0000241137 00000 n +0000241221 00000 n +0000241305 00000 n +0000241389 00000 n +0000241473 00000 n +0000241558 00000 n +0000241643 00000 n +0000241728 00000 n +0000241813 00000 n +0000241898 00000 n +0000241983 00000 n +0000242068 00000 n +0000242153 00000 n +0000242238 00000 n +0000242323 00000 n +0000242408 00000 n +0000242493 00000 n +0000242578 00000 n +0000242663 00000 n +0000242748 00000 n +0000242833 00000 n +0000242918 00000 n +0000243003 00000 n +0000243088 00000 n +0000243173 00000 n +0000243258 00000 n +0000243343 00000 n +0000243428 00000 n +0000243513 00000 n +0000243598 00000 n +0000243683 00000 n +0000243768 00000 n +0000243853 00000 n +0000243938 00000 n +0000244023 00000 n +0000244108 00000 n +0000244193 00000 n +0000244278 00000 n +0000244363 00000 n +0000244448 00000 n +0000244533 00000 n +0000244618 00000 n +0000244703 00000 n +0000244788 00000 n +0000244873 00000 n +0000244958 00000 n +0000245043 00000 n +0000245128 00000 n +0000245213 00000 n +0000245298 00000 n +0000245383 00000 n +0000245468 00000 n +0000245553 00000 n +0000245638 00000 n +0000245723 00000 n +0000245808 00000 n +0000245893 00000 n +0000245978 00000 n +0000246063 00000 n +0000246148 00000 n +0000246233 00000 n +0000246318 00000 n +0000246403 00000 n +0000246488 00000 n +0000246573 00000 n +0000246658 00000 n +0000246743 00000 n +0000246828 00000 n +0000246913 00000 n +0000246998 00000 n +0000247083 00000 n +0000247168 00000 n +0000247253 00000 n +0000247338 00000 n +0000247423 00000 n +0000247508 00000 n +0000247593 00000 n +0000247678 00000 n +0000247763 00000 n +0000247848 00000 n +0000247933 00000 n +0000248018 00000 n +0000248103 00000 n +0000248188 00000 n +0000248273 00000 n +0000248358 00000 n +0000248443 00000 n +0000248528 00000 n +0000248613 00000 n +0000248698 00000 n +0000248783 00000 n +0000248868 00000 n +0000248953 00000 n +0000249038 00000 n +0000249123 00000 n +0000249208 00000 n +0000249293 00000 n +0000249378 00000 n +0000249463 00000 n +0000249548 00000 n +0000249633 00000 n +0000249718 00000 n +0000249803 00000 n +0000249888 00000 n +0000249973 00000 n +0000250058 00000 n +0000250143 00000 n +0000250228 00000 n +0000250313 00000 n +0000250398 00000 n +0000250483 00000 n +0000250568 00000 n +0000250653 00000 n +0000250738 00000 n +0000250823 00000 n +0000250908 00000 n +0000250993 00000 n +0000251078 00000 n +0000251163 00000 n +0000251248 00000 n +0000251333 00000 n +0000251418 00000 n +0000251503 00000 n +0000251588 00000 n +0000251673 00000 n +0000251758 00000 n +0000251843 00000 n +0000251928 00000 n +0000252013 00000 n +0000252098 00000 n +0000252183 00000 n +0000252268 00000 n +0000252353 00000 n +0000252438 00000 n +0000252523 00000 n +0000252608 00000 n +0000252693 00000 n +0000252778 00000 n +0000252863 00000 n +0000252948 00000 n +0000253033 00000 n +0000253118 00000 n +0000253203 00000 n +0000253288 00000 n +0000253373 00000 n +0000253458 00000 n +0000253543 00000 n +0000253628 00000 n +0000253713 00000 n +0000253798 00000 n +0000253883 00000 n +0000253968 00000 n +0000254053 00000 n +0000254138 00000 n +0000254223 00000 n +0000254308 00000 n +0000254393 00000 n +0000254478 00000 n +0000254563 00000 n +0000254648 00000 n +0000254733 00000 n +0000254818 00000 n +0000254903 00000 n +0000254988 00000 n +0000255073 00000 n +0000255158 00000 n +0000255243 00000 n +0000255328 00000 n +0000255413 00000 n +0000255498 00000 n +0000255583 00000 n +0000255668 00000 n +0000255753 00000 n +0000255838 00000 n +0000255923 00000 n +0000256008 00000 n +0000256093 00000 n +0000256178 00000 n +0000256263 00000 n +0000256348 00000 n +0000256433 00000 n +0000256518 00000 n +0000256603 00000 n +0000256688 00000 n +0000256773 00000 n +0000256858 00000 n +0000256943 00000 n +0000257028 00000 n +0000257152 00000 n +0000257276 00000 n +0000257400 00000 n +0000257524 00000 n +0000257616 00000 n +0000257702 00000 n +0000257788 00000 n +0000257874 00000 n +0000257960 00000 n +0000258046 00000 n +0000258132 00000 n +0000258224 00000 n +0000258310 00000 n +0000258396 00000 n +0000258488 00000 n +0000258574 00000 n +0000258660 00000 n +0000258746 00000 n +0000258832 00000 n +0000258923 00000 n +0000259008 00000 n +0000259093 00000 n +0000259178 00000 n +0000259263 00000 n +0000259354 00000 n +0000259439 00000 n +0000259524 00000 n +0000259609 00000 n +0000259694 00000 n +0000259785 00000 n +0000259870 00000 n +0000259955 00000 n +0000260040 00000 n +0000260125 00000 n +0000260216 00000 n +0000260301 00000 n +0000260386 00000 n +0000260477 00000 n +0000260562 00000 n +0000260647 00000 n +0000260732 00000 n +0000260817 00000 n +0000260908 00000 n +0000260993 00000 n +0000261078 00000 n +0000261169 00000 n +0000261254 00000 n +0000261339 00000 n +0000261424 00000 n +0000261509 00000 n +0000261600 00000 n +0000261685 00000 n +0000261770 00000 n +0000261861 00000 n +0000261946 00000 n +0000262031 00000 n +0000262116 00000 n +0000262201 00000 n +0000262279 00000 n +0000262364 00000 n +0000262448 00000 n +0000262526 00000 n +0000262611 00000 n +0000262695 00000 n +0000262785 00000 n +0000262870 00000 n +0000262954 00000 n +0000263044 00000 n +0000263129 00000 n +0000263213 00000 n +0000263303 00000 n +0000263388 00000 n +0000263472 00000 n +0000263562 00000 n +0000263647 00000 n +0000263731 00000 n +0000263821 00000 n +0000263906 00000 n +0000263990 00000 n +0000264068 00000 n +0000264153 00000 n +0000264237 00000 n +0000264327 00000 n +0000264412 00000 n +0000264496 00000 n +0000264586 00000 n +0000264671 00000 n +0000264749 00000 n +0000264834 00000 n +0000264918 00000 n +0000264996 00000 n +0000265081 00000 n +0000265166 00000 n +0000265245 00000 n +0000265331 00000 n +0000265416 00000 n +0000265507 00000 n +0000265593 00000 n +0000265678 00000 n +0000265763 00000 n +0000265848 00000 n +0000265933 00000 n +0000266025 00000 n +0000266111 00000 n +0000266197 00000 n +0000266283 00000 n +0000266369 00000 n +0000266461 00000 n +0000266547 00000 n +0000266633 00000 n +0000266725 00000 n +0000266811 00000 n +0000266903 00000 n +0000266989 00000 n +0000267075 00000 n +0000267167 00000 n +0000267253 00000 n +0000267345 00000 n +0000267431 00000 n +0000267517 00000 n +0000267613 00000 n +0000267705 00000 n +0000267797 00000 n +0000267883 00000 n +0000267969 00000 n +0000268061 00000 n +0000268147 00000 n +0000268239 00000 n +0000268325 00000 n +0000268411 00000 n +0000268507 00000 n +0000268599 00000 n +0000268691 00000 n +0000268777 00000 n +0000268863 00000 n +0000268955 00000 n +0000269041 00000 n +0000269133 00000 n +0000269219 00000 n +0000269305 00000 n +0000269391 00000 n +0000269483 00000 n +0000269569 00000 n +0000269655 00000 n +0000269741 00000 n +0000269833 00000 n +0000269919 00000 n +0000270005 00000 n +0000270091 00000 n +0000270187 00000 n +0000270279 00000 n +0000270365 00000 n +0000270451 00000 n +0000270537 00000 n +0000270622 00000 n +0000270713 00000 n +0000270799 00000 n +0000270884 00000 n +0000270975 00000 n +0000271061 00000 n +0000271146 00000 n +0000271237 00000 n +0000271323 00000 n +0000271408 00000 n +0000271532 00000 n +0000271656 00000 n +0000271780 00000 n +0000271866 00000 n +0000271952 00000 n +0000272038 00000 n +0000272124 00000 n +0000272209 00000 n +0000272294 00000 n +0000272379 00000 n +0000272464 00000 n +0000272548 00000 n +0000272632 00000 n +0000272716 00000 n +0000272800 00000 n +0000272891 00000 n +0000272976 00000 n +0000273061 00000 n +0000273146 00000 n +0000273231 00000 n +0000273322 00000 n +0000273407 00000 n +0000273492 00000 n +0000273577 00000 n +0000273662 00000 n +0000273753 00000 n +0000273838 00000 n +0000273923 00000 n +0000274008 00000 n +0000274099 00000 n +0000274184 00000 n +0000274269 00000 n +0000274354 00000 n +0000274445 00000 n +0000274530 00000 n +0000274615 00000 n +0000274700 00000 n +0000274791 00000 n +0000274876 00000 n +0000274961 00000 n +0000275046 00000 n +0000275130 00000 n +0000275214 00000 n +0000275298 00000 n +0000275382 00000 n +0000275466 00000 n +0000275551 00000 n +0000275642 00000 n +0000275727 00000 n +0000275812 00000 n +0000275903 00000 n +0000275988 00000 n +0000276073 00000 n +0000276158 00000 n +0000276249 00000 n +0000276334 00000 n +0000276419 00000 n +0000276510 00000 n +0000276595 00000 n +0000276680 00000 n +0000276765 00000 n +0000276856 00000 n +0000276941 00000 n +0000277026 00000 n +0000277117 00000 n +0000277202 00000 n +0000277287 00000 n +0000277371 00000 n +0000277456 00000 n +0000277541 00000 n +0000277626 00000 n +0000277711 00000 n +0000277796 00000 n +0000277881 00000 n +0000277966 00000 n +0000278051 00000 n +0000278136 00000 n +0000278221 00000 n +0000278312 00000 n +0000278436 00000 n +0000278560 00000 n +0000278684 00000 n +0000278808 00000 n +0000278900 00000 n +0000278986 00000 n +0000279072 00000 n +0000279158 00000 n +0000279244 00000 n +0000279336 00000 n +0000279422 00000 n +0000279508 00000 n +0000279594 00000 n +0000279680 00000 n +0000279772 00000 n +0000279858 00000 n +0000279944 00000 n +0000280030 00000 n +0000280116 00000 n +0000280208 00000 n +0000280294 00000 n +0000280380 00000 n +0000280466 00000 n +0000280552 00000 n +0000280644 00000 n +0000280730 00000 n +0000280816 00000 n +0000280902 00000 n +0000280988 00000 n +0000281080 00000 n +0000281166 00000 n +0000281252 00000 n +0000281338 00000 n +0000281424 00000 n +0000281516 00000 n +0000281602 00000 n +0000281688 00000 n +0000281774 00000 n +0000281860 00000 n +0000281952 00000 n +0000282038 00000 n +0000282124 00000 n +0000282210 00000 n +0000282296 00000 n +0000282474 00000 n +0000282565 00000 n +0000282650 00000 n +0000282735 00000 n +0000282820 00000 n +0000282905 00000 n +0000282996 00000 n +0000283081 00000 n +0000283166 00000 n +0000283251 00000 n +0000283336 00000 n +0000283427 00000 n +0000283512 00000 n +0000283597 00000 n +0000283682 00000 n +0000283767 00000 n +0000283858 00000 n +0000283943 00000 n +0000284028 00000 n +0000284113 00000 n +0000284198 00000 n +0000284282 00000 n +0000284366 00000 n +0000284450 00000 n +0000284535 00000 n +0000284620 00000 n +0000284705 00000 n +0000284790 00000 n +0000284875 00000 n +0000284960 00000 n +0000285045 00000 n +0000285130 00000 n +0000285215 00000 n +0000285300 00000 n +0000285385 00000 n +0000285470 00000 n +0000285554 00000 n +0000285638 00000 n +0000285722 00000 n +0000285806 00000 n +0000285891 00000 n +0000285976 00000 n +0000286067 00000 n +0000286152 00000 n +0000286237 00000 n +0000286322 00000 n +0000286407 00000 n +0000286492 00000 n +0000286583 00000 n +0000286668 00000 n +0000286753 00000 n +0000286838 00000 n +0000286923 00000 n +0000287008 00000 n +0000287093 00000 n +0000287178 00000 n +0000287263 00000 n +0000287348 00000 n +0000287433 00000 n +0000287518 00000 n +0000287603 00000 n +0000287688 00000 n +0000287773 00000 n +0000287857 00000 n +0000287941 00000 n +0000288025 00000 n +0000288109 00000 n +0000288194 00000 n +0000288279 00000 n +0000288364 00000 n +0000288449 00000 n +0000288534 00000 n +0000288619 00000 n +0000288704 00000 n +0000288789 00000 n +0000288874 00000 n +0000288959 00000 n +0000289044 00000 n +0000289129 00000 n +0000289214 00000 n +0000289299 00000 n +0000289384 00000 n +0000289469 00000 n +0000289554 00000 n +0000289639 00000 n +0000289724 00000 n +0000289809 00000 n +0000289894 00000 n +0000289979 00000 n +0000290064 00000 n +0000290149 00000 n +0000290234 00000 n +0000290319 00000 n +0000290404 00000 n +0000290489 00000 n +0000290574 00000 n +0000290659 00000 n +0000290744 00000 n +0000290829 00000 n +0000290914 00000 n +0000290999 00000 n +0000291084 00000 n +0000291169 00000 n +0000291254 00000 n +0000291339 00000 n +0000291424 00000 n +0000291509 00000 n +0000291594 00000 n +0000291679 00000 n +0000291764 00000 n +0000291849 00000 n +0000291934 00000 n +0000292019 00000 n +0000292104 00000 n +0000292189 00000 n +0000292274 00000 n +0000292359 00000 n +0000292444 00000 n +0000292529 00000 n +0000292614 00000 n +0000292699 00000 n +0000292784 00000 n +0000292869 00000 n +0000292954 00000 n +0000293039 00000 n +0000293124 00000 n +0000293209 00000 n +0000293294 00000 n +0000293379 00000 n +0000293464 00000 n +0000293549 00000 n +0000293634 00000 n +0000293719 00000 n +0000293804 00000 n +0000293889 00000 n +0000293974 00000 n +0000294059 00000 n +0000294144 00000 n +0000294229 00000 n +0000294314 00000 n +0000294399 00000 n +0000294484 00000 n +0000294569 00000 n +0000294654 00000 n +0000294739 00000 n +0000294824 00000 n +0000294909 00000 n +0000294994 00000 n +0000295079 00000 n +0000295164 00000 n +0000295249 00000 n +0000295334 00000 n +0000295419 00000 n +0000295504 00000 n +0000295589 00000 n +0000295674 00000 n +0000295759 00000 n +0000295844 00000 n +0000295929 00000 n +0000296014 00000 n +0000296099 00000 n +0000296184 00000 n +0000296269 00000 n +0000296354 00000 n +0000296439 00000 n +0000296524 00000 n +0000296609 00000 n +0000296694 00000 n +0000296779 00000 n +0000296864 00000 n +0000296949 00000 n +0000297034 00000 n +0000297119 00000 n +0000297198 00000 n +0000297289 00000 n +0000297375 00000 n +0000297460 00000 n +0000297539 00000 n +0000297624 00000 n +0000297715 00000 n +0000297801 00000 n +0000297886 00000 n +0000297977 00000 n +0000298063 00000 n +0000298148 00000 n +0000298227 00000 n +0000298312 00000 n +0000298391 00000 n +0000298482 00000 n +0000298568 00000 n +0000298653 00000 n +0000298737 00000 n +0000298821 00000 n +0000298905 00000 n +0000298989 00000 n +0000299073 00000 n +0000299157 00000 n +0000299241 00000 n +0000299325 00000 n +0000299409 00000 n +0000299493 00000 n +0000299577 00000 n +0000299661 00000 n +0000299745 00000 n +0000299829 00000 n +0000299913 00000 n +0000299997 00000 n +0000300081 00000 n +0000300165 00000 n +0000300249 00000 n +0000300333 00000 n +0000300417 00000 n +0000300501 00000 n +0000300585 00000 n +0000300669 00000 n +0000300753 00000 n +0000300837 00000 n +0000300921 00000 n +0000301005 00000 n +0000301089 00000 n +0000301173 00000 n +0000301257 00000 n +0000301341 00000 n +0000301425 00000 n +0000301509 00000 n +0000301593 00000 n +0000301677 00000 n +0000301761 00000 n +0000301845 00000 n +0000301929 00000 n +0000302013 00000 n +0000302097 00000 n +0000302181 00000 n +0000302265 00000 n +0000302349 00000 n +0000302433 00000 n +0000302517 00000 n +0000302601 00000 n +0000302685 00000 n +0000302769 00000 n +0000302853 00000 n +0000302937 00000 n +0000303021 00000 n +0000303105 00000 n +0000303189 00000 n +0000303273 00000 n +0000303357 00000 n +0000303441 00000 n +0000303525 00000 n +0000303609 00000 n +0000303693 00000 n +0000303777 00000 n +0000303861 00000 n +0000303946 00000 n +0000304031 00000 n +0000304116 00000 n +0000304201 00000 n +0000304284 00000 n +0000304367 00000 n +0000304450 00000 n +0000304534 00000 n +0000304618 00000 n +0000304702 00000 n +0000304786 00000 n +0000304870 00000 n +0000304954 00000 n +0000305038 00000 n +0000305122 00000 n +0000305206 00000 n +0000305290 00000 n +0000305374 00000 n +0000305458 00000 n +0000305542 00000 n +0000305626 00000 n +0000305710 00000 n +0000305794 00000 n +0000305878 00000 n +0000305962 00000 n +0000306046 00000 n +0000306130 00000 n +0000306214 00000 n +0000306298 00000 n +0000306382 00000 n +0000306466 00000 n +0000306550 00000 n +0000306634 00000 n +0000306718 00000 n +0000306802 00000 n +0000306886 00000 n +0000306970 00000 n +0000307054 00000 n +0000307138 00000 n +0000307223 00000 n +0000307307 00000 n +0000307391 00000 n +0000307475 00000 n +0000307559 00000 n +0000307643 00000 n +0000307727 00000 n +0000307811 00000 n +0000307895 00000 n +0000307979 00000 n +0000308063 00000 n +0000308147 00000 n +0000308231 00000 n +0000308315 00000 n +0000308399 00000 n +0000308483 00000 n +0000308567 00000 n +0000308651 00000 n +0000308736 00000 n +0000308821 00000 n +0000308906 00000 n +0000308991 00000 n +0000309076 00000 n +0000309161 00000 n +0000309246 00000 n +0000309331 00000 n +0000309416 00000 n +0000309501 00000 n +0000309586 00000 n +0000309671 00000 n +0000309755 00000 n +0000309839 00000 n +0000309923 00000 n +0000310008 00000 n +0000310093 00000 n +0000310178 00000 n +0000310263 00000 n +0000310348 00000 n +0000310433 00000 n +0000310518 00000 n +0000310603 00000 n +0000310688 00000 n +0000310773 00000 n +0000310858 00000 n +0000310943 00000 n +0000311028 00000 n +0000311113 00000 n +0000311198 00000 n +0000311282 00000 n +0000311366 00000 n +0000311450 00000 n +0000311534 00000 n +0000311618 00000 n +0000311702 00000 n +0000311786 00000 n +0000311870 00000 n +0000311954 00000 n +0000312038 00000 n +0000312122 00000 n +0000312206 00000 n +0000312290 00000 n +0000312374 00000 n +0000312458 00000 n +0000312542 00000 n +0000312626 00000 n +0000312710 00000 n +0000312794 00000 n +0000312878 00000 n +0000312962 00000 n +0000313046 00000 n +0000313130 00000 n +0000313214 00000 n +0000313298 00000 n +0000313382 00000 n +0000313466 00000 n +0000313550 00000 n +0000313634 00000 n +0000313718 00000 n +0000313802 00000 n +0000313886 00000 n +0000313970 00000 n +0000314054 00000 n +0000314138 00000 n +0000314222 00000 n +0000314306 00000 n +0000314390 00000 n +0000314474 00000 n +0000314558 00000 n +0000314642 00000 n +0000314726 00000 n +0000314810 00000 n +0000314894 00000 n +0000314978 00000 n +0000315062 00000 n +0000315146 00000 n +0000315230 00000 n +0000315315 00000 n +0000315400 00000 n +0000315485 00000 n +0000315570 00000 n +0000315655 00000 n +0000315740 00000 n +0000315825 00000 n +0000315910 00000 n +0000315995 00000 n +0000316080 00000 n +0000316165 00000 n +0000316250 00000 n +0000316335 00000 n +0000316420 00000 n +0000316505 00000 n +0000316590 00000 n +0000316675 00000 n +0000316760 00000 n +0000316845 00000 n +0000316930 00000 n +0000317015 00000 n +0000317100 00000 n +0000317185 00000 n +0000317270 00000 n +0000317355 00000 n +0000317440 00000 n +0000317525 00000 n +0000317610 00000 n +0000317695 00000 n +0000317779 00000 n +0000317863 00000 n +0000317947 00000 n +0000318031 00000 n +0000318115 00000 n +0000318199 00000 n +0000318283 00000 n +0000318367 00000 n +0000318451 00000 n +0000318535 00000 n +0000318619 00000 n +0000318710 00000 n +0000318795 00000 n +0000318880 00000 n +0000318965 00000 n +0000319050 00000 n +0000319135 00000 n +0000319226 00000 n +0000319311 00000 n +0000319396 00000 n +0000319481 00000 n +0000319566 00000 n +0000319651 00000 n +0000319736 00000 n +0000319821 00000 n +0000319906 00000 n +0000319997 00000 n +0000320082 00000 n +0000320167 00000 n +0000320252 00000 n +0000320337 00000 n +0000320422 00000 n +0000320506 00000 n +0000320590 00000 n +0000320674 00000 n +0000320758 00000 n +0000320842 00000 n +0000320926 00000 n +0000321010 00000 n +0000321094 00000 n +0000321178 00000 n +0000321262 00000 n +0000321346 00000 n +0000321430 00000 n +0000321514 00000 n +0000321598 00000 n +0000321682 00000 n +0000321766 00000 n +0000321850 00000 n +0000321934 00000 n +0000322018 00000 n +0000322102 00000 n +0000322186 00000 n +0000322270 00000 n +0000322354 00000 n +0000322438 00000 n +0000322522 00000 n +0000322606 00000 n +0000322690 00000 n +0000322774 00000 n +0000322858 00000 n +0000322942 00000 n +0000323026 00000 n +0000323110 00000 n +0000323194 00000 n +0000323278 00000 n +0000323362 00000 n +0000323446 00000 n +0000323530 00000 n +0000323614 00000 n +0000323698 00000 n +0000323782 00000 n +0000323867 00000 n +0000323952 00000 n +0000324037 00000 n +0000324122 00000 n +0000324207 00000 n +0000324292 00000 n +0000324377 00000 n +0000324462 00000 n +0000324547 00000 n +0000324632 00000 n +0000324717 00000 n +0000324802 00000 n +0000324887 00000 n +0000324972 00000 n +0000325057 00000 n +0000325142 00000 n +0000325227 00000 n +0000325312 00000 n +0000325397 00000 n +0000325482 00000 n +0000325567 00000 n +0000325652 00000 n +0000325737 00000 n +0000325822 00000 n +0000325907 00000 n +0000325992 00000 n +0000326077 00000 n +0000326162 00000 n +0000326247 00000 n +0000326332 00000 n +0000326417 00000 n +0000326502 00000 n +0000326587 00000 n +0000326672 00000 n +0000326757 00000 n +0000326842 00000 n +0000326927 00000 n +0000327012 00000 n +0000327097 00000 n +0000327182 00000 n +0000327266 00000 n +0000327350 00000 n +0000327434 00000 n +0000327518 00000 n +0000327602 00000 n +0000327686 00000 n +0000327770 00000 n +0000327854 00000 n +0000327938 00000 n +0000328022 00000 n +0000328106 00000 n +0000328190 00000 n +0000328274 00000 n +0000328358 00000 n +0000328442 00000 n +0000328526 00000 n +0000328610 00000 n +0000328694 00000 n +0000328778 00000 n +0000328862 00000 n +0000328946 00000 n +0000329030 00000 n +0000329114 00000 n +0000329198 00000 n +0000329282 00000 n +0000329366 00000 n +0000329450 00000 n +0000329534 00000 n +0000329618 00000 n +0000329702 00000 n +0000329786 00000 n +0000329870 00000 n +0000329954 00000 n +0000330038 00000 n +0000330122 00000 n +0000330206 00000 n +0000330290 00000 n +0000330374 00000 n +0000330458 00000 n +0000330542 00000 n +0000330626 00000 n +0000330710 00000 n +0000330794 00000 n +0000330878 00000 n +0000330962 00000 n +0000331046 00000 n +0000331130 00000 n +0000331214 00000 n +0000331298 00000 n +0000331382 00000 n +0000331466 00000 n +0000331550 00000 n +0000331634 00000 n +0000331718 00000 n +0000331802 00000 n +0000331886 00000 n +0000331970 00000 n +0000332054 00000 n +0000332138 00000 n +0000332222 00000 n +0000332306 00000 n +0000332390 00000 n +0000332474 00000 n +0000332558 00000 n +0000332642 00000 n +0000332726 00000 n +0000332810 00000 n +0000332894 00000 n +0000332978 00000 n +0000333062 00000 n +0000333146 00000 n +0000333230 00000 n +0000333314 00000 n +0000333398 00000 n +0000333482 00000 n +0000333567 00000 n +0000333652 00000 n +0000333737 00000 n +0000333822 00000 n +0000333907 00000 n +0000333993 00000 n +0000334079 00000 n +0000334165 00000 n +0000334251 00000 n +0000334337 00000 n +0000334423 00000 n +0000334509 00000 n +0000334595 00000 n +0000334681 00000 n +0000334767 00000 n +0000334853 00000 n +0000334939 00000 n +0000335025 00000 n +0000335111 00000 n +0000335197 00000 n +0000335283 00000 n +0000335369 00000 n +0000335455 00000 n +0000335541 00000 n +0000335627 00000 n +0000335713 00000 n +0000335799 00000 n +0000335885 00000 n +0000335971 00000 n +0000336057 00000 n +0000336143 00000 n +0000336229 00000 n +0000336314 00000 n +0000336399 00000 n +0000336484 00000 n +0000336569 00000 n +0000336653 00000 n +0000336737 00000 n +0000336821 00000 n +0000336905 00000 n +0000336989 00000 n +0000337067 00000 n +0000337157 00000 n +0000337242 00000 n +0000337326 00000 n +0000337416 00000 n +0000337501 00000 n +0000337585 00000 n +0000337663 00000 n +0000337753 00000 n +0000337838 00000 n +0000337922 00000 n +0000338012 00000 n +0000338097 00000 n +0000338181 00000 n +0000338259 00000 n +0000338349 00000 n +0000338434 00000 n +0000338518 00000 n +0000338596 00000 n +0000338680 00000 n +0000338770 00000 n +0000338855 00000 n +0000338939 00000 n +0000339029 00000 n +0000339114 00000 n +0000339198 00000 n +0000339288 00000 n +0000339373 00000 n +0000339457 00000 n +0000339541 00000 n +0000339625 00000 n +0000339709 00000 n +0000339794 00000 n +0000339879 00000 n +0000339964 00000 n +0000340049 00000 n +0000340134 00000 n +0000340219 00000 n +0000340304 00000 n +0000340389 00000 n +0000340474 00000 n +0000340559 00000 n +0000340644 00000 n +0000340729 00000 n +0000340813 00000 n +0000340897 00000 n +0000340981 00000 n +0000341065 00000 n +0000341150 00000 n +0000341235 00000 n +0000341320 00000 n +0000341405 00000 n +0000341490 00000 n +0000341576 00000 n +0000341662 00000 n +0000341748 00000 n +0000341834 00000 n +0000341920 00000 n +0000342006 00000 n +0000342092 00000 n +0000342178 00000 n +0000342264 00000 n +0000342350 00000 n +0000342436 00000 n +0000342521 00000 n +0000342606 00000 n +0000342691 00000 n +0000342777 00000 n +0000342863 00000 n +0000342949 00000 n +0000343035 00000 n +0000343121 00000 n +0000343207 00000 n +0000343293 00000 n +0000343379 00000 n +0000343465 00000 n +0000343551 00000 n +0000343637 00000 n +0000343723 00000 n +0000343809 00000 n +0000343895 00000 n +0000343981 00000 n +0000344067 00000 n +0000344153 00000 n +0000344239 00000 n +0000344325 00000 n +0000344411 00000 n +0000344497 00000 n +0000344621 00000 n +0000344745 00000 n +0000344869 00000 n +0000344955 00000 n +0000345041 00000 n +0000345127 00000 n +0000345213 00000 n +0000345299 00000 n +0000345385 00000 n +0000345470 00000 n +0000345555 00000 n +0000345640 00000 n +0000345725 00000 n +0000345810 00000 n +0000345895 00000 n +0000345980 00000 n +0000346065 00000 n +0000346150 00000 n +0000346235 00000 n +0000346320 00000 n +0000346405 00000 n +0000346489 00000 n +0000346573 00000 n +0000346658 00000 n +0000346743 00000 n +0000346828 00000 n +0000346913 00000 n +0000346998 00000 n +0000347083 00000 n +0000347168 00000 n +0000347253 00000 n +0000347337 00000 n +0000347421 00000 n +0000347504 00000 n +0000347587 00000 n +0000347670 00000 n +0000347753 00000 n +0000347836 00000 n +0000347919 00000 n +0000348002 00000 n +0000348086 00000 n +0000348170 00000 n +0000348254 00000 n +0000348338 00000 n +0000348422 00000 n +0000348506 00000 n +0000348590 00000 n +0000348674 00000 n +0000348758 00000 n +0000348842 00000 n +0000348926 00000 n +0000349010 00000 n +0000349094 00000 n +0000349178 00000 n +0000349262 00000 n +0000349346 00000 n +0000349430 00000 n +0000349514 00000 n +0000349598 00000 n +0000349682 00000 n +0000349766 00000 n +0000349850 00000 n +0000349934 00000 n +0000350018 00000 n +0000350102 00000 n +0000350186 00000 n +0000350270 00000 n +0000350354 00000 n +0000350438 00000 n +0000350522 00000 n +0000350606 00000 n +0000350690 00000 n +0000350774 00000 n +0000350858 00000 n +0000350942 00000 n +0000351026 00000 n +0000351110 00000 n +0000351194 00000 n +0000351278 00000 n +0000351362 00000 n +0000351446 00000 n +0000351530 00000 n +0000351614 00000 n +0000351698 00000 n +0000351782 00000 n +0000351866 00000 n +0000351950 00000 n +0000352034 00000 n +0000352118 00000 n +0000352202 00000 n +0000352286 00000 n +0000352370 00000 n +0000352454 00000 n +0000352538 00000 n +0000352622 00000 n +0000352706 00000 n +0000352790 00000 n +0000352874 00000 n +0000352958 00000 n +0000353042 00000 n +0000353126 00000 n +0000353210 00000 n +0000353294 00000 n +0000353378 00000 n +0000353462 00000 n +0000353546 00000 n +0000353630 00000 n +0000353714 00000 n +0000353798 00000 n +0000353882 00000 n +0000353966 00000 n +0000354050 00000 n +0000354134 00000 n +0000354218 00000 n +0000354302 00000 n +0000354386 00000 n +0000354470 00000 n +0000354554 00000 n +0000354638 00000 n +0000354722 00000 n +0000354806 00000 n +0000354890 00000 n +0000354974 00000 n +0000355058 00000 n +0000355142 00000 n +0000355226 00000 n +0000355310 00000 n +0000355394 00000 n +0000355478 00000 n +0000355562 00000 n +0000355647 00000 n +0000355732 00000 n +0000355817 00000 n +0000355902 00000 n +0000355987 00000 n +0000356072 00000 n +0000356157 00000 n +0000356242 00000 n +0000356327 00000 n +0000356412 00000 n +0000356497 00000 n +0000356582 00000 n +0000356667 00000 n +0000356752 00000 n +0000356837 00000 n +0000356922 00000 n +0000357007 00000 n +0000357092 00000 n +0000357177 00000 n +0000357262 00000 n +0000357347 00000 n +0000357432 00000 n +0000357517 00000 n +0000357602 00000 n +0000357687 00000 n +0000357772 00000 n +0000357857 00000 n +0000357942 00000 n +0000358027 00000 n +0000358112 00000 n +0000358197 00000 n +0000358282 00000 n +0000358367 00000 n +0000358452 00000 n +0000358537 00000 n +0000358622 00000 n +0000358707 00000 n +0000358792 00000 n +0000358877 00000 n +0000358962 00000 n +0000359047 00000 n +0000359132 00000 n +0000359217 00000 n +0000359302 00000 n +0000359387 00000 n +0000359472 00000 n +0000359557 00000 n +0000359642 00000 n +0000359727 00000 n +0000359812 00000 n +0000359897 00000 n +0000359982 00000 n +0000360067 00000 n +0000360152 00000 n +0000360237 00000 n +0000360322 00000 n +0000360407 00000 n +0000360492 00000 n +0000360577 00000 n +0000360662 00000 n +0000360747 00000 n +0000360832 00000 n +0000360917 00000 n +0000361002 00000 n +0000361087 00000 n +0000361172 00000 n +0000361257 00000 n +0000361342 00000 n +0000361427 00000 n +0000361512 00000 n +0000361597 00000 n +0000361682 00000 n +0000361767 00000 n +0000361852 00000 n +0000361937 00000 n +0000362022 00000 n +0000362107 00000 n +0000362192 00000 n +0000362277 00000 n +0000362362 00000 n +0000362447 00000 n +0000362532 00000 n +0000362617 00000 n +0000362702 00000 n +0000362787 00000 n +0000362872 00000 n +0000362957 00000 n +0000363042 00000 n +0000363127 00000 n +0000363212 00000 n +0000363297 00000 n +0000363382 00000 n +0000363467 00000 n +0000363552 00000 n +0000363637 00000 n +0000363722 00000 n +0000363807 00000 n +0000363892 00000 n +0000363977 00000 n +0000364062 00000 n +0000364147 00000 n +0000364232 00000 n +0000364317 00000 n +0000364402 00000 n +0000364487 00000 n +0000364836 00000 n +0000365187 00000 n +0000366097 00000 n +0000367577 00000 n +0000368589 00000 n +0000370460 00000 n +0000370618 00000 n +0000370706 00000 n +0000370794 00000 n +0000370882 00000 n +0000371090 00000 n +0000372366 00000 n +0000373540 00000 n +0000374701 00000 n +0000375020 00000 n +0000375255 00000 n +0000375744 00000 n +0000375961 00000 n +0000376988 00000 n +0000377290 00000 n +0000377719 00000 n +0000377975 00000 n +0000378063 00000 n +0000378271 00000 n +0000379547 00000 n +0000379849 00000 n +0000380089 00000 n +0000380459 00000 n +0000380534 00000 n +0000380609 00000 n +0000380684 00000 n +0000380759 00000 n +0000380832 00000 n +0000380905 00000 n +0000380978 00000 n +0000381051 00000 n +0000381124 00000 n +0000381197 00000 n +0000381270 00000 n +0000381343 00000 n +0000381515 00000 n +0000381687 00000 n +0000381859 00000 n +0000382032 00000 n +0000382204 00000 n +0000382376 00000 n +0000382548 00000 n +0000382720 00000 n +0000382893 00000 n +0000383065 00000 n +0000383237 00000 n +0000383409 00000 n +0000383581 00000 n +0000383754 00000 n +0000383926 00000 n +0000384098 00000 n +0000384270 00000 n +0000384442 00000 n +0000384615 00000 n +0000384787 00000 n +0000384959 00000 n +0000385131 00000 n +0000385303 00000 n +0000385476 00000 n +0000385648 00000 n +0000385820 00000 n +0000385992 00000 n +0000386164 00000 n +0000386337 00000 n +0000386509 00000 n +0000386681 00000 n +0000386853 00000 n +0000387026 00000 n +0000387198 00000 n +0000387370 00000 n +0000387542 00000 n +0000387715 00000 n +0000387887 00000 n +0000388059 00000 n +0000388231 00000 n +0000388404 00000 n +0000388576 00000 n +0000388748 00000 n +0000388920 00000 n +0000389093 00000 n +0000389265 00000 n +0000389437 00000 n +0000389609 00000 n +0000389782 00000 n +0000389954 00000 n +0000390126 00000 n +0000390298 00000 n +0000390471 00000 n +0000390643 00000 n +0000390815 00000 n +0000390987 00000 n +0000391160 00000 n +0000391332 00000 n +0000391504 00000 n +0000391676 00000 n +0000391849 00000 n +0000392021 00000 n +0000392193 00000 n +0000392365 00000 n +0000392538 00000 n +0000392710 00000 n +0000392882 00000 n +0000393054 00000 n +0000393227 00000 n +0000393399 00000 n +0000393583 00000 n +0000393756 00000 n +0000393940 00000 n +0000394113 00000 n +0000394306 00000 n +0000394479 00000 n +0000394652 00000 n +0000394825 00000 n +0000394998 00000 n +0000395171 00000 n +0000395344 00000 n +0000395517 00000 n +0000395690 00000 n +0000395863 00000 n +0000396036 00000 n +0000396209 00000 n +0000396382 00000 n +0000396555 00000 n +0000396728 00000 n +0000396901 00000 n +0000397094 00000 n +0000397267 00000 n +0000397440 00000 n +0000397613 00000 n +0000397806 00000 n +0000397979 00000 n +0000398152 00000 n +0000398325 00000 n +0000398518 00000 n +0000398691 00000 n +0000398864 00000 n +0000399037 00000 n +0000399113 00000 n +0000399189 00000 n +0000399265 00000 n +0000399341 00000 n +0000399417 00000 n +0000399493 00000 n +0000399666 00000 n +0000399839 00000 n +0000400023 00000 n +0000400196 00000 n +0000400369 00000 n +0000400542 00000 n +0000400715 00000 n +0000400888 00000 n +0000401061 00000 n +0000401234 00000 n +0000401407 00000 n +0000401580 00000 n +0000401753 00000 n +0000401926 00000 n +0000402099 00000 n +0000402272 00000 n +0000402445 00000 n +0000402618 00000 n +0000402791 00000 n +0000402964 00000 n +0000403137 00000 n +0000403310 00000 n +0000403483 00000 n +0000403656 00000 n +0000403829 00000 n +0000404002 00000 n +0000404175 00000 n +0000404348 00000 n +0000404521 00000 n +0000404694 00000 n +0000404867 00000 n +0000405040 00000 n +0000405213 00000 n +0000405289 00000 n +0000405462 00000 n +0000405635 00000 n +0000405819 00000 n +0000405992 00000 n +0000406165 00000 n +0000406349 00000 n +0000406533 00000 n +0000406706 00000 n +0000406879 00000 n +0000407063 00000 n +0000407236 00000 n +0000407409 00000 n +0000407582 00000 n +0000407755 00000 n +0000407928 00000 n +0000408101 00000 n +0000408274 00000 n +0000408447 00000 n +0000408620 00000 n +0000408793 00000 n +0000408966 00000 n +0000409139 00000 n +0000409312 00000 n +0000409485 00000 n +0000409658 00000 n +0000409842 00000 n +0000410015 00000 n +0000410188 00000 n +0000410361 00000 n +0000410545 00000 n +0000410718 00000 n +0000410891 00000 n +0000411064 00000 n +0000411248 00000 n +0000411421 00000 n +0000411594 00000 n +0000411767 00000 n +0000411940 00000 n +0000412113 00000 n +0000412286 00000 n +0000412459 00000 n +0000412632 00000 n +0000412805 00000 n +0000412978 00000 n +0000413151 00000 n +0000413324 00000 n +0000413497 00000 n +0000413670 00000 n +0000413843 00000 n +0000414016 00000 n +0000414189 00000 n +0000414362 00000 n +0000414535 00000 n +0000414708 00000 n +0000414881 00000 n +0000415054 00000 n +0000415227 00000 n +0000415400 00000 n +0000415573 00000 n +0000415746 00000 n +0000415919 00000 n +0000416092 00000 n +0000416265 00000 n +0000416438 00000 n +0000416611 00000 n +0000416784 00000 n +0000416957 00000 n +0000417130 00000 n +0000417303 00000 n +0000417476 00000 n +0000417649 00000 n +0000417822 00000 n +0000417995 00000 n +0000418168 00000 n +0000418341 00000 n +0000418514 00000 n +0000418687 00000 n +0000418860 00000 n +0000419033 00000 n +0000419206 00000 n +0000419379 00000 n +0000419552 00000 n +0000419725 00000 n +0000419898 00000 n +0000420071 00000 n +0000420244 00000 n +0000420417 00000 n +0000420590 00000 n +0000420763 00000 n +0000420936 00000 n +0000421109 00000 n +0000421282 00000 n +0000421455 00000 n +0000421628 00000 n +0000421801 00000 n +0000421974 00000 n +0000422147 00000 n +0000422331 00000 n +0000422515 00000 n +0000422688 00000 n +0000422872 00000 n +0000423056 00000 n +0000423229 00000 n +0000423402 00000 n +0000423575 00000 n +0000423748 00000 n +0000423921 00000 n +0000424094 00000 n +0000424267 00000 n +0000424440 00000 n +0000424624 00000 n +0000424700 00000 n +0000424873 00000 n +0000425046 00000 n +0000425219 00000 n +0000425392 00000 n +0000425565 00000 n +0000425738 00000 n +0000425911 00000 n +0000426084 00000 n +0000426257 00000 n +0000426430 00000 n +0000426603 00000 n +0000426776 00000 n +0000426949 00000 n +0000427122 00000 n +0000427295 00000 n +0000427479 00000 n +0000427652 00000 n +0000427825 00000 n +0000427998 00000 n +0000428171 00000 n +0000428344 00000 n +0000428517 00000 n +0000428690 00000 n +0000428863 00000 n +0000429036 00000 n +0000429209 00000 n +0000429382 00000 n +0000429566 00000 n +0000429739 00000 n +0000429912 00000 n +0000430085 00000 n +0000430258 00000 n +0000430431 00000 n +0000430604 00000 n +0000430777 00000 n +0000430950 00000 n +0000431123 00000 n +0000431296 00000 n +0000431469 00000 n +0000431642 00000 n +0000431815 00000 n +0000431988 00000 n +0000432161 00000 n +0000432334 00000 n +0000432507 00000 n +0000432680 00000 n +0000432853 00000 n +0000433026 00000 n +0000433199 00000 n +0000433372 00000 n +0000433545 00000 n +0000433718 00000 n +0000433891 00000 n +0000434064 00000 n +0000434237 00000 n +0000434410 00000 n +0000434583 00000 n +0000434756 00000 n +0000434929 00000 n +0000435102 00000 n +0000435275 00000 n +0000435448 00000 n +0000435621 00000 n +0000435794 00000 n +0000435967 00000 n +0000436140 00000 n +0000436313 00000 n +0000436486 00000 n +0000436659 00000 n +0000436832 00000 n +0000437005 00000 n +0000437178 00000 n +0000437351 00000 n +0000437524 00000 n +0000437697 00000 n +0000437870 00000 n +0000438043 00000 n +0000438216 00000 n +0000438389 00000 n +0000438562 00000 n +0000438735 00000 n +0000438908 00000 n +0000439081 00000 n +0000439254 00000 n +0000439427 00000 n +0000439600 00000 n +0000439773 00000 n +0000439946 00000 n +0000440119 00000 n +0000440292 00000 n +0000440465 00000 n +0000440638 00000 n +0000440811 00000 n +0000440984 00000 n +0000441157 00000 n +0000441330 00000 n +0000441503 00000 n +0000441676 00000 n +0000441849 00000 n +0000442022 00000 n +0000442195 00000 n +0000442368 00000 n +0000442541 00000 n +0000442714 00000 n +0000442887 00000 n +0000443060 00000 n +0000443233 00000 n +0000443406 00000 n +0000443579 00000 n +0000443752 00000 n +0000443925 00000 n +0000444098 00000 n +0000444271 00000 n +0000444444 00000 n +0000444617 00000 n +0000444790 00000 n +0000444963 00000 n +0000445136 00000 n +0000445309 00000 n +0000445482 00000 n +0000445655 00000 n +0000445828 00000 n +0000446001 00000 n +0000446174 00000 n +0000446347 00000 n +0000446520 00000 n +0000446693 00000 n +0000446866 00000 n +0000447039 00000 n +0000447212 00000 n +0000447385 00000 n +0000447558 00000 n +0000447731 00000 n +0000447807 00000 n +0000447883 00000 n +0000447959 00000 n +0000448035 00000 n +0000448111 00000 n +0000448187 00000 n +0000448263 00000 n +0000448339 00000 n +0000448415 00000 n +0000448491 00000 n +0000448567 00000 n +0000448643 00000 n +0000448719 00000 n +0000448795 00000 n +0000448871 00000 n +0000448947 00000 n +0000449024 00000 n +0000449101 00000 n +0000449178 00000 n +0000449255 00000 n +0000449332 00000 n +0000449409 00000 n +0000449486 00000 n +0000449563 00000 n +0000449640 00000 n +0000449717 00000 n +0000449794 00000 n +0000449871 00000 n +0000449948 00000 n +0000450025 00000 n +0000450102 00000 n +0000450179 00000 n +0000450256 00000 n +0000450333 00000 n +0000450410 00000 n +0000450487 00000 n +0000450564 00000 n +0000450641 00000 n +0000450718 00000 n +0000450795 00000 n +0000450872 00000 n +0000450949 00000 n +0000451026 00000 n +0000451103 00000 n +0000451180 00000 n +0000451257 00000 n +0000451334 00000 n +0000451411 00000 n +0000451488 00000 n +0000451565 00000 n +0000451642 00000 n +0000451719 00000 n +0000451796 00000 n +0000451873 00000 n +0000451950 00000 n +0000452027 00000 n +0000452104 00000 n +0000452181 00000 n +0000452236 00000 n +0000452504 00000 n +0000452559 00000 n +0000452830 00000 n +0000453087 00000 n +0000453338 00000 n +0000453650 00000 n +0000454010 00000 n +0000454370 00000 n +0000454730 00000 n +0000455090 00000 n +0000455450 00000 n +0000455810 00000 n +0000456131 00000 n +0000456491 00000 n +0000456851 00000 n +0000457211 00000 n +0000457571 00000 n +0000457931 00000 n +0000458291 00000 n +0000458614 00000 n +0000458974 00000 n +0000459334 00000 n +0000459694 00000 n +0000460054 00000 n +0000460414 00000 n +0000460774 00000 n +0000461134 00000 n +0000461381 00000 n +0000461613 00000 n +0000461870 00000 n +0000462118 00000 n +0000524566 00000 n +0000596184 00000 n +0000596277 00000 n +0000596599 00000 n +0000596692 00000 n +0000597051 00000 n +0000597144 00000 n +0000597645 00000 n +0000597738 00000 n +0000598111 00000 n +0000598204 00000 n +0000598691 00000 n +0000598784 00000 n +0000599154 00000 n +0000599247 00000 n +0000599610 00000 n +0000599703 00000 n +0000600065 00000 n +0000600158 00000 n +0000600663 00000 n +0000600756 00000 n +0000601261 00000 n +0000601354 00000 n +0000602080 00000 n +0000602173 00000 n +0000602899 00000 n +0000602992 00000 n +0000603320 00000 n +0000603413 00000 n +0000604143 00000 n +0000604236 00000 n +0000604968 00000 n +0000605061 00000 n +0000605430 00000 n +0000605523 00000 n +0000605898 00000 n +0000605991 00000 n +0000606358 00000 n +0000606451 00000 n +0000606818 00000 n +0000625130 00000 n +0000645650 00000 n +0000654929 00000 n +0000661607 00000 n +0000661939 00000 n +0000662271 00000 n +0000662603 00000 n +0000662935 00000 n +0000663267 00000 n +0000663599 00000 n +0000663931 00000 n +0000664263 00000 n +0000664595 00000 n +0000664927 00000 n +0000665259 00000 n +0000665591 00000 n +0000665923 00000 n +0000666255 00000 n +0000666587 00000 n +0000666919 00000 n +0000667251 00000 n +0000667583 00000 n +0000667915 00000 n +0000668207 00000 n +0000668536 00000 n +0000668981 00000 n +0000669326 00000 n +0000669771 00000 n +0000670111 00000 n +0000670450 00000 n +0000670788 00000 n +0000671245 00000 n +0000671702 00000 n +0000672347 00000 n +0000672992 00000 n +0000673290 00000 n +0000673960 00000 n +0000674632 00000 n +0000674977 00000 n +0000675328 00000 n +0000675665 00000 n +trailer +<< +/Info 1 0 R +/Root 2 0 R +/Size 3053 +>> +startxref +676002 +%%EOF diff --git a/data/Piezo 6채널 측정 시 에러 코드.pdf b/data/Piezo 6채널 측정 시 에러 코드.pdf new file mode 100644 index 0000000..3abd3cb Binary files /dev/null and b/data/Piezo 6채널 측정 시 에러 코드.pdf differ diff --git a/data/curcuit/20305 VB0HW0100 (1).asc b/data/curcuit/20305 VB0HW0100 (1).asc new file mode 100644 index 0000000..fe27d56 --- /dev/null +++ b/data/curcuit/20305 VB0HW0100 (1).asc @@ -0,0 +1,3521 @@ +!PADS-POWERPCB-V9.0-METRIC-CP949! NETLIST FILE FROM PADS LOGIC VVX.2 +*REMARK* 20305 VB0HW0100.sch -- Mon Mar 09 17:28:45 2026 +*REMARK* + + +*PCB* GENERAL PARAMETERS OF THE PCB DESIGN + +MAXIMUMLAYER 4 Maximum routing layer + +*PART* ITEMS +R31 RES1005@1005 +C17 CAP1005@1005 +U2 OPA2836IDGSR@SOP50P490X110-10N +C18 CAP1005@1005 +J2 2026560021@2026560021 +R23 RES1005@1005 +R8 RES1005@1005 +U9 RECE.20279.001E.01@RECE.20279.001E.01 +R11 RES1005@1005 +C2 CAP1005@1005 +C30 CAP1608@1608 +C4 CAP1005@1005 +R25 RES1005@1005 +J4 217B-CA04@ATTEND_217B-CA04 +J1 ECV3-06-ICESPI@ECV3-06-ICESPI +C19 CAP1005@1005 +C16 CAP1005@1005 +C23 CAP1005@1005 +R28 RES1005@1005 +R42 RES1005@1005 +R6 RES1005@1005 +R12 RES1005@1005 +U5 MIC5528-3.3YMT@MIC5528-3.3YMT +C21 CAP1005@1005 +C22 CAP1005@1005 +C31 CAP1005@1005 +R14 RES1005@1005 +LED3 LED1608@LED1608 +C32 CAP1608@1608 +C20 CAP1005@1005 +R16 RES1005@1005 +R18 RES1005@1005 +U20 PESD5V0F1BLD_315@PESD5V0F1BLD315 +C15 CAP1005@1005 +C24 CAP1005@1005 +C5 CAP1608@1608 +C7 CAP1608@1608 +C10 CAP1608@1608 +C14 CAP1005@1005 +C12 CAP1005@1005 +C13 CAP1608@1608 +C37 CAP1608@1608 +C38 CAP1608@1608 +U23 ADL5513ACPZ-R7@QFN50P300X300X80-17N-D +C61 CAP1005@1005 +R19 RES1005@1005 +R29 RES1005@1005 +C64 CAP1005@1005 +C67 CAP1005@1005 +R20 RES1005@1005 +C72 CAP1005@1005 +C29 CAP1608@1608 +L4 IND1608@1608 +L3 IND1005@1005 +Y1 FC-12M@FC-12M +R26 RES1005@1005 +R27 RES1005@1005 +Y2 FA-128_32MHZ@FA-128 +R35 RES1005@1005 +C51 CAP1005@1005 +L1 IND1608@1608 +C42 CAP1608@1608 +C36 CAP1005@1005 +R24 RES1005@1005 +H2 M2_HOLE@HOLE-1.8 +C43 CAP1608@1608 +C39 CAP1608@1608 +T5 TEST_POINT@TP +H3 M2_HOLE@HOLE-1.8 +C28 CAP1005@1005 +C27 CAP1005@1005 +R36 RES1005@1005 +C26 CAP1005@1005 +C25 CAP1005@1005 +R39 RES1005@1005 +C40 CAP1005@1005 +C41 CAP1005@1005 +C44 CAP1608@1608 +C45 CAP1608@1608 +C46 CAP1608@1608 +C47 CAP1608@1608 +C48 CAP1005@1005 +C49 CAP1005@1005 +U16 W25Q32RVXHJQ_TR@SON50P300X200X40-9N +C50 CAP1608@1608 +C103 CAP1005@1005 +R83 RES1005@1005 +C52 CAP1608@1608 +R30 RES1005@1005 +C34 CAP1005@1005 +R40 RES1005@1005 +L5 IND1005@1005 +U6 PRG18BC1R0MM1RB@THRMC1608X95N +U7 PRG18BC1R0MM1RB@THRMC1608X95N +L6 IND1608@1608 +SW2 A03-05@A03-05 +C53 CAP1005@1005 +R17 RES1005@1005 +R41 RES1005@1005 +C54 CAP1005@1005 +C55 CAP1005@1005 +C56 CAP1608@1608 +R43 RES1005@1005 +LED4 LED1608@LED1608 +U4 PMFPB8032XP@PMFPB8032XP +P1 AXT510124@PANASONIC_AXT510124 +R15 RES1005@1005 +H4 M2_HOLE@HOLE-1.8 +U10 ICM-42670-P@ICM-42675-P +U27 MD1822K6-G@QFN50P300X300X100-17N-D +C35 CAP1005@1005 +C8 CAP1608@1608 +C9 CAP1005@1005 +H1 M2_HOLE@HOLE-1.8 +JP1 TP_DBL@TP_DBL +R65 RES1005@1005 +D3 DAP222WM@EMD3F-DAP222WM +D4 BAS3005B-02V@SC79-BAS3005B-02V +U1 PRTR5V0U2X@SOT143B-PRTR5V0U2X +R34 RES1005@1005 +U22 TMP235-Q1@SOT-23 +L2 IND1608@1608 +R21 RES1005@1005 +R22 RES1005@1005 +U8 SN74LVC1G04DRY2@USON-SN74LVC1G04DRY2 +R33 RES1005@1005 +R32 RES1005@1005 +R37 RES1005@1005 +R4 RES1005@1005 +U30 TC7920K6-G@SON50P400X400X100-13N-D +R38 RES1005@1005 +C62 CAP1005@1005 +C65 CAP1005@1005 +C70 CAP1005@1005 +C74 CAP1005@1005 +U26 NRF52840_QIAA_R@NRF52840-QIAA-F-R7 +U3 MCP73838@MSOP10-MCP73838 +C73 CAP1005@1005 +C11 CAP1608@1608 +C75 CAP1005@1005 +U31 MAX14778ETP+@QFN65P500X500X80-21N +C76 CAP1005@1005 +C77 CAP1005@1005 +R58 RES1005@1005 +C33 CAP1608@1608 +R73 RES1005@1005 +R63 RES1005@1005 +U34 MD0100N8-G@AMP_PHA-1 +C80 CAP1005@1005 +C81 CAP1005@1005 +PZT_PE TEST_POINT@TP +PZT_DMP TEST_POINT@TP +PZT_PIN TEST_POINT@TP +PZT_NIN TEST_POINT@TP +C82 CAP1005@1005 +C83 CAP1005@1005 +PZT_T/R TEST_POINT@TP +C84 CAP1005@1005 +L10 IND1608@1608 +L11 IND1608@1608 +L12 IND1608@1608 +L14 IND1608@1608 +C1 CAP1608@1608 +U32 LT3463EDDPBF@DFN-10_DD +C3 CAP1608@1608 +C6 CAP1608@1608 +R7 RES1005@1005 +L13 IND1608@1608 +R10 RES1005@1005 +R9 RES1005@1005 +R5 RES1005@1005 +L15 IND1608@1608 +TH1 THER1608@TH1608-NB21K00103KBB +R13 RES1005@1005 +C85 CAP1005@1005 +C86 CAP1005@1005 +D1 B0540WS-TP@SOD2512X115N +R66 RES1005@1005 +R67 RES1005@1005 +C87 CAP1005@1005 +R68 RES1005@1005 +R69 RES1005@1005 +R70 RES1005@1005 +R71 RES1005@1005 +C88 CAP1005@1005 +C89 CAP1005@1005 +C79 CAP1005@1005 +L16 IND1608@1608 +U33 MCP1804T-A002I_OT@SOT95P270X145-5N +C90 CAP1005@1005 +C91 CAP1005@1005 +C98 CAP1005@1005 +R1 RES1005@1005 +R2 RES1005@1005 +LED1 LED1608@LED1608 +LED2 LED1608@LED1608 +L17 IND1608@1608 +R3 RES1005@1005 +R74 RES1005@1005 +C110 CAP1005@1005 +R77 RES1005@1005 +C119 CAP1005@1005 +R79 RES1005@1005 +R80 RES1005@1005 +U37 ADC121S051CIMF_NOPB@SOT95P280X145-6N +C78 CAP1005@1005 +C93 CAP1005@1005 +C95 CAP1005@1005 +T1 TEST_POINT@TP +T2 TEST_POINT@TP +T3 TEST_POINT@TP +L19 IND1608@1608 +U38 LM27762DSSR@SON50P200X300X80-13N-D +U42 MIC5528-3.3YMT@MIC5528-3.3YMT +C96 CAP1005@1005 +R64 RES1005@1005 +R72 RES1005@1005 +R76 RES1005@1005 +R78 RES1005@1005 +R81 RES1005@1005 +L20 IND1608@1608 +R82 RES1005@1005 +L22 IND1608@1608 +L23 IND1608@1608 +C102 CAP1005@1005 +U41 MIC5528-3.3YMT@MIC5528-3.3YMT +C104 CAP1608@1608 +L32 IND1608@1608 +R61 RES1005@1005 +C121 CAP1005@1005 +R84 RES1005@1005 +C105 CAP1005@1005 +R87 RES1005@1005 +C106 CAP1005@1005 +T4 TEST_POINT@TP +T6 TEST_POINT@TP +CS TEST_POINT@TP +MISO TEST_POINT@TP +SCLK TEST_POINT@TP +R90 RES1005@1005 +C109 CAP1005@1005 +C113 CAP1608@1608 +L31 IND1608@1608 +C114 CAP1005@1005 +C115 CAP1608@1608 +C116 CAP1608@1608 +*NET* +*SIGNAL* 2NDAMP_IN +C78.1 U2.7 R82.2 +*SIGNAL* $$$21938 +U31.1 R11.2 +*SIGNAL* $$$26420 +C51.2 U23.4 U23.1 L1.1 C42.1 +*SIGNAL* 2NDAMP_OUT +U2.9 R80.2 T4.1 C40.2 +*SIGNAL* GND +C16.2 C17.2 C18.1 Y2.4 Y2.2 +C21.1 C22.1 C28.1 C19.1 U26.B7 +C20.1 C31.1 C24.1 C29.2 C30.2 +C32.2 C36.1 C26.1 C14.1 C25.1 +U26.F23 C27.1 U10.7 U10.6 C34.1 +C33.2 C35.1 U10.1 U10.2 U10.3 +U10.10 U10.11 J1.5 C72.1 C73.1 +U9.1 U9.2 C15.1 U26.74 U16.4 +U16.9 C53.1 R41.2 C11.2 U5.3 +C8.2 R17.2 C9.2 R15.2 R21.2 +U5.5 U3.5 TH1.2 R7.2 R13.2 +R10.2 C6.2 C1.2 J2.2 U1.1 +C3.2 R29.1 C23.1 C121.1 R4.2 +C65.1 U22.3 C119.1 J4.A1/B12 J4.A12/B1 +J4.SH2 J4.SH1 R37.2 R38.2 U27.17 +U27.3 U27.6 U27.7 U27.14 U30.12 +U30.9 U30.13 U31.3 C77.1 C82.2 +C48.1 C76.1 C84.1 C85.2 U32.11 +R71.2 C88.2 C89.2 U33.2 C90.2 +C91.2 C79.2 C104.2 U42.3 R65.2 +C98.2 U42.5 C114.2 C115.2 C81.1 +C80.1 C38.2 C47.2 C83.2 C49.1 +R6.2 P1.8 P1.4 P1.7 P1.3 +U41.3 C113.2 U41.5 C116.2 R77.1 +R79.1 U37.2 C95.1 U38.13 C10.2 +R76.1 R81.2 U38.4 C52.2 C7.2 +C5.2 C102.1 R83.2 C105.2 C106.2 +C109.2 R3.1 C93.1 R82.1 C4.1 +C2.1 U20.2 C12.1 C13.2 C37.2 +U23.17 C64.1 U23.10 U23.5 U23.6 +U23.7 U23.8 U23.16 U23.15 U23.13 +C67.2 R26.2 R27.1 C51.1 C39.2 +R36.2 C41.2 C42.2 C43.2 C44.2 +C45.2 C46.2 C50.2 C54.1 C55.1 +C56.2 J2.3 J2.4 U5.7 U8.3 +U3.11 U42.7 +*SIGNAL* PREAMP_OUT +R74.2 C103.2 T2.1 U2.1 +*SIGNAL* SWDIO +U26.AC24 J1.2 +*SIGNAL* INT2_ICM +U26.G1 R31.2 U10.9 +*SIGNAL* SWDCLK +U26.AA24 J1.4 +*SIGNAL* $$$7457 +U23.2 C61.1 +*SIGNAL* $$$3365 +R43.2 LED4.1 +*SIGNAL* $$$7588 +R19.2 R20.1 U23.12 +*SIGNAL* $$$4037 +J4.A4/B9 U6.1 J4.A9/B4 +*SIGNAL* $$$3654 +U42.2 L32.1 U42.1 +*SIGNAL* PWR_MCU_EN +R17.1 U5.4 C9.1 R22.2 D3.1 +*SIGNAL* $$$14862 +C64.2 U23.14 +*SIGNAL* \SPI_CS_LOCK-IN +U26.AD8 +*SIGNAL* SYNCO +U26.AD12 +*SIGNAL* ADC_RDATA_N +U26.B13 +*SIGNAL* ADC_RDATA_P +U26.A12 +*SIGNAL* XL1 +C16.1 Y1.2 U26.D2 +*SIGNAL* I2C_SCL_ICM +U26.B15 U10.13 R34.2 +*SIGNAL* XL2 +C17.1 Y1.1 U26.F2 +*SIGNAL* $$$25958 +L3.2 U26.E24 C14.2 C15.2 U26.B5 +*SIGNAL* VDD_BAT +C6.1 J2.1 U3.10 U4.4 R28.2 +*SIGNAL* $$$22393 +R90.2 C109.1 U38.12 U38.8 +*SIGNAL* SPI_SCK +U26.AC9 U16.6 R18.1 +*SIGNAL* $$$32490 +R23.2 LED3.1 +*SIGNAL* $$$15263 +U23.3 C67.1 +*SIGNAL* SPI_MOSI +U26.AC11 U16.5 +*SIGNAL* VBUS_IN +U1.4 L2.1 U6.2 +*SIGNAL* $$$15328 +R20.2 R26.1 U23.11 +*SIGNAL* $$$24450 +U3.8 R5.2 R10.1 +*SIGNAL* $$$20152 +R35.1 R27.2 U23.9 +*SIGNAL* RXD +U26.M2 J1.6 +*SIGNAL* TXD +U26.L1 J1.3 +*SIGNAL* $$$16529 +U26.H23 C25.2 L5.2 +*SIGNAL* ADC_TEMP +U26.K2 U22.2 C119.2 +*SIGNAL* I2C_SCL_NIR +U26.L24 R25.1 +*SIGNAL* PWR_HOLD +U26.N1 D4.2 +*SIGNAL* I2C_SDA_NIR +U26.J24 R24.1 +*SIGNAL* $$$22557 +CS.1 U37.6 R8.2 R14.2 +*SIGNAL* VBUS +U4.5 JP1.2 R15.1 U3.1 U3.7 +R5.1 C1.1 LED2.2 LED1.2 L2.2 +*SIGNAL* SPI_MISO +U26.AD10 U16.2 R16.1 +*SIGNAL* $$$5070 +U4.3 U4.6 U4.7 U4.8 U7.1 +*SIGNAL* INT1_ICM +U10.4 R32.2 U26.A16 +*SIGNAL* $$$22594 +MISO.1 U37.5 R16.2 +*SIGNAL* $$$6539 +L4.2 L3.1 +*SIGNAL* $$$12824 +R19.1 R87.2 +*SIGNAL* ANT +C26.2 U9.3 L5.1 C28.2 C27.2 +*SIGNAL* $$$12989 +R36.1 R39.2 C40.1 +*SIGNAL* $$$3572 +U27.16 U27.1 PZT_DMP.1 R12.2 +*SIGNAL* $$$25431 +U26.C1 C18.2 +*SIGNAL* $$$6537 +L4.1 U26.B3 +*SIGNAL* VCC_NRF +C32.1 U26.AD2 +*SIGNAL* $$$22610 +SCLK.1 U37.4 R18.2 +*SIGNAL* $$$12990 +R39.1 C41.1 T5.1 C61.2 +*SIGNAL* I2C_SDA_ICM +U26.A14 U10.14 R33.2 +*SIGNAL* $$$85 +U3.2 C3.1 +*SIGNAL* $$$1313 +U3.6 R7.1 +*SIGNAL* \WP_FLASH +U26.H2 U16.3 R41.1 +*SIGNAL* $$$18796 +R38.1 J4.B5 +*SIGNAL* $$$18801 +R37.1 J4.A5 +*SIGNAL* $$$1329 +TH1.1 R13.1 R9.2 +*SIGNAL* $$$16790 +R9.1 U3.9 +*SIGNAL* $$$3604 +U27.5 PZT_NIN.1 R40.2 +*SIGNAL* $$$3606 +U27.4 PZT_PIN.1 R30.2 +*SIGNAL* ADC_BAT +U26.J1 R28.1 R29.2 C23.2 +*SIGNAL* VDD_MAIN +SW2.1 C8.1 U7.2 U5.6 U42.6 +C115.1 U41.6 C116.1 C54.2 +*SIGNAL* $$$26274 +U26.N24 C24.2 +*SIGNAL* PZT_EN_MUXB +U26.AC19 U31.16 +*SIGNAL* \SPI_CS_FLASH +U26.AD20 R42.1 U16.1 +*SIGNAL* $$$20341 +JP1.1 U4.1 +*SIGNAL* $$$18101 +R61.1 C121.2 D3.3 +*SIGNAL* PWR_I/R_EN +U26.T2 +*SIGNAL* LIGHT_ON +U26.AD18 +*SIGNAL* $$$27542 +U26.AC5 C30.1 +*SIGNAL* $$$18102 +D3.2 U8.2 R21.1 +*SIGNAL* BUTTON_CHECK +U26.P2 U8.4 +*SIGNAL* $$$18103 +R22.1 D4.1 +*SIGNAL* LED_BLE +U26.U1 R23.1 +*SIGNAL* NIRLED_SEL0 +U26.U24 +*SIGNAL* NIRLED_SEL1 +U26.T23 +*SIGNAL* $$$4032 +U5.2 U5.1 L6.1 +*SIGNAL* GND_RX +U41.7 +*SIGNAL* $$$14845 +U26.D23 C72.2 +*SIGNAL* $$$14940 +C73.2 U26.A18 +*SIGNAL* $$$3432 +R61.2 R4.1 SW2.2 +*SIGNAL* FUNCTION_LED +U26.A10 R43.1 +*SIGNAL* $$$20788 +L23.1 U2.4 C102.2 C37.1 +*SIGNAL* ADC_PRESSURE +U26.A8 +*SIGNAL* $$$14839 +U27.8 C62.1 +*SIGNAL* $$$14847 +C62.2 U30.5 +*SIGNAL* +3.3V_M +C19.2 U26.A22 U26.AD23 C29.1 U26.Y2 +R25.2 U26.AD14 C33.1 C35.2 R33.1 +R34.1 R32.1 U10.12 C34.2 U10.5 +R31.1 R24.2 J1.1 U10.8 C20.2 +U26.B1 C31.2 U26.W1 C36.2 U16.7 +U16.8 C53.2 R42.2 L6.2 C11.1 +LED3.2 LED4.2 U8.6 +*SIGNAL* STAT1_1 +R1.2 U3.3 +*SIGNAL* STAT1_2 +U3.4 R2.2 +*SIGNAL* $$$30190 +R1.1 LED1.1 +*SIGNAL* $$$30191 +R2.1 LED2.1 +*SIGNAL* $$$14861 +C70.1 U27.9 +*SIGNAL* NIR_WAV_SEL0 +U26.Y23 +*SIGNAL* $$$14864 +C70.2 U30.3 +*SIGNAL* $$$14885 +U27.12 C74.1 +*SIGNAL* $$$14887 +C74.2 U30.2 +*SIGNAL* ADC_AGC +U26.B9 +*SIGNAL* AGC_SW +U26.AD16 +*SIGNAL* $$$14896 +U27.13 C75.1 +*SIGNAL* $$$14902 +C75.2 U30.1 +*SIGNAL* $$$25289 +U30.6 C82.1 L11.1 C48.2 +*SIGNAL* PZT_-20V +L12.2 D1.A R68.1 C89.1 +*SIGNAL* $$$25231 +U27.10 U27.11 L10.1 U27.2 C81.2 +C80.2 +*SIGNAL* PZT_PE +U26.AC21 U27.15 R6.1 PZT_PE.1 +*SIGNAL* PZT_DMP +U26.AD22 R12.1 +*SIGNAL* PZT_P_PULSE +U26.P23 R30.1 +*SIGNAL* PZT_N_PULSE +U26.R24 R40.1 +*SIGNAL* $$$2625 +U31.2 C77.2 +*SIGNAL* PD_SEL0 +U26.B17 +*SIGNAL* $$$2626 +U31.4 U31.21 C76.2 +*SIGNAL* $$$2708 +U30.11 U30.8 U30.10 R58.1 U30.7 +*SIGNAL* PZT_RX +R58.2 PZT_T/R.1 U31.5 R11.1 U34.1 +*SIGNAL* $$$25617 +L22.1 U2.10 U2.5 U2.6 C93.2 +C13.1 +*SIGNAL* $$$24188 +R3.2 U2.2 R74.1 +*SIGNAL* $$$24714 +R77.2 T1.1 C110.1 U2.3 +*SIGNAL* PD_SEL1 +U26.B19 +*SIGNAL* $$$5663 +U34.3 U20.1 C110.2 +*SIGNAL* $$$7726 +R79.2 U2.8 R80.1 +*SIGNAL* $$$6258 +U31.9 P1.6 +*SIGNAL* $$$6259 +U31.8 P1.5 +*SIGNAL* $$$6260 +U31.7 P1.2 +*SIGNAL* PZT_CH_SEL1 +U26.B11 U31.14 U31.12 +*SIGNAL* PZT_CH_SEL0 +U26.A20 U31.15 U31.11 +*SIGNAL* $$$6261 +U31.6 P1.1 +*SIGNAL* PZT_EN_MUXA +U26.AC17 U31.10 +*SIGNAL* PZT_+10V +L10.2 U33.5 C91.1 +*SIGNAL* PZT_+20V +L11.2 U32.1 R69.1 C88.1 L17.1 +*SIGNAL* $$$6264 +U31.19 P1.10 +*SIGNAL* $$$6265 +U31.20 P1.9 +*SIGNAL* $$$13633 +U33.4 C79.1 R73.2 +*SIGNAL* NIR_WAV_SEL1 +U26.W24 +*SIGNAL* NIR_WAV_SEL2 +U26.V23 +*SIGNAL* $$$13703 +R63.1 U32.8 U32.9 C114.1 +*SIGNAL* $$$26435 +C21.2 Y2.1 U26.A23 +*SIGNAL* $$$26436 +C22.2 Y2.3 U26.B24 +*SIGNAL* $$$25419 +C84.2 L14.1 U31.13 +*SIGNAL* $$$25322 +C83.1 U30.4 C49.2 L12.1 +*SIGNAL* $$$26511 +C95.2 U37.1 C39.1 L19.1 +*SIGNAL* +3.3V_PZT_TX +U22.1 C65.2 L14.2 R73.1 R63.2 +L32.2 C104.1 C47.1 L16.2 +*SIGNAL* $$$19431 +U32.2 L13.2 +*SIGNAL* $$$19433 +L15.2 C86.1 U32.4 +*SIGNAL* $$$25510 +U32.3 L15.1 C85.1 L16.1 L13.1 +C38.1 +*SIGNAL* $$$19894 +U32.5 C86.2 D1.C +*SIGNAL* $$$27698 +R66.1 U32.7 +*SIGNAL* PZT_PWR_EN +U26.R1 R65.1 U42.4 C98.1 U41.4 +*SIGNAL* $$$27702 +R66.2 U32.6 R67.2 C87.1 +*SIGNAL* $$$2967 +C87.2 R67.1 R68.2 +*SIGNAL* $$$3237 +R69.2 R70.1 +*SIGNAL* $$$3259 +R70.2 R71.1 U32.10 +*SIGNAL* $$$3655 +U41.2 L31.1 U41.1 C56.1 +*SIGNAL* +3.3V_PZT_RX +L31.2 C113.1 R90.1 R8.1 R35.2 +C45.1 L1.2 C46.1 L19.2 C50.1 +L20.2 C55.2 +*SIGNAL* +2.75V_CP +U38.11 R72.2 L22.2 C2.2 C7.1 +C44.1 +*SIGNAL* -2.75V_CP +U38.6 R78.1 C5.1 L23.2 C4.2 +C43.1 +*SIGNAL* $$$14934 +C96.1 U38.10 +*SIGNAL* $$$14941 +C96.2 U38.9 +*SIGNAL* $$$15655 +U38.1 R64.2 +*SIGNAL* $$$17850 +U38.3 R64.1 L20.1 C10.1 C12.2 +*SIGNAL* $$$16265 +R72.1 U38.2 R76.2 +*SIGNAL* $$$16444 +U38.7 R81.1 R78.2 +*SIGNAL* $$$16815 +C52.1 U38.5 +*SIGNAL* $$$20303 +R83.1 R84.2 C103.1 +*SIGNAL* $$$20306 +R84.1 C105.1 T3.1 C78.2 +*SIGNAL* \PZT_SPI_CS +U26.AC15 R14.1 +*SIGNAL* $$$22044 +R87.1 C106.1 U37.3 T6.1 +*SIGNAL* $$$25374 +U33.1 L17.2 C90.1 + +*MISC* MISCELLANEOUS PARAMETERS + +*REMARK* PARENT_KEYWORD PARENT_VALUE +*REMARK* [ { +*REMARK* CHILD_KEYWORD CHILD_VALUE +*REMARK* [ CHILD_KEYWORD CHILD_VALUE +*REMARK* [ { +*REMARK* GRAND_CHILD_KEYWORD GRAND_CHILD_VALUE [...] +*REMARK* } ]] +*REMARK* } ] + +LAYER METRIC +{ +LAYER 0 +{ +LAYER_THICKNESS 0 +DIELECTRIC 3.300000 +} +LAYER 1 +{ +LAYER_NAME Top Component +LAYER_TYPE ROUTING +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +ASSOCIATED_SILK_SCREEN Silkscreen Top +ASSOCIATED_PASTE_MASK Paste Mask Top +ASSOCIATED_SOLDER_MASK Solder Mask Top +ASSOCIATED_ASSEMBLY Assembly Drawing Top +COMPONENT Y +ROUTABLE Y +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0.254 +COPPER_THICKNESS 0.03429 +DIELECTRIC 4.300000 +COST 0 +} +LAYER 2 +{ +LAYER_NAME Inner Layer 2 +LAYER_TYPE ROUTING +PLANE NONE +ROUTING_DIRECTION VERTICAL +ROUTABLE Y +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0.254 +COPPER_THICKNESS 0.03429 +DIELECTRIC 4.300000 +COST 0 +} +LAYER 3 +{ +LAYER_NAME Inner Layer 3 +LAYER_TYPE ROUTING +PLANE NONE +ROUTING_DIRECTION HORIZONTAL +ROUTABLE Y +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0.254 +COPPER_THICKNESS 0.03429 +DIELECTRIC 4.300000 +COST 0 +} +LAYER 4 +{ +LAYER_NAME Bottom Component +LAYER_TYPE ROUTING +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +ASSOCIATED_SILK_SCREEN Silkscreen Bottom +ASSOCIATED_PASTE_MASK Paste Mask Bottom +ASSOCIATED_SOLDER_MASK Solder Mask Bottom +ASSOCIATED_ASSEMBLY Assembly Drawing Bottom +COMPONENT Y +ROUTABLE Y +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0.03429 +DIELECTRIC 3.300000 +COST 0 +} +LAYER 5 +{ +LAYER_NAME Layer_5 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION HORIZONTAL +ENABLED Y +LAYER_THICKNESS 0.254 +COPPER_THICKNESS 0.03429 +DIELECTRIC 4.300000 +COST 0 +} +LAYER 6 +{ +LAYER_NAME Layer_6 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +ASSOCIATED_SILK_SCREEN Silkscreen Bottom +ASSOCIATED_PASTE_MASK Paste Mask Bottom +ASSOCIATED_SOLDER_MASK Solder Mask Bottom +ASSOCIATED_ASSEMBLY Assembly Drawing Bottom +COMPONENT Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0.03429 +DIELECTRIC 3.300000 +COST 0 +} +LAYER 7 +{ +LAYER_NAME Layer_7 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 8 +{ +LAYER_NAME Layer_8 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 9 +{ +LAYER_NAME Layer_9 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 10 +{ +LAYER_NAME Layer_10 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 11 +{ +LAYER_NAME Layer_11 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 12 +{ +LAYER_NAME Layer_12 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 13 +{ +LAYER_NAME Layer_13 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 14 +{ +LAYER_NAME Layer_14 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 15 +{ +LAYER_NAME Layer_15 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 16 +{ +LAYER_NAME Layer_16 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 17 +{ +LAYER_NAME Layer_17 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 18 +{ +LAYER_NAME Layer_18 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 19 +{ +LAYER_NAME Layer_19 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 20 +{ +LAYER_NAME Layer_20 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 21 +{ +LAYER_NAME Solder Mask Top +LAYER_TYPE SOLDER_MASK +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 22 +{ +LAYER_NAME Paste Mask Bottom +LAYER_TYPE PASTE_MASK +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 23 +{ +LAYER_NAME Paste Mask Top +LAYER_TYPE PASTE_MASK +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 24 +{ +LAYER_NAME Drill Drawing +LAYER_TYPE DRILL +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 25 +{ +LAYER_NAME Layer_25 +LAYER_TYPE UNASSIGNED +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 26 +{ +LAYER_NAME Silkscreen Top +LAYER_TYPE SILK_SCREEN +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 27 +{ +LAYER_NAME Assembly Drawing Top +LAYER_TYPE ASSEMBLY +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 28 +{ +LAYER_NAME Solder Mask Bottom +LAYER_TYPE SOLDER_MASK +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 29 +{ +LAYER_NAME Silkscreen Bottom +LAYER_TYPE SILK_SCREEN +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +LAYER 30 +{ +LAYER_NAME Assembly Drawing Bottom +LAYER_TYPE ASSEMBLY +PLANE NONE +ROUTING_DIRECTION NO_PREFERENCE +VISIBLE Y +SELECTABLE Y +ENABLED Y +LAYER_THICKNESS 0 +COPPER_THICKNESS 0 +DIELECTRIC 0.000000 +COST 0 +} +} +*REMARK* PARENT_KEYWORD PARENT_VALUE +*REMARK* [ { +*REMARK* CHILD_KEYWORD CHILD_VALUE +*REMARK* [ CHILD_KEYWORD CHILD_VALUE +*REMARK* [ { +*REMARK* GRAND_CHILD_KEYWORD GRAND_CHILD_VALUE [...] +*REMARK* } ]] +*REMARK* } ] + +RULES_SECTION METRIC +{ +NET_CLASS DATA +DESIGN RULES +{ +RULE_SET (1) +{ +FOR : +{ +DEFAULT : +} +AGAINST : +{ +DEFAULT : +} +LAYER 0 +CLEARANCE_RULE : +{ +TRACK_TO_TRACK 0.1 +VIA_TO_TRACK 0.1 +VIA_TO_VIA 0.1 +PAD_TO_TRACK 0.1 +PAD_TO_VIA 0.1 +PAD_TO_PAD 0.1 +SMD_TO_TRACK 0.1 +SMD_TO_VIA 0.1 +SMD_TO_PAD 0.1 +SMD_TO_SMD 0.1 +COPPER_TO_TRACK 0.1 +COPPER_TO_VIA 0.1 +COPPER_TO_PAD 0.1 +COPPER_TO_SMD 0.1 +COPPER_TO_COPPER 0.1 +TEXT_TO_TRACK 0.1 +TEXT_TO_VIA 0.1 +TEXT_TO_PAD 0.1 +TEXT_TO_SMD 0.1 +OUTLINE_TO_TRACK 0.2 +OUTLINE_TO_VIA 0.2 +OUTLINE_TO_PAD 0.2 +OUTLINE_TO_SMD 0.2 +OUTLINE_TO_COPPER 0.2 +DRILL_TO_TRACK 0.1 +DRILL_TO_VIA 0.1 +DRILL_TO_PAD 0.1 +DRILL_TO_SMD 0.1 +DRILL_TO_COPPER 0.1 +SAME_NET_SMD_TO_VIA 0.1 +SAME_NET_SMD_TO_CRN 0.1 +SAME_NET_VIA_TO_VIA 0.1 +SAME_NET_PAD_TO_CRN 0.1 +MIN_TRACK_WIDTH 0.1 +REC_TRACK_WIDTH 0.1 +MAX_TRACK_WIDTH 1 +DRILL_TO_DRILL 0.1 +BODY_TO_BODY 0.1 +SAME_NET_TRACK_TO_CRN 0.1 +} +} +RULE_SET (2) +{ +FOR : +{ +DEFAULT : +} +AGAINST : +{ +DEFAULT : +} +LAYER 0 +ROUTE_RULE : +{ +LENGTH_MINIMIZATION_TYPE 1 +TRACE_SHARE Y +VIA_SHARE Y +AUTO_ROUTE Y +RIPUP Y +SHOVE Y +ROUTE_PRIORITY 3 +MAX_NUMBER_OF_VIAS -1 +VALID_LAYER 1 +VALID_LAYER 2 +VALID_LAYER 3 +VALID_LAYER 4 +VALID_VIA_TYPE MICROVIA +VALID_VIA_TYPE STANDARDVIA +VALID_VIA_TYPE NOPLATED +VALID_VIA_TYPE GUIDEHOLE +} +} +RULE_SET (3) +{ +FOR : +{ +DEFAULT : +} +AGAINST : +{ +DEFAULT : +} +LAYER 0 +HIGH_SPEED_RULE : +{ +MIN_LENGTH 0 +MAX_LENGTH 1269.99996 +STUB_LENGTH 0 +PARALLEL_LENGTH 25.4 +PARALLEL_GAP 5.08 +TANDEM_LENGTH 25.4 +TANDEM_GAP 5.08 +MIN_DELAY 0.000000 +MAX_DELAY 10.000000 +MIN_CAPACITANCE 0.000000 +MAX_CAPACITANCE 10.000000 +MIN_IMPEDANCE 50.000000 +MAX_IMPEDANCE 150.000000 +SHIELD_NET * +SHIELD_GAP 5.08 +MATCH_LENGTH_TOLERANCE 5.08 +} +} +RULE_SET (4) +{ +FOR : +{ +NET VDD_BAT +} +AGAINST : +{ +DEFAULT : +} +LAYER 0 +CLEARANCE_RULE : +{ +TRACK_TO_TRACK 0.1 +VIA_TO_TRACK 0.1 +VIA_TO_VIA 0.1 +PAD_TO_TRACK 0.1 +PAD_TO_VIA 0.1 +PAD_TO_PAD 0.1 +SMD_TO_TRACK 0.1 +SMD_TO_VIA 0.1 +SMD_TO_PAD 0.1 +SMD_TO_SMD 0.1 +COPPER_TO_TRACK 0.1 +COPPER_TO_VIA 0.1 +COPPER_TO_PAD 0.1 +COPPER_TO_SMD 0.1 +COPPER_TO_COPPER 0.1 +TEXT_TO_TRACK 0.1 +TEXT_TO_VIA 0.1 +TEXT_TO_PAD 0.1 +TEXT_TO_SMD 0.1 +OUTLINE_TO_TRACK 0.15 +OUTLINE_TO_VIA 0.15 +OUTLINE_TO_PAD 0.15 +OUTLINE_TO_SMD 0.15 +OUTLINE_TO_COPPER 0.15 +DRILL_TO_TRACK 0.1 +DRILL_TO_VIA 0.1 +DRILL_TO_PAD 0.1 +DRILL_TO_SMD 0.1 +DRILL_TO_COPPER 0.1 +SAME_NET_SMD_TO_VIA 0.1 +SAME_NET_SMD_TO_CRN 0.1 +SAME_NET_VIA_TO_VIA 0.1 +SAME_NET_PAD_TO_CRN 0.1 +MIN_TRACK_WIDTH 0.1 +REC_TRACK_WIDTH 0.2 +MAX_TRACK_WIDTH 1 +DRILL_TO_DRILL 0.1 +BODY_TO_BODY 0.1 +SAME_NET_TRACK_TO_CRN 0.1 +} +} +RULE_SET (5) +{ +FOR : +{ +NET ANT +NET $$$16529 +NET $$$3606 +} +AGAINST : +{ +DEFAULT : +} +LAYER 0 +CLEARANCE_RULE : +{ +TRACK_TO_TRACK 0.1 +VIA_TO_TRACK 0.1 +VIA_TO_VIA 0.1 +PAD_TO_TRACK 0.1 +PAD_TO_VIA 0.1 +PAD_TO_PAD 0.1 +SMD_TO_TRACK 0.1 +SMD_TO_VIA 0.1 +SMD_TO_PAD 0.1 +SMD_TO_SMD 0.1 +COPPER_TO_TRACK 0.1 +COPPER_TO_VIA 0.1 +COPPER_TO_PAD 0.1 +COPPER_TO_SMD 0.1 +COPPER_TO_COPPER 0.1 +TEXT_TO_TRACK 0.1 +TEXT_TO_VIA 0.1 +TEXT_TO_PAD 0.1 +TEXT_TO_SMD 0.1 +OUTLINE_TO_TRACK 0.2 +OUTLINE_TO_VIA 0.2 +OUTLINE_TO_PAD 0.2 +OUTLINE_TO_SMD 0.2 +OUTLINE_TO_COPPER 0.2 +DRILL_TO_TRACK 0.1 +DRILL_TO_VIA 0.1 +DRILL_TO_PAD 0.1 +DRILL_TO_SMD 0.1 +DRILL_TO_COPPER 0.1 +SAME_NET_SMD_TO_VIA 0.1 +SAME_NET_SMD_TO_CRN 0.1 +SAME_NET_VIA_TO_VIA 0.1 +SAME_NET_PAD_TO_CRN 0.1 +MIN_TRACK_WIDTH 0.1 +REC_TRACK_WIDTH 0.3 +MAX_TRACK_WIDTH 1 +DRILL_TO_DRILL 0.1 +BODY_TO_BODY 0.1 +SAME_NET_TRACK_TO_CRN 0.1 +} +} +RULE_SET (6) +{ +FOR : +{ +NET +3.3V_M +} +AGAINST : +{ +DEFAULT : +} +LAYER 0 +CLEARANCE_RULE : +{ +TRACK_TO_TRACK 0.1 +VIA_TO_TRACK 0.1 +VIA_TO_VIA 0.1 +PAD_TO_TRACK 0.1 +PAD_TO_VIA 0.1 +PAD_TO_PAD 0.1 +SMD_TO_TRACK 0.1 +SMD_TO_VIA 0.1 +SMD_TO_PAD 0.1 +SMD_TO_SMD 0.1 +COPPER_TO_TRACK 0.1 +COPPER_TO_VIA 0.1 +COPPER_TO_PAD 0.1 +COPPER_TO_SMD 0.1 +COPPER_TO_COPPER 0.1 +TEXT_TO_TRACK 0.1 +TEXT_TO_VIA 0.1 +TEXT_TO_PAD 0.1 +TEXT_TO_SMD 0.1 +OUTLINE_TO_TRACK 0.2 +OUTLINE_TO_VIA 0.2 +OUTLINE_TO_PAD 0.2 +OUTLINE_TO_SMD 0.2 +OUTLINE_TO_COPPER 0.2 +DRILL_TO_TRACK 0.1 +DRILL_TO_VIA 0.1 +DRILL_TO_PAD 0.1 +DRILL_TO_SMD 0.1 +DRILL_TO_COPPER 0.1 +SAME_NET_SMD_TO_VIA 0.1 +SAME_NET_SMD_TO_CRN 0.1 +SAME_NET_VIA_TO_VIA 0.1 +SAME_NET_PAD_TO_CRN 0.1 +MIN_TRACK_WIDTH 0.1 +REC_TRACK_WIDTH 0.3 +MAX_TRACK_WIDTH 1 +DRILL_TO_DRILL 0.1 +BODY_TO_BODY 0.1 +SAME_NET_TRACK_TO_CRN 0.1 +} +} +RULE_SET (7) +{ +FOR : +{ +NET GND +} +AGAINST : +{ +DEFAULT : +} +LAYER 0 +CLEARANCE_RULE : +{ +TRACK_TO_TRACK 0.1 +VIA_TO_TRACK 0.1 +VIA_TO_VIA 0.1 +PAD_TO_TRACK 0.1 +PAD_TO_VIA 0.1 +PAD_TO_PAD 0.1 +SMD_TO_TRACK 0.1 +SMD_TO_VIA 0.1 +SMD_TO_PAD 0.1 +SMD_TO_SMD 0.1 +COPPER_TO_TRACK 0.1 +COPPER_TO_VIA 0.1 +COPPER_TO_PAD 0.1 +COPPER_TO_SMD 0.1 +COPPER_TO_COPPER 0.1 +TEXT_TO_TRACK 0.1 +TEXT_TO_VIA 0.1 +TEXT_TO_PAD 0.1 +TEXT_TO_SMD 0.1 +OUTLINE_TO_TRACK 0.2 +OUTLINE_TO_VIA 0.2 +OUTLINE_TO_PAD 0.2 +OUTLINE_TO_SMD 0.2 +OUTLINE_TO_COPPER 0.2 +DRILL_TO_TRACK 0.1 +DRILL_TO_VIA 0.1 +DRILL_TO_PAD 0.1 +DRILL_TO_SMD 0.1 +DRILL_TO_COPPER 0.1 +SAME_NET_SMD_TO_VIA 0.1 +SAME_NET_SMD_TO_CRN 0.1 +SAME_NET_VIA_TO_VIA 0.1 +SAME_NET_PAD_TO_CRN 0.1 +MIN_TRACK_WIDTH 0.1 +REC_TRACK_WIDTH 0.2 +MAX_TRACK_WIDTH 1 +DRILL_TO_DRILL 0.1 +BODY_TO_BODY 0.1 +SAME_NET_TRACK_TO_CRN 0.1 +} +} +RULE_SET (8) +{ +FOR : +{ +NET ADC_BAT +NET VDD_BAT +NET $$$14940 +} +AGAINST : +{ +DEFAULT : +} +LAYER 0 +CLEARANCE_RULE : +{ +TRACK_TO_TRACK 0.1 +VIA_TO_TRACK 0.1 +VIA_TO_VIA 0.1 +PAD_TO_TRACK 0.1 +PAD_TO_VIA 0.1 +PAD_TO_PAD 0.1 +SMD_TO_TRACK 0.1 +SMD_TO_VIA 0.1 +SMD_TO_PAD 0.1 +SMD_TO_SMD 0.1 +COPPER_TO_TRACK 0.1 +COPPER_TO_VIA 0.1 +COPPER_TO_PAD 0.1 +COPPER_TO_SMD 0.1 +COPPER_TO_COPPER 0.1 +TEXT_TO_TRACK 0.1 +TEXT_TO_VIA 0.1 +TEXT_TO_PAD 0.1 +TEXT_TO_SMD 0.1 +OUTLINE_TO_TRACK 0.2 +OUTLINE_TO_VIA 0.2 +OUTLINE_TO_PAD 0.2 +OUTLINE_TO_SMD 0.2 +OUTLINE_TO_COPPER 0.2 +DRILL_TO_TRACK 0.1 +DRILL_TO_VIA 0.1 +DRILL_TO_PAD 0.1 +DRILL_TO_SMD 0.1 +DRILL_TO_COPPER 0.1 +SAME_NET_SMD_TO_VIA 0.1 +SAME_NET_SMD_TO_CRN 0.1 +SAME_NET_VIA_TO_VIA 0.1 +SAME_NET_PAD_TO_CRN 0.1 +MIN_TRACK_WIDTH 0.1 +REC_TRACK_WIDTH 0.5 +MAX_TRACK_WIDTH 1 +DRILL_TO_DRILL 0.1 +BODY_TO_BODY 0.1 +SAME_NET_TRACK_TO_CRN 0.1 +} +} +RULE_SET (9) +{ +FOR : +{ +NET $$$6537 +NET $$$6539 +NET $$$25431 +NET $$$25958 +NET $$$26274 +NET $$$27542 +} +AGAINST : +{ +DEFAULT : +} +LAYER 0 +CLEARANCE_RULE : +{ +TRACK_TO_TRACK 0.1 +VIA_TO_TRACK 0.1 +VIA_TO_VIA 0.1 +PAD_TO_TRACK 0.1 +PAD_TO_VIA 0.1 +PAD_TO_PAD 0.1 +SMD_TO_TRACK 0.1 +SMD_TO_VIA 0.1 +SMD_TO_PAD 0.1 +SMD_TO_SMD 0.1 +COPPER_TO_TRACK 0.1 +COPPER_TO_VIA 0.1 +COPPER_TO_PAD 0.1 +COPPER_TO_SMD 0.1 +COPPER_TO_COPPER 0.1 +TEXT_TO_TRACK 0.1 +TEXT_TO_VIA 0.1 +TEXT_TO_PAD 0.1 +TEXT_TO_SMD 0.1 +OUTLINE_TO_TRACK 0.2 +OUTLINE_TO_VIA 0.2 +OUTLINE_TO_PAD 0.2 +OUTLINE_TO_SMD 0.2 +OUTLINE_TO_COPPER 0.2 +DRILL_TO_TRACK 0.1 +DRILL_TO_VIA 0.1 +DRILL_TO_PAD 0.1 +DRILL_TO_SMD 0.1 +DRILL_TO_COPPER 0.1 +SAME_NET_SMD_TO_VIA 0.1 +SAME_NET_SMD_TO_CRN 0.1 +SAME_NET_VIA_TO_VIA 0.1 +SAME_NET_PAD_TO_CRN 0.1 +MIN_TRACK_WIDTH 0.1 +REC_TRACK_WIDTH 0.2 +MAX_TRACK_WIDTH 1 +DRILL_TO_DRILL 0.1 +BODY_TO_BODY 0.1 +SAME_NET_TRACK_TO_CRN 0.1 +} +} +RULE_SET (10) +{ +FOR : +{ +NET VBUS +NET $$$12824 +NET \SPI_CS_FLASH +} +AGAINST : +{ +DEFAULT : +} +LAYER 0 +CLEARANCE_RULE : +{ +TRACK_TO_TRACK 0.1 +VIA_TO_TRACK 0.1 +VIA_TO_VIA 0.1 +PAD_TO_TRACK 0.1 +PAD_TO_VIA 0.1 +PAD_TO_PAD 0.1 +SMD_TO_TRACK 0.1 +SMD_TO_VIA 0.1 +SMD_TO_PAD 0.1 +SMD_TO_SMD 0.1 +COPPER_TO_TRACK 0.1 +COPPER_TO_VIA 0.1 +COPPER_TO_PAD 0.1 +COPPER_TO_SMD 0.1 +COPPER_TO_COPPER 0.1 +TEXT_TO_TRACK 0.1 +TEXT_TO_VIA 0.1 +TEXT_TO_PAD 0.1 +TEXT_TO_SMD 0.1 +OUTLINE_TO_TRACK 0.2 +OUTLINE_TO_VIA 0.2 +OUTLINE_TO_PAD 0.2 +OUTLINE_TO_SMD 0.2 +OUTLINE_TO_COPPER 0.2 +DRILL_TO_TRACK 0.1 +DRILL_TO_VIA 0.1 +DRILL_TO_PAD 0.1 +DRILL_TO_SMD 0.1 +DRILL_TO_COPPER 0.1 +SAME_NET_SMD_TO_VIA 0.1 +SAME_NET_SMD_TO_CRN 0.1 +SAME_NET_VIA_TO_VIA 0.1 +SAME_NET_PAD_TO_CRN 0.1 +MIN_TRACK_WIDTH 0.1 +REC_TRACK_WIDTH 0.5 +MAX_TRACK_WIDTH 1 +DRILL_TO_DRILL 0.1 +BODY_TO_BODY 0.1 +SAME_NET_TRACK_TO_CRN 0.1 +} +} +RULE_SET (11) +{ +FOR : +{ +NET $$$85 +NET $$$1313 +NET $$$1329 +NET $$$24450 +} +AGAINST : +{ +DEFAULT : +} +LAYER 0 +CLEARANCE_RULE : +{ +TRACK_TO_TRACK 0.1 +VIA_TO_TRACK 0.1 +VIA_TO_VIA 0.1 +PAD_TO_TRACK 0.1 +PAD_TO_VIA 0.1 +PAD_TO_PAD 0.1 +SMD_TO_TRACK 0.1 +SMD_TO_VIA 0.1 +SMD_TO_PAD 0.1 +SMD_TO_SMD 0.1 +COPPER_TO_TRACK 0.1 +COPPER_TO_VIA 0.1 +COPPER_TO_PAD 0.1 +COPPER_TO_SMD 0.1 +COPPER_TO_COPPER 0.1 +TEXT_TO_TRACK 0.1 +TEXT_TO_VIA 0.1 +TEXT_TO_PAD 0.1 +TEXT_TO_SMD 0.1 +OUTLINE_TO_TRACK 0.2 +OUTLINE_TO_VIA 0.2 +OUTLINE_TO_PAD 0.2 +OUTLINE_TO_SMD 0.2 +OUTLINE_TO_COPPER 0.2 +DRILL_TO_TRACK 0.1 +DRILL_TO_VIA 0.1 +DRILL_TO_PAD 0.1 +DRILL_TO_SMD 0.1 +DRILL_TO_COPPER 0.1 +SAME_NET_SMD_TO_VIA 0.1 +SAME_NET_SMD_TO_CRN 0.1 +SAME_NET_VIA_TO_VIA 0.1 +SAME_NET_PAD_TO_CRN 0.1 +MIN_TRACK_WIDTH 0.1 +REC_TRACK_WIDTH 0.3 +MAX_TRACK_WIDTH 1 +DRILL_TO_DRILL 0.1 +BODY_TO_BODY 0.1 +SAME_NET_TRACK_TO_CRN 0.1 +} +} +RULE_SET (12) +{ +FOR : +{ +NET VDD_MAIN +} +AGAINST : +{ +DEFAULT : +} +LAYER 0 +CLEARANCE_RULE : +{ +TRACK_TO_TRACK 0.1 +VIA_TO_TRACK 0.1 +VIA_TO_VIA 0.1 +PAD_TO_TRACK 0.1 +PAD_TO_VIA 0.1 +PAD_TO_PAD 0.1 +SMD_TO_TRACK 0.1 +SMD_TO_VIA 0.1 +SMD_TO_PAD 0.1 +SMD_TO_SMD 0.1 +COPPER_TO_TRACK 0.1 +COPPER_TO_VIA 0.1 +COPPER_TO_PAD 0.1 +COPPER_TO_SMD 0.1 +COPPER_TO_COPPER 0.1 +TEXT_TO_TRACK 0.1 +TEXT_TO_VIA 0.1 +TEXT_TO_PAD 0.1 +TEXT_TO_SMD 0.1 +OUTLINE_TO_TRACK 0.2 +OUTLINE_TO_VIA 0.2 +OUTLINE_TO_PAD 0.2 +OUTLINE_TO_SMD 0.2 +OUTLINE_TO_COPPER 0.2 +DRILL_TO_TRACK 0.1 +DRILL_TO_VIA 0.1 +DRILL_TO_PAD 0.1 +DRILL_TO_SMD 0.1 +DRILL_TO_COPPER 0.1 +SAME_NET_SMD_TO_VIA 0.1 +SAME_NET_SMD_TO_CRN 0.1 +SAME_NET_VIA_TO_VIA 0.1 +SAME_NET_PAD_TO_CRN 0.1 +MIN_TRACK_WIDTH 0.1 +REC_TRACK_WIDTH 0.3 +MAX_TRACK_WIDTH 1 +DRILL_TO_DRILL 0.1 +BODY_TO_BODY 0.1 +SAME_NET_TRACK_TO_CRN 0.1 +} +} +RULE_SET (14) +{ +FOR : +{ +NET ADC_AGC +} +AGAINST : +{ +DEFAULT : +} +LAYER 0 +CLEARANCE_RULE : +{ +TRACK_TO_TRACK 0.1 +VIA_TO_TRACK 0.1 +VIA_TO_VIA 0.1 +PAD_TO_TRACK 0.1 +PAD_TO_VIA 0.1 +PAD_TO_PAD 0.1 +SMD_TO_TRACK 0.1 +SMD_TO_VIA 0.1 +SMD_TO_PAD 0.1 +SMD_TO_SMD 0.1 +COPPER_TO_TRACK 0.1 +COPPER_TO_VIA 0.1 +COPPER_TO_PAD 0.1 +COPPER_TO_SMD 0.1 +COPPER_TO_COPPER 0.1 +TEXT_TO_TRACK 0.1 +TEXT_TO_VIA 0.1 +TEXT_TO_PAD 0.1 +TEXT_TO_SMD 0.1 +OUTLINE_TO_TRACK 0.2 +OUTLINE_TO_VIA 0.2 +OUTLINE_TO_PAD 0.2 +OUTLINE_TO_SMD 0.2 +OUTLINE_TO_COPPER 0.2 +DRILL_TO_TRACK 0.1 +DRILL_TO_VIA 0.1 +DRILL_TO_PAD 0.1 +DRILL_TO_SMD 0.1 +DRILL_TO_COPPER 0.1 +SAME_NET_SMD_TO_VIA 0.1 +SAME_NET_SMD_TO_CRN 0.1 +SAME_NET_VIA_TO_VIA 0.1 +SAME_NET_PAD_TO_CRN 0.1 +MIN_TRACK_WIDTH 0.1 +REC_TRACK_WIDTH 0.3 +MAX_TRACK_WIDTH 1 +DRILL_TO_DRILL 0.1 +BODY_TO_BODY 0.1 +SAME_NET_TRACK_TO_CRN 0.1 +} +} +RULE_SET (15) +{ +FOR : +{ +NET ADC_RDATA_N +NET ADC_RDATA_P +} +AGAINST : +{ +DEFAULT : +} +LAYER 0 +CLEARANCE_RULE : +{ +TRACK_TO_TRACK 0.1 +VIA_TO_TRACK 0.1 +VIA_TO_VIA 0.1 +PAD_TO_TRACK 0.1 +PAD_TO_VIA 0.1 +PAD_TO_PAD 0.1 +SMD_TO_TRACK 0.1 +SMD_TO_VIA 0.1 +SMD_TO_PAD 0.1 +SMD_TO_SMD 0.1 +COPPER_TO_TRACK 0.1 +COPPER_TO_VIA 0.1 +COPPER_TO_PAD 0.1 +COPPER_TO_SMD 0.1 +COPPER_TO_COPPER 0.1 +TEXT_TO_TRACK 0.1 +TEXT_TO_VIA 0.1 +TEXT_TO_PAD 0.1 +TEXT_TO_SMD 0.1 +OUTLINE_TO_TRACK 0.2 +OUTLINE_TO_VIA 0.2 +OUTLINE_TO_PAD 0.2 +OUTLINE_TO_SMD 0.2 +OUTLINE_TO_COPPER 0.2 +DRILL_TO_TRACK 0.1 +DRILL_TO_VIA 0.1 +DRILL_TO_PAD 0.1 +DRILL_TO_SMD 0.1 +DRILL_TO_COPPER 0.1 +SAME_NET_SMD_TO_VIA 0.1 +SAME_NET_SMD_TO_CRN 0.1 +SAME_NET_VIA_TO_VIA 0.1 +SAME_NET_PAD_TO_CRN 0.1 +MIN_TRACK_WIDTH 0.1 +REC_TRACK_WIDTH 0.3 +MAX_TRACK_WIDTH 1 +DRILL_TO_DRILL 0.1 +BODY_TO_BODY 0.1 +SAME_NET_TRACK_TO_CRN 0.1 +} +} +} +} + +*MISC* MISCELLANEOUS PARAMETERS + +ATTRIBUTE VALUES +{ +PART R31 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C17 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 12pF_1005 +"Tolerance" +"Voltage Rating" +} +PART U2 +{ +"Manufacturer_Name" Texas Instruments +"Value" OPA2836IDGSR +"Mouser Part Number" 595-OPA2836IDGSR +"Mouser Price/Stock" https://www.mouser.co.uk/ProductDetail/Texas-Instruments/OPA2836IDGSR?qs=RqytGdBYyUGqgkd64C%252BPLQ%3D%3D +"Arrow Part Number" OPA2836IDGSR +"Arrow Price/Stock" https://www.arrow.com/en/products/opa2836idgsr/texas-instruments?utm_currency=USD®ion=europe +"Description" Dual, Very Low Power, Rail to Rail out, Negative Rail in, VFB Op Amp +"Datasheet Link" http://www.ti.com/lit/gpn/opa2836 +"Geometry.Height" 1.1mm +} +PART C18 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +"Tolerance" +"Voltage Rating" +} +PART J2 +{ +"Description" Battery Connector +"Manufacturer #1" MOLEX +"Value" 2026560021 +} +PART R23 +{ +"Value" 2k_1005_5% +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART R8 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART U9 +{ +"Manufacturer_Name" Taoglas +"Value" RECE.20279.001E.01 +"Mouser Part Number" 960-RECE20279001E01 +"Mouser Price/Stock" https://www.mouser.co.uk/ProductDetail/Taoglas/RECE.20279.001E.01?qs=MyNHzdoqoQIdppWb9vcEBA%3D%3D +"Arrow Part Number" RECE.20279.001E.01 +"Arrow Price/Stock" https://www.arrow.com/en/products/rece.20279.001e.01/taoglas?utm_currency=USD®ion=nac +"Description" IPEX MHF Receptacle +"Datasheet Link" https://datasheet.datasheetarchive.com/originals/distributors/Datasheets-DGA15/760324.pdf +} +PART R11 +{ +"Value" 0_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C2 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART C30 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 4.7uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART C4 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART R25 +{ +"Value" 4.7k_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART J4 +{ +"MF" ATTEND_Technology +"MAXIMUM_PACKAGE_HEIGHT" 5.46_mm +"Package" None +"Price" None +"Check_prices" https://www.snapeda.com/parts/217B-CA04/Attend/view-part/?ref=eda +"STANDARD" Manufacturer_Recommendations +"PARTREV" 1 +"SnapEDA_Link" https://www.snapeda.com/parts/217B-CA04/Attend/view-part/?ref=snap +"Value" 217B-CA04 +"Description" ______________________________________________________USB-C_(USB_TYPE-C)_Receptacle_Connector_24_(16+8_Dummy)_Position_Surface_Mount,_Right_Angle______________________________________________ +"Availability" In_Stock +"MANUFACTURER" Attend +"PKG_TYPE" ATTEND_217B-CA04 +} +PART J1 +{ +"Value" NC +} +PART C19 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 1uF_1005 +"Tolerance" +"Voltage Rating" +} +PART C16 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 12pF_1005 +"Tolerance" +"Voltage Rating" +} +PART C23 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 1nF_1005 +"Tolerance" +"Voltage Rating" +} +PART R28 +{ +"Value" 806k_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART R42 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R6 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R12 +{ +"Value" 48.7_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART U5 +{ +"Description" High Performance 500 mA LDO +"Manufacturer #1" MICROCHIP +"Value" MIC5528-3.3YMT +} +PART C21 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 12pF_1005 +"Tolerance" +"Voltage Rating" +} +PART C22 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 12pF_1005 +"Tolerance" +"Voltage Rating" +} +PART C31 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +"Tolerance" +"Voltage Rating" +} +PART R14 +{ +"Value" 0_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART LED3 +{ +"Description" LED GREEN/1608 +"Value" FC-DA1608UGK-520D10 +"Manufacturer #1" ANY VENDOR +} +PART C32 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 4.7uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART C20 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +"Tolerance" +"Voltage Rating" +} +PART R16 +{ +"Value" 0_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R18 +{ +"Value" 0_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART U20 +{ +"Manufacturer_Name" Nexperia +"Value" PESD5V0F1BLD,315 +"Mouser Part Number" 771-PESD5V0F1BLD315 +"Mouser Price/Stock" https://www.mouser.co.uk/ProductDetail/Nexperia/PESD5V0F1BLD315?qs=1sbE9T7hb3b3MsEvtkPidA%3D%3D +"Arrow Part Number" PESD5V0F1BLD,315 +"Arrow Price/Stock" https://www.arrow.com/en/products/pesd5v0f1bld315/nexperia?region=nac +"Description" PESD5V0F1BLD - Femtofarad bidirectional ESD protection diode +"Datasheet Link" https://assets.nexperia.com/documents/data-sheet/PESD5V0F1BLD.pdf +"Geometry.Height" 0.4mm +} +PART C15 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 47nF_1005 +"Tolerance" +"Voltage Rating" +} +PART C24 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 820pF_1005 +"Tolerance" +"Voltage Rating" +} +PART C5 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 10uF_1608 +"Tolerance" +"Voltage Rating" +} +PART C7 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 10uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART C10 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 4.7uF_1608 +"Tolerance" +"Voltage Rating" +} +PART C14 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 1uF_1005 +"Tolerance" +"Voltage Rating" +} +PART C12 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART C13 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 4.7uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART C37 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 4.7uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART C38 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 4.7uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART U23 +{ +"Manufacturer_Name" Analog Devices +"Value" ADL5513ACPZ-R7 +"Mouser Part Number" 584-ADL5513ACPZ-R7 +"Mouser Price/Stock" https://www.mouser.co.uk/ProductDetail/Analog-Devices/ADL5513ACPZ-R7?qs=BpaRKvA4VqGe6%2FPlUcoEpw%3D%3D +"Arrow Part Number" ADL5513ACPZ-R7 +"Arrow Price/Stock" https://www.arrow.com/en/products/adl5513acpz-r7/analog-devices?utm_currency=USD®ion=nac +"Description" ANALOG DEVICES - ADL5513ACPZ-R7 - DETECTOR, 1MHZ - 4GHZ, 80DB, LFCSP-16 +"Datasheet Link" https://www.analog.com/media/en/technical-documentation/data-sheets/ADL5513.pdf +"Geometry.Height" 0.8mm +} +PART C61 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 47nF_1005 +} +PART R19 +{ +"Value" 1k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R29 +{ +"Value" 2M_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART C64 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100pF_1005 +} +PART C67 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 47nF_1005 +} +PART R20 +{ +"Value" 0_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C72 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 100pF_1005 +"Tolerance" +"Voltage Rating" +} +PART C29 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 4.7uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART L4 +{ +"Manufacturer #1" TAIYO YUDEN +"Value" 10uH_1608 +"Description" RF INDUCTOR +"Part Number" LBMF1608T100K +} +PART L3 +{ +"Manufacturer #1" TAIYO YUDEN +"Value" 15nH_1005 +"Description" RF INDUCTOR +"Part Number" HK100515NJ-T +} +PART Y1 +{ +"Cost" +"Description" CRYSTAL FC-12M 32.768KHZ 20PPM,12.5PF +"Manufacturer #1" SEIKO EPSON +"Value" FC-12M 32.7680KA-A0 +"Geometry.Height" 1.27000mm +} +PART R26 +{ +"Value" NC +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R27 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART Y2 +{ +"Value" FA-128 32.0000MF10Z-AJ0 +"Manufacturer #1" SEIKO EPSON +"Cost" +"Description" CRYSTAL 2016 32MHz, 8PF(6PF), 10PPM +} +PART R35 +{ +"Value" 100k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C51 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART L1 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART C42 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 4.7uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART C36 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +"Tolerance" +"Voltage Rating" +} +PART R24 +{ +"Value" 4.7k_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART C43 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 10uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART C39 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 4.7uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART C28 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" NC +"Tolerance" +"Voltage Rating" +} +PART C27 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" NC +"Tolerance" +} +PART R36 +{ +"Value" 1k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C26 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 0.5pF_1005 +"Tolerance" +"Voltage Rating" +} +PART C25 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 0.8pF_1005 +"Tolerance" +"Voltage Rating" +} +PART R39 +{ +"Value" 1k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C40 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100pF_1005 +} +PART C41 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 47pF_1005 +} +PART C44 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 10uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART C45 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 10uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART C46 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 10uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART C47 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 10uF_1608 +"Tolerance" +"Voltage Rating" +} +PART C48 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 1uF_1005_50V +} +PART C49 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 1uF_1005_50V +} +PART U16 +{ +"Manufacturer_Name" Winbond +"Value" W25Q32RVXHJQ TR +"Mouser Part Number" 454-W25Q32RVXHJQTR +"Mouser Price/Stock" https://www.mouser.co.uk/ProductDetail/Winbond/W25Q32RVXHJQ-TR?qs=mELouGlnn3dFwM4lg8JCig%3D%3D +"Arrow Part Number" W25Q32RVXHJQ TR +"Arrow Price/Stock" https://www.arrow.com/en/products/w25q32rvxhjq-tr/winbond-electronics?utm_currency=USD®ion=nac +"Description" NOR Flash spiFlash, 3V, 32M-bit, 4Kb Uniform Sector +"Datasheet Link" https://www.winbond.com/hq/product/code-storage-flash-memory/serial-nor-flash/?__locale=ja&partNo=W25Q32RV +"Geometry.Height" 0.4mm +} +PART C50 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 10uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART C103 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100pF_1005 +} +PART R83 +{ +"Value" 1k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C52 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 4.7uF_1608 +"Tolerance" +"Voltage Rating" +} +PART R30 +{ +"Value" 48.7_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C34 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +"Tolerance" +"Voltage Rating" +} +PART R40 +{ +"Value" 48.7_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART L5 +{ +"Manufacturer #1" MURATA +"Value" 4.7nH_1005 +"Description" RF INDUCTOR +"Part Number" LQP15MN3N9B02D +} +PART U6 +{ +"MF" Murata +"MAXIMUM_PACKAGE_HEIGHT" 0.95mm +"Package" 1608_Taiyo_Yuden +"Price" None +"Check_prices" https://www.snapeda.com/parts/PRG18BC1R0MM1RB/Murata/view-part/?ref=eda +"STANDARD" IPC-7351B +"PARTREV" N/A +"SnapEDA_Link" https://www.snapeda.com/parts/PRG18BC1R0MM1RB/Murata/view-part/?ref=snap +"Value" PRG18BC1R0MM1RB +"Description" ______________________________________________________Ceramic_PTC_Resettable_Fuse_6V_330_mA_Ih_Surface_Mount_0603_(1608_Metric)______________________________________________ +"Availability" In_Stock +"MANUFACTURER" Murata +"PKG_TYPE" THRMC1608X95N +} +PART U7 +{ +"MF" Murata +"MAXIMUM_PACKAGE_HEIGHT" 0.95mm +"Package" 1608_Taiyo_Yuden +"Price" None +"Check_prices" https://www.snapeda.com/parts/PRG18BC1R0MM1RB/Murata/view-part/?ref=eda +"STANDARD" IPC-7351B +"PARTREV" N/A +"SnapEDA_Link" https://www.snapeda.com/parts/PRG18BC1R0MM1RB/Murata/view-part/?ref=snap +"Value" PRG18BC1R0MM1RB +"Description" ______________________________________________________Ceramic_PTC_Resettable_Fuse_6V_330_mA_Ih_Surface_Mount_0603_(1608_Metric)______________________________________________ +"Availability" In_Stock +"MANUFACTURER" Murata +"PKG_TYPE" THRMC1608X95N +} +PART L6 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART SW2 +{ +"Value" NW3-A03-05 +"Manufacturer #1" MADE IN CHINA +"Description" TACTILE SWITCH +} +PART C53 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +"Tolerance" +"Voltage Rating" +} +PART R17 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R41 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C54 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART C55 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART C56 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 10uF_1608 +"Tolerance" +"Voltage Rating" +} +PART R43 +{ +"Value" 2k_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART LED4 +{ +"Description" LED ORANGE/1608 +"Value" FC-DA1608HOK-600H +"Manufacturer #1" ANY VENDOR +} +PART U4 +{ +"Manufacturer #1" NEXPERIA +"Value" PMFPB8032XP +"Description" 20V, 3.7A P-channel MOSFET-Schottky +} +PART P1 +{ +"MANUFACTURER" Panasonic +"PKG_TYPE" PANASONIC_AXT510124 +} +PART R15 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART U10 +{ +"Description" 6-Axis MotionTracking IMU +"Manufacturer #1" TDK_INVENSENSE +"Value" ICM-42670-P +} +PART U27 +{ +"Manufacturer_Name" Microchip +"Value" MD1822K6-G +"Mouser Part Number" 689-MD1822K6-G +"Mouser Price/Stock" https://www.mouser.co.uk/ProductDetail/Microchip-Technology/MD1822K6-G?qs=SPVxp5Gxk7pFYhy0Y%2FNrig%3D%3D +"Arrow Part Number" MD1822K6-G +"Arrow Price/Stock" https://www.arrow.com/en/products/md1822k6-g/microchip-technology?region=nac +"Description" MICROCHIP - MD1822K6-G - MOSFET Driver, High Side and Low Side, 5V to 10V Supply, 2A Out, 6.5ns Delay, QFN-16 +"Datasheet Link" https://ms.componentsearchengine.com/Datasheets/2/MD1822K6-G.pdf +"Geometry.Height" 1mm +} +PART C35 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +"Tolerance" +"Voltage Rating" +} +PART C8 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 2.2uF_1608 +"Tolerance" +"Voltage Rating" +} +PART C9 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART JP1 +{ +"Value" NC +} +PART R65 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART D3 +{ +"Description" DUAL SWITCHING DIODE +"Cost" +"Value" DAP222WM +"Manufacturer #1" ROHM KOREA. +} +PART D4 +{ +"Description" Medium Power AF Schottky Diode +"Manufacturer #1" INFINEON +"Value" BAS3005B-02V +} +PART U1 +{ +"Description" ESD protection diode +"Manufacturer #1" NEXPERIA +"Value" PRTR5V0U2X +} +PART R34 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART U22 +{ +"Description" High-Accuracy Analog Temperature Sensors +"Manufacturer #1" TI +"Value" TMP235AEDBZTQ1 +} +PART L2 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART R21 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R22 +{ +"Value" 100_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART U8 +{ +"Description" Single Inverter Gate +"Manufacturer #1" TI +"Value" SN74LVC1G04DRY2 +} +PART R33 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R32 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R37 +{ +"Value" 5.1K_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART R4 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART U30 +{ +"Manufacturer_Name" Microchip +"Value" TC7920K6-G +"Mouser Part Number" 689-TC7920K6-G +"Mouser Price/Stock" https://www.mouser.co.uk/ProductDetail/Microchip-Technology/TC7920K6-G?qs=SPVxp5Gxk7rlZ7Pl2YwJVQ%3D%3D +"Arrow Part Number" TC7920K6-G +"Arrow Price/Stock" https://www.arrow.com/en/products/tc7920k6-g/microchip-technology +"Description" MOSFET 2PR N- & PCH ENHANCE MD MSFET w/DRAIN-DI +"Datasheet Link" https://4donline.ihs.com/images/VipMasterIC/IC/MCHP/MCHP-S-A0019419833/MCHP-S-A0019419833-1.pdf?hkey=EF798316E3902B6ED9A73243A3159BB0 +"Geometry.Height" 1mm +} +PART R38 +{ +"Value" 5.1K_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART C62 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 10nF_1005_50V +} +PART C65 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +"Tolerance" +"Voltage Rating" +} +PART C70 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 10nF_1005_50V +} +PART C74 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 10nF_1005_50V +} +PART U26 +{ +"Copyright" Copyright (C) 2025 Ultra Librarian. All rights reserved. +"Manufacturer_Name" Nordic Semiconductor +"Value" NRF52840-QIAA-F-R +} +PART U3 +{ +"Description" Advanced Stand-Alone Li-Ion/Li-Polymer Battery Charger +"Manufacturer #1" MICROCHIP +"Value" MCP73838-FCI/UN +} +PART C73 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" NC +"Tolerance" +"Voltage Rating" +} +PART C11 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 2.2uF_1608 +"Tolerance" +"Voltage Rating" +} +PART C75 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 10nF_1005_50V +} +PART U31 +{ +"Manufacturer_Name" Analog Devices +"Value" MAX14778ETP+ +"Mouser Part Number" 700-MAX14778ETP+ +"Mouser Price/Stock" https://www.mouser.co.uk/ProductDetail/Analog-Devices-Maxim-Integrated/MAX14778ETP%2b?qs=4Rc5iGDDRGhnkuxvUsFiYQ%3D%3D +"Arrow Part Number" MAX14778ETP+ +"Arrow Price/Stock" https://www.arrow.com/en/products/max14778etp/analog-devices?utm_currency=USD®ion=nac +"Description" Maxim MAX14778ETP+, Multiplexer Dual 4:1 20Mbit/s, 3 5.5 V, 20-Pin TQFN +"Datasheet Link" https://datasheets.maximintegrated.com/en/ds/MAX14778.pdf +"Geometry.Height" 0.8mm +} +PART C76 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005_50V +} +PART C77 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005_50V +} +PART R58 +{ +"Value" 0_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C33 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 2.2uF_1608 +"Tolerance" +"Voltage Rating" +} +PART R73 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R63 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART U34 +{ +"Value" MD0100N8-G +} +PART C80 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 1uF_1005_50V +} +PART C81 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 1uF_1005_50V +} +PART C82 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005_50V +} +PART C83 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005_50V +} +PART C84 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005_50V +} +PART L10 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART L11 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART L12 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART L14 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART C1 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 4.7uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART U32 +{ +"MF" Analog_Devices +"VENDOR" Linear_Technology +"Description" ______________________________________________________Boost,_Charge_Pump_Switching_Regulator_IC_Positive_and_Negative_(Dual_Rail)_Adjustable_±1.25V_2_Output_180mA_(Switch),_320mA_(Switch)_10-WFDFN_Exposed_Pad______________________________________________ +"Package" DFN-10_Linear_Technology +"Price" None +"Check_prices" https://www.snapeda.com/parts/LT3463EDD%23PBF/Analog+Devices/view-part/?ref=eda +"SnapEDA_Link" https://www.snapeda.com/parts/LT3463EDD%23PBF/Analog+Devices/view-part/?ref=snap +"Value" LT3463EDD#PBF +"Availability" In_Stock +"MANUFACTURER_PART_NUMBER" lt3463edd +"PKG_TYPE" DFN-10_DD +} +PART C3 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 4.7uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART C6 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 4.7uF_1608_25V +"Tolerance" +"Voltage Rating" +} +PART R7 +{ +"Value" 4.7k_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART L13 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" 10uH_1608 +} +PART R10 +{ +"Value" NC +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART R9 +{ +"Value" 1.54k_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART R5 +{ +"Value" 1k_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART L15 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" 10uH_1608 +} +PART TH1 +{ +"Manufacturer #1" KYOCERA AVX +"Value" NB21K00103KBB +"Description" THERMISTOR NTC, 10K/1608 +} +PART R13 +{ +"Value" 69.8k_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART C85 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART C86 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005_50V +} +PART D1 +{ +"MAXIMUM_PACKAGE_HEIGHT" 1.15mm +"Value" B0540WS +} +PART R66 +{ +"Value" 61.9k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R67 +{ +"Value" 1M_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C87 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" NC +} +PART R68 +{ +"Value" 240k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R69 +{ +"Value" 240k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R70 +{ +"Value" 1M_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R71 +{ +"Value" 66.5k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C88 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 470nF_1005_50V +} +PART C89 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 470nF_1005_50V +} +PART C79 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 1uF_1005 +} +PART L16 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART U33 +{ +"Manufacturer_Name" Microchip +"Value" MCP1804T-A002I/OT +"Mouser Part Number" 579-MCP1804T-A002IOT +"Mouser Price/Stock" https://www.mouser.co.uk/ProductDetail/Microchip-Technology/MCP1804T-A002I-OT?qs=X8nz4ozed5igIlf9%252BFEUbg%3D%3D +"Arrow Part Number" MCP1804T-A002I/OT +"Arrow Price/Stock" https://www.arrow.com/en/products/mcp1804t-a002iot/microchip-technology?region=nac +"Description" LDO, 150mA max, Vin 28V max, Vout =10.0V +"Datasheet Link" http://ww1.microchip.com/downloads/en/DeviceDoc/20002200D.pdf +"Geometry.Height" 1.45mm +} +PART C90 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 1uF_1005_50V +} +PART C91 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 1uF_1005_50V +} +PART C98 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART R1 +{ +"Value" 1k_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART R2 +{ +"Value" 1k_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART LED1 +{ +"Description" LED ORANGE/1608 +"Value" FC-DA1608HOK-600H +"Manufacturer #1" ANY VENDOR +} +PART LED2 +{ +"Description" LED BLUE/1608 +"Value" LS-SP192DNB74-D +"Manufacturer #1" ANY VENDOR +} +PART L17 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART R3 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R74 +{ +"Value" 100k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C110 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 10nF_1005 +} +PART R77 +{ +"Value" 1k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C119 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 10nF_1005 +"Tolerance" +"Voltage Rating" +} +PART R79 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R80 +{ +"Value" 100k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART U37 +{ +"Manufacturer_Name" Texas Instruments +"Value" ADC121S051CIMF/NOPB +"Mouser Part Number" 926-AD121S051CIMFNPB +"Mouser Price/Stock" https://www.mouser.co.uk/ProductDetail/Texas-Instruments/ADC121S051CIMF-NOPB?qs=7X5t%252BdzoRHDM6gt6xt2J%252Bw%3D%3D +"Arrow Part Number" ADC121S051CIMF/NOPB +"Arrow Price/Stock" https://www.arrow.com/en/products/adc121s051cimfnopb/texas-instruments?region=nac +"Description" Single Channel, 200 to 500 ksps, 12-Bit A/D Converter +"Datasheet Link" http://www.ti.com/lit/ds/symlink/adc121s051.pdf +"Geometry.Height" 1.45mm +} +PART C78 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART C93 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART C95 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART L19 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART U38 +{ +"Manufacturer_Name" Texas Instruments +"Value" LM27762DSSR +"Mouser Part Number" 595-LM27762DSSR +"Mouser Price/Stock" https://www.mouser.co.uk/ProductDetail/Texas-Instruments/LM27762DSSR?qs=vcbl%252BK4rRlfEJcC9xQ80sA%3D%3D +"Arrow Part Number" LM27762DSSR +"Arrow Price/Stock" https://www.arrow.com/en/products/lm27762dssr/texas-instruments?utm_currency=USD®ion=nac +"Description" LDO Voltage Regulators Low-Noise Positive- and Negative-Output Integrated Switched Capacitor Plus LDO 12-WSON -40 to 85 +"Datasheet Link" https://www.ti.com/lit/ds/symlink/lm27762.pdf +"Geometry.Height" 0.8mm +} +PART U42 +{ +"Description" High Performance 500 mA LDO +"Manufacturer #1" MICROCHIP +"Value" MIC5528-3.3YMT +} +PART C96 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 1uF_1005 +} +PART R64 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R72 +{ +"Value" 13k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R76 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R78 +{ +"Value" 13k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART R81 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART L20 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART R82 +{ +"Value" 1k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART L22 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART L23 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART C102 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART U41 +{ +"Description" High Performance 500 mA LDO +"Manufacturer #1" MICROCHIP +"Value" MIC5528-3.3YMT +} +PART C104 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 2.2uF_1608 +"Tolerance" +"Voltage Rating" +} +PART L32 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART R61 +{ +"Value" 100_1005 +"Manufacturer #1" ANY VENDOR +"Part Number" +"Description" SMT RESISTOR 1005, 1/16W +"Tolerance" +} +PART C121 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +"Tolerance" +"Voltage Rating" +} +PART R84 +{ +"Value" 1k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C105 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 47pF_1005 +} +PART R87 +{ +"Value" 1.54k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C106 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100pF_1005 +} +PART R90 +{ +"Value" 10k_1005 +"Manufacturer #1" ANY VENDOR +"Description" SMT RESISTOR 1005, 1/16W +} +PART C109 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART C113 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 4.7uF_1608 +"Tolerance" +"Voltage Rating" +} +PART L31 +{ +"Manufacturer #1" MURATA +"Description" CHIP FERRITE BEAD 120R/2A/1608 +"Value" BLM18PG330SH1D +} +PART C114 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Manufacturer #1" ANY VENDOR +"Value" 100nF_1005 +} +PART C115 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 2.2uF_1608 +"Tolerance" +"Voltage Rating" +} +PART C116 +{ +"Description" SURFACE MOUNT CAPACITOR 1005 +"Part Number" +"Manufacturer #1" ANY VENDOR +"Value" 10uF_1608 +"Tolerance" +"Voltage Rating" +} +} + +*END* OF ASCII OUTPUT FILE diff --git a/data/curcuit/20305 VB0HW0100.sch b/data/curcuit/20305 VB0HW0100.sch new file mode 100644 index 0000000..9cd4ee3 Binary files /dev/null and b/data/curcuit/20305 VB0HW0100.sch differ diff --git a/data/curcuit/VesiScan-Basic_curcuit.pdf b/data/curcuit/VesiScan-Basic_curcuit.pdf new file mode 100644 index 0000000..8d8766d Binary files /dev/null and b/data/curcuit/VesiScan-Basic_curcuit.pdf differ diff --git a/data/datasheet/adc121s051_datasheet.pdf b/data/datasheet/adc121s051_datasheet.pdf new file mode 100644 index 0000000..0161069 Binary files /dev/null and b/data/datasheet/adc121s051_datasheet.pdf differ diff --git a/data/pdf-style.css b/data/pdf-style.css new file mode 100644 index 0000000..9f70884 --- /dev/null +++ b/data/pdf-style.css @@ -0,0 +1,84 @@ +body { + font-family: 'Malgun Gothic', '맑은 고딕', sans-serif; + font-size: 11pt; + line-height: 1.6; + color: #333; +} + +h2 { + font-size: 18pt; + border-bottom: 2px solid #333; + padding-bottom: 6px; + margin-top: 30px; +} + +h3 { + font-size: 14pt; + border-bottom: 1px solid #ccc; + padding-bottom: 4px; + margin-top: 24px; +} + +h4 { + font-size: 12pt; + margin-top: 16px; +} + +table { + border-collapse: collapse; + width: 100%; + font-size: 10pt; + margin: 12px 0; +} + +th, td { + border: 1px solid #ccc; + padding: 6px 10px; + text-align: left; +} + +th { + background-color: #f5f5f5; + font-weight: bold; +} + +code { + font-family: 'Consolas', 'D2Coding', monospace; + font-size: 9.5pt; + background-color: #f5f5f5; + padding: 1px 4px; + border-radius: 3px; +} + +pre { + font-family: 'Consolas', 'D2Coding', monospace; + font-size: 9.5pt; + background-color: #f5f5f5; + padding: 12px; + border-radius: 4px; + border: 1px solid #ddd; + overflow-x: auto; +} + +blockquote { + border-left: 4px solid #4a90d9; + background-color: #f0f6ff; + padding: 10px 16px; + margin: 16px 0; + font-size: 11pt; +} + +ul, ol { + margin: 8px 0; + padding-left: 24px; +} + +li { + margin: 4px 0; +} + +hr { + border: none; + border-top: 1px solid #ddd; + margin: 24px 0; +} diff --git a/external/fprintf/nrf_fprintf.c b/external/fprintf/nrf_fprintf.c new file mode 100644 index 0000000..ad28276 --- /dev/null +++ b/external/fprintf/nrf_fprintf.c @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_FPRINTF) +#include + +#include "nrf_assert.h" +#include "nrf_fprintf_format.h" + +void nrf_fprintf_buffer_flush(nrf_fprintf_ctx_t * const p_ctx) +{ + ASSERT(p_ctx != NULL); + + if (p_ctx->io_buffer_cnt == 0) + { + return; + } + + p_ctx->fwrite(p_ctx->p_user_ctx, + p_ctx->p_io_buffer, + p_ctx->io_buffer_cnt); + p_ctx->io_buffer_cnt = 0; +} + +void nrf_fprintf(nrf_fprintf_ctx_t * const p_ctx, + char const * p_fmt, + ...) +{ + ASSERT(p_ctx != NULL); + ASSERT(p_ctx->fwrite != NULL); + ASSERT(p_ctx->p_io_buffer != NULL); + ASSERT(p_ctx->io_buffer_size > 0); + + if (p_fmt == NULL) + { + return; + } + + va_list args = {0}; + va_start(args, p_fmt); + + nrf_fprintf_fmt(p_ctx, p_fmt, &args); + + va_end(args); +} + +#endif // NRF_MODULE_ENABLED(NRF_FPRINTF) + diff --git a/external/fprintf/nrf_fprintf.h b/external/fprintf/nrf_fprintf.h new file mode 100644 index 0000000..e18e965 --- /dev/null +++ b/external/fprintf/nrf_fprintf.h @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_FPRINTF_H__ +#define NRF_FPRINTF_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (* nrf_fprintf_fwrite)(void const * p_user_ctx, char const * p_str, size_t length); + +/** + * @brief fprintf context + */ +typedef struct nrf_fprintf_ctx +{ + char * const p_io_buffer; ///< Pointer to IO buffer. + size_t const io_buffer_size; ///< IO buffer size. + size_t io_buffer_cnt; ///< IO buffer usage. + bool auto_flush; ///< Auto flush configurator. + + void const * const p_user_ctx; ///< Pointer to user data to be passed to the fwrite funciton. + + nrf_fprintf_fwrite fwrite; ///< Pointer to function sending data stream. +} nrf_fprintf_ctx_t; + + +/** + * @brief Macro for defining nrf_fprintf instance. + * + * @param name Instance name. + * @param _p_user_ctx Pointer to user data. + * @param _p_io_buffer Pointer to IO buffer + * @param _io_buffer_size Size of IO buffer. + * @param _auto_flush Indicator if IO buffer shall be automatically flush. + * @param _fwrite Pointer to function sending data stream. + * */ +#define NRF_FPRINTF_DEF(name, _p_user_ctx, _p_io_buffer, _io_buffer_size, _auto_flush, _fwrite) \ + static nrf_fprintf_ctx_t name = \ + { \ + .p_io_buffer = _p_io_buffer, \ + .io_buffer_size = _io_buffer_size, \ + .io_buffer_cnt = 0, \ + .auto_flush = _auto_flush, \ + .p_user_ctx = _p_user_ctx, \ + .fwrite = _fwrite \ + } + +/** + * @brief fprintf like function which send formated data stream to output specified by user + * @ref nrf_fprintf_ctx_t + * + * @param p_ctx fprintf context. + * @param p_fmt Format string. + * @param ... List of parameters to print. + * */ +void nrf_fprintf(nrf_fprintf_ctx_t * const p_ctx, + char const * p_fmt, + ...); + +/** + * @brief function flushing data stored in io_buffer @ref nrf_fprintf_ctx_t + * + * @param p_ctx fprintf context + */ +void nrf_fprintf_buffer_flush(nrf_fprintf_ctx_t * const p_ctx); + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_FPRINTF_H__ */ + diff --git a/external/fprintf/nrf_fprintf_format.c b/external/fprintf/nrf_fprintf_format.c new file mode 100644 index 0000000..05b4e78 --- /dev/null +++ b/external/fprintf/nrf_fprintf_format.c @@ -0,0 +1,810 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH & Co. KG * +* The Embedded Experts * +********************************************************************** +* * +* (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH & Co. KG * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 6.14d * +* * +*********************************************************************/ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_FPRINTF) + +#include + +#include "nrf_assert.h" +#include "nrf_fprintf.h" +#include "nrf_fprintf_format.h" + +#define NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) +#define NRF_CLI_FORMAT_FLAG_PAD_ZERO (1u << 1) +#define NRF_CLI_FORMAT_FLAG_PRINT_SIGN (1u << 2) + +#define NRF_CLI_FORMAT_DOUBLE_DEF_PRECISION 6 + +#define NRF_CLI_FORMAT_DOUBLE_SIGN_POSITION 63U +#define NRF_CLI_FORMAT_DOUBLE_SIGN_MASK 1ULL +#define NRF_CLI_FORMAT_DOUBLE_SIGN (NRF_CLI_FORMAT_DOUBLE_SIGN_MASK << NRF_CLI_FORMAT_DOUBLE_SIGN_POSITION) +#define NRF_CLI_FORMAT_DOUBLE_EXP_POSITION 52U +#define NRF_CLI_FORMAT_DOUBLE_EXP_MASK 0x7FFULL +#define NRF_CLI_FORMAT_DOUBLE_EXP (NRF_CLI_FORMAT_DOUBLE_EXP_MASK << NRF_CLI_FORMAT_DOUBLE_EXP_POSITION) +#define NRF_CLI_FORMAT_DOUBLE_MANT_POSITION 0U +#define NRF_CLI_FORMAT_DOUBLE_MANT_MASK 0xFFFFFFFFFFFFF +#define NRF_CLI_FORMAT_DOUBLE_MANT (NRF_CLI_FORMAT_DOUBLE_MANT_MASK << NRF_CLI_FORMAT_DOUBLE_MANT_POSITION) + +#define NRF_CLI_FORMAT_DOUBLE_SIGN_GET(v) (!!((v) & NRF_CLI_FORMAT_DOUBLE_SIGN)) +#define NRF_CLI_FORMAT_DOUBLE_EXP_GET(v) (((v) & NRF_CLI_FORMAT_DOUBLE_EXP) >> NRF_CLI_FORMAT_DOUBLE_EXP_POSITION) +#define NRF_CLI_FORMAT_DOUBLE_MANT_GET(v) (((v) & NRF_CLI_FORMAT_DOUBLE_MANT) >> NRF_CLI_FORMAT_DOUBLE_MANT_POSITION) +#define NRF_CLI_FORMAT_REQ_SIGN_SPACE(s, f) ((s) | (!!((f) & NRF_CLI_FORMAT_FLAG_PRINT_SIGN))) + +#define HIGH_32(v) ((v) >> 32) +#define LOW_32(v) (((1ULL << 32) - 1) & v) + + +static void buffer_add(nrf_fprintf_ctx_t * const p_ctx, char c) +{ +#if NRF_MODULE_ENABLED(NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF) + if (c == '\n') + { + buffer_add(p_ctx, '\r'); + } +#endif + p_ctx->p_io_buffer[p_ctx->io_buffer_cnt++] = c; + + if (p_ctx->io_buffer_cnt >= p_ctx->io_buffer_size) + { + nrf_fprintf_buffer_flush(p_ctx); + } +} + +static void string_print(nrf_fprintf_ctx_t * const p_ctx, + char const * p_str, + uint32_t FieldWidth, + uint32_t FormatFlags) +{ + uint32_t Width = 0; + char c; + + if ((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) + { + while ((c = *p_str) != '\0') + { + p_str++; + Width++; + buffer_add(p_ctx, c); + } + + while ((FieldWidth > Width) && (FieldWidth > 0)) + { + FieldWidth--; + buffer_add(p_ctx, ' '); + } + } + else + { + if (p_str != 0) + { + Width = strlen(p_str); + } + + while ((FieldWidth > Width) && (FieldWidth > 0)) + { + FieldWidth--; + buffer_add(p_ctx, ' '); + } + + while ((c = *p_str) != '\0') + { + p_str++; + Width++; + buffer_add(p_ctx, c); + } + } +} + +static void unsigned_print(nrf_fprintf_ctx_t * const p_ctx, + uint32_t v, + uint32_t Base, + uint32_t NumDigits, + uint32_t FieldWidth, + uint32_t FormatFlags) +{ + static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' }; + uint32_t Div; + uint32_t Value; + uint32_t Width; + char c; + + Value = v; + // + // Get actual field width + // + Width = 1u; + while (Value >= Base) + { + Value = (Value / Base); + Width++; + } + if (NumDigits > Width) + { + Width = NumDigits; + } + // + // Print leading chars if necessary + // + if ((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == 0u) + { + if (FieldWidth != 0u) + { + if (((FormatFlags & NRF_CLI_FORMAT_FLAG_PAD_ZERO) == NRF_CLI_FORMAT_FLAG_PAD_ZERO) && + (NumDigits == 0u)) + { + c = '0'; + } + else + { + c = ' '; + } + while ((FieldWidth != 0u) && (Width < FieldWidth)) + { + FieldWidth--; + buffer_add(p_ctx, c); + } + } + } + + Value = 1; + /* + * Compute Digit. + * Loop until Digit has the value of the highest digit required. + * Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. + */ + while (1) + { + /* User specified a min number of digits to print? => Make sure we loop at least that + * often, before checking anything else (> 1 check avoids problems with NumDigits + * being signed / unsigned) + */ + if (NumDigits > 1u) + { + NumDigits--; + } + else + { + Div = v / Value; + // Is our divider big enough to extract the highest digit from value? => Done + if (Div < Base) + { + break; + } + } + Value *= Base; + } + // + // Output digits + // + do + { + Div = v / Value; + v -= Div * Value; + buffer_add(p_ctx, _aV2C[Div]); + Value /= Base; + } while (Value); + // + // Print trailing spaces if necessary + // + if ((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) + { + if (FieldWidth != 0u) + { + while ((FieldWidth != 0u) && (Width < FieldWidth)) + { + FieldWidth--; + buffer_add(p_ctx, ' '); + } + } + } +} + +static void int_print(nrf_fprintf_ctx_t * const p_ctx, + int32_t v, + uint32_t Base, + uint32_t NumDigits, + uint32_t FieldWidth, + uint32_t FormatFlags) +{ + uint32_t Width; + int32_t Number; + + Number = (v < 0) ? -v : v; + + // + // Get actual field width + // + Width = 1u; + while (Number >= (int32_t)Base) + { + Number = (Number / (int32_t)Base); + Width++; + } + if (NumDigits > Width) + { + Width = NumDigits; + } + if ((FieldWidth > 0u) && ((v < 0) || + ((FormatFlags & NRF_CLI_FORMAT_FLAG_PRINT_SIGN) == NRF_CLI_FORMAT_FLAG_PRINT_SIGN))) + { + FieldWidth--; + } + // + // Print leading spaces if necessary + // + if ((((FormatFlags & NRF_CLI_FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && + ((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) + { + if (FieldWidth != 0u) + { + while ((FieldWidth != 0u) && (Width < FieldWidth)) + { + FieldWidth--; + buffer_add(p_ctx, ' '); + } + } + } + // + // Print sign if necessary + // + if (v < 0) + { + v = -v; + buffer_add(p_ctx, '-'); + } + else if ((FormatFlags & NRF_CLI_FORMAT_FLAG_PRINT_SIGN) == NRF_CLI_FORMAT_FLAG_PRINT_SIGN) + { + buffer_add(p_ctx, '+'); + } + else + { + /* do nothing */ + } + // + // Print leading zeros if necessary + // + if (((FormatFlags & NRF_CLI_FORMAT_FLAG_PAD_ZERO) == NRF_CLI_FORMAT_FLAG_PAD_ZERO) && + ((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) + { + if (FieldWidth != 0u) + { + while ((FieldWidth != 0u) && (Width < FieldWidth)) + { + FieldWidth--; + buffer_add(p_ctx, '0'); + } + } + } + // + // Print number without sign + // + unsigned_print(p_ctx, (uint32_t)v, Base, NumDigits, FieldWidth, FormatFlags); +} + +#if NRF_MODULE_ENABLED(NRF_FPRINTF_DOUBLE) + +static void fill_space(nrf_fprintf_ctx_t * const p_ctx, + uint8_t len, + bool zeros) +{ + for (; len > 0; len--) + { + if (zeros) + { + buffer_add(p_ctx, '0'); + } + else + { + buffer_add(p_ctx, ' '); + } + } +} + +static void float_print(nrf_fprintf_ctx_t * const p_ctx, + double v, + uint32_t digits, + uint32_t width, + uint32_t format, + bool uppercase) +{ + bool sign, transform = false; + uint64_t num, mant, lead, low, base, res, carry, x, s0, s1, s2, s3, fr; + int32_t exp; + uint8_t highest, offset, lead_len = 0, skipped = 0; + uint8_t precision = digits ? digits + 1 : NRF_CLI_FORMAT_DOUBLE_DEF_PRECISION + 1; + /* Default digits should be -1, because 0 could be a requirement, not the default. + * This should be changed for the whole library. + */ + + if ((v > 0.0) && (v < 1.0)) + { + v += 1.0; + transform = true; + } + else if ((v > -1.0) && (v < 0.0)) + { + v -= 1.0; + transform = true; + } + + memcpy(&num, &v, sizeof(num)); + sign = NRF_CLI_FORMAT_DOUBLE_SIGN_GET(num); + exp = NRF_CLI_FORMAT_DOUBLE_EXP_GET(num); + mant = NRF_CLI_FORMAT_DOUBLE_MANT_GET(num); + + /* Special cases */ + if (exp == NRF_CLI_FORMAT_DOUBLE_EXP_MASK) + { + if (width && (!(format & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY))) + { + fill_space(p_ctx, width - 3 - NRF_CLI_FORMAT_REQ_SIGN_SPACE(sign, format), false); + } + + if (sign) + { + buffer_add(p_ctx, '-'); + } + else if (format & NRF_CLI_FORMAT_FLAG_PRINT_SIGN) + { + buffer_add(p_ctx, '+'); + } + + if (mant != 0) + { + if(uppercase) + { + buffer_add(p_ctx, 'N'); + buffer_add(p_ctx, 'A'); + buffer_add(p_ctx, 'N'); + } + else + { + buffer_add(p_ctx, 'n'); + buffer_add(p_ctx, 'a'); + buffer_add(p_ctx, 'n'); + } + } + else + { + if(uppercase) + { + buffer_add(p_ctx, 'I'); + buffer_add(p_ctx, 'N'); + buffer_add(p_ctx, 'F'); + } + else + { + buffer_add(p_ctx, 'i'); + buffer_add(p_ctx, 'n'); + buffer_add(p_ctx, 'f'); + } + } + return; + } + + /* Add leading 1 to mantissa (except 0.0) */ + if ((mant != 0) || (exp != 0)) + { + mant |= (1ULL << 52); + } + + /* Convert the exponent */ + exp = exp - 1023; + + /* Whole numbers */ + offset = 52 - exp; + + if (offset > 64) + { + /* Float fraction offset overflow */ + return; + } + + lead = (mant >> (offset)); + + /* Fraction */ + low = mant & (~(lead << offset)); + + while (((low & 0x1) == 0) && low > 0) + { + low = low >> 1U; + skipped++; + } + + highest = (offset - skipped); + base = 1; + + for(uint8_t i = 0; i < precision; i++) + { + base *= 10; + } + + /* Handle multiplication with possible overflow */ + x = LOW_32(low) * LOW_32(base); + s0 = LOW_32(x); + + x = HIGH_32(low) * LOW_32(base) + HIGH_32(x); + s1 = LOW_32(x); + s2 = HIGH_32(x); + + x = s1 + LOW_32(low) * HIGH_32(base); + s1 = LOW_32(x); + + x = s2 + HIGH_32(low) * HIGH_32(base) + HIGH_32(x); + s2 = LOW_32(x); + s3 = HIGH_32(x); + + res = s1 << 32 | s0; + carry = s3 << 32 | s2; + + /* Divide and combine */ + carry = carry << (64 - highest); + res = res >> highest; + fr = res | carry; + + /* Roundup */ + if (fr%10 >= 5) + { + fr /= 10; + fr++; + } + else + { + fr /= 10; + } + precision--; + + if (transform && (lead == 1)) + { + lead = 0; + } + + /* Maximum precision handled by int_print() is 10 */ + if (precision > 10) + { + for (uint8_t delta = precision - 10; delta > 0; delta--) + { + fr /= 10; + } + precision = 10; + } + + res = lead; + while (res > 0) + { + res /= 10; + lead_len++; + } + + if ((lead == 0) && (fr == 0)) + { + lead_len = 1; + } + + if(lead_len == 0) + { + lead_len = 1; + } + + if (width && (!(format & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY))) + { + int32_t space = width - lead_len - precision - NRF_CLI_FORMAT_REQ_SIGN_SPACE(sign, format) - 1; + if (space > 0) + { + fill_space(p_ctx, space, format & NRF_CLI_FORMAT_FLAG_PAD_ZERO); + } + } + + if (sign) + { + buffer_add(p_ctx, '-'); + } + else if (format & NRF_CLI_FORMAT_FLAG_PRINT_SIGN) + { + buffer_add(p_ctx, '+'); + } + + int_print(p_ctx, + lead, + 10u, + 0, + 0, + 0); + buffer_add(p_ctx, '.'); + int_print(p_ctx, + fr, + 10u, + precision, + 0, + 0); + + if (width && (format & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY)) + { + int32_t space = width - lead_len - precision - NRF_CLI_FORMAT_REQ_SIGN_SPACE(sign, format) - 1; + if (space > 0) + { + fill_space(p_ctx, space, false); + } + } +} + +#endif + +void nrf_fprintf_fmt(nrf_fprintf_ctx_t * const p_ctx, + char const * p_fmt, + va_list * p_args) +{ + ASSERT(p_ctx != NULL); + + ASSERT(p_ctx->fwrite != NULL); + ASSERT(p_ctx->p_io_buffer != NULL); + ASSERT(p_ctx->io_buffer_size > 0); + + if (p_fmt == NULL) + { + return; + } + + char c; + int32_t v; + uint32_t NumDigits; + uint32_t FormatFlags; + uint32_t FieldWidth; + + do + { + c = *p_fmt; + p_fmt++; + + if (c == 0u) + { + break; + } + if (c == '%') + { + // + // Filter out flags + // + FormatFlags = 0u; + v = 1; + + do + { + c = *p_fmt; + switch (c) + { + case '-': + FormatFlags |= NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY; + p_fmt++; + break; + case '0': + FormatFlags |= NRF_CLI_FORMAT_FLAG_PAD_ZERO; + p_fmt++; + break; + case '+': + FormatFlags |= NRF_CLI_FORMAT_FLAG_PRINT_SIGN; + p_fmt++; + break; + default: + v = 0; + break; + } + } while (v); + + // + // filter out field width + // + FieldWidth = 0u; + do + { + if (c == '*') + { + /*lint -save -e64 -e56*/ + FieldWidth += va_arg(*p_args, unsigned); + /*lint -restore*/ + p_fmt++; + break; + } + c = *p_fmt; + if ((c < '0') || (c > '9')) + { + break; + } + p_fmt++; + FieldWidth = (FieldWidth * 10u) + (c - '0'); + } while (1); + + // + // Filter out precision (number of digits to display) + // + NumDigits = 0u; + c = *p_fmt; + if (c == '.') + { + p_fmt++; + do + { + c = *p_fmt; + if ((c < '0') || (c > '9')) + { + break; + } + p_fmt++; + NumDigits = NumDigits * 10u + (c - '0'); + } while (1); + } + // + // Filter out length modifier + // + c = *p_fmt; + do + { + if ((c == 'l') || (c == 'h')) + { + p_fmt++; + c = *p_fmt; + } + else + { + break; + } + } while (1); + // + // Handle specifiers + // + /*lint -save -e64*/ + switch (c) + { + case 'c': + { + char c0; + v = va_arg(*p_args, int32_t); + c0 = (char)v; + buffer_add(p_ctx, c0); + break; + } + case 'd': + case 'i': + v = va_arg(*p_args, int32_t); + int_print(p_ctx, + v, + 10u, + NumDigits, + FieldWidth, + FormatFlags); + break; + case 'u': + v = va_arg(*p_args, int32_t); + unsigned_print(p_ctx, + (uint32_t)v, + 10u, + NumDigits, + FieldWidth, + FormatFlags); + break; + case 'x': + case 'X': + v = va_arg(*p_args, int32_t); + unsigned_print(p_ctx, + (uint32_t)v, + 16u, + NumDigits, + FieldWidth, + FormatFlags); + break; + case 's': + { + char const * p_s = va_arg(*p_args, const char *); + string_print(p_ctx, p_s, FieldWidth, FormatFlags); + break; + } + case 'p': + v = va_arg(*p_args, int32_t); + buffer_add(p_ctx, '0'); + buffer_add(p_ctx, 'x'); + unsigned_print(p_ctx, (uint32_t)v, 16u, 8u, 8u, 0); + break; + case '%': + buffer_add(p_ctx, '%'); + break; +#if NRF_MODULE_ENABLED(NRF_FPRINTF_DOUBLE) + case 'f': + { + double dbl = va_arg(*p_args, double); + float_print(p_ctx, + dbl, + NumDigits, + FieldWidth, + FormatFlags, + false); + break; + } + case 'F': + { + double dbl = va_arg(*p_args, double); + float_print(p_ctx, + dbl, + NumDigits, + FieldWidth, + FormatFlags, + true); + break; + } +#endif + default: + break; + } + /*lint -restore*/ + p_fmt++; + } + else + { + buffer_add(p_ctx, c); + } + } while (*p_fmt != '\0'); + + if (p_ctx->auto_flush) + { + nrf_fprintf_buffer_flush(p_ctx); + } +} + +#endif // NRF_MODULE_ENABLED(NRF_FPRINTF) + diff --git a/external/fprintf/nrf_fprintf_format.h b/external/fprintf/nrf_fprintf_format.h new file mode 100644 index 0000000..920e685 --- /dev/null +++ b/external/fprintf/nrf_fprintf_format.h @@ -0,0 +1,86 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH & Co. KG * +* The Embedded Experts * +********************************************************************** +* * +* (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH & Co. KG * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 6.14d * +* * +*********************************************************************/ + +#ifndef NRF_FPRINTF_FORMAT_H__ +#define NRF_FPRINTF_FORMAT_H__ + +#include +#include "nrf_fprintf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Printf like function which sends formated data stream to output. + * + * @param nrf_fprintf_ctx_t Print context. + * @param p_fmt Format string. + * @param p_args List of parameters to print. + * */ +void nrf_fprintf_fmt(nrf_fprintf_ctx_t * const p_ctx, + char const * p_fmt, + va_list * p_args); + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_FPRINTF_FORMAT_H__ */ + diff --git a/external/licenses_external.txt b/external/licenses_external.txt new file mode 100644 index 0000000..1dfaeff --- /dev/null +++ b/external/licenses_external.txt @@ -0,0 +1,5 @@ +IMPORTANT NOTE +All source code contained under this folder originates from third +parties, and is covered by the corresponding licenses found in the +respective subfolders + diff --git a/external/mbedtls/.github/issue_template.md b/external/mbedtls/.github/issue_template.md new file mode 100644 index 0000000..7c31353 --- /dev/null +++ b/external/mbedtls/.github/issue_template.md @@ -0,0 +1,41 @@ +Note: This is just a template, so feel free to use/remove the unnecessary things + +### Description +- Type: Bug | Enhancement\Feature Request | Question +- Priority: Blocker | Major | Minor + +--------------------------------------------------------------- +## Bug + +**OS** +Mbed OS|linux|windows| + +**mbed TLS build:** +Version: x.x.x or git commit id +OS version: x.x.x +Configuration: please attach config.h file where possible +Compiler and options (if you used a pre-built binary, please indicate how you obtained it): +Additional environment information: + +**Peer device TLS stack and version** +OpenSSL|GnuTls|Chrome|NSS(Firefox)|SecureChannel (IIS/Internet Explorer/Edge)|Other +Version: + +**Expected behavior** + +**Actual behavior** + +**Steps to reproduce** + +---------------------------------------------------------------- +## Enhancement\Feature Request + +**Justification - why does the library need this feature?** + +**Suggested enhancement** + +----------------------------------------------------------------- + +## Question + +**Please first check for answers in the [Mbed TLS knowledge Base](https://tls.mbed.org/kb), and preferably file an issue in the [Mbed TLS support forum](https://forums.mbed.com/c/mbed-tls)** diff --git a/external/mbedtls/.github/pull_request_template.md b/external/mbedtls/.github/pull_request_template.md new file mode 100644 index 0000000..c580443 --- /dev/null +++ b/external/mbedtls/.github/pull_request_template.md @@ -0,0 +1,36 @@ +Notes: +* Pull requests cannot be accepted until the PR follows the [contributing guidelines](../CONTRIBUTING.md). In particular, each commit must have at least one `Signed-off-by:` line from the committer to certify that the contribution is made under the terms of the [Developer Certificate of Origin](../dco.txt). +* This is just a template, so feel free to use/remove the unnecessary things +## Description +A few sentences describing the overall goals of the pull request's commits. + + +## Status +**READY/IN DEVELOPMENT/HOLD** + +## Requires Backporting +When there is a bug fix, it should be backported to all maintained and supported branches. +Changes do not have to be backported if: +- This PR is a new feature\enhancement +- This PR contains changes in the API. If this is true, and there is a need for the fix to be backported, the fix should be handled differently in the legacy branch + +Yes | NO +Which branch? + +## Migrations +If there is any API change, what's the incentive and logic for it. + +YES | NO + +## Additional comments +Any additional information that could be of interest + +## Todos +- [ ] Tests +- [ ] Documentation +- [ ] Changelog updated +- [ ] Backported + + +## Steps to test or reproduce +Outline the steps to test or reproduce the PR here. diff --git a/external/mbedtls/.globalrc b/external/mbedtls/.globalrc new file mode 100644 index 0000000..01b2ea5 --- /dev/null +++ b/external/mbedtls/.globalrc @@ -0,0 +1,3 @@ +default:\ + :langmap=c\:.c.h.function:\ + diff --git a/external/mbedtls/.pylintrc b/external/mbedtls/.pylintrc new file mode 100644 index 0000000..08c114a --- /dev/null +++ b/external/mbedtls/.pylintrc @@ -0,0 +1,72 @@ +[BASIC] +# We're ok with short funtion argument names. +# [invalid-name] +argument-rgx=[a-z_][a-z0-9_]*$ + +# Allow filter and map. +# [bad-builtin] +bad-functions=input + +# We prefer docstrings, but we don't require them on all functions. +# Require them only on long functions (for some value of long). +# [missing-docstring] +docstring-min-length=10 + +# Allow longer methods than the default. +# [invalid-name] +method-rgx=[a-z_][a-z0-9_]{2,35}$ + +# Allow module names containing a dash (but no underscore or uppercase letter). +# They are whole programs, not meant to be included by another module. +# [invalid-name] +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|[a-z][-0-9a-z]+)$ + +# Some functions don't need docstrings. +# [missing-docstring] +no-docstring-rgx=(run_)main$ + +# We're ok with short local or global variable names. +# [invalid-name] +variable-rgx=[a-z_][a-z0-9_]*$ + +[DESIGN] +# Allow more than the default 7 attributes. +# [too-many-instance-attributes] +max-attributes=15 + +[FORMAT] +# Allow longer modules than the default recommended maximum. +# [too-many-lines] +max-module-lines=2000 + +[MESSAGES CONTROL] +# * locally-disabled, locally-enabled: If we disable or enable a message +# locally, it's by design. There's no need to clutter the Pylint output +# with this information. +# * logging-format-interpolation: Pylint warns about things like +# ``log.info('...'.format(...))``. It insists on ``log.info('...', ...)``. +# This is of minor utility (mainly a performance gain when there are +# many messages that use formatting and are below the log level). +# Some versions of Pylint (including 1.8, which is the version on +# Ubuntu 18.04) only recognize old-style format strings using '%', +# and complain about something like ``log.info('{}', foo)`` with +# logging-too-many-args (Pylint supports new-style formatting if +# declared globally with logging_format_style under [LOGGING] but +# this requires Pylint >=2.2). +# * no-else-return: Allow the perfectly reasonable idiom +# if condition1: +# return value1 +# else: +# return value2 +# * unnecessary-pass: If we take the trouble of adding a line with "pass", +# it's because we think the code is clearer that way. +disable=locally-disabled,locally-enabled,logging-format-interpolation,no-else-return,unnecessary-pass + +[REPORTS] +# Don't diplay statistics. Just the facts. +reports=no + +[VARIABLES] +# Allow unused variables if their name starts with an underscore. +# [unused-argument] +dummy-variables-rgx=_.* diff --git a/external/mbedtls/.travis.yml b/external/mbedtls/.travis.yml new file mode 100644 index 0000000..8789c44 --- /dev/null +++ b/external/mbedtls/.travis.yml @@ -0,0 +1,64 @@ +language: c +compiler: gcc +sudo: false +cache: ccache + +jobs: + include: + - name: basic checks and reference configurations + addons: + apt: + packages: + - gnutls-bin + - doxygen + - graphviz + - gcc-arm-none-eabi + - libnewlib-arm-none-eabi + language: python # Needed to get pip for Python 3 + python: 3.5 # version from Ubuntu 16.04 + install: + - pip install pylint==2.4.4 + script: + - tests/scripts/all.sh -k 'check_*' + - tests/scripts/all.sh -k test_default_out_of_box + - tests/scripts/test-ref-configs.pl + - tests/scripts/all.sh -k build_arm_none_eabi_gcc_arm5vte build_arm_none_eabi_gcc_m0plus + + - name: full configuration + script: + - tests/scripts/all.sh -k test_full_cmake_gcc_asan + + - name: check compilation guards + script: + - tests/scripts/all.sh -k 'test_depends_*' 'build_key_exchanges' + + - name: macOS + os: osx + compiler: clang + script: + - tests/scripts/all.sh -k test_default_out_of_box + + - name: Windows + os: windows + script: + - scripts/windows_msbuild.bat v141 # Visual Studio 2017 + +after_failure: +- tests/scripts/travis-log-failure.sh + +env: + global: + - SEED=1 + - secure: "FrI5d2s+ckckC17T66c8jm2jV6i2DkBPU5nyWzwbedjmEBeocREfQLd/x8yKpPzLDz7ghOvr+/GQvsPPn0dVkGlNzm3Q+hGHc/ujnASuUtGrcuMM+0ALnJ3k4rFr9xEvjJeWb4SmhJO5UCAZYvTItW4k7+bj9L+R6lt3TzQbXzg=" + +addons: + apt: + packages: + - gnutls-bin + coverity_scan: + project: + name: "ARMmbed/mbedtls" + notification_email: support-mbedtls@arm.com + build_command_prepend: + build_command: make + branch_pattern: coverity_scan diff --git a/external/mbedtls/CMakeLists.txt b/external/mbedtls/CMakeLists.txt new file mode 100644 index 0000000..5f7d0d8 --- /dev/null +++ b/external/mbedtls/CMakeLists.txt @@ -0,0 +1,240 @@ +cmake_minimum_required(VERSION 2.6) +if(TEST_CPP) + project("mbed TLS" C CXX) +else() + project("mbed TLS" C) +endif() + +option(USE_PKCS11_HELPER_LIBRARY "Build mbed TLS with the pkcs11-helper library." OFF) +option(ENABLE_ZLIB_SUPPORT "Build mbed TLS with zlib library." OFF) + +option(ENABLE_PROGRAMS "Build mbed TLS programs." ON) + +option(UNSAFE_BUILD "Allow unsafe builds. These builds ARE NOT SECURE." OFF) + +string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}") +string(REGEX MATCH "GNU" CMAKE_COMPILER_IS_GNU "${CMAKE_C_COMPILER_ID}") +string(REGEX MATCH "IAR" CMAKE_COMPILER_IS_IAR "${CMAKE_C_COMPILER_ID}") +string(REGEX MATCH "MSVC" CMAKE_COMPILER_IS_MSVC "${CMAKE_C_COMPILER_ID}") + +# the test suites currently have compile errors with MSVC +if(CMAKE_COMPILER_IS_MSVC) + option(ENABLE_TESTING "Build mbed TLS tests." OFF) +else() + option(ENABLE_TESTING "Build mbed TLS tests." ON) +endif() + +# Warning string - created as a list for compatibility with CMake 2.8 +set(WARNING_BORDER "*******************************************************\n") +set(NULL_ENTROPY_WARN_L1 "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined!\n") +set(NULL_ENTROPY_WARN_L2 "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES\n") +set(NULL_ENTROPY_WARN_L3 "**** AND IS *NOT* SUITABLE FOR PRODUCTION USE\n") + +set(NULL_ENTROPY_WARNING "${WARNING_BORDER}" + "${NULL_ENTROPY_WARN_L1}" + "${NULL_ENTROPY_WARN_L2}" + "${NULL_ENTROPY_WARN_L3}" + "${WARNING_BORDER}") + +set(CTR_DRBG_128_BIT_KEY_WARN_L1 "**** WARNING! MBEDTLS_CTR_DRBG_USE_128_BIT_KEY defined!\n") +set(CTR_DRBG_128_BIT_KEY_WARN_L2 "**** Using 128-bit keys for CTR_DRBG limits the security of generated\n") +set(CTR_DRBG_128_BIT_KEY_WARN_L3 "**** keys and operations that use random values generated to 128-bit security\n") + +set(CTR_DRBG_128_BIT_KEY_WARNING "${WARNING_BORDER}" + "${CTR_DRBG_128_BIT_KEY_WARN_L1}" + "${CTR_DRBG_128_BIT_KEY_WARN_L2}" + "${CTR_DRBG_128_BIT_KEY_WARN_L3}" + "${WARNING_BORDER}") + +find_package(PythonInterp) +find_package(Perl) +if(PERL_FOUND) + + # If 128-bit keys are configured for CTR_DRBG, display an appropriate warning + execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.pl -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + RESULT_VARIABLE result) + if(${result} EQUAL 0) + message(WARNING ${CTR_DRBG_128_BIT_KEY_WARNING}) + endif() + + # If NULL Entropy is configured, display an appropriate warning + execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.pl -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_TEST_NULL_ENTROPY + RESULT_VARIABLE result) + if(${result} EQUAL 0) + message(WARNING ${NULL_ENTROPY_WARNING}) + + if(NOT UNSAFE_BUILD) + message(FATAL_ERROR "\ +\n\ +Warning! You have enabled MBEDTLS_TEST_NULL_ENTROPY. \ +This option is not safe for production use and negates all security \ +It is intended for development use only. \ +\n\ +To confirm you want to build with this option, re-run cmake with the \ +option: \n\ + cmake -DUNSAFE_BUILD=ON ") + + return() + endif() + endif() +endif() + +set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} + CACHE STRING "Choose the type of build: None Debug Release Coverage ASan ASanDbg MemSan MemSanDbg Check CheckFull" + FORCE) + +# Create a symbolic link from ${base_name} in the binary directory +# to the corresponding path in the source directory. +function(link_to_source base_name) + # Get OS dependent path to use in `execute_process` + if (CMAKE_HOST_WIN32) + #mklink is an internal command of cmd.exe it can only work with \ + string(REPLACE "/" "\\" link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}") + string(REPLACE "/" "\\" target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}") + else() + set(link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}") + set(target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}") + endif() + + if (NOT EXISTS ${link}) + if (CMAKE_HOST_UNIX) + set(command ln -s ${target} ${link}) + else() + if (IS_DIRECTORY ${target}) + set(command cmd.exe /c mklink /j ${link} ${target}) + else() + set(command cmd.exe /c mklink /h ${link} ${target}) + endif() + endif() + + execute_process(COMMAND ${command} + RESULT_VARIABLE result + ERROR_VARIABLE output) + + if (NOT ${result} EQUAL 0) + message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}") + endif() + endif() +endfunction(link_to_source) + +string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}") + +if(CMAKE_COMPILER_IS_GNU) + # some warnings we want are not available with old GCC versions + # note: starting with CMake 2.8 we could use CMAKE_C_COMPILER_VERSION + execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion + OUTPUT_VARIABLE GCC_VERSION) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -W -Wdeclaration-after-statement -Wwrite-strings") + if (GCC_VERSION VERSION_GREATER 4.5 OR GCC_VERSION VERSION_EQUAL 4.5) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wlogical-op") + endif() + if (GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow") + endif() + set(CMAKE_C_FLAGS_RELEASE "-O2") + set(CMAKE_C_FLAGS_DEBUG "-O0 -g3") + set(CMAKE_C_FLAGS_COVERAGE "-O0 -g3 --coverage") + set(CMAKE_C_FLAGS_ASAN "-Werror -fsanitize=address -fno-common -O3") + set(CMAKE_C_FLAGS_ASANDBG "-Werror -fsanitize=address -fno-common -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ") + set(CMAKE_C_FLAGS_CHECK "-Werror -Os") + set(CMAKE_C_FLAGS_CHECKFULL "${CMAKE_C_FLAGS_CHECK} -Wcast-qual") +endif(CMAKE_COMPILER_IS_GNU) + +if(CMAKE_COMPILER_IS_CLANG) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -W -Wdeclaration-after-statement -Wwrite-strings -Wpointer-arith -Wimplicit-fallthrough -Wshadow") + set(CMAKE_C_FLAGS_RELEASE "-O2") + set(CMAKE_C_FLAGS_DEBUG "-O0 -g3") + set(CMAKE_C_FLAGS_COVERAGE "-O0 -g3 --coverage") + set(CMAKE_C_FLAGS_ASAN "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3") + set(CMAKE_C_FLAGS_ASANDBG "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ") + set(CMAKE_C_FLAGS_MEMSAN "-Werror -fsanitize=memory -O3") + set(CMAKE_C_FLAGS_MEMSANDBG "-Werror -fsanitize=memory -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2") + set(CMAKE_C_FLAGS_CHECK "-Werror -Os") +endif(CMAKE_COMPILER_IS_CLANG) + +if(CMAKE_COMPILER_IS_IAR) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --warn_about_c_style_casts --warnings_are_errors -Ohz") +endif(CMAKE_COMPILER_IS_IAR) + +if(CMAKE_COMPILER_IS_MSVC) + # Strictest warnings, and treat as errors + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") +endif(CMAKE_COMPILER_IS_MSVC) + +if(CMAKE_BUILD_TYPE STREQUAL "Coverage") + if(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG) + set(CMAKE_SHARED_LINKER_FLAGS "--coverage") + endif(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG) +endif(CMAKE_BUILD_TYPE STREQUAL "Coverage") + +if(LIB_INSTALL_DIR) +else() + set(LIB_INSTALL_DIR lib) +endif() + +include_directories(include/) + +if(ENABLE_ZLIB_SUPPORT) + find_package(ZLIB) + + if(ZLIB_FOUND) + include_directories(${ZLIB_INCLUDE_DIR}) + endif(ZLIB_FOUND) +endif(ENABLE_ZLIB_SUPPORT) + +add_subdirectory(library) +add_subdirectory(include) + +if(ENABLE_PROGRAMS) + add_subdirectory(programs) +endif() + +ADD_CUSTOM_TARGET(apidoc + COMMAND doxygen mbedtls.doxyfile + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doxygen) + +if(ENABLE_TESTING) + enable_testing() + + add_subdirectory(tests) + + # additional convenience targets for Unix only + if(UNIX) + + ADD_CUSTOM_TARGET(covtest + COMMAND make test + COMMAND programs/test/selftest + COMMAND tests/compat.sh + COMMAND tests/ssl-opt.sh + ) + + ADD_CUSTOM_TARGET(lcov + COMMAND rm -rf Coverage + COMMAND lcov --capture --initial --directory library/CMakeFiles/mbedtls.dir -o files.info + COMMAND lcov --capture --directory library/CMakeFiles/mbedtls.dir -o tests.info + COMMAND lcov --add-tracefile files.info --add-tracefile tests.info -o all.info + COMMAND lcov --remove all.info -o final.info '*.h' + COMMAND gendesc tests/Descriptions.txt -o descriptions + COMMAND genhtml --title "mbed TLS" --description-file descriptions --keep-descriptions --legend --no-branch-coverage -o Coverage final.info + COMMAND rm -f files.info tests.info all.info final.info descriptions + ) + + ADD_CUSTOM_TARGET(memcheck + COMMAND sed -i.bak s+/usr/bin/valgrind+`which valgrind`+ DartConfiguration.tcl + COMMAND ctest -O memcheck.log -D ExperimentalMemCheck + COMMAND tail -n1 memcheck.log | grep 'Memory checking results:' > /dev/null + COMMAND rm -f memcheck.log + COMMAND mv DartConfiguration.tcl.bak DartConfiguration.tcl + ) + endif(UNIX) + + # Make scripts needed for testing available in an out-of-source build. + if (NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) + link_to_source(scripts) + # Copy (don't link) DartConfiguration.tcl, needed for memcheck, to + # keep things simple with the sed commands in the memcheck target. + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/DartConfiguration.tcl + ${CMAKE_CURRENT_BINARY_DIR}/DartConfiguration.tcl COPYONLY) + endif() +endif() diff --git a/external/mbedtls/CONTRIBUTING.md b/external/mbedtls/CONTRIBUTING.md new file mode 100644 index 0000000..9b02ba5 --- /dev/null +++ b/external/mbedtls/CONTRIBUTING.md @@ -0,0 +1,82 @@ +Contributing +============ +We gratefully accept bug reports and contributions from the community. There are some requirements we need to fulfill in order to be able to integrate contributions: + + - As with any open source project, contributions will be reviewed by the project team and community and may need some modifications to be accepted. + - The contribution should not break API or ABI, unless there is a real justification for that. If there is an API change, the contribution, if accepted, will be merged only when there will be a major release. + +Coding Standards +---------------- +- We would ask that contributions conform to [our coding standards](https://tls.mbed.org/kb/development/mbedtls-coding-standards), and that contributions are fully tested before submission, as mentioned in the [Tests](#tests) and [Continuous Integration](#continuous-integration-tests) sections. +- The code should be written in a clean and readable style. +- The code should be written in a portable generic way, that will benefit the whole community, and not only your own needs. +- The code should be secure, and will be reviewed from a security point of view as well. + +Making a Contribution +--------------------- +1. [Check for open issues](https://github.com/ARMmbed/mbedtls/issues) or [start a discussion](https://lists.trustedfirmware.org/mailman/listinfo/mbed-tls) around a feature idea or a bug. +1. Fork the [Mbed TLS repository on GitHub](https://github.com/ARMmbed/mbedtls) to start making your changes. As a general rule, you should use the ["development" branch](https://github.com/ARMmbed/mbedtls/tree/development) as a basis. +1. Write a test which shows that the bug was fixed or that the feature works as expected. +1. Send a pull request (PR) and work with us until it gets merged and published. Contributions may need some modifications, so a few rounds of review and fixing may be necessary. We will include your name in the ChangeLog :) +1. For quick merging, the contribution should be short, and concentrated on a single feature or topic. The larger the contribution is, the longer it would take to review it and merge it. +1. All new files should include the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) standard license header where possible. +1. Ensure that each commit has at least one `Signed-off-by:` line from the committer. If anyone else contributes to the commit, they should also add their own `Signed-off-by:` line. By adding this line, contributor(s) certify that the contribution is made under the terms of the [Developer Certificate of Origin](dco.txt). The contribution licensing is described in the [License section of the README](README.md#License). + +API/ABI Compatibility +--------------------- +The project aims to minimise the impact on users upgrading to newer versions of the library and it should not be necessary for a user to make any changes to their own code to work with a newer version of the library. Unless the user has made an active decision to use newer features, a newer generation of the library or a change has been necessary due to a security issue or other significant software defect, no modifications to their own code should be necessary. To achieve this, API compatibility is maintained between different versions of Mbed TLS on the main development branch and in LTS (Long Term Support) branches. + +To minimise such disruption to users, where a change to the interface is required, all changes to the ABI or API, even on the main development branch where new features are added, need to be justifiable by either being a significant enhancement, new feature or bug fix which is best resolved by an interface change. + +Where changes to an existing interface are necessary, functions in the public interface which need to be changed, are marked as 'deprecated'. This is done with the preprocessor symbols `MBEDTLS_DEPRECATED_WARNING` and `MBEDTLS_DEPRECATED_REMOVED`. Then, a new function with a new name but similar if not identical behaviour to the original function containing the necessary changes should be created alongside the existing deprecated function. + +When a build is made with the deprecation preprocessor symbols defined, a compiler warning will be generated to warn a user that the function will be removed at some point in the future, notifying users that they should change from the older deprecated function to the newer function at their own convenience. + +Therefore, no changes are permitted to the definition of functions in the public interface which will change the API. Instead the interface can only be changed by its extension. As described above, if a function needs to be changed, a new function needs to be created alongside it, with a new name, and whatever change is necessary, such as a new parameter or the addition of a return value. + +Periodically, the library will remove deprecated functions from the library which will be a breaking change in the API, but such changes will be made only in a planned, structured way that gives sufficient notice to users of the library. + +Long Term Support Branches +-------------------------- +Mbed TLS maintains several LTS (Long Term Support) branches, which are maintained continuously for a given period. The LTS branches are provided to allow users of the library to have a maintained, stable version of the library which contains only security fixes and fixes for other defects, without encountering additional features or API extensions which may introduce issues or change the code size or RAM usage, which can be significant considerations on some platforms. To allow users to take advantage of the LTS branches, these branches maintain backwards compatibility for both the public API and ABI. + +When backporting to these branches please observe the following rules: + +1. Any change to the library which changes the API or ABI cannot be backported. +1. All bug fixes that correct a defect that is also present in an LTS branch must be backported to that LTS branch. If a bug fix introduces a change to the API such as a new function, the fix should be reworked to avoid the API change. API changes without very strong justification are unlikely to be accepted. +1. If a contribution is a new feature or enhancement, no backporting is required. Exceptions to this may be additional test cases or quality improvements such as changes to build or test scripts. + +It would be highly appreciated if contributions are backported to LTS branches in addition to the [development branch](https://github.com/ARMmbed/mbedtls/tree/development) by contributors. + +Currently maintained LTS branches are: +1. [mbedtls-2.7](https://github.com/ARMmbed/mbedtls/tree/mbedtls-2.7) +1. [mbedtls-2.16](https://github.com/ARMmbed/mbedtls/tree/mbedtls-2.16) + + +Tests +----- +As mentioned, tests that show the correctness of the feature or bug fix should be added to the pull request, if no such tests exist. + +Mbed TLS includes a comprehensive set of test suites in the `tests/` directory that are dynamically generated to produce the actual test source files (e.g. `test_suite_mpi.c`). These files are generated from a `function file` (e.g. `suites/test_suite_mpi.function`) and a `data file` (e.g. `suites/test_suite_mpi.data`). The function file contains the test functions. The data file contains the test cases, specified as parameters that will be passed to the test function. + +[A Knowledge Base article describing how to add additional tests is available on the Mbed TLS website](https://tls.mbed.org/kb/development/test_suites). + +A test script `tests/scripts/basic-build-test.sh` is available to show test coverage of the library. New code contributions should provide a similar level of code coverage to that which already exists for the library. + +Sample applications, if needed, should be modified as well. + +Continuous Integration Tests +---------------------------- +Once a PR has been made, the Continuous Integration (CI) tests are triggered and run. You should follow the result of the CI tests, and fix failures. + +It is advised to enable the [githooks scripts](https://github.com/ARMmbed/mbedtls/tree/development/tests/git-scripts) prior to pushing your changes, for catching some of the issues as early as possible. + +Documentation +------------- +Mbed TLS is well documented, but if you think documentation is needed, speak out! + +1. All interfaces should be documented through Doxygen. New APIs should introduce Doxygen documentation. +1. Complex parts in the code should include comments. +1. If needed, a Readme file is advised. +1. If a [Knowledge Base (KB)](https://tls.mbed.org/kb) article should be added, write this as a comment in the PR description. +1. A [ChangeLog](https://github.com/ARMmbed/mbedtls/blob/development/ChangeLog.d/00README.md) entry should be added for this contribution. diff --git a/external/mbedtls/ChangeLog b/external/mbedtls/ChangeLog new file mode 100644 index 0000000..fe7aecd --- /dev/null +++ b/external/mbedtls/ChangeLog @@ -0,0 +1,3650 @@ +mbed TLS ChangeLog (Sorted per branch, date) + += mbed TLS 2.16.10 branch released 2021-03-12 + +Default behavior changes + * In mbedtls_rsa_context objects, the ver field was formerly documented + as always 0. It is now reserved for internal purposes and may take + different values. + +Security + * Fix a buffer overflow in mbedtls_mpi_sub_abs() when calculating + |A| - |B| where |B| is larger than |A| and has more limbs (so the + function should return MBEDTLS_ERR_MPI_NEGATIVE_VALUE). Only + applications calling mbedtls_mpi_sub_abs() directly are affected: + all calls inside the library were safe since this function is + only called with |A| >= |B|. Reported by Guido Vranken in #4042. + * Fix an errorneous estimation for an internal buffer in + mbedtls_pk_write_key_pem(). If MBEDTLS_MPI_MAX_SIZE is set to an odd + value the function might fail to write a private RSA keys of the largest + supported size. + Found by Daniel Otte, reported in #4093 and fixed in #4094, + backported in #4100. + * Fix a stack buffer overflow with mbedtls_net_poll() and + mbedtls_net_recv_timeout() when given a file descriptor that is + beyond FD_SETSIZE. Reported by FigBug in #4169. + * Guard against strong local side channel attack against base64 tables by + making access aceess to them use constant flow code. + +Bugfix + * Fix an incorrect error code if an RSA private operation glitched. + * Fix a resource leak in CTR_DRBG and HMAC_DRBG when MBEDTLS_THREADING_C + is enabled, on platforms where initializing a mutex allocates resources. + This was a regression introduced in the previous release. Reported in + #4017, #4045 and #4071. + * Ensure that calling mbedtls_rsa_free() or mbedtls_entropy_free() + twice is safe. This happens for RSA when some Mbed TLS library functions + fail. Such a double-free was not safe when MBEDTLS_THREADING_C was + enabled on platforms where freeing a mutex twice is not safe. + * Fix a resource leak in a bad-arguments case of mbedtls_rsa_gen_key() + when MBEDTLS_THREADING_C is enabled on platforms where initializing + a mutex allocates resources. + * This change makes 'mbedtls_x509write_crt_set_basic_constraints' + consistent with RFC 5280 4.2.1.9 which says: "Conforming CAs MUST + include this extension in all CA certificates that contain public keys + used to validate digital signatures on certificates and MUST mark the + extension as critical in such certificates." Previous to this change, + the extension was always marked as non-critical. This was fixed by + #4044. + += mbed TLS 2.16.9 branch released 2020-12-11 + +Security + * Limit the size of calculations performed by mbedtls_mpi_exp_mod to + MBEDTLS_MPI_MAX_SIZE to prevent a potential denial of service when + generating Diffie-Hellman key pairs. Credit to OSS-Fuzz. + * A failure of the random generator was ignored in mbedtls_mpi_fill_random(), + which is how most uses of randomization in asymmetric cryptography + (including key generation, intermediate value randomization and blinding) + are implemented. This could cause failures or the silent use of non-random + values. A random generator can fail if it needs reseeding and cannot not + obtain entropy, or due to an internal failure (which, for Mbed TLS's own + CTR_DRBG or HMAC_DRBG, can only happen due to a misconfiguration). + * Fix a compliance issue whereby we were not checking the tag on the + algorithm parameters (only the size) when comparing the signature in the + description part of the cert to the real signature. This meant that a + NULL algorithm parameters entry would look identical to an array of REAL + (size zero) to the library and thus the certificate would be considered + valid. However, if the parameters do not match in *any* way then the + certificate should be considered invalid, and indeed OpenSSL marks these + certs as invalid when mbedtls did not. + Many thanks to guidovranken who found this issue via differential fuzzing + and reported it in #3629. + * Zeroising of local buffers and variables which are used for calculations + in mbedtls_pkcs5_pbkdf2_hmac(), mbedtls_internal_sha*_process(), + mbedtls_internal_md*_process() and mbedtls_internal_ripemd160_process() + functions to erase sensitive data from memory. Reported by + Johan Malmgren and Johan Uppman Bruce from Sectra. + +Bugfix + * Fix an invalid (but nonzero) return code from mbedtls_pk_parse_subpubkey() + when the input has trailing garbage. Fixes #2512. + * Fix rsa_prepare_blinding() to retry when the blinding value is not + invertible (mod N), instead of returning MBEDTLS_ERR_RSA_RNG_FAILED. This + addresses a regression but is rare in practice (approx. 1 in 2/sqrt(N)). + Found by Synopsys Coverity, fix contributed by Peter Kolbus (Garmin). + Fixes #3647. + * Fix the build when the macro _GNU_SOURCE is defined to a non-empty value. + Fix #3432. + * Correct the default IV size for mbedtls_cipher_info_t structures using + MBEDTLS_MODE_ECB to 0, since ECB mode ciphers don't use IVs. + * Make arc4random_buf available on NetBSD and OpenBSD when _POSIX_C_SOURCE is + defined. Fix contributed in #3571. Adopted for LTS branch 2.16 in #3602. + * Fix build failures on GCC 11. Fixes #3782. + * Fix a memory leak in mbedtls_mpi_sub_abs() when the result was negative + (an error condition) and the second operand was aliased to the result. + * Fix a case in elliptic curve arithmetic where an out-of-memory condition + could go undetected, resulting in an incorrect result. + * In CTR_DRBG and HMAC_DRBG, don't reset the reseed interval in seed(). + Fixes #2927. + * In PEM writing functions, fill the trailing part of the buffer with null + bytes. This guarantees that the corresponding parsing function can read + the buffer back, which was the case for mbedtls_x509write_{crt,csr}_pem + until this property was inadvertently broken in Mbed TLS 2.19.0. + Fixes #3682. + * Fix a build failure that occurred with the MBEDTLS_AES_SETKEY_DEC_ALT + option on. In this configuration key management methods that are required + for MBEDTLS_CIPHER_MODE_XTS were excluded from the build and made it fail. + Fixes #3818. Reported by John Stroebel. + +Changes + * Reduce stack usage significantly during sliding window exponentiation. + Reported in #3591 and fix contributed in #3592 by Daniel Otte. + * Remove the zeroization of a pointer variable in AES rounds. It was valid + but spurious and misleading since it looked like a mistaken attempt to + zeroize the pointed-to buffer. Reported by Antonio de la Piedra, CEA + Leti, France. + += mbed TLS 2.16.8 branch released 2020-09-01 + +Features + * Support building on e2k (Elbrus) architecture: correctly enable + -Wformat-signedness, and fix the code that causes signed-one-bit-field + and sign-compare warnings. Contributed by makise-homura (Igor Molchanov) + . + +Security + * When checking X.509 CRLs, a certificate was only considered as revoked if + its revocationDate was in the past according to the local clock if + available. In particular, on builds without MBEDTLS_HAVE_TIME_DATE, + certificates were never considered as revoked. On builds with + MBEDTLS_HAVE_TIME_DATE, an attacker able to control the local clock (for + example, an untrusted OS attacking a secure enclave) could prevent + revocation of certificates via CRLs. Fixed by no longer checking the + revocationDate field, in accordance with RFC 5280. Reported by + yuemonangong in #3340. Reported independently and fixed by + Raoul Strackx and Jethro Beekman in #3433. + * In (D)TLS record decryption, when using a CBC ciphersuites without the + Encrypt-then-Mac extension, use constant code flow memory access patterns + to extract and check the MAC. This is an improvement to the existing + countermeasure against Lucky 13 attacks. The previous countermeasure was + effective against network-based attackers, but less so against local + attackers. The new countermeasure defends against local attackers, even + if they have access to fine-grained measurements. In particular, this + fixes a local Lucky 13 cache attack found and reported by Tuba Yavuz, + Farhaan Fowze, Ken (Yihan) Bai, Grant Hernandez, and Kevin Butler + (University of Florida) and Dave Tian (Purdue University). + * Fix side channel in RSA private key operations and static (finite-field) + Diffie-Hellman. An adversary with precise enough timing and memory access + information (typically an untrusted operating system attacking a secure + enclave) could bypass an existing counter-measure (base blinding) and + potentially fully recover the private key. + * Fix a 1-byte buffer overread in mbedtls_x509_crl_parse_der(). + Credit to OSS-Fuzz for detecting the problem and to Philippe Antoine + for pinpointing the problematic code. + * Zeroising of plaintext buffers in mbedtls_ssl_read() to erase unused + application data from memory. Reported in #689 by + Johan Uppman Bruce of Sectra. + +Bugfix + * Avoid use of statically sized stack buffers for certificate writing. + This previously limited the maximum size of DER encoded certificates + in mbedtls_x509write_crt_der() to 2Kb. Reported by soccerGB in #2631. + * Reduce the stack consumption of mbedtls_x509write_csr_der() which + previously could lead to stack overflow on constrained devices. + Contributed by Doru Gucea and Simon Leet in #3464. + * Use arc4random_buf on NetBSD instead of rand implementation with cyclical + lower bits. Fix contributed in #3540. + * Fix building library/net_sockets.c and the ssl_mail_client program on + NetBSD. NetBSD conditionals were added for the backport to avoid the risk + of breaking a platform. Original fix contributed by Nia Alarie in #3422. + Adapted for long-term support branch 2.16 in #3558. + * Fix bug in redirection of unit test outputs on platforms where stdout is + defined as a macro. First reported in #2311 and fix contributed in #3528. + Adopted for LTS branch 2.16 in #3601. + +Changes + * Update copyright notices to use Linux Foundation guidance. As a result, + the copyright of contributors other than Arm is now acknowledged, and the + years of publishing are no longer tracked in the source files. This also + eliminates the need for the lines declaring the files to be part of + MbedTLS. Fixes #3457. + += mbed TLS 2.16.7 branch released 2020-07-01 + +Security + * Fix a side channel vulnerability in modular exponentiation that could + reveal an RSA private key used in a secure enclave. Noticed by Sangho Lee, + Ming-Wei Shih, Prasun Gera, Taesoo Kim and Hyesoon Kim (Georgia Institute + of Technology); and Marcus Peinado (Microsoft Research). Reported by Raoul + Strackx (Fortanix) in #3394. + * Fix side channel in mbedtls_ecp_check_pub_priv() and + mbedtls_pk_parse_key() / mbedtls_pk_parse_keyfile() (when loading a + private key that didn't include the uncompressed public key), as well as + mbedtls_ecp_mul() / mbedtls_ecp_mul_restartable() when called with a NULL + f_rng argument. An attacker with access to precise enough timing and + memory access information (typically an untrusted operating system + attacking a secure enclave) could fully recover the ECC private key. + Found and reported by Alejandro Cabrera Aldaya and Billy Brumley. + * Fix issue in Lucky 13 counter-measure that could make it ineffective when + hardware accelerators were used (using one of the MBEDTLS_SHAxxx_ALT + macros). This would cause the original Lucky 13 attack to be possible in + those configurations, allowing an active network attacker to recover + plaintext after repeated timing measurements under some conditions. + Reported and fix suggested by Luc Perneel in #3246. + +Bugfix + * Fix the Visual Studio Release x64 build configuration for mbedtls itself. + Completes a previous fix in Mbed TLS 2.16.3 that only fixed the build for + the example programs. Reported in #1430 and fix contributed by irwir. + * Fix undefined behavior in X.509 certificate parsing if the + pathLenConstraint basic constraint value is equal to INT_MAX. + The actual effect with almost every compiler is the intended + behavior, so this is unlikely to be exploitable anywhere. #3197 + * Include asn1.h in error.c. Fixes #3328 reported by David Hu. + * Fix potential memory leaks in ecp_randomize_jac() and ecp_randomize_mxz() + when PRNG function fails. Contributed by Jonas Lejeune in #3318. + * Add additional bounds checks in ssl_write_client_hello() preventing + output buffer overflow if the configuration declared a buffer that was + too small. + +Changes + * Unify the example programs termination to call mbedtls_exit() instead of + using a return command. This has been done to enable customization of the + behavior in bare metal environments. + * Abort the ClientHello writing function as soon as some extension doesn't + fit into the record buffer. Previously, such extensions were silently + dropped. As a consequence, the TLS handshake now fails when the output + buffer is not large enough to hold the ClientHello. + * The ECP module, enabled by `MBEDTLS_ECP_C`, now depends on + `MBEDTLS_CTR_DRBG_C`, `MBEDTLS_HMAC_DRBG_C`, `MBEDTLS_SHA512_C` or + `MBEDTLS_SHA256_C` for some side-channel coutermeasures. If side channels + are not a concern, this dependency can be avoided by enabling the new + option `MBEDTLS_ECP_NO_INTERNAL_RNG`. + += mbed TLS 2.16.6 branch released 2020-04-14 + +Security + * Fix side channel in ECC code that allowed an adversary with access to + precise enough timing and memory access information (typically an + untrusted operating system attacking a secure enclave) to fully recover + an ECDSA private key. Found and reported by Alejandro Cabrera Aldaya, + Billy Brumley and Cesar Pereida Garcia. CVE-2020-10932 + * Fix a potentially remotely exploitable buffer overread in a + DTLS client when parsing the Hello Verify Request message. + +Bugfix + * Fix compilation failure when both MBEDTLS_SSL_PROTO_DTLS and + MBEDTLS_SSL_HW_RECORD_ACCEL are enabled. + * Fix a function name in a debug message. Contributed by Ercan Ozturk in + #3013. + += mbed TLS 2.16.5 branch released 2020-02-20 + +Security + * Fix potential memory overread when performing an ECDSA signature + operation. The overread only happens with cryptographically low + probability (of the order of 2^-n where n is the bitsize of the curve) + unless the RNG is broken, and could result in information disclosure or + denial of service (application crash or extra resource consumption). + Found by Auke Zeilstra and Peter Schwabe, using static analysis. + * To avoid a side channel vulnerability when parsing an RSA private key, + read all the CRT parameters from the DER structure rather than + reconstructing them. Found by Alejandro Cabrera Aldaya and Billy Bob + Brumley. Reported and fix contributed by Jack Lloyd. + ARMmbed/mbed-crypto#352 + +Bugfix + * Fix an unchecked call to mbedtls_md() in the x509write module. + * Fix a bug in mbedtls_pk_parse_key() that would cause it to accept some + RSA keys that would later be rejected by functions expecting private + keys. Found by Catena cyber using oss-fuzz (issue 20467). + * Fix a bug in mbedtls_pk_parse_key() that would cause it to accept some + RSA keys with invalid values by silently fixing those values. + += mbed TLS 2.16.4 branch released 2020-01-15 + +Security + * Fix side channel vulnerability in ECDSA. Our bignum implementation is not + constant time/constant trace, so side channel attacks can retrieve the + blinded value, factor it (as it is smaller than RSA keys and not guaranteed + to have only large prime factors), and then, by brute force, recover the + key. Reported by Alejandro Cabrera Aldaya and Billy Brumley. + * Zeroize local variables in mbedtls_internal_aes_encrypt() and + mbedtls_internal_aes_decrypt() before exiting the function. The value of + these variables can be used to recover the last round key. To follow best + practice and to limit the impact of buffer overread vulnerabilities (like + Heartbleed) we need to zeroize them before exiting the function. + Issue reported by Tuba Yavuz, Farhaan Fowze, Ken (Yihang) Bai, + Grant Hernandez, and Kevin Butler (University of Florida) and + Dave Tian (Purdue University). + * Fix side channel vulnerability in ECDSA key generation. Obtaining precise + timings on the comparison in the key generation enabled the attacker to + learn leading bits of the ephemeral key used during ECDSA signatures and to + recover the private key. Reported by Jeremy Dubeuf. + * Catch failure of AES functions in mbedtls_ctr_drbg_random(). Uncaught + failures could happen with alternative implementations of AES. Bug + reported and fix proposed by Johan Uppman Bruce and Christoffer Lauri, + Sectra. + +Bugfix + * Remove redundant line for getting the bitlen of a bignum, since the variable + holding the returned value is overwritten a line after. + Found by irwir in #2377. + * Support mbedtls_hmac_drbg_set_entropy_len() and + mbedtls_ctr_drbg_set_entropy_len() before the DRBG is seeded. Before, + the initial seeding always reset the entropy length to the compile-time + default. + +Changes + * Add unit tests for AES-GCM when called through mbedtls_cipher_auth_xxx() + from the cipher abstraction layer. Fixes #2198. + * Clarify how the interface of the CTR_DRBG and HMAC modules relates to + NIST SP 800-90A. In particular CTR_DRBG requires an explicit nonce + to achieve a 256-bit strength if MBEDTLS_ENTROPY_FORCE_SHA256 is set. + += mbed TLS 2.16.3 branch released 2019-09-06 + +Security + * Fix a missing error detection in ECJPAKE. This could have caused a + predictable shared secret if a hardware accelerator failed and the other + side of the key exchange had a similar bug. + * The deterministic ECDSA calculation reused the scheme's HMAC-DRBG to + implement blinding. Because of this for the same key and message the same + blinding value was generated. This reduced the effectiveness of the + countermeasure and leaked information about the private key through side + channels. Reported by Jack Lloyd. + * When writing a private EC key, use a constant size for the private + value, as specified in RFC 5915. Previously, the value was written + as an ASN.1 INTEGER, which caused the size of the key to leak + about 1 bit of information on average and could cause the value to be + 1 byte too large for the output buffer. + +API Changes + * The new function mbedtls_ecdsa_sign_det_ext() is similar to + mbedtls_ecdsa_sign_det() but allows passing an external RNG for the + purpose of blinding. + +Bugfix + * Fix to allow building test suites with any warning that detects unused + functions. Fixes #1628. + * Fix typo in net_would_block(). Fixes #528 reported by github-monoculture. + * Remove redundant include file in timing.c. Fixes #2640 reported by irwir. + * Fix Visual Studio Release x64 build configuration by inheriting + PlatformToolset from the project configuration. Fixes #1430 reported by + irwir. + * Enable Suite B with subset of ECP curves. Make sure the code compiles even + if some curves are not defined. Fixes #1591 reported by dbedev. + * Fix misuse of signed arithmetic in the HAVEGE module. #2598 + * Update test certificates that were about to expire. Reported by + Bernhard M. Wiedemann in #2357. + * Fix the build on ARMv5TE in ARM mode to not use assembly instructions + that are only available in Thumb mode. Fix contributed by Aurelien Jarno + in #2169. + * Fix undefined memset(NULL) call in test_suite_nist_kw. + * Make NV seed test support MBEDTLS_ENTROPY_FORCE_SHA256. + * Fix propagation of restart contexts in restartable EC operations. + This could previously lead to segmentation faults in builds using an + address-sanitizer and enabling but not using MBEDTLS_ECP_RESTARTABLE. + * Fix memory leak in in mpi_miller_rabin(). Contributed by + Jens Wiklander in #2363 + * Improve code clarity in x509_crt module, removing false-positive + uninitialized variable warnings on some recent toolchains (GCC8, etc). + Discovered and fixed by Andy Gross (Linaro), #2392. + * Zero length buffer check for undefined behavior in + mbedtls_platform_zeroize(). Fixes ARMmbed/mbed-crypto#49. + * Fix bug in endianness conversion in bignum module. This lead to + functionally incorrect code on bigendian systems which don't have + __BYTE_ORDER__ defined. Reported by Brendan Shanks. Fixes #2622. + +Changes + * Make it easier to define MBEDTLS_PARAM_FAILED as assert (which config.h + suggests). #2671 + * Make `make clean` clean all programs always. Fixes #1862. + += mbed TLS 2.16.2 branch released 2019-06-11 + +Security + * Make mbedtls_ecdh_get_params return an error if the second key + belongs to a different group from the first. Before, if an application + passed keys that belonged to different group, the first key's data was + interpreted according to the second group, which could lead to either + an error or a meaningless output from mbedtls_ecdh_get_params. In the + latter case, this could expose at most 5 bits of the private key. + +Bugfix + * Server's RSA certificate in certs.c was SHA-1 signed. In the default + mbedTLS configuration only SHA-2 signed certificates are accepted. + This certificate is used in the demo server programs, which lead the + client programs to fail at the peer's certificate verification + due to an unacceptable hash signature. The certificate has been + updated to one that is SHA-256 signed. Fix contributed by + Illya Gerasymchuk. + * Fix private key DER output in the key_app_writer example. File contents + were shifted by one byte, creating an invalid ASN.1 tag. Fixed by + Christian Walther in #2239. + * Fix potential memory leak in X.509 self test. Found and fixed by + Junhwan Park, #2106. + * Reduce stack usage of hkdf tests. Fixes #2195. + * Fix 1-byte buffer overflow in mbedtls_mpi_write_string() when + used with negative inputs. Found by Guido Vranken in #2404. Credit to + OSS-Fuzz. + * Fix bugs in the AEAD test suite which would be exposed by ciphers which + either used both encrypt and decrypt key schedules, or which perform padding. + GCM and CCM were not affected. Fixed by Jack Lloyd. + * Fix incorrect default port number in ssl_mail_client example's usage. + Found and fixed by irwir. #2337 + * Add missing parentheses around parameters in the definition of the + public macro MBEDTLS_X509_ID_FLAG. This could lead to invalid evaluation + in case operators binding less strongly than subtraction were used + for the parameter. + * Add a check for MBEDTLS_X509_CRL_PARSE_C in ssl_server2, guarding the crl + sni entry parameter. Reported by inestlerode in #560. + * Add DER-encoded test CRTs to library/certs.c, allowing + the example programs ssl_server2 and ssl_client2 to be run + if MBEDTLS_FS_IO and MBEDTLS_PEM_PARSE_C are unset. Fixes #2254. + * Fix missing bounds checks in X.509 parsing functions that could + lead to successful parsing of ill-formed X.509 CRTs. Fixes #2437. + * Fix multiple X.509 functions previously returning ASN.1 low-level error + codes to always wrap these codes into X.509 high level error codes before + returning. Fixes #2431. + +Changes + * Return from various debugging routines immediately if the + provided SSL context is unset. + * Remove dead code from bignum.c in the default configuration. + Found by Coverity, reported and fixed by Peter Kolbus (Garmin). Fixes #2309. + * Add test for minimal value of MBEDTLS_MPI_WINDOW_SIZE to all.sh. + Contributed by Peter Kolbus (Garmin). + * Change wording in the `mbedtls_ssl_conf_max_frag_len()`'s documentation to + improve clarity. Fixes #2258. + * Replace multiple uses of MD2 by SHA-256 in X.509 test suite. Fixes #821. + += mbed TLS 2.16.1 branch released 2019-03-19 + +Features + * Add MBEDTLS_REMOVE_3DES_CIPHERSUITES to allow removing 3DES ciphersuites + from the default list (enabled by default). See + https://sweet32.info/SWEET32_CCS16.pdf. + +Bugfix + * Fix a compilation issue with mbedtls_ecp_restart_ctx not being defined + when MBEDTLS_ECP_ALT is defined. Reported by jwhui. Fixes #2242. + * Run the AD too long test only if MBEDTLS_CCM_ALT is not defined. + Raised as a comment in #1996. + * Reduce the stack consumption of mbedtls_mpi_fill_random() which could + previously lead to a stack overflow on constrained targets. + * Add `MBEDTLS_SELF_TEST` for the mbedtls_self_test functions + in the header files, which missed the precompilation check. #971 + * Fix clobber list in MIPS assembly for large integer multiplication. + Previously, this could lead to functionally incorrect assembly being + produced by some optimizing compilers, showing up as failures in + e.g. RSA or ECC signature operations. Reported in #1722, fix suggested + by Aurelien Jarno and submitted by Jeffrey Martin. + * Fix signed-to-unsigned integer conversion warning + in X.509 module. Fixes #2212. + * Reduce stack usage of `mpi_write_hlp()` by eliminating recursion. + Fixes #2190. + * Remove a duplicate #include in a sample program. Fixed by Masashi Honma #2326. + * Remove the mbedtls namespacing from the header file, to fix a "file not found" + build error. Fixed by Haijun Gu #2319. + * Fix returning the value 1 when mbedtls_ecdsa_genkey failed. + * Fix false failure in all.sh when backup files exist in include/mbedtls + (e.g. config.h.bak). Fixed by Peter Kolbus (Garmin) #2407. + * Ensure that unused bits are zero when writing ASN.1 bitstrings when using + mbedtls_asn1_write_bitstring(). + * Fix issue when writing the named bitstrings in KeyUsage and NsCertType + extensions in CSRs and CRTs that caused these bitstrings to not be encoded + correctly as trailing zeroes were not accounted for as unused bits in the + leading content octet. Fixes #1610. + +Changes + * Include configuration file in all header files that use configuration, + instead of relying on other header files that they include. + Inserted as an enhancement for #1371 + * Add support for alternative CSR headers, as used by Microsoft and defined + in RFC 7468. Found by Michael Ernst. Fixes #767. + * Fix configuration queries in ssl-opt.h. #2030 + * Ensure that ssl-opt.h can be run in OS X. #2029 + * Reduce the complexity of the timing tests. They were assuming more than the + underlying OS actually guarantees. + * Re-enable certain interoperability tests in ssl-opt.sh which had previously + been disabled for lack of a sufficiently recent version of GnuTLS on the CI. + * Ciphersuites based on 3DES now have the lowest priority by default when + they are enabled. + += mbed TLS 2.16.0 branch released 2018-12-21 + +Features + * Add a new config.h option of MBEDTLS_CHECK_PARAMS that enables validation + of parameters in the API. This allows detection of obvious misuses of the + API, such as passing NULL pointers. The API of existing functions hasn't + changed, but requirements on parameters have been made more explicit in + the documentation. See the corresponding API documentation for each + function to see for which parameter values it is defined. This feature is + disabled by default. See its API documentation in config.h for additional + steps you have to take when enabling it. + +API Changes + * The following functions in the random generator modules have been + deprecated and replaced as shown below. The new functions change + the return type from void to int to allow returning error codes when + using MBEDTLS__ALT for the underlying AES or message digest + primitive. Fixes #1798. + mbedtls_ctr_drbg_update() -> mbedtls_ctr_drbg_update_ret() + mbedtls_hmac_drbg_update() -> mbedtls_hmac_drbg_update_ret() + * Extend ECDH interface to enable alternative implementations. + * Deprecate error codes of the form MBEDTLS_ERR_xxx_INVALID_KEY_LENGTH for + ARIA, CAMELLIA and Blowfish. These error codes will be replaced by + the more generic per-module error codes MBEDTLS_ERR_xxx_BAD_INPUT_DATA. + * Additional parameter validation checks have been added for the following + modules - AES, ARIA, Blowfish, CAMELLIA, CCM, GCM, DHM, ECP, ECDSA, ECDH, + ECJPAKE, SHA, Chacha20 and Poly1305, cipher, pk, RSA, and MPI. + Where modules have had parameter validation added, existing parameter + checks may have changed. Some modules, such as Chacha20 had existing + parameter validation whereas other modules had little. This has now been + changed so that the same level of validation is present in all modules, and + that it is now optional with the MBEDTLS_CHECK_PARAMS flag which by default + is off. That means that checks which were previously present by default + will no longer be. + +New deprecations + * Deprecate mbedtls_ctr_drbg_update and mbedtls_hmac_drbg_update + in favor of functions that can return an error code. + +Bugfix + * Fix for Clang, which was reporting a warning for the bignum.c inline + assembly for AMD64 targets creating string literals greater than those + permitted by the ISO C99 standard. Found by Aaron Jones. Fixes #482. + * Fix runtime error in `mbedtls_platform_entropy_poll()` when run + through qemu user emulation. Reported and fix suggested by randombit + in #1212. Fixes #1212. + * Fix an unsafe bounds check when restoring an SSL session from a ticket. + This could lead to a buffer overflow, but only in case ticket authentication + was broken. Reported and fix suggested by Guido Vranken in #659. + * Add explicit integer to enumeration type casts to example program + programs/pkey/gen_key which previously led to compilation failure + on some toolchains. Reported by phoenixmcallister. Fixes #2170. + * Fix double initialization of ECC hardware that made some accelerators + hang. + * Clarify documentation of mbedtls_ssl_set_own_cert() regarding the absence + of check for certificate/key matching. Reported by Attila Molnar, #507. + += mbed TLS 2.14.1 branch released 2018-11-30 + +Security + * Fix timing variations and memory access variations in RSA PKCS#1 v1.5 + decryption that could lead to a Bleichenbacher-style padding oracle + attack. In TLS, this affects servers that accept ciphersuites based on + RSA decryption (i.e. ciphersuites whose name contains RSA but not + (EC)DH(E)). Discovered by Eyal Ronen (Weizmann Institute), Robert Gillham + (University of Adelaide), Daniel Genkin (University of Michigan), + Adi Shamir (Weizmann Institute), David Wong (NCC Group), and Yuval Yarom + (University of Adelaide, Data61). The attack is described in more detail + in the paper available here: http://cat.eyalro.net/cat.pdf CVE-2018-19608 + * In mbedtls_mpi_write_binary(), don't leak the exact size of the number + via branching and memory access patterns. An attacker who could submit + a plaintext for RSA PKCS#1 v1.5 decryption but only observe the timing + of the decryption and not its result could nonetheless decrypt RSA + plaintexts and forge RSA signatures. Other asymmetric algorithms may + have been similarly vulnerable. Reported by Eyal Ronen, Robert Gillham, + Daniel Genkin, Adi Shamir, David Wong and Yuval Yarom. + * Wipe sensitive buffers on the stack in the CTR_DRBG and HMAC_DRBG + modules. + +API Changes + * The new functions mbedtls_ctr_drbg_update_ret() and + mbedtls_hmac_drbg_update_ret() are similar to mbedtls_ctr_drbg_update() + and mbedtls_hmac_drbg_update() respectively, but the new functions + report errors whereas the old functions return void. We recommend that + applications use the new functions. + += mbed TLS 2.14.0 branch released 2018-11-19 + +Security + * Fix overly strict DN comparison when looking for CRLs belonging to a + particular CA. This previously led to ignoring CRLs when the CRL's issuer + name and the CA's subject name differed in their string encoding (e.g., + one using PrintableString and the other UTF8String) or in the choice of + upper and lower case. Reported by Henrik Andersson of Bosch GmbH in issue + #1784. + * Fix a flawed bounds check in server PSK hint parsing. In case the + incoming message buffer was placed within the first 64KiB of address + space and a PSK-(EC)DHE ciphersuite was used, this allowed an attacker + to trigger a memory access up to 64KiB beyond the incoming message buffer, + potentially leading to an application crash or information disclosure. + * Fix mbedtls_mpi_is_prime() to use more rounds of probabilistic testing. The + previous settings for the number of rounds made it practical for an + adversary to construct non-primes that would be erroneously accepted as + primes with high probability. This does not have an impact on the + security of TLS, but can matter in other contexts with numbers chosen + potentially by an adversary that should be prime and can be validated. + For example, the number of rounds was enough to securely generate RSA key + pairs or Diffie-Hellman parameters, but was insufficient to validate + Diffie-Hellman parameters properly. + See "Prime and Prejudice" by by Martin R. Albrecht and Jake Massimo and + Kenneth G. Paterson and Juraj Somorovsky. + +Features + * Add support for temporarily suspending expensive ECC computations after + some configurable amount of operations. This is intended to be used in + constrained, single-threaded systems where ECC is time consuming and can + block other operations until they complete. This is disabled by default, + but can be enabled by MBEDTLS_ECP_RESTARTABLE at compile time and + configured by mbedtls_ecp_set_max_ops() at runtime. It applies to the new + xxx_restartable functions in ECP, ECDSA, PK and X.509 (CRL not supported + yet), and to existing functions in ECDH and SSL (currently only + implemented client-side, for ECDHE-ECDSA ciphersuites in TLS 1.2, + including client authentication). + * Add support for Arm CPU DSP extensions to accelerate asymmetric key + operations. On CPUs where the extensions are available, they can accelerate + MPI multiplications used in ECC and RSA cryptography. Contributed by + Aurelien Jarno. + * Extend RSASSA-PSS signature to allow a smaller salt size. Previously, PSS + signature always used a salt with the same length as the hash, and returned + an error if this was not possible. Now the salt size may be up to two bytes + shorter. This allows the library to support all hash and signature sizes + that comply with FIPS 186-4, including SHA-512 with a 1024-bit key. + * Add support for 128-bit keys in CTR_DRBG. Note that using keys shorter + than 256 bits limits the security of generated material to 128 bits. + +API Changes + * Add a common error code of `MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED` for + a feature that is not supported by underlying alternative + implementations implementing cryptographic primitives. This is useful for + hardware accelerators that don't implement all options or features. + +New deprecations + * All module specific errors following the form + MBEDTLS_ERR_XXX_FEATURE_UNAVAILABLE that indicate a feature is not + supported are deprecated and are now replaced by the new equivalent + platform error. + * All module specific generic hardware acceleration errors following the + form MBEDTLS_ERR_XXX_HW_ACCEL_FAILED that are deprecated and are replaced + by the equivalent plaform error. + * Deprecate the function mbedtls_mpi_is_prime() in favor of + mbedtls_mpi_is_prime_ext() which allows specifying the number of + Miller-Rabin rounds. + +Bugfix + * Fix wrong order of freeing in programs/ssl/ssl_server2 example + application leading to a memory leak in case both + MBEDTLS_MEMORY_BUFFER_ALLOC_C and MBEDTLS_MEMORY_BACKTRACE are set. + Fixes #2069. + * Fix a bug in the update function for SSL ticket keys which previously + invalidated keys of a lifetime of less than a 1s. Fixes #1968. + * Fix failure in hmac_drbg in the benchmark sample application, when + MBEDTLS_THREADING_C is defined. Found by TrinityTonic, #1095 + * Fix a bug in the record decryption routine ssl_decrypt_buf() + which lead to accepting properly authenticated but improperly + padded records in case of CBC ciphersuites using Encrypt-then-MAC. + * Fix memory leak and freeing without initialization in the example + program programs/x509/cert_write. Fixes #1422. + * Ignore IV in mbedtls_cipher_set_iv() when the cipher mode is + MBEDTLS_MODE_ECB. Found by ezdevelop. Fixes #1091. + * Zeroize memory used for buffering or reassembling handshake messages + after use. + * Use `mbedtls_platform_zeroize()` instead of `memset()` for zeroization + of sensitive data in the example programs aescrypt2 and crypt_and_hash. + * Change the default string format used for various X.509 DN attributes to + UTF8String. Previously, the use of the PrintableString format led to + wildcards and non-ASCII characters being unusable in some DN attributes. + Reported by raprepo in #1860 and by kevinpt in #468. Fix contributed by + Thomas-Dee. + * Fix compilation failure for configurations which use compile time + replacements of standard calloc/free functions through the macros + MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_FREE_MACRO. + Reported by ole-de and ddhome2006. Fixes #882, #1642 and #1706. + +Changes + * Removed support for Yotta as a build tool. + * Add tests for session resumption in DTLS. + * Close a test gap in (D)TLS between the client side and the server side: + test the handling of large packets and small packets on the client side + in the same way as on the server side. + * Change the dtls_client and dtls_server samples to work by default over + IPv6 and optionally by a build option over IPv4. + * Change the use of Windows threading to use Microsoft Visual C++ runtime + calls, rather than Win32 API calls directly. This is necessary to avoid + conflict with C runtime usage. Found and fixed by irwir. + * Remember the string format of X.509 DN attributes when replicating + X.509 DNs. Previously, DN attributes were always written in their default + string format (mostly PrintableString), which could lead to CRTs being + created which used PrintableStrings in the issuer field even though the + signing CA used UTF8Strings in its subject field; while X.509 compliant, + such CRTs were rejected in some applications, e.g. some versions of + Firefox, curl and GnuTLS. Reported in #1033 by Moschn. Fix contributed by + Thomas-Dee. + * Improve documentation of mbedtls_ssl_get_verify_result(). + Fixes #517 reported by github-monoculture. + * Add MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR flag to mbedtls_mpi_gen_prime() and + use it to reduce error probability in RSA key generation to levels mandated + by FIPS-186-4. + += mbed TLS 2.13.1 branch released 2018-09-06 + +API Changes + * Extend the platform module with an abstraction mbedtls_platform_gmtime_r() + whose implementation should behave as a thread-safe version of gmtime(). + This allows users to configure such an implementation at compile time when + the target system cannot be deduced automatically, by setting the option + MBEDTLS_PLATFORM_GMTIME_R_ALT. At this stage Mbed TLS is only able to + automatically select implementations for Windows and POSIX C libraries. + +Bugfix + * Fix build failures on platforms where only gmtime() is available but + neither gmtime_r() nor gmtime_s() are present. Fixes #1907. + += mbed TLS 2.13.0 branch released 2018-08-31 + +Security + * Fix an issue in the X.509 module which could lead to a buffer overread + during certificate extensions parsing. In case of receiving malformed + input (extensions length field equal to 0), an illegal read of one byte + beyond the input buffer is made. Found and analyzed by Nathan Crandall. + +Features + * Add support for fragmentation of outgoing DTLS handshake messages. This + is controlled by the maximum fragment length as set locally or negotiated + with the peer, as well as by a new per-connection MTU option, set using + mbedtls_ssl_set_mtu(). + * Add support for auto-adjustment of MTU to a safe value during the + handshake when flights do not get through (RFC 6347, section 4.1.1.1, + last paragraph). + * Add support for packing multiple records within a single datagram, + enabled by default. + * Add support for buffering out-of-order handshake messages in DTLS. + The maximum amount of RAM used for this can be controlled by the + compile-time constant MBEDTLS_SSL_DTLS_MAX_BUFFERING defined + in mbedtls/config.h. + +API Changes + * Add function mbedtls_ssl_set_datagram_packing() to configure + the use of datagram packing (enabled by default). + +Bugfix + * Fix a potential memory leak in mbedtls_ssl_setup() function. An allocation + failure in the function could lead to other buffers being leaked. + * Fixes an issue with MBEDTLS_CHACHAPOLY_C which would not compile if + MBEDTLS_ARC4_C and MBEDTLS_CIPHER_NULL_CIPHER weren't also defined. #1890 + * Fix a memory leak in ecp_mul_comb() if ecp_precompute_comb() fails. + Fix contributed by Espressif Systems. + * Add ecc extensions only if an ecc based ciphersuite is used. + This improves compliance to RFC 4492, and as a result, solves + interoperability issues with BouncyCastle. Raised by milenamil in #1157. + * Replace printf with mbedtls_printf in the ARIA module. Found by + TrinityTonic in #1908. + * Fix potential use-after-free in mbedtls_ssl_get_max_frag_len() + and mbedtls_ssl_get_record_expansion() after a session reset. Fixes #1941. + * Fix a bug that caused SSL/TLS clients to incorrectly abort the handshake + with TLS versions 1.1 and earlier when the server requested authentication + without providing a list of CAs. This was due to an overly strict bounds + check in parsing the CertificateRequest message, + introduced in Mbed TLS 2.12.0. Fixes #1954. + * Fix a miscalculation of the maximum record expansion in + mbedtls_ssl_get_record_expansion() in case of ChachaPoly ciphersuites, + or CBC ciphersuites in (D)TLS versions 1.1 or higher. Fixes #1913, #1914. + * Fix undefined shifts with negative values in certificates parsing + (found by Catena cyber using oss-fuzz) + * Fix memory leak and free without initialization in pk_encrypt + and pk_decrypt example programs. Reported by Brace Stout. Fixes #1128. + * Remove redundant else statement. Raised by irwir. Fixes #1776. + +Changes + * Copy headers preserving timestamps when doing a "make install". + Contributed by xueruini. + * Allow the forward declaration of public structs. Contributed by Dawid + Drozd. Fixes #1215 raised by randombit. + * Improve compatibility with some alternative CCM implementations by using + CCM test vectors from RAM. + * Add support for buffering of out-of-order handshake messages. + * Add warnings to the documentation of the HKDF module to reduce the risk + of misusing the mbedtls_hkdf_extract() and mbedtls_hkdf_expand() + functions. Fixes #1775. Reported by Brian J. Murray. + += mbed TLS 2.12.0 branch released 2018-07-25 + +Security + * Fix a vulnerability in TLS ciphersuites based on CBC and using SHA-384, + in (D)TLS 1.0 to 1.2, that allowed an active network attacker to + partially recover the plaintext of messages under some conditions by + exploiting timing measurements. With DTLS, the attacker could perform + this recovery by sending many messages in the same connection. With TLS + or if mbedtls_ssl_conf_dtls_badmac_limit() was used, the attack only + worked if the same secret (for example a HTTP Cookie) has been repeatedly + sent over connections manipulated by the attacker. Connections using GCM + or CCM instead of CBC, using hash sizes other than SHA-384, or using + Encrypt-then-Mac (RFC 7366) were not affected. The vulnerability was + caused by a miscalculation (for SHA-384) in a countermeasure to the + original Lucky 13 attack. Found by Kenny Paterson, Eyal Ronen and Adi + Shamir. + * Fix a vulnerability in TLS ciphersuites based on CBC, in (D)TLS 1.0 to + 1.2, that allowed a local attacker, able to execute code on the local + machine as well as manipulate network packets, to partially recover the + plaintext of messages under some conditions by using a cache attack + targeting an internal MD/SHA buffer. With TLS or if + mbedtls_ssl_conf_dtls_badmac_limit() was used, the attack only worked if + the same secret (for example a HTTP Cookie) has been repeatedly sent over + connections manipulated by the attacker. Connections using GCM or CCM + instead of CBC or using Encrypt-then-Mac (RFC 7366) were not affected. + Found by Kenny Paterson, Eyal Ronen and Adi Shamir. + * Add a counter-measure against a vulnerability in TLS ciphersuites based + on CBC, in (D)TLS 1.0 to 1.2, that allowed a local attacker, able to + execute code on the local machine as well as manipulate network packets, + to partially recover the plaintext of messages under some conditions (see + previous entry) by using a cache attack targeting the SSL input record + buffer. Connections using GCM or CCM instead of CBC or using + Encrypt-then-Mac (RFC 7366) were not affected. Found by Kenny Paterson, + Eyal Ronen and Adi Shamir. + +Features + * Add new crypto primitives from RFC 7539: stream cipher Chacha20, one-time + authenticator Poly1305 and AEAD construct Chacha20-Poly1305. Contributed + by Daniel King. + * Add support for CHACHA20-POLY1305 ciphersuites from RFC 7905. + * Add platform support for the Haiku OS. (https://www.haiku-os.org). + Contributed by Augustin Cavalier. + * Make the receive and transmit buffers independent sizes, for situations + where the outgoing buffer can be fixed at a smaller size than the incoming + buffer, which can save some RAM. If buffer lengths are kept equal, there + is no functional difference. Contributed by Angus Gratton, and also + independently contributed again by Paul Sokolovsky. + * Add support for key wrapping modes based on AES as defined by + NIST SP 800-38F algorithms KW and KWP and by RFC 3394 and RFC 5649. + +Bugfix + * Fix the key_app_writer example which was writing a leading zero byte which + was creating an invalid ASN.1 tag. Found by Aryeh R. Fixes #1257. + * Fix compilation error on C++, because of a variable named new. + Found and fixed by Hirotaka Niisato in #1783. + * Fix "no symbols" warning issued by ranlib when building on Mac OS X. Fix + contributed by tabascoeye. + * Clarify documentation for mbedtls_ssl_write() to include 0 as a valid + return value. Found by @davidwu2000. #839 + * Fix a memory leak in mbedtls_x509_csr_parse(), found by catenacyber, + Philippe Antoine. Fixes #1623. + * Remove unused headers included in x509.c. Found by Chris Hanson and fixed + by Brendan Shanks. Part of a fix for #992. + * Fix compilation error when MBEDTLS_ARC4_C is disabled and + MBEDTLS_CIPHER_NULL_CIPHER is enabled. Found by TrinityTonic in #1719. + * Added length checks to some TLS parsing functions. Found and fixed by + Philippe Antoine from Catena cyber. #1663. + * Fix the inline assembly for the MPI multiply helper function for i386 and + i386 with SSE2. Found by László Langó. Fixes #1550 + * Fix namespacing in header files. Remove the `mbedtls` namespacing in + the `#include` in the header files. Resolves #857 + * Fix compiler warning of 'use before initialisation' in + mbedtls_pk_parse_key(). Found by Martin Boye Petersen and fixed by Dawid + Drozd. #1098 + * Fix decryption for zero length messages (which contain all padding) when a + CBC based ciphersuite is used together with Encrypt-then-MAC. Previously, + such a message was wrongly reported as an invalid record and therefore lead + to the connection being terminated. Seen most often with OpenSSL using + TLS 1.0. Reported by @kFYatek and by Conor Murphy on the forum. Fix + contributed by Espressif Systems. Fixes #1632 + * Fix ssl_client2 example to send application data with 0-length content + when the request_size argument is set to 0 as stated in the documentation. + Fixes #1833. + * Correct the documentation for `mbedtls_ssl_get_session()`. This API has + deep copy of the session, and the peer certificate is not lost. Fixes #926. + * Fix build using -std=c99. Fixed by Nick Wilson. + +Changes + * Fail when receiving a TLS alert message with an invalid length, or invalid + zero-length messages when using TLS 1.2. Contributed by Espressif Systems. + * Change the default behaviour of mbedtls_hkdf_extract() to return an error + when calling with a NULL salt and non-zero salt_len. Contributed by + Brian J Murray + * Change the shebang line in Perl scripts to look up perl in the PATH. + Contributed by fbrosson. + * Allow overriding the time on Windows via the platform-time abstraction. + Fixed by Nick Wilson. + * Use gmtime_r/gmtime_s for thread-safety. Fixed by Nick Wilson. + += mbed TLS 2.11.0 branch released 2018-06-18 + +Features + * Add additional block mode, OFB (Output Feedback), to the AES module and + cipher abstraction module. + * Implement the HMAC-based extract-and-expand key derivation function + (HKDF) per RFC 5869. Contributed by Thomas Fossati. + * Add support for the CCM* block cipher mode as defined in IEEE Std. 802.15.4. + * Add support for the XTS block cipher mode with AES (AES-XTS). + Contributed by Aorimn in pull request #414. + * In TLS servers, support offloading private key operations to an external + cryptoprocessor. Private key operations can be asynchronous to allow + non-blocking operation of the TLS server stack. + +Bugfix + * Fix the cert_write example to handle certificates signed with elliptic + curves as well as RSA. Fixes #777 found by dbedev. + * Fix for redefinition of _WIN32_WINNT to avoid overriding a definition + used by user applications. Found and fixed by Fabio Alessandrelli. + * Fix compilation warnings with IAR toolchain, on 32 bit platform. + Reported by rahmanih in #683 + * Fix braces in mbedtls_memory_buffer_alloc_status(). Found by sbranden, #552. + +Changes + * Changed CMake defaults for IAR to treat all compiler warnings as errors. + * Changed the Clang parameters used in the CMake build files to work for + versions later than 3.6. Versions of Clang earlier than this may no longer + work. Fixes #1072 + += mbed TLS 2.10.0 branch released 2018-06-06 + +Features + * Add support for ARIA cipher (RFC 5794) and associated TLS ciphersuites + (RFC 6209). Disabled by default, see MBEDTLS_ARIA_C in config.h + +API Changes + * Extend the platform module with a util component that contains + functionality shared by multiple Mbed TLS modules. At this stage + platform_util.h (and its associated platform_util.c) only contain + mbedtls_platform_zeroize(), which is a critical function from a security + point of view. mbedtls_platform_zeroize() needs to be regularly tested + against compilers to ensure that calls to it are not removed from the + output binary as part of redundant code elimination optimizations. + Therefore, mbedtls_platform_zeroize() is moved to the platform module to + facilitate testing and maintenance. + +Bugfix + * Fix an issue with MicroBlaze support in bn_mul.h which was causing the + build to fail. Found by zv-io. Fixes #1651. + +Changes + * Support TLS testing in out-of-source builds using cmake. Fixes #1193. + * Fix redundant declaration of mbedtls_ssl_list_ciphersuites. Raised by + TrinityTonic. #1359. + += mbed TLS 2.9.0 branch released 2018-04-30 + +Security + * Fix an issue in the X.509 module which could lead to a buffer overread + during certificate validation. Additionally, the issue could also lead to + unnecessary callback checks being made or to some validation checks to be + omitted. The overread could be triggered remotely, while the other issues + would require a non DER-compliant certificate to be correctly signed by a + trusted CA, or a trusted CA with a non DER-compliant certificate. Found by + luocm. Fixes #825. + * Fix the buffer length assertion in the ssl_parse_certificate_request() + function which led to an arbitrary overread of the message buffer. The + overreads could be caused by receiving a malformed message at the point + where an optional signature algorithms list is expected when the signature + algorithms section is too short. In builds with debug output, the overread + data is output with the debug data. + * Fix a client-side bug in the validation of the server's ciphersuite choice + which could potentially lead to the client accepting a ciphersuite it didn't + offer or a ciphersuite that cannot be used with the TLS or DTLS version + chosen by the server. This could lead to corruption of internal data + structures for some configurations. + +Features + * Add an option, MBEDTLS_AES_FEWER_TABLES, to dynamically compute smaller AES + tables during runtime, thereby reducing the RAM/ROM footprint by ~6KiB. + Suggested and contributed by jkivilin in pull request #394. + * Add initial support for Curve448 (RFC 7748). Only mbedtls_ecp_mul() and + ECDH primitive functions (mbedtls_ecdh_gen_public(), + mbedtls_ecdh_compute_shared()) are supported for now. Contributed by + Nicholas Wilson in pull request #348. + +API Changes + * Extend the public API with the function of mbedtls_net_poll() to allow user + applications to wait for a network context to become ready before reading + or writing. + * Add function mbedtls_ssl_check_pending() to the public API to allow + a check for whether more more data is pending to be processed in the + internal message buffers. + This function is necessary to determine when it is safe to idle on the + underlying transport in case event-driven IO is used. + +Bugfix + * Fix a spurious uninitialized variable warning in cmac.c. Fix independently + contributed by Brian J Murray and David Brown. + * Add missing dependencies in test suites that led to build failures + in configurations that omit certain hashes or public-key algorithms. + Fixes #1040. + * Fix C89 incompatibility in benchmark.c. Contributed by Brendan Shanks. + #1353 + * Add missing dependencies for MBEDTLS_HAVE_TIME_DATE and + MBEDTLS_VERSION_FEATURES in some test suites. Contributed by + Deomid Ryabkov. Fixes #1299, #1475. + * Fix the Makefile build process for building shared libraries on Mac OS X. + Fixed by mnacamura. + * Fix parsing of PKCS#8 encoded Elliptic Curve keys. Previously Mbed TLS was + unable to parse keys which had only the optional parameters field of the + ECPrivateKey structure. Found by Jethro Beekman, fixed in #1379. + * Return the plaintext data more quickly on unpadded CBC decryption, as + stated in the mbedtls_cipher_update() documentation. Contributed by + Andy Leiserson. + * Fix overriding and ignoring return values when parsing and writing to + a file in pk_sign program. Found by kevlut in #1142. + * Restrict usage of error code MBEDTLS_ERR_SSL_WANT_READ to situations + where data needs to be fetched from the underlying transport in order + to make progress. Previously, this error code was also occasionally + returned when unexpected messages were being discarded, ignoring that + further messages could potentially already be pending to be processed + in the internal buffers; these cases led to deadlocks when event-driven + I/O was used. Found and reported by Hubert Mis in #772. + * Fix buffer length assertions in the ssl_parse_certificate_request() + function which leads to a potential one byte overread of the message + buffer. + * Fix invalid buffer sizes passed to zlib during record compression and + decompression. + * Fix the soversion of libmbedcrypto to match the soversion of the + maintained 2.7 branch. The soversion was increased in Mbed TLS + version 2.7.1 to reflect breaking changes in that release, but the + increment was missed in 2.8.0 and later releases outside of the 2.7 branch. + +Changes + * Remove some redundant code in bignum.c. Contributed by Alexey Skalozub. + * Support cmake builds where Mbed TLS is a subproject. Fix contributed + independently by Matthieu Volat and Arne Schwabe. + * Improve testing in configurations that omit certain hashes or + public-key algorithms. Includes contributions by Gert van Dijk. + * Improve negative testing of X.509 parsing. + * Do not define global mutexes around readdir() and gmtime() in + configurations where the feature is disabled. Found and fixed by Gergely + Budai. + * Harden the function mbedtls_ssl_config_free() against misuse, so that it + doesn't leak memory if the user doesn't use mbedtls_ssl_conf_psk() and + instead incorrectly manipulates the configuration structure directly. + Found and fix submitted by junyeonLEE in #1220. + * Provide an empty implementation of mbedtls_pkcs5_pbes2() when + MBEDTLS_ASN1_PARSE_C is not enabled. This allows the use of PBKDF2 + without PBES2. Fixed by Marcos Del Sol Vives. + * Add the order of the base point as N in the mbedtls_ecp_group structure + for Curve25519 (other curves had it already). Contributed by Nicholas + Wilson #481 + * Improve the documentation of mbedtls_net_accept(). Contributed by Ivan + Krylov. + * Improve the documentation of mbedtls_ssl_write(). Suggested by + Paul Sokolovsky in #1356. + * Add an option in the Makefile to support ar utilities where the operation + letter must not be prefixed by '-', such as LLVM. Found and fixed by + Alex Hixon. + * Allow configuring the shared library extension by setting the DLEXT + environment variable when using the project makefiles. + * Optimize unnecessary zeroing in mbedtls_mpi_copy. Based on a contribution + by Alexey Skalozub in #405. + * In the SSL module, when f_send, f_recv or f_recv_timeout report + transmitting more than the required length, return an error. Raised by + Sam O'Connor in #1245. + * Improve robustness of mbedtls_ssl_derive_keys against the use of + HMAC functions with non-HMAC ciphersuites. Independently contributed + by Jiayuan Chen in #1377. Fixes #1437. + * Improve security of RSA key generation by including criteria from + FIPS 186-4. Contributed by Jethro Beekman. #1380 + * Declare functions in header files even when an alternative implementation + of the corresponding module is activated by defining the corresponding + MBEDTLS_XXX_ALT macro. This means that alternative implementations do + not need to copy the declarations, and ensures that they will have the + same API. + * Add platform setup and teardown calls in test suites. + += mbed TLS 2.8.0 branch released 2018-03-16 + +Default behavior changes + * The truncated HMAC extension now conforms to RFC 6066. This means + that when both sides of a TLS connection negotiate the truncated + HMAC extension, Mbed TLS can now interoperate with other + compliant implementations, but this breaks interoperability with + prior versions of Mbed TLS. To restore the old behavior, enable + the (deprecated) option MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT in + config.h. Found by Andreas Walz (ivESK, Offenburg University of + Applied Sciences). + +Security + * Fix implementation of the truncated HMAC extension. The previous + implementation allowed an offline 2^80 brute force attack on the + HMAC key of a single, uninterrupted connection (with no + resumption of the session). + * Verify results of RSA private key operations to defend + against Bellcore glitch attack. + * Fix a buffer overread in ssl_parse_server_key_exchange() that could cause + a crash on invalid input. + * Fix a buffer overread in ssl_parse_server_psk_hint() that could cause a + crash on invalid input. + * Fix CRL parsing to reject CRLs containing unsupported critical + extensions. Found by Falko Strenzke and Evangelos Karatsiolis. + +Features + * Extend PKCS#8 interface by introducing support for the entire SHA + algorithms family when encrypting private keys using PKCS#5 v2.0. + This allows reading encrypted PEM files produced by software that + uses PBKDF2-SHA2, such as OpenSSL 1.1. Submitted by Antonio Quartulli, + OpenVPN Inc. Fixes #1339 + * Add support for public keys encoded in PKCS#1 format. #1122 + +New deprecations + * Deprecate support for record compression (configuration option + MBEDTLS_ZLIB_SUPPORT). + +Bugfix + * Fix the name of a DHE parameter that was accidentally changed in 2.7.0. + Fixes #1358. + * Fix test_suite_pk to work on 64-bit ILP32 systems. #849 + * Fix mbedtls_x509_crt_profile_suiteb, which used to reject all certificates + with flag MBEDTLS_X509_BADCERT_BAD_PK even when the key type was correct. + In the context of SSL, this resulted in handshake failure. Reported by + daniel in the Mbed TLS forum. #1351 + * Fix Windows x64 builds with the included mbedTLS.sln file. #1347 + * Fix setting version TLSv1 as minimal version, even if TLS 1 + is not enabled. Set MBEDTLS_SSL_MIN_MAJOR_VERSION + and MBEDTLS_SSL_MIN_MINOR_VERSION instead of + MBEDTLS_SSL_MAJOR_VERSION_3 and MBEDTLS_SSL_MINOR_VERSION_1. #664 + * Fix compilation error on Mingw32 when _TRUNCATE is defined. Use _TRUNCATE + only if __MINGW32__ not defined. Fix suggested by Thomas Glanzmann and + Nick Wilson on issue #355 + * In test_suite_pk, pass valid parameters when testing for hash length + overflow. #1179 + * Fix memory allocation corner cases in memory_buffer_alloc.c module. Found + by Guido Vranken. #639 + * Log correct number of ciphersuites used in Client Hello message. #918 + * Fix X509 CRT parsing that would potentially accept an invalid tag when + parsing the subject alternative names. + * Fix a possible arithmetic overflow in ssl_parse_server_key_exchange() + that could cause a key exchange to fail on valid data. + * Fix a possible arithmetic overflow in ssl_parse_server_psk_hint() that + could cause a key exchange to fail on valid data. + * Don't define mbedtls_aes_decrypt and mbedtls_aes_encrypt under + MBEDTLS_DEPRECATED_REMOVED. #1388 + * Fix a 1-byte heap buffer overflow (read-only) during private key parsing. + Found through fuzz testing. + +Changes + * Fix tag lengths and value ranges in the documentation of CCM encryption. + Contributed by Mathieu Briand. + * Fix typo in a comment ctr_drbg.c. Contributed by Paul Sokolovsky. + * Remove support for the library reference configuration for picocoin. + * MD functions deprecated in 2.7.0 are no longer inline, to provide + a migration path for those depending on the library's ABI. + * Clarify the documentation of mbedtls_ssl_setup. + * Use (void) when defining functions with no parameters. Contributed by + Joris Aerts. #678 + += mbed TLS 2.7.0 branch released 2018-02-03 + +Security + * Fix a heap corruption issue in the implementation of the truncated HMAC + extension. When the truncated HMAC extension is enabled and CBC is used, + sending a malicious application packet could be used to selectively corrupt + 6 bytes on the peer's heap, which could potentially lead to crash or remote + code execution. The issue could be triggered remotely from either side in + both TLS and DTLS. CVE-2018-0488 + * Fix a buffer overflow in RSA-PSS verification when the hash was too large + for the key size, which could potentially lead to crash or remote code + execution. Found by Seth Terashima, Qualcomm Product Security Initiative, + Qualcomm Technologies Inc. CVE-2018-0487 + * Fix buffer overflow in RSA-PSS verification when the unmasked data is all + zeros. + * Fix an unsafe bounds check in ssl_parse_client_psk_identity() when adding + 64 KiB to the address of the SSL buffer and causing a wrap around. + * Fix a potential heap buffer overflow in mbedtls_ssl_write(). When the (by + default enabled) maximum fragment length extension is disabled in the + config and the application data buffer passed to mbedtls_ssl_write + is larger than the internal message buffer (16384 bytes by default), the + latter overflows. The exploitability of this issue depends on whether the + application layer can be forced into sending such large packets. The issue + was independently reported by Tim Nordell via e-mail and by Florin Petriuc + and sjorsdewit on GitHub. Fix proposed by Florin Petriuc in #1022. + Fixes #707. + * Add a provision to prevent compiler optimizations breaking the time + constancy of mbedtls_ssl_safer_memcmp(). + * Ensure that buffers are cleared after use if they contain sensitive data. + Changes were introduced in multiple places in the library. + * Set PEM buffer to zero before freeing it, to avoid decoded private keys + being leaked to memory after release. + * Fix dhm_check_range() failing to detect trivial subgroups and potentially + leaking 1 bit of the private key. Reported by prashantkspatil. + * Make mbedtls_mpi_read_binary() constant-time with respect to the input + data. Previously, trailing zero bytes were detected and omitted for the + sake of saving memory, but potentially leading to slight timing + differences. Reported by Marco Macchetti, Kudelski Group. + * Wipe stack buffer temporarily holding EC private exponent + after keypair generation. + * Fix a potential heap buffer over-read in ALPN extension parsing + (server-side). Could result in application crash, but only if an ALPN + name larger than 16 bytes had been configured on the server. + * Change default choice of DHE parameters from untrustworthy RFC 5114 + to RFC 3526 containing parameters generated in a nothing-up-my-sleeve + manner. + +Features + * Allow comments in test data files. + * The selftest program can execute a subset of the tests based on command + line arguments. + * New unit tests for timing. Improve the self-test to be more robust + when run on a heavily-loaded machine. + * Add alternative implementation support for CCM and CMAC (MBEDTLS_CCM_ALT, + MBEDTLS_CMAC_ALT). Submitted by Steven Cooreman, Silicon Labs. + * Add support for alternative implementations of GCM, selected by the + configuration flag MBEDTLS_GCM_ALT. + * Add support for alternative implementations for ECDSA, controlled by new + configuration flags MBEDTLS_ECDSA_SIGN_ALT, MBEDTLS_ECDSA_VERIFY_ALT and + MBEDTLS_ECDSDA_GENKEY_AT in config.h. + The following functions from the ECDSA module can be replaced + with alternative implementation: + mbedtls_ecdsa_sign(), mbedtls_ecdsa_verify() and mbedtls_ecdsa_genkey(). + * Add support for alternative implementation of ECDH, controlled by the + new configuration flags MBEDTLS_ECDH_COMPUTE_SHARED_ALT and + MBEDTLS_ECDH_GEN_PUBLIC_ALT in config.h. + The following functions from the ECDH module can be replaced + with an alternative implementation: + mbedtls_ecdh_gen_public() and mbedtls_ecdh_compute_shared(). + * Add support for alternative implementation of ECJPAKE, controlled by + the new configuration flag MBEDTLS_ECJPAKE_ALT. + * Add mechanism to provide alternative implementation of the DHM module. + +API Changes + * Extend RSA interface by multiple functions allowing structure- + independent setup and export of RSA contexts. Most notably, + mbedtls_rsa_import() and mbedtls_rsa_complete() are introduced for setting + up RSA contexts from partial key material and having them completed to the + needs of the implementation automatically. This allows to setup private RSA + contexts from keys consisting of N,D,E only, even if P,Q are needed for the + purpose or CRT and/or blinding. + * The configuration option MBEDTLS_RSA_ALT can be used to define alternative + implementations of the RSA interface declared in rsa.h. + * The following functions in the message digest modules (MD2, MD4, MD5, + SHA1, SHA256, SHA512) have been deprecated and replaced as shown below. + The new functions change the return type from void to int to allow + returning error codes when using MBEDTLS__ALT. + mbedtls__starts() -> mbedtls__starts_ret() + mbedtls__update() -> mbedtls__update_ret() + mbedtls__finish() -> mbedtls__finish_ret() + mbedtls__process() -> mbedtls_internal__process() + +New deprecations + * Deprecate usage of RSA primitives with non-matching key-type + (e.g. signing with a public key). + * Direct manipulation of structure fields of RSA contexts is deprecated. + Users are advised to use the extended RSA API instead. + * Deprecate usage of message digest functions that return void + (mbedtls__starts, mbedtls__update, + mbedtls__finish and mbedtls__process where is + any of MD2, MD4, MD5, SHA1, SHA256, SHA512) in favor of functions + that can return an error code. + * Deprecate untrustworthy DHE parameters from RFC 5114. Superseded by + parameters from RFC 3526 or the newly added parameters from RFC 7919. + * Deprecate hex string DHE constants MBEDTLS_DHM_RFC3526_MODP_2048_P etc. + Supserseded by binary encoded constants MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN + etc. + * Deprecate mbedtls_ssl_conf_dh_param() for setting default DHE parameters + from hex strings. Superseded by mbedtls_ssl_conf_dh_param_bin() + accepting DHM parameters in binary form, matching the new constants. + +Bugfix + * Fix ssl_parse_record_header() to silently discard invalid DTLS records + as recommended in RFC 6347 Section 4.1.2.7. + * Fix memory leak in mbedtls_ssl_set_hostname() when called multiple times. + Found by projectgus and Jethro Beekman, #836. + * Fix usage help in ssl_server2 example. Found and fixed by Bei Lin. + * Parse signature algorithm extension when renegotiating. Previously, + renegotiated handshakes would only accept signatures using SHA-1 + regardless of the peer's preferences, or fail if SHA-1 was disabled. + * Fix leap year calculation in x509_date_is_valid() to ensure that invalid + dates on leap years with 100 and 400 intervals are handled correctly. Found + by Nicholas Wilson. #694 + * Fix some invalid RSA-PSS signatures with keys of size 8N+1 that were + accepted. Generating these signatures required the private key. + * Fix out-of-memory problem when parsing 4096-bit PKCS8-encrypted RSA keys. + Found independently by Florian in the mbed TLS forum and by Mishamax. + #878, #1019. + * Fix variable used before assignment compilation warnings with IAR + toolchain. Found by gkerrien38. + * Fix unchecked return codes from AES, DES and 3DES functions in + pem_aes_decrypt(), pem_des_decrypt() and pem_des3_decrypt() respectively. + If a call to one of the functions of the cryptographic primitive modules + failed, the error may not be noticed by the function + mbedtls_pem_read_buffer() causing it to return invalid values. Found by + Guido Vranken. #756 + * Include configuration file in md.h, to fix compilation warnings. + Reported by aaronmdjones in #1001 + * Correct extraction of signature-type from PK instance in X.509 CRT and CSR + writing routines that prevented these functions to work with alternative + RSA implementations. Raised by J.B. in the Mbed TLS forum. Fixes #1011. + * Don't print X.509 version tag for v1 CRT's, and omit extensions for + non-v3 CRT's. + * Fix bugs in RSA test suite under MBEDTLS_NO_PLATFORM_ENTROPY. #1023 #1024 + * Fix net_would_block() to avoid modification by errno through fcntl() call. + Found by nkolban. Fixes #845. + * Fix handling of handshake messages in mbedtls_ssl_read() in case + MBEDTLS_SSL_RENEGOTIATION is disabled. Found by erja-gp. + * Add a check for invalid private parameters in mbedtls_ecdsa_sign(). + Reported by Yolan Romailler. + * Fix word size check in in pk.c to not depend on MBEDTLS_HAVE_INT64. + * Fix incorrect unit in benchmark output. #850 + * Add size-checks for record and handshake message content, securing + fragile yet non-exploitable code-paths. + * Fix crash when calling mbedtls_ssl_cache_free() twice. Found by + MilenkoMitrovic, #1104 + * Fix mbedtls_timing_alarm(0) on Unix and MinGW. + * Fix use of uninitialized memory in mbedtls_timing_get_timer() when reset=1. + * Fix possible memory leaks in mbedtls_gcm_self_test(). + * Added missing return code checks in mbedtls_aes_self_test(). + * Fix issues in RSA key generation program programs/x509/rsa_genkey and the + RSA test suite where the failure of CTR DRBG initialization lead to + freeing an RSA context and several MPI's without proper initialization + beforehand. + * Fix error message in programs/pkey/gen_key.c. Found and fixed by Chris Xue. + * Fix programs/pkey/dh_server.c so that it actually works with dh_client.c. + Found and fixed by Martijn de Milliano. + * Fix an issue in the cipher decryption with the mode + MBEDTLS_PADDING_ONE_AND_ZEROS that sometimes accepted invalid padding. + Note, this padding mode is not used by the TLS protocol. Found and fixed by + Micha Kraus. + * Fix the entropy.c module to not call mbedtls_sha256_starts() or + mbedtls_sha512_starts() in the mbedtls_entropy_init() function. + * Fix the entropy.c module to ensure that mbedtls_sha256_init() or + mbedtls_sha512_init() is called before operating on the relevant context + structure. Do not assume that zeroizing a context is a correct way to + reset it. Found independently by ccli8 on Github. + * In mbedtls_entropy_free(), properly free the message digest context. + * Fix status handshake status message in programs/ssl/dtls_client.c. Found + and fixed by muddog. + +Changes + * Extend cert_write example program by options to set the certificate version + and the message digest. Further, allow enabling/disabling of authority + identifier, subject identifier and basic constraints extensions. + * Only check for necessary RSA structure fields in `mbedtls_rsa_private`. In + particular, don't require P,Q if neither CRT nor blinding are + used. Reported and fix proposed independently by satur9nine and sliai + on GitHub. + * Only run AES-192 self-test if AES-192 is available. Fixes #963. + * Tighten the RSA PKCS#1 v1.5 signature verification code and remove the + undeclared dependency of the RSA module on the ASN.1 module. + * Update all internal usage of deprecated message digest functions to the + new ones with return codes. In particular, this modifies the + mbedtls_md_info_t structure. Propagate errors from these functions + everywhere except some locations in the ssl_tls.c module. + * Improve CTR_DRBG error handling by propagating underlying AES errors. + * Add MBEDTLS_ERR_XXX_HW_ACCEL_FAILED error codes for all cryptography + modules where the software implementation can be replaced by a hardware + implementation. + * Add explicit warnings for the use of MD2, MD4, MD5, SHA-1, DES and ARC4 + throughout the library. + += mbed TLS 2.6.0 branch released 2017-08-10 + +Security + * Fix authentication bypass in SSL/TLS: when authmode is set to optional, + mbedtls_ssl_get_verify_result() would incorrectly return 0 when the peer's + X.509 certificate chain had more than MBEDTLS_X509_MAX_INTERMEDIATE_CA + (default: 8) intermediates, even when it was not trusted. This could be + triggered remotely from either side. (With authmode set to 'required' + (the default), the handshake was correctly aborted). + * Reliably wipe sensitive data after use in the AES example applications + programs/aes/aescrypt2 and programs/aes/crypt_and_hash. + Found by Laurent Simon. + +Features + * Add the functions mbedtls_platform_setup() and mbedtls_platform_teardown() + and the context struct mbedtls_platform_context to perform + platform-specific setup and teardown operations. The macro + MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT allows the functions to be overridden + by the user in a platform_alt.h file. These new functions are required in + some embedded environments to provide a means of initialising underlying + cryptographic acceleration hardware. + +API Changes + * Reverted API/ABI breaking changes introduced in mbed TLS 2.5.1, to make the + API consistent with mbed TLS 2.5.0. Specifically removed the inline + qualifier from the functions mbedtls_aes_decrypt, mbedtls_aes_encrypt, + mbedtls_ssl_ciphersuite_uses_ec and mbedtls_ssl_ciphersuite_uses_psk. Found + by James Cowgill. #978 + * Certificate verification functions now set flags to -1 in case the full + chain was not verified due to an internal error (including in the verify + callback) or chain length limitations. + * With authmode set to optional, the TLS handshake is now aborted if the + verification of the peer's certificate failed due to an overlong chain or + a fatal error in the verify callback. + +Bugfix + * Add a check if iv_len is zero in GCM, and return an error if it is zero. + Reported by roberto. #716 + * Replace preprocessor condition from #if defined(MBEDTLS_THREADING_PTHREAD) + to #if defined(MBEDTLS_THREADING_C) as the library cannot assume they will + always be implemented by pthread support. #696 + * Fix a resource leak on Windows platforms in mbedtls_x509_crt_parse_path(), + in the case of an error. Found by redplait. #590 + * Add MBEDTLS_MPI_CHK to check for error value of mbedtls_mpi_fill_random. + Reported and fix suggested by guidovranken. #740 + * Fix conditional preprocessor directives in bignum.h to enable 64-bit + compilation when using ARM Compiler 6. + * Fix a potential integer overflow in the version verification for DER + encoded X.509 CRLs. The overflow could enable maliciously constructed CRLs + to bypass the version verification check. Found by Peng Li/Yueh-Hsun Lin, + KNOX Security, Samsung Research America + * Fix potential integer overflow in the version verification for DER + encoded X.509 CSRs. The overflow could enable maliciously constructed CSRs + to bypass the version verification check. Found by Peng Li/Yueh-Hsun Lin, + KNOX Security, Samsung Research America + * Fix a potential integer overflow in the version verification for DER + encoded X.509 certificates. The overflow could enable maliciously + constructed certificates to bypass the certificate verification check. + * Fix a call to the libc function time() to call the platform abstraction + function mbedtls_time() instead. Found by wairua. #666 + * Avoid shadowing of time and index functions through mbed TLS function + arguments. Found by inestlerode. #557. + +Changes + * Added config.h option MBEDTLS_NO_UDBL_DIVISION, to prevent the use of + 64-bit division. This is useful on embedded platforms where 64-bit division + created a dependency on external libraries. #708 + * Removed mutexes from ECP hardware accelerator code. Now all hardware + accelerator code in the library leaves concurrency handling to the + platform. Reported by Steven Cooreman. #863 + * Define the macro MBEDTLS_AES_ROM_TABLES in the configuration file + config-no-entropy.h to reduce the RAM footprint. + * Added a test script that can be hooked into git that verifies commits + before they are pushed. + * Improve documentation of PKCS1 decryption functions. + += mbed TLS 2.5.1 released 2017-06-21 + +Security + * Fixed unlimited overread of heap-based buffer in mbedtls_ssl_read(). + The issue could only happen client-side with renegotiation enabled. + Could result in DoS (application crash) or information leak + (if the application layer sent data read from mbedtls_ssl_read() + back to the server or to a third party). Can be triggered remotely. + * Removed SHA-1 and RIPEMD-160 from the default hash algorithms for + certificate verification. SHA-1 can be turned back on with a compile-time + option if needed. + * Fixed offset in FALLBACK_SCSV parsing that caused TLS server to fail to + detect it sometimes. Reported by Hugo Leisink. #810 + * Tighten parsing of RSA PKCS#1 v1.5 signatures, to avoid a + potential Bleichenbacher/BERserk-style attack. + +Bugfix + * Remove size zero arrays from ECJPAKE test suite. Size zero arrays are not + valid C and they prevented the test from compiling in Visual Studio 2015 + and with GCC using the -Wpedantic compilation option. + * Fix insufficient support for signature-hash-algorithm extension, + resulting in compatibility problems with Chrome. Found by hfloyrd. #823 + * Fix behaviour that hid the original cause of fatal alerts in some cases + when sending the alert failed. The fix makes sure not to hide the error + that triggered the alert. + * Fix SSLv3 renegotiation behaviour and stop processing data received from + peer after sending a fatal alert to refuse a renegotiation attempt. + Previous behaviour was to keep processing data even after the alert has + been sent. + * Accept empty trusted CA chain in authentication mode + MBEDTLS_SSL_VERIFY_OPTIONAL. Found by Jethro Beekman. #864 + * Fix implementation of mbedtls_ssl_parse_certificate() to not annihilate + fatal errors in authentication mode MBEDTLS_SSL_VERIFY_OPTIONAL and to + reflect bad EC curves within verification result. + * Fix bug that caused the modular inversion function to accept the invalid + modulus 1 and therefore to hang. Found by blaufish. #641. + * Fix incorrect sign computation in modular exponentiation when the base is + a negative MPI. Previously the result was always negative. Found by Guido + Vranken. + * Fix a numerical underflow leading to stack overflow in mpi_read_file() + that was triggered uppon reading an empty line. Found by Guido Vranken. + +Changes + * Send fatal alerts in more cases. The previous behaviour was to skip + sending the fatal alert and just drop the connection. + * Clarify ECDSA documentation and improve the sample code to avoid + misunderstanding and potentially dangerous use of the API. Pointed out + by Jean-Philippe Aumasson. + += mbed TLS 2.5.0 branch released 2017-05-17 + +Security + * Wipe stack buffers in RSA private key operations + (rsa_rsaes_pkcs1_v15_decrypt(), rsa_rsaes_oaep_decrypt). Found by Laurent + Simon. + * Add exponent blinding to RSA private operations as a countermeasure + against side-channel attacks like the cache attack described in + https://arxiv.org/abs/1702.08719v2. + Found and fix proposed by Michael Schwarz, Samuel Weiser, Daniel Gruss, + Clémentine Maurice and Stefan Mangard. + +Features + * Add hardware acceleration support for the Elliptic Curve Point module. + This involved exposing parts of the internal interface to enable + replacing the core functions and adding and alternative, module level + replacement support for enabling the extension of the interface. + * Add a new configuration option to 'mbedtls_ssl_config' to enable + suppressing the CA list in Certificate Request messages. The default + behaviour has not changed, namely every configured CAs name is included. + +API Changes + * The following functions in the AES module have been deprecated and replaced + by the functions shown below. The new functions change the return type from + void to int to allow returning error codes when using MBEDTLS_AES_ALT, + MBEDTLS_AES_DECRYPT_ALT or MBEDTLS_AES_ENCRYPT_ALT. + mbedtls_aes_decrypt() -> mbedtls_internal_aes_decrypt() + mbedtls_aes_encrypt() -> mbedtls_internal_aes_encrypt() + +Bugfix + * Remove macros from compat-1.3.h that correspond to deleted items from most + recent versions of the library. Found by Kyle Keen. + * Fixed issue in the Threading module that prevented mutexes from + initialising. Found by sznaider. #667 #843 + * Add checks in the PK module for the RSA functions on 64-bit systems. + The PK and RSA modules use different types for passing hash length and + without these checks the type cast could lead to data loss. Found by Guido + Vranken. + += mbed TLS 2.4.2 branch released 2017-03-08 + +Security + * Add checks to prevent signature forgeries for very large messages while + using RSA through the PK module in 64-bit systems. The issue was caused by + some data loss when casting a size_t to an unsigned int value in the + functions rsa_verify_wrap(), rsa_sign_wrap(), rsa_alt_sign_wrap() and + mbedtls_pk_sign(). Found by Jean-Philippe Aumasson. + * Fixed potential livelock during the parsing of a CRL in PEM format in + mbedtls_x509_crl_parse(). A string containing a CRL followed by trailing + characters after the footer could result in the execution of an infinite + loop. The issue can be triggered remotely. Found by Greg Zaverucha, + Microsoft. + * Removed MD5 from the allowed hash algorithms for CertificateRequest and + CertificateVerify messages, to prevent SLOTH attacks against TLS 1.2. + Introduced by interoperability fix for #513. + * Fixed a bug that caused freeing a buffer that was allocated on the stack, + when verifying the validity of a key on secp224k1. This could be + triggered remotely for example with a maliciously constructed certificate + and potentially could lead to remote code execution on some platforms. + Reported independently by rongsaws and Aleksandar Nikolic, Cisco Talos + team. #569 CVE-2017-2784 + +Bugfix + * Fix output certificate verification flags set by x509_crt_verify_top() when + traversing a chain of trusted CA. The issue would cause both flags, + MBEDTLS_X509_BADCERT_NOT_TRUSTED and MBEDTLS_X509_BADCERT_EXPIRED, to be + set when the verification conditions are not met regardless of the cause. + Found by Harm Verhagen and inestlerode. #665 #561 + * Fix the redefinition of macro ssl_set_bio to an undefined symbol + mbedtls_ssl_set_bio_timeout in compat-1.3.h, by removing it. + Found by omlib-lin. #673 + * Fix unused variable/function compilation warnings in pem.c, x509_crt.c and + x509_csr.c that are reported when building mbed TLS with a config.h that + does not define MBEDTLS_PEM_PARSE_C. Found by omnium21. #562 + * Fix incorrect renegotiation condition in ssl_check_ctr_renegotiate() that + would compare 64 bits of the record counter instead of 48 bits as indicated + in RFC 6347 Section 4.3.1. This could cause the execution of the + renegotiation routines at unexpected times when the protocol is DTLS. Found + by wariua. #687 + * Fixed multiple buffer overreads in mbedtls_pem_read_buffer() when parsing + the input string in PEM format to extract the different components. Found + by Eyal Itkin. + * Fixed potential arithmetic overflow in mbedtls_ctr_drbg_reseed() that could + cause buffer bound checks to be bypassed. Found by Eyal Itkin. + * Fixed potential arithmetic overflows in mbedtls_cipher_update() that could + cause buffer bound checks to be bypassed. Found by Eyal Itkin. + * Fixed potential arithmetic overflow in mbedtls_md2_update() that could + cause buffer bound checks to be bypassed. Found by Eyal Itkin. + * Fixed potential arithmetic overflow in mbedtls_base64_decode() that could + cause buffer bound checks to be bypassed. Found by Eyal Itkin. + * Fixed heap overreads in mbedtls_x509_get_time(). Found by Peng + Li/Yueh-Hsun Lin, KNOX Security, Samsung Research America. + * Fix potential memory leak in mbedtls_x509_crl_parse(). The leak was caused + by missing calls to mbedtls_pem_free() in cases when a + MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT error was encountered. Found and + fix proposed by Guido Vranken. #722 + * Fixed the templates used to generate project and solution files for Visual + Studio 2015 as well as the files themselves, to remove a build warning + generated in Visual Studio 2015. Reported by Steve Valliere. #742 + * Fix a resource leak in ssl_cookie, when using MBEDTLS_THREADING_C. + Raised and fix suggested by Alan Gillingham in the mbed TLS forum. #771 + * Fix 1 byte buffer overflow in mbedtls_mpi_write_string() when the MPI + number to write in hexadecimal is negative and requires an odd number of + digits. Found and fixed by Guido Vranken. + * Fix unlisted DES configuration dependency in some pkparse test cases. Found + by inestlerode. #555 + += mbed TLS 2.4.1 branch released 2016-12-13 + +Changes + * Update to CMAC test data, taken from - NIST Special Publication 800-38B - + Recommendation for Block Cipher Modes of Operation: The CMAC Mode for + Authentication – October 2016 + += mbed TLS 2.4.0 branch released 2016-10-17 + +Security + * Removed the MBEDTLS_SSL_AEAD_RANDOM_IV option, because it was not compliant + with RFC-5116 and could lead to session key recovery in very long TLS + sessions. "Nonce-Disrespecting Adversaries Practical Forgery Attacks on GCM in + TLS" - H. Bock, A. Zauner, S. Devlin, J. Somorovsky, P. Jovanovic. + https://eprint.iacr.org/2016/475.pdf + * Fixed potential stack corruption in mbedtls_x509write_crt_der() and + mbedtls_x509write_csr_der() when the signature is copied to the buffer + without checking whether there is enough space in the destination. The + issue cannot be triggered remotely. Found by Jethro Beekman. + +Features + * Added support for CMAC for AES and 3DES and AES-CMAC-PRF-128, as defined by + NIST SP 800-38B, RFC-4493 and RFC-4615. + * Added hardware entropy selftest to verify that the hardware entropy source + is functioning correctly. + * Added a script to print build environment info for diagnostic use in test + scripts, which is also now called by all.sh. + * Added the macro MBEDTLS_X509_MAX_FILE_PATH_LEN that enables the user to + configure the maximum length of a file path that can be buffered when + calling mbedtls_x509_crt_parse_path(). + * Added a configuration file config-no-entropy.h that configures the subset of + library features that do not require an entropy source. + * Added the macro MBEDTLS_ENTROPY_MIN_HARDWARE in config.h. This allows users + to configure the minimum number of bytes for entropy sources using the + mbedtls_hardware_poll() function. + +Bugfix + * Fix for platform time abstraction to avoid dependency issues where a build + may need time but not the standard C library abstraction, and added + configuration consistency checks to check_config.h + * Fix dependency issue in Makefile to allow parallel builds. + * Fix incorrect handling of block lengths in crypt_and_hash.c sample program, + when GCM is used. Found by udf2457. #441 + * Fix for key exchanges based on ECDH-RSA or ECDH-ECDSA which weren't + enabled unless others were also present. Found by David Fernandez. #428 + * Fix for out-of-tree builds using CMake. Found by jwurzer, and fix based on + a contribution from Tobias Tangemann. #541 + * Fixed cert_app.c sample program for debug output and for use when no root + certificates are provided. + * Fix conditional statement that would cause a 1 byte overread in + mbedtls_asn1_get_int(). Found and fixed by Guido Vranken. #599 + * Fixed pthread implementation to avoid unintended double initialisations + and double frees. Found by Niklas Amnebratt. + * Fixed the sample applications gen_key.c, cert_req.c and cert_write.c for + builds where the configuration MBEDTLS_PEM_WRITE_C is not defined. Found + by inestlerode. #559. + * Fix mbedtls_x509_get_sig() to update the ASN1 type in the mbedtls_x509_buf + data structure until after error checks are successful. Found by + subramanyam-c. #622 + * Fix documentation and implementation missmatch for function arguments of + mbedtls_gcm_finish(). Found by cmiatpaar. #602 + * Guarantee that P>Q at RSA key generation. Found by inestlerode. #558 + * Fix potential byte overread when verifying malformed SERVER_HELLO in + ssl_parse_hello_verify_request() for DTLS. Found by Guido Vranken. + * Fix check for validity of date when parsing in mbedtls_x509_get_time(). + Found by subramanyam-c. #626 + * Fix compatibility issue with Internet Explorer client authentication, + where the limited hash choices prevented the client from sending its + certificate. Found by teumas. #513 + * Fix compilation without MBEDTLS_SELF_TEST enabled. + +Changes + * Extended test coverage of special cases, and added new timing test suite. + * Removed self-tests from the basic-built-test.sh script, and added all + missing self-tests to the test suites, to ensure self-tests are only + executed once. + * Added support for 3 and 4 byte lengths to mbedtls_asn1_write_len(). + * Added support for a Yotta specific configuration file - + through the symbol YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE. + * Added optimization for code space for X.509/OID based on configured + features. Contributed by Aviv Palivoda. + * Renamed source file library/net.c to library/net_sockets.c to avoid + naming collision in projects which also have files with the common name + net.c. For consistency, the corresponding header file, net.h, is marked as + deprecated, and its contents moved to net_sockets.h. + * Changed the strategy for X.509 certificate parsing and validation, to no + longer disregard certificates with unrecognised fields. + += mbed TLS 2.3.0 branch released 2016-06-28 + +Security + * Fix missing padding length check in mbedtls_rsa_rsaes_pkcs1_v15_decrypt + required by PKCS1 v2.2 + * Fix potential integer overflow to buffer overflow in + mbedtls_rsa_rsaes_pkcs1_v15_encrypt and mbedtls_rsa_rsaes_oaep_encrypt + (not triggerable remotely in (D)TLS). + * Fix a potential integer underflow to buffer overread in + mbedtls_rsa_rsaes_oaep_decrypt. It is not triggerable remotely in + SSL/TLS. + +Features + * Support for platform abstraction of the standard C library time() + function. + +Bugfix + * Fix bug in mbedtls_mpi_add_mpi() that caused wrong results when the three + arguments where the same (in-place doubling). Found and fixed by Janos + Follath. #309 + * Fix potential build failures related to the 'apidoc' target, introduced + in the previous patch release. Found by Robert Scheck. #390 #391 + * Fix issue in Makefile that prevented building using armar. #386 + * Fix memory leak that occurred only when ECJPAKE was enabled and ECDHE and + ECDSA was disabled in config.h . The leak didn't occur by default. + * Fix an issue that caused valid certificates to be rejected whenever an + expired or not yet valid certificate was parsed before a valid certificate + in the trusted certificate list. + * Fix bug in mbedtls_x509_crt_parse that caused trailing extra data in the + buffer after DER certificates to be included in the raw representation. + * Fix issue that caused a hang when generating RSA keys of odd bitlength + * Fix bug in mbedtls_rsa_rsaes_pkcs1_v15_encrypt that made null pointer + dereference possible. + * Fix issue that caused a crash if invalid curves were passed to + mbedtls_ssl_conf_curves. #373 + * Fix issue in ssl_fork_server which was preventing it from functioning. #429 + * Fix memory leaks in test framework + * Fix test in ssl-opt.sh that does not run properly with valgrind + * Fix unchecked calls to mmbedtls_md_setup(). Fix by Brian Murray. #502 + +Changes + * On ARM platforms, when compiling with -O0 with GCC, Clang or armcc5, + don't use the optimized assembly for bignum multiplication. This removes + the need to pass -fomit-frame-pointer to avoid a build error with -O0. + * Disabled SSLv3 in the default configuration. + * Optimized mbedtls_mpi_zeroize() for MPI integer size. (Fix by Alexey + Skalozub). + * Fix non-compliance server extension handling. Extensions for SSLv3 are now + ignored, as required by RFC6101. + += mbed TLS 2.2.1 released 2016-01-05 + +Security + * Fix potential double free when mbedtls_asn1_store_named_data() fails to + allocate memory. Only used for certificate generation, not triggerable + remotely in SSL/TLS. Found by Rafał Przywara. #367 + * Disable MD5 handshake signatures in TLS 1.2 by default to prevent the + SLOTH attack on TLS 1.2 server authentication (other attacks from the + SLOTH paper do not apply to any version of mbed TLS or PolarSSL). + https://www.mitls.org/pages/attacks/SLOTH + +Bugfix + * Fix over-restrictive length limit in GCM. Found by Andreas-N. #362 + * Fix bug in certificate validation that caused valid chains to be rejected + when the first intermediate certificate has pathLenConstraint=0. Found by + Nicholas Wilson. Introduced in mbed TLS 2.2.0. #280 + * Removed potential leak in mbedtls_rsa_rsassa_pkcs1_v15_sign(), found by + JayaraghavendranK. #372 + * Fix suboptimal handling of unexpected records that caused interop issues + with some peers over unreliable links. Avoid dropping an entire DTLS + datagram if a single record in a datagram is unexpected, instead only + drop the record and look at subsequent records (if any are present) in + the same datagram. Found by jeannotlapin. #345 + += mbed TLS 2.2.0 released 2015-11-04 + +Security + * Fix potential double free if mbedtls_ssl_conf_psk() is called more than + once and some allocation fails. Cannot be forced remotely. Found by Guido + Vranken, Intelworks. + * Fix potential heap corruption on Windows when + mbedtls_x509_crt_parse_path() is passed a path longer than 2GB. Cannot be + triggered remotely. Found by Guido Vranken, Intelworks. + * Fix potential buffer overflow in some asn1_write_xxx() functions. + Cannot be triggered remotely unless you create X.509 certificates based + on untrusted input or write keys of untrusted origin. Found by Guido + Vranken, Intelworks. + * The X509 max_pathlen constraint was not enforced on intermediate + certificates. Found by Nicholas Wilson, fix and tests provided by + Janos Follath. #280 and #319 + +Features + * Experimental support for EC J-PAKE as defined in Thread 1.0.0. + Disabled by default as the specification might still change. + * Added a key extraction callback to accees the master secret and key + block. (Potential uses include EAP-TLS and Thread.) + +Bugfix + * Self-signed certificates were not excluded from pathlen counting, + resulting in some valid X.509 being incorrectly rejected. Found and fix + provided by Janos Follath. #319 + * Fix build error with configurations where ECDHE-PSK is the only key + exchange. Found and fix provided by Chris Hammond. #270 + * Fix build error with configurations where RSA, RSA-PSK, ECDH-RSA or + ECHD-ECDSA if the only key exchange. Multiple reports. #310 + * Fixed a bug causing some handshakes to fail due to some non-fatal alerts + not being properly ignored. Found by mancha and Kasom Koht-arsa, #308 + * mbedtls_x509_crt_verify(_with_profile)() now also checks the key type and + size/curve against the profile. Before that, there was no way to set a + minimum key size for end-entity certificates with RSA keys. Found by + Matthew Page of Scannex Electronics Ltd. + * Fix failures in MPI on Sparc(64) due to use of bad assembly code. + Found by Kurt Danielson. #292 + * Fix typo in name of the extKeyUsage OID. Found by inestlerode, #314 + * Fix bug in ASN.1 encoding of booleans that caused generated CA + certificates to be rejected by some applications, including OS X + Keychain. Found and fixed by Jonathan Leroy, Inikup. + +Changes + * Improved performance of mbedtls_ecp_muladd() when one of the scalars is 1 + or -1. + += mbed TLS 2.1.2 released 2015-10-06 + +Security + * Added fix for CVE-2015-5291 to prevent heap corruption due to buffer + overflow of the hostname or session ticket. Found by Guido Vranken, + Intelworks. + * Fix potential double-free if mbedtls_ssl_set_hs_psk() is called more than + once in the same handhake and mbedtls_ssl_conf_psk() was used. + Found and patch provided by Guido Vranken, Intelworks. Cannot be forced + remotely. + * Fix stack buffer overflow in pkcs12 decryption (used by + mbedtls_pk_parse_key(file)() when the password is > 129 bytes. + Found by Guido Vranken, Intelworks. Not triggerable remotely. + * Fix potential buffer overflow in mbedtls_mpi_read_string(). + Found by Guido Vranken, Intelworks. Not exploitable remotely in the context + of TLS, but might be in other uses. On 32 bit machines, requires reading a + string of close to or larger than 1GB to exploit; on 64 bit machines, would + require reading a string of close to or larger than 2^62 bytes. + * Fix potential random memory allocation in mbedtls_pem_read_buffer() + on crafted PEM input data. Found and fix provided by Guido Vranken, + Intelworks. Not triggerable remotely in TLS. Triggerable remotely if you + accept PEM data from an untrusted source. + * Fix possible heap buffer overflow in base64_encoded() when the input + buffer is 512MB or larger on 32-bit platforms. Found by Guido Vranken, + Intelworks. Not trigerrable remotely in TLS. + * Fix potential double-free if mbedtls_conf_psk() is called repeatedly on + the same mbedtls_ssl_config object and memory allocation fails. Found by + Guido Vranken, Intelworks. Cannot be forced remotely. + * Fix potential heap buffer overflow in servers that perform client + authentication against a crafted CA cert. Cannot be triggered remotely + unless you allow third parties to pick trust CAs for client auth. + Found by Guido Vranken, Intelworks. + +Bugfix + * Fix compile error in net.c with musl libc. Found and patch provided by + zhasha (#278). + * Fix macroization of 'inline' keyword when building as C++. (#279) + +Changes + * Added checking of hostname length in mbedtls_ssl_set_hostname() to ensure + domain names are compliant with RFC 1035. + * Fixed paths for check_config.h in example config files. (Found by bachp) + (#291) + += mbed TLS 2.1.1 released 2015-09-17 + +Security + * Add countermeasure against Lenstra's RSA-CRT attack for PKCS#1 v1.5 + signatures. (Found by Florian Weimer, Red Hat.) + https://securityblog.redhat.com/2015/09/02/factoring-rsa-keys-with-tls-perfect-forward-secrecy/ + * Fix possible client-side NULL pointer dereference (read) when the client + tries to continue the handshake after it failed (a misuse of the API). + (Found and patch provided by Fabian Foerg, Gotham Digital Science using + afl-fuzz.) + +Bugfix + * Fix warning when using a 64bit platform. (found by embedthis) (#275) + * Fix off-by-one error in parsing Supported Point Format extension that + caused some handshakes to fail. + +Changes + * Made X509 profile pointer const in mbedtls_ssl_conf_cert_profile() to allow + use of mbedtls_x509_crt_profile_next. (found by NWilson) + * When a client initiates a reconnect from the same port as a live + connection, if cookie verification is available + (MBEDTLS_SSL_DTLS_HELLO_VERIFY defined in config.h, and usable cookie + callbacks set with mbedtls_ssl_conf_dtls_cookies()), this will be + detected and mbedtls_ssl_read() will return + MBEDTLS_ERR_SSL_CLIENT_RECONNECT - it is then possible to start a new + handshake with the same context. (See RFC 6347 section 4.2.8.) + += mbed TLS 2.1.0 released 2015-09-04 + +Features + * Added support for yotta as a build system. + * Primary open source license changed to Apache 2.0 license. + +Bugfix + * Fix segfault in the benchmark program when benchmarking DHM. + * Fix build error with CMake and pre-4.5 versions of GCC (found by Hugo + Leisink). + * Fix bug when parsing a ServerHello without extensions (found by David + Sears). + * Fix bug in CMake lists that caused libmbedcrypto.a not to be installed + (found by Benoit Lecocq). + * Fix bug in Makefile that caused libmbedcrypto and libmbedx509 not to be + installed (found by Rawi666). + * Fix compile error with armcc 5 with --gnu option. + * Fix bug in Makefile that caused programs not to be installed correctly + (found by robotanarchy) (#232). + * Fix bug in Makefile that prevented from installing without building the + tests (found by robotanarchy) (#232). + * Fix missing -static-libgcc when building shared libraries for Windows + with make. + * Fix link error when building shared libraries for Windows with make. + * Fix error when loading libmbedtls.so. + * Fix bug in mbedtls_ssl_conf_default() that caused the default preset to + be always used (found by dcb314) (#235) + * Fix bug in mbedtls_rsa_public() and mbedtls_rsa_private() that could + result trying to unlock an unlocked mutex on invalid input (found by + Fredrik Axelsson) (#257) + * Fix -Wshadow warnings (found by hnrkp) (#240) + * Fix memory corruption on client with overlong PSK identity, around + SSL_MAX_CONTENT_LEN or higher - not triggerrable remotely (found by + Aleksandrs Saveljevs) (#238) + * Fix unused function warning when using MBEDTLS_MDx_ALT or + MBEDTLS_SHAxxx_ALT (found by Henrik) (#239) + * Fix memory corruption in pkey programs (found by yankuncheng) (#210) + +Changes + * The PEM parser now accepts a trailing space at end of lines (#226). + * It is now possible to #include a user-provided configuration file at the + end of the default config.h by defining MBEDTLS_USER_CONFIG_FILE on the + compiler's command line. + * When verifying a certificate chain, if an intermediate certificate is + trusted, no later cert is checked. (suggested by hannes-landeholm) + (#220). + * Prepend a "thread identifier" to debug messages (issue pointed out by + Hugo Leisink) (#210). + * Add mbedtls_ssl_get_max_frag_len() to query the current maximum fragment + length. + += mbed TLS 2.0.0 released 2015-07-13 + +Features + * Support for DTLS 1.0 and 1.2 (RFC 6347). + * Ability to override core functions from MDx, SHAx, AES and DES modules + with custom implementation (eg hardware accelerated), complementing the + ability to override the whole module. + * New server-side implementation of session tickets that rotate keys to + preserve forward secrecy, and allows sharing across multiple contexts. + * Added a concept of X.509 cerificate verification profile that controls + which algorithms and key sizes (curves for ECDSA) are acceptable. + * Expanded configurability of security parameters in the SSL module with + mbedtls_ssl_conf_dhm_min_bitlen() and mbedtls_ssl_conf_sig_hashes(). + * Introduced a concept of presets for SSL security-relevant configuration + parameters. + +API Changes + * The library has been split into libmbedcrypto, libmbedx509, libmbedtls. + You now need to link to all of them if you use TLS for example. + * All public identifiers moved to the mbedtls_* or MBEDTLS_* namespace. + Some names have been further changed to make them more consistent. + Migration helpers scripts/rename.pl and include/mbedtls/compat-1.3.h are + provided. Full list of renamings in scripts/data_files/rename-1.3-2.0.txt + * Renamings of fields inside structures, not covered by the previous list: + mbedtls_cipher_info_t.key_length -> key_bitlen + mbedtls_cipher_context_t.key_length -> key_bitlen + mbedtls_ecp_curve_info.size -> bit_size + * Headers are now found in the 'mbedtls' directory (previously 'polarssl'). + * The following _init() functions that could return errors have + been split into an _init() that returns void and another function that + should generally be the first function called on this context after init: + mbedtls_ssl_init() -> mbedtls_ssl_setup() + mbedtls_ccm_init() -> mbedtls_ccm_setkey() + mbedtls_gcm_init() -> mbedtls_gcm_setkey() + mbedtls_hmac_drbg_init() -> mbedtls_hmac_drbg_seed(_buf)() + mbedtls_ctr_drbg_init() -> mbedtls_ctr_drbg_seed() + Note that for mbedtls_ssl_setup(), you need to be done setting up the + ssl_config structure before calling it. + * Most ssl_set_xxx() functions (all except ssl_set_bio(), ssl_set_hostname(), + ssl_set_session() and ssl_set_client_transport_id(), plus + ssl_legacy_renegotiation()) have been renamed to mbedtls_ssl_conf_xxx() + (see rename.pl and compat-1.3.h above) and their first argument's type + changed from ssl_context to ssl_config. + * ssl_set_bio() changed signature (contexts merged, order switched, one + additional callback for read-with-timeout). + * The following functions have been introduced and must be used in callback + implementations (SNI, PSK) instead of their *conf counterparts: + mbedtls_ssl_set_hs_own_cert() + mbedtls_ssl_set_hs_ca_chain() + mbedtls_ssl_set_hs_psk() + * mbedtls_ssl_conf_ca_chain() lost its last argument (peer_cn), now set + using mbedtls_ssl_set_hostname(). + * mbedtls_ssl_conf_session_cache() changed prototype (only one context + pointer, parameters reordered). + * On server, mbedtls_ssl_conf_session_tickets_cb() must now be used in + place of mbedtls_ssl_conf_session_tickets() to enable session tickets. + * The SSL debug callback gained two new arguments (file name, line number). + * Debug modes were removed. + * mbedtls_ssl_conf_truncated_hmac() now returns void. + * mbedtls_memory_buffer_alloc_init() now returns void. + * X.509 verification flags are now an uint32_t. Affect the signature of: + mbedtls_ssl_get_verify_result() + mbedtls_x509_ctr_verify_info() + mbedtls_x509_crt_verify() (flags, f_vrfy -> needs to be updated) + mbedtls_ssl_conf_verify() (f_vrfy -> needs to be updated) + * The following functions changed prototype to avoid an in-out length + parameter: + mbedtls_base64_encode() + mbedtls_base64_decode() + mbedtls_mpi_write_string() + mbedtls_dhm_calc_secret() + * In the NET module, all "int" and "int *" arguments for file descriptors + changed type to "mbedtls_net_context *". + * net_accept() gained new arguments for the size of the client_ip buffer. + * In the threading layer, mbedtls_mutex_init() and mbedtls_mutex_free() now + return void. + * ecdsa_write_signature() gained an additional md_alg argument and + ecdsa_write_signature_det() was deprecated. + * pk_sign() no longer accepts md_alg == POLARSSL_MD_NONE with ECDSA. + * Last argument of x509_crt_check_key_usage() and + mbedtls_x509write_crt_set_key_usage() changed from int to unsigned. + * test_ca_list (from certs.h) is renamed to test_cas_pem and is only + available if POLARSSL_PEM_PARSE_C is defined (it never worked without). + * Test certificates in certs.c are no longer guaranteed to be nul-terminated + strings; use the new *_len variables instead of strlen(). + * Functions mbedtls_x509_xxx_parse(), mbedtls_pk_parse_key(), + mbedtls_pk_parse_public_key() and mbedtls_dhm_parse_dhm() now expect the + length parameter to include the terminating null byte for PEM input. + * Signature of mpi_mul_mpi() changed to make the last argument unsigned + * calloc() is now used instead of malloc() everywhere. API of platform + layer and the memory_buffer_alloc module changed accordingly. + (Thanks to Mansour Moufid for helping with the replacement.) + * Change SSL_DISABLE_RENEGOTIATION config.h flag to SSL_RENEGOTIATION + (support for renegotiation now needs explicit enabling in config.h). + * Split MBEDTLS_HAVE_TIME into MBEDTLS_HAVE_TIME and MBEDTLS_HAVE_TIME_DATE + in config.h + * net_connect() and net_bind() have a new 'proto' argument to choose + between TCP and UDP, using the macros NET_PROTO_TCP or NET_PROTO_UDP. + Their 'port' argument type is changed to a string. + * Some constness fixes + +Removals + * Removed mbedtls_ecp_group_read_string(). Only named groups are supported. + * Removed mbedtls_ecp_sub() and mbedtls_ecp_add(), use + mbedtls_ecp_muladd(). + * Removed individual mdX_hmac, shaX_hmac, mdX_file and shaX_file functions + (use generic functions from md.h) + * Removed mbedtls_timing_msleep(). Use mbedtls_net_usleep() or a custom + waiting function. + * Removed test DHM parameters from the test certs module. + * Removed the PBKDF2 module (use PKCS5). + * Removed POLARSSL_ERROR_STRERROR_BC (use mbedtls_strerror()). + * Removed compat-1.2.h (helper for migrating from 1.2 to 1.3). + * Removed openssl.h (very partial OpenSSL compatibility layer). + * Configuration options POLARSSL_HAVE_LONGLONG was removed (now always on). + * Configuration options POLARSSL_HAVE_INT8 and POLARSSL_HAVE_INT16 have + been removed (compiler is required to support 32-bit operations). + * Configuration option POLARSSL_HAVE_IPV6 was removed (always enabled). + * Removed test program o_p_test, the script compat.sh does more. + * Removed test program ssl_test, superseded by ssl-opt.sh. + * Removed helper script active-config.pl + +New deprecations + * md_init_ctx() is deprecated in favour of md_setup(), that adds a third + argument (allowing memory savings if HMAC is not used) + +Semi-API changes (technically public, morally private) + * Renamed a few headers to include _internal in the name. Those headers are + not supposed to be included by users. + * Changed md_info_t into an opaque structure (use md_get_xxx() accessors). + * Changed pk_info_t into an opaque structure. + * Changed cipher_base_t into an opaque structure. + * Removed sig_oid2 and rename sig_oid1 to sig_oid in x509_crt and x509_crl. + * x509_crt.key_usage changed from unsigned char to unsigned int. + * Removed r and s from ecdsa_context + * Removed mode from des_context and des3_context + +Default behavior changes + * The default minimum TLS version is now TLS 1.0. + * RC4 is now blacklisted by default in the SSL/TLS layer, and excluded from the + default ciphersuite list returned by ssl_list_ciphersuites() + * Support for receiving SSLv2 ClientHello is now disabled by default at + compile time. + * The default authmode for SSL/TLS clients is now REQUIRED. + * Support for RSA_ALT contexts in the PK layer is now optional. Since is is + enabled in the default configuration, this is only noticeable if using a + custom config.h + * Default DHM parameters server-side upgraded from 1024 to 2048 bits. + * A minimum RSA key size of 2048 bits is now enforced during ceritificate + chain verification. + * Negotiation of truncated HMAC is now disabled by default on server too. + * The following functions are now case-sensitive: + mbedtls_cipher_info_from_string() + mbedtls_ecp_curve_info_from_name() + mbedtls_md_info_from_string() + mbedtls_ssl_ciphersuite_from_string() + mbedtls_version_check_feature() + +Requirement changes + * The minimum MSVC version required is now 2010 (better C99 support). + * The NET layer now unconditionnaly relies on getaddrinfo() and select(). + * Compiler is required to support C99 types such as long long and uint32_t. + +API changes from the 1.4 preview branch + * ssl_set_bio_timeout() was removed, split into mbedtls_ssl_set_bio() with + new prototype, and mbedtls_ssl_set_read_timeout(). + * The following functions now return void: + mbedtls_ssl_conf_transport() + mbedtls_ssl_conf_max_version() + mbedtls_ssl_conf_min_version() + * DTLS no longer hard-depends on TIMING_C, but uses a callback interface + instead, see mbedtls_ssl_set_timer_cb(), with the Timing module providing + an example implementation, see mbedtls_timing_delay_context and + mbedtls_timing_set/get_delay(). + * With UDP sockets, it is no longer necessary to call net_bind() again + after a successful net_accept(). + +Changes + * mbedtls_ctr_drbg_random() and mbedtls_hmac_drbg_random() are now + thread-safe if MBEDTLS_THREADING_C is enabled. + * Reduced ROM fooprint of SHA-256 and added an option to reduce it even + more (at the expense of performance) MBEDTLS_SHA256_SMALLER. + += mbed TLS 1.3 branch + +Security + * With authmode set to SSL_VERIFY_OPTIONAL, verification of keyUsage and + extendedKeyUsage on the leaf certificate was lost (results not accessible + via ssl_get_verify_results()). + * Add countermeasure against "Lucky 13 strikes back" cache-based attack, + https://dl.acm.org/citation.cfm?id=2714625 + +Features + * Improve ECC performance by using more efficient doubling formulas + (contributed by Peter Dettman). + * Add x509_crt_verify_info() to display certificate verification results. + * Add support for reading DH parameters with privateValueLength included + (contributed by Daniel Kahn Gillmor). + * Add support for bit strings in X.509 names (request by Fredrik Axelsson). + * Add support for id-at-uniqueIdentifier in X.509 names. + * Add support for overriding snprintf() (except on Windows) and exit() in + the platform layer. + * Add an option to use macros instead of function pointers in the platform + layer (helps get rid of unwanted references). + * Improved Makefiles for Windows targets by fixing library targets and making + cross-compilation easier (thanks to Alon Bar-Lev). + * The benchmark program also prints heap usage for public-key primitives + if POLARSSL_MEMORY_BUFFER_ALLOC_C and POLARSSL_MEMORY_DEBUG are defined. + * New script ecc-heap.sh helps measuring the impact of ECC parameters on + speed and RAM (heap only for now) usage. + * New script memory.sh helps measuring the ROM and RAM requirements of two + reduced configurations (PSK-CCM and NSA suite B). + * Add config flag POLARSSL_DEPRECATED_WARNING (off by default) to produce + warnings on use of deprecated functions (with GCC and Clang only). + * Add config flag POLARSSL_DEPRECATED_REMOVED (off by default) to produce + errors on use of deprecated functions. + +Bugfix + * Fix compile errors with PLATFORM_NO_STD_FUNCTIONS. + * Fix compile error with PLATFORM_EXIT_ALT (thanks to Rafał Przywara). + * Fix bug in entropy.c when THREADING_C is also enabled that caused + entropy_free() to crash (thanks to Rafał Przywara). + * Fix memory leak when gcm_setkey() and ccm_setkey() are used more than + once on the same context. + * Fix bug in ssl_mail_client when password is longer that username (found + by Bruno Pape). + * Fix undefined behaviour (memcmp( NULL, NULL, 0 );) in X.509 modules + (detected by Clang's 3.6 UBSan). + * mpi_size() and mpi_msb() would segfault when called on an mpi that is + initialized but not set (found by pravic). + * Fix detection of support for getrandom() on Linux (reported by syzzer) by + doing it at runtime (using uname) rather that compile time. + * Fix handling of symlinks by "make install" (found by Gaël PORTAY). + * Fix potential NULL pointer dereference (not trigerrable remotely) when + ssl_write() is called before the handshake is finished (introduced in + 1.3.10) (first reported by Martin Blumenstingl). + * Fix bug in pk_parse_key() that caused some valid private EC keys to be + rejected. + * Fix bug in Via Padlock support (found by Nikos Mavrogiannopoulos). + * Fix thread safety bug in RSA operations (found by Fredrik Axelsson). + * Fix hardclock() (only used in the benchmarking program) with some + versions of mingw64 (found by kxjhlele). + * Fix warnings from mingw64 in timing.c (found by kxjklele). + * Fix potential unintended sign extension in asn1_get_len() on 64-bit + platforms. + * Fix potential memory leak in ssl_set_psk() (found by Mansour Moufid). + * Fix compile error when POLARSSL_SSL_DISABLE_RENEGOTATION and + POLARSSL_SSL_SSESSION_TICKETS where both enabled in config.h (introduced + in 1.3.10). + * Add missing extern "C" guard in aesni.h (reported by amir zamani). + * Add missing dependency on SHA-256 in some x509 programs (reported by + Gergely Budai). + * Fix bug related to ssl_set_curves(): the client didn't check that the + curve picked by the server was actually allowed. + +Changes + * Remove bias in mpi_gen_prime (contributed by Pascal Junod). + * Remove potential sources of timing variations (some contributed by Pascal + Junod). + * Options POLARSSL_HAVE_INT8 and POLARSSL_HAVE_INT16 are deprecated. + * Enabling POLARSSL_NET_C without POLARSSL_HAVE_IPV6 is deprecated. + * compat-1.2.h and openssl.h are deprecated. + * Adjusting/overriding CFLAGS and LDFLAGS with the make build system is now + more flexible (warning: OFLAGS is not used any more) (see the README) + (contributed by Alon Bar-Lev). + * ssl_set_own_cert() no longer calls pk_check_pair() since the + performance impact was bad for some users (this was introduced in 1.3.10). + * Move from SHA-1 to SHA-256 in example programs using signatures + (suggested by Thorsten Mühlfelder). + * Remove some unneeded inclusions of header files from the standard library + "minimize" others (eg use stddef.h if only size_t is needed). + * Change #include lines in test files to use double quotes instead of angle + brackets for uniformity with the rest of the code. + * Remove dependency on sscanf() in X.509 parsing modules. + += mbed TLS 1.3.10 released 2015-02-09 +Security + * NULL pointer dereference in the buffer-based allocator when the buffer is + full and polarssl_free() is called (found by Mark Hasemeyer) + (only possible if POLARSSL_MEMORY_BUFFER_ALLOC_C is enabled, which it is + not by default). + * Fix remotely-triggerable uninitialised pointer dereference caused by + crafted X.509 certificate (TLS server is not affected if it doesn't ask for a + client certificate) (found using Codenomicon Defensics). + * Fix remotely-triggerable memory leak caused by crafted X.509 certificates + (TLS server is not affected if it doesn't ask for a client certificate) + (found using Codenomicon Defensics). + * Fix potential stack overflow while parsing crafted X.509 certificates + (TLS server is not affected if it doesn't ask for a client certificate) + (found using Codenomicon Defensics). + * Fix timing difference that could theoretically lead to a + Bleichenbacher-style attack in the RSA and RSA-PSK key exchanges + (reported by Sebastian Schinzel). + +Features + * Add support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv). + * Add support for Extended Master Secret (draft-ietf-tls-session-hash). + * Add support for Encrypt-then-MAC (RFC 7366). + * Add function pk_check_pair() to test if public and private keys match. + * Add x509_crl_parse_der(). + * Add compile-time option POLARSSL_X509_MAX_INTERMEDIATE_CA to limit the + length of an X.509 verification chain. + * Support for renegotiation can now be disabled at compile-time + * Support for 1/n-1 record splitting, a countermeasure against BEAST. + * Certificate selection based on signature hash, preferring SHA-1 over SHA-2 + for pre-1.2 clients when multiple certificates are available. + * Add support for getrandom() syscall on recent Linux kernels with Glibc or + a compatible enough libc (eg uClibc). + * Add ssl_set_arc4_support() to make it easier to disable RC4 at runtime + while using the default ciphersuite list. + * Added new error codes and debug messages about selection of + ciphersuite/certificate. + +Bugfix + * Stack buffer overflow if ctr_drbg_update() is called with too large + add_len (found by Jean-Philippe Aumasson) (not triggerable remotely). + * Possible buffer overflow of length at most POLARSSL_MEMORY_ALIGN_MULTIPLE + if memory_buffer_alloc_init() was called with buf not aligned and len not + a multiple of POLARSSL_MEMORY_ALIGN_MULTIPLE (not triggerable remotely). + * User set CFLAGS were ignored by Cmake with gcc (introduced in 1.3.9, found + by Julian Ospald). + * Fix potential undefined behaviour in Camellia. + * Fix potential failure in ECDSA signatures when POLARSSL_ECP_MAX_BITS is a + multiple of 8 (found by Gergely Budai). + * Fix unchecked return code in x509_crt_parse_path() on Windows (found by + Peter Vaskovic). + * Fix assembly selection for MIPS64 (thanks to James Cowgill). + * ssl_get_verify_result() now works even if the handshake was aborted due + to a failed verification (found by Fredrik Axelsson). + * Skip writing and parsing signature_algorithm extension if none of the + key exchanges enabled needs certificates. This fixes a possible interop + issue with some servers when a zero-length extension was sent. (Reported + by Peter Dettman.) + * On a 0-length input, base64_encode() did not correctly set output length + (found by Hendrik van den Boogaard). + +Changes + * Use deterministic nonces for AEAD ciphers in TLS by default (possible to + switch back to random with POLARSSL_SSL_AEAD_RANDOM_IV in config.h). + * Blind RSA private operations even when POLARSSL_RSA_NO_CRT is defined. + * ssl_set_own_cert() now returns an error on key-certificate mismatch. + * Forbid repeated extensions in X.509 certificates. + * debug_print_buf() now prints a text view in addition to hexadecimal. + * A specific error is now returned when there are ciphersuites in common + but none of them is usable due to external factors such as no certificate + with a suitable (extended)KeyUsage or curve or no PSK set. + * It is now possible to disable negotiation of truncated HMAC server-side + at runtime with ssl_set_truncated_hmac(). + * Example programs for SSL client and server now disable SSLv3 by default. + * Example programs for SSL client and server now disable RC4 by default. + * Use platform.h in all test suites and programs. + += PolarSSL 1.3.9 released 2014-10-20 +Security + * Lowest common hash was selected from signature_algorithms extension in + TLS 1.2 (found by Darren Bane) (introduced in 1.3.8). + * Remotely-triggerable memory leak when parsing some X.509 certificates + (server is not affected if it doesn't ask for a client certificate) + (found using Codenomicon Defensics). + * Remotely-triggerable memory leak when parsing crafted ClientHello + (not affected if ECC support was compiled out) (found using Codenomicon + Defensics). + +Bugfix + * Support escaping of commas in x509_string_to_names() + * Fix compile error in ssl_pthread_server (found by Julian Ospald). + * Fix net_accept() regarding non-blocking sockets (found by Luca Pesce). + * Don't print uninitialised buffer in ssl_mail_client (found by Marc Abel). + * Fix warnings from Clang's scan-build (contributed by Alfred Klomp). + * Fix compile error in timing.c when POLARSSL_NET_C and POLARSSL_SELFTEST + are defined but not POLARSSL_HAVE_TIME (found by Stephane Di Vito). + * Remove non-existent file from VS projects (found by Peter Vaskovic). + * ssl_read() could return non-application data records on server while + renegotation was pending, and on client when a HelloRequest was received. + * Server-initiated renegotiation would fail with non-blocking I/O if the + write callback returned WANT_WRITE when requesting renegotiation. + * ssl_close_notify() could send more than one message in some circumstances + with non-blocking I/O. + * Fix compiler warnings on iOS (found by Sander Niemeijer). + * x509_crt_parse() did not increase total_failed on PEM error + * Fix compile error with armcc in mpi_is_prime() + * Fix potential bad read in parsing ServerHello (found by Adrien + Vialletelle). + +Changes + * Ciphersuites using SHA-256 or SHA-384 now require TLS 1.x (there is no + standard defining how to use SHA-2 with SSL 3.0). + * Ciphersuites using RSA-PSK key exchange new require TLS 1.x (the spec is + ambiguous on how to encode some packets with SSL 3.0). + * Made buffer size in pk_write_(pub)key_pem() more dynamic, eg smaller if + RSA is disabled, larger if POLARSSL_MPI_MAX_SIZE is larger. + * ssl_read() now returns POLARSSL_ERR_NET_WANT_READ rather than + POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE on harmless alerts. + * POLARSSL_MPI_MAX_SIZE now defaults to 1024 in order to allow 8192 bits + RSA keys. + * Accept spaces at end of line or end of buffer in base64_decode(). + * X.509 certificates with more than one AttributeTypeAndValue per + RelativeDistinguishedName are not accepted any more. + += PolarSSL 1.3.8 released 2014-07-11 +Security + * Fix length checking for AEAD ciphersuites (found by Codenomicon). + It was possible to crash the server (and client) using crafted messages + when a GCM suite was chosen. + +Features + * Add CCM module and cipher mode to Cipher Layer + * Support for CCM and CCM_8 ciphersuites + * Support for parsing and verifying RSASSA-PSS signatures in the X.509 + modules (certificates, CRLs and CSRs). + * Blowfish in the cipher layer now supports variable length keys. + * Add example config.h for PSK with CCM, optimized for low RAM usage. + * Optimize for RAM usage in example config.h for NSA Suite B profile. + * Add POLARSSL_REMOVE_ARC4_CIPHERSUITES to allow removing RC4 ciphersuites + from the default list (inactive by default). + * Add server-side enforcement of sent renegotiation requests + (ssl_set_renegotiation_enforced()) + * Add SSL_CIPHERSUITES config.h flag to allow specifying a list of + ciphersuites to use and save some memory if the list is small. + +Changes + * Add LINK_WITH_PTHREAD option in CMake for explicit linking that is + required on some platforms (e.g. OpenBSD) + * Migrate zeroizing of data to polarssl_zeroize() instead of memset() + against unwanted compiler optimizations + * md_list() now returns hashes strongest first + * Selection of hash for signing ServerKeyExchange in TLS 1.2 now picks + strongest offered by client. + * All public contexts have _init() and _free() functions now for simpler + usage pattern + +Bugfix + * Fix in debug_print_msg() + * Enforce alignment in the buffer allocator even if buffer is not aligned + * Remove less-than-zero checks on unsigned numbers + * Stricter check on SSL ClientHello internal sizes compared to actual packet + size (found by TrustInSoft) + * Fix WSAStartup() return value check (found by Peter Vaskovic) + * Other minor issues (found by Peter Vaskovic) + * Fix symlink command for cross compiling with CMake (found by Andre + Heinecke) + * Fix DER output of gen_key app (found by Gergely Budai) + * Very small records were incorrectly rejected when truncated HMAC was in + use with some ciphersuites and versions (RC4 in all versions, CBC with + versions < TLS 1.1). + * Very large records using more than 224 bytes of padding were incorrectly + rejected with CBC-based ciphersuites and TLS >= 1.1 + * Very large records using less padding could cause a buffer overread of up + to 32 bytes with CBC-based ciphersuites and TLS >= 1.1 + * Restore ability to use a v1 cert as a CA if trusted locally. (This had + been removed in 1.3.6.) + * Restore ability to locally trust a self-signed cert that is not a proper + CA for use as an end entity certificate. (This had been removed in + 1.3.6.) + * Fix preprocessor checks for bn_mul PPC asm (found by Barry K. Nathan). + * Use \n\t rather than semicolons for bn_mul asm, since some assemblers + interpret semicolons as comment delimiters (found by Barry K. Nathan). + * Fix off-by-one error in parsing Supported Point Format extension that + caused some handshakes to fail. + * Fix possible miscomputation of the premaster secret with DHE-PSK key + exchange that caused some handshakes to fail with other implementations. + (Failure rate <= 1/255 with common DHM moduli.) + * Disable broken Sparc64 bn_mul assembly (found by Florian Obser). + * Fix base64_decode() to return and check length correctly (in case of + tight buffers) + * Fix mpi_write_string() to write "00" as hex output for empty MPI (found + by Hui Dong) + += PolarSSL 1.3.7 released on 2014-05-02 +Features + * debug_set_log_mode() added to determine raw or full logging + * debug_set_threshold() added to ignore messages over threshold level + * version_check_feature() added to check for compile-time options at + run-time + +Changes + * POLARSSL_CONFIG_OPTIONS has been removed. All values are individually + checked and filled in the relevant module headers + * Debug module only outputs full lines instead of parts + * Better support for the different Attribute Types from IETF PKIX (RFC 5280) + * AES-NI now compiles with "old" assemblers too + * Ciphersuites based on RC4 now have the lowest priority by default + +Bugfix + * Only iterate over actual certificates in ssl_write_certificate_request() + (found by Matthew Page) + * Typos in platform.c and pkcs11.c (found by Daniel Phillips and Steffan + Karger) + * cert_write app should use subject of issuer certificate as issuer of cert + * Fix false reject in padding check in ssl_decrypt_buf() for CBC + ciphersuites, for full SSL frames of data. + * Improve interoperability by not writing extension length in ClientHello / + ServerHello when no extensions are present (found by Matthew Page) + * rsa_check_pubkey() now allows an E up to N + * On OpenBSD, use arc4random_buf() instead of rand() to prevent warnings + * mpi_fill_random() was creating numbers larger than requested on + big-endian platform when size was not an integer number of limbs + * Fix dependencies issues in X.509 test suite. + * Some parts of ssl_tls.c were compiled even when the module was disabled. + * Fix detection of DragonflyBSD in net.c (found by Markus Pfeiffer) + * Fix detection of Clang on some Apple platforms with CMake + (found by Barry K. Nathan) + += PolarSSL 1.3.6 released on 2014-04-11 + +Features + * Support for the ALPN SSL extension + * Add option 'use_dev_random' to gen_key application + * Enable verification of the keyUsage extension for CA and leaf + certificates (POLARSSL_X509_CHECK_KEY_USAGE) + * Enable verification of the extendedKeyUsage extension + (POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) + +Changes + * x509_crt_info() now prints information about parsed extensions as well + * pk_verify() now returns a specific error code when the signature is valid + but shorter than the supplied length. + * Use UTC time to check certificate validity. + * Reject certificates with times not in UTC, per RFC 5280. + +Security + * Avoid potential timing leak in ecdsa_sign() by blinding modular division. + (Found by Watson Ladd.) + * The notAfter date of some certificates was no longer checked since 1.3.5. + This affects certificates in the user-supplied chain except the top + certificate. If the user-supplied chain contains only one certificates, + it is not affected (ie, its notAfter date is properly checked). + * Prevent potential NULL pointer dereference in ssl_read_record() (found by + TrustInSoft) + +Bugfix + * The length of various ClientKeyExchange messages was not properly checked. + * Some example server programs were not sending the close_notify alert. + * Potential memory leak in mpi_exp_mod() when error occurs during + calculation of RR. + * Fixed malloc/free default #define in platform.c (found by Gergely Budai). + * Fixed type which made POLARSSL_ENTROPY_FORCE_SHA256 uneffective (found by + Gergely Budai). + * Fix #include path in ecdsa.h which wasn't accepted by some compilers. + (found by Gergely Budai) + * Fix compile errors when POLARSSL_ERROR_STRERROR_BC is undefined (found by + Shuo Chen). + * oid_get_numeric_string() used to truncate the output without returning an + error if the output buffer was just 1 byte too small. + * dhm_parse_dhm() (hence dhm_parse_dhmfile()) did not set dhm->len. + * Calling pk_debug() on an RSA-alt key would segfault. + * pk_get_size() and pk_get_len() were off by a factor 8 for RSA-alt keys. + * Potential buffer overwrite in pem_write_buffer() because of low length + indication (found by Thijs Alkemade) + * EC curves constants, which should be only in ROM since 1.3.3, were also + stored in RAM due to missing 'const's (found by Gergely Budai). + += PolarSSL 1.3.5 released on 2014-03-26 +Features + * HMAC-DRBG as a separate module + * Option to set the Curve preference order (disabled by default) + * Single Platform compatilibity layer (for memory / printf / fprintf) + * Ability to provide alternate timing implementation + * Ability to force the entropy module to use SHA-256 as its basis + (POLARSSL_ENTROPY_FORCE_SHA256) + * Testing script ssl-opt.sh added for testing 'live' ssl option + interoperability against OpenSSL and PolarSSL + * Support for reading EC keys that use SpecifiedECDomain in some cases. + * Entropy module now supports seed writing and reading + +Changes + * Deprecated the Memory layer + * entropy_add_source(), entropy_update_manual() and entropy_gather() + now thread-safe if POLARSSL_THREADING_C defined + * Improvements to the CMake build system, contributed by Julian Ospald. + * Work around a bug of the version of Clang shipped by Apple with Mavericks + that prevented bignum.c from compiling. (Reported by Rafael Baptista.) + * Revamped the compat.sh interoperatibility script to include support for + testing against GnuTLS + * Deprecated ssl_set_own_cert_rsa() and ssl_set_own_cert_rsa_alt() + * Improvements to tests/Makefile, contributed by Oden Eriksson. + +Security + * Forbid change of server certificate during renegotiation to prevent + "triple handshake" attack when authentication mode is 'optional' (the + attack was already impossible when authentication is required). + * Check notBefore timestamp of certificates and CRLs from the future. + * Forbid sequence number wrapping + * Fixed possible buffer overflow with overlong PSK + * Possible remotely-triggered out-of-bounds memory access fixed (found by + TrustInSoft) + +Bugfix + * ecp_gen_keypair() does more tries to prevent failure because of + statistics + * Fixed bug in RSA PKCS#1 v1.5 "reversed" operations + * Fixed testing with out-of-source builds using cmake + * Fixed version-major intolerance in server + * Fixed CMake symlinking on out-of-source builds + * Fixed dependency issues in test suite + * Programs rsa_sign_pss and rsa_verify_pss were not using PSS since 1.3.0 + * Bignum's MIPS-32 assembly was used on MIPS-64, causing chaos. (Found by + Alex Wilson.) + * ssl_cache was creating entries when max_entries=0 if TIMING_C was enabled. + * m_sleep() was sleeping twice too long on most Unix platforms. + * Fixed bug with session tickets and non-blocking I/O in the unlikely case + send() would return an EAGAIN error when sending the ticket. + * ssl_cache was leaking memory when reusing a timed out entry containing a + client certificate. + * ssl_srv was leaking memory when client presented a timed out ticket + containing a client certificate + * ssl_init() was leaving a dirty pointer in ssl_context if malloc of + out_ctr failed + * ssl_handshake_init() was leaving dirty pointers in subcontexts if malloc + of one of them failed + * Fix typo in rsa_copy() that impacted PKCS#1 v2 contexts + * x509_get_current_time() uses localtime_r() to prevent thread issues + += PolarSSL 1.3.4 released on 2014-01-27 +Features + * Support for the Koblitz curves: secp192k1, secp224k1, secp256k1 + * Support for RIPEMD-160 + * Support for AES CFB8 mode + * Support for deterministic ECDSA (RFC 6979) + +Bugfix + * Potential memory leak in bignum_selftest() + * Replaced expired test certificate + * ssl_mail_client now terminates lines with CRLF, instead of LF + * net module handles timeouts on blocking sockets better (found by Tilman + Sauerbeck) + * Assembly format fixes in bn_mul.h + +Security + * Missing MPI_CHK calls added around unguarded mpi calls (found by + TrustInSoft) + += PolarSSL 1.3.3 released on 2013-12-31 +Features + * EC key generation support in gen_key app + * Support for adhering to client ciphersuite order preference + (POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + * Support for Curve25519 + * Support for ECDH-RSA and ECDH-ECDSA key exchanges and ciphersuites + * Support for IPv6 in the NET module + * AES-NI support for AES, AES-GCM and AES key scheduling + * SSL Pthread-based server example added (ssl_pthread_server) + +Changes + * gen_prime() speedup + * Speedup of ECP multiplication operation + * Relaxed some SHA2 ciphersuite's version requirements + * Dropped use of readdir_r() instead of readdir() with threading support + * More constant-time checks in the RSA module + * Split off curves from ecp.c into ecp_curves.c + * Curves are now stored fully in ROM + * Memory usage optimizations in ECP module + * Removed POLARSSL_THREADING_DUMMY + +Bugfix + * Fixed bug in mpi_set_bit() on platforms where t_uint is wider than int + * Fixed X.509 hostname comparison (with non-regular characters) + * SSL now gracefully handles missing RNG + * Missing defines / cases for RSA_PSK key exchange + * crypt_and_hash app checks MAC before final decryption + * Potential memory leak in ssl_ticket_keys_init() + * Memory leak in benchmark application + * Fixed x509_crt_parse_path() bug on Windows platforms + * Added missing MPI_CHK() around some statements in mpi_div_mpi() (found by + TrustInSoft) + * Fixed potential overflow in certificate size verification in + ssl_write_certificate() (found by TrustInSoft) + +Security + * Possible remotely-triggered out-of-bounds memory access fixed (found by + TrustInSoft) + += PolarSSL 1.3.2 released on 2013-11-04 +Features + * PK tests added to test framework + * Added optional optimization for NIST MODP curves (POLARSSL_ECP_NIST_OPTIM) + * Support for Camellia-GCM mode and ciphersuites + +Changes + * Padding checks in cipher layer are now constant-time + * Value comparisons in SSL layer are now constant-time + * Support for serialNumber, postalAddress and postalCode in X509 names + * SSL Renegotiation was refactored + +Bugfix + * More stringent checks in cipher layer + * Server does not send out extensions not advertised by client + * Prevent possible alignment warnings on casting from char * to 'aligned *' + * Misc fixes and additions to dependency checks + * Const correctness + * cert_write with selfsign should use issuer_name as subject_name + * Fix ECDSA corner case: missing reduction mod N (found by DualTachyon) + * Defines to handle UEFI environment under MSVC + * Server-side initiated renegotiations send HelloRequest + += PolarSSL 1.3.1 released on 2013-10-15 +Features + * Support for Brainpool curves and TLS ciphersuites (RFC 7027) + * Support for ECDHE-PSK key-exchange and ciphersuites + * Support for RSA-PSK key-exchange and ciphersuites + +Changes + * RSA blinding locks for a smaller amount of time + * TLS compression only allocates working buffer once + * Introduced POLARSSL_HAVE_READDIR_R for systems without it + * config.h is more script-friendly + +Bugfix + * Missing MSVC defines added + * Compile errors with POLARSSL_RSA_NO_CRT + * Header files with 'polarssl/' + * Const correctness + * Possible naming collision in dhm_context + * Better support for MSVC + * threading_set_alt() name + * Added missing x509write_crt_set_version() + += PolarSSL 1.3.0 released on 2013-10-01 +Features + * Elliptic Curve Cryptography module added + * Elliptic Curve Diffie Hellman module added + * Ephemeral Elliptic Curve Diffie Hellman support for SSL/TLS + (ECDHE-based ciphersuites) + * Ephemeral Elliptic Curve Digital Signature Algorithm support for SSL/TLS + (ECDSA-based ciphersuites) + * Ability to specify allowed ciphersuites based on the protocol version. + * PSK and DHE-PSK based ciphersuites added + * Memory allocation abstraction layer added + * Buffer-based memory allocator added (no malloc() / free() / HEAP usage) + * Threading abstraction layer added (dummy / pthread / alternate) + * Public Key abstraction layer added + * Parsing Elliptic Curve keys + * Parsing Elliptic Curve certificates + * Support for max_fragment_length extension (RFC 6066) + * Support for truncated_hmac extension (RFC 6066) + * Support for zeros-and-length (ANSI X.923) padding, one-and-zeros + (ISO/IEC 7816-4) padding and zero padding in the cipher layer + * Support for session tickets (RFC 5077) + * Certificate Request (CSR) generation with extensions (key_usage, + ns_cert_type) + * X509 Certificate writing with extensions (basic_constraints, + issuer_key_identifier, etc) + * Optional blinding for RSA, DHM and EC + * Support for multiple active certificate / key pairs in SSL servers for + the same host (Not to be confused with SNI!) + +Changes + * Ability to enable / disable SSL v3 / TLS 1.0 / TLS 1.1 / TLS 1.2 + individually + * Introduced separate SSL Ciphersuites module that is based on + Cipher and MD information + * Internals for SSL module adapted to have separate IV pointer that is + dynamically set (Better support for hardware acceleration) + * Moved all OID functionality to a separate module. RSA function + prototypes for the RSA sign and verify functions changed as a result + * Split up the GCM module into a starts/update/finish cycle + * Client and server now filter sent and accepted ciphersuites on minimum + and maximum protocol version + * Ability to disable server_name extension (RFC 6066) + * Renamed error_strerror() to the less conflicting polarssl_strerror() + (Ability to keep old as well with POLARSSL_ERROR_STRERROR_BC) + * SHA2 renamed to SHA256, SHA4 renamed to SHA512 and functions accordingly + * All RSA operations require a random generator for blinding purposes + * X509 core refactored + * x509_crt_verify() now case insensitive for cn (RFC 6125 6.4) + * Also compiles / runs without time-based functions (!POLARSSL_HAVE_TIME) + * Support faulty X509 v1 certificates with extensions + (POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3) + +Bugfix + * Fixed parse error in ssl_parse_certificate_request() + * zlib compression/decompression skipped on empty blocks + * Support for AIX header locations in net.c module + * Fixed file descriptor leaks + +Security + * RSA blinding on CRT operations to counter timing attacks + (found by Cyril Arnaud and Pierre-Alain Fouque) + + += Version 1.2.14 released 2015-05-?? + +Security + * Fix potential invalid memory read in the server, that allows a client to + crash it remotely (found by Caj Larsson). + * Fix potential invalid memory read in certificate parsing, that allows a + client to crash the server remotely if client authentication is enabled + (found using Codenomicon Defensics). + * Add countermeasure against "Lucky 13 strikes back" cache-based attack, + https://dl.acm.org/citation.cfm?id=2714625 + +Bugfix + * Fix bug in Via Padlock support (found by Nikos Mavrogiannopoulos). + * Fix hardclock() (only used in the benchmarking program) with some + versions of mingw64 (found by kxjhlele). + * Fix warnings from mingw64 in timing.c (found by kxjklele). + * Fix potential unintended sign extension in asn1_get_len() on 64-bit + platforms (found with Coverity Scan). + += Version 1.2.13 released 2015-02-16 +Note: Although PolarSSL has been renamed to mbed TLS, no changes reflecting + this will be made in the 1.2 branch at this point. + +Security + * Fix remotely-triggerable uninitialised pointer dereference caused by + crafted X.509 certificate (TLS server is not affected if it doesn't ask + for a client certificate) (found using Codenomicon Defensics). + * Fix remotely-triggerable memory leak caused by crafted X.509 certificates + (TLS server is not affected if it doesn't ask for a client certificate) + (found using Codenomicon Defensics). + * Fix potential stack overflow while parsing crafted X.509 certificates + (TLS server is not affected if it doesn't ask for a client certificate) + found using Codenomicon Defensics). + * Fix buffer overread of size 1 when parsing crafted X.509 certificates + (TLS server is not affected if it doesn't ask for a client certificate). + +Bugfix + * Fix potential undefined behaviour in Camellia. + * Fix memory leaks in PKCS#5 and PKCS#12. + * Stack buffer overflow if ctr_drbg_update() is called with too large + add_len (found by Jean-Philippe Aumasson) (not triggerable remotely). + * Fix bug in MPI/bignum on s390/s390x (reported by Dan Horák) (introduced + in 1.2.12). + * Fix unchecked return code in x509_crt_parse_path() on Windows (found by + Peter Vaskovic). + * Fix assembly selection for MIPS64 (thanks to James Cowgill). + * ssl_get_verify_result() now works even if the handshake was aborted due + to a failed verification (found by Fredrik Axelsson). + * Skip writing and parsing signature_algorithm extension if none of the + key exchanges enabled needs certificates. This fixes a possible interop + issue with some servers when a zero-length extension was sent. (Reported + by Peter Dettman.) + * On a 0-length input, base64_encode() did not correctly set output length + (found by Hendrik van den Boogaard). + +Changes + * Blind RSA private operations even when POLARSSL_RSA_NO_CRT is defined. + * Forbid repeated extensions in X.509 certificates. + * Add compile-time option POLARSSL_X509_MAX_INTERMEDIATE_CA to limit the + length of an X.509 verification chain (default = 8). += Version 1.2.12 released 2014-10-24 + +Security + * Remotely-triggerable memory leak when parsing some X.509 certificates + (server is not affected if it doesn't ask for a client certificate). + (Found using Codenomicon Defensics.) + +Bugfix + * Fix potential bad read in parsing ServerHello (found by Adrien + Vialletelle). + * ssl_close_notify() could send more than one message in some circumstances + with non-blocking I/O. + * x509_crt_parse() did not increase total_failed on PEM error + * Fix compiler warnings on iOS (found by Sander Niemeijer). + * Don't print uninitialised buffer in ssl_mail_client (found by Marc Abel). + * Fix net_accept() regarding non-blocking sockets (found by Luca Pesce). + * ssl_read() could return non-application data records on server while + renegotation was pending, and on client when a HelloRequest was received. + * Fix warnings from Clang's scan-build (contributed by Alfred Klomp). + +Changes + * X.509 certificates with more than one AttributeTypeAndValue per + RelativeDistinguishedName are not accepted any more. + * ssl_read() now returns POLARSSL_ERR_NET_WANT_READ rather than + POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE on harmless alerts. + * Accept spaces at end of line or end of buffer in base64_decode(). + += Version 1.2.11 released 2014-07-11 +Features + * Entropy module now supports seed writing and reading + +Changes + * Introduced POLARSSL_HAVE_READDIR_R for systems without it + * Improvements to the CMake build system, contributed by Julian Ospald. + * Work around a bug of the version of Clang shipped by Apple with Mavericks + that prevented bignum.c from compiling. (Reported by Rafael Baptista.) + * Improvements to tests/Makefile, contributed by Oden Eriksson. + * Use UTC time to check certificate validity. + * Reject certificates with times not in UTC, per RFC 5280. + * Migrate zeroizing of data to polarssl_zeroize() instead of memset() + against unwanted compiler optimizations + +Security + * Forbid change of server certificate during renegotiation to prevent + "triple handshake" attack when authentication mode is optional (the + attack was already impossible when authentication is required). + * Check notBefore timestamp of certificates and CRLs from the future. + * Forbid sequence number wrapping + * Prevent potential NULL pointer dereference in ssl_read_record() (found by + TrustInSoft) + * Fix length checking for AEAD ciphersuites (found by Codenomicon). + It was possible to crash the server (and client) using crafted messages + when a GCM suite was chosen. + +Bugfix + * Fixed X.509 hostname comparison (with non-regular characters) + * SSL now gracefully handles missing RNG + * crypt_and_hash app checks MAC before final decryption + * Fixed x509_crt_parse_path() bug on Windows platforms + * Added missing MPI_CHK() around some statements in mpi_div_mpi() (found by + TrustInSoft) + * Fixed potential overflow in certificate size verification in + ssl_write_certificate() (found by TrustInSoft) + * Fix ASM format in bn_mul.h + * Potential memory leak in bignum_selftest() + * Replaced expired test certificate + * ssl_mail_client now terminates lines with CRLF, instead of LF + * Fix bug in RSA PKCS#1 v1.5 "reversed" operations + * Fixed testing with out-of-source builds using cmake + * Fixed version-major intolerance in server + * Fixed CMake symlinking on out-of-source builds + * Bignum's MIPS-32 assembly was used on MIPS-64, causing chaos. (Found by + Alex Wilson.) + * ssl_init() was leaving a dirty pointer in ssl_context if malloc of + out_ctr failed + * ssl_handshake_init() was leaving dirty pointers in subcontexts if malloc + of one of them failed + * x509_get_current_time() uses localtime_r() to prevent thread issues + * Some example server programs were not sending the close_notify alert. + * Potential memory leak in mpi_exp_mod() when error occurs during + calculation of RR. + * Improve interoperability by not writing extension length in ClientHello + when no extensions are present (found by Matthew Page) + * rsa_check_pubkey() now allows an E up to N + * On OpenBSD, use arc4random_buf() instead of rand() to prevent warnings + * mpi_fill_random() was creating numbers larger than requested on + big-endian platform when size was not an integer number of limbs + * Fix detection of DragonflyBSD in net.c (found by Markus Pfeiffer) + * Stricter check on SSL ClientHello internal sizes compared to actual packet + size (found by TrustInSoft) + * Fix preprocessor checks for bn_mul PPC asm (found by Barry K. Nathan). + * Use \n\t rather than semicolons for bn_mul asm, since some assemblers + interpret semicolons as comment delimiters (found by Barry K. Nathan). + * Disable broken Sparc64 bn_mul assembly (found by Florian Obser). + * Fix base64_decode() to return and check length correctly (in case of + tight buffers) + += Version 1.2.10 released 2013-10-07 +Changes + * Changed RSA blinding to a slower but thread-safe version + +Bugfix + * Fixed memory leak in RSA as a result of introduction of blinding + * Fixed ssl_pkcs11_decrypt() prototype + * Fixed MSVC project files + += Version 1.2.9 released 2013-10-01 +Changes + * x509_verify() now case insensitive for cn (RFC 6125 6.4) + +Bugfix + * Fixed potential memory leak when failing to resume a session + * Fixed potential file descriptor leaks (found by Remi Gacogne) + * Minor fixes + +Security + * Fixed potential heap buffer overflow on large hostname setting + * Fixed potential negative value misinterpretation in load_file() + * RSA blinding on CRT operations to counter timing attacks + (found by Cyril Arnaud and Pierre-Alain Fouque) + += Version 1.2.8 released 2013-06-19 +Features + * Parsing of PKCS#8 encrypted private key files + * PKCS#12 PBE and derivation functions + * Centralized module option values in config.h to allow user-defined + settings without editing header files by using POLARSSL_CONFIG_OPTIONS + +Changes + * HAVEGE random generator disabled by default + * Internally split up x509parse_key() into a (PEM) handler function + and specific DER parser functions for the PKCS#1 and unencrypted + PKCS#8 private key formats + * Added mechanism to provide alternative implementations for all + symmetric cipher and hash algorithms (e.g. POLARSSL_AES_ALT in + config.h) + * PKCS#5 module added. Moved PBKDF2 functionality inside and deprecated + old PBKDF2 module + +Bugfix + * Secure renegotiation extension should only be sent in case client + supports secure renegotiation + * Fixed offset for cert_type list in ssl_parse_certificate_request() + * Fixed const correctness issues that have no impact on the ABI + * x509parse_crt() now better handles PEM error situations + * ssl_parse_certificate() now calls x509parse_crt_der() directly + instead of the x509parse_crt() wrapper that can also parse PEM + certificates + * x509parse_crtpath() is now reentrant and uses more portable stat() + * Fixed bignum.c and bn_mul.h to support Thumb2 and LLVM compiler + * Fixed values for 2-key Triple DES in cipher layer + * ssl_write_certificate_request() can handle empty ca_chain + +Security + * A possible DoS during the SSL Handshake, due to faulty parsing of + PEM-encoded certificates has been fixed (found by Jack Lloyd) + += Version 1.2.7 released 2013-04-13 +Features + * Ability to specify allowed ciphersuites based on the protocol version. + +Changes + * Default Blowfish keysize is now 128-bits + * Test suites made smaller to accommodate Raspberry Pi + +Bugfix + * Fix for MPI assembly for ARM + * GCM adapted to support sizes > 2^29 + += Version 1.2.6 released 2013-03-11 +Bugfix + * Fixed memory leak in ssl_free() and ssl_reset() for active session + * Corrected GCM counter incrementation to use only 32-bits instead of + 128-bits (found by Yawning Angel) + * Fixes for 64-bit compilation with MS Visual Studio + * Fixed net_bind() for specified IP addresses on little endian systems + * Fixed assembly code for ARM (Thumb and regular) for some compilers + +Changes + * Internally split up rsa_pkcs1_encrypt(), rsa_pkcs1_decrypt(), + rsa_pkcs1_sign() and rsa_pkcs1_verify() to separate PKCS#1 v1.5 and + PKCS#1 v2.1 functions + * Added support for custom labels when using rsa_rsaes_oaep_encrypt() + or rsa_rsaes_oaep_decrypt() + * Re-added handling for SSLv2 Client Hello when the define + POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is set + * The SSL session cache module (ssl_cache) now also retains peer_cert + information (not the entire chain) + +Security + * Removed further timing differences during SSL message decryption in + ssl_decrypt_buf() + * Removed timing differences due to bad padding from + rsa_rsaes_pkcs1_v15_decrypt() and rsa_pkcs1_decrypt() for PKCS#1 v1.5 + operations + += Version 1.2.5 released 2013-02-02 +Changes + * Allow enabling of dummy error_strerror() to support some use-cases + * Debug messages about padding errors during SSL message decryption are + disabled by default and can be enabled with POLARSSL_SSL_DEBUG_ALL + * Sending of security-relevant alert messages that do not break + interoperability can be switched on/off with the flag + POLARSSL_SSL_ALL_ALERT_MESSAGES + +Security + * Removed timing differences during SSL message decryption in + ssl_decrypt_buf() due to badly formatted padding + += Version 1.2.4 released 2013-01-25 +Changes + * More advanced SSL ciphersuite representation and moved to more dynamic + SSL core + * Added ssl_handshake_step() to allow single stepping the handshake process + +Bugfix + * Memory leak when using RSA_PKCS_V21 operations fixed + * Handle future version properly in ssl_write_certificate_request() + * Correctly handle CertificateRequest message in client for <= TLS 1.1 + without DN list + += Version 1.2.3 released 2012-11-26 +Bugfix + * Server not always sending correct CertificateRequest message + += Version 1.2.2 released 2012-11-24 +Changes + * Added p_hw_data to ssl_context for context specific hardware acceleration + data + * During verify trust-CA is only checked for expiration and CRL presence + +Bugfixes + * Fixed client authentication compatibility + * Fixed dependency on POLARSSL_SHA4_C in SSL modules + += Version 1.2.1 released 2012-11-20 +Changes + * Depth that the certificate verify callback receives is now numbered + bottom-up (Peer cert depth is 0) + +Bugfixes + * Fixes for MSVC6 + * Moved mpi_inv_mod() outside POLARSSL_GENPRIME + * Allow R and A to point to same mpi in mpi_div_mpi (found by Manuel + Pégourié-Gonnard) + * Fixed possible segfault in mpi_shift_r() (found by Manuel + Pégourié-Gonnard) + * Added max length check for rsa_pkcs1_sign with PKCS#1 v2.1 + += Version 1.2.0 released 2012-10-31 +Features + * Added support for NULL cipher (POLARSSL_CIPHER_NULL_CIPHER) and weak + ciphersuites (POLARSSL_ENABLE_WEAK_CIPHERSUITES). They are disabled by + default! + * Added support for wildcard certificates + * Added support for multi-domain certificates through the X509 Subject + Alternative Name extension + * Added preliminary ASN.1 buffer writing support + * Added preliminary X509 Certificate Request writing support + * Added key_app_writer example application + * Added cert_req example application + * Added base Galois Counter Mode (GCM) for AES + * Added TLS 1.2 support (RFC 5246) + * Added GCM suites to TLS 1.2 (RFC 5288) + * Added commandline error code convertor (util/strerror) + * Added support for Hardware Acceleration hooking in SSL/TLS + * Added OpenSSL / PolarSSL compatibility script (tests/compat.sh) and + example application (programs/ssl/o_p_test) (requires OpenSSL) + * Added X509 CA Path support + * Added Thumb assembly optimizations + * Added DEFLATE compression support as per RFC3749 (requires zlib) + * Added blowfish algorithm (Generic and cipher layer) + * Added PKCS#5 PBKDF2 key derivation function + * Added Secure Renegotiation (RFC 5746) + * Added predefined DHM groups from RFC 5114 + * Added simple SSL session cache implementation + * Added ServerName extension parsing (SNI) at server side + * Added option to add minimum accepted SSL/TLS protocol version + +Changes + * Removed redundant POLARSSL_DEBUG_MSG define + * AES code only check for Padlock once + * Fixed const-correctness mpi_get_bit() + * Documentation for mpi_lsb() and mpi_msb() + * Moved out_msg to out_hdr + 32 to support hardware acceleration + * Changed certificate verify behaviour to comply with RFC 6125 section 6.3 + to not match CN if subjectAltName extension is present (Closes ticket #56) + * Cipher layer cipher_mode_t POLARSSL_MODE_CFB128 is renamed to + POLARSSL_MODE_CFB, to also handle different block size CFB modes. + * Removed handling for SSLv2 Client Hello (as per RFC 5246 recommendation) + * Revamped session resumption handling + * Generalized external private key implementation handling (like PKCS#11) + in SSL/TLS + * Revamped x509_verify() and the SSL f_vrfy callback implementations + * Moved from unsigned long to fixed width uint32_t types throughout code + * Renamed ciphersuites naming scheme to IANA reserved names + +Bugfix + * Fixed handling error in mpi_cmp_mpi() on longer B values (found by + Hui Dong) + * Fixed potential heap corruption in x509_name allocation + * Fixed single RSA test that failed on Big Endian systems (Closes ticket #54) + * mpi_exp_mod() now correctly handles negative base numbers (Closes ticket + #52) + * Handle encryption with private key and decryption with public key as per + RFC 2313 + * Handle empty certificate subject names + * Prevent reading over buffer boundaries on X509 certificate parsing + * mpi_add_abs() now correctly handles adding short numbers to long numbers + with carry rollover (found by Ruslan Yushchenko) + * Handle existence of OpenSSL Trust Extensions at end of X.509 DER blob + * Fixed MPI assembly for SPARC64 platform + +Security + * Fixed potential memory zeroization on miscrafted RSA key (found by Eloi + Vanderbeken) + += Version 1.1.8 released on 2013-10-01 +Bugfix + * Fixed potential memory leak when failing to resume a session + * Fixed potential file descriptor leaks + +Security + * Potential buffer-overflow for ssl_read_record() (independently found by + both TrustInSoft and Paul Brodeur of Leviathan Security Group) + * Potential negative value misinterpretation in load_file() + * Potential heap buffer overflow on large hostname setting + += Version 1.1.7 released on 2013-06-19 +Changes + * HAVEGE random generator disabled by default + +Bugfix + * x509parse_crt() now better handles PEM error situations + * ssl_parse_certificate() now calls x509parse_crt_der() directly + instead of the x509parse_crt() wrapper that can also parse PEM + certificates + * Fixed values for 2-key Triple DES in cipher layer + * ssl_write_certificate_request() can handle empty ca_chain + +Security + * A possible DoS during the SSL Handshake, due to faulty parsing of + PEM-encoded certificates has been fixed (found by Jack Lloyd) + += Version 1.1.6 released on 2013-03-11 +Bugfix + * Fixed net_bind() for specified IP addresses on little endian systems + +Changes + * Allow enabling of dummy error_strerror() to support some use-cases + * Debug messages about padding errors during SSL message decryption are + disabled by default and can be enabled with POLARSSL_SSL_DEBUG_ALL + +Security + * Removed timing differences during SSL message decryption in + ssl_decrypt_buf() + * Removed timing differences due to bad padding from + rsa_rsaes_pkcs1_v15_decrypt() and rsa_pkcs1_decrypt() for PKCS#1 v1.5 + operations + += Version 1.1.5 released on 2013-01-16 +Bugfix + * Fixed MPI assembly for SPARC64 platform + * Handle existence of OpenSSL Trust Extensions at end of X.509 DER blob + * mpi_add_abs() now correctly handles adding short numbers to long numbers + with carry rollover + * Moved mpi_inv_mod() outside POLARSSL_GENPRIME + * Prevent reading over buffer boundaries on X509 certificate parsing + * mpi_exp_mod() now correctly handles negative base numbers (Closes ticket + #52) + * Fixed possible segfault in mpi_shift_r() (found by Manuel + Pégourié-Gonnard) + * Allow R and A to point to same mpi in mpi_div_mpi (found by Manuel + Pégourié-Gonnard) + * Added max length check for rsa_pkcs1_sign with PKCS#1 v2.1 + * Memory leak when using RSA_PKCS_V21 operations fixed + * Handle encryption with private key and decryption with public key as per + RFC 2313 + * Fixes for MSVC6 + +Security + * Fixed potential memory zeroization on miscrafted RSA key (found by Eloi + Vanderbeken) + += Version 1.1.4 released on 2012-05-31 +Bugfix + * Correctly handle empty SSL/TLS packets (Found by James Yonan) + * Fixed potential heap corruption in x509_name allocation + * Fixed single RSA test that failed on Big Endian systems (Closes ticket #54) + += Version 1.1.3 released on 2012-04-29 +Bugfix + * Fixed random MPI generation to not generate more size than requested. + += Version 1.1.2 released on 2012-04-26 +Bugfix + * Fixed handling error in mpi_cmp_mpi() on longer B values (found by + Hui Dong) + +Security + * Fixed potential memory corruption on miscrafted client messages (found by + Frama-C team at CEA LIST) + * Fixed generation of DHM parameters to correct length (found by Ruslan + Yushchenko) + += Version 1.1.1 released on 2012-01-23 +Bugfix + * Check for failed malloc() in ssl_set_hostname() and x509_get_entries() + (Closes ticket #47, found by Hugo Leisink) + * Fixed issues with Intel compiler on 64-bit systems (Closes ticket #50) + * Fixed multiple compiler warnings for VS6 and armcc + * Fixed bug in CTR_CRBG selftest + += Version 1.1.0 released on 2011-12-22 +Features + * Added ssl_session_reset() to allow better multi-connection pools of + SSL contexts without needing to set all non-connection-specific + data and pointers again. Adapted ssl_server to use this functionality. + * Added ssl_set_max_version() to allow clients to offer a lower maximum + supported version to a server to help buggy server implementations. + (Closes ticket #36) + * Added cipher_get_cipher_mode() and cipher_get_cipher_operation() + introspection functions (Closes ticket #40) + * Added CTR_DRBG based on AES-256-CTR (NIST SP 800-90) random generator + * Added a generic entropy accumulator that provides support for adding + custom entropy sources and added some generic and platform dependent + entropy sources + +Changes + * Documentation for AES and Camellia in modes CTR and CFB128 clarified. + * Fixed rsa_encrypt and rsa_decrypt examples to use public key for + encryption and private key for decryption. (Closes ticket #34) + * Inceased maximum size of ASN1 length reads to 32-bits. + * Added an EXPLICIT tag number parameter to x509_get_ext() + * Added a separate CRL entry extension parsing function + * Separated the ASN.1 parsing code from the X.509 specific parsing code. + So now there is a module that is controlled with POLARSSL_ASN1_PARSE_C. + * Changed the defined key-length of DES ciphers in cipher.h to include the + parity bits, to prevent mistakes in copying data. (Closes ticket #33) + * Loads of minimal changes to better support WINCE as a build target + (Credits go to Marco Lizza) + * Added POLARSSL_MPI_WINDOW_SIZE definition to allow easier time to memory + trade-off + * Introduced POLARSSL_MPI_MAX_SIZE and POLARSSL_MPI_MAX_BITS for MPI size + management (Closes ticket #44) + * Changed the used random function pointer to more flexible format. Renamed + havege_rand() to havege_random() to prevent mistakes. Lots of changes as + a consequence in library code and programs + * Moved all examples programs to use the new entropy and CTR_DRBG + * Added permissive certificate parsing to x509parse_crt() and + x509parse_crtfile(). With permissive parsing the parsing does not stop on + encountering a parse-error. Beware that the meaning of return values has + changed! + * All error codes are now negative. Even on mermory failures and IO errors. + +Bugfix + * Fixed faulty HMAC-MD2 implementation. Found by dibac. (Closes + ticket #37) + * Fixed a bug where the CRL parser expected an EXPLICIT ASN.1 tag + before version numbers + * Allowed X509 key usage parsing to accept 4 byte values instead of the + standard 1 byte version sometimes used by Microsoft. (Closes ticket #38) + * Fixed incorrect behaviour in case of RSASSA-PSS with a salt length + smaller than the hash length. (Closes ticket #41) + * If certificate serial is longer than 32 octets, serial number is now + appended with '....' after first 28 octets + * Improved build support for s390x and sparc64 in bignum.h + * Fixed MS Visual C++ name clash with int64 in sha4.h + * Corrected removal of leading "00:" in printing serial numbers in + certificates and CRLs + += Version 1.0.0 released on 2011-07-27 +Features + * Expanded cipher layer with support for CFB128 and CTR mode + * Added rsa_encrypt and rsa_decrypt simple example programs. + +Changes + * The generic cipher and message digest layer now have normal error + codes instead of integers + +Bugfix + * Undid faulty bug fix in ssl_write() when flushing old data (Ticket + #18) + += Version 0.99-pre5 released on 2011-05-26 +Features + * Added additional Cipher Block Modes to symmetric ciphers + (AES CTR, Camellia CTR, XTEA CBC) including the option to + enable and disable individual modes when needed + * Functions requiring File System functions can now be disabled + by undefining POLARSSL_FS_IO + * A error_strerror function() has been added to translate between + error codes and their description. + * Added mpi_get_bit() and mpi_set_bit() individual bit setter/getter + functions. + * Added ssl_mail_client and ssl_fork_server as example programs. + +Changes + * Major argument / variable rewrite. Introduced use of size_t + instead of int for buffer lengths and loop variables for + better unsigned / signed use. Renamed internal bigint types + t_int and t_dbl to t_uint and t_udbl in the process + * mpi_init() and mpi_free() now only accept a single MPI + argument and do not accept variable argument lists anymore. + * The error codes have been remapped and combining error codes + is now done with a PLUS instead of an OR as error codes + used are negative. + * Changed behaviour of net_read(), ssl_fetch_input() and ssl_recv(). + net_recv() now returns 0 on EOF instead of + POLARSSL_ERR_NET_CONN_RESET. ssl_fetch_input() returns + POLARSSL_ERR_SSL_CONN_EOF on an EOF from its f_recv() function. + ssl_read() returns 0 if a POLARSSL_ERR_SSL_CONN_EOF is received + after the handshake. + * Network functions now return POLARSSL_ERR_NET_WANT_READ or + POLARSSL_ERR_NET_WANT_WRITE instead of the ambiguous + POLARSSL_ERR_NET_TRY_AGAIN + += Version 0.99-pre4 released on 2011-04-01 +Features + * Added support for PKCS#1 v2.1 encoding and thus support + for the RSAES-OAEP and RSASSA-PSS operations. + * Reading of Public Key files incorporated into default x509 + functionality as well. + * Added mpi_fill_random() for centralized filling of big numbers + with random data (Fixed ticket #10) + +Changes + * Debug print of MPI now removes leading zero octets and + displays actual bit size of the value. + * x509parse_key() (and as a consequence x509parse_keyfile()) + does not zeroize memory in advance anymore. Use rsa_init() + before parsing a key or keyfile! + +Bugfix + * Debug output of MPI's now the same independent of underlying + platform (32-bit / 64-bit) (Fixes ticket #19, found by Mads + Kiilerich and Mihai Militaru) + * Fixed bug in ssl_write() when flushing old data (Fixed ticket + #18, found by Nikolay Epifanov) + * Fixed proper handling of RSASSA-PSS verification with variable + length salt lengths + += Version 0.99-pre3 released on 2011-02-28 +This release replaces version 0.99-pre2 which had possible copyright issues. +Features + * Parsing PEM private keys encrypted with DES and AES + are now supported as well (Fixes ticket #5) + * Added crl_app program to allow easy reading and + printing of X509 CRLs from file + +Changes + * Parsing of PEM files moved to separate module (Fixes + ticket #13). Also possible to remove PEM support for + systems only using DER encoding + +Bugfixes + * Corrected parsing of UTCTime dates before 1990 and + after 1950 + * Support more exotic OID's when parsing certificates + (found by Mads Kiilerich) + * Support more exotic name representations when parsing + certificates (found by Mads Kiilerich) + * Replaced the expired test certificates + * Do not bail out if no client certificate specified. Try + to negotiate anonymous connection (Fixes ticket #12, + found by Boris Krasnovskiy) + +Security fixes + * Fixed a possible Man-in-the-Middle attack on the + Diffie Hellman key exchange (thanks to Larry Highsmith, + Subreption LLC) + += Version 0.99-pre1 released on 2011-01-30 +Features +Note: Most of these features have been donated by Fox-IT + * Added Doxygen source code documentation parts + * Added reading of DHM context from memory and file + * Improved X509 certificate parsing to include extended + certificate fields, including Key Usage + * Improved certificate verification and verification + against the available CRLs + * Detection for DES weak keys and parity bits added + * Improvements to support integration in other + applications: + + Added generic message digest and cipher wrapper + + Improved information about current capabilities, + status, objects and configuration + + Added verification callback on certificate chain + verification to allow external blacklisting + + Additional example programs to show usage + * Added support for PKCS#11 through the use of the + libpkcs11-helper library + +Changes + * x509parse_time_expired() checks time in addition to + the existing date check + * The ciphers member of ssl_context and the cipher member + of ssl_session have been renamed to ciphersuites and + ciphersuite respectively. This clarifies the difference + with the generic cipher layer and is better naming + altogether + += Version 0.14.0 released on 2010-08-16 +Features + * Added support for SSL_EDH_RSA_AES_128_SHA and + SSL_EDH_RSA_CAMELLIA_128_SHA ciphersuites + * Added compile-time and run-time version information + * Expanded ssl_client2 arguments for more flexibility + * Added support for TLS v1.1 + +Changes + * Made Makefile cleaner + * Removed dependency on rand() in rsa_pkcs1_encrypt(). + Now using random fuction provided to function and + changed the prototype of rsa_pkcs1_encrypt(), + rsa_init() and rsa_gen_key(). + * Some SSL defines were renamed in order to avoid + future confusion + +Bug fixes + * Fixed CMake out of source build for tests (found by + kkert) + * rsa_check_private() now supports PKCS1v2 keys as well + * Fixed deadlock in rsa_pkcs1_encrypt() on failing random + generator + += Version 0.13.1 released on 2010-03-24 +Bug fixes + * Fixed Makefile in library that was mistakenly merged + * Added missing const string fixes + += Version 0.13.0 released on 2010-03-21 +Features + * Added option parsing for host and port selection to + ssl_client2 + * Added support for GeneralizedTime in X509 parsing + * Added cert_app program to allow easy reading and + printing of X509 certificates from file or SSL + connection. + +Changes + * Added const correctness for main code base + * X509 signature algorithm determination is now + in a function to allow easy future expansion + * Changed symmetric cipher functions to + identical interface (returning int result values) + * Changed ARC4 to use separate input/output buffer + * Added reset function for HMAC context as speed-up + for specific use-cases + +Bug fixes + * Fixed bug resulting in failure to send the last + certificate in the chain in ssl_write_certificate() and + ssl_write_certificate_request() (found by fatbob) + * Added small fixes for compiler warnings on a Mac + (found by Frank de Brabander) + * Fixed algorithmic bug in mpi_is_prime() (found by + Smbat Tonoyan) + += Version 0.12.1 released on 2009-10-04 +Changes + * Coverage test definitions now support 'depends_on' + tagging system. + * Tests requiring specific hashing algorithms now honor + the defines. + +Bug fixes + * Changed typo in #ifdef in x509parse.c (found + by Eduardo) + += Version 0.12.0 released on 2009-07-28 +Features + * Added CMake makefiles as alternative to regular Makefiles. + * Added preliminary Code Coverage tests for AES, ARC4, + Base64, MPI, SHA-family, MD-family, HMAC-SHA-family, + Camellia, DES, 3-DES, RSA PKCS#1, XTEA, Diffie-Hellman + and X509parse. + +Changes + * Error codes are not (necessarily) negative. Keep + this is mind when checking for errors. + * RSA_RAW renamed to SIG_RSA_RAW for consistency. + * Fixed typo in name of POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE. + * Changed interface for AES and Camellia setkey functions + to indicate invalid key lengths. + +Bug fixes + * Fixed include location of endian.h on FreeBSD (found by + Gabriel) + * Fixed include location of endian.h and name clash on + Apples (found by Martin van Hensbergen) + * Fixed HMAC-MD2 by modifying md2_starts(), so that the + required HMAC ipad and opad variables are not cleared. + (found by code coverage tests) + * Prevented use of long long in bignum if + POLARSSL_HAVE_LONGLONG not defined (found by Giles + Bathgate). + * Fixed incorrect handling of negative strings in + mpi_read_string() (found by code coverage tests). + * Fixed segfault on handling empty rsa_context in + rsa_check_pubkey() and rsa_check_privkey() (found by + code coverage tests). + * Fixed incorrect handling of one single negative input + value in mpi_add_abs() (found by code coverage tests). + * Fixed incorrect handling of negative first input + value in mpi_sub_abs() (found by code coverage tests). + * Fixed incorrect handling of negative first input + value in mpi_mod_mpi() and mpi_mod_int(). Resulting + change also affects mpi_write_string() (found by code + coverage tests). + * Corrected is_prime() results for 0, 1 and 2 (found by + code coverage tests). + * Fixed Camellia and XTEA for 64-bit Windows systems. + += Version 0.11.1 released on 2009-05-17 + * Fixed missing functionality for SHA-224, SHA-256, SHA384, + SHA-512 in rsa_pkcs1_sign() + += Version 0.11.0 released on 2009-05-03 + * Fixed a bug in mpi_gcd() so that it also works when both + input numbers are even and added testcases to check + (found by Pierre Habouzit). + * Added support for SHA-224, SHA-256, SHA-384 and SHA-512 + one way hash functions with the PKCS#1 v1.5 signing and + verification. + * Fixed minor bug regarding mpi_gcd located within the + POLARSSL_GENPRIME block. + * Fixed minor memory leak in x509parse_crt() and added better + handling of 'full' certificate chains (found by Mathias + Olsson). + * Centralized file opening and reading for x509 files into + load_file() + * Made definition of net_htons() endian-clean for big endian + systems (Found by Gernot). + * Undefining POLARSSL_HAVE_ASM now also handles prevents asm in + padlock and timing code. + * Fixed an off-by-one buffer allocation in ssl_set_hostname() + responsible for crashes and unwanted behaviour. + * Added support for Certificate Revocation List (CRL) parsing. + * Added support for CRL revocation to x509parse_verify() and + SSL/TLS code. + * Fixed compatibility of XTEA and Camellia on a 64-bit system + (found by Felix von Leitner). + += Version 0.10.0 released on 2009-01-12 + * Migrated XySSL to PolarSSL + * Added XTEA symmetric cipher + * Added Camellia symmetric cipher + * Added support for ciphersuites: SSL_RSA_CAMELLIA_128_SHA, + SSL_RSA_CAMELLIA_256_SHA and SSL_EDH_RSA_CAMELLIA_256_SHA + * Fixed dangerous bug that can cause a heap overflow in + rsa_pkcs1_decrypt (found by Christophe Devine) + +================================================================ +XySSL ChangeLog + += Version 0.9 released on 2008-03-16 + + * Added support for ciphersuite: SSL_RSA_AES_128_SHA + * Enabled support for large files by default in aescrypt2.c + * Preliminary openssl wrapper contributed by David Barrett + * Fixed a bug in ssl_write() that caused the same payload to + be sent twice in non-blocking mode when send returns EAGAIN + * Fixed ssl_parse_client_hello(): session id and challenge must + not be swapped in the SSLv2 ClientHello (found by Greg Robson) + * Added user-defined callback debug function (Krystian Kolodziej) + * Before freeing a certificate, properly zero out all cert. data + * Fixed the "mode" parameter so that encryption/decryption are + not swapped on PadLock; also fixed compilation on older versions + of gcc (bug reported by David Barrett) + * Correctly handle the case in padlock_xcryptcbc() when input or + output data is non-aligned by falling back to the software + implementation, as VIA Nehemiah cannot handle non-aligned buffers + * Fixed a memory leak in x509parse_crt() which was reported by Greg + Robson-Garth; some x509write.c fixes by Pascal Vizeli, thanks to + Matthew Page who reported several bugs + * Fixed x509_get_ext() to accept some rare certificates which have + an INTEGER instead of a BOOLEAN for BasicConstraints::cA. + * Added support on the client side for the TLS "hostname" extension + (patch contributed by David Patino) + * Make x509parse_verify() return BADCERT_CN_MISMATCH when an empty + string is passed as the CN (bug reported by spoofy) + * Added an option to enable/disable the BN assembly code + * Updated rsa_check_privkey() to verify that (D*E) = 1 % (P-1)*(Q-1) + * Disabled obsolete hash functions by default (MD2, MD4); updated + selftest and benchmark to not test ciphers that have been disabled + * Updated x509parse_cert_info() to correctly display byte 0 of the + serial number, setup correct server port in the ssl client example + * Fixed a critical denial-of-service with X.509 cert. verification: + peer may cause xyssl to loop indefinitely by sending a certificate + for which the RSA signature check fails (bug reported by Benoit) + * Added test vectors for: AES-CBC, AES-CFB, DES-CBC and 3DES-CBC, + HMAC-MD5, HMAC-SHA1, HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 + * Fixed HMAC-SHA-384 and HMAC-SHA-512 (thanks to Josh Sinykin) + * Modified ssl_parse_client_key_exchange() to protect against + Daniel Bleichenbacher attack on PKCS#1 v1.5 padding, as well + as the Klima-Pokorny-Rosa extension of Bleichenbacher's attack + * Updated rsa_gen_key() so that ctx->N is always nbits in size + * Fixed assembly PPC compilation errors on Mac OS X, thanks to + David Barrett and Dusan Semen + += Version 0.8 released on 2007-10-20 + + * Modified the HMAC functions to handle keys larger + than 64 bytes, thanks to Stephane Desneux and gary ng + * Fixed ssl_read_record() to properly update the handshake + message digests, which fixes IE6/IE7 client authentication + * Cleaned up the XYSSL* #defines, suggested by Azriel Fasten + * Fixed net_recv(), thanks to Lorenz Schori and Egon Kocjan + * Added user-defined callbacks for handling I/O and sessions + * Added lots of debugging output in the SSL/TLS functions + * Added preliminary X.509 cert. writing by Pascal Vizeli + * Added preliminary support for the VIA PadLock routines + * Added AES-CFB mode of operation, contributed by chmike + * Added an SSL/TLS stress testing program (ssl_test.c) + * Updated the RSA PKCS#1 code to allow choosing between + RSA_PUBLIC and RSA_PRIVATE, as suggested by David Barrett + * Updated ssl_read() to skip 0-length records from OpenSSL + * Fixed the make install target to comply with *BSD make + * Fixed a bug in mpi_read_binary() on 64-bit platforms + * mpi_is_prime() speedups, thanks to Kevin McLaughlin + * Fixed a long standing memory leak in mpi_is_prime() + * Replaced realloc with malloc in mpi_grow(), and set + the sign of zero as positive in mpi_init() (reported + by Jonathan M. McCune) + += Version 0.7 released on 2007-07-07 + + * Added support for the MicroBlaze soft-core processor + * Fixed a bug in ssl_tls.c which sometimes prevented SSL + connections from being established with non-blocking I/O + * Fixed a couple bugs in the VS6 and UNIX Makefiles + * Fixed the "PIC register ebx clobbered in asm" bug + * Added HMAC starts/update/finish support functions + * Added the SHA-224, SHA-384 and SHA-512 hash functions + * Fixed the net_set_*block routines, thanks to Andreas + * Added a few demonstration programs: md5sum, sha1sum, + dh_client, dh_server, rsa_genkey, rsa_sign, rsa_verify + * Added new bignum import and export helper functions + * Rewrote README.txt in program/ssl/ca to better explain + how to create a test PKI + += Version 0.6 released on 2007-04-01 + + * Ciphers used in SSL/TLS can now be disabled at compile + time, to reduce the memory footprint on embedded systems + * Added multiply assembly code for the TriCore and modified + havege_struct for this processor, thanks to David Patiño + * Added multiply assembly code for 64-bit PowerPCs, + thanks to Peking University and the OSU Open Source Lab + * Added experimental support of Quantum Cryptography + * Added support for autoconf, contributed by Arnaud Cornet + * Fixed "long long" compilation issues on IA-64 and PPC64 + * Fixed a bug introduced in xyssl-0.5/timing.c: hardclock + was not being correctly defined on ARM and MIPS + += Version 0.5 released on 2007-03-01 + + * Added multiply assembly code for SPARC and Alpha + * Added (beta) support for non-blocking I/O operations + * Implemented session resuming and client authentication + * Fixed some portability issues on WinCE, MINIX 3, Plan9 + (thanks to Benjamin Newman), HP-UX, FreeBSD and Solaris + * Improved the performance of the EDH key exchange + * Fixed a bug that caused valid packets with a payload + size of 16384 bytes to be rejected + += Version 0.4 released on 2007-02-01 + + * Added support for Ephemeral Diffie-Hellman key exchange + * Added multiply asm code for SSE2, ARM, PPC, MIPS and M68K + * Various improvement to the modular exponentiation code + * Rewrote the headers to generate the API docs with doxygen + * Fixed a bug in ssl_encrypt_buf (incorrect padding was + generated) and in ssl_parse_client_hello (max. client + version was not properly set), thanks to Didier Rebeix + * Fixed another bug in ssl_parse_client_hello: clients with + cipherlists larger than 96 bytes were incorrectly rejected + * Fixed a couple memory leak in x509_read.c + += Version 0.3 released on 2007-01-01 + + * Added server-side SSLv3 and TLSv1.0 support + * Multiple fixes to enhance the compatibility with g++, + thanks to Xosé Antón Otero Ferreira + * Fixed a bug in the CBC code, thanks to dowst; also, + the bignum code is no longer dependent on long long + * Updated rsa_pkcs1_sign to handle arbitrary large inputs + * Updated timing.c for improved compatibility with i386 + and 486 processors, thanks to Arnaud Cornet + += Version 0.2 released on 2006-12-01 + + * Updated timing.c to support ARM and MIPS arch + * Updated the MPI code to support 8086 on MSVC 1.5 + * Added the copyright notice at the top of havege.h + * Fixed a bug in sha2_hmac, thanks to newsoft/Wenfang Zhang + * Fixed a bug reported by Adrian Rüegsegger in x509_read_key + * Fixed a bug reported by Torsten Lauter in ssl_read_record + * Fixed a bug in rsa_check_privkey that would wrongly cause + valid RSA keys to be dismissed (thanks to oldwolf) + * Fixed a bug in mpi_is_prime that caused some primes to fail + the Miller-Rabin primality test + + I'd also like to thank Younès Hafri for the CRUX linux port, + Khalil Petit who added XySSL into pkgsrc and Arnaud Cornet + who maintains the Debian package :-) + += Version 0.1 released on 2006-11-01 diff --git a/external/mbedtls/DartConfiguration.tcl b/external/mbedtls/DartConfiguration.tcl new file mode 100644 index 0000000..dfa0f07 --- /dev/null +++ b/external/mbedtls/DartConfiguration.tcl @@ -0,0 +1,4 @@ +Site: localhost +BuildName: mbed TLS-test +CoverageCommand: /usr/bin/gcov +MemoryCheckCommand: /usr/bin/valgrind diff --git a/external/mbedtls/LICENSE b/external/mbedtls/LICENSE new file mode 100644 index 0000000..e15ea82 --- /dev/null +++ b/external/mbedtls/LICENSE @@ -0,0 +1,5 @@ +Unless specifically indicated otherwise in a file, Mbed TLS files are provided +under the Apache License 2.0, or the GNU General Public License v2.0 or later +(SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later). + +A copy of these licenses can be found in apache-2.0.txt and gpl-2.0.txt diff --git a/external/mbedtls/Makefile b/external/mbedtls/Makefile new file mode 100644 index 0000000..3942fbd --- /dev/null +++ b/external/mbedtls/Makefile @@ -0,0 +1,138 @@ + +DESTDIR=/usr/local +PREFIX=mbedtls_ + +.SILENT: + +.PHONY: all no_test programs lib tests install uninstall clean test check covtest lcov apidoc apidoc_clean + +all: programs tests + $(MAKE) post_build + +no_test: programs + +programs: lib + $(MAKE) -C programs + +lib: + $(MAKE) -C library + +tests: lib + $(MAKE) -C tests + +ifndef WINDOWS +install: no_test + mkdir -p $(DESTDIR)/include/mbedtls + cp -rp include/mbedtls $(DESTDIR)/include + + mkdir -p $(DESTDIR)/lib + cp -RP library/libmbedtls.* $(DESTDIR)/lib + cp -RP library/libmbedx509.* $(DESTDIR)/lib + cp -RP library/libmbedcrypto.* $(DESTDIR)/lib + + mkdir -p $(DESTDIR)/bin + for p in programs/*/* ; do \ + if [ -x $$p ] && [ ! -d $$p ] ; \ + then \ + f=$(PREFIX)`basename $$p` ; \ + cp $$p $(DESTDIR)/bin/$$f ; \ + fi \ + done + +uninstall: + rm -rf $(DESTDIR)/include/mbedtls + rm -f $(DESTDIR)/lib/libmbedtls.* + rm -f $(DESTDIR)/lib/libmbedx509.* + rm -f $(DESTDIR)/lib/libmbedcrypto.* + + for p in programs/*/* ; do \ + if [ -x $$p ] && [ ! -d $$p ] ; \ + then \ + f=$(PREFIX)`basename $$p` ; \ + rm -f $(DESTDIR)/bin/$$f ; \ + fi \ + done +endif + +WARNING_BORDER =*******************************************************\n +NULL_ENTROPY_WARN_L1=**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! ****\n +NULL_ENTROPY_WARN_L2=**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES ****\n +NULL_ENTROPY_WARN_L3=**** AND IS *NOT* SUITABLE FOR PRODUCTION USE ****\n + +NULL_ENTROPY_WARNING=\n$(WARNING_BORDER)$(NULL_ENTROPY_WARN_L1)$(NULL_ENTROPY_WARN_L2)$(NULL_ENTROPY_WARN_L3)$(WARNING_BORDER) + +WARNING_BORDER_LONG =**********************************************************************************\n +CTR_DRBG_128_BIT_KEY_WARN_L1=**** WARNING! MBEDTLS_CTR_DRBG_USE_128_BIT_KEY defined! ****\n +CTR_DRBG_128_BIT_KEY_WARN_L2=**** Using 128-bit keys for CTR_DRBG limits the security of generated ****\n +CTR_DRBG_128_BIT_KEY_WARN_L3=**** keys and operations that use random values generated to 128-bit security ****\n + +CTR_DRBG_128_BIT_KEY_WARNING=\n$(WARNING_BORDER_LONG)$(CTR_DRBG_128_BIT_KEY_WARN_L1)$(CTR_DRBG_128_BIT_KEY_WARN_L2)$(CTR_DRBG_128_BIT_KEY_WARN_L3)$(WARNING_BORDER_LONG) + +# Post build steps +post_build: +ifndef WINDOWS + + # If 128-bit keys are configured for CTR_DRBG, display an appropriate warning + -scripts/config.pl get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY && ([ $$? -eq 0 ]) && \ + echo '$(CTR_DRBG_128_BIT_KEY_WARNING)' + + # If NULL Entropy is configured, display an appropriate warning + -scripts/config.pl get MBEDTLS_TEST_NULL_ENTROPY && ([ $$? -eq 0 ]) && \ + echo '$(NULL_ENTROPY_WARNING)' +endif + +clean: + $(MAKE) -C library clean + $(MAKE) -C programs clean + $(MAKE) -C tests clean +ifndef WINDOWS + find . \( -name \*.gcno -o -name \*.gcda -o -name \*.info \) -exec rm {} + +endif + +check: lib tests + $(MAKE) -C tests check + +test: check + +ifndef WINDOWS +# note: for coverage testing, build with: +# make CFLAGS='--coverage -g3 -O0' +covtest: + $(MAKE) check + programs/test/selftest + tests/compat.sh + tests/ssl-opt.sh + +lcov: + rm -rf Coverage + lcov --capture --initial --directory library -o files.info + lcov --rc lcov_branch_coverage=1 --capture --directory library -o tests.info + lcov --rc lcov_branch_coverage=1 --add-tracefile files.info --add-tracefile tests.info -o all.info + lcov --rc lcov_branch_coverage=1 --remove all.info -o final.info '*.h' + gendesc tests/Descriptions.txt -o descriptions + genhtml --title "mbed TLS" --description-file descriptions --keep-descriptions --legend --branch-coverage -o Coverage final.info + rm -f files.info tests.info all.info final.info descriptions + +apidoc: + mkdir -p apidoc + cd doxygen && doxygen mbedtls.doxyfile + +apidoc_clean: + rm -rf apidoc +endif + +## Editor navigation files +C_SOURCE_FILES = $(wildcard include/*/*.h library/*.[hc] programs/*/*.[hc] tests/suites/*.function) +# Exuberant-ctags invocation. Other ctags implementations may require different options. +CTAGS = ctags --langmap=c:+.h.function -o +tags: $(C_SOURCE_FILES) + $(CTAGS) $@ $(C_SOURCE_FILES) +TAGS: $(C_SOURCE_FILES) + etags -o $@ $(C_SOURCE_FILES) +global: GPATH GRTAGS GSYMS GTAGS +GPATH GRTAGS GSYMS GTAGS: $(C_SOURCE_FILES) + ls $(C_SOURCE_FILES) | gtags -f - --gtagsconf .globalrc +cscope: cscope.in.out cscope.po.out cscope.out +cscope.in.out cscope.po.out cscope.out: $(C_SOURCE_FILES) + cscope -bq -u -Iinclude -Ilibrary $(patsubst %,-I%,$(wildcard 3rdparty/*/include)) -Itests/include $(C_SOURCE_FILES) +.PHONY: cscope global diff --git a/external/mbedtls/README.md b/external/mbedtls/README.md new file mode 100644 index 0000000..11f9ba4 --- /dev/null +++ b/external/mbedtls/README.md @@ -0,0 +1,180 @@ +README for Mbed TLS +=================== + +Mbed TLS is a C library that implements cryptographic primitives, X.509 certificate manipulation and the SSL/TLS and DTLS protocols. Its small code footprint makes it suitable for embedded systems. + +Configuration +------------- + +Mbed TLS should build out of the box on most systems. Some platform specific options are available in the fully documented configuration file `include/mbedtls/config.h`, which is also the place where features can be selected. This file can be edited manually, or in a more programmatic way using the Perl script `scripts/config.pl` (use `--help` for usage instructions). + +Compiler options can be set using conventional environment variables such as `CC` and `CFLAGS` when using the Make and CMake build system (see below). + +Compiling +--------- + +There are currently three active build systems used within Mbed TLS releases: + +- GNU Make +- CMake +- Microsoft Visual Studio (Microsoft Visual Studio 2010 or later) + +The main systems used for development are CMake and GNU Make. Those systems are always complete and up-to-date. The others should reflect all changes present in the CMake and Make build system, although features may not be ported there automatically. + +The Make and CMake build systems create three libraries: libmbedcrypto, libmbedx509, and libmbedtls. Note that libmbedtls depends on libmbedx509 and libmbedcrypto, and libmbedx509 depends on libmbedcrypto. As a result, some linkers will expect flags to be in a specific order, for example the GNU linker wants `-lmbedtls -lmbedx509 -lmbedcrypto`. Also, when loading shared libraries using dlopen(), you'll need to load libmbedcrypto first, then libmbedx509, before you can load libmbedtls. + +### Make + +We require GNU Make. To build the library and the sample programs, GNU Make and a C compiler are sufficient. Some of the more advanced build targets require some Unix/Linux tools. + +We intentionally only use a minimum of functionality in the makefiles in order to keep them as simple and independent of different toolchains as possible, to allow users to more easily move between different platforms. Users who need more features are recommended to use CMake. + +In order to build from the source code using GNU Make, just enter at the command line: + + make + +In order to run the tests, enter: + + make check + +The tests need Python to be built and Perl to be run. If you don't have one of them installed, you can skip building the tests with: + + make no_test + +You'll still be able to run a much smaller set of tests with: + + programs/test/selftest + +In order to build for a Windows platform, you should use `WINDOWS_BUILD=1` if the target is Windows but the build environment is Unix-like (for instance when cross-compiling, or compiling from an MSYS shell), and `WINDOWS=1` if the build environment is a Windows shell (for instance using mingw32-make) (in that case some targets will not be available). + +Setting the variable `SHARED` in your environment will build shared libraries in addition to the static libraries. Setting `DEBUG` gives you a debug build. You can override `CFLAGS` and `LDFLAGS` by setting them in your environment or on the make command line; compiler warning options may be overridden separately using `WARNING_CFLAGS`. Some directory-specific options (for example, `-I` directives) are still preserved. + +Please note that setting `CFLAGS` overrides its default value of `-O2` and setting `WARNING_CFLAGS` overrides its default value (starting with `-Wall -W`), so if you just want to add some warning options to the default ones, you can do so by setting `CFLAGS=-O2 -Werror` for example. Setting `WARNING_CFLAGS` is useful when you want to get rid of its default content (for example because your compiler doesn't accept `-Wall` as an option). Directory-specific options cannot be overridden from the command line. + +Depending on your platform, you might run into some issues. Please check the Makefiles in `library/`, `programs/` and `tests/` for options to manually add or remove for specific platforms. You can also check [the Mbed TLS Knowledge Base](https://tls.mbed.org/kb) for articles on your platform or issue. + +In case you find that you need to do something else as well, please let us know what, so we can add it to the [Mbed TLS Knowledge Base](https://tls.mbed.org/kb). + +### CMake + +In order to build the source using CMake in a separate directory (recommended), just enter at the command line: + + mkdir /path/to/build_dir && cd /path/to/build_dir + cmake /path/to/mbedtls_source + make + +In order to run the tests, enter: + + make test + +The test suites need Python to be built and Perl to be executed. If you don't have one of these installed, you'll want to disable the test suites with: + + cmake -DENABLE_TESTING=Off /path/to/mbedtls_source + +If you disabled the test suites, but kept the programs enabled, you can still run a much smaller set of tests with: + + programs/test/selftest + +To configure CMake for building shared libraries, use: + + cmake -DUSE_SHARED_MBEDTLS_LIBRARY=On /path/to/mbedtls_source + +There are many different build modes available within the CMake buildsystem. Most of them are available for gcc and clang, though some are compiler-specific: + +- `Release`. This generates the default code without any unnecessary information in the binary files. +- `Debug`. This generates debug information and disables optimization of the code. +- `Coverage`. This generates code coverage information in addition to debug information. +- `ASan`. This instruments the code with AddressSanitizer to check for memory errors. (This includes LeakSanitizer, with recent version of gcc and clang.) (With recent version of clang, this mode also instruments the code with UndefinedSanitizer to check for undefined behaviour.) +- `ASanDbg`. Same as ASan but slower, with debug information and better stack traces. +- `MemSan`. This instruments the code with MemorySanitizer to check for uninitialised memory reads. Experimental, needs recent clang on Linux/x86\_64. +- `MemSanDbg`. Same as MemSan but slower, with debug information, better stack traces and origin tracking. +- `Check`. This activates the compiler warnings that depend on optimization and treats all warnings as errors. + +Switching build modes in CMake is simple. For debug mode, enter at the command line: + + cmake -D CMAKE_BUILD_TYPE=Debug /path/to/mbedtls_source + +To list other available CMake options, use: + + cmake -LH + +Note that, with CMake, you can't adjust the compiler or its flags after the +initial invocation of cmake. This means that `CC=your_cc make` and `make +CC=your_cc` will *not* work (similarly with `CFLAGS` and other variables). +These variables need to be adjusted when invoking cmake for the first time, +for example: + + CC=your_cc cmake /path/to/mbedtls_source + +If you already invoked cmake and want to change those settings, you need to +remove the build directory and create it again. + +Note that it is possible to build in-place; this will however overwrite the +provided Makefiles (see `scripts/tmp_ignore_makefiles.sh` if you want to +prevent `git status` from showing them as modified). In order to do so, from +the Mbed TLS source directory, use: + + cmake . + make + +If you want to change `CC` or `CFLAGS` afterwards, you will need to remove the +CMake cache. This can be done with the following command using GNU find: + + find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} + + +You can now make the desired change: + + CC=your_cc cmake . + make + +Regarding variables, also note that if you set CFLAGS when invoking cmake, +your value of CFLAGS doesn't override the content provided by cmake (depending +on the build mode as seen above), it's merely prepended to it. + +### Microsoft Visual Studio + +The build files for Microsoft Visual Studio are generated for Visual Studio 2010. + +The solution file `mbedTLS.sln` contains all the basic projects needed to build the library and all the programs. The files in tests are not generated and compiled, as these need Python and perl environments as well. However, the selftest program in `programs/test/` is still available. + +Example programs +---------------- + +We've included example programs for a lot of different features and uses in [`programs/`](programs/README.md). Most programs only focus on a single feature or usage scenario, so keep that in mind when copying parts of the code. + +Tests +----- + +Mbed TLS includes an elaborate test suite in `tests/` that initially requires Python to generate the tests files (e.g. `test\_suite\_mpi.c`). These files are generated from a `function file` (e.g. `suites/test\_suite\_mpi.function`) and a `data file` (e.g. `suites/test\_suite\_mpi.data`). The `function file` contains the test functions. The `data file` contains the test cases, specified as parameters that will be passed to the test function. + +For machines with a Unix shell and OpenSSL (and optionally GnuTLS) installed, additional test scripts are available: + +- `tests/ssl-opt.sh` runs integration tests for various TLS options (renegotiation, resumption, etc.) and tests interoperability of these options with other implementations. +- `tests/compat.sh` tests interoperability of every ciphersuite with other implementations. +- `tests/scripts/test-ref-configs.pl` test builds in various reduced configurations. +- `tests/scripts/key-exchanges.pl` test builds in configurations with a single key exchange enabled +- `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `config.h`, etc). + +Configurations +-------------- + +We provide some non-standard configurations focused on specific use cases in the `configs/` directory. You can read more about those in `configs/README.txt` + +Porting Mbed TLS +---------------- + +Mbed TLS can be ported to many different architectures, OS's and platforms. Before starting a port, you may find the following Knowledge Base articles useful: + +- [Porting Mbed TLS to a new environment or OS](https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS) +- [What external dependencies does Mbed TLS rely on?](https://tls.mbed.org/kb/development/what-external-dependencies-does-mbedtls-rely-on) +- [How do I configure Mbed TLS](https://tls.mbed.org/kb/compiling-and-building/how-do-i-configure-mbedtls) + +License +------- + +Unless specifically indicated otherwise in a file, Mbed TLS files are provided under the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) OR [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) licenses. A copy of these licenses can be found in [apache-2.0.txt](./apache-2.0.txt) and [gpl-2.0.txt](./gpl-2.0.txt). Contributors must accept that their contributions are made under both the Apache-2.0 AND GPL-2.0-or-later licenses. + +Contributing +------------ + +We gratefully accept bug reports and contributions from the community. Please see the [contributing guidelines](CONTRIBUTING.md) for details on how to do this. diff --git a/external/mbedtls/apache-2.0.txt b/external/mbedtls/apache-2.0.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/external/mbedtls/apache-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/external/mbedtls/configs/README.txt b/external/mbedtls/configs/README.txt new file mode 100644 index 0000000..933fa7f --- /dev/null +++ b/external/mbedtls/configs/README.txt @@ -0,0 +1,26 @@ +This directory contains example configuration files. + +The examples are generally focused on a particular usage case (eg, support for +a restricted number of ciphersuites) and aim at minimizing resource usage for +this target. They can be used as a basis for custom configurations. + +These files are complete replacements for the default config.h. To use one of +them, you can pick one of the following methods: + +1. Replace the default file include/mbedtls/config.h with the chosen one. + (Depending on your compiler, you may need to adjust the line with + #include "mbedtls/check_config.h" then.) + +2. Define MBEDTLS_CONFIG_FILE and adjust the include path accordingly. + For example, using make: + + CFLAGS="-I$PWD/configs -DMBEDTLS_CONFIG_FILE=''" make + + Or, using cmake: + + find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} + + CFLAGS="-I$PWD/configs -DMBEDTLS_CONFIG_FILE=''" cmake . + make + +Note that the second method also works if you want to keep your custom +configuration file outside the mbed TLS tree. diff --git a/external/mbedtls/configs/config-ccm-psk-tls1_2.h b/external/mbedtls/configs/config-ccm-psk-tls1_2.h new file mode 100644 index 0000000..f3929ae --- /dev/null +++ b/external/mbedtls/configs/config-ccm-psk-tls1_2.h @@ -0,0 +1,113 @@ +/** + * \file config-ccm-psk-tls1_2.h + * + * \brief Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites + * Distinguishing features: + * - no bignum, no PK, no X509 + * - fully modern and secure (provided the pre-shared keys have high entropy) + * - very low record overhead with CCM-8 + * - optimized for low RAM usage + * + * See README.txt for usage instructions. + */ +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +//#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */ +/* Other MBEDTLS_HAVE_XXX flags irrelevant for this configuration */ + +/* mbed TLS feature support */ +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_CCM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_MD_C +#define MBEDTLS_NET_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C + +/* Save RAM at the expense of ROM */ +#define MBEDTLS_AES_ROM_TABLES + +/* Save some RAM by adjusting to your exact needs */ +#define MBEDTLS_PSK_MAX_LEN 16 /* 128-bits keys are generally enough */ + +/* + * You should adjust this to the exact number of sources you're using: default + * is the "platform_entropy_poll" source, but you may want to add other ones + * Minimum is 2 for the entropy test suite. + */ +#define MBEDTLS_ENTROPY_MAX_SOURCES 2 + +/* + * Use only CCM_8 ciphersuites, and + * save ROM and a few bytes of RAM by specifying our own ciphersuite list + */ +#define MBEDTLS_SSL_CIPHERSUITES \ + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, \ + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 + +/* + * Save RAM at the expense of interoperability: do this only if you control + * both ends of the connection! (See comments in "mbedtls/ssl.h".) + * The optimal size here depends on the typical size of records. + */ +#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024 + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external/mbedtls/configs/config-mini-tls1_1.h b/external/mbedtls/configs/config-mini-tls1_1.h new file mode 100644 index 0000000..c235e3c --- /dev/null +++ b/external/mbedtls/configs/config-mini-tls1_1.h @@ -0,0 +1,103 @@ +/** + * \file config-mini-tls1_1.h + * + * \brief Minimal configuration for TLS 1.1 (RFC 4346) + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * Minimal configuration for TLS 1.1 (RFC 4346), implementing only the + * required ciphersuite: MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * + * See README.txt for usage instructions. + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +#define MBEDTLS_HAVE_ASM +#define MBEDTLS_HAVE_TIME + +/* mbed TLS feature support */ +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define MBEDTLS_SSL_PROTO_TLS1_1 + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_DES_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_MD_C +#define MBEDTLS_MD5_C +#define MBEDTLS_NET_C +#define MBEDTLS_OID_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_RSA_C +#define MBEDTLS_SHA1_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_USE_C + +/* For test certificates */ +#define MBEDTLS_BASE64_C +#define MBEDTLS_CERTS_C +#define MBEDTLS_PEM_PARSE_C + +/* For testing with compat.sh */ +#define MBEDTLS_FS_IO + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external/mbedtls/configs/config-no-entropy.h b/external/mbedtls/configs/config-no-entropy.h new file mode 100644 index 0000000..54e2f6c --- /dev/null +++ b/external/mbedtls/configs/config-no-entropy.h @@ -0,0 +1,117 @@ +/** + * \file config-no-entropy.h + * + * \brief Minimal configuration of features that do not require an entropy source + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * Minimal configuration of features that do not require an entropy source + * Distinguishing reatures: + * - no entropy module + * - no TLS protocol implementation available due to absence of an entropy + * source + * + * See README.txt for usage instructions. + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +#define MBEDTLS_HAVE_ASM +#define MBEDTLS_HAVE_TIME + +/* mbed TLS feature support */ +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_NIST_OPTIM +#define MBEDTLS_ECDSA_DETERMINISTIC +#define MBEDTLS_PK_RSA_ALT_SUPPORT +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_PKCS1_V21 +#define MBEDTLS_SELF_TEST +#define MBEDTLS_VERSION_FEATURES +#define MBEDTLS_X509_CHECK_KEY_USAGE +#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_BASE64_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CCM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ERROR_C +#define MBEDTLS_GCM_C +#define MBEDTLS_HMAC_DRBG_C +#define MBEDTLS_MD_C +#define MBEDTLS_OID_C +#define MBEDTLS_PEM_PARSE_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PK_WRITE_C +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_RSA_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA512_C +#define MBEDTLS_VERSION_C +#define MBEDTLS_X509_USE_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_CRL_PARSE_C +//#define MBEDTLS_CMAC_C + +/* Miscellaneous options */ +#define MBEDTLS_AES_ROM_TABLES + +#include "check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external/mbedtls/configs/config-suite-b.h b/external/mbedtls/configs/config-suite-b.h new file mode 100644 index 0000000..897c4d6 --- /dev/null +++ b/external/mbedtls/configs/config-suite-b.h @@ -0,0 +1,142 @@ +/** + * \file config-suite-b.h + * + * \brief Minimal configuration for TLS NSA Suite B Profile (RFC 6460) + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * Minimal configuration for TLS NSA Suite B Profile (RFC 6460) + * + * Distinguishing features: + * - no RSA or classic DH, fully based on ECC + * - optimized for low RAM usage + * + * Possible improvements: + * - if 128-bit security is enough, disable secp384r1 and SHA-512 + * - use embedded certs in DER format and disable PEM_PARSE_C and BASE64_C + * + * See README.txt for usage instructions. + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +#define MBEDTLS_HAVE_ASM +#define MBEDTLS_HAVE_TIME + +/* mbed TLS feature support */ +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_GCM_C +#define MBEDTLS_MD_C +#define MBEDTLS_NET_C +#define MBEDTLS_OID_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA512_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_USE_C + +/* For test certificates */ +#define MBEDTLS_BASE64_C +#define MBEDTLS_CERTS_C +#define MBEDTLS_PEM_PARSE_C + +/* Save RAM at the expense of ROM */ +#define MBEDTLS_AES_ROM_TABLES + +/* Save RAM by adjusting to our exact needs */ +#define MBEDTLS_ECP_MAX_BITS 384 +#define MBEDTLS_MPI_MAX_SIZE 48 // 384 bits is 48 bytes + +/* Save RAM at the expense of speed, see ecp.h */ +#define MBEDTLS_ECP_WINDOW_SIZE 2 +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 + +/* Significant speed benefit at the expense of some ROM */ +#define MBEDTLS_ECP_NIST_OPTIM + +/* + * You should adjust this to the exact number of sources you're using: default + * is the "mbedtls_platform_entropy_poll" source, but you may want to add other ones. + * Minimum is 2 for the entropy test suite. + */ +#define MBEDTLS_ENTROPY_MAX_SOURCES 2 + +/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */ +#define MBEDTLS_SSL_CIPHERSUITES \ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* + * Save RAM at the expense of interoperability: do this only if you control + * both ends of the connection! (See coments in "mbedtls/ssl.h".) + * The minimum size here depends on the certificate chain used as well as the + * typical size of records. + */ +#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024 + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external/mbedtls/configs/config-thread.h b/external/mbedtls/configs/config-thread.h new file mode 100644 index 0000000..4c18f6a --- /dev/null +++ b/external/mbedtls/configs/config-thread.h @@ -0,0 +1,119 @@ +/** + * \file config-thread.h + * + * \brief Minimal configuration for using TLS as part of Thread + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * Minimal configuration for using TLS a part of Thread + * http://threadgroup.org/ + * + * Distinguishing features: + * - no RSA or classic DH, fully based on ECC + * - no X.509 + * - support for experimental EC J-PAKE key exchange + * + * See README.txt for usage instructions. + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +#define MBEDTLS_HAVE_ASM + +/* mbed TLS feature support */ +#define MBEDTLS_AES_ROM_TABLES +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_NIST_OPTIM +#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#define MBEDTLS_SSL_PROTO_TLS1_2 +#define MBEDTLS_SSL_PROTO_DTLS +#define MBEDTLS_SSL_DTLS_ANTI_REPLAY +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY +#define MBEDTLS_SSL_EXPORT_KEYS + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CCM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_CMAC_C +#define MBEDTLS_ECJPAKE_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_HMAC_DRBG_C +#define MBEDTLS_MD_C +#define MBEDTLS_OID_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SSL_COOKIE_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C + +/* For tests using ssl-opt.sh */ +#define MBEDTLS_NET_C +#define MBEDTLS_TIMING_C + +/* Save RAM at the expense of ROM */ +#define MBEDTLS_AES_ROM_TABLES + +/* Save RAM by adjusting to our exact needs */ +#define MBEDTLS_ECP_MAX_BITS 256 +#define MBEDTLS_MPI_MAX_SIZE 32 // 256 bits is 32 bytes + +/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */ +#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external/mbedtls/dco.txt b/external/mbedtls/dco.txt new file mode 100644 index 0000000..8201f99 --- /dev/null +++ b/external/mbedtls/dco.txt @@ -0,0 +1,37 @@ +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +1 Letterman Drive +Suite D4700 +San Francisco, CA, 94129 + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. diff --git a/external/mbedtls/doxygen/input/doc_encdec.h b/external/mbedtls/doxygen/input/doc_encdec.h new file mode 100644 index 0000000..81b1b91 --- /dev/null +++ b/external/mbedtls/doxygen/input/doc_encdec.h @@ -0,0 +1,97 @@ +/** + * \file doc_encdec.h + * + * \brief Encryption/decryption module documentation file. + */ +/* + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/** + * @addtogroup encdec_module Encryption/decryption module + * + * The Encryption/decryption module provides encryption/decryption functions. + * One can differentiate between symmetric and asymmetric algorithms; the + * symmetric ones are mostly used for message confidentiality and the asymmetric + * ones for key exchange and message integrity. + * Some symmetric algorithms provide different block cipher modes, mainly + * Electronic Code Book (ECB) which is used for short (64-bit) messages and + * Cipher Block Chaining (CBC) which provides the structure needed for longer + * messages. In addition the Cipher Feedback Mode (CFB-128) stream cipher mode, + * Counter mode (CTR) and Galois Counter Mode (GCM) are implemented for + * specific algorithms. + * + * All symmetric encryption algorithms are accessible via the generic cipher layer + * (see \c mbedtls_cipher_setup()). + * + * The asymmetric encryptrion algorithms are accessible via the generic public + * key layer (see \c mbedtls_pk_init()). + * + * The following algorithms are provided: + * - Symmetric: + * - AES (see \c mbedtls_aes_crypt_ecb(), \c mbedtls_aes_crypt_cbc(), \c mbedtls_aes_crypt_cfb128() and + * \c mbedtls_aes_crypt_ctr()). + * - ARCFOUR (see \c mbedtls_arc4_crypt()). + * - Blowfish / BF (see \c mbedtls_blowfish_crypt_ecb(), \c mbedtls_blowfish_crypt_cbc(), + * \c mbedtls_blowfish_crypt_cfb64() and \c mbedtls_blowfish_crypt_ctr()) + * - Camellia (see \c mbedtls_camellia_crypt_ecb(), \c mbedtls_camellia_crypt_cbc(), + * \c mbedtls_camellia_crypt_cfb128() and \c mbedtls_camellia_crypt_ctr()). + * - DES/3DES (see \c mbedtls_des_crypt_ecb(), \c mbedtls_des_crypt_cbc(), \c mbedtls_des3_crypt_ecb() + * and \c mbedtls_des3_crypt_cbc()). + * - GCM (AES-GCM and CAMELLIA-GCM) (see \c mbedtls_gcm_init()) + * - XTEA (see \c mbedtls_xtea_crypt_ecb()). + * - Asymmetric: + * - Diffie-Hellman-Merkle (see \c mbedtls_dhm_read_public(), \c mbedtls_dhm_make_public() + * and \c mbedtls_dhm_calc_secret()). + * - RSA (see \c mbedtls_rsa_public() and \c mbedtls_rsa_private()). + * - Elliptic Curves over GF(p) (see \c mbedtls_ecp_point_init()). + * - Elliptic Curve Digital Signature Algorithm (ECDSA) (see \c mbedtls_ecdsa_init()). + * - Elliptic Curve Diffie Hellman (ECDH) (see \c mbedtls_ecdh_init()). + * + * This module provides encryption/decryption which can be used to provide + * secrecy. + * + * It also provides asymmetric key functions which can be used for + * confidentiality, integrity, authentication and non-repudiation. + */ diff --git a/external/mbedtls/doxygen/input/doc_hashing.h b/external/mbedtls/doxygen/input/doc_hashing.h new file mode 100644 index 0000000..7de2957 --- /dev/null +++ b/external/mbedtls/doxygen/input/doc_hashing.h @@ -0,0 +1,69 @@ +/** + * \file doc_hashing.h + * + * \brief Hashing module documentation file. + */ +/* + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/** + * @addtogroup hashing_module Hashing module + * + * The Message Digest (MD) or Hashing module provides one-way hashing + * functions. Such functions can be used for creating a hash message + * authentication code (HMAC) when sending a message. Such a HMAC can be used + * in combination with a private key for authentication, which is a message + * integrity control. + * + * All hash algorithms can be accessed via the generic MD layer (see + * \c mbedtls_md_setup()) + * + * The following hashing-algorithms are provided: + * - MD2, MD4, MD5 128-bit one-way hash functions by Ron Rivest. + * - SHA-1, SHA-256, SHA-384/512 160-bit or more one-way hash functions by + * NIST and NSA. + * + * This module provides one-way hashing which can be used for authentication. + */ diff --git a/external/mbedtls/doxygen/input/doc_mainpage.h b/external/mbedtls/doxygen/input/doc_mainpage.h new file mode 100644 index 0000000..e640c7b --- /dev/null +++ b/external/mbedtls/doxygen/input/doc_mainpage.h @@ -0,0 +1,121 @@ +/** + * \file doc_mainpage.h + * + * \brief Main page documentation file. + */ +/* + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/** + * @mainpage mbed TLS v2.16.10 source code documentation + * + * This documentation describes the internal structure of mbed TLS. It was + * automatically generated from specially formatted comment blocks in + * mbed TLS's source code using Doxygen. (See + * http://www.stack.nl/~dimitri/doxygen/ for more information on Doxygen) + * + * mbed TLS has a simple setup: it provides the ingredients for an SSL/TLS + * implementation. These ingredients are listed as modules in the + * \ref mainpage_modules "Modules section". This "Modules section" introduces + * the high-level module concepts used throughout this documentation.\n + * Some examples of mbed TLS usage can be found in the \ref mainpage_examples + * "Examples section". + * + * @section mainpage_modules Modules + * + * mbed TLS supports SSLv3 up to TLSv1.2 communication by providing the + * following: + * - TCP/IP communication functions: listen, connect, accept, read/write. + * - SSL/TLS communication functions: init, handshake, read/write. + * - X.509 functions: CRT, CRL and key handling + * - Random number generation + * - Hashing + * - Encryption/decryption + * + * Above functions are split up neatly into logical interfaces. These can be + * used separately to provide any of the above functions or to mix-and-match + * into an SSL server/client solution that utilises a X.509 PKI. Examples of + * such implementations are amply provided with the source code. + * + * Note that mbed TLS does not provide a control channel or (multiple) session + * handling without additional work from the developer. + * + * @section mainpage_examples Examples + * + * Example server setup: + * + * \b Prerequisites: + * - X.509 certificate and private key + * - session handling functions + * + * \b Setup: + * - Load your certificate and your private RSA key (X.509 interface) + * - Setup the listening TCP socket (TCP/IP interface) + * - Accept incoming client connection (TCP/IP interface) + * - Initialise as an SSL-server (SSL/TLS interface) + * - Set parameters, e.g. authentication, ciphers, CA-chain, key exchange + * - Set callback functions RNG, IO, session handling + * - Perform an SSL-handshake (SSL/TLS interface) + * - Read/write data (SSL/TLS interface) + * - Close and cleanup (all interfaces) + * + * Example client setup: + * + * \b Prerequisites: + * - X.509 certificate and private key + * - X.509 trusted CA certificates + * + * \b Setup: + * - Load the trusted CA certificates (X.509 interface) + * - Load your certificate and your private RSA key (X.509 interface) + * - Setup a TCP/IP connection (TCP/IP interface) + * - Initialise as an SSL-client (SSL/TLS interface) + * - Set parameters, e.g. authentication mode, ciphers, CA-chain, session + * - Set callback functions RNG, IO + * - Perform an SSL-handshake (SSL/TLS interface) + * - Verify the server certificate (SSL/TLS interface) + * - Write/read data (SSL/TLS interface) + * - Close and cleanup (all interfaces) + */ diff --git a/external/mbedtls/doxygen/input/doc_rng.h b/external/mbedtls/doxygen/input/doc_rng.h new file mode 100644 index 0000000..44c4204 --- /dev/null +++ b/external/mbedtls/doxygen/input/doc_rng.h @@ -0,0 +1,71 @@ +/** + * \file doc_rng.h + * + * \brief Random number generator (RNG) module documentation file. + */ +/* + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/** + * @addtogroup rng_module Random number generator (RNG) module + * + * The Random number generator (RNG) module provides random number + * generation, see \c mbedtls_ctr_drbg_random(). + * + * The block-cipher counter-mode based deterministic random + * bit generator (CTR_DBRG) as specified in NIST SP800-90. It needs an external + * source of entropy. For these purposes \c mbedtls_entropy_func() can be used. + * This is an implementation based on a simple entropy accumulator design. + * + * The other number generator that is included is less strong and uses the + * HAVEGE (HArdware Volatile Entropy Gathering and Expansion) software heuristic + * which considered unsafe for primary usage, but provides additional random + * to the entropy pool if enables. + * + * Meaning that there seems to be no practical algorithm that can guess + * the next bit with a probability larger than 1/2 in an output sequence. + * + * This module can be used to generate random numbers. + */ diff --git a/external/mbedtls/doxygen/input/doc_ssltls.h b/external/mbedtls/doxygen/input/doc_ssltls.h new file mode 100644 index 0000000..1db44c2 --- /dev/null +++ b/external/mbedtls/doxygen/input/doc_ssltls.h @@ -0,0 +1,76 @@ +/** + * \file doc_ssltls.h + * + * \brief SSL/TLS communication module documentation file. + */ +/* + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/** + * @addtogroup ssltls_communication_module SSL/TLS communication module + * + * The SSL/TLS communication module provides the means to create an SSL/TLS + * communication channel. + * + * The basic provisions are: + * - initialise an SSL/TLS context (see \c mbedtls_ssl_init()). + * - perform an SSL/TLS handshake (see \c mbedtls_ssl_handshake()). + * - read/write (see \c mbedtls_ssl_read() and \c mbedtls_ssl_write()). + * - notify a peer that connection is being closed (see \c mbedtls_ssl_close_notify()). + * + * Many aspects of such a channel are set through parameters and callback + * functions: + * - the endpoint role: client or server. + * - the authentication mode. Should verification take place. + * - the Host-to-host communication channel. A TCP/IP module is provided. + * - the random number generator (RNG). + * - the ciphers to use for encryption/decryption. + * - session control functions. + * - X.509 parameters for certificate-handling and key exchange. + * + * This module can be used to create an SSL/TLS server and client and to provide a basic + * framework to setup and communicate through an SSL/TLS communication channel.\n + * Note that you need to provide for several aspects yourself as mentioned above. + */ diff --git a/external/mbedtls/doxygen/input/doc_tcpip.h b/external/mbedtls/doxygen/input/doc_tcpip.h new file mode 100644 index 0000000..a089601 --- /dev/null +++ b/external/mbedtls/doxygen/input/doc_tcpip.h @@ -0,0 +1,71 @@ +/** + * \file doc_tcpip.h + * + * \brief TCP/IP communication module documentation file. + */ +/* + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/** + * @addtogroup tcpip_communication_module TCP/IP communication module + * + * The TCP/IP communication module provides for a channel of + * communication for the \link ssltls_communication_module SSL/TLS communication + * module\endlink to use. + * In the TCP/IP-model it provides for communication up to the Transport + * (or Host-to-host) layer. + * SSL/TLS resides on top of that, in the Application layer, and makes use of + * its basic provisions: + * - listening on a port (see \c mbedtls_net_bind()). + * - accepting a connection (through \c mbedtls_net_accept()). + * - read/write (through \c mbedtls_net_recv()/\c mbedtls_net_send()). + * - close a connection (through \c mbedtls_net_close()). + * + * This way you have the means to, for example, implement and use an UDP or + * IPSec communication solution as a basis. + * + * This module can be used at server- and clientside to provide a basic + * means of communication over the internet. + */ diff --git a/external/mbedtls/doxygen/input/doc_x509.h b/external/mbedtls/doxygen/input/doc_x509.h new file mode 100644 index 0000000..1f9f8e0 --- /dev/null +++ b/external/mbedtls/doxygen/input/doc_x509.h @@ -0,0 +1,70 @@ +/** + * \file doc_x509.h + * + * \brief X.509 module documentation file. + */ +/* + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/** + * @addtogroup x509_module X.509 module + * + * The X.509 module provides X.509 support for reading, writing and verification + * of certificates. + * In summary: + * - X.509 certificate (CRT) reading (see \c mbedtls_x509_crt_parse(), + * \c mbedtls_x509_crt_parse_der(), \c mbedtls_x509_crt_parse_file()). + * - X.509 certificate revocation list (CRL) reading (see + * \c mbedtls_x509_crl_parse(), \c mbedtls_x509_crl_parse_der(), + * and \c mbedtls_x509_crl_parse_file()). + * - X.509 certificate signature verification (see \c + * mbedtls_x509_crt_verify() and \c mbedtls_x509_crt_verify_with_profile(). + * - X.509 certificate writing and certificate request writing (see + * \c mbedtls_x509write_crt_der() and \c mbedtls_x509write_csr_der()). + * + * This module can be used to build a certificate authority (CA) chain and + * verify its signature. It is also used to generate Certificate Signing + * Requests and X.509 certificates just as a CA would do. + */ diff --git a/external/mbedtls/doxygen/mbedtls.doxyfile b/external/mbedtls/doxygen/mbedtls.doxyfile new file mode 100644 index 0000000..61a42c4 --- /dev/null +++ b/external/mbedtls/doxygen/mbedtls.doxyfile @@ -0,0 +1,1911 @@ +# Doxyfile 1.8.4 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed +# in front of the TAG it is preceding . +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = "mbed TLS v2.16.10" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ../apidoc/ + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian, +# Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, +# Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. Note that you specify absolute paths here, but also +# relative paths, which will be relative from the directory where doxygen is +# started. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, +# and language is one of the parsers supported by doxygen: IDL, Java, +# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, +# C++. For instance to make doxygen treat .inc files as Fortran files (default +# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note +# that for custom extensions you also need to set FILE_PATTERNS otherwise the +# files are not read by doxygen. + +EXTENSION_MAPPING = + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES (the +# default) will make doxygen replace the get and set methods by a property in +# the documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields or simple typedef fields will be shown +# inline in the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO (the default), structs, classes, and unions are shown on a separate +# page (for HTML and Man pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can +# be an expensive process and often the same symbol appear multiple times in +# the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too +# small doxygen will become slower. If the cache is too large, memory is wasted. +# The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid +# range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536 +# symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = YES + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if section-label ... \endif +# and \cond section-label ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. Do not use +# file names with spaces, bibtex cannot handle them. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../include input + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = YES + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = *_internal.h *_wrap.h + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be ignored. +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C, C++ and Fortran comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = . + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If left blank doxygen will +# generate a default style sheet. Note that it is recommended to use +# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this +# tag will in the future become obsolete. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional +# user-defined cascading style sheet that is included after the standard +# style sheets created by doxygen. Using this option one can overrule +# certain style aspects. This is preferred over using HTML_STYLESHEET +# since it does not replace the standard style sheet and is therefor more +# robust against future updates. Doxygen will copy the style sheet file to +# the output directory. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of +# entries shown in the various tree structured indices initially; the user +# can expand and collapse entries dynamically later on. Doxygen will expand +# the tree to such a level that at most the specified number of entries are +# visible (unless a fully collapsed tree already exceeds this amount). +# So setting the number of entries 1 will produce a full collapsed tree by +# default. 0 is a special value representing an infinite number of entries +# and will result in a full expanded tree by default. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely +# identify the documentation publisher. This should be a reverse domain-name +# style string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and +# SVG. The default value is HTML-CSS, which is slower, but has the best +# compatibility. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript +# pieces of code that will be used on startup of the MathJax code. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a web server instead of a web client using Javascript. +# There are two flavours of web server based search depending on the +# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for +# searching and an index file used by the script. When EXTERNAL_SEARCH is +# enabled the indexing and searching needs to be provided by external tools. +# See the manual for details. + +SERVER_BASED_SEARCH = NO + +# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain +# the search results. Doxygen ships with an example indexer (doxyindexer) and +# search engine (doxysearch.cgi) which are based on the open source search +# engine library Xapian. See the manual for configuration details. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will returned the search results when EXTERNAL_SEARCH is enabled. +# Doxygen ships with an example search engine (doxysearch) which is based on +# the open source search engine library Xapian. See the manual for configuration +# details. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. + +EXTERNAL_SEARCH_ID = + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id +# of to a relative location where the documentation can be found. +# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ... + +EXTRA_SEARCH_MAPPINGS = + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = YES + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4 will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images +# or other source files which should be copied to the LaTeX output directory. +# Note that the files will be copied as-is; there are no commands or markers +# available. + +LATEX_EXTRA_FILES = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +#XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +#XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- + +# If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files +# that can be used to generate PDF. + +GENERATE_DOCBOOK = NO + +# The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in +# front of it. If left blank docbook will be used as the default path. + +DOCBOOK_OUTPUT = docbook + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = WIN32 \ + NTLM \ + USE_LZO \ + ENABLE_FRAGMENT \ + P2MP \ + P2MP_SERVER \ + USE_CRYPTO \ + USE_SSL \ + ENABLE_PLUGIN \ + ENABLE_MANAGEMENT \ + ENABLE_OCC \ + HAVE_GETTIMEOFDAY + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed +# in the related pages index. If set to NO, only the current project's +# pages will be listed. + +EXTERNAL_PAGES = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# manageable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 200 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 1000 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/external/mbedtls/gpl-2.0.txt b/external/mbedtls/gpl-2.0.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/external/mbedtls/gpl-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/external/mbedtls/include/CMakeLists.txt b/external/mbedtls/include/CMakeLists.txt new file mode 100644 index 0000000..c2f2bd4 --- /dev/null +++ b/external/mbedtls/include/CMakeLists.txt @@ -0,0 +1,16 @@ +option(INSTALL_MBEDTLS_HEADERS "Install mbed TLS headers." ON) + +if(INSTALL_MBEDTLS_HEADERS) + + file(GLOB headers "mbedtls/*.h") + + install(FILES ${headers} + DESTINATION include/mbedtls + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) + +endif(INSTALL_MBEDTLS_HEADERS) + +# Make config.h available in an out-of-source build. ssl-opt.sh requires it. +if (ENABLE_TESTING AND NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) + link_to_source(mbedtls) +endif() diff --git a/external/mbedtls/include/mbedtls/aes.h b/external/mbedtls/include/mbedtls/aes.h new file mode 100644 index 0000000..4468b66 --- /dev/null +++ b/external/mbedtls/include/mbedtls/aes.h @@ -0,0 +1,700 @@ +/** + * \file aes.h + * + * \brief This file contains AES definitions and functions. + * + * The Advanced Encryption Standard (AES) specifies a FIPS-approved + * cryptographic algorithm that can be used to protect electronic + * data. + * + * The AES algorithm is a symmetric block cipher that can + * encrypt and decrypt information. For more information, see + * FIPS Publication 197: Advanced Encryption Standard and + * ISO/IEC 18033-2:2006: Information technology -- Security + * techniques -- Encryption algorithms -- Part 2: Asymmetric + * ciphers. + * + * The AES-XTS block mode is standardized by NIST SP 800-38E + * + * and described in detail by IEEE P1619 + * . + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_AES_H +#define MBEDTLS_AES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* padlock.c and aesni.c rely on these values! */ +#define MBEDTLS_AES_ENCRYPT 1 /**< AES encryption. */ +#define MBEDTLS_AES_DECRYPT 0 /**< AES decryption. */ + +/* Error codes in range 0x0020-0x0022 */ +#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +/* Error codes in range 0x0021-0x0025 */ +#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */ + +/* MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */ +#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ + +/* MBEDTLS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_AES_ALT) +// Regular implementation +// + +/** + * \brief The AES context-type definition. + */ +typedef struct mbedtls_aes_context +{ + int nr; /*!< The number of rounds. */ + uint32_t *rk; /*!< AES round keys. */ + uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can + hold 32 extra Bytes, which can be used for + one of the following purposes: +
  • Alignment if VIA padlock is + used.
  • +
  • Simplifying key expansion in the 256-bit + case by generating an extra round key. +
*/ +} +mbedtls_aes_context; + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief The AES XTS context-type definition. + */ +typedef struct mbedtls_aes_xts_context +{ + mbedtls_aes_context crypt; /*!< The AES context to use for AES block + encryption or decryption. */ + mbedtls_aes_context tweak; /*!< The AES context used for tweak + computation. */ +} mbedtls_aes_xts_context; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#else /* MBEDTLS_AES_ALT */ +#include "aes_alt.h" +#endif /* MBEDTLS_AES_ALT */ + +/** + * \brief This function initializes the specified AES context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES context to initialize. This must not be \c NULL. + */ +void mbedtls_aes_init( mbedtls_aes_context *ctx ); + +/** + * \brief This function releases and clears the specified AES context. + * + * \param ctx The AES context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. + */ +void mbedtls_aes_free( mbedtls_aes_context *ctx ); + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function initializes the specified AES XTS context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES XTS context to initialize. This must not be \c NULL. + */ +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ); + +/** + * \brief This function releases and clears the specified AES XTS context. + * + * \param ctx The AES XTS context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. + */ +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function sets the encryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function prepares an XTS context for encryption and + * sets the encryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function prepares an XTS context for decryption and + * sets the decryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function performs an AES single-block encryption or + * decryption operation. + * + * It performs the operation defined in the \p mode parameter + * (encrypt or decrypt), on the input data buffer defined in + * the \p input parameter. + * + * mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or + * mbedtls_aes_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param input The buffer holding the input data. + * It must be readable and at least \c 16 Bytes long. + * \param output The buffer where the output data will be written. + * It must be writeable and at least \c 16 Bytes long. + + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an AES-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aes_init(), and either + * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on full blocks, that is, the input size + * must be a multiple of the AES block size of \c 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (\c 16 Bytes). + * \param iv Initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH + * on failure. + */ +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function performs an AES-XTS encryption or decryption + * operation for an entire XTS data unit. + * + * AES-XTS encrypts or decrypts blocks based on their location as + * defined by a data unit number. The data unit number must be + * provided by \p data_unit. + * + * NIST SP 800-38E limits the maximum size of a data unit to 2^20 + * AES blocks. If the data unit is larger than this, this function + * returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH. + * + * \param ctx The AES XTS context to use for AES XTS operations. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of a data unit in Bytes. This can be any + * length between 16 bytes and 2^24 bytes inclusive + * (between 1 and 2^20 block cipher blocks). + * \param data_unit The address of the data unit encoded as an array of 16 + * bytes in little-endian format. For disk encryption, this + * is typically the index of the block device sector that + * contains the data. + * \param input The buffer holding the input data (which is an entire + * data unit). This function reads \p length Bytes from \p + * input. + * \param output The buffer holding the output data (which is an entire + * data unit). This function writes \p length Bytes to \p + * output. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is + * smaller than an AES block in size (16 Bytes) or if \p + * length is larger than 2^20 blocks (16 MiB). + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an AES-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aes_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an AES-CFB8 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined + * in the \p input parameter. + * + * Due to the nature of CFB, you must use the same key schedule for + * both encryption and decryption operations. Therefore, you must + * use the context initialized with mbedtls_aes_setkey_enc() for + * both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT + * \param length The length of the input data. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/** + * \brief This function performs an AES-OFB (Output Feedback Mode) + * encryption or decryption operation. + * + * For OFB, you must set up the context with + * mbedtls_aes_setkey_enc(), regardless of whether you are + * performing an encryption or decryption operation. This is + * because OFB mode uses the same key schedule for encryption and + * decryption. + * + * The OFB operation is identical for encryption or decryption, + * therefore no operation mode needs to be specified. + * + * \note Upon exit, the content of iv, the Initialisation Vector, is + * updated so that you can call the same function again on the next + * block(s) of data and get the same result as if it was encrypted + * in one call. This allows a "streaming" usage, by initialising + * iv_off to 0 before the first call, and preserving its value + * between calls. + * + * For non-streaming use, the iv should be initialised on each call + * to a unique value, and iv_off set to 0 on each call. + * + * If you need to retain the contents of the initialisation vector, + * you must either save it manually or use the cipher module + * instead. + * + * \warning For the OFB mode, the initialisation vector must be unique + * every encryption operation. Reuse of an initialisation vector + * will compromise security. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an AES-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aes_setkey_enc() + * for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that an AES block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param nc_off The offset in the current \p stream_block, for + * resuming within the current cipher stream. The + * offset pointer should be 0 at the start of a stream. + * It must point to a valid \c size_t. + * \param nonce_counter The 128-bit nonce and counter. + * It must be a readable-writeable buffer of \c 16 Bytes. + * \param stream_block The saved stream block for resuming. This is + * overwritten by the function. + * It must be a readable-writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/** + * \brief Internal AES block encryption function. This is only + * exposed to allow overriding it using + * \c MBEDTLS_AES_ENCRYPT_ALT. + * + * \param ctx The AES context to use for encryption. + * \param input The plaintext block. + * \param output The output (ciphertext) block. + * + * \return \c 0 on success. + */ +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal AES block decryption function. This is only + * exposed to allow overriding it using see + * \c MBEDTLS_AES_DECRYPT_ALT. + * + * \param ctx The AES context to use for decryption. + * \param input The ciphertext block. + * \param output The output (plaintext) block. + * + * \return \c 0 on success. + */ +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Deprecated internal AES block encryption function + * without return value. + * + * \deprecated Superseded by mbedtls_internal_aes_encrypt() + * + * \param ctx The AES context to use for encryption. + * \param input Plaintext block. + * \param output Output (ciphertext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Deprecated internal AES block decryption function + * without return value. + * + * \deprecated Superseded by mbedtls_internal_aes_decrypt() + * + * \param ctx The AES context to use for decryption. + * \param input Ciphertext block. + * \param output Output (plaintext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_aes_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ diff --git a/external/mbedtls/include/mbedtls/aesni.h b/external/mbedtls/include/mbedtls/aesni.h new file mode 100644 index 0000000..9b63a00 --- /dev/null +++ b/external/mbedtls/include/mbedtls/aesni.h @@ -0,0 +1,163 @@ +/** + * \file aesni.h + * + * \brief AES-NI for hardware AES acceleration on some Intel processors + * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_AESNI_H +#define MBEDTLS_AESNI_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "aes.h" + +#define MBEDTLS_AESNI_AES 0x02000000u +#define MBEDTLS_AESNI_CLMUL 0x00000002u + +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ + ( defined(__amd64__) || defined(__x86_64__) ) && \ + ! defined(MBEDTLS_HAVE_X86_64) +#define MBEDTLS_HAVE_X86_64 +#endif + +#if defined(MBEDTLS_HAVE_X86_64) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal function to detect the AES-NI feature in CPUs. + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param what The feature to detect + * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL) + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_aesni_has_support( unsigned int what ); + +/** + * \brief Internal AES-NI AES-ECB block encryption and decryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 on success (cannot fail) + */ +int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal GCM multiplication: c = a * b in GF(2^128) + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param c Result + * \param a First operand + * \param b Second operand + * + * \note Both operands and result are bit strings interpreted as + * elements of GF(2^128) as per the GCM spec. + */ +void mbedtls_aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ); + +/** + * \brief Internal round key inversion. This function computes + * decryption round keys from the encryption round keys. + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param invkey Round keys for the equivalent inverse cipher + * \param fwdkey Original round keys (for encryption) + * \param nr Number of rounds (that is, number of round keys minus one) + */ +void mbedtls_aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, + int nr ); + +/** + * \brief Internal key expansion for encryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param rk Destination buffer where the round keys are written + * \param key Encryption key + * \param bits Key size in bits (must be 128, 192 or 256) + * + * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + */ +int mbedtls_aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_HAVE_X86_64 */ + +#endif /* MBEDTLS_AESNI_H */ diff --git a/external/mbedtls/include/mbedtls/arc4.h b/external/mbedtls/include/mbedtls/arc4.h new file mode 100644 index 0000000..6334a9c --- /dev/null +++ b/external/mbedtls/include/mbedtls/arc4.h @@ -0,0 +1,171 @@ +/** + * \file arc4.h + * + * \brief The ARCFOUR stream cipher + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * + */ +#ifndef MBEDTLS_ARC4_H +#define MBEDTLS_ARC4_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/* MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_ARC4_ALT) +// Regular implementation +// + +/** + * \brief ARC4 context structure + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + * + */ +typedef struct mbedtls_arc4_context +{ + int x; /*!< permutation index */ + int y; /*!< permutation index */ + unsigned char m[256]; /*!< permutation table */ +} +mbedtls_arc4_context; + +#else /* MBEDTLS_ARC4_ALT */ +#include "arc4_alt.h" +#endif /* MBEDTLS_ARC4_ALT */ + +/** + * \brief Initialize ARC4 context + * + * \param ctx ARC4 context to be initialized + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ); + +/** + * \brief Clear ARC4 context + * + * \param ctx ARC4 context to be cleared + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_free( mbedtls_arc4_context *ctx ); + +/** + * \brief ARC4 key schedule + * + * \param ctx ARC4 context to be setup + * \param key the secret key + * \param keylen length of the key, in bytes + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, + unsigned int keylen ); + +/** + * \brief ARC4 cipher function + * + * \param ctx ARC4 context + * \param length length of the input data + * \param input buffer holding the input data + * \param output buffer for the output data + * + * \return 0 if successful + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* arc4.h */ diff --git a/external/mbedtls/include/mbedtls/aria.h b/external/mbedtls/include/mbedtls/aria.h new file mode 100644 index 0000000..13763d4 --- /dev/null +++ b/external/mbedtls/include/mbedtls/aria.h @@ -0,0 +1,396 @@ +/** + * \file aria.h + * + * \brief ARIA block cipher + * + * The ARIA algorithm is a symmetric block cipher that can encrypt and + * decrypt information. It is defined by the Korean Agency for + * Technology and Standards (KATS) in KS X 1213:2004 (in + * Korean, but see http://210.104.33.10/ARIA/index-e.html in English) + * and also described by the IETF in RFC 5794. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_ARIA_H +#define MBEDTLS_ARIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#include "platform_util.h" + +#define MBEDTLS_ARIA_ENCRYPT 1 /**< ARIA encryption. */ +#define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */ + +#define MBEDTLS_ARIA_BLOCKSIZE 16 /**< ARIA block size in bytes. */ +#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maxiumum number of rounds in ARIA. */ +#define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x005C ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C /**< Bad input data. */ + +#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E /**< Invalid data input length. */ + +/* MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE is deprecated and should not be used. + */ +#define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE -0x005A /**< Feature not available. For example, an unsupported ARIA key size. */ + +/* MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED -0x0058 /**< ARIA hardware accelerator failed. */ + +#if !defined(MBEDTLS_ARIA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The ARIA context-type definition. + */ +typedef struct mbedtls_aria_context +{ + unsigned char nr; /*!< The number of rounds (12, 14 or 16) */ + /*! The ARIA round keys. */ + uint32_t rk[MBEDTLS_ARIA_MAX_ROUNDS + 1][MBEDTLS_ARIA_BLOCKSIZE / 4]; +} +mbedtls_aria_context; + +#else /* MBEDTLS_ARIA_ALT */ +#include "aria_alt.h" +#endif /* MBEDTLS_ARIA_ALT */ + +/** + * \brief This function initializes the specified ARIA context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The ARIA context to initialize. This must not be \c NULL. + */ +void mbedtls_aria_init( mbedtls_aria_context *ctx ); + +/** + * \brief This function releases and clears the specified ARIA context. + * + * \param ctx The ARIA context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized ARIA context. + */ +void mbedtls_aria_free( mbedtls_aria_context *ctx ); + +/** + * \brief This function sets the encryption key. + * + * \param ctx The ARIA context to which the key should be bound. + * This must be initialized. + * \param key The encryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The size of \p key in Bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The ARIA context to which the key should be bound. + * This must be initialized. + * \param key The decryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs an ARIA single-block encryption or + * decryption operation. + * + * It performs encryption or decryption (depending on whether + * the key was set for encryption on decryption) on the input + * data buffer defined in the \p input parameter. + * + * mbedtls_aria_init(), and either mbedtls_aria_setkey_enc() or + * mbedtls_aria_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param input The 16-Byte buffer holding the input data. + * \param output The 16-Byte buffer holding the output data. + + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, + const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an ARIA-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aria_init(), and either + * mbedtls_aria_setkey_enc() or mbedtls_aria_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on aligned blocks, that is, the input size + * must be a multiple of the ARIA block size of 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_ARIA_ENCRYPT for encryption, or + * #MBEDTLS_ARIA_DECRYPT for decryption. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (16 Bytes). + * \param iv Initialization vector (updated after use). + * This must be a readable buffer of size 16 Bytes. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an ARIA-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aria_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_ARIA_ENCRYPT for encryption, or + * #MBEDTLS_ARIA_DECRYPT for decryption. + * \param length The length of the input data \p input in Bytes. + * \param iv_off The offset in IV (updated after use). + * This must not be larger than 15. + * \param iv The initialization vector (updated after use). + * This must be a readable buffer of size 16 Bytes. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an ARIA-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aria_setkey_enc() + * for both #MBEDTLS_ARIA_ENCRYPT and #MBEDTLS_ARIA_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that an ARIA block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param length The length of the input data \p input in Bytes. + * \param nc_off The offset in Bytes in the current \p stream_block, + * for resuming within the current cipher stream. The + * offset pointer should be \c 0 at the start of a + * stream. This must not be larger than \c 15 Bytes. + * \param nonce_counter The 128-bit nonce and counter. This must point to + * a read/write buffer of length \c 16 bytes. + * \param stream_block The saved stream block for resuming. This must + * point to a read/write buffer of length \c 16 bytes. + * This is overwritten by the function. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_aria_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* aria.h */ diff --git a/external/mbedtls/include/mbedtls/asn1.h b/external/mbedtls/include/mbedtls/asn1.h new file mode 100644 index 0000000..0e596bc --- /dev/null +++ b/external/mbedtls/include/mbedtls/asn1.h @@ -0,0 +1,383 @@ +/** + * \file asn1.h + * + * \brief Generic ASN.1 parsing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_ASN1_H +#define MBEDTLS_ASN1_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "bignum.h" +#endif + +/** + * \addtogroup asn1_module + * \{ + */ + +/** + * \name ASN1 Error codes + * These error codes are OR'ed to X509 error codes for + * higher error granularity. + * ASN1 is a standard to specify data structures. + * \{ + */ +#define MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */ +#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */ +#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */ +#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */ +#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */ +#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /**< Memory allocation failed */ +#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */ + +/* \} name */ + +/** + * \name DER constants + * These constants comply with the DER encoded ASN.1 type tags. + * DER encoding uses hexadecimal representation. + * An example DER sequence is:\n + * - 0x02 -- tag indicating INTEGER + * - 0x01 -- length in octets + * - 0x05 -- value + * Such sequences are typically read into \c ::mbedtls_x509_buf. + * \{ + */ +#define MBEDTLS_ASN1_BOOLEAN 0x01 +#define MBEDTLS_ASN1_INTEGER 0x02 +#define MBEDTLS_ASN1_BIT_STRING 0x03 +#define MBEDTLS_ASN1_OCTET_STRING 0x04 +#define MBEDTLS_ASN1_NULL 0x05 +#define MBEDTLS_ASN1_OID 0x06 +#define MBEDTLS_ASN1_UTF8_STRING 0x0C +#define MBEDTLS_ASN1_SEQUENCE 0x10 +#define MBEDTLS_ASN1_SET 0x11 +#define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 +#define MBEDTLS_ASN1_T61_STRING 0x14 +#define MBEDTLS_ASN1_IA5_STRING 0x16 +#define MBEDTLS_ASN1_UTC_TIME 0x17 +#define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 +#define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C +#define MBEDTLS_ASN1_BMP_STRING 0x1E +#define MBEDTLS_ASN1_PRIMITIVE 0x00 +#define MBEDTLS_ASN1_CONSTRUCTED 0x20 +#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 + +/* + * Bit masks for each of the components of an ASN.1 tag as specified in + * ITU X.690 (08/2015), section 8.1 "General rules for encoding", + * paragraph 8.1.2.2: + * + * Bit 8 7 6 5 1 + * +-------+-----+------------+ + * | Class | P/C | Tag number | + * +-------+-----+------------+ + */ +#define MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0 +#define MBEDTLS_ASN1_TAG_PC_MASK 0x20 +#define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F + +/* \} name */ +/* \} addtogroup asn1_module */ + +/** Returns the size of the binary string, without the trailing \\0 */ +#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) + +/** + * Compares an mbedtls_asn1_buf structure to a reference OID. + * + * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a + * 'unsigned char *oid' here! + */ +#define MBEDTLS_OID_CMP(oid_str, oid_buf) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ + memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Functions to parse ASN.1 data structures + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef struct mbedtls_asn1_buf +{ + int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ + size_t len; /**< ASN1 length, in octets. */ + unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ +} +mbedtls_asn1_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef struct mbedtls_asn1_bitstring +{ + size_t len; /**< ASN1 length, in octets. */ + unsigned char unused_bits; /**< Number of unused bits at the end of the string */ + unsigned char *p; /**< Raw ASN1 data for the bit string */ +} +mbedtls_asn1_bitstring; + +/** + * Container for a sequence of ASN.1 items + */ +typedef struct mbedtls_asn1_sequence +{ + mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ + struct mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */ +} +mbedtls_asn1_sequence; + +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +typedef struct mbedtls_asn1_named_data +{ + mbedtls_asn1_buf oid; /**< The object identifier. */ + mbedtls_asn1_buf val; /**< The named value. */ + struct mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */ + unsigned char next_merged; /**< Merge next item into the current one? */ +} +mbedtls_asn1_named_data; + +/** + * \brief Get the length of an ASN.1 element. + * Updates the pointer to immediately behind the length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the value + * + * \return 0 if successful, MBEDTLS_ERR_ASN1_OUT_OF_DATA on reaching + * end of data, MBEDTLS_ERR_ASN1_INVALID_LENGTH if length is + * unparseable. + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Get the tag and length of the tag. Check for the requested tag. + * Updates the pointer to immediately behind the tag and length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the length + * \param tag The expected tag + * + * \return 0 if successful, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if tag did + * not match requested tag, or another specific ASN.1 error code. + */ +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ); + +/** + * \brief Retrieve a boolean ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve a bitstring ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param bs The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs); + +/** + * \brief Retrieve a bitstring ASN.1 tag without unused bits and its + * value. + * Updates the pointer to the beginning of the bit/octet string. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len Length of the actual bit/octect string in bytes + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ); + +/** + * \brief Parses and splits an ASN.1 "SEQUENCE OF " + * Updated the pointer to immediately behind the full sequence tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param cur First variable in the chain to fill + * \param tag Type of sequence + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Retrieve a MPI value from an integer ASN.1 tag. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param X The MPI that will receive the value + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * \param params The buffer to receive the params (if any) + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ); + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no + * params. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ); + +/** + * \brief Find a specific named_data entry in a sequence or list based on + * the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \return NULL if not found, or a pointer to the existing entry. + */ +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ); + +/** + * \brief Free a mbedtls_asn1_named_data entry + * + * \param entry The named data entry to free + */ +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); + +/** + * \brief Free all entries in a mbedtls_asn1_named_data list + * Head will be set to NULL + * + * \param head Pointer to the head of the list of named data entries to free + */ +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); + +#ifdef __cplusplus +} +#endif + +#endif /* asn1.h */ diff --git a/external/mbedtls/include/mbedtls/asn1write.h b/external/mbedtls/include/mbedtls/asn1write.h new file mode 100644 index 0000000..3c7cdd6 --- /dev/null +++ b/external/mbedtls/include/mbedtls/asn1write.h @@ -0,0 +1,354 @@ +/** + * \file asn1write.h + * + * \brief ASN.1 buffer writing functionality + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_ASN1_WRITE_H +#define MBEDTLS_ASN1_WRITE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "asn1.h" + +#define MBEDTLS_ASN1_CHK_ADD(g, f) \ + do \ + { \ + if( ( ret = (f) ) < 0 ) \ + return( ret ); \ + else \ + (g) += ret; \ + } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Write a length field in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param len The length value to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, + size_t len ); +/** + * \brief Write an ASN.1 tag in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param tag The tag to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, + unsigned char tag ); + +/** + * \brief Write raw buffer data. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The data buffer to write. + * \param size The length of the data buffer. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Write a arbitrary-precision number (#MBEDTLS_ASN1_INTEGER) + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param X The MPI to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, + const mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Write a NULL tag (#MBEDTLS_ASN1_NULL) with zero data + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ); + +/** + * \brief Write an OID tag (#MBEDTLS_ASN1_OID) and data + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param oid The OID to write. + * \param oid_len The length of the OID. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ); + +/** + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param oid The OID of the algorithm to write. + * \param oid_len The length of the algorithm's OID. + * \param par_len The length of the parameters, which must be already written. + * If 0, NULL parameters are added + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, + unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ); + +/** + * \brief Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param boolean The boolean value to write, either \c 0 or \c 1. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, + int boolean ); + +/** + * \brief Write an int tag (#MBEDTLS_ASN1_INTEGER) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param val The integer value to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write a string in ASN.1 format using a specific + * string encoding tag. + + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param tag The string encoding tag to write, e.g. + * #MBEDTLS_ASN1_UTF8_STRING. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, + int tag, const char *text, + size_t text_len ); + +/** + * \brief Write a string in ASN.1 format using the PrintableString + * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_printable_string( unsigned char **p, + unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a UTF8 string in ASN.1 format using the UTF8String + * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a string in ASN.1 format using the IA5String + * string encoding tag (#MBEDTLS_ASN1_IA5_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and + * value in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The bitstring to write. + * \param bits The total number of bits in the bitstring. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ); + +/** + * \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING) + * and value in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The buffer holding the data to write. + * \param size The length of the data buffer \p buf. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +/** + * \brief Create or find a specific named_data entry for writing in a + * sequence or list based on the OID. If not already in there, + * a new entry is added to the head of the list. + * Warning: Destructive behaviour for the val data! + * + * \param list The pointer to the location of the head of the list to seek + * through (will be updated in case of a new entry). + * \param oid The OID to look for. + * \param oid_len The size of the OID. + * \param val The data to store (can be \c NULL if you want to fill + * it by hand). + * \param val_len The minimum length of the data buffer needed. + * + * \return A pointer to the new / existing entry on success. + * \return \c NULL if if there was a memory allocation error. + */ +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_ASN1_WRITE_H */ diff --git a/external/mbedtls/include/mbedtls/base64.h b/external/mbedtls/include/mbedtls/base64.h new file mode 100644 index 0000000..cbed688 --- /dev/null +++ b/external/mbedtls/include/mbedtls/base64.h @@ -0,0 +1,123 @@ +/** + * \file base64.h + * + * \brief RFC 1521 base64 encoding/decoding + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_BASE64_H +#define MBEDTLS_BASE64_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ +#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * If that length cannot be represented, then no data is + * written to the buffer and *olen is set to the maximum + * length representable as a size_t. + * + * \note Call this function with dlen = 0 to obtain the + * required buffer size in *olen + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer (can be NULL for checking size) + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or + * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is + * not correct. *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dst = NULL or dlen = 0 to obtain + * the required buffer size in *olen + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_base64_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ diff --git a/external/mbedtls/include/mbedtls/bignum.h b/external/mbedtls/include/mbedtls/bignum.h new file mode 100644 index 0000000..4d04b33 --- /dev/null +++ b/external/mbedtls/include/mbedtls/bignum.h @@ -0,0 +1,1009 @@ +/** + * \file bignum.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_BIGNUM_H +#define MBEDTLS_BIGNUM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ +#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ +#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ +#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ +#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ +#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */ + +#define MBEDTLS_MPI_CHK(f) \ + do \ + { \ + if( ( ret = (f) ) != 0 ) \ + goto cleanup; \ + } while( 0 ) + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define MBEDTLS_MPI_MAX_LIMBS 10000 + +#if !defined(MBEDTLS_MPI_WINDOW_SIZE) +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 ** MBEDTLS_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */ +#endif /* !MBEDTLS_MPI_WINDOW_SIZE */ + +#if !defined(MBEDTLS_MPI_MAX_SIZE) +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can temporarily result in larger MPIs. So the number + * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. + */ +#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ +#endif /* !MBEDTLS_MPI_MAX_SIZE */ + +#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mbedtls_mpi_read_file() and writing to files with + * mbedtls_mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) +#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 +#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise. + * + * 32 or 64-bit integer types can be forced regardless of the underlying + * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 + * respectively and undefining MBEDTLS_HAVE_ASM. + * + * Double-width integers (e.g. 128-bit in 64-bit architectures) can be + * disabled by defining MBEDTLS_NO_UDBL_DIVISION. + */ +#if !defined(MBEDTLS_HAVE_INT32) + #if defined(_MSC_VER) && defined(_M_AMD64) + /* Always choose 64-bit when using MSC */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #elif defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + ( defined(__sparc__) && defined(__arch64__) ) || \ + defined(__s390x__) || defined(__mips64) ) + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(__ARMCC_VERSION) && defined(__aarch64__) + /* + * __ARMCC_VERSION is defined for both armcc and armclang and + * __aarch64__ is only defined by armclang when compiling 64-bit code + */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef __uint128_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(MBEDTLS_HAVE_INT64) + /* Force 64-bit integers with unknown compiler */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #endif +#endif /* !MBEDTLS_HAVE_INT32 */ + +#if !defined(MBEDTLS_HAVE_INT64) + /* Default to 32-bit compilation */ + #if !defined(MBEDTLS_HAVE_INT32) + #define MBEDTLS_HAVE_INT32 + #endif /* !MBEDTLS_HAVE_INT32 */ + typedef int32_t mbedtls_mpi_sint; + typedef uint32_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + typedef uint64_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ +#endif /* !MBEDTLS_HAVE_INT64 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct mbedtls_mpi +{ + int s; /*!< Sign: -1 if the mpi is negative, 1 otherwise */ + size_t n; /*!< total # of limbs */ + mbedtls_mpi_uint *p; /*!< pointer to limbs */ +} +mbedtls_mpi; + +/** + * \brief Initialize an MPI context. + * + * This makes the MPI ready to be set or freed, + * but does not define a value for the MPI. + * + * \param X The MPI context to initialize. This must not be \c NULL. + */ +void mbedtls_mpi_init( mbedtls_mpi *X ); + +/** + * \brief This function frees the components of an MPI context. + * + * \param X The MPI context to be cleared. This may be \c NULL, + * in which case this function is a no-op. If it is + * not \c NULL, it must point to an initialized MPI. + */ +void mbedtls_mpi_free( mbedtls_mpi *X ); + +/** + * \brief Enlarge an MPI to the specified number of limbs. + * + * \note This function does nothing if the MPI is + * already large enough. + * + * \param X The MPI to grow. It must be initialized. + * \param nblimbs The target number of limbs. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief This function resizes an MPI downwards, keeping at least the + * specified number of limbs. + * + * If \c X is smaller than \c nblimbs, it is resized up + * instead. + * + * \param X The MPI to shrink. This must point to an initialized MPI. + * \param nblimbs The minimum number of limbs to keep. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * (this can only happen when resizing up). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Make a copy of an MPI. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param Y The source MPI. This must point to an initialized MPI. + * + * \note The limb-buffer in the destination MPI is enlarged + * if necessary to hold the value in the source MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Swap the contents of two MPIs. + * + * \param X The first MPI. It must be initialized. + * \param Y The second MPI. It must be initialized. + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); + +/** + * \brief Perform a safe conditional copy of MPI which doesn't + * reveal whether the condition was true or not. + * + * \param X The MPI to conditionally assign to. This must point + * to an initialized MPI. + * \param Y The MPI to be assigned from. This must point to an + * initialized MPI. + * \param assign The condition deciding whether to perform the + * assignment or not. Possible values: + * * \c 1: Perform the assignment `X = Y`. + * * \c 0: Keep the original value of \p X. + * + * \note This function is equivalent to + * `if( assign ) mbedtls_mpi_copy( X, Y );` + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Perform a safe conditional swap which doesn't + * reveal whether the condition was true or not. + * + * \param X The first MPI. This must be initialized. + * \param Y The second MPI. This must be initialized. + * \param assign The condition deciding whether to perform + * the swap or not. Possible values: + * * \c 1: Swap the values of \p X and \p Y. + * * \c 0: Keep the original values of \p X and \p Y. + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + * + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Store integer value in MPI. + * + * \param X The MPI to set. This must be initialized. + * \param z The value to use. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Get a specific bit from an MPI. + * + * \param X The MPI to query. This must be initialized. + * \param pos Zero-based index of the bit to query. + * + * \return \c 0 or \c 1 on success, depending on whether bit \c pos + * of \c X is unset or set. + * \return A negative error code on failure. + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); + +/** + * \brief Modify a specific bit in an MPI. + * + * \note This function will grow the target MPI if necessary to set a + * bit to \c 1 in a not yet existing limb. It will not grow if + * the bit should be set to \c 0. + * + * \param X The MPI to modify. This must be initialized. + * \param pos Zero-based index of the bit to modify. + * \param val The desired value of bit \c pos: \c 0 or \c 1. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of bits of value \c 0 before the + * least significant bit of value \c 1. + * + * \note This is the same as the zero-based index of + * the least significant bit of value \c 1. + * + * \param X The MPI to query. + * + * \return The number of bits of value \c 0 before the least significant + * bit of value \c 1 in \p X. + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant bit of value \c 1. + * + * * \note This is same as the one-based index of the most + * significant bit of value \c 1. + * + * \param X The MPI to query. This must point to an initialized MPI. + * + * \return The number of bits up to and including the most + * significant bit of value \c 1. + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); + +/** + * \brief Return the total size of an MPI value in bytes. + * + * \param X The MPI to use. This must point to an initialized MPI. + * + * \note The value returned by this function may be less than + * the number of bytes used to store \p X internally. + * This happens if and only if there are trailing bytes + * of value zero. + * + * \return The least number of bytes capable of storing + * the absolute value of \p X. + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ); + +/** + * \brief Import an MPI from an ASCII string. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the input string. + * \param s Null-terminated string buffer. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); + +/** + * \brief Export an MPI to an ASCII string. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base of the output string. + * \param buf The buffer to write the string to. This must be writable + * buffer of length \p buflen Bytes. + * \param buflen The available size in Bytes of \p buf. + * \param olen The address at which to store the length of the string + * written, including the final \c NULL byte. This must + * not be \c NULL. + * + * \note You can call this function with `buflen == 0` to obtain the + * minimum required buffer size in `*olen`. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the target buffer \p buf + * is too small to hold the value of \p X in the desired base. + * In this case, `*olen` is nonetheless updated to contain the + * size of \p buf required for a successful call. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Read an MPI from a line in an opened file. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the string representation used + * in the source line. + * \param fin The input file handle to use. This must not be \c NULL. + * + * \note On success, this function advances the file stream + * to the end of the current line or to EOF. + * + * The function returns \c 0 on an empty line. + * + * Leading whitespaces are ignored, as is a + * '0x' prefix for radix \c 16. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the file read buffer + * is too small. + * \return Another negative error code on failure. + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); + +/** + * \brief Export an MPI into an opened file. + * + * \param p A string prefix to emit prior to the MPI data. + * For example, this might be a label, or "0x" when + * printing in base \c 16. This may be \c NULL if no prefix + * is needed. + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base to be used in the emitted string. + * \param fout The output file handle. This may be \c NULL, in which case + * the output is written to \c stdout. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, + int radix, FILE *fout ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Import an MPI from unsigned big endian binary data. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param buf The input buffer. This must be a readable buffer of length + * \p buflen Bytes. + * \param buflen The length of the input buffer \p p in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, + size_t buflen ); + +/** + * \brief Export an MPI into unsigned big endian binary data + * of fixed size. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param buf The output buffer. This must be a writable buffer of length + * \p buflen Bytes. + * \param buflen The size of the output buffer \p buf in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p X. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, + size_t buflen ); + +/** + * \brief Perform a left-shift on an MPI: X <<= count + * + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); + +/** + * \brief Perform a right-shift on an MPI: X >>= count + * + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); + +/** + * \brief Compare the absolute values of two MPIs. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. + * + * \return \c 1 if `|X|` is greater than `|Y|`. + * \return \c -1 if `|X|` is lesser than `|Y|`. + * \return \c 0 if `|X|` is equal to `|Y|`. + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare two MPIs. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. + * + * \return \c 1 if \p X is greater than \p Y. + * \return \c -1 if \p X is lesser than \p Y. + * \return \c 0 if \p X is equal to \p Y. + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Check if an MPI is less than the other in constant time. + * + * \param X The left-hand MPI. This must point to an initialized MPI + * with the same allocated length as Y. + * \param Y The right-hand MPI. This must point to an initialized MPI + * with the same allocated length as X. + * \param ret The result of the comparison: + * \c 1 if \p X is less than \p Y. + * \c 0 if \p X is greater than or equal to \p Y. + * + * \return 0 on success. + * \return MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the allocated length of + * the two input MPIs is not the same. + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, + unsigned *ret ); + +/** + * \brief Compare an MPI with an integer. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param z The integer value to compare \p X to. + * + * \return \c 1 if \p X is greater than \p z. + * \return \c -1 if \p X is lesser than \p z. + * \return \c 0 if \p X is equal to \p z. + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Perform an unsigned addition of MPIs: X = |A| + |B| + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform an unsigned subtraction of MPIs: X = |A| - |B| + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is greater than \p A. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed addition of MPIs: X = A + B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed subtraction of MPIs: X = A - B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed addition of an MPI and an integer: X = A + b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param b The second summand. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a signed subtraction of an MPI and an integer: + * X = A - b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param b The subtrahend. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a multiplication of two MPIs: X = A * B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param B The second factor. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a multiplication of an MPI with an unsigned integer: + * X = A * b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param b The second factor. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_uint b ); + +/** + * \brief Perform a division with remainder of two MPIs: + * A = Q * B + R + * + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param B The divisor. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a division with remainder of an MPI by an integer: + * A = Q * b + R + * + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param b The divisor. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a modular reduction. R = A mod B + * + * \param R The destination MPI for the residue value. + * This must point to an initialized MPI. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPI. + * \param B The base of the modular reduction. + * This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is negative. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a modular reduction with respect to an integer. + * r = A mod b + * + * \param r The address at which to store the residue. + * This must not be \c NULL. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPi. + * \param b The integer base of the modular reduction. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p b is negative. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a sliding-window exponentiation: X = A^E mod N + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The base of the exponentiation. + * This must point to an initialized MPI. + * \param E The exponent MPI. This must point to an initialized MPI. + * \param N The base for the modular reduction. This must point to an + * initialized MPI. + * \param _RR A helper MPI depending solely on \p N which can be used to + * speed-up multiple modular exponentiations for the same value + * of \p N. This may be \c NULL. If it is not \c NULL, it must + * point to an initialized MPI. If it hasn't been used after + * the call to mbedtls_mpi_init(), this function will compute + * the helper value and store it in \p _RR for reuse on + * subsequent calls to this function. Otherwise, the function + * will assume that \p _RR holds the helper value set by a + * previous call to mbedtls_mpi_exp_mod(), and reuse it. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or + * even, or if \c E is negative. + * \return Another negative error code on different kinds of failures. + * + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *_RR ); + +/** + * \brief Fill an MPI with a number of random bytes. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param size The number of random bytes to generate. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on failure. + * + * \note The bytes obtained from the RNG are interpreted + * as a big-endian representation of an MPI; this can + * be relevant in applications like deterministic ECDSA. + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Compute the greatest common divisor: G = gcd(A, B) + * + * \param G The destination MPI. This must point to an initialized MPI. + * \param A The first operand. This must point to an initialized MPI. + * \param B The second operand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Compute the modular inverse: X = A^-1 mod N + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The MPI to calculate the modular inverse of. This must point + * to an initialized MPI. + * \param N The base of the modular inversion. This must point to an + * initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p N is less than + * or equal to one. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p has no modular inverse + * with respect to \p N. + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *N ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Perform a Miller-Rabin primality test with error + * probability of 2-80. + * + * \deprecated Superseded by mbedtls_mpi_is_prime_ext() which allows + * specifying the number of Miller-Rabin rounds. + * + * \param X The MPI to check for primality. + * This must point to an initialized MPI. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use a + * context parameter. + * + * \return \c 0 if successful, i.e. \p X is probably prime. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. + * \return Another negative error code on other kinds of failure. + */ +MBEDTLS_DEPRECATED int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Miller-Rabin primality test. + * + * \warning If \p X is potentially generated by an adversary, for example + * when validating cryptographic parameters that you didn't + * generate yourself and that are supposed to be prime, then + * \p rounds should be at least the half of the security + * strength of the cryptographic algorithm. On the other hand, + * if \p X is chosen uniformly or non-adversially (as is the + * case when mbedtls_mpi_gen_prime calls this function), then + * \p rounds can be much lower. + * + * \param X The MPI to check for primality. + * This must point to an initialized MPI. + * \param rounds The number of bases to perform the Miller-Rabin primality + * test for. The probability of returning 0 on a composite is + * at most 2-2*\p rounds. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, i.e. \p X is probably prime. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +/** + * \brief Flags for mbedtls_mpi_gen_prime() + * + * Each of these flags is a constraint on the result X returned by + * mbedtls_mpi_gen_prime(). + */ +typedef enum { + MBEDTLS_MPI_GEN_PRIME_FLAG_DH = 0x0001, /**< (X-1)/2 is prime too */ + MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR = 0x0002, /**< lower error rate from 2-80 to 2-128 */ +} mbedtls_mpi_gen_prime_flag_t; + +/** + * \brief Generate a prime number. + * + * \param X The destination MPI to store the generated prime in. + * This must point to an initialized MPi. + * \param nbits The required size of the destination MPI in bits. + * This must be between \c 3 and #MBEDTLS_MPI_MAX_BITS. + * \param flags A mask of flags of type #mbedtls_mpi_gen_prime_flag_t. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, in which case \p X holds a + * probably prime number. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if `nbits` is not between + * \c 3 and #MBEDTLS_MPI_MAX_BITS. + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_mpi_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ diff --git a/external/mbedtls/include/mbedtls/blowfish.h b/external/mbedtls/include/mbedtls/blowfish.h new file mode 100644 index 0000000..945bd42 --- /dev/null +++ b/external/mbedtls/include/mbedtls/blowfish.h @@ -0,0 +1,312 @@ +/** + * \file blowfish.h + * + * \brief Blowfish block cipher + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_BLOWFISH_H +#define MBEDTLS_BLOWFISH_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#include "platform_util.h" + +#define MBEDTLS_BLOWFISH_ENCRYPT 1 +#define MBEDTLS_BLOWFISH_DECRYPT 0 +#define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448 +#define MBEDTLS_BLOWFISH_MIN_KEY_BITS 32 +#define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ +#define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0016 ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA -0x0016 /**< Bad input data. */ + +#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ + +/* MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_BLOWFISH_ALT) +// Regular implementation +// + +/** + * \brief Blowfish context structure + */ +typedef struct mbedtls_blowfish_context +{ + uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ + uint32_t S[4][256]; /*!< key dependent S-boxes */ +} +mbedtls_blowfish_context; + +#else /* MBEDTLS_BLOWFISH_ALT */ +#include "blowfish_alt.h" +#endif /* MBEDTLS_BLOWFISH_ALT */ + +/** + * \brief Initialize a Blowfish context. + * + * \param ctx The Blowfish context to be initialized. + * This must not be \c NULL. + */ +void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ); + +/** + * \brief Clear a Blowfish context. + * + * \param ctx The Blowfish context to be cleared. + * This may be \c NULL, in which case this function + * returns immediately. If it is not \c NULL, it must + * point to an initialized Blowfish context. + */ +void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ); + +/** + * \brief Perform a Blowfish key schedule operation. + * + * \param ctx The Blowfish context to perform the key schedule on. + * \param key The encryption key. This must be a readable buffer of + * length \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be between + * \c 32 and \c 448 and a multiple of \c 8. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Perform a Blowfish-ECB block encryption/decryption operation. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param input The input block. This must be a readable buffer + * of size \c 8 Bytes. + * \param output The output block. This must be a writable buffer + * of size \c 8 Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, + int mode, + const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief Perform a Blowfish-CBC buffer encryption/decryption operation. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param length The length of the input data in Bytes. This must be + * multiple of \c 8. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 8 Bytes. It is updated by this function. + * \param input The input data. This must be a readable buffer of length + * \p length Bytes. + * \param output The output data. This must be a writable buffer of length + * \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief Perform a Blowfish CFB buffer encryption/decryption operation. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param length The length of the input data in Bytes. + * \param iv_off The offset in the initialiation vector. + * The value pointed to must be smaller than \c 8 Bytes. + * It is updated by this function to support the aforementioned + * streaming usage. + * \param iv The initialization vector. This must be a read/write buffer + * of size \c 8 Bytes. It is updated after use. + * \param input The input data. This must be a readable buffer of length + * \p length Bytes. + * \param output The output data. This must be a writable buffer of length + * \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief Perform a Blowfish-CTR buffer encryption/decryption operation. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**64 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 4 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 4 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**32 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. + * + * Note that for both stategies, sizes are measured in blocks and + * that a Blowfish block is 8 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param length The length of the input data in Bytes. + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer + * should be \c 0 at the start of a stream and must be + * smaller than \c 8. It is updated by this function. + * \param nonce_counter The 64-bit nonce and counter. This must point to a + * read/write buffer of length \c 8 Bytes. + * \param stream_block The saved stream-block for resuming. This must point to + * a read/write buffer of length \c 8 Bytes. + * \param input The input data. This must be a readable buffer of + * length \p length Bytes. + * \param output The output data. This must be a writable buffer of + * length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#endif /* blowfish.h */ diff --git a/external/mbedtls/include/mbedtls/bn_mul.h b/external/mbedtls/include/mbedtls/bn_mul.h new file mode 100644 index 0000000..9615090 --- /dev/null +++ b/external/mbedtls/include/mbedtls/bn_mul.h @@ -0,0 +1,941 @@ +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef MBEDTLS_BN_MUL_H +#define MBEDTLS_BN_MUL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" + +#if defined(MBEDTLS_HAVE_ASM) + +#ifndef asm +#define asm __asm +#endif + +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) + +/* + * Disable use of the i386 assembly code below if option -O0, to disable all + * compiler optimisations, is passed, detected with __OPTIMIZE__ + * This is done as the number of registers used in the assembly code doesn't + * work with the -O0 option. + */ +#if defined(__i386__) && defined(__OPTIMIZE__) + +#define MULADDC_INIT \ + asm( \ + "movl %%ebx, %0 \n\t" \ + "movl %5, %%esi \n\t" \ + "movl %6, %%edi \n\t" \ + "movl %7, %%ecx \n\t" \ + "movl %8, %%ebx \n\t" + +#define MULADDC_CORE \ + "lodsl \n\t" \ + "mull %%ebx \n\t" \ + "addl %%ecx, %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "addl (%%edi), %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "movl %%edx, %%ecx \n\t" \ + "stosl \n\t" + +#if defined(MBEDTLS_HAVE_SSE2) + +#define MULADDC_HUIT \ + "movd %%ecx, %%mm1 \n\t" \ + "movd %%ebx, %%mm0 \n\t" \ + "movd (%%edi), %%mm3 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd (%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "movd 4(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "movd 8(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd 12(%%esi), %%mm7 \n\t" \ + "pmuludq %%mm0, %%mm7 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 4(%%edi), %%mm3 \n\t" \ + "paddq %%mm4, %%mm3 \n\t" \ + "movd 8(%%edi), %%mm5 \n\t" \ + "paddq %%mm6, %%mm5 \n\t" \ + "movd 12(%%edi), %%mm4 \n\t" \ + "paddq %%mm4, %%mm7 \n\t" \ + "movd %%mm1, (%%edi) \n\t" \ + "movd 16(%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 20(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd 24(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd %%mm1, 4(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 28(%%esi), %%mm3 \n\t" \ + "pmuludq %%mm0, %%mm3 \n\t" \ + "paddq %%mm5, %%mm1 \n\t" \ + "movd 16(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm2 \n\t" \ + "movd %%mm1, 8(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm7, %%mm1 \n\t" \ + "movd 20(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm4 \n\t" \ + "movd %%mm1, 12(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 24(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm6 \n\t" \ + "movd %%mm1, 16(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm4, %%mm1 \n\t" \ + "movd 28(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm3 \n\t" \ + "movd %%mm1, 20(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm6, %%mm1 \n\t" \ + "movd %%mm1, 24(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd %%mm1, 28(%%edi) \n\t" \ + "addl $32, %%edi \n\t" \ + "addl $32, %%esi \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd %%mm1, %%ecx \n\t" + +#define MULADDC_STOP \ + "emms \n\t" \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "xorq %%r8, %%r8\n" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax\n" \ + "mulq %%rbx\n" \ + "addq $8, %%rsi\n" \ + "addq %%rcx, %%rax\n" \ + "movq %%r8, %%rcx\n" \ + "adcq $0, %%rdx\n" \ + "nop \n" \ + "addq %%rax, (%%rdi)\n" \ + "adcq %%rdx, %%rcx\n" \ + "addq $8, %%rdi\n" + +#define MULADDC_STOP \ + : "+c" (c), "+D" (d), "+S" (s) \ + : "b" (b) \ + : "rax", "rdx", "r8" \ + ); + +#endif /* AMD64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( \ + "movl %3, %%a2 \n\t" \ + "movl %4, %%a3 \n\t" \ + "movl %5, %%d3 \n\t" \ + "movl %6, %%d2 \n\t" \ + "moveq #0, %%d0 \n\t" + +#define MULADDC_CORE \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "moveq #0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d4, %%d3 \n\t" + +#define MULADDC_STOP \ + "movl %%d3, %0 \n\t" \ + "movl %%a3, %1 \n\t" \ + "movl %%a2, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ + ); + +#define MULADDC_HUIT \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d0, %%d3 \n\t" + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "ld r3, %3 \n\t" \ + "ld r4, %4 \n\t" \ + "ld r5, %5 \n\t" \ + "ld r6, %6 \n\t" \ + "addi r3, r3, -8 \n\t" \ + "addi r4, r4, -8 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu r7, 8(r3) \n\t" \ + "mulld r8, r7, r6 \n\t" \ + "mulhdu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "ld r7, 8(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stdu r8, 8(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 8 \n\t" \ + "addi r3, r3, 8 \n\t" \ + "std r5, %0 \n\t" \ + "std r4, %1 \n\t" \ + "std r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %%r3, %3 \n\t" \ + "ld %%r4, %4 \n\t" \ + "ld %%r5, %5 \n\t" \ + "ld %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -8 \n\t" \ + "addi %%r4, %%r4, -8 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu %%r7, 8(%%r3) \n\t" \ + "mulld %%r8, %%r7, %%r6 \n\t" \ + "mulhdu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "ld %%r7, 8(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stdu %%r8, 8(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 8 \n\t" \ + "addi %%r3, %%r3, 8 \n\t" \ + "std %%r5, %0 \n\t" \ + "std %%r4, %1 \n\t" \ + "std %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "lwz r3, %3 \n\t" \ + "lwz r4, %4 \n\t" \ + "lwz r5, %5 \n\t" \ + "lwz r6, %6 \n\t" \ + "addi r3, r3, -4 \n\t" \ + "addi r4, r4, -4 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu r7, 4(r3) \n\t" \ + "mullw r8, r7, r6 \n\t" \ + "mulhwu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "lwz r7, 4(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stwu r8, 4(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 4 \n\t" \ + "addi r3, r3, 4 \n\t" \ + "stw r5, %0 \n\t" \ + "stw r4, %1 \n\t" \ + "stw r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "lwz %%r3, %3 \n\t" \ + "lwz %%r4, %4 \n\t" \ + "lwz %%r5, %5 \n\t" \ + "lwz %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -4 \n\t" \ + "addi %%r4, %%r4, -4 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu %%r7, 4(%%r3) \n\t" \ + "mullw %%r8, %%r7, %%r6 \n\t" \ + "mulhwu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "lwz %%r7, 4(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stwu %%r8, 4(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 4 \n\t" \ + "addi %%r3, %%r3, 4 \n\t" \ + "stw %%r5, %0 \n\t" \ + "stw %%r4, %1 \n\t" \ + "stw %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#endif /* PPC32 */ + +/* + * The Sparc(64) assembly is reported to be broken. + * Disable it for now, until we're able to fix it. + */ +#if 0 && defined(__sparc__) +#if defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + + #define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "stx %%o1, %1 \n\t" \ + "stx %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#else /* __sparc64__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + +#define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "st %%o1, %1 \n\t" \ + "st %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* __sparc64__ */ +#endif /* __sparc__ */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( \ + "lwi r3, %3 \n\t" \ + "lwi r4, %4 \n\t" \ + "lwi r5, %5 \n\t" \ + "lwi r6, %6 \n\t" \ + "andi r7, r6, 0xffff \n\t" \ + "bsrli r6, r6, 16 \n\t" + +#define MULADDC_CORE \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "mul r10, r9, r6 \n\t" \ + "mul r11, r8, r7 \n\t" \ + "mul r12, r9, r7 \n\t" \ + "mul r13, r8, r6 \n\t" \ + "bsrli r8, r10, 16 \n\t" \ + "bsrli r9, r11, 16 \n\t" \ + "add r13, r13, r8 \n\t" \ + "add r13, r13, r9 \n\t" \ + "bslli r10, r10, 16 \n\t" \ + "bslli r11, r11, 16 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r11 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "lwi r10, r4, 0 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r5 \n\t" \ + "addc r5, r13, r0 \n\t" \ + "swi r12, r4, 0 \n\t" \ + "addi r4, r4, 4 \n\t" + +#define MULADDC_STOP \ + "swi r5, %0 \n\t" \ + "swi r4, %1 \n\t" \ + "swi r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "r13" \ + ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( \ + "ld.a %%a2, %3 \n\t" \ + "ld.a %%a3, %4 \n\t" \ + "ld.w %%d4, %5 \n\t" \ + "ld.w %%d1, %6 \n\t" \ + "xor %%d5, %%d5 \n\t" + +#define MULADDC_CORE \ + "ld.w %%d0, [%%a2+] \n\t" \ + "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ + "ld.w %%d0, [%%a3] \n\t" \ + "addx %%d2, %%d2, %%d0 \n\t" \ + "addc %%d3, %%d3, 0 \n\t" \ + "mov %%d4, %%d3 \n\t" \ + "st.w [%%a3+], %%d2 \n\t" + +#define MULADDC_STOP \ + "st.w %0, %%d4 \n\t" \ + "st.a %1, %%a3 \n\t" \ + "st.a %2, %%a2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "e2", "d4", "a2", "a3" \ + ); + +#endif /* TriCore */ + +/* + * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about + * our use of r7 below, unless -fomit-frame-pointer is passed. + * + * On the other hand, -fomit-frame-pointer is implied by any -Ox options with + * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by + * clang and armcc5 under the same conditions). + * + * So, only use the optimized assembly below for optimized build, which avoids + * the build error and is pretty reasonable anyway. + */ +#if defined(__GNUC__) && !defined(__OPTIMIZE__) +#define MULADDC_CANNOT_USE_R7 +#endif + +#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) + +#if defined(__thumb__) && !defined(__thumb2__) + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" \ + "lsr r7, r3, #16 \n\t" \ + "mov r9, r7 \n\t" \ + "lsl r7, r3, #16 \n\t" \ + "lsr r7, r7, #16 \n\t" \ + "mov r8, r7 \n\t" + +#define MULADDC_CORE \ + "ldmia r0!, {r6} \n\t" \ + "lsr r7, r6, #16 \n\t" \ + "lsl r6, r6, #16 \n\t" \ + "lsr r6, r6, #16 \n\t" \ + "mov r4, r8 \n\t" \ + "mul r4, r6 \n\t" \ + "mov r3, r9 \n\t" \ + "mul r6, r3 \n\t" \ + "mov r5, r9 \n\t" \ + "mul r5, r7 \n\t" \ + "mov r3, r8 \n\t" \ + "mul r7, r3 \n\t" \ + "lsr r3, r6, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "lsr r3, r7, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "add r4, r4, r2 \n\t" \ + "mov r2, #0 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r6, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r7, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "ldr r3, [r1] \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r2, r5 \n\t" \ + "stmia r1!, {r4} \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#elif (__ARM_ARCH >= 6) && \ + defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1) + +#define MULADDC_INIT \ + asm( + +#define MULADDC_CORE \ + "ldr r0, [%0], #4 \n\t" \ + "ldr r1, [%1] \n\t" \ + "umaal r1, %2, %3, r0 \n\t" \ + "str r1, [%1], #4 \n\t" + +#define MULADDC_STOP \ + : "=r" (s), "=r" (d), "=r" (c) \ + : "r" (b), "0" (s), "1" (d), "2" (c) \ + : "r0", "r1", "memory" \ + ); + +#else + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_CORE \ + "ldr r4, [r0], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r1] \n\t" \ + "umlal r2, r5, r3, r4 \n\t" \ + "adds r7, r6, r2 \n\t" \ + "adc r2, r5, #0 \n\t" \ + "str r7, [r1], #4 \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_CORE \ + "ldq $6, 0($1) \n\t" \ + "addq $1, 8, $1 \n\t" \ + "mulq $6, $4, $7 \n\t" \ + "umulh $6, $4, $6 \n\t" \ + "addq $7, $3, $7 \n\t" \ + "cmpult $7, $3, $3 \n\t" \ + "ldq $5, 0($2) \n\t" \ + "addq $7, $5, $7 \n\t" \ + "cmpult $7, $5, $5 \n\t" \ + "stq $7, 0($2) \n\t" \ + "addq $2, 8, $2 \n\t" \ + "addq $6, $3, $3 \n\t" \ + "addq $5, $3, $3 \n\t" + +#define MULADDC_STOP \ + "stq $3, %0 \n\t" \ + "stq $2, %1 \n\t" \ + "stq $1, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ + ); +#endif /* Alpha */ + +#if defined(__mips__) && !defined(__mips64) + +#define MULADDC_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_CORE \ + "lw $14, 0($10) \n\t" \ + "multu $13, $14 \n\t" \ + "addi $10, $10, 4 \n\t" \ + "mflo $14 \n\t" \ + "mfhi $9 \n\t" \ + "addu $14, $12, $14 \n\t" \ + "lw $15, 0($11) \n\t" \ + "sltu $12, $14, $12 \n\t" \ + "addu $15, $14, $15 \n\t" \ + "sltu $14, $15, $14 \n\t" \ + "addu $12, $12, $9 \n\t" \ + "sw $15, 0($11) \n\t" \ + "addu $12, $12, $14 \n\t" \ + "addi $11, $11, 4 \n\t" + +#define MULADDC_STOP \ + "sw $12, %0 \n\t" \ + "sw $11, %1 \n\t" \ + "sw $10, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15", "lo", "hi" \ + ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(MBEDTLS_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* MBEDTLS_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(MBEDTLS_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + mbedtls_t_udbl r; \ + mbedtls_mpi_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (mbedtls_t_udbl) b; \ + r0 = (mbedtls_mpi_uint) r; \ + r1 = (mbedtls_mpi_uint)( r >> biL ); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + mbedtls_mpi_uint s0, s1, b0, b1; \ + mbedtls_mpi_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ diff --git a/external/mbedtls/include/mbedtls/camellia.h b/external/mbedtls/include/mbedtls/camellia.h new file mode 100644 index 0000000..3887128 --- /dev/null +++ b/external/mbedtls/include/mbedtls/camellia.h @@ -0,0 +1,351 @@ +/** + * \file camellia.h + * + * \brief Camellia block cipher + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_CAMELLIA_H +#define MBEDTLS_CAMELLIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#include "platform_util.h" + +#define MBEDTLS_CAMELLIA_ENCRYPT 1 +#define MBEDTLS_CAMELLIA_DECRYPT 0 + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0024 ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024 /**< Bad input data. */ + +#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ + +/* MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CAMELLIA_ALT) +// Regular implementation +// + +/** + * \brief CAMELLIA context structure + */ +typedef struct mbedtls_camellia_context +{ + int nr; /*!< number of rounds */ + uint32_t rk[68]; /*!< CAMELLIA round keys */ +} +mbedtls_camellia_context; + +#else /* MBEDTLS_CAMELLIA_ALT */ +#include "camellia_alt.h" +#endif /* MBEDTLS_CAMELLIA_ALT */ + +/** + * \brief Initialize a CAMELLIA context. + * + * \param ctx The CAMELLIA context to be initialized. + * This must not be \c NULL. + */ +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ); + +/** + * \brief Clear a CAMELLIA context. + * + * \param ctx The CAMELLIA context to be cleared. This may be \c NULL, + * in which case this function returns immediately. If it is not + * \c NULL, it must be initialized. + */ +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ); + +/** + * \brief Perform a CAMELLIA key schedule operation for encryption. + * + * \param ctx The CAMELLIA context to use. This must be initialized. + * \param key The encryption key to use. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be either \c 128, + * \c 192 or \c 256. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Perform a CAMELLIA key schedule operation for decryption. + * + * \param ctx The CAMELLIA context to use. This must be initialized. + * \param key The decryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be either \c 128, + * \c 192 or \c 256. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Perform a CAMELLIA-ECB block encryption/decryption operation. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param input The input block. This must be a readable buffer + * of size \c 16 Bytes. + * \param output The output block. This must be a writable buffer + * of size \c 16 Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief Perform a CAMELLIA-CBC buffer encryption/decryption operation. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param length The length in Bytes of the input data \p input. + * This must be a multiple of \c 16 Bytes. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 16 Bytes. It is updated to allow streaming + * use as explained above. + * \param input The buffer holding the input data. This must point to a + * readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must point to a + * writable buffer of length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief Perform a CAMELLIA-CFB128 buffer encryption/decryption + * operation. + * + * \note Due to the nature of CFB mode, you should use the same + * key for both encryption and decryption. In particular, calls + * to this function should be preceded by a key-schedule via + * mbedtls_camellia_setkey_enc() regardless of whether \p mode + * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param length The length of the input data \p input. Any value is allowed. + * \param iv_off The current offset in the IV. This must be smaller + * than \c 16 Bytes. It is updated after this call to allow + * the aforementioned streaming usage. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 16 Bytes. It is updated after this call to + * allow the aforementioned streaming usage. + * \param input The buffer holding the input data. This must be a readable + * buffer of size \p length Bytes. + * \param output The buffer to hold the output data. This must be a writable + * buffer of length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief Perform a CAMELLIA-CTR buffer encryption/decryption operation. + * + * *note Due to the nature of CTR mode, you should use the same + * key for both encryption and decryption. In particular, calls + * to this function should be preceded by a key-schedule via + * mbedtls_camellia_setkey_enc() regardless of whether \p mode + * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first \c 12 Bytes for the + * per-message nonce, and the last \c 4 Bytes for internal use. + * In that case, before calling this function on a new message you + * need to set the first \c 12 Bytes of \p nonce_counter to your + * chosen nonce value, the last four to \c 0, and \p nc_off to \c 0 + * (which will cause \p stream_block to be ignored). That way, you + * can encrypt at most \c 2**96 messages of up to \c 2**32 blocks + * each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be + * unique. The recommended way to ensure uniqueness is to use a + * message counter. An alternative is to generate random nonces, + * but this limits the number of messages that can be securely + * encrypted: for example, with 96-bit random nonces, you should + * not encrypt more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that a CAMELLIA block is \c 16 Bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param length The length of the input data \p input in Bytes. + * Any value is allowed. + * \param nc_off The offset in the current \p stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be \c 0 at the start of a stream. It is updated + * at the end of this call. + * \param nonce_counter The 128-bit nonce and counter. This must be a read/write + * buffer of length \c 16 Bytes. + * \param stream_block The saved stream-block for resuming. This must be a + * read/write buffer of length \c 16 Bytes. + * \param input The input data stream. This must be a readable buffer of + * size \p length Bytes. + * \param output The output data stream. This must be a writable buffer + * of size \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_camellia_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* camellia.h */ diff --git a/external/mbedtls/include/mbedtls/ccm.h b/external/mbedtls/include/mbedtls/ccm.h new file mode 100644 index 0000000..d50c6ec --- /dev/null +++ b/external/mbedtls/include/mbedtls/ccm.h @@ -0,0 +1,335 @@ +/** + * \file ccm.h + * + * \brief This file provides an API for the CCM authenticated encryption + * mode for block ciphers. + * + * CCM combines Counter mode encryption with CBC-MAC authentication + * for 128-bit block ciphers. + * + * Input to CCM includes the following elements: + *
  • Payload - data that is both authenticated and encrypted.
  • + *
  • Associated data (Adata) - data that is authenticated but not + * encrypted, For example, a header.
  • + *
  • Nonce - A unique value that is assigned to the payload and the + * associated data.
+ * + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + * + * Definition of CCM*: + * IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks + * Integer representation is fixed most-significant-octet-first order and + * the representation of octets is most-significant-bit-first order. This is + * consistent with RFC 3610. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_CCM_H +#define MBEDTLS_CCM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "cipher.h" + +#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */ +#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ + +/* MBEDTLS_ERR_CCM_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CCM_ALT) +// Regular implementation +// + +/** + * \brief The CCM context-type definition. The CCM context is passed + * to the APIs called. + */ +typedef struct mbedtls_ccm_context +{ + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ +} +mbedtls_ccm_context; + +#else /* MBEDTLS_CCM_ALT */ +#include "ccm_alt.h" +#endif /* MBEDTLS_CCM_ALT */ + +/** + * \brief This function initializes the specified CCM context, + * to make references valid, and prepare the context + * for mbedtls_ccm_setkey() or mbedtls_ccm_free(). + * + * \param ctx The CCM context to initialize. This must not be \c NULL. + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ); + +/** + * \brief This function initializes the CCM context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The CCM context to initialize. This must be an initialized + * context. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. This must not be \c NULL. + * \param keybits The key size in bits. This must be acceptable by the cipher. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function releases and clears the specified CCM context + * and underlying cipher sub-context. + * + * \param ctx The CCM context to clear. If this is \c NULL, the function + * has no effect. Otherwise, this must be initialized. + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); + +/** + * \brief This function encrypts a buffer using CCM. + * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * + * \param ctx The CCM context to use for encryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. If \p add_len is greater than + * zero, \p add must be a readable buffer of at least that + * length. + * \param add_len The length of additional data in Bytes. + * This must be less than `2^16 - 2^8`. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * writable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function encrypts a buffer using CCM*. + * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * + * \note When using this function in a variable tag length context, + * the tag length has to be encoded into the \p iv passed to + * this function. + * + * \param ctx The CCM context to use for encryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer of + * at least \p add_len Bytes. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * writable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing \c 0 as \p tag_len means that the message is no + * longer authenticated. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function performs a CCM authenticated decryption of a + * buffer. + * + * \param ctx The CCM context to use for decryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer + * of at least that \p add_len Bytes.. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * + * \return \c 0 on success. This indicates that the message is authentic. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. + */ +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + +/** + * \brief This function performs a CCM* authenticated decryption of a + * buffer. + * + * \note When using this function in a variable tag length context, + * the tag length has to be decoded from \p iv and passed to + * this function as \p tag_len. (\p tag needs to be adjusted + * accordingly.) + * + * \param ctx The CCM context to use for decryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer of + * at least that \p add_len Bytes. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field in Bytes. + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing \c 0 as \p tag_len means that the message is nos + * longer authenticated. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. + */ +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The CCM checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ccm_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CCM_H */ diff --git a/external/mbedtls/include/mbedtls/certs.h b/external/mbedtls/include/mbedtls/certs.h new file mode 100644 index 0000000..8472a6f --- /dev/null +++ b/external/mbedtls/include/mbedtls/certs.h @@ -0,0 +1,277 @@ +/** + * \file certs.h + * + * \brief Sample certificates and DHM parameters for testing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_CERTS_H +#define MBEDTLS_CERTS_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* List of all PEM-encoded CA certificates, terminated by NULL; + * PEM encoded if MBEDTLS_PEM_PARSE_C is enabled, DER encoded + * otherwise. */ +extern const char * mbedtls_test_cas[]; +extern const size_t mbedtls_test_cas_len[]; + +/* List of all DER-encoded CA certificates, terminated by NULL */ +extern const unsigned char * mbedtls_test_cas_der[]; +extern const size_t mbedtls_test_cas_der_len[]; + +#if defined(MBEDTLS_PEM_PARSE_C) +/* Concatenation of all CA certificates in PEM format if available */ +extern const char mbedtls_test_cas_pem[]; +extern const size_t mbedtls_test_cas_pem_len; +#endif /* MBEDTLS_PEM_PARSE_C */ + +/* + * CA test certificates + */ + +extern const char mbedtls_test_ca_crt_ec_pem[]; +extern const char mbedtls_test_ca_key_ec_pem[]; +extern const char mbedtls_test_ca_pwd_ec_pem[]; +extern const char mbedtls_test_ca_key_rsa_pem[]; +extern const char mbedtls_test_ca_pwd_rsa_pem[]; +extern const char mbedtls_test_ca_crt_rsa_sha1_pem[]; +extern const char mbedtls_test_ca_crt_rsa_sha256_pem[]; + +extern const unsigned char mbedtls_test_ca_crt_ec_der[]; +extern const unsigned char mbedtls_test_ca_key_ec_der[]; +extern const unsigned char mbedtls_test_ca_key_rsa_der[]; +extern const unsigned char mbedtls_test_ca_crt_rsa_sha1_der[]; +extern const unsigned char mbedtls_test_ca_crt_rsa_sha256_der[]; + +extern const size_t mbedtls_test_ca_crt_ec_pem_len; +extern const size_t mbedtls_test_ca_key_ec_pem_len; +extern const size_t mbedtls_test_ca_pwd_ec_pem_len; +extern const size_t mbedtls_test_ca_key_rsa_pem_len; +extern const size_t mbedtls_test_ca_pwd_rsa_pem_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha1_pem_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha256_pem_len; + +extern const size_t mbedtls_test_ca_crt_ec_der_len; +extern const size_t mbedtls_test_ca_key_ec_der_len; +extern const size_t mbedtls_test_ca_pwd_ec_der_len; +extern const size_t mbedtls_test_ca_key_rsa_der_len; +extern const size_t mbedtls_test_ca_pwd_rsa_der_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha1_der_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha256_der_len; + +/* Config-dependent dispatch between PEM and DER encoding + * (PEM if enabled, otherwise DER) */ + +extern const char mbedtls_test_ca_crt_ec[]; +extern const char mbedtls_test_ca_key_ec[]; +extern const char mbedtls_test_ca_pwd_ec[]; +extern const char mbedtls_test_ca_key_rsa[]; +extern const char mbedtls_test_ca_pwd_rsa[]; +extern const char mbedtls_test_ca_crt_rsa_sha1[]; +extern const char mbedtls_test_ca_crt_rsa_sha256[]; + +extern const size_t mbedtls_test_ca_crt_ec_len; +extern const size_t mbedtls_test_ca_key_ec_len; +extern const size_t mbedtls_test_ca_pwd_ec_len; +extern const size_t mbedtls_test_ca_key_rsa_len; +extern const size_t mbedtls_test_ca_pwd_rsa_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha1_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha256_len; + +/* Config-dependent dispatch between SHA-1 and SHA-256 + * (SHA-256 if enabled, otherwise SHA-1) */ + +extern const char mbedtls_test_ca_crt_rsa[]; +extern const size_t mbedtls_test_ca_crt_rsa_len; + +/* Config-dependent dispatch between EC and RSA + * (RSA if enabled, otherwise EC) */ + +extern const char * mbedtls_test_ca_crt; +extern const char * mbedtls_test_ca_key; +extern const char * mbedtls_test_ca_pwd; +extern const size_t mbedtls_test_ca_crt_len; +extern const size_t mbedtls_test_ca_key_len; +extern const size_t mbedtls_test_ca_pwd_len; + +/* + * Server test certificates + */ + +extern const char mbedtls_test_srv_crt_ec_pem[]; +extern const char mbedtls_test_srv_key_ec_pem[]; +extern const char mbedtls_test_srv_pwd_ec_pem[]; +extern const char mbedtls_test_srv_key_rsa_pem[]; +extern const char mbedtls_test_srv_pwd_rsa_pem[]; +extern const char mbedtls_test_srv_crt_rsa_sha1_pem[]; +extern const char mbedtls_test_srv_crt_rsa_sha256_pem[]; + +extern const unsigned char mbedtls_test_srv_crt_ec_der[]; +extern const unsigned char mbedtls_test_srv_key_ec_der[]; +extern const unsigned char mbedtls_test_srv_key_rsa_der[]; +extern const unsigned char mbedtls_test_srv_crt_rsa_sha1_der[]; +extern const unsigned char mbedtls_test_srv_crt_rsa_sha256_der[]; + +extern const size_t mbedtls_test_srv_crt_ec_pem_len; +extern const size_t mbedtls_test_srv_key_ec_pem_len; +extern const size_t mbedtls_test_srv_pwd_ec_pem_len; +extern const size_t mbedtls_test_srv_key_rsa_pem_len; +extern const size_t mbedtls_test_srv_pwd_rsa_pem_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha1_pem_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha256_pem_len; + +extern const size_t mbedtls_test_srv_crt_ec_der_len; +extern const size_t mbedtls_test_srv_key_ec_der_len; +extern const size_t mbedtls_test_srv_pwd_ec_der_len; +extern const size_t mbedtls_test_srv_key_rsa_der_len; +extern const size_t mbedtls_test_srv_pwd_rsa_der_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha1_der_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha256_der_len; + +/* Config-dependent dispatch between PEM and DER encoding + * (PEM if enabled, otherwise DER) */ + +extern const char mbedtls_test_srv_crt_ec[]; +extern const char mbedtls_test_srv_key_ec[]; +extern const char mbedtls_test_srv_pwd_ec[]; +extern const char mbedtls_test_srv_key_rsa[]; +extern const char mbedtls_test_srv_pwd_rsa[]; +extern const char mbedtls_test_srv_crt_rsa_sha1[]; +extern const char mbedtls_test_srv_crt_rsa_sha256[]; + +extern const size_t mbedtls_test_srv_crt_ec_len; +extern const size_t mbedtls_test_srv_key_ec_len; +extern const size_t mbedtls_test_srv_pwd_ec_len; +extern const size_t mbedtls_test_srv_key_rsa_len; +extern const size_t mbedtls_test_srv_pwd_rsa_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha1_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha256_len; + +/* Config-dependent dispatch between SHA-1 and SHA-256 + * (SHA-256 if enabled, otherwise SHA-1) */ + +extern const char mbedtls_test_srv_crt_rsa[]; +extern const size_t mbedtls_test_srv_crt_rsa_len; + +/* Config-dependent dispatch between EC and RSA + * (RSA if enabled, otherwise EC) */ + +extern const char * mbedtls_test_srv_crt; +extern const char * mbedtls_test_srv_key; +extern const char * mbedtls_test_srv_pwd; +extern const size_t mbedtls_test_srv_crt_len; +extern const size_t mbedtls_test_srv_key_len; +extern const size_t mbedtls_test_srv_pwd_len; + +/* + * Client test certificates + */ + +extern const char mbedtls_test_cli_crt_ec_pem[]; +extern const char mbedtls_test_cli_key_ec_pem[]; +extern const char mbedtls_test_cli_pwd_ec_pem[]; +extern const char mbedtls_test_cli_key_rsa_pem[]; +extern const char mbedtls_test_cli_pwd_rsa_pem[]; +extern const char mbedtls_test_cli_crt_rsa_pem[]; + +extern const unsigned char mbedtls_test_cli_crt_ec_der[]; +extern const unsigned char mbedtls_test_cli_key_ec_der[]; +extern const unsigned char mbedtls_test_cli_key_rsa_der[]; +extern const unsigned char mbedtls_test_cli_crt_rsa_der[]; + +extern const size_t mbedtls_test_cli_crt_ec_pem_len; +extern const size_t mbedtls_test_cli_key_ec_pem_len; +extern const size_t mbedtls_test_cli_pwd_ec_pem_len; +extern const size_t mbedtls_test_cli_key_rsa_pem_len; +extern const size_t mbedtls_test_cli_pwd_rsa_pem_len; +extern const size_t mbedtls_test_cli_crt_rsa_pem_len; + +extern const size_t mbedtls_test_cli_crt_ec_der_len; +extern const size_t mbedtls_test_cli_key_ec_der_len; +extern const size_t mbedtls_test_cli_key_rsa_der_len; +extern const size_t mbedtls_test_cli_crt_rsa_der_len; + +/* Config-dependent dispatch between PEM and DER encoding + * (PEM if enabled, otherwise DER) */ + +extern const char mbedtls_test_cli_crt_ec[]; +extern const char mbedtls_test_cli_key_ec[]; +extern const char mbedtls_test_cli_pwd_ec[]; +extern const char mbedtls_test_cli_key_rsa[]; +extern const char mbedtls_test_cli_pwd_rsa[]; +extern const char mbedtls_test_cli_crt_rsa[]; + +extern const size_t mbedtls_test_cli_crt_ec_len; +extern const size_t mbedtls_test_cli_key_ec_len; +extern const size_t mbedtls_test_cli_pwd_ec_len; +extern const size_t mbedtls_test_cli_key_rsa_len; +extern const size_t mbedtls_test_cli_pwd_rsa_len; +extern const size_t mbedtls_test_cli_crt_rsa_len; + +/* Config-dependent dispatch between EC and RSA + * (RSA if enabled, otherwise EC) */ + +extern const char * mbedtls_test_cli_crt; +extern const char * mbedtls_test_cli_key; +extern const char * mbedtls_test_cli_pwd; +extern const size_t mbedtls_test_cli_crt_len; +extern const size_t mbedtls_test_cli_key_len; +extern const size_t mbedtls_test_cli_pwd_len; + +#ifdef __cplusplus +} +#endif + +#endif /* certs.h */ diff --git a/external/mbedtls/include/mbedtls/chacha20.h b/external/mbedtls/include/mbedtls/chacha20.h new file mode 100644 index 0000000..8c9c2af --- /dev/null +++ b/external/mbedtls/include/mbedtls/chacha20.h @@ -0,0 +1,252 @@ +/** + * \file chacha20.h + * + * \brief This file contains ChaCha20 definitions and functions. + * + * ChaCha20 is a stream cipher that can encrypt and decrypt + * information. ChaCha was created by Daniel Bernstein as a variant of + * its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf + * ChaCha20 is the variant with 20 rounds, that was also standardized + * in RFC 7539. + * + * \author Daniel King + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_CHACHA20_H +#define MBEDTLS_CHACHA20_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 /**< Invalid input parameter(s). */ + +/* MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ +#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */ + +/* MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 /**< Chacha20 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CHACHA20_ALT) + +typedef struct mbedtls_chacha20_context +{ + uint32_t state[16]; /*! The state (before round operations). */ + uint8_t keystream8[64]; /*! Leftover keystream bytes. */ + size_t keystream_bytes_used; /*! Number of keystream bytes already used. */ +} +mbedtls_chacha20_context; + +#else /* MBEDTLS_CHACHA20_ALT */ +#include "chacha20_alt.h" +#endif /* MBEDTLS_CHACHA20_ALT */ + +/** + * \brief This function initializes the specified ChaCha20 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by calls to + * \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts(), then one or more calls to + * to \c mbedtls_chacha20_update(), and finally to + * \c mbedtls_chacha20_free(). + * + * \param ctx The ChaCha20 context to initialize. + * This must not be \c NULL. + */ +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function releases and clears the specified + * ChaCha20 context. + * + * \param ctx The ChaCha20 context to clear. This may be \c NULL, + * in which case this function is a no-op. If it is not + * \c NULL, it must point to an initialized context. + * + */ +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function sets the encryption/decryption key. + * + * \note After using this function, you must also call + * \c mbedtls_chacha20_starts() to set a nonce before you + * start encrypting/decrypting data with + * \c mbedtls_chacha_update(). + * + * \param ctx The ChaCha20 context to which the key should be bound. + * It must be initialized. + * \param key The encryption/decryption key. This must be \c 32 Bytes + * in length. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL. + */ +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function sets the nonce and initial counter value. + * + * \note A ChaCha20 context can be re-used with the same key by + * calling this function to change the nonce. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality guarantees for the + * messages encrypted with the same nonce and key. + * + * \param ctx The ChaCha20 context to which the nonce should be bound. + * It must be initialized and bound to a key. + * \param nonce The nonce. This must be \c 12 Bytes in size. + * \param counter The initial counter value. This is usually \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is + * NULL. + */ +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ); + +/** + * \brief This function encrypts or decrypts data. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \note \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts() must be called at least once + * to setup the context before this function can be called. + * + * \note This function can be called multiple times in a row in + * order to encrypt of decrypt data piecewise with the same + * key and nonce. + * + * \param ctx The ChaCha20 context to use for encryption or decryption. + * It must be initialized and bound to a key and nonce. + * \param size The length of the input data in Bytes. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `size == 0`. + * \param output The buffer holding the output data. + * This must be able to hold \p size Bytes. + * This pointer can be \c NULL if `size == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function encrypts or decrypts data with ChaCha20 and + * the given key and nonce. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \warning You must never use the same (key, nonce) pair more than + * once. This would void any confidentiality guarantees for + * the messages encrypted with the same nonce and key. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \param key The encryption/decryption key. + * This must be \c 32 Bytes in length. + * \param nonce The nonce. This must be \c 12 Bytes in size. + * \param counter The initial counter value. This is usually \c 0. + * \param size The length of the input data in Bytes. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `size == 0`. + * \param output The buffer holding the output data. + * This must be able to hold \p size Bytes. + * This pointer can be \c NULL if `size == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t size, + const unsigned char* input, + unsigned char* output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chacha20_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHA20_H */ diff --git a/external/mbedtls/include/mbedtls/chachapoly.h b/external/mbedtls/include/mbedtls/chachapoly.h new file mode 100644 index 0000000..5f6cb6e --- /dev/null +++ b/external/mbedtls/include/mbedtls/chachapoly.h @@ -0,0 +1,384 @@ +/** + * \file chachapoly.h + * + * \brief This file contains the AEAD-ChaCha20-Poly1305 definitions and + * functions. + * + * ChaCha20-Poly1305 is an algorithm for Authenticated Encryption + * with Associated Data (AEAD) that can be used to encrypt and + * authenticate data. It is based on ChaCha20 and Poly1305 by Daniel + * Bernstein and was standardized in RFC 7539. + * + * \author Daniel King + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_CHACHAPOLY_H +#define MBEDTLS_CHACHAPOLY_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* for shared error codes */ +#include "poly1305.h" + +#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE -0x0054 /**< The requested operation is not permitted in the current state. */ +#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED -0x0056 /**< Authenticated decryption failed: data was not authentic. */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_CHACHAPOLY_ENCRYPT, /**< The mode value for performing encryption. */ + MBEDTLS_CHACHAPOLY_DECRYPT /**< The mode value for performing decryption. */ +} +mbedtls_chachapoly_mode_t; + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +#include "chacha20.h" + +typedef struct mbedtls_chachapoly_context +{ + mbedtls_chacha20_context chacha20_ctx; /**< The ChaCha20 context. */ + mbedtls_poly1305_context poly1305_ctx; /**< The Poly1305 context. */ + uint64_t aad_len; /**< The length (bytes) of the Additional Authenticated Data. */ + uint64_t ciphertext_len; /**< The length (bytes) of the ciphertext. */ + int state; /**< The current state of the context. */ + mbedtls_chachapoly_mode_t mode; /**< Cipher mode (encrypt or decrypt). */ +} +mbedtls_chachapoly_context; + +#else /* !MBEDTLS_CHACHAPOLY_ALT */ +#include "chachapoly_alt.h" +#endif /* !MBEDTLS_CHACHAPOLY_ALT */ + +/** + * \brief This function initializes the specified ChaCha20-Poly1305 context. + * + * It must be the first API called before using + * the context. It must be followed by a call to + * \c mbedtls_chachapoly_setkey() before any operation can be + * done, and to \c mbedtls_chachapoly_free() once all + * operations with that context have been finished. + * + * In order to encrypt or decrypt full messages at once, for + * each message you should make a single call to + * \c mbedtls_chachapoly_crypt_and_tag() or + * \c mbedtls_chachapoly_auth_decrypt(). + * + * In order to encrypt messages piecewise, for each + * message you should make a call to + * \c mbedtls_chachapoly_starts(), then 0 or more calls to + * \c mbedtls_chachapoly_update_aad(), then 0 or more calls to + * \c mbedtls_chachapoly_update(), then one call to + * \c mbedtls_chachapoly_finish(). + * + * \warning Decryption with the piecewise API is discouraged! Always + * use \c mbedtls_chachapoly_auth_decrypt() when possible! + * + * If however this is not possible because the data is too + * large to fit in memory, you need to: + * + * - call \c mbedtls_chachapoly_starts() and (if needed) + * \c mbedtls_chachapoly_update_aad() as above, + * - call \c mbedtls_chachapoly_update() multiple times and + * ensure its output (the plaintext) is NOT used in any other + * way than placing it in temporary storage at this point, + * - call \c mbedtls_chachapoly_finish() to compute the + * authentication tag and compared it in constant time to the + * tag received with the ciphertext. + * + * If the tags are not equal, you must immediately discard + * all previous outputs of \c mbedtls_chachapoly_update(), + * otherwise you can now safely use the plaintext. + * + * \param ctx The ChachaPoly context to initialize. Must not be \c NULL. + */ +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function releases and clears the specified + * ChaCha20-Poly1305 context. + * + * \param ctx The ChachaPoly context to clear. This may be \c NULL, in which + * case this function is a no-op. + */ +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function sets the ChaCha20-Poly1305 + * symmetric encryption key. + * + * \param ctx The ChaCha20-Poly1305 context to which the key should be + * bound. This must be initialized. + * \param key The \c 256 Bit (\c 32 Bytes) key. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function starts a ChaCha20-Poly1305 encryption or + * decryption operation. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \note If the context is being used for AAD only (no data to + * encrypt or decrypt) then \p mode can be set to any value. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context. This must be initialized + * and bound to a key. + * \param nonce The nonce/IV to use for the message. + * This must be a redable buffer of length \c 12 Bytes. + * \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or + * #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning). + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ); + +/** + * \brief This function feeds additional data to be authenticated + * into an ongoing ChaCha20-Poly1305 operation. + * + * The Additional Authenticated Data (AAD), also called + * Associated Data (AD) is only authenticated but not + * encrypted nor included in the encrypted output. It is + * usually transmitted separately from the ciphertext or + * computed locally by each party. + * + * \note This function is called before data is encrypted/decrypted. + * I.e. call this function to process the AAD before calling + * \c mbedtls_chachapoly_update(). + * + * You may call this function multiple times to process + * an arbitrary amount of AAD. It is permitted to call + * this function 0 times, if no AAD is used. + * + * This function cannot be called any more if data has + * been processed by \c mbedtls_chachapoly_update(), + * or if the context has been finished. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context. This must be initialized + * and bound to a key. + * \param aad_len The length in Bytes of the AAD. The length has no + * restrictions. + * \param aad Buffer containing the AAD. + * This pointer can be \c NULL if `aad_len == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx or \p aad are NULL. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operations has not been started or has been + * finished, or if the AAD has been finished. + */ +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ); + +/** + * \brief Thus function feeds data to be encrypted or decrypted + * into an on-going ChaCha20-Poly1305 + * operation. + * + * The direction (encryption or decryption) depends on the + * mode that was given when calling + * \c mbedtls_chachapoly_starts(). + * + * You may call this function multiple times to process + * an arbitrary amount of data. It is permitted to call + * this function 0 times, if no data is to be encrypted + * or decrypted. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. + * \param len The length (in bytes) of the data to encrypt or decrypt. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be \c NULL if `len == 0`. + * \param output The buffer to where the encrypted or decrypted data is + * written. This must be able to hold \p len bytes. + * This pointer can be \c NULL if `len == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finished the ChaCha20-Poly1305 operation and + * generates the MAC (authentication tag). + * + * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. + * \param mac The buffer to where the 128-bit (16 bytes) MAC is written. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated encryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * This must be initialized. + * \param length The length (in bytes) of the data to encrypt or decrypt. + * \param nonce The 96-bit (12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated + * data (AAD). This pointer can be \c NULL if `aad_len == 0`. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be \c NULL if `ilen == 0`. + * \param output The buffer to where the encrypted or decrypted data + * is written. This pointer can be \c NULL if `ilen == 0`. + * \param tag The buffer to where the computed 128-bit (16 bytes) MAC + * is written. This must not be \c NULL. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated decryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * \param length The length (in Bytes) of the data to decrypt. + * \param nonce The \c 96 Bit (\c 12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated data (AAD). + * This pointer can be \c NULL if `aad_len == 0`. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param tag The buffer holding the authentication tag. + * This must be a readable buffer of length \c 16 Bytes. + * \param input The buffer containing the data to decrypt. + * This pointer can be \c NULL if `ilen == 0`. + * \param output The buffer to where the decrypted data is written. + * This pointer can be \c NULL if `ilen == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED + * if the data was not authentic. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20-Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chachapoly_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHAPOLY_H */ diff --git a/external/mbedtls/include/mbedtls/check_config.h b/external/mbedtls/include/mbedtls/check_config.h new file mode 100644 index 0000000..2bbd7a8 --- /dev/null +++ b/external/mbedtls/include/mbedtls/check_config.h @@ -0,0 +1,774 @@ +/** + * \file check_config.h + * + * \brief Consistency checks for configuration options + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * It is recommended to include this file from your config.h + * in order to catch dependency issues early. + */ + +#ifndef MBEDTLS_CHECK_CONFIG_H +#define MBEDTLS_CHECK_CONFIG_H + +/* + * We assume CHAR_BIT is 8 in many places. In practice, this is true on our + * target platforms, so not an issue, but let's just be extra sure. + */ +#include +#if CHAR_BIT != 8 +#error "mbed TLS requires a platform with 8-bit chars" +#endif + +#if defined(_WIN32) +#if !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_C is required on Windows" +#endif + +/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as + * it would confuse config.pl. */ +#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif +#endif /* _WIN32 */ + +#if defined(TARGET_LIKE_MBED) && \ + ( defined(MBEDTLS_NET_C) || defined(MBEDTLS_TIMING_C) ) +#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS" +#endif + +#if defined(MBEDTLS_DEPRECATED_WARNING) && \ + !defined(__GNUC__) && !defined(__clang__) +#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) +#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" +#endif + +#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_AESNI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) +#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) +#error "MBEDTLS_DHM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) && !defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CMAC_C) && \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) +#error "MBEDTLS_CMAC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_NIST_KW_C) && \ + ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) ) +#error "MBEDTLS_NIST_KW_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) +#error "MBEDTLS_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + ( !defined(MBEDTLS_ECP_C) || \ + !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_ASN1_WRITE_C) ) +#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECJPAKE_C) && \ + ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + ( defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \ + defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \ + defined(MBEDTLS_ECDSA_SIGN_ALT) || \ + defined(MBEDTLS_ECDSA_VERIFY_ALT) || \ + defined(MBEDTLS_ECDSA_GENKEY_ALT) || \ + defined(MBEDTLS_ECP_INTERNAL_ALT) || \ + defined(MBEDTLS_ECP_ALT) ) +#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative ECP implementation" +#endif + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) +#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ + !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) ) ) +#error "MBEDTLS_ECP_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && !( \ + defined(MBEDTLS_ECP_ALT) || \ + defined(MBEDTLS_CTR_DRBG_C) || \ + defined(MBEDTLS_HMAC_DRBG_C) || \ + defined(MBEDTLS_SHA512_C) || \ + defined(MBEDTLS_SHA256_C) || \ + defined(MBEDTLS_ECP_NO_INTERNAL_RNG)) +#error "MBEDTLS_ECP_C requires a DRBG or SHA-2 module unless MBEDTLS_ECP_NO_INTERNAL_RNG is defined or an alternative implementation is used" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA256_C)) +#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ + defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ + && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" +#endif + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define MBEDTLS_HAS_MEMSAN +#endif +#endif +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) && !defined(MBEDTLS_HAS_MEMSAN) +#error "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer" +#endif +#undef MBEDTLS_HAS_MEMSAN + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ + defined(MBEDTLS_HAVEGE_C) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" +#endif + +#if defined(MBEDTLS_GCM_C) && ( \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) ) +#error "MBEDTLS_GCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) +#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HKDF_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) +#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ + !defined(MBEDTLS_ECDH_C) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + ( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) +#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_C) && \ + ( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) ) +#error "MBEDTLS_PK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS11_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PKCS11_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ + defined(MBEDTLS_PLATFORM_EXIT_ALT) ) +#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ + defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_FREE) +#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_CALLOC) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) +#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ + defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ + defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ + !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ + !defined(MBEDTLS_PLATFORM_EXIT_ALT) +#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ + ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ + !defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) +#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ + !defined(MBEDTLS_ENTROPY_NV_SEED) +#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) ) +#error "MBEDTLS_RSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" +#endif + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) ) +#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \ + !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +#if (defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \ + !(defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ) +#error "One or more versions of the TLS protocol are enabled " \ + "but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \ + !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (!defined(MBEDTLS_SSL_PROTO_SSL3) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2)) +#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) && !defined(MBEDTLS_SSL_PROTO_TLS1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_TLS1) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_SSL_PROTO_TLS1_1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && (!defined(MBEDTLS_SSL_PROTO_TLS1) || \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1))) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) +#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ + !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \ + !defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1) +#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + !defined(MBEDTLS_X509_CRT_PARSE_C) +#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_THREADING_PTHREAD) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_ALT) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_C defined, single threading implementation required" +#endif +#undef MBEDTLS_THREADING_IMPL + +#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) +#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_PK_PARSE_C) ) +#error "MBEDTLS_X509_USE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ + !defined(MBEDTLS_PK_WRITE_C) ) +#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CERTS_C) && !defined(MBEDTLS_X509_USE_C) +#error "MBEDTLS_CERTS_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) +#error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" +#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ + +#if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \ + defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" +#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ + +/* + * Avoid warning from -pedantic. This is a convenient place for this + * workaround since this is included by every single file before the + * #if defined(MBEDTLS_xxx_C) that results in empty translation units. + */ +typedef int mbedtls_iso_c_forbids_empty_translation_units; + +#endif /* MBEDTLS_CHECK_CONFIG_H */ diff --git a/external/mbedtls/include/mbedtls/cipher.h b/external/mbedtls/include/mbedtls/cipher.h new file mode 100644 index 0000000..1f41b52 --- /dev/null +++ b/external/mbedtls/include/mbedtls/cipher.h @@ -0,0 +1,897 @@ +/** + * \file cipher.h + * + * \brief This file contains an abstraction interface for use with the cipher + * primitives provided by the library. It provides a common interface to all of + * the available cipher operations. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_CIPHER_H +#define MBEDTLS_CIPHER_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include "platform_util.h" + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +#define MBEDTLS_CIPHER_MODE_AEAD +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_CIPHER_MODE_WITH_PADDING +#endif + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + defined(MBEDTLS_CHACHA20_C) +#define MBEDTLS_CIPHER_MODE_STREAM +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters. */ +#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ +#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ +#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid. For example, because it was freed. */ + +/* MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */ + +#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ +#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Supported cipher types. + * + * \warning RC4 and DES are considered weak ciphers and their use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_ID_NONE = 0, /**< Placeholder to mark the end of cipher ID lists. */ + MBEDTLS_CIPHER_ID_NULL, /**< The identity cipher, treated as a stream cipher. */ + MBEDTLS_CIPHER_ID_AES, /**< The AES cipher. */ + MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. */ + MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. */ + MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ + MBEDTLS_CIPHER_ID_BLOWFISH, /**< The Blowfish cipher. */ + MBEDTLS_CIPHER_ID_ARC4, /**< The RC4 cipher. */ + MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */ + MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */ +} mbedtls_cipher_id_t; + +/** + * \brief Supported {cipher type, cipher mode} pairs. + * + * \warning RC4 and DES are considered weak ciphers and their use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_NONE = 0, /**< Placeholder to mark the end of cipher-pair lists. */ + MBEDTLS_CIPHER_NULL, /**< The identity stream cipher. */ + MBEDTLS_CIPHER_AES_128_ECB, /**< AES cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_AES_192_ECB, /**< AES cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_AES_256_ECB, /**< AES cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_AES_128_CBC, /**< AES cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_AES_192_CBC, /**< AES cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_AES_256_CBC, /**< AES cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_AES_128_CFB128, /**< AES cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_192_CFB128, /**< AES cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_256_CFB128, /**< AES cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_128_CTR, /**< AES cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_AES_192_CTR, /**< AES cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_AES_256_CTR, /**< AES cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_AES_128_GCM, /**< AES cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_AES_192_GCM, /**< AES cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_AES_256_GCM, /**< AES cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_ECB, /**< Camellia cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_ECB, /**< Camellia cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_ECB, /**< Camellia cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CBC, /**< Camellia cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CBC, /**< Camellia cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CBC, /**< Camellia cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, /**< Camellia cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, /**< Camellia cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, /**< Camellia cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CTR, /**< Camellia cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CTR, /**< Camellia cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CTR, /**< Camellia cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_GCM, /**< Camellia cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_GCM, /**< Camellia cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_GCM, /**< Camellia cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_DES_ECB, /**< DES cipher with ECB mode. */ + MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. */ + MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. */ + MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. */ + MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. */ + MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. */ + MBEDTLS_CIPHER_BLOWFISH_ECB, /**< Blowfish cipher with ECB mode. */ + MBEDTLS_CIPHER_BLOWFISH_CBC, /**< Blowfish cipher with CBC mode. */ + MBEDTLS_CIPHER_BLOWFISH_CFB64, /**< Blowfish cipher with CFB64 mode. */ + MBEDTLS_CIPHER_BLOWFISH_CTR, /**< Blowfish cipher with CTR mode. */ + MBEDTLS_CIPHER_ARC4_128, /**< RC4 cipher with 128-bit mode. */ + MBEDTLS_CIPHER_AES_128_CCM, /**< AES cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_AES_192_CCM, /**< AES cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_AES_256_CCM, /**< AES cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_ARIA_128_ECB, /**< Aria cipher with 128-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_192_ECB, /**< Aria cipher with 192-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_256_ECB, /**< Aria cipher with 256-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_128_CBC, /**< Aria cipher with 128-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_192_CBC, /**< Aria cipher with 192-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_256_CBC, /**< Aria cipher with 256-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_128_CFB128, /**< Aria cipher with 128-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_192_CFB128, /**< Aria cipher with 192-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_256_CFB128, /**< Aria cipher with 256-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_128_CTR, /**< Aria cipher with 128-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_192_CTR, /**< Aria cipher with 192-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_256_CTR, /**< Aria cipher with 256-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_128_GCM, /**< Aria cipher with 128-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_192_GCM, /**< Aria cipher with 192-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_256_GCM, /**< Aria cipher with 256-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */ + MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */ + MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */ +} mbedtls_cipher_type_t; + +/** Supported cipher modes. */ +typedef enum { + MBEDTLS_MODE_NONE = 0, /**< None. */ + MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */ + MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */ + MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */ + MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */ + MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */ + MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */ + MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */ + MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */ + MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */ + MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */ +} mbedtls_cipher_mode_t; + +/** Supported cipher padding types. */ +typedef enum { + MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */ + MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */ + MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */ + MBEDTLS_PADDING_ZEROS, /**< Zero padding (not reversible). */ + MBEDTLS_PADDING_NONE, /**< Never pad (full blocks only). */ +} mbedtls_cipher_padding_t; + +/** Type of operation. */ +typedef enum { + MBEDTLS_OPERATION_NONE = -1, + MBEDTLS_DECRYPT = 0, + MBEDTLS_ENCRYPT, +} mbedtls_operation_t; + +enum { + /** Undefined key length. */ + MBEDTLS_KEY_LENGTH_NONE = 0, + /** Key length, in bits (including parity), for DES keys. */ + MBEDTLS_KEY_LENGTH_DES = 64, + /** Key length in bits, including parity, for DES in two-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE = 128, + /** Key length in bits, including parity, for DES in three-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, +}; + +/** Maximum length of any IV, in Bytes. */ +#define MBEDTLS_MAX_IV_LENGTH 16 +/** Maximum block size of any cipher, in Bytes. */ +#define MBEDTLS_MAX_BLOCK_LENGTH 16 + +/** + * Base cipher information (opaque struct). + */ +typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; + +/** + * CMAC context (opaque struct). + */ +typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; + +/** + * Cipher information. Allows calling cipher functions + * in a generic way. + */ +typedef struct mbedtls_cipher_info_t +{ + /** Full cipher identifier. For example, + * MBEDTLS_CIPHER_AES_256_CBC. + */ + mbedtls_cipher_type_t type; + + /** The cipher mode. For example, MBEDTLS_MODE_CBC. */ + mbedtls_cipher_mode_t mode; + + /** The cipher key length, in bits. This is the + * default length for variable sized ciphers. + * Includes parity bits for ciphers like DES. + */ + unsigned int key_bitlen; + + /** Name of the cipher. */ + const char * name; + + /** IV or nonce size, in Bytes. + * For ciphers that accept variable IV sizes, + * this is the recommended size. + */ + unsigned int iv_size; + + /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and + * MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the + * cipher supports variable IV or variable key sizes, respectively. + */ + int flags; + + /** The block size, in Bytes. */ + unsigned int block_size; + + /** Struct for base cipher information and functions. */ + const mbedtls_cipher_base_t *base; + +} mbedtls_cipher_info_t; + +/** + * Generic cipher context. + */ +typedef struct mbedtls_cipher_context_t +{ + /** Information about the associated cipher. */ + const mbedtls_cipher_info_t *cipher_info; + + /** Key length to use. */ + int key_bitlen; + + /** Operation that the key of the context has been + * initialized for. + */ + mbedtls_operation_t operation; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /** Padding functions to use, if relevant for + * the specific cipher mode. + */ + void (*add_padding)( unsigned char *output, size_t olen, size_t data_len ); + int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len ); +#endif + + /** Buffer for input that has not been processed yet. */ + unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH]; + + /** Number of Bytes that have not been processed yet. */ + size_t unprocessed_len; + + /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number + * for XTS-mode. */ + unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; + + /** IV size in Bytes, for ciphers with variable-length IVs. */ + size_t iv_size; + + /** The cipher-specific context. */ + void *cipher_ctx; + +#if defined(MBEDTLS_CMAC_C) + /** CMAC-specific context. */ + mbedtls_cmac_context_t *cmac_ctx; +#endif +} mbedtls_cipher_context_t; + +/** + * \brief This function retrieves the list of ciphers supported by the generic + * cipher module. + * + * \return A statically-allocated array of ciphers. The last entry + * is zero. + */ +const int *mbedtls_cipher_list( void ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher name. + * + * \param cipher_name Name of the cipher to search for. This must not be + * \c NULL. + * + * \return The cipher information structure associated with the + * given \p cipher_name. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher type. + * + * \param cipher_type Type of the cipher to search for. + * + * \return The cipher information structure associated with the + * given \p cipher_type. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher ID, + * key size and mode. + * + * \param cipher_id The ID of the cipher to search for. For example, + * #MBEDTLS_CIPHER_ID_AES. + * \param key_bitlen The length of the key in bits. + * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC. + * + * \return The cipher information structure associated with the + * given \p cipher_id. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ); + +/** + * \brief This function initializes a \p cipher_context as NONE. + * + * \param ctx The context to be initialized. This must not be \c NULL. + */ +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function frees and clears the cipher-specific + * context of \p ctx. Freeing \p ctx itself remains the + * responsibility of the caller. + * + * \param ctx The context to be freed. If this is \c NULL, the + * function has no effect, otherwise this must point to an + * initialized context. + */ +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); + + +/** + * \brief This function initializes and fills the cipher-context + * structure with the appropriate values. It also clears + * the structure. + * + * \param ctx The context to initialize. This must be initialized. + * \param cipher_info The cipher to use. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context fails. + * + * \internal Currently, the function also clears the structure. + * In future versions, the caller will be required to call + * mbedtls_cipher_init() on the structure first. + */ +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info ); + +/** + * \brief This function returns the block size of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The block size of the underlying cipher. + * \return \c 0 if \p ctx has not been initialized. + */ +static inline unsigned int mbedtls_cipher_get_block_size( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) + return 0; + + return ctx->cipher_info->block_size; +} + +/** + * \brief This function returns the mode of operation for + * the cipher. For example, MBEDTLS_MODE_CBC. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The mode of operation. + * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, MBEDTLS_MODE_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_MODE_NONE; + + return ctx->cipher_info->mode; +} + +/** + * \brief This function returns the size of the IV or nonce + * of the cipher, in Bytes. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The recommended IV size if no IV has been set. + * \return \c 0 for ciphers not using an IV or a nonce. + * \return The actual size if an IV has been set. + */ +static inline int mbedtls_cipher_get_iv_size( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) + return 0; + + if( ctx->iv_size != 0 ) + return (int) ctx->iv_size; + + return (int) ctx->cipher_info->iv_size; +} + +/** + * \brief This function returns the type of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The type of the cipher. + * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_CIPHER_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_CIPHER_NONE; + + return ctx->cipher_info->type; +} + +/** + * \brief This function returns the name of the given cipher + * as a string. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The name of the cipher. + * \return NULL if \p ctx has not been not initialized. + */ +static inline const char *mbedtls_cipher_get_name( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) + return 0; + + return ctx->cipher_info->name; +} + +/** + * \brief This function returns the key length of the cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The key length of the cipher in bits. + * \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been + * initialized. + */ +static inline int mbedtls_cipher_get_key_bitlen( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_KEY_LENGTH_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_KEY_LENGTH_NONE; + + return (int) ctx->cipher_info->key_bitlen; +} + +/** + * \brief This function returns the operation of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_operation_t mbedtls_cipher_get_operation( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_OPERATION_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_OPERATION_NONE; + + return ctx->operation; +} + +/** + * \brief This function sets the key to use with the given context. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param key The key to use. This must be a readable buffer of at + * least \p key_bitlen Bits. + * \param key_bitlen The key length to use, in Bits. + * \param operation The operation that the key will be used for: + * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, + const unsigned char *key, + int key_bitlen, + const mbedtls_operation_t operation ); + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +/** + * \brief This function sets the padding mode, for cipher modes + * that use padding. + * + * The default passing mode is PKCS7 padding. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param mode The padding mode. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + * if the selected padding mode is not supported. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode + * does not support padding. + */ +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, + mbedtls_cipher_padding_t mode ); +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +/** + * \brief This function sets the initialization vector (IV) + * or nonce. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, this function has no effect. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This + * must be a readable buffer of at least \p iv_len Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + */ +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, + size_t iv_len ); + +/** + * \brief This function resets the cipher state. + * + * \param ctx The generic cipher context. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + */ +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/** + * \brief This function adds additional data for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called exactly once, after + * mbedtls_cipher_reset(). + * + * \param ctx The generic cipher context. This must be initialized. + * \param ad The additional data to use. This must be a readable + * buffer of at least \p ad_len Bytes. + * \param ad_len the Length of \p ad Bytes. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ); +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/** + * \brief The generic cipher update function. It encrypts or + * decrypts using the given cipher context. Writes as + * many block-sized blocks of data as possible to output. + * Any data that cannot be written immediately is either + * added to the next block, or flushed when + * mbedtls_cipher_finish() is called. + * Exception: For MBEDTLS_MODE_ECB, expects a single block + * in size. For example, 16 Bytes for AES. + * + * \note If the underlying cipher is used in GCM mode, all calls + * to this function, except for the last one before + * mbedtls_cipher_finish(), must have \p ilen as a + * multiple of the block size of the cipher. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ); + +/** + * \brief The generic cipher finalization function. If data still + * needs to be flushed from an incomplete block, the data + * contained in it is padded to the size of + * the last block, and written to the \p output buffer. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param output The buffer to write data to. This needs to be a writable + * buffer of at least \p block_size Bytes. + * \param olen The length of the data written to the \p output buffer. + * This may not be \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/** + * \brief This function writes a tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. This must be initialized, + * bound to a key, and have just completed a cipher + * operation through mbedtls_cipher_finish() the tag for + * which should be written. + * \param tag The buffer to write the tag to. This must be a writable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to write. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function checks the tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. This must be initialized. + * \param tag The buffer holding the tag. This must be a readable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to check. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/** + * \brief The generic all-in-one encryption/decryption function, + * for all ciphers except AEAD constructs. + * + * \param ctx The generic cipher context. This must be initialized. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size + * IV. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, use \p iv = NULL and \p iv_len = 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/** + * \brief The generic autenticated encryption (AEAD) function. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to authenticate. This must be a + * readable buffer of at least \p ad_len Bytes. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be able to + * hold at least \p ilen Bytes. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * \param tag The buffer for the authentication tag. This must be a + * writable buffer of at least \p tag_len Bytes. + * \param tag_len The desired length of the authentication tag. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ); + +/** + * \brief The generic autenticated decryption (AEAD) function. + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext being + * used, making this interface safer. + * + * \param ctx The generic cipher context. This must be initialized and + * and bound to a key. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to be authenticated. This must be a + * readable buffer of at least \p ad_len Bytes. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. + * This must be able to hold at least \p ilen Bytes. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * \param tag The buffer holding the authentication tag. This must be + * a readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication tag. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_H */ diff --git a/external/mbedtls/include/mbedtls/cipher_internal.h b/external/mbedtls/include/mbedtls/cipher_internal.h new file mode 100644 index 0000000..88282ec --- /dev/null +++ b/external/mbedtls/include/mbedtls/cipher_internal.h @@ -0,0 +1,150 @@ +/** + * \file cipher_internal.h + * + * \brief Cipher wrappers. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_CIPHER_WRAP_H +#define MBEDTLS_CIPHER_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Base cipher information. The non-mode specific functions and values. + */ +struct mbedtls_cipher_base_t +{ + /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ + mbedtls_cipher_id_t cipher; + + /** Encrypt using ECB */ + int (*ecb_func)( void *ctx, mbedtls_operation_t mode, + const unsigned char *input, unsigned char *output ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /** Encrypt using CBC */ + int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /** Encrypt using CFB (Full length) */ + int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /** Encrypt using OFB (Full length) */ + int (*ofb_func)( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, + const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /** Encrypt using CTR */ + int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + /** Encrypt or decrypt using XTS. */ + int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length, + const unsigned char data_unit[16], + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + /** Encrypt using STREAM */ + int (*stream_func)( void *ctx, size_t length, + const unsigned char *input, unsigned char *output ); +#endif + + /** Set key for encryption purposes */ + int (*setkey_enc_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen ); + + /** Set key for decryption purposes */ + int (*setkey_dec_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +}; + +typedef struct +{ + mbedtls_cipher_type_t type; + const mbedtls_cipher_info_t *info; +} mbedtls_cipher_definition_t; + +extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; + +extern int mbedtls_cipher_supported[]; + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_WRAP_H */ diff --git a/external/mbedtls/include/mbedtls/cmac.h b/external/mbedtls/include/mbedtls/cmac.h new file mode 100644 index 0000000..5a7c9b2 --- /dev/null +++ b/external/mbedtls/include/mbedtls/cmac.h @@ -0,0 +1,238 @@ +/** + * \file cmac.h + * + * \brief This file contains CMAC definitions and functions. + * + * The Cipher-based Message Authentication Code (CMAC) Mode for + * Authentication is defined in RFC-4493: The AES-CMAC Algorithm. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_CMAC_H +#define MBEDTLS_CMAC_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A /**< CMAC hardware accelerator failed. */ + +#define MBEDTLS_AES_BLOCK_SIZE 16 +#define MBEDTLS_DES3_BLOCK_SIZE 8 + +#if defined(MBEDTLS_AES_C) +#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /**< The longest block used by CMAC is that of AES. */ +#else +#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /**< The longest block used by CMAC is that of 3DES. */ +#endif + +#if !defined(MBEDTLS_CMAC_ALT) + +/** + * The CMAC context structure. + */ +struct mbedtls_cmac_context_t +{ + /** The internal state of the CMAC algorithm. */ + unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** Unprocessed data - either data that was not block aligned and is still + * pending processing, or the final block. */ + unsigned char unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** The length of data pending processing. */ + size_t unprocessed_len; +}; + +#else /* !MBEDTLS_CMAC_ALT */ +#include "cmac_alt.h" +#endif /* !MBEDTLS_CMAC_ALT */ + +/** + * \brief This function sets the CMAC key, and prepares to authenticate + * the input data. + * Must be called with an initialized cipher context. + * + * \param ctx The cipher context used for the CMAC operation, initialized + * as one of the following types: MBEDTLS_CIPHER_AES_128_ECB, + * MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB, + * or MBEDTLS_CIPHER_DES_EDE3_ECB. + * \param key The CMAC key. + * \param keybits The length of the CMAC key in bits. + * Must be supported by the cipher. + * + * \return \c 0 on success. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ); + +/** + * \brief This function feeds an input buffer into an ongoing CMAC + * computation. + * + * It is called between mbedtls_cipher_cmac_starts() or + * mbedtls_cipher_cmac_reset(), and mbedtls_cipher_cmac_finish(). + * Can be called repeatedly. + * + * \param ctx The cipher context used for the CMAC operation. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes the CMAC operation, and writes + * the result to the output buffer. + * + * It is called after mbedtls_cipher_cmac_update(). + * It can be followed by mbedtls_cipher_cmac_reset() and + * mbedtls_cipher_cmac_update(), or mbedtls_cipher_free(). + * + * \param ctx The cipher context used for the CMAC operation. + * \param output The output buffer for the CMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ); + +/** + * \brief This function prepares the authentication of another + * message with the same key as the previous CMAC + * operation. + * + * It is called after mbedtls_cipher_cmac_finish() + * and before mbedtls_cipher_cmac_update(). + * + * \param ctx The cipher context used for the CMAC operation. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function calculates the full generic CMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The CMAC result is calculated as + * output = generic CMAC(cmac key, input buffer). + * + * + * \param cipher_info The cipher information. + * \param key The CMAC key. + * \param keylen The length of the CMAC key in bits. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the generic CMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_AES_C) +/** + * \brief This function implements the AES-CMAC-PRF-128 pseudorandom + * function, as defined in + * RFC-4615: The Advanced Encryption Standard-Cipher-based + * Message Authentication Code-Pseudo-Random Function-128 + * (AES-CMAC-PRF-128) Algorithm for the Internet Key + * Exchange Protocol (IKE). + * + * \param key The key to use. + * \param key_len The key length in Bytes. + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * \param output The buffer holding the generated 16 Bytes of + * pseudorandom output. + * + * \return \c 0 on success. + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len, + const unsigned char *input, size_t in_len, + unsigned char output[16] ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) +/** + * \brief The CMAC checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_cmac_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CMAC_H */ diff --git a/external/mbedtls/include/mbedtls/compat-1.3.h b/external/mbedtls/include/mbedtls/compat-1.3.h new file mode 100644 index 0000000..45e5a1c --- /dev/null +++ b/external/mbedtls/include/mbedtls/compat-1.3.h @@ -0,0 +1,2556 @@ +/** + * \file compat-1.3.h + * + * \brief Compatibility definitions for using mbed TLS with client code written + * for the PolarSSL naming conventions. + * + * \deprecated Use the new names directly instead + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Including compat-1.3.h is deprecated" +#endif + +#ifndef MBEDTLS_COMPAT13_H +#define MBEDTLS_COMPAT13_H + +/* + * config.h options + */ +#if defined MBEDTLS_AESNI_C +#define POLARSSL_AESNI_C MBEDTLS_AESNI_C +#endif +#if defined MBEDTLS_AES_ALT +#define POLARSSL_AES_ALT MBEDTLS_AES_ALT +#endif +#if defined MBEDTLS_AES_C +#define POLARSSL_AES_C MBEDTLS_AES_C +#endif +#if defined MBEDTLS_AES_ROM_TABLES +#define POLARSSL_AES_ROM_TABLES MBEDTLS_AES_ROM_TABLES +#endif +#if defined MBEDTLS_ARC4_ALT +#define POLARSSL_ARC4_ALT MBEDTLS_ARC4_ALT +#endif +#if defined MBEDTLS_ARC4_C +#define POLARSSL_ARC4_C MBEDTLS_ARC4_C +#endif +#if defined MBEDTLS_ASN1_PARSE_C +#define POLARSSL_ASN1_PARSE_C MBEDTLS_ASN1_PARSE_C +#endif +#if defined MBEDTLS_ASN1_WRITE_C +#define POLARSSL_ASN1_WRITE_C MBEDTLS_ASN1_WRITE_C +#endif +#if defined MBEDTLS_BASE64_C +#define POLARSSL_BASE64_C MBEDTLS_BASE64_C +#endif +#if defined MBEDTLS_BIGNUM_C +#define POLARSSL_BIGNUM_C MBEDTLS_BIGNUM_C +#endif +#if defined MBEDTLS_BLOWFISH_ALT +#define POLARSSL_BLOWFISH_ALT MBEDTLS_BLOWFISH_ALT +#endif +#if defined MBEDTLS_BLOWFISH_C +#define POLARSSL_BLOWFISH_C MBEDTLS_BLOWFISH_C +#endif +#if defined MBEDTLS_CAMELLIA_ALT +#define POLARSSL_CAMELLIA_ALT MBEDTLS_CAMELLIA_ALT +#endif +#if defined MBEDTLS_CAMELLIA_C +#define POLARSSL_CAMELLIA_C MBEDTLS_CAMELLIA_C +#endif +#if defined MBEDTLS_CAMELLIA_SMALL_MEMORY +#define POLARSSL_CAMELLIA_SMALL_MEMORY MBEDTLS_CAMELLIA_SMALL_MEMORY +#endif +#if defined MBEDTLS_CCM_C +#define POLARSSL_CCM_C MBEDTLS_CCM_C +#endif +#if defined MBEDTLS_CERTS_C +#define POLARSSL_CERTS_C MBEDTLS_CERTS_C +#endif +#if defined MBEDTLS_CIPHER_C +#define POLARSSL_CIPHER_C MBEDTLS_CIPHER_C +#endif +#if defined MBEDTLS_CIPHER_MODE_CBC +#define POLARSSL_CIPHER_MODE_CBC MBEDTLS_CIPHER_MODE_CBC +#endif +#if defined MBEDTLS_CIPHER_MODE_CFB +#define POLARSSL_CIPHER_MODE_CFB MBEDTLS_CIPHER_MODE_CFB +#endif +#if defined MBEDTLS_CIPHER_MODE_CTR +#define POLARSSL_CIPHER_MODE_CTR MBEDTLS_CIPHER_MODE_CTR +#endif +#if defined MBEDTLS_CIPHER_NULL_CIPHER +#define POLARSSL_CIPHER_NULL_CIPHER MBEDTLS_CIPHER_NULL_CIPHER +#endif +#if defined MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#endif +#if defined MBEDTLS_CIPHER_PADDING_PKCS7 +#define POLARSSL_CIPHER_PADDING_PKCS7 MBEDTLS_CIPHER_PADDING_PKCS7 +#endif +#if defined MBEDTLS_CIPHER_PADDING_ZEROS +#define POLARSSL_CIPHER_PADDING_ZEROS MBEDTLS_CIPHER_PADDING_ZEROS +#endif +#if defined MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#endif +#if defined MBEDTLS_CTR_DRBG_C +#define POLARSSL_CTR_DRBG_C MBEDTLS_CTR_DRBG_C +#endif +#if defined MBEDTLS_DEBUG_C +#define POLARSSL_DEBUG_C MBEDTLS_DEBUG_C +#endif +#if defined MBEDTLS_DEPRECATED_REMOVED +#define POLARSSL_DEPRECATED_REMOVED MBEDTLS_DEPRECATED_REMOVED +#endif +#if defined MBEDTLS_DEPRECATED_WARNING +#define POLARSSL_DEPRECATED_WARNING MBEDTLS_DEPRECATED_WARNING +#endif +#if defined MBEDTLS_DES_ALT +#define POLARSSL_DES_ALT MBEDTLS_DES_ALT +#endif +#if defined MBEDTLS_DES_C +#define POLARSSL_DES_C MBEDTLS_DES_C +#endif +#if defined MBEDTLS_DHM_C +#define POLARSSL_DHM_C MBEDTLS_DHM_C +#endif +#if defined MBEDTLS_ECDH_C +#define POLARSSL_ECDH_C MBEDTLS_ECDH_C +#endif +#if defined MBEDTLS_ECDSA_C +#define POLARSSL_ECDSA_C MBEDTLS_ECDSA_C +#endif +#if defined MBEDTLS_ECDSA_DETERMINISTIC +#define POLARSSL_ECDSA_DETERMINISTIC MBEDTLS_ECDSA_DETERMINISTIC +#endif +#if defined MBEDTLS_ECP_C +#define POLARSSL_ECP_C MBEDTLS_ECP_C +#endif +#if defined MBEDTLS_ECP_DP_BP256R1_ENABLED +#define POLARSSL_ECP_DP_BP256R1_ENABLED MBEDTLS_ECP_DP_BP256R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_BP384R1_ENABLED +#define POLARSSL_ECP_DP_BP384R1_ENABLED MBEDTLS_ECP_DP_BP384R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_BP512R1_ENABLED +#define POLARSSL_ECP_DP_BP512R1_ENABLED MBEDTLS_ECP_DP_BP512R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define POLARSSL_ECP_DP_M255_ENABLED MBEDTLS_ECP_DP_CURVE25519_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define POLARSSL_ECP_DP_SECP192K1_ENABLED MBEDTLS_ECP_DP_SECP192K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define POLARSSL_ECP_DP_SECP192R1_ENABLED MBEDTLS_ECP_DP_SECP192R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define POLARSSL_ECP_DP_SECP224K1_ENABLED MBEDTLS_ECP_DP_SECP224K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define POLARSSL_ECP_DP_SECP224R1_ENABLED MBEDTLS_ECP_DP_SECP224R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define POLARSSL_ECP_DP_SECP256K1_ENABLED MBEDTLS_ECP_DP_SECP256K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define POLARSSL_ECP_DP_SECP256R1_ENABLED MBEDTLS_ECP_DP_SECP256R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define POLARSSL_ECP_DP_SECP384R1_ENABLED MBEDTLS_ECP_DP_SECP384R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define POLARSSL_ECP_DP_SECP521R1_ENABLED MBEDTLS_ECP_DP_SECP521R1_ENABLED +#endif +#if defined MBEDTLS_ECP_FIXED_POINT_OPTIM +#define POLARSSL_ECP_FIXED_POINT_OPTIM MBEDTLS_ECP_FIXED_POINT_OPTIM +#endif +#if defined MBEDTLS_ECP_MAX_BITS +#define POLARSSL_ECP_MAX_BITS MBEDTLS_ECP_MAX_BITS +#endif +#if defined MBEDTLS_ECP_NIST_OPTIM +#define POLARSSL_ECP_NIST_OPTIM MBEDTLS_ECP_NIST_OPTIM +#endif +#if defined MBEDTLS_ECP_WINDOW_SIZE +#define POLARSSL_ECP_WINDOW_SIZE MBEDTLS_ECP_WINDOW_SIZE +#endif +#if defined MBEDTLS_ENABLE_WEAK_CIPHERSUITES +#define POLARSSL_ENABLE_WEAK_CIPHERSUITES MBEDTLS_ENABLE_WEAK_CIPHERSUITES +#endif +#if defined MBEDTLS_ENTROPY_C +#define POLARSSL_ENTROPY_C MBEDTLS_ENTROPY_C +#endif +#if defined MBEDTLS_ENTROPY_FORCE_SHA256 +#define POLARSSL_ENTROPY_FORCE_SHA256 MBEDTLS_ENTROPY_FORCE_SHA256 +#endif +#if defined MBEDTLS_ERROR_C +#define POLARSSL_ERROR_C MBEDTLS_ERROR_C +#endif +#if defined MBEDTLS_ERROR_STRERROR_DUMMY +#define POLARSSL_ERROR_STRERROR_DUMMY MBEDTLS_ERROR_STRERROR_DUMMY +#endif +#if defined MBEDTLS_FS_IO +#define POLARSSL_FS_IO MBEDTLS_FS_IO +#endif +#if defined MBEDTLS_GCM_C +#define POLARSSL_GCM_C MBEDTLS_GCM_C +#endif +#if defined MBEDTLS_GENPRIME +#define POLARSSL_GENPRIME MBEDTLS_GENPRIME +#endif +#if defined MBEDTLS_HAVEGE_C +#define POLARSSL_HAVEGE_C MBEDTLS_HAVEGE_C +#endif +#if defined MBEDTLS_HAVE_ASM +#define POLARSSL_HAVE_ASM MBEDTLS_HAVE_ASM +#endif +#if defined MBEDTLS_HAVE_SSE2 +#define POLARSSL_HAVE_SSE2 MBEDTLS_HAVE_SSE2 +#endif +#if defined MBEDTLS_HAVE_TIME +#define POLARSSL_HAVE_TIME MBEDTLS_HAVE_TIME +#endif +#if defined MBEDTLS_HMAC_DRBG_C +#define POLARSSL_HMAC_DRBG_C MBEDTLS_HMAC_DRBG_C +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_INPUT +#define POLARSSL_HMAC_DRBG_MAX_INPUT MBEDTLS_HMAC_DRBG_MAX_INPUT +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_REQUEST +#define POLARSSL_HMAC_DRBG_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT +#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT +#endif +#if defined MBEDTLS_HMAC_DRBG_RESEED_INTERVAL +#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL MBEDTLS_HMAC_DRBG_RESEED_INTERVAL +#endif +#if defined MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#endif +#if defined MBEDTLS_MD2_ALT +#define POLARSSL_MD2_ALT MBEDTLS_MD2_ALT +#endif +#if defined MBEDTLS_MD2_C +#define POLARSSL_MD2_C MBEDTLS_MD2_C +#endif +#if defined MBEDTLS_MD2_PROCESS_ALT +#define POLARSSL_MD2_PROCESS_ALT MBEDTLS_MD2_PROCESS_ALT +#endif +#if defined MBEDTLS_MD4_ALT +#define POLARSSL_MD4_ALT MBEDTLS_MD4_ALT +#endif +#if defined MBEDTLS_MD4_C +#define POLARSSL_MD4_C MBEDTLS_MD4_C +#endif +#if defined MBEDTLS_MD4_PROCESS_ALT +#define POLARSSL_MD4_PROCESS_ALT MBEDTLS_MD4_PROCESS_ALT +#endif +#if defined MBEDTLS_MD5_ALT +#define POLARSSL_MD5_ALT MBEDTLS_MD5_ALT +#endif +#if defined MBEDTLS_MD5_C +#define POLARSSL_MD5_C MBEDTLS_MD5_C +#endif +#if defined MBEDTLS_MD5_PROCESS_ALT +#define POLARSSL_MD5_PROCESS_ALT MBEDTLS_MD5_PROCESS_ALT +#endif +#if defined MBEDTLS_MD_C +#define POLARSSL_MD_C MBEDTLS_MD_C +#endif +#if defined MBEDTLS_MEMORY_ALIGN_MULTIPLE +#define POLARSSL_MEMORY_ALIGN_MULTIPLE MBEDTLS_MEMORY_ALIGN_MULTIPLE +#endif +#if defined MBEDTLS_MEMORY_BACKTRACE +#define POLARSSL_MEMORY_BACKTRACE MBEDTLS_MEMORY_BACKTRACE +#endif +#if defined MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define POLARSSL_MEMORY_BUFFER_ALLOC_C MBEDTLS_MEMORY_BUFFER_ALLOC_C +#endif +#if defined MBEDTLS_MEMORY_DEBUG +#define POLARSSL_MEMORY_DEBUG MBEDTLS_MEMORY_DEBUG +#endif +#if defined MBEDTLS_MPI_MAX_SIZE +#define POLARSSL_MPI_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif +#if defined MBEDTLS_MPI_WINDOW_SIZE +#define POLARSSL_MPI_WINDOW_SIZE MBEDTLS_MPI_WINDOW_SIZE +#endif +#if defined MBEDTLS_NET_C +#define POLARSSL_NET_C MBEDTLS_NET_C +#endif +#if defined MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#endif +#if defined MBEDTLS_NO_PLATFORM_ENTROPY +#define POLARSSL_NO_PLATFORM_ENTROPY MBEDTLS_NO_PLATFORM_ENTROPY +#endif +#if defined MBEDTLS_OID_C +#define POLARSSL_OID_C MBEDTLS_OID_C +#endif +#if defined MBEDTLS_PADLOCK_C +#define POLARSSL_PADLOCK_C MBEDTLS_PADLOCK_C +#endif +#if defined MBEDTLS_PEM_PARSE_C +#define POLARSSL_PEM_PARSE_C MBEDTLS_PEM_PARSE_C +#endif +#if defined MBEDTLS_PEM_WRITE_C +#define POLARSSL_PEM_WRITE_C MBEDTLS_PEM_WRITE_C +#endif +#if defined MBEDTLS_PKCS11_C +#define POLARSSL_PKCS11_C MBEDTLS_PKCS11_C +#endif +#if defined MBEDTLS_PKCS12_C +#define POLARSSL_PKCS12_C MBEDTLS_PKCS12_C +#endif +#if defined MBEDTLS_PKCS1_V15 +#define POLARSSL_PKCS1_V15 MBEDTLS_PKCS1_V15 +#endif +#if defined MBEDTLS_PKCS1_V21 +#define POLARSSL_PKCS1_V21 MBEDTLS_PKCS1_V21 +#endif +#if defined MBEDTLS_PKCS5_C +#define POLARSSL_PKCS5_C MBEDTLS_PKCS5_C +#endif +#if defined MBEDTLS_PK_C +#define POLARSSL_PK_C MBEDTLS_PK_C +#endif +#if defined MBEDTLS_PK_PARSE_C +#define POLARSSL_PK_PARSE_C MBEDTLS_PK_PARSE_C +#endif +#if defined MBEDTLS_PK_PARSE_EC_EXTENDED +#define POLARSSL_PK_PARSE_EC_EXTENDED MBEDTLS_PK_PARSE_EC_EXTENDED +#endif +#if defined MBEDTLS_PK_RSA_ALT_SUPPORT +#define POLARSSL_PK_RSA_ALT_SUPPORT MBEDTLS_PK_RSA_ALT_SUPPORT +#endif +#if defined MBEDTLS_PK_WRITE_C +#define POLARSSL_PK_WRITE_C MBEDTLS_PK_WRITE_C +#endif +#if defined MBEDTLS_PLATFORM_C +#define POLARSSL_PLATFORM_C MBEDTLS_PLATFORM_C +#endif +#if defined MBEDTLS_PLATFORM_EXIT_ALT +#define POLARSSL_PLATFORM_EXIT_ALT MBEDTLS_PLATFORM_EXIT_ALT +#endif +#if defined MBEDTLS_PLATFORM_EXIT_MACRO +#define POLARSSL_PLATFORM_EXIT_MACRO MBEDTLS_PLATFORM_EXIT_MACRO +#endif +#if defined MBEDTLS_PLATFORM_FPRINTF_ALT +#define POLARSSL_PLATFORM_FPRINTF_ALT MBEDTLS_PLATFORM_FPRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_FPRINTF_MACRO +#define POLARSSL_PLATFORM_FPRINTF_MACRO MBEDTLS_PLATFORM_FPRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_FREE_MACRO +#define POLARSSL_PLATFORM_FREE_MACRO MBEDTLS_PLATFORM_FREE_MACRO +#endif +#if defined MBEDTLS_PLATFORM_MEMORY +#define POLARSSL_PLATFORM_MEMORY MBEDTLS_PLATFORM_MEMORY +#endif +#if defined MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#endif +#if defined MBEDTLS_PLATFORM_PRINTF_ALT +#define POLARSSL_PLATFORM_PRINTF_ALT MBEDTLS_PLATFORM_PRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_PRINTF_MACRO +#define POLARSSL_PLATFORM_PRINTF_MACRO MBEDTLS_PLATFORM_PRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_SNPRINTF_ALT +#define POLARSSL_PLATFORM_SNPRINTF_ALT MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_SNPRINTF_MACRO +#define POLARSSL_PLATFORM_SNPRINTF_MACRO MBEDTLS_PLATFORM_SNPRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_STD_EXIT +#define POLARSSL_PLATFORM_STD_EXIT MBEDTLS_PLATFORM_STD_EXIT +#endif +#if defined MBEDTLS_PLATFORM_STD_FPRINTF +#define POLARSSL_PLATFORM_STD_FPRINTF MBEDTLS_PLATFORM_STD_FPRINTF +#endif +#if defined MBEDTLS_PLATFORM_STD_FREE +#define POLARSSL_PLATFORM_STD_FREE MBEDTLS_PLATFORM_STD_FREE +#endif +#if defined MBEDTLS_PLATFORM_STD_MEM_HDR +#define POLARSSL_PLATFORM_STD_MEM_HDR MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#if defined MBEDTLS_PLATFORM_STD_PRINTF +#define POLARSSL_PLATFORM_STD_PRINTF MBEDTLS_PLATFORM_STD_PRINTF +#endif +#if defined MBEDTLS_PLATFORM_STD_SNPRINTF +#define POLARSSL_PLATFORM_STD_SNPRINTF MBEDTLS_PLATFORM_STD_SNPRINTF +#endif +#if defined MBEDTLS_PSK_MAX_LEN +#define POLARSSL_PSK_MAX_LEN MBEDTLS_PSK_MAX_LEN +#endif +#if defined MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#define POLARSSL_REMOVE_ARC4_CIPHERSUITES MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#endif +#if defined MBEDTLS_RIPEMD160_ALT +#define POLARSSL_RIPEMD160_ALT MBEDTLS_RIPEMD160_ALT +#endif +#if defined MBEDTLS_RIPEMD160_C +#define POLARSSL_RIPEMD160_C MBEDTLS_RIPEMD160_C +#endif +#if defined MBEDTLS_RIPEMD160_PROCESS_ALT +#define POLARSSL_RIPEMD160_PROCESS_ALT MBEDTLS_RIPEMD160_PROCESS_ALT +#endif +#if defined MBEDTLS_RSA_C +#define POLARSSL_RSA_C MBEDTLS_RSA_C +#endif +#if defined MBEDTLS_RSA_NO_CRT +#define POLARSSL_RSA_NO_CRT MBEDTLS_RSA_NO_CRT +#endif +#if defined MBEDTLS_SELF_TEST +#define POLARSSL_SELF_TEST MBEDTLS_SELF_TEST +#endif +#if defined MBEDTLS_SHA1_ALT +#define POLARSSL_SHA1_ALT MBEDTLS_SHA1_ALT +#endif +#if defined MBEDTLS_SHA1_C +#define POLARSSL_SHA1_C MBEDTLS_SHA1_C +#endif +#if defined MBEDTLS_SHA1_PROCESS_ALT +#define POLARSSL_SHA1_PROCESS_ALT MBEDTLS_SHA1_PROCESS_ALT +#endif +#if defined MBEDTLS_SHA256_ALT +#define POLARSSL_SHA256_ALT MBEDTLS_SHA256_ALT +#endif +#if defined MBEDTLS_SHA256_C +#define POLARSSL_SHA256_C MBEDTLS_SHA256_C +#endif +#if defined MBEDTLS_SHA256_PROCESS_ALT +#define POLARSSL_SHA256_PROCESS_ALT MBEDTLS_SHA256_PROCESS_ALT +#endif +#if defined MBEDTLS_SHA512_ALT +#define POLARSSL_SHA512_ALT MBEDTLS_SHA512_ALT +#endif +#if defined MBEDTLS_SHA512_C +#define POLARSSL_SHA512_C MBEDTLS_SHA512_C +#endif +#if defined MBEDTLS_SHA512_PROCESS_ALT +#define POLARSSL_SHA512_PROCESS_ALT MBEDTLS_SHA512_PROCESS_ALT +#endif +#if defined MBEDTLS_SSL_ALL_ALERT_MESSAGES +#define POLARSSL_SSL_ALL_ALERT_MESSAGES MBEDTLS_SSL_ALL_ALERT_MESSAGES +#endif +#if defined MBEDTLS_SSL_ALPN +#define POLARSSL_SSL_ALPN MBEDTLS_SSL_ALPN +#endif +#if defined MBEDTLS_SSL_CACHE_C +#define POLARSSL_SSL_CACHE_C MBEDTLS_SSL_CACHE_C +#endif +#if defined MBEDTLS_SSL_CBC_RECORD_SPLITTING +#define POLARSSL_SSL_CBC_RECORD_SPLITTING MBEDTLS_SSL_CBC_RECORD_SPLITTING +#endif +#if defined MBEDTLS_SSL_CLI_C +#define POLARSSL_SSL_CLI_C MBEDTLS_SSL_CLI_C +#endif +#if defined MBEDTLS_SSL_COOKIE_C +#define POLARSSL_SSL_COOKIE_C MBEDTLS_SSL_COOKIE_C +#endif +#if defined MBEDTLS_SSL_COOKIE_TIMEOUT +#define POLARSSL_SSL_COOKIE_TIMEOUT MBEDTLS_SSL_COOKIE_TIMEOUT +#endif +#if defined MBEDTLS_SSL_DEBUG_ALL +#define POLARSSL_SSL_DEBUG_ALL MBEDTLS_SSL_DEBUG_ALL +#endif +#if defined MBEDTLS_SSL_DTLS_ANTI_REPLAY +#define POLARSSL_SSL_DTLS_ANTI_REPLAY MBEDTLS_SSL_DTLS_ANTI_REPLAY +#endif +#if defined MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#define POLARSSL_SSL_DTLS_BADMAC_LIMIT MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#endif +#if defined MBEDTLS_SSL_DTLS_HELLO_VERIFY +#define POLARSSL_SSL_DTLS_HELLO_VERIFY MBEDTLS_SSL_DTLS_HELLO_VERIFY +#endif +#if defined MBEDTLS_SSL_ENCRYPT_THEN_MAC +#define POLARSSL_SSL_ENCRYPT_THEN_MAC MBEDTLS_SSL_ENCRYPT_THEN_MAC +#endif +#if defined MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#define POLARSSL_SSL_EXTENDED_MASTER_SECRET MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#endif +#if defined MBEDTLS_SSL_FALLBACK_SCSV +#define POLARSSL_SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV +#endif +#if defined MBEDTLS_SSL_HW_RECORD_ACCEL +#define POLARSSL_SSL_HW_RECORD_ACCEL MBEDTLS_SSL_HW_RECORD_ACCEL +#endif +#if defined MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#endif +#if defined MBEDTLS_SSL_PROTO_DTLS +#define POLARSSL_SSL_PROTO_DTLS MBEDTLS_SSL_PROTO_DTLS +#endif +#if defined MBEDTLS_SSL_PROTO_SSL3 +#define POLARSSL_SSL_PROTO_SSL3 MBEDTLS_SSL_PROTO_SSL3 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1 +#define POLARSSL_SSL_PROTO_TLS1 MBEDTLS_SSL_PROTO_TLS1 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1_1 +#define POLARSSL_SSL_PROTO_TLS1_1 MBEDTLS_SSL_PROTO_TLS1_1 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1_2 +#define POLARSSL_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_2 +#endif +#if defined MBEDTLS_SSL_RENEGOTIATION +#define POLARSSL_SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION +#endif +#if defined MBEDTLS_SSL_SERVER_NAME_INDICATION +#define POLARSSL_SSL_SERVER_NAME_INDICATION MBEDTLS_SSL_SERVER_NAME_INDICATION +#endif +#if defined MBEDTLS_SSL_SESSION_TICKETS +#define POLARSSL_SSL_SESSION_TICKETS MBEDTLS_SSL_SESSION_TICKETS +#endif +#if defined MBEDTLS_SSL_SRV_C +#define POLARSSL_SSL_SRV_C MBEDTLS_SSL_SRV_C +#endif +#if defined MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE +#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE +#endif +#if defined MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO +#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO +#endif +#if defined MBEDTLS_SSL_TLS_C +#define POLARSSL_SSL_TLS_C MBEDTLS_SSL_TLS_C +#endif +#if defined MBEDTLS_SSL_TRUNCATED_HMAC +#define POLARSSL_SSL_TRUNCATED_HMAC MBEDTLS_SSL_TRUNCATED_HMAC +#endif +#if defined MBEDTLS_THREADING_ALT +#define POLARSSL_THREADING_ALT MBEDTLS_THREADING_ALT +#endif +#if defined MBEDTLS_THREADING_C +#define POLARSSL_THREADING_C MBEDTLS_THREADING_C +#endif +#if defined MBEDTLS_THREADING_PTHREAD +#define POLARSSL_THREADING_PTHREAD MBEDTLS_THREADING_PTHREAD +#endif +#if defined MBEDTLS_TIMING_ALT +#define POLARSSL_TIMING_ALT MBEDTLS_TIMING_ALT +#endif +#if defined MBEDTLS_TIMING_C +#define POLARSSL_TIMING_C MBEDTLS_TIMING_C +#endif +#if defined MBEDTLS_VERSION_C +#define POLARSSL_VERSION_C MBEDTLS_VERSION_C +#endif +#if defined MBEDTLS_VERSION_FEATURES +#define POLARSSL_VERSION_FEATURES MBEDTLS_VERSION_FEATURES +#endif +#if defined MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 +#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 +#endif +#if defined MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +#endif +#if defined MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#endif +#if defined MBEDTLS_X509_CHECK_KEY_USAGE +#define POLARSSL_X509_CHECK_KEY_USAGE MBEDTLS_X509_CHECK_KEY_USAGE +#endif +#if defined MBEDTLS_X509_CREATE_C +#define POLARSSL_X509_CREATE_C MBEDTLS_X509_CREATE_C +#endif +#if defined MBEDTLS_X509_CRL_PARSE_C +#define POLARSSL_X509_CRL_PARSE_C MBEDTLS_X509_CRL_PARSE_C +#endif +#if defined MBEDTLS_X509_CRT_PARSE_C +#define POLARSSL_X509_CRT_PARSE_C MBEDTLS_X509_CRT_PARSE_C +#endif +#if defined MBEDTLS_X509_CRT_WRITE_C +#define POLARSSL_X509_CRT_WRITE_C MBEDTLS_X509_CRT_WRITE_C +#endif +#if defined MBEDTLS_X509_CSR_PARSE_C +#define POLARSSL_X509_CSR_PARSE_C MBEDTLS_X509_CSR_PARSE_C +#endif +#if defined MBEDTLS_X509_CSR_WRITE_C +#define POLARSSL_X509_CSR_WRITE_C MBEDTLS_X509_CSR_WRITE_C +#endif +#if defined MBEDTLS_X509_MAX_INTERMEDIATE_CA +#define POLARSSL_X509_MAX_INTERMEDIATE_CA MBEDTLS_X509_MAX_INTERMEDIATE_CA +#endif +#if defined MBEDTLS_X509_RSASSA_PSS_SUPPORT +#define POLARSSL_X509_RSASSA_PSS_SUPPORT MBEDTLS_X509_RSASSA_PSS_SUPPORT +#endif +#if defined MBEDTLS_X509_USE_C +#define POLARSSL_X509_USE_C MBEDTLS_X509_USE_C +#endif +#if defined MBEDTLS_XTEA_ALT +#define POLARSSL_XTEA_ALT MBEDTLS_XTEA_ALT +#endif +#if defined MBEDTLS_XTEA_C +#define POLARSSL_XTEA_C MBEDTLS_XTEA_C +#endif +#if defined MBEDTLS_ZLIB_SUPPORT +#define POLARSSL_ZLIB_SUPPORT MBEDTLS_ZLIB_SUPPORT +#endif + +/* + * Misc names (macros, types, functions, enum constants...) + */ +#define AES_DECRYPT MBEDTLS_AES_DECRYPT +#define AES_ENCRYPT MBEDTLS_AES_ENCRYPT +#define ASN1_BIT_STRING MBEDTLS_ASN1_BIT_STRING +#define ASN1_BMP_STRING MBEDTLS_ASN1_BMP_STRING +#define ASN1_BOOLEAN MBEDTLS_ASN1_BOOLEAN +#define ASN1_CHK_ADD MBEDTLS_ASN1_CHK_ADD +#define ASN1_CONSTRUCTED MBEDTLS_ASN1_CONSTRUCTED +#define ASN1_CONTEXT_SPECIFIC MBEDTLS_ASN1_CONTEXT_SPECIFIC +#define ASN1_GENERALIZED_TIME MBEDTLS_ASN1_GENERALIZED_TIME +#define ASN1_IA5_STRING MBEDTLS_ASN1_IA5_STRING +#define ASN1_INTEGER MBEDTLS_ASN1_INTEGER +#define ASN1_NULL MBEDTLS_ASN1_NULL +#define ASN1_OCTET_STRING MBEDTLS_ASN1_OCTET_STRING +#define ASN1_OID MBEDTLS_ASN1_OID +#define ASN1_PRIMITIVE MBEDTLS_ASN1_PRIMITIVE +#define ASN1_PRINTABLE_STRING MBEDTLS_ASN1_PRINTABLE_STRING +#define ASN1_SEQUENCE MBEDTLS_ASN1_SEQUENCE +#define ASN1_SET MBEDTLS_ASN1_SET +#define ASN1_T61_STRING MBEDTLS_ASN1_T61_STRING +#define ASN1_UNIVERSAL_STRING MBEDTLS_ASN1_UNIVERSAL_STRING +#define ASN1_UTC_TIME MBEDTLS_ASN1_UTC_TIME +#define ASN1_UTF8_STRING MBEDTLS_ASN1_UTF8_STRING +#define BADCERT_CN_MISMATCH MBEDTLS_X509_BADCERT_CN_MISMATCH +#define BADCERT_EXPIRED MBEDTLS_X509_BADCERT_EXPIRED +#define BADCERT_FUTURE MBEDTLS_X509_BADCERT_FUTURE +#define BADCERT_MISSING MBEDTLS_X509_BADCERT_MISSING +#define BADCERT_NOT_TRUSTED MBEDTLS_X509_BADCERT_NOT_TRUSTED +#define BADCERT_OTHER MBEDTLS_X509_BADCERT_OTHER +#define BADCERT_REVOKED MBEDTLS_X509_BADCERT_REVOKED +#define BADCERT_SKIP_VERIFY MBEDTLS_X509_BADCERT_SKIP_VERIFY +#define BADCRL_EXPIRED MBEDTLS_X509_BADCRL_EXPIRED +#define BADCRL_FUTURE MBEDTLS_X509_BADCRL_FUTURE +#define BADCRL_NOT_TRUSTED MBEDTLS_X509_BADCRL_NOT_TRUSTED +#define BLOWFISH_BLOCKSIZE MBEDTLS_BLOWFISH_BLOCKSIZE +#define BLOWFISH_DECRYPT MBEDTLS_BLOWFISH_DECRYPT +#define BLOWFISH_ENCRYPT MBEDTLS_BLOWFISH_ENCRYPT +#define BLOWFISH_MAX_KEY MBEDTLS_BLOWFISH_MAX_KEY_BITS +#define BLOWFISH_MIN_KEY MBEDTLS_BLOWFISH_MIN_KEY_BITS +#define BLOWFISH_ROUNDS MBEDTLS_BLOWFISH_ROUNDS +#define CAMELLIA_DECRYPT MBEDTLS_CAMELLIA_DECRYPT +#define CAMELLIA_ENCRYPT MBEDTLS_CAMELLIA_ENCRYPT +#define COLLECT_SIZE MBEDTLS_HAVEGE_COLLECT_SIZE +#define CTR_DRBG_BLOCKSIZE MBEDTLS_CTR_DRBG_BLOCKSIZE +#define CTR_DRBG_ENTROPY_LEN MBEDTLS_CTR_DRBG_ENTROPY_LEN +#define CTR_DRBG_KEYBITS MBEDTLS_CTR_DRBG_KEYBITS +#define CTR_DRBG_KEYSIZE MBEDTLS_CTR_DRBG_KEYSIZE +#define CTR_DRBG_MAX_INPUT MBEDTLS_CTR_DRBG_MAX_INPUT +#define CTR_DRBG_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST +#define CTR_DRBG_MAX_SEED_INPUT MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +#define CTR_DRBG_PR_OFF MBEDTLS_CTR_DRBG_PR_OFF +#define CTR_DRBG_PR_ON MBEDTLS_CTR_DRBG_PR_ON +#define CTR_DRBG_RESEED_INTERVAL MBEDTLS_CTR_DRBG_RESEED_INTERVAL +#define CTR_DRBG_SEEDLEN MBEDTLS_CTR_DRBG_SEEDLEN +#define DEPRECATED MBEDTLS_DEPRECATED +#define DES_DECRYPT MBEDTLS_DES_DECRYPT +#define DES_ENCRYPT MBEDTLS_DES_ENCRYPT +#define DES_KEY_SIZE MBEDTLS_DES_KEY_SIZE +#define ENTROPY_BLOCK_SIZE MBEDTLS_ENTROPY_BLOCK_SIZE +#define ENTROPY_MAX_GATHER MBEDTLS_ENTROPY_MAX_GATHER +#define ENTROPY_MAX_SEED_SIZE MBEDTLS_ENTROPY_MAX_SEED_SIZE +#define ENTROPY_MAX_SOURCES MBEDTLS_ENTROPY_MAX_SOURCES +#define ENTROPY_MIN_HARDCLOCK MBEDTLS_ENTROPY_MIN_HARDCLOCK +#define ENTROPY_MIN_HAVEGE MBEDTLS_ENTROPY_MIN_HAVEGE +#define ENTROPY_MIN_PLATFORM MBEDTLS_ENTROPY_MIN_PLATFORM +#define ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_SOURCE_MANUAL +#define EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER +#define EXT_BASIC_CONSTRAINTS MBEDTLS_X509_EXT_BASIC_CONSTRAINTS +#define EXT_CERTIFICATE_POLICIES MBEDTLS_X509_EXT_CERTIFICATE_POLICIES +#define EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS +#define EXT_EXTENDED_KEY_USAGE MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE +#define EXT_FRESHEST_CRL MBEDTLS_X509_EXT_FRESHEST_CRL +#define EXT_INIHIBIT_ANYPOLICY MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY +#define EXT_ISSUER_ALT_NAME MBEDTLS_X509_EXT_ISSUER_ALT_NAME +#define EXT_KEY_USAGE MBEDTLS_X509_EXT_KEY_USAGE +#define EXT_NAME_CONSTRAINTS MBEDTLS_X509_EXT_NAME_CONSTRAINTS +#define EXT_NS_CERT_TYPE MBEDTLS_X509_EXT_NS_CERT_TYPE +#define EXT_POLICY_CONSTRAINTS MBEDTLS_X509_EXT_POLICY_CONSTRAINTS +#define EXT_POLICY_MAPPINGS MBEDTLS_X509_EXT_POLICY_MAPPINGS +#define EXT_SUBJECT_ALT_NAME MBEDTLS_X509_EXT_SUBJECT_ALT_NAME +#define EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS +#define EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER +#define GCM_DECRYPT MBEDTLS_GCM_DECRYPT +#define GCM_ENCRYPT MBEDTLS_GCM_ENCRYPT +#define KU_CRL_SIGN MBEDTLS_X509_KU_CRL_SIGN +#define KU_DATA_ENCIPHERMENT MBEDTLS_X509_KU_DATA_ENCIPHERMENT +#define KU_DIGITAL_SIGNATURE MBEDTLS_X509_KU_DIGITAL_SIGNATURE +#define KU_KEY_AGREEMENT MBEDTLS_X509_KU_KEY_AGREEMENT +#define KU_KEY_CERT_SIGN MBEDTLS_X509_KU_KEY_CERT_SIGN +#define KU_KEY_ENCIPHERMENT MBEDTLS_X509_KU_KEY_ENCIPHERMENT +#define KU_NON_REPUDIATION MBEDTLS_X509_KU_NON_REPUDIATION +#define LN_2_DIV_LN_10_SCALE100 MBEDTLS_LN_2_DIV_LN_10_SCALE100 +#define MEMORY_VERIFY_ALLOC MBEDTLS_MEMORY_VERIFY_ALLOC +#define MEMORY_VERIFY_ALWAYS MBEDTLS_MEMORY_VERIFY_ALWAYS +#define MEMORY_VERIFY_FREE MBEDTLS_MEMORY_VERIFY_FREE +#define MEMORY_VERIFY_NONE MBEDTLS_MEMORY_VERIFY_NONE +#define MPI_CHK MBEDTLS_MPI_CHK +#define NET_PROTO_TCP MBEDTLS_NET_PROTO_TCP +#define NET_PROTO_UDP MBEDTLS_NET_PROTO_UDP +#define NS_CERT_TYPE_EMAIL MBEDTLS_X509_NS_CERT_TYPE_EMAIL +#define NS_CERT_TYPE_EMAIL_CA MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA +#define NS_CERT_TYPE_OBJECT_SIGNING MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING +#define NS_CERT_TYPE_OBJECT_SIGNING_CA MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA +#define NS_CERT_TYPE_RESERVED MBEDTLS_X509_NS_CERT_TYPE_RESERVED +#define NS_CERT_TYPE_SSL_CA MBEDTLS_X509_NS_CERT_TYPE_SSL_CA +#define NS_CERT_TYPE_SSL_CLIENT MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT +#define NS_CERT_TYPE_SSL_SERVER MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER +#define OID_ANSI_X9_62 MBEDTLS_OID_ANSI_X9_62 +#define OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE +#define OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD +#define OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62_SIG +#define OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 +#define OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE +#define OID_AT MBEDTLS_OID_AT +#define OID_AT_CN MBEDTLS_OID_AT_CN +#define OID_AT_COUNTRY MBEDTLS_OID_AT_COUNTRY +#define OID_AT_DN_QUALIFIER MBEDTLS_OID_AT_DN_QUALIFIER +#define OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT_GENERATION_QUALIFIER +#define OID_AT_GIVEN_NAME MBEDTLS_OID_AT_GIVEN_NAME +#define OID_AT_INITIALS MBEDTLS_OID_AT_INITIALS +#define OID_AT_LOCALITY MBEDTLS_OID_AT_LOCALITY +#define OID_AT_ORGANIZATION MBEDTLS_OID_AT_ORGANIZATION +#define OID_AT_ORG_UNIT MBEDTLS_OID_AT_ORG_UNIT +#define OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT_POSTAL_ADDRESS +#define OID_AT_POSTAL_CODE MBEDTLS_OID_AT_POSTAL_CODE +#define OID_AT_PSEUDONYM MBEDTLS_OID_AT_PSEUDONYM +#define OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT_SERIAL_NUMBER +#define OID_AT_STATE MBEDTLS_OID_AT_STATE +#define OID_AT_SUR_NAME MBEDTLS_OID_AT_SUR_NAME +#define OID_AT_TITLE MBEDTLS_OID_AT_TITLE +#define OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT_UNIQUE_IDENTIFIER +#define OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER +#define OID_BASIC_CONSTRAINTS MBEDTLS_OID_BASIC_CONSTRAINTS +#define OID_CERTICOM MBEDTLS_OID_CERTICOM +#define OID_CERTIFICATE_POLICIES MBEDTLS_OID_CERTIFICATE_POLICIES +#define OID_CLIENT_AUTH MBEDTLS_OID_CLIENT_AUTH +#define OID_CMP MBEDTLS_OID_CMP +#define OID_CODE_SIGNING MBEDTLS_OID_CODE_SIGNING +#define OID_COUNTRY_US MBEDTLS_OID_COUNTRY_US +#define OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_CRL_DISTRIBUTION_POINTS +#define OID_CRL_NUMBER MBEDTLS_OID_CRL_NUMBER +#define OID_DES_CBC MBEDTLS_OID_DES_CBC +#define OID_DES_EDE3_CBC MBEDTLS_OID_DES_EDE3_CBC +#define OID_DIGEST_ALG_MD2 MBEDTLS_OID_DIGEST_ALG_MD2 +#define OID_DIGEST_ALG_MD4 MBEDTLS_OID_DIGEST_ALG_MD4 +#define OID_DIGEST_ALG_MD5 MBEDTLS_OID_DIGEST_ALG_MD5 +#define OID_DIGEST_ALG_SHA1 MBEDTLS_OID_DIGEST_ALG_SHA1 +#define OID_DIGEST_ALG_SHA224 MBEDTLS_OID_DIGEST_ALG_SHA224 +#define OID_DIGEST_ALG_SHA256 MBEDTLS_OID_DIGEST_ALG_SHA256 +#define OID_DIGEST_ALG_SHA384 MBEDTLS_OID_DIGEST_ALG_SHA384 +#define OID_DIGEST_ALG_SHA512 MBEDTLS_OID_DIGEST_ALG_SHA512 +#define OID_DOMAIN_COMPONENT MBEDTLS_OID_DOMAIN_COMPONENT +#define OID_ECDSA_SHA1 MBEDTLS_OID_ECDSA_SHA1 +#define OID_ECDSA_SHA224 MBEDTLS_OID_ECDSA_SHA224 +#define OID_ECDSA_SHA256 MBEDTLS_OID_ECDSA_SHA256 +#define OID_ECDSA_SHA384 MBEDTLS_OID_ECDSA_SHA384 +#define OID_ECDSA_SHA512 MBEDTLS_OID_ECDSA_SHA512 +#define OID_EC_ALG_ECDH MBEDTLS_OID_EC_ALG_ECDH +#define OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_EC_ALG_UNRESTRICTED +#define OID_EC_BRAINPOOL_V1 MBEDTLS_OID_EC_BRAINPOOL_V1 +#define OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_GRP_BP256R1 +#define OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_GRP_BP384R1 +#define OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_GRP_BP512R1 +#define OID_EC_GRP_SECP192K1 MBEDTLS_OID_EC_GRP_SECP192K1 +#define OID_EC_GRP_SECP192R1 MBEDTLS_OID_EC_GRP_SECP192R1 +#define OID_EC_GRP_SECP224K1 MBEDTLS_OID_EC_GRP_SECP224K1 +#define OID_EC_GRP_SECP224R1 MBEDTLS_OID_EC_GRP_SECP224R1 +#define OID_EC_GRP_SECP256K1 MBEDTLS_OID_EC_GRP_SECP256K1 +#define OID_EC_GRP_SECP256R1 MBEDTLS_OID_EC_GRP_SECP256R1 +#define OID_EC_GRP_SECP384R1 MBEDTLS_OID_EC_GRP_SECP384R1 +#define OID_EC_GRP_SECP521R1 MBEDTLS_OID_EC_GRP_SECP521R1 +#define OID_EMAIL_PROTECTION MBEDTLS_OID_EMAIL_PROTECTION +#define OID_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE +#define OID_FRESHEST_CRL MBEDTLS_OID_FRESHEST_CRL +#define OID_GOV MBEDTLS_OID_GOV +#define OID_HMAC_SHA1 MBEDTLS_OID_HMAC_SHA1 +#define OID_ID_CE MBEDTLS_OID_ID_CE +#define OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_INIHIBIT_ANYPOLICY +#define OID_ISO_CCITT_DS MBEDTLS_OID_ISO_CCITT_DS +#define OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ISO_IDENTIFIED_ORG +#define OID_ISO_ITU_COUNTRY MBEDTLS_OID_ISO_ITU_COUNTRY +#define OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_US_ORG +#define OID_ISO_MEMBER_BODIES MBEDTLS_OID_ISO_MEMBER_BODIES +#define OID_ISSUER_ALT_NAME MBEDTLS_OID_ISSUER_ALT_NAME +#define OID_KEY_USAGE MBEDTLS_OID_KEY_USAGE +#define OID_KP MBEDTLS_OID_KP +#define OID_MGF1 MBEDTLS_OID_MGF1 +#define OID_NAME_CONSTRAINTS MBEDTLS_OID_NAME_CONSTRAINTS +#define OID_NETSCAPE MBEDTLS_OID_NETSCAPE +#define OID_NS_BASE_URL MBEDTLS_OID_NS_BASE_URL +#define OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CA_POLICY_URL +#define OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CA_REVOCATION_URL +#define OID_NS_CERT MBEDTLS_OID_NS_CERT +#define OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_CERT_SEQUENCE +#define OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT_TYPE +#define OID_NS_COMMENT MBEDTLS_OID_NS_COMMENT +#define OID_NS_DATA_TYPE MBEDTLS_OID_NS_DATA_TYPE +#define OID_NS_RENEWAL_URL MBEDTLS_OID_NS_RENEWAL_URL +#define OID_NS_REVOCATION_URL MBEDTLS_OID_NS_REVOCATION_URL +#define OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_SSL_SERVER_NAME +#define OID_OCSP_SIGNING MBEDTLS_OID_OCSP_SIGNING +#define OID_OIW_SECSIG MBEDTLS_OID_OIW_SECSIG +#define OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG_ALG +#define OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_SHA1 +#define OID_ORGANIZATION MBEDTLS_OID_ORGANIZATION +#define OID_ORG_ANSI_X9_62 MBEDTLS_OID_ORG_ANSI_X9_62 +#define OID_ORG_CERTICOM MBEDTLS_OID_ORG_CERTICOM +#define OID_ORG_DOD MBEDTLS_OID_ORG_DOD +#define OID_ORG_GOV MBEDTLS_OID_ORG_GOV +#define OID_ORG_NETSCAPE MBEDTLS_OID_ORG_NETSCAPE +#define OID_ORG_OIW MBEDTLS_OID_ORG_OIW +#define OID_ORG_RSA_DATA_SECURITY MBEDTLS_OID_ORG_RSA_DATA_SECURITY +#define OID_ORG_TELETRUST MBEDTLS_OID_ORG_TELETRUST +#define OID_PKCS MBEDTLS_OID_PKCS +#define OID_PKCS1 MBEDTLS_OID_PKCS1 +#define OID_PKCS12 MBEDTLS_OID_PKCS12 +#define OID_PKCS12_PBE MBEDTLS_OID_PKCS12_PBE +#define OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC +#define OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC +#define OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC +#define OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC +#define OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 +#define OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 +#define OID_PKCS1_MD2 MBEDTLS_OID_PKCS1_MD2 +#define OID_PKCS1_MD4 MBEDTLS_OID_PKCS1_MD4 +#define OID_PKCS1_MD5 MBEDTLS_OID_PKCS1_MD5 +#define OID_PKCS1_RSA MBEDTLS_OID_PKCS1_RSA +#define OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1_SHA1 +#define OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1_SHA224 +#define OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1_SHA256 +#define OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1_SHA384 +#define OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1_SHA512 +#define OID_PKCS5 MBEDTLS_OID_PKCS5 +#define OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5_PBES2 +#define OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC +#define OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC +#define OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC +#define OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC +#define OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC +#define OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC +#define OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5_PBKDF2 +#define OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5_PBMAC1 +#define OID_PKCS9 MBEDTLS_OID_PKCS9 +#define OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9_CSR_EXT_REQ +#define OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9_EMAIL +#define OID_PKIX MBEDTLS_OID_PKIX +#define OID_POLICY_CONSTRAINTS MBEDTLS_OID_POLICY_CONSTRAINTS +#define OID_POLICY_MAPPINGS MBEDTLS_OID_POLICY_MAPPINGS +#define OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD +#define OID_RSASSA_PSS MBEDTLS_OID_RSASSA_PSS +#define OID_RSA_COMPANY MBEDTLS_OID_RSA_COMPANY +#define OID_RSA_SHA_OBS MBEDTLS_OID_RSA_SHA_OBS +#define OID_SERVER_AUTH MBEDTLS_OID_SERVER_AUTH +#define OID_SIZE MBEDTLS_OID_SIZE +#define OID_SUBJECT_ALT_NAME MBEDTLS_OID_SUBJECT_ALT_NAME +#define OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS +#define OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER +#define OID_TELETRUST MBEDTLS_OID_TELETRUST +#define OID_TIME_STAMPING MBEDTLS_OID_TIME_STAMPING +#define PADLOCK_ACE MBEDTLS_PADLOCK_ACE +#define PADLOCK_ALIGN16 MBEDTLS_PADLOCK_ALIGN16 +#define PADLOCK_PHE MBEDTLS_PADLOCK_PHE +#define PADLOCK_PMM MBEDTLS_PADLOCK_PMM +#define PADLOCK_RNG MBEDTLS_PADLOCK_RNG +#define PKCS12_DERIVE_IV MBEDTLS_PKCS12_DERIVE_IV +#define PKCS12_DERIVE_KEY MBEDTLS_PKCS12_DERIVE_KEY +#define PKCS12_DERIVE_MAC_KEY MBEDTLS_PKCS12_DERIVE_MAC_KEY +#define PKCS12_PBE_DECRYPT MBEDTLS_PKCS12_PBE_DECRYPT +#define PKCS12_PBE_ENCRYPT MBEDTLS_PKCS12_PBE_ENCRYPT +#define PKCS5_DECRYPT MBEDTLS_PKCS5_DECRYPT +#define PKCS5_ENCRYPT MBEDTLS_PKCS5_ENCRYPT +#define POLARSSL_AESNI_AES MBEDTLS_AESNI_AES +#define POLARSSL_AESNI_CLMUL MBEDTLS_AESNI_CLMUL +#define POLARSSL_AESNI_H MBEDTLS_AESNI_H +#define POLARSSL_AES_H MBEDTLS_AES_H +#define POLARSSL_ARC4_H MBEDTLS_ARC4_H +#define POLARSSL_ASN1_H MBEDTLS_ASN1_H +#define POLARSSL_ASN1_WRITE_H MBEDTLS_ASN1_WRITE_H +#define POLARSSL_BASE64_H MBEDTLS_BASE64_H +#define POLARSSL_BIGNUM_H MBEDTLS_BIGNUM_H +#define POLARSSL_BLOWFISH_H MBEDTLS_BLOWFISH_H +#define POLARSSL_BN_MUL_H MBEDTLS_BN_MUL_H +#define POLARSSL_CAMELLIA_H MBEDTLS_CAMELLIA_H +#define POLARSSL_CCM_H MBEDTLS_CCM_H +#define POLARSSL_CERTS_H MBEDTLS_CERTS_H +#define POLARSSL_CHECK_CONFIG_H MBEDTLS_CHECK_CONFIG_H +#define POLARSSL_CIPHERSUITE_NODTLS MBEDTLS_CIPHERSUITE_NODTLS +#define POLARSSL_CIPHERSUITE_SHORT_TAG MBEDTLS_CIPHERSUITE_SHORT_TAG +#define POLARSSL_CIPHERSUITE_WEAK MBEDTLS_CIPHERSUITE_WEAK +#define POLARSSL_CIPHER_AES_128_CBC MBEDTLS_CIPHER_AES_128_CBC +#define POLARSSL_CIPHER_AES_128_CCM MBEDTLS_CIPHER_AES_128_CCM +#define POLARSSL_CIPHER_AES_128_CFB128 MBEDTLS_CIPHER_AES_128_CFB128 +#define POLARSSL_CIPHER_AES_128_CTR MBEDTLS_CIPHER_AES_128_CTR +#define POLARSSL_CIPHER_AES_128_ECB MBEDTLS_CIPHER_AES_128_ECB +#define POLARSSL_CIPHER_AES_128_GCM MBEDTLS_CIPHER_AES_128_GCM +#define POLARSSL_CIPHER_AES_192_CBC MBEDTLS_CIPHER_AES_192_CBC +#define POLARSSL_CIPHER_AES_192_CCM MBEDTLS_CIPHER_AES_192_CCM +#define POLARSSL_CIPHER_AES_192_CFB128 MBEDTLS_CIPHER_AES_192_CFB128 +#define POLARSSL_CIPHER_AES_192_CTR MBEDTLS_CIPHER_AES_192_CTR +#define POLARSSL_CIPHER_AES_192_ECB MBEDTLS_CIPHER_AES_192_ECB +#define POLARSSL_CIPHER_AES_192_GCM MBEDTLS_CIPHER_AES_192_GCM +#define POLARSSL_CIPHER_AES_256_CBC MBEDTLS_CIPHER_AES_256_CBC +#define POLARSSL_CIPHER_AES_256_CCM MBEDTLS_CIPHER_AES_256_CCM +#define POLARSSL_CIPHER_AES_256_CFB128 MBEDTLS_CIPHER_AES_256_CFB128 +#define POLARSSL_CIPHER_AES_256_CTR MBEDTLS_CIPHER_AES_256_CTR +#define POLARSSL_CIPHER_AES_256_ECB MBEDTLS_CIPHER_AES_256_ECB +#define POLARSSL_CIPHER_AES_256_GCM MBEDTLS_CIPHER_AES_256_GCM +#define POLARSSL_CIPHER_ARC4_128 MBEDTLS_CIPHER_ARC4_128 +#define POLARSSL_CIPHER_BLOWFISH_CBC MBEDTLS_CIPHER_BLOWFISH_CBC +#define POLARSSL_CIPHER_BLOWFISH_CFB64 MBEDTLS_CIPHER_BLOWFISH_CFB64 +#define POLARSSL_CIPHER_BLOWFISH_CTR MBEDTLS_CIPHER_BLOWFISH_CTR +#define POLARSSL_CIPHER_BLOWFISH_ECB MBEDTLS_CIPHER_BLOWFISH_ECB +#define POLARSSL_CIPHER_CAMELLIA_128_CBC MBEDTLS_CIPHER_CAMELLIA_128_CBC +#define POLARSSL_CIPHER_CAMELLIA_128_CCM MBEDTLS_CIPHER_CAMELLIA_128_CCM +#define POLARSSL_CIPHER_CAMELLIA_128_CFB128 MBEDTLS_CIPHER_CAMELLIA_128_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_128_CTR MBEDTLS_CIPHER_CAMELLIA_128_CTR +#define POLARSSL_CIPHER_CAMELLIA_128_ECB MBEDTLS_CIPHER_CAMELLIA_128_ECB +#define POLARSSL_CIPHER_CAMELLIA_128_GCM MBEDTLS_CIPHER_CAMELLIA_128_GCM +#define POLARSSL_CIPHER_CAMELLIA_192_CBC MBEDTLS_CIPHER_CAMELLIA_192_CBC +#define POLARSSL_CIPHER_CAMELLIA_192_CCM MBEDTLS_CIPHER_CAMELLIA_192_CCM +#define POLARSSL_CIPHER_CAMELLIA_192_CFB128 MBEDTLS_CIPHER_CAMELLIA_192_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_192_CTR MBEDTLS_CIPHER_CAMELLIA_192_CTR +#define POLARSSL_CIPHER_CAMELLIA_192_ECB MBEDTLS_CIPHER_CAMELLIA_192_ECB +#define POLARSSL_CIPHER_CAMELLIA_192_GCM MBEDTLS_CIPHER_CAMELLIA_192_GCM +#define POLARSSL_CIPHER_CAMELLIA_256_CBC MBEDTLS_CIPHER_CAMELLIA_256_CBC +#define POLARSSL_CIPHER_CAMELLIA_256_CCM MBEDTLS_CIPHER_CAMELLIA_256_CCM +#define POLARSSL_CIPHER_CAMELLIA_256_CFB128 MBEDTLS_CIPHER_CAMELLIA_256_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_256_CTR MBEDTLS_CIPHER_CAMELLIA_256_CTR +#define POLARSSL_CIPHER_CAMELLIA_256_ECB MBEDTLS_CIPHER_CAMELLIA_256_ECB +#define POLARSSL_CIPHER_CAMELLIA_256_GCM MBEDTLS_CIPHER_CAMELLIA_256_GCM +#define POLARSSL_CIPHER_DES_CBC MBEDTLS_CIPHER_DES_CBC +#define POLARSSL_CIPHER_DES_ECB MBEDTLS_CIPHER_DES_ECB +#define POLARSSL_CIPHER_DES_EDE3_CBC MBEDTLS_CIPHER_DES_EDE3_CBC +#define POLARSSL_CIPHER_DES_EDE3_ECB MBEDTLS_CIPHER_DES_EDE3_ECB +#define POLARSSL_CIPHER_DES_EDE_CBC MBEDTLS_CIPHER_DES_EDE_CBC +#define POLARSSL_CIPHER_DES_EDE_ECB MBEDTLS_CIPHER_DES_EDE_ECB +#define POLARSSL_CIPHER_H MBEDTLS_CIPHER_H +#define POLARSSL_CIPHER_ID_3DES MBEDTLS_CIPHER_ID_3DES +#define POLARSSL_CIPHER_ID_AES MBEDTLS_CIPHER_ID_AES +#define POLARSSL_CIPHER_ID_ARC4 MBEDTLS_CIPHER_ID_ARC4 +#define POLARSSL_CIPHER_ID_BLOWFISH MBEDTLS_CIPHER_ID_BLOWFISH +#define POLARSSL_CIPHER_ID_CAMELLIA MBEDTLS_CIPHER_ID_CAMELLIA +#define POLARSSL_CIPHER_ID_DES MBEDTLS_CIPHER_ID_DES +#define POLARSSL_CIPHER_ID_NONE MBEDTLS_CIPHER_ID_NONE +#define POLARSSL_CIPHER_ID_NULL MBEDTLS_CIPHER_ID_NULL +#define POLARSSL_CIPHER_MODE_AEAD MBEDTLS_CIPHER_MODE_AEAD +#define POLARSSL_CIPHER_MODE_STREAM MBEDTLS_CIPHER_MODE_STREAM +#define POLARSSL_CIPHER_MODE_WITH_PADDING MBEDTLS_CIPHER_MODE_WITH_PADDING +#define POLARSSL_CIPHER_NONE MBEDTLS_CIPHER_NONE +#define POLARSSL_CIPHER_NULL MBEDTLS_CIPHER_NULL +#define POLARSSL_CIPHER_VARIABLE_IV_LEN MBEDTLS_CIPHER_VARIABLE_IV_LEN +#define POLARSSL_CIPHER_VARIABLE_KEY_LEN MBEDTLS_CIPHER_VARIABLE_KEY_LEN +#define POLARSSL_CIPHER_WRAP_H MBEDTLS_CIPHER_WRAP_H +#define POLARSSL_CONFIG_H MBEDTLS_CONFIG_H +#define POLARSSL_CTR_DRBG_H MBEDTLS_CTR_DRBG_H +#define POLARSSL_DEBUG_H MBEDTLS_DEBUG_H +#define POLARSSL_DECRYPT MBEDTLS_DECRYPT +#define POLARSSL_DES_H MBEDTLS_DES_H +#define POLARSSL_DHM_H MBEDTLS_DHM_H +#define POLARSSL_DHM_RFC3526_MODP_2048_G MBEDTLS_DHM_RFC3526_MODP_2048_G +#define POLARSSL_DHM_RFC3526_MODP_2048_P MBEDTLS_DHM_RFC3526_MODP_2048_P +#define POLARSSL_DHM_RFC3526_MODP_3072_G MBEDTLS_DHM_RFC3526_MODP_3072_G +#define POLARSSL_DHM_RFC3526_MODP_3072_P MBEDTLS_DHM_RFC3526_MODP_3072_P +#define POLARSSL_DHM_RFC5114_MODP_2048_G MBEDTLS_DHM_RFC5114_MODP_2048_G +#define POLARSSL_DHM_RFC5114_MODP_2048_P MBEDTLS_DHM_RFC5114_MODP_2048_P +#define POLARSSL_ECDH_H MBEDTLS_ECDH_H +#define POLARSSL_ECDH_OURS MBEDTLS_ECDH_OURS +#define POLARSSL_ECDH_THEIRS MBEDTLS_ECDH_THEIRS +#define POLARSSL_ECDSA_H MBEDTLS_ECDSA_H +#define POLARSSL_ECP_DP_BP256R1 MBEDTLS_ECP_DP_BP256R1 +#define POLARSSL_ECP_DP_BP384R1 MBEDTLS_ECP_DP_BP384R1 +#define POLARSSL_ECP_DP_BP512R1 MBEDTLS_ECP_DP_BP512R1 +#define POLARSSL_ECP_DP_M255 MBEDTLS_ECP_DP_CURVE25519 +#define POLARSSL_ECP_DP_MAX MBEDTLS_ECP_DP_MAX +#define POLARSSL_ECP_DP_NONE MBEDTLS_ECP_DP_NONE +#define POLARSSL_ECP_DP_SECP192K1 MBEDTLS_ECP_DP_SECP192K1 +#define POLARSSL_ECP_DP_SECP192R1 MBEDTLS_ECP_DP_SECP192R1 +#define POLARSSL_ECP_DP_SECP224K1 MBEDTLS_ECP_DP_SECP224K1 +#define POLARSSL_ECP_DP_SECP224R1 MBEDTLS_ECP_DP_SECP224R1 +#define POLARSSL_ECP_DP_SECP256K1 MBEDTLS_ECP_DP_SECP256K1 +#define POLARSSL_ECP_DP_SECP256R1 MBEDTLS_ECP_DP_SECP256R1 +#define POLARSSL_ECP_DP_SECP384R1 MBEDTLS_ECP_DP_SECP384R1 +#define POLARSSL_ECP_DP_SECP521R1 MBEDTLS_ECP_DP_SECP521R1 +#define POLARSSL_ECP_H MBEDTLS_ECP_H +#define POLARSSL_ECP_MAX_BYTES MBEDTLS_ECP_MAX_BYTES +#define POLARSSL_ECP_MAX_PT_LEN MBEDTLS_ECP_MAX_PT_LEN +#define POLARSSL_ECP_PF_COMPRESSED MBEDTLS_ECP_PF_COMPRESSED +#define POLARSSL_ECP_PF_UNCOMPRESSED MBEDTLS_ECP_PF_UNCOMPRESSED +#define POLARSSL_ECP_TLS_NAMED_CURVE MBEDTLS_ECP_TLS_NAMED_CURVE +#define POLARSSL_ENCRYPT MBEDTLS_ENCRYPT +#define POLARSSL_ENTROPY_H MBEDTLS_ENTROPY_H +#define POLARSSL_ENTROPY_POLL_H MBEDTLS_ENTROPY_POLL_H +#define POLARSSL_ENTROPY_SHA256_ACCUMULATOR MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#define POLARSSL_ENTROPY_SHA512_ACCUMULATOR MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#define POLARSSL_ERROR_H MBEDTLS_ERROR_H +#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH MBEDTLS_ERR_AES_INVALID_KEY_LENGTH +#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL MBEDTLS_ERR_ASN1_BUF_TOO_SMALL +#define POLARSSL_ERR_ASN1_INVALID_DATA MBEDTLS_ERR_ASN1_INVALID_DATA +#define POLARSSL_ERR_ASN1_INVALID_LENGTH MBEDTLS_ERR_ASN1_INVALID_LENGTH +#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH MBEDTLS_ERR_ASN1_LENGTH_MISMATCH +#define POLARSSL_ERR_ASN1_MALLOC_FAILED MBEDTLS_ERR_ASN1_ALLOC_FAILED +#define POLARSSL_ERR_ASN1_OUT_OF_DATA MBEDTLS_ERR_ASN1_OUT_OF_DATA +#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG MBEDTLS_ERR_ASN1_UNEXPECTED_TAG +#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL +#define POLARSSL_ERR_BASE64_INVALID_CHARACTER MBEDTLS_ERR_BASE64_INVALID_CHARACTER +#define POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH +#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH +#define POLARSSL_ERR_CCM_AUTH_FAILED MBEDTLS_ERR_CCM_AUTH_FAILED +#define POLARSSL_ERR_CCM_BAD_INPUT MBEDTLS_ERR_CCM_BAD_INPUT +#define POLARSSL_ERR_CIPHER_ALLOC_FAILED MBEDTLS_ERR_CIPHER_ALLOC_FAILED +#define POLARSSL_ERR_CIPHER_AUTH_FAILED MBEDTLS_ERR_CIPHER_AUTH_FAILED +#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA +#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED +#define POLARSSL_ERR_CIPHER_INVALID_PADDING MBEDTLS_ERR_CIPHER_INVALID_PADDING +#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR +#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG +#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG +#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_DHM_BAD_INPUT_DATA MBEDTLS_ERR_DHM_BAD_INPUT_DATA +#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED MBEDTLS_ERR_DHM_CALC_SECRET_FAILED +#define POLARSSL_ERR_DHM_FILE_IO_ERROR MBEDTLS_ERR_DHM_FILE_IO_ERROR +#define POLARSSL_ERR_DHM_INVALID_FORMAT MBEDTLS_ERR_DHM_INVALID_FORMAT +#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED +#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED +#define POLARSSL_ERR_DHM_MALLOC_FAILED MBEDTLS_ERR_DHM_ALLOC_FAILED +#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED MBEDTLS_ERR_DHM_READ_PARAMS_FAILED +#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED +#define POLARSSL_ERR_ECP_BAD_INPUT_DATA MBEDTLS_ERR_ECP_BAD_INPUT_DATA +#define POLARSSL_ERR_ECP_BUFFER_TOO_SMALL MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL +#define POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_ECP_INVALID_KEY MBEDTLS_ERR_ECP_INVALID_KEY +#define POLARSSL_ERR_ECP_MALLOC_FAILED MBEDTLS_ERR_ECP_ALLOC_FAILED +#define POLARSSL_ERR_ECP_RANDOM_FAILED MBEDTLS_ERR_ECP_RANDOM_FAILED +#define POLARSSL_ERR_ECP_SIG_LEN_MISMATCH MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH +#define POLARSSL_ERR_ECP_VERIFY_FAILED MBEDTLS_ERR_ECP_VERIFY_FAILED +#define POLARSSL_ERR_ENTROPY_FILE_IO_ERROR MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR +#define POLARSSL_ERR_ENTROPY_MAX_SOURCES MBEDTLS_ERR_ENTROPY_MAX_SOURCES +#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED +#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_GCM_AUTH_FAILED MBEDTLS_ERR_GCM_AUTH_FAILED +#define POLARSSL_ERR_GCM_BAD_INPUT MBEDTLS_ERR_GCM_BAD_INPUT +#define POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR +#define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG +#define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG +#define POLARSSL_ERR_MD_ALLOC_FAILED MBEDTLS_ERR_MD_ALLOC_FAILED +#define POLARSSL_ERR_MD_BAD_INPUT_DATA MBEDTLS_ERR_MD_BAD_INPUT_DATA +#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_MD_FILE_IO_ERROR MBEDTLS_ERR_MD_FILE_IO_ERROR +#define POLARSSL_ERR_MPI_BAD_INPUT_DATA MBEDTLS_ERR_MPI_BAD_INPUT_DATA +#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL +#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO MBEDTLS_ERR_MPI_DIVISION_BY_ZERO +#define POLARSSL_ERR_MPI_FILE_IO_ERROR MBEDTLS_ERR_MPI_FILE_IO_ERROR +#define POLARSSL_ERR_MPI_INVALID_CHARACTER MBEDTLS_ERR_MPI_INVALID_CHARACTER +#define POLARSSL_ERR_MPI_MALLOC_FAILED MBEDTLS_ERR_MPI_ALLOC_FAILED +#define POLARSSL_ERR_MPI_NEGATIVE_VALUE MBEDTLS_ERR_MPI_NEGATIVE_VALUE +#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE MBEDTLS_ERR_MPI_NOT_ACCEPTABLE +#define POLARSSL_ERR_NET_ACCEPT_FAILED MBEDTLS_ERR_NET_ACCEPT_FAILED +#define POLARSSL_ERR_NET_BIND_FAILED MBEDTLS_ERR_NET_BIND_FAILED +#define POLARSSL_ERR_NET_CONNECT_FAILED MBEDTLS_ERR_NET_CONNECT_FAILED +#define POLARSSL_ERR_NET_CONN_RESET MBEDTLS_ERR_NET_CONN_RESET +#define POLARSSL_ERR_NET_LISTEN_FAILED MBEDTLS_ERR_NET_LISTEN_FAILED +#define POLARSSL_ERR_NET_RECV_FAILED MBEDTLS_ERR_NET_RECV_FAILED +#define POLARSSL_ERR_NET_SEND_FAILED MBEDTLS_ERR_NET_SEND_FAILED +#define POLARSSL_ERR_NET_SOCKET_FAILED MBEDTLS_ERR_NET_SOCKET_FAILED +#define POLARSSL_ERR_NET_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT +#define POLARSSL_ERR_NET_UNKNOWN_HOST MBEDTLS_ERR_NET_UNKNOWN_HOST +#define POLARSSL_ERR_NET_WANT_READ MBEDTLS_ERR_SSL_WANT_READ +#define POLARSSL_ERR_NET_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE +#define POLARSSL_ERR_OID_BUF_TOO_SMALL MBEDTLS_ERR_OID_BUF_TOO_SMALL +#define POLARSSL_ERR_OID_NOT_FOUND MBEDTLS_ERR_OID_NOT_FOUND +#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED +#define POLARSSL_ERR_PEM_BAD_INPUT_DATA MBEDTLS_ERR_PEM_BAD_INPUT_DATA +#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PEM_INVALID_DATA MBEDTLS_ERR_PEM_INVALID_DATA +#define POLARSSL_ERR_PEM_INVALID_ENC_IV MBEDTLS_ERR_PEM_INVALID_ENC_IV +#define POLARSSL_ERR_PEM_MALLOC_FAILED MBEDTLS_ERR_PEM_ALLOC_FAILED +#define POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT +#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH MBEDTLS_ERR_PEM_PASSWORD_MISMATCH +#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED MBEDTLS_ERR_PEM_PASSWORD_REQUIRED +#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG +#define POLARSSL_ERR_PKCS12_BAD_INPUT_DATA MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA +#define POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH +#define POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT +#define POLARSSL_ERR_PKCS5_BAD_INPUT_DATA MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA +#define POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PKCS5_INVALID_FORMAT MBEDTLS_ERR_PKCS5_INVALID_FORMAT +#define POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH +#define POLARSSL_ERR_PK_BAD_INPUT_DATA MBEDTLS_ERR_PK_BAD_INPUT_DATA +#define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PK_FILE_IO_ERROR MBEDTLS_ERR_PK_FILE_IO_ERROR +#define POLARSSL_ERR_PK_INVALID_ALG MBEDTLS_ERR_PK_INVALID_ALG +#define POLARSSL_ERR_PK_INVALID_PUBKEY MBEDTLS_ERR_PK_INVALID_PUBKEY +#define POLARSSL_ERR_PK_KEY_INVALID_FORMAT MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +#define POLARSSL_ERR_PK_KEY_INVALID_VERSION MBEDTLS_ERR_PK_KEY_INVALID_VERSION +#define POLARSSL_ERR_PK_MALLOC_FAILED MBEDTLS_ERR_PK_ALLOC_FAILED +#define POLARSSL_ERR_PK_PASSWORD_MISMATCH MBEDTLS_ERR_PK_PASSWORD_MISMATCH +#define POLARSSL_ERR_PK_PASSWORD_REQUIRED MBEDTLS_ERR_PK_PASSWORD_REQUIRED +#define POLARSSL_ERR_PK_SIG_LEN_MISMATCH MBEDTLS_ERR_PK_SIG_LEN_MISMATCH +#define POLARSSL_ERR_PK_TYPE_MISMATCH MBEDTLS_ERR_PK_TYPE_MISMATCH +#define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE +#define POLARSSL_ERR_PK_UNKNOWN_PK_ALG MBEDTLS_ERR_PK_UNKNOWN_PK_ALG +#define POLARSSL_ERR_RSA_BAD_INPUT_DATA MBEDTLS_ERR_RSA_BAD_INPUT_DATA +#define POLARSSL_ERR_RSA_INVALID_PADDING MBEDTLS_ERR_RSA_INVALID_PADDING +#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED MBEDTLS_ERR_RSA_KEY_CHECK_FAILED +#define POLARSSL_ERR_RSA_KEY_GEN_FAILED MBEDTLS_ERR_RSA_KEY_GEN_FAILED +#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE +#define POLARSSL_ERR_RSA_PRIVATE_FAILED MBEDTLS_ERR_RSA_PRIVATE_FAILED +#define POLARSSL_ERR_RSA_PUBLIC_FAILED MBEDTLS_ERR_RSA_PUBLIC_FAILED +#define POLARSSL_ERR_RSA_RNG_FAILED MBEDTLS_ERR_RSA_RNG_FAILED +#define POLARSSL_ERR_RSA_VERIFY_FAILED MBEDTLS_ERR_RSA_VERIFY_FAILED +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY +#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP +#define POLARSSL_ERR_SSL_BAD_HS_FINISHED MBEDTLS_ERR_SSL_BAD_HS_FINISHED +#define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET +#define POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE +#define POLARSSL_ERR_SSL_BAD_INPUT_DATA MBEDTLS_ERR_SSL_BAD_INPUT_DATA +#define POLARSSL_ERR_SSL_BUFFER_TOO_SMALL MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL +#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED +#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED +#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE +#define POLARSSL_ERR_SSL_COMPRESSION_FAILED MBEDTLS_ERR_SSL_COMPRESSION_FAILED +#define POLARSSL_ERR_SSL_CONN_EOF MBEDTLS_ERR_SSL_CONN_EOF +#define POLARSSL_ERR_SSL_COUNTER_WRAPPING MBEDTLS_ERR_SSL_COUNTER_WRAPPING +#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE +#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_SSL_HELLO_VERIFY_REQUIRED MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED +#define POLARSSL_ERR_SSL_HW_ACCEL_FAILED MBEDTLS_ERR_SSL_HW_ACCEL_FAILED +#define POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH +#define POLARSSL_ERR_SSL_INTERNAL_ERROR MBEDTLS_ERR_SSL_INTERNAL_ERROR +#define POLARSSL_ERR_SSL_INVALID_MAC MBEDTLS_ERR_SSL_INVALID_MAC +#define POLARSSL_ERR_SSL_INVALID_RECORD MBEDTLS_ERR_SSL_INVALID_RECORD +#define POLARSSL_ERR_SSL_MALLOC_FAILED MBEDTLS_ERR_SSL_ALLOC_FAILED +#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN +#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE +#define POLARSSL_ERR_SSL_NO_RNG MBEDTLS_ERR_SSL_NO_RNG +#define POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE +#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY +#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED +#define POLARSSL_ERR_SSL_PK_TYPE_MISMATCH MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH +#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED +#define POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED +#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE +#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER MBEDTLS_ERR_SSL_UNKNOWN_CIPHER +#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY +#define POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO +#define POLARSSL_ERR_THREADING_BAD_INPUT_DATA MBEDTLS_ERR_THREADING_BAD_INPUT_DATA +#define POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_THREADING_MUTEX_ERROR MBEDTLS_ERR_THREADING_MUTEX_ERROR +#define POLARSSL_ERR_X509_BAD_INPUT_DATA MBEDTLS_ERR_X509_BAD_INPUT_DATA +#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT +#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED MBEDTLS_ERR_X509_CERT_VERIFY_FAILED +#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_X509_FILE_IO_ERROR MBEDTLS_ERR_X509_FILE_IO_ERROR +#define POLARSSL_ERR_X509_INVALID_ALG MBEDTLS_ERR_X509_INVALID_ALG +#define POLARSSL_ERR_X509_INVALID_DATE MBEDTLS_ERR_X509_INVALID_DATE +#define POLARSSL_ERR_X509_INVALID_EXTENSIONS MBEDTLS_ERR_X509_INVALID_EXTENSIONS +#define POLARSSL_ERR_X509_INVALID_FORMAT MBEDTLS_ERR_X509_INVALID_FORMAT +#define POLARSSL_ERR_X509_INVALID_NAME MBEDTLS_ERR_X509_INVALID_NAME +#define POLARSSL_ERR_X509_INVALID_SERIAL MBEDTLS_ERR_X509_INVALID_SERIAL +#define POLARSSL_ERR_X509_INVALID_SIGNATURE MBEDTLS_ERR_X509_INVALID_SIGNATURE +#define POLARSSL_ERR_X509_INVALID_VERSION MBEDTLS_ERR_X509_INVALID_VERSION +#define POLARSSL_ERR_X509_MALLOC_FAILED MBEDTLS_ERR_X509_ALLOC_FAILED +#define POLARSSL_ERR_X509_SIG_MISMATCH MBEDTLS_ERR_X509_SIG_MISMATCH +#define POLARSSL_ERR_X509_UNKNOWN_OID MBEDTLS_ERR_X509_UNKNOWN_OID +#define POLARSSL_ERR_X509_UNKNOWN_SIG_ALG MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG +#define POLARSSL_ERR_X509_UNKNOWN_VERSION MBEDTLS_ERR_X509_UNKNOWN_VERSION +#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH +#define POLARSSL_GCM_H MBEDTLS_GCM_H +#define POLARSSL_HAVEGE_H MBEDTLS_HAVEGE_H +#define POLARSSL_HAVE_INT32 MBEDTLS_HAVE_INT32 +#define POLARSSL_HAVE_INT64 MBEDTLS_HAVE_INT64 +#define POLARSSL_HAVE_UDBL MBEDTLS_HAVE_UDBL +#define POLARSSL_HAVE_X86 MBEDTLS_HAVE_X86 +#define POLARSSL_HAVE_X86_64 MBEDTLS_HAVE_X86_64 +#define POLARSSL_HMAC_DRBG_H MBEDTLS_HMAC_DRBG_H +#define POLARSSL_HMAC_DRBG_PR_OFF MBEDTLS_HMAC_DRBG_PR_OFF +#define POLARSSL_HMAC_DRBG_PR_ON MBEDTLS_HMAC_DRBG_PR_ON +#define POLARSSL_KEY_EXCHANGE_DHE_PSK MBEDTLS_KEY_EXCHANGE_DHE_PSK +#define POLARSSL_KEY_EXCHANGE_DHE_RSA MBEDTLS_KEY_EXCHANGE_DHE_RSA +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK MBEDTLS_KEY_EXCHANGE_ECDHE_PSK +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA MBEDTLS_KEY_EXCHANGE_ECDHE_RSA +#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA +#define POLARSSL_KEY_EXCHANGE_ECDH_RSA MBEDTLS_KEY_EXCHANGE_ECDH_RSA +#define POLARSSL_KEY_EXCHANGE_NONE MBEDTLS_KEY_EXCHANGE_NONE +#define POLARSSL_KEY_EXCHANGE_PSK MBEDTLS_KEY_EXCHANGE_PSK +#define POLARSSL_KEY_EXCHANGE_RSA MBEDTLS_KEY_EXCHANGE_RSA +#define POLARSSL_KEY_EXCHANGE_RSA_PSK MBEDTLS_KEY_EXCHANGE_RSA_PSK +#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED +#define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED +#define POLARSSL_KEY_LENGTH_DES MBEDTLS_KEY_LENGTH_DES +#define POLARSSL_KEY_LENGTH_DES_EDE MBEDTLS_KEY_LENGTH_DES_EDE +#define POLARSSL_KEY_LENGTH_DES_EDE3 MBEDTLS_KEY_LENGTH_DES_EDE3 +#define POLARSSL_KEY_LENGTH_NONE MBEDTLS_KEY_LENGTH_NONE +#define POLARSSL_MAX_BLOCK_LENGTH MBEDTLS_MAX_BLOCK_LENGTH +#define POLARSSL_MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH +#define POLARSSL_MD2_H MBEDTLS_MD2_H +#define POLARSSL_MD4_H MBEDTLS_MD4_H +#define POLARSSL_MD5_H MBEDTLS_MD5_H +#define POLARSSL_MD_H MBEDTLS_MD_H +#define POLARSSL_MD_MAX_SIZE MBEDTLS_MD_MAX_SIZE +#define POLARSSL_MD_MD2 MBEDTLS_MD_MD2 +#define POLARSSL_MD_MD4 MBEDTLS_MD_MD4 +#define POLARSSL_MD_MD5 MBEDTLS_MD_MD5 +#define POLARSSL_MD_NONE MBEDTLS_MD_NONE +#define POLARSSL_MD_RIPEMD160 MBEDTLS_MD_RIPEMD160 +#define POLARSSL_MD_SHA1 MBEDTLS_MD_SHA1 +#define POLARSSL_MD_SHA224 MBEDTLS_MD_SHA224 +#define POLARSSL_MD_SHA256 MBEDTLS_MD_SHA256 +#define POLARSSL_MD_SHA384 MBEDTLS_MD_SHA384 +#define POLARSSL_MD_SHA512 MBEDTLS_MD_SHA512 +#define POLARSSL_MD_WRAP_H MBEDTLS_MD_WRAP_H +#define POLARSSL_MEMORY_BUFFER_ALLOC_H MBEDTLS_MEMORY_BUFFER_ALLOC_H +#define POLARSSL_MODE_CBC MBEDTLS_MODE_CBC +#define POLARSSL_MODE_CCM MBEDTLS_MODE_CCM +#define POLARSSL_MODE_CFB MBEDTLS_MODE_CFB +#define POLARSSL_MODE_CTR MBEDTLS_MODE_CTR +#define POLARSSL_MODE_ECB MBEDTLS_MODE_ECB +#define POLARSSL_MODE_GCM MBEDTLS_MODE_GCM +#define POLARSSL_MODE_NONE MBEDTLS_MODE_NONE +#define POLARSSL_MODE_OFB MBEDTLS_MODE_OFB +#define POLARSSL_MODE_STREAM MBEDTLS_MODE_STREAM +#define POLARSSL_MPI_MAX_BITS MBEDTLS_MPI_MAX_BITS +#define POLARSSL_MPI_MAX_BITS_SCALE100 MBEDTLS_MPI_MAX_BITS_SCALE100 +#define POLARSSL_MPI_MAX_LIMBS MBEDTLS_MPI_MAX_LIMBS +#define POLARSSL_MPI_RW_BUFFER_SIZE MBEDTLS_MPI_RW_BUFFER_SIZE +#define POLARSSL_NET_H MBEDTLS_NET_SOCKETS_H +#define POLARSSL_NET_LISTEN_BACKLOG MBEDTLS_NET_LISTEN_BACKLOG +#define POLARSSL_OID_H MBEDTLS_OID_H +#define POLARSSL_OPERATION_NONE MBEDTLS_OPERATION_NONE +#define POLARSSL_PADDING_NONE MBEDTLS_PADDING_NONE +#define POLARSSL_PADDING_ONE_AND_ZEROS MBEDTLS_PADDING_ONE_AND_ZEROS +#define POLARSSL_PADDING_PKCS7 MBEDTLS_PADDING_PKCS7 +#define POLARSSL_PADDING_ZEROS MBEDTLS_PADDING_ZEROS +#define POLARSSL_PADDING_ZEROS_AND_LEN MBEDTLS_PADDING_ZEROS_AND_LEN +#define POLARSSL_PADLOCK_H MBEDTLS_PADLOCK_H +#define POLARSSL_PEM_H MBEDTLS_PEM_H +#define POLARSSL_PKCS11_H MBEDTLS_PKCS11_H +#define POLARSSL_PKCS12_H MBEDTLS_PKCS12_H +#define POLARSSL_PKCS5_H MBEDTLS_PKCS5_H +#define POLARSSL_PK_DEBUG_ECP MBEDTLS_PK_DEBUG_ECP +#define POLARSSL_PK_DEBUG_MAX_ITEMS MBEDTLS_PK_DEBUG_MAX_ITEMS +#define POLARSSL_PK_DEBUG_MPI MBEDTLS_PK_DEBUG_MPI +#define POLARSSL_PK_DEBUG_NONE MBEDTLS_PK_DEBUG_NONE +#define POLARSSL_PK_ECDSA MBEDTLS_PK_ECDSA +#define POLARSSL_PK_ECKEY MBEDTLS_PK_ECKEY +#define POLARSSL_PK_ECKEY_DH MBEDTLS_PK_ECKEY_DH +#define POLARSSL_PK_H MBEDTLS_PK_H +#define POLARSSL_PK_NONE MBEDTLS_PK_NONE +#define POLARSSL_PK_RSA MBEDTLS_PK_RSA +#define POLARSSL_PK_RSASSA_PSS MBEDTLS_PK_RSASSA_PSS +#define POLARSSL_PK_RSA_ALT MBEDTLS_PK_RSA_ALT +#define POLARSSL_PK_WRAP_H MBEDTLS_PK_WRAP_H +#define POLARSSL_PLATFORM_H MBEDTLS_PLATFORM_H +#define POLARSSL_PREMASTER_SIZE MBEDTLS_PREMASTER_SIZE +#define POLARSSL_RIPEMD160_H MBEDTLS_RIPEMD160_H +#define POLARSSL_RSA_H MBEDTLS_RSA_H +#define POLARSSL_SHA1_H MBEDTLS_SHA1_H +#define POLARSSL_SHA256_H MBEDTLS_SHA256_H +#define POLARSSL_SHA512_H MBEDTLS_SHA512_H +#define POLARSSL_SSL_CACHE_H MBEDTLS_SSL_CACHE_H +#define POLARSSL_SSL_CIPHERSUITES_H MBEDTLS_SSL_CIPHERSUITES_H +#define POLARSSL_SSL_COOKIE_H MBEDTLS_SSL_COOKIE_H +#define POLARSSL_SSL_H MBEDTLS_SSL_H +#define POLARSSL_THREADING_H MBEDTLS_THREADING_H +#define POLARSSL_THREADING_IMPL MBEDTLS_THREADING_IMPL +#define POLARSSL_TIMING_H MBEDTLS_TIMING_H +#define POLARSSL_VERSION_H MBEDTLS_VERSION_H +#define POLARSSL_VERSION_MAJOR MBEDTLS_VERSION_MAJOR +#define POLARSSL_VERSION_MINOR MBEDTLS_VERSION_MINOR +#define POLARSSL_VERSION_NUMBER MBEDTLS_VERSION_NUMBER +#define POLARSSL_VERSION_PATCH MBEDTLS_VERSION_PATCH +#define POLARSSL_VERSION_STRING MBEDTLS_VERSION_STRING +#define POLARSSL_VERSION_STRING_FULL MBEDTLS_VERSION_STRING_FULL +#define POLARSSL_X509_CRL_H MBEDTLS_X509_CRL_H +#define POLARSSL_X509_CRT_H MBEDTLS_X509_CRT_H +#define POLARSSL_X509_CSR_H MBEDTLS_X509_CSR_H +#define POLARSSL_X509_H MBEDTLS_X509_H +#define POLARSSL_XTEA_H MBEDTLS_XTEA_H +#define RSA_CRYPT MBEDTLS_RSA_CRYPT +#define RSA_PKCS_V15 MBEDTLS_RSA_PKCS_V15 +#define RSA_PKCS_V21 MBEDTLS_RSA_PKCS_V21 +#define RSA_PRIVATE MBEDTLS_RSA_PRIVATE +#define RSA_PUBLIC MBEDTLS_RSA_PUBLIC +#define RSA_SALT_LEN_ANY MBEDTLS_RSA_SALT_LEN_ANY +#define RSA_SIGN MBEDTLS_RSA_SIGN +#define SSL_ALERT_LEVEL_FATAL MBEDTLS_SSL_ALERT_LEVEL_FATAL +#define SSL_ALERT_LEVEL_WARNING MBEDTLS_SSL_ALERT_LEVEL_WARNING +#define SSL_ALERT_MSG_ACCESS_DENIED MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED +#define SSL_ALERT_MSG_BAD_CERT MBEDTLS_SSL_ALERT_MSG_BAD_CERT +#define SSL_ALERT_MSG_BAD_RECORD_MAC MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC +#define SSL_ALERT_MSG_CERT_EXPIRED MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED +#define SSL_ALERT_MSG_CERT_REVOKED MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED +#define SSL_ALERT_MSG_CERT_UNKNOWN MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN +#define SSL_ALERT_MSG_CLOSE_NOTIFY MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY +#define SSL_ALERT_MSG_DECODE_ERROR MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR +#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE +#define SSL_ALERT_MSG_DECRYPTION_FAILED MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED +#define SSL_ALERT_MSG_DECRYPT_ERROR MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR +#define SSL_ALERT_MSG_EXPORT_RESTRICTION MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION +#define SSL_ALERT_MSG_HANDSHAKE_FAILURE MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE +#define SSL_ALERT_MSG_ILLEGAL_PARAMETER MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER +#define SSL_ALERT_MSG_INAPROPRIATE_FALLBACK MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK +#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY +#define SSL_ALERT_MSG_INTERNAL_ERROR MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR +#define SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL +#define SSL_ALERT_MSG_NO_CERT MBEDTLS_SSL_ALERT_MSG_NO_CERT +#define SSL_ALERT_MSG_NO_RENEGOTIATION MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION +#define SSL_ALERT_MSG_PROTOCOL_VERSION MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION +#define SSL_ALERT_MSG_RECORD_OVERFLOW MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW +#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE +#define SSL_ALERT_MSG_UNKNOWN_CA MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA +#define SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY +#define SSL_ALERT_MSG_UNRECOGNIZED_NAME MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME +#define SSL_ALERT_MSG_UNSUPPORTED_CERT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT +#define SSL_ALERT_MSG_UNSUPPORTED_EXT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT +#define SSL_ALERT_MSG_USER_CANCELED MBEDTLS_SSL_ALERT_MSG_USER_CANCELED +#define SSL_ANTI_REPLAY_DISABLED MBEDTLS_SSL_ANTI_REPLAY_DISABLED +#define SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED +#define SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED +#define SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED +#define SSL_BUFFER_LEN ( ( ( MBEDTLS_SSL_IN_BUFFER_LEN ) < ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) \ + ? ( MBEDTLS_SSL_IN_BUFFER_LEN ) : ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) +#define SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES +#define SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT +#define SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED +#define SSL_CBC_RECORD_SPLITTING_ENABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED +#define SSL_CERTIFICATE_REQUEST MBEDTLS_SSL_CERTIFICATE_REQUEST +#define SSL_CERTIFICATE_VERIFY MBEDTLS_SSL_CERTIFICATE_VERIFY +#define SSL_CERT_TYPE_ECDSA_SIGN MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN +#define SSL_CERT_TYPE_RSA_SIGN MBEDTLS_SSL_CERT_TYPE_RSA_SIGN +#define SSL_CHANNEL_INBOUND MBEDTLS_SSL_CHANNEL_INBOUND +#define SSL_CHANNEL_OUTBOUND MBEDTLS_SSL_CHANNEL_OUTBOUND +#define SSL_CIPHERSUITES MBEDTLS_SSL_CIPHERSUITES +#define SSL_CLIENT_CERTIFICATE MBEDTLS_SSL_CLIENT_CERTIFICATE +#define SSL_CLIENT_CHANGE_CIPHER_SPEC MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC +#define SSL_CLIENT_FINISHED MBEDTLS_SSL_CLIENT_FINISHED +#define SSL_CLIENT_HELLO MBEDTLS_SSL_CLIENT_HELLO +#define SSL_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_CLIENT_KEY_EXCHANGE +#define SSL_COMPRESSION_ADD MBEDTLS_SSL_COMPRESSION_ADD +#define SSL_COMPRESS_DEFLATE MBEDTLS_SSL_COMPRESS_DEFLATE +#define SSL_COMPRESS_NULL MBEDTLS_SSL_COMPRESS_NULL +#define SSL_DEBUG_BUF MBEDTLS_SSL_DEBUG_BUF +#define SSL_DEBUG_CRT MBEDTLS_SSL_DEBUG_CRT +#define SSL_DEBUG_ECP MBEDTLS_SSL_DEBUG_ECP +#define SSL_DEBUG_MPI MBEDTLS_SSL_DEBUG_MPI +#define SSL_DEBUG_MSG MBEDTLS_SSL_DEBUG_MSG +#define SSL_DEBUG_RET MBEDTLS_SSL_DEBUG_RET +#define SSL_DEFAULT_TICKET_LIFETIME MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME +#define SSL_DTLS_TIMEOUT_DFL_MAX MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX +#define SSL_DTLS_TIMEOUT_DFL_MIN MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN +#define SSL_EMPTY_RENEGOTIATION_INFO MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO +#define SSL_ETM_DISABLED MBEDTLS_SSL_ETM_DISABLED +#define SSL_ETM_ENABLED MBEDTLS_SSL_ETM_ENABLED +#define SSL_EXTENDED_MS_DISABLED MBEDTLS_SSL_EXTENDED_MS_DISABLED +#define SSL_EXTENDED_MS_ENABLED MBEDTLS_SSL_EXTENDED_MS_ENABLED +#define SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV +#define SSL_FLUSH_BUFFERS MBEDTLS_SSL_FLUSH_BUFFERS +#define SSL_HANDSHAKE_OVER MBEDTLS_SSL_HANDSHAKE_OVER +#define SSL_HANDSHAKE_WRAPUP MBEDTLS_SSL_HANDSHAKE_WRAPUP +#define SSL_HASH_MD5 MBEDTLS_SSL_HASH_MD5 +#define SSL_HASH_NONE MBEDTLS_SSL_HASH_NONE +#define SSL_HASH_SHA1 MBEDTLS_SSL_HASH_SHA1 +#define SSL_HASH_SHA224 MBEDTLS_SSL_HASH_SHA224 +#define SSL_HASH_SHA256 MBEDTLS_SSL_HASH_SHA256 +#define SSL_HASH_SHA384 MBEDTLS_SSL_HASH_SHA384 +#define SSL_HASH_SHA512 MBEDTLS_SSL_HASH_SHA512 +#define SSL_HELLO_REQUEST MBEDTLS_SSL_HELLO_REQUEST +#define SSL_HS_CERTIFICATE MBEDTLS_SSL_HS_CERTIFICATE +#define SSL_HS_CERTIFICATE_REQUEST MBEDTLS_SSL_HS_CERTIFICATE_REQUEST +#define SSL_HS_CERTIFICATE_VERIFY MBEDTLS_SSL_HS_CERTIFICATE_VERIFY +#define SSL_HS_CLIENT_HELLO MBEDTLS_SSL_HS_CLIENT_HELLO +#define SSL_HS_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE +#define SSL_HS_FINISHED MBEDTLS_SSL_HS_FINISHED +#define SSL_HS_HELLO_REQUEST MBEDTLS_SSL_HS_HELLO_REQUEST +#define SSL_HS_HELLO_VERIFY_REQUEST MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST +#define SSL_HS_NEW_SESSION_TICKET MBEDTLS_SSL_HS_NEW_SESSION_TICKET +#define SSL_HS_SERVER_HELLO MBEDTLS_SSL_HS_SERVER_HELLO +#define SSL_HS_SERVER_HELLO_DONE MBEDTLS_SSL_HS_SERVER_HELLO_DONE +#define SSL_HS_SERVER_KEY_EXCHANGE MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE +#define SSL_INITIAL_HANDSHAKE MBEDTLS_SSL_INITIAL_HANDSHAKE +#define SSL_IS_CLIENT MBEDTLS_SSL_IS_CLIENT +#define SSL_IS_FALLBACK MBEDTLS_SSL_IS_FALLBACK +#define SSL_IS_NOT_FALLBACK MBEDTLS_SSL_IS_NOT_FALLBACK +#define SSL_IS_SERVER MBEDTLS_SSL_IS_SERVER +#define SSL_LEGACY_ALLOW_RENEGOTIATION MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION +#define SSL_LEGACY_BREAK_HANDSHAKE MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE +#define SSL_LEGACY_NO_RENEGOTIATION MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION +#define SSL_LEGACY_RENEGOTIATION MBEDTLS_SSL_LEGACY_RENEGOTIATION +#define SSL_MAC_ADD MBEDTLS_SSL_MAC_ADD +#define SSL_MAJOR_VERSION_3 MBEDTLS_SSL_MAJOR_VERSION_3 +#define SSL_MAX_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#define SSL_MAX_FRAG_LEN_1024 MBEDTLS_SSL_MAX_FRAG_LEN_1024 +#define SSL_MAX_FRAG_LEN_2048 MBEDTLS_SSL_MAX_FRAG_LEN_2048 +#define SSL_MAX_FRAG_LEN_4096 MBEDTLS_SSL_MAX_FRAG_LEN_4096 +#define SSL_MAX_FRAG_LEN_512 MBEDTLS_SSL_MAX_FRAG_LEN_512 +#define SSL_MAX_FRAG_LEN_INVALID MBEDTLS_SSL_MAX_FRAG_LEN_INVALID +#define SSL_MAX_FRAG_LEN_NONE MBEDTLS_SSL_MAX_FRAG_LEN_NONE +#define SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAX_MAJOR_VERSION +#define SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MAX_MINOR_VERSION +#define SSL_MINOR_VERSION_0 MBEDTLS_SSL_MINOR_VERSION_0 +#define SSL_MINOR_VERSION_1 MBEDTLS_SSL_MINOR_VERSION_1 +#define SSL_MINOR_VERSION_2 MBEDTLS_SSL_MINOR_VERSION_2 +#define SSL_MINOR_VERSION_3 MBEDTLS_SSL_MINOR_VERSION_3 +#define SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MIN_MAJOR_VERSION +#define SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MIN_MINOR_VERSION +#define SSL_MSG_ALERT MBEDTLS_SSL_MSG_ALERT +#define SSL_MSG_APPLICATION_DATA MBEDTLS_SSL_MSG_APPLICATION_DATA +#define SSL_MSG_CHANGE_CIPHER_SPEC MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC +#define SSL_MSG_HANDSHAKE MBEDTLS_SSL_MSG_HANDSHAKE +#define SSL_PADDING_ADD MBEDTLS_SSL_PADDING_ADD +#define SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION +#define SSL_RENEGOTIATION_DISABLED MBEDTLS_SSL_RENEGOTIATION_DISABLED +#define SSL_RENEGOTIATION_DONE MBEDTLS_SSL_RENEGOTIATION_DONE +#define SSL_RENEGOTIATION_ENABLED MBEDTLS_SSL_RENEGOTIATION_ENABLED +#define SSL_RENEGOTIATION_NOT_ENFORCED MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED +#define SSL_RENEGOTIATION_PENDING MBEDTLS_SSL_RENEGOTIATION_PENDING +#define SSL_RENEGO_MAX_RECORDS_DEFAULT MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT +#define SSL_RETRANS_FINISHED MBEDTLS_SSL_RETRANS_FINISHED +#define SSL_RETRANS_PREPARING MBEDTLS_SSL_RETRANS_PREPARING +#define SSL_RETRANS_SENDING MBEDTLS_SSL_RETRANS_SENDING +#define SSL_RETRANS_WAITING MBEDTLS_SSL_RETRANS_WAITING +#define SSL_SECURE_RENEGOTIATION MBEDTLS_SSL_SECURE_RENEGOTIATION +#define SSL_SERVER_CERTIFICATE MBEDTLS_SSL_SERVER_CERTIFICATE +#define SSL_SERVER_CHANGE_CIPHER_SPEC MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC +#define SSL_SERVER_FINISHED MBEDTLS_SSL_SERVER_FINISHED +#define SSL_SERVER_HELLO MBEDTLS_SSL_SERVER_HELLO +#define SSL_SERVER_HELLO_DONE MBEDTLS_SSL_SERVER_HELLO_DONE +#define SSL_SERVER_HELLO_VERIFY_REQUEST_SENT MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT +#define SSL_SERVER_KEY_EXCHANGE MBEDTLS_SSL_SERVER_KEY_EXCHANGE +#define SSL_SERVER_NEW_SESSION_TICKET MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET +#define SSL_SESSION_TICKETS_DISABLED MBEDTLS_SSL_SESSION_TICKETS_DISABLED +#define SSL_SESSION_TICKETS_ENABLED MBEDTLS_SSL_SESSION_TICKETS_ENABLED +#define SSL_SIG_ANON MBEDTLS_SSL_SIG_ANON +#define SSL_SIG_ECDSA MBEDTLS_SSL_SIG_ECDSA +#define SSL_SIG_RSA MBEDTLS_SSL_SIG_RSA +#define SSL_TRANSPORT_DATAGRAM MBEDTLS_SSL_TRANSPORT_DATAGRAM +#define SSL_TRANSPORT_STREAM MBEDTLS_SSL_TRANSPORT_STREAM +#define SSL_TRUNCATED_HMAC_LEN MBEDTLS_SSL_TRUNCATED_HMAC_LEN +#define SSL_TRUNC_HMAC_DISABLED MBEDTLS_SSL_TRUNC_HMAC_DISABLED +#define SSL_TRUNC_HMAC_ENABLED MBEDTLS_SSL_TRUNC_HMAC_ENABLED +#define SSL_VERIFY_DATA_MAX_LEN MBEDTLS_SSL_VERIFY_DATA_MAX_LEN +#define SSL_VERIFY_NONE MBEDTLS_SSL_VERIFY_NONE +#define SSL_VERIFY_OPTIONAL MBEDTLS_SSL_VERIFY_OPTIONAL +#define SSL_VERIFY_REQUIRED MBEDTLS_SSL_VERIFY_REQUIRED +#define TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_DHE_PSK_WITH_AES_128_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM +#define TLS_DHE_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 +#define TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_DHE_PSK_WITH_AES_256_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM +#define TLS_DHE_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 +#define TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_DHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA +#define TLS_DHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 +#define TLS_DHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 +#define TLS_DHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA +#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_DHE_RSA_WITH_AES_128_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM +#define TLS_DHE_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 +#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 +#define TLS_DHE_RSA_WITH_AES_256_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM +#define TLS_DHE_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 +#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_DHE_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 +#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 +#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDHE_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA +#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA +#define TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA +#define TLS_ECDHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 +#define TLS_ECDHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 +#define TLS_ECDHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA +#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDHE_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA +#define TLS_ECDHE_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA +#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDH_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA +#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA +#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDH_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA +#define TLS_ECDH_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA +#define TLS_EXT_ALPN MBEDTLS_TLS_EXT_ALPN +#define TLS_EXT_ENCRYPT_THEN_MAC MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC +#define TLS_EXT_EXTENDED_MASTER_SECRET MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET +#define TLS_EXT_MAX_FRAGMENT_LENGTH MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH +#define TLS_EXT_RENEGOTIATION_INFO MBEDTLS_TLS_EXT_RENEGOTIATION_INFO +#define TLS_EXT_SERVERNAME MBEDTLS_TLS_EXT_SERVERNAME +#define TLS_EXT_SERVERNAME_HOSTNAME MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME +#define TLS_EXT_SESSION_TICKET MBEDTLS_TLS_EXT_SESSION_TICKET +#define TLS_EXT_SIG_ALG MBEDTLS_TLS_EXT_SIG_ALG +#define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES +#define TLS_EXT_SUPPORTED_POINT_FORMATS MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS +#define TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT +#define TLS_EXT_TRUNCATED_HMAC MBEDTLS_TLS_EXT_TRUNCATED_HMAC +#define TLS_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA +#define TLS_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_PSK_WITH_AES_128_CCM MBEDTLS_TLS_PSK_WITH_AES_128_CCM +#define TLS_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 +#define TLS_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA +#define TLS_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_PSK_WITH_AES_256_CCM MBEDTLS_TLS_PSK_WITH_AES_256_CCM +#define TLS_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 +#define TLS_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_PSK_WITH_NULL_SHA MBEDTLS_TLS_PSK_WITH_NULL_SHA +#define TLS_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_PSK_WITH_NULL_SHA256 +#define TLS_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_PSK_WITH_NULL_SHA384 +#define TLS_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_PSK_WITH_RC4_128_SHA +#define TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_RSA_PSK_WITH_NULL_SHA MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA +#define TLS_RSA_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 +#define TLS_RSA_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 +#define TLS_RSA_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA +#define TLS_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA +#define TLS_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_RSA_WITH_AES_128_CCM MBEDTLS_TLS_RSA_WITH_AES_128_CCM +#define TLS_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 +#define TLS_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA +#define TLS_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 +#define TLS_RSA_WITH_AES_256_CCM MBEDTLS_TLS_RSA_WITH_AES_256_CCM +#define TLS_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 +#define TLS_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 +#define TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA +#define TLS_RSA_WITH_NULL_MD5 MBEDTLS_TLS_RSA_WITH_NULL_MD5 +#define TLS_RSA_WITH_NULL_SHA MBEDTLS_TLS_RSA_WITH_NULL_SHA +#define TLS_RSA_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_WITH_NULL_SHA256 +#define TLS_RSA_WITH_RC4_128_MD5 MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 +#define TLS_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_WITH_RC4_128_SHA +#define X509_CRT_VERSION_1 MBEDTLS_X509_CRT_VERSION_1 +#define X509_CRT_VERSION_2 MBEDTLS_X509_CRT_VERSION_2 +#define X509_CRT_VERSION_3 MBEDTLS_X509_CRT_VERSION_3 +#define X509_FORMAT_DER MBEDTLS_X509_FORMAT_DER +#define X509_FORMAT_PEM MBEDTLS_X509_FORMAT_PEM +#define X509_MAX_DN_NAME_SIZE MBEDTLS_X509_MAX_DN_NAME_SIZE +#define X509_RFC5280_MAX_SERIAL_LEN MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN +#define X509_RFC5280_UTC_TIME_LEN MBEDTLS_X509_RFC5280_UTC_TIME_LEN +#define XTEA_DECRYPT MBEDTLS_XTEA_DECRYPT +#define XTEA_ENCRYPT MBEDTLS_XTEA_ENCRYPT +#define _asn1_bitstring mbedtls_asn1_bitstring +#define _asn1_buf mbedtls_asn1_buf +#define _asn1_named_data mbedtls_asn1_named_data +#define _asn1_sequence mbedtls_asn1_sequence +#define _ssl_cache_context mbedtls_ssl_cache_context +#define _ssl_cache_entry mbedtls_ssl_cache_entry +#define _ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t +#define _ssl_context mbedtls_ssl_context +#define _ssl_flight_item mbedtls_ssl_flight_item +#define _ssl_handshake_params mbedtls_ssl_handshake_params +#define _ssl_key_cert mbedtls_ssl_key_cert +#define _ssl_premaster_secret mbedtls_ssl_premaster_secret +#define _ssl_session mbedtls_ssl_session +#define _ssl_transform mbedtls_ssl_transform +#define _x509_crl mbedtls_x509_crl +#define _x509_crl_entry mbedtls_x509_crl_entry +#define _x509_crt mbedtls_x509_crt +#define _x509_csr mbedtls_x509_csr +#define _x509_time mbedtls_x509_time +#define _x509write_cert mbedtls_x509write_cert +#define _x509write_csr mbedtls_x509write_csr +#define aes_context mbedtls_aes_context +#define aes_crypt_cbc mbedtls_aes_crypt_cbc +#define aes_crypt_cfb128 mbedtls_aes_crypt_cfb128 +#define aes_crypt_cfb8 mbedtls_aes_crypt_cfb8 +#define aes_crypt_ctr mbedtls_aes_crypt_ctr +#define aes_crypt_ecb mbedtls_aes_crypt_ecb +#define aes_free mbedtls_aes_free +#define aes_init mbedtls_aes_init +#define aes_self_test mbedtls_aes_self_test +#define aes_setkey_dec mbedtls_aes_setkey_dec +#define aes_setkey_enc mbedtls_aes_setkey_enc +#define aesni_crypt_ecb mbedtls_aesni_crypt_ecb +#define aesni_gcm_mult mbedtls_aesni_gcm_mult +#define aesni_inverse_key mbedtls_aesni_inverse_key +#define aesni_setkey_enc mbedtls_aesni_setkey_enc +#define aesni_supports mbedtls_aesni_has_support +#define alarmed mbedtls_timing_alarmed +#define arc4_context mbedtls_arc4_context +#define arc4_crypt mbedtls_arc4_crypt +#define arc4_free mbedtls_arc4_free +#define arc4_init mbedtls_arc4_init +#define arc4_self_test mbedtls_arc4_self_test +#define arc4_setup mbedtls_arc4_setup +#define asn1_bitstring mbedtls_asn1_bitstring +#define asn1_buf mbedtls_asn1_buf +#define asn1_find_named_data mbedtls_asn1_find_named_data +#define asn1_free_named_data mbedtls_asn1_free_named_data +#define asn1_free_named_data_list mbedtls_asn1_free_named_data_list +#define asn1_get_alg mbedtls_asn1_get_alg +#define asn1_get_alg_null mbedtls_asn1_get_alg_null +#define asn1_get_bitstring mbedtls_asn1_get_bitstring +#define asn1_get_bitstring_null mbedtls_asn1_get_bitstring_null +#define asn1_get_bool mbedtls_asn1_get_bool +#define asn1_get_int mbedtls_asn1_get_int +#define asn1_get_len mbedtls_asn1_get_len +#define asn1_get_mpi mbedtls_asn1_get_mpi +#define asn1_get_sequence_of mbedtls_asn1_get_sequence_of +#define asn1_get_tag mbedtls_asn1_get_tag +#define asn1_named_data mbedtls_asn1_named_data +#define asn1_sequence mbedtls_asn1_sequence +#define asn1_store_named_data mbedtls_asn1_store_named_data +#define asn1_write_algorithm_identifier mbedtls_asn1_write_algorithm_identifier +#define asn1_write_bitstring mbedtls_asn1_write_bitstring +#define asn1_write_bool mbedtls_asn1_write_bool +#define asn1_write_ia5_string mbedtls_asn1_write_ia5_string +#define asn1_write_int mbedtls_asn1_write_int +#define asn1_write_len mbedtls_asn1_write_len +#define asn1_write_mpi mbedtls_asn1_write_mpi +#define asn1_write_null mbedtls_asn1_write_null +#define asn1_write_octet_string mbedtls_asn1_write_octet_string +#define asn1_write_oid mbedtls_asn1_write_oid +#define asn1_write_printable_string mbedtls_asn1_write_printable_string +#define asn1_write_raw_buffer mbedtls_asn1_write_raw_buffer +#define asn1_write_tag mbedtls_asn1_write_tag +#define base64_decode mbedtls_base64_decode +#define base64_encode mbedtls_base64_encode +#define base64_self_test mbedtls_base64_self_test +#define blowfish_context mbedtls_blowfish_context +#define blowfish_crypt_cbc mbedtls_blowfish_crypt_cbc +#define blowfish_crypt_cfb64 mbedtls_blowfish_crypt_cfb64 +#define blowfish_crypt_ctr mbedtls_blowfish_crypt_ctr +#define blowfish_crypt_ecb mbedtls_blowfish_crypt_ecb +#define blowfish_free mbedtls_blowfish_free +#define blowfish_init mbedtls_blowfish_init +#define blowfish_setkey mbedtls_blowfish_setkey +#define camellia_context mbedtls_camellia_context +#define camellia_crypt_cbc mbedtls_camellia_crypt_cbc +#define camellia_crypt_cfb128 mbedtls_camellia_crypt_cfb128 +#define camellia_crypt_ctr mbedtls_camellia_crypt_ctr +#define camellia_crypt_ecb mbedtls_camellia_crypt_ecb +#define camellia_free mbedtls_camellia_free +#define camellia_init mbedtls_camellia_init +#define camellia_self_test mbedtls_camellia_self_test +#define camellia_setkey_dec mbedtls_camellia_setkey_dec +#define camellia_setkey_enc mbedtls_camellia_setkey_enc +#define ccm_auth_decrypt mbedtls_ccm_auth_decrypt +#define ccm_context mbedtls_ccm_context +#define ccm_encrypt_and_tag mbedtls_ccm_encrypt_and_tag +#define ccm_free mbedtls_ccm_free +#define ccm_init mbedtls_ccm_init +#define ccm_self_test mbedtls_ccm_self_test +#define cipher_auth_decrypt mbedtls_cipher_auth_decrypt +#define cipher_auth_encrypt mbedtls_cipher_auth_encrypt +#define cipher_base_t mbedtls_cipher_base_t +#define cipher_check_tag mbedtls_cipher_check_tag +#define cipher_context_t mbedtls_cipher_context_t +#define cipher_crypt mbedtls_cipher_crypt +#define cipher_definition_t mbedtls_cipher_definition_t +#define cipher_definitions mbedtls_cipher_definitions +#define cipher_finish mbedtls_cipher_finish +#define cipher_free mbedtls_cipher_free +#define cipher_get_block_size mbedtls_cipher_get_block_size +#define cipher_get_cipher_mode mbedtls_cipher_get_cipher_mode +#define cipher_get_iv_size mbedtls_cipher_get_iv_size +#define cipher_get_key_size mbedtls_cipher_get_key_bitlen +#define cipher_get_name mbedtls_cipher_get_name +#define cipher_get_operation mbedtls_cipher_get_operation +#define cipher_get_type mbedtls_cipher_get_type +#define cipher_id_t mbedtls_cipher_id_t +#define cipher_info_from_string mbedtls_cipher_info_from_string +#define cipher_info_from_type mbedtls_cipher_info_from_type +#define cipher_info_from_values mbedtls_cipher_info_from_values +#define cipher_info_t mbedtls_cipher_info_t +#define cipher_init mbedtls_cipher_init +#define cipher_init_ctx mbedtls_cipher_setup +#define cipher_list mbedtls_cipher_list +#define cipher_mode_t mbedtls_cipher_mode_t +#define cipher_padding_t mbedtls_cipher_padding_t +#define cipher_reset mbedtls_cipher_reset +#define cipher_set_iv mbedtls_cipher_set_iv +#define cipher_set_padding_mode mbedtls_cipher_set_padding_mode +#define cipher_setkey mbedtls_cipher_setkey +#define cipher_type_t mbedtls_cipher_type_t +#define cipher_update mbedtls_cipher_update +#define cipher_update_ad mbedtls_cipher_update_ad +#define cipher_write_tag mbedtls_cipher_write_tag +#define ctr_drbg_context mbedtls_ctr_drbg_context +#define ctr_drbg_free mbedtls_ctr_drbg_free +#define ctr_drbg_init mbedtls_ctr_drbg_init +#define ctr_drbg_random mbedtls_ctr_drbg_random +#define ctr_drbg_random_with_add mbedtls_ctr_drbg_random_with_add +#define ctr_drbg_reseed mbedtls_ctr_drbg_reseed +#define ctr_drbg_self_test mbedtls_ctr_drbg_self_test +#define ctr_drbg_set_entropy_len mbedtls_ctr_drbg_set_entropy_len +#define ctr_drbg_set_prediction_resistance mbedtls_ctr_drbg_set_prediction_resistance +#define ctr_drbg_set_reseed_interval mbedtls_ctr_drbg_set_reseed_interval +#define ctr_drbg_update mbedtls_ctr_drbg_update +#define ctr_drbg_update_seed_file mbedtls_ctr_drbg_update_seed_file +#define ctr_drbg_write_seed_file mbedtls_ctr_drbg_write_seed_file +#define debug_print_buf mbedtls_debug_print_buf +#define debug_print_crt mbedtls_debug_print_crt +#define debug_print_ecp mbedtls_debug_print_ecp +#define debug_print_mpi mbedtls_debug_print_mpi +#define debug_print_msg mbedtls_debug_print_msg +#define debug_print_ret mbedtls_debug_print_ret +#define debug_set_threshold mbedtls_debug_set_threshold +#define des3_context mbedtls_des3_context +#define des3_crypt_cbc mbedtls_des3_crypt_cbc +#define des3_crypt_ecb mbedtls_des3_crypt_ecb +#define des3_free mbedtls_des3_free +#define des3_init mbedtls_des3_init +#define des3_set2key_dec mbedtls_des3_set2key_dec +#define des3_set2key_enc mbedtls_des3_set2key_enc +#define des3_set3key_dec mbedtls_des3_set3key_dec +#define des3_set3key_enc mbedtls_des3_set3key_enc +#define des_context mbedtls_des_context +#define des_crypt_cbc mbedtls_des_crypt_cbc +#define des_crypt_ecb mbedtls_des_crypt_ecb +#define des_free mbedtls_des_free +#define des_init mbedtls_des_init +#define des_key_check_key_parity mbedtls_des_key_check_key_parity +#define des_key_check_weak mbedtls_des_key_check_weak +#define des_key_set_parity mbedtls_des_key_set_parity +#define des_self_test mbedtls_des_self_test +#define des_setkey_dec mbedtls_des_setkey_dec +#define des_setkey_enc mbedtls_des_setkey_enc +#define dhm_calc_secret mbedtls_dhm_calc_secret +#define dhm_context mbedtls_dhm_context +#define dhm_free mbedtls_dhm_free +#define dhm_init mbedtls_dhm_init +#define dhm_make_params mbedtls_dhm_make_params +#define dhm_make_public mbedtls_dhm_make_public +#define dhm_parse_dhm mbedtls_dhm_parse_dhm +#define dhm_parse_dhmfile mbedtls_dhm_parse_dhmfile +#define dhm_read_params mbedtls_dhm_read_params +#define dhm_read_public mbedtls_dhm_read_public +#define dhm_self_test mbedtls_dhm_self_test +#define ecdh_calc_secret mbedtls_ecdh_calc_secret +#define ecdh_compute_shared mbedtls_ecdh_compute_shared +#define ecdh_context mbedtls_ecdh_context +#define ecdh_free mbedtls_ecdh_free +#define ecdh_gen_public mbedtls_ecdh_gen_public +#define ecdh_get_params mbedtls_ecdh_get_params +#define ecdh_init mbedtls_ecdh_init +#define ecdh_make_params mbedtls_ecdh_make_params +#define ecdh_make_public mbedtls_ecdh_make_public +#define ecdh_read_params mbedtls_ecdh_read_params +#define ecdh_read_public mbedtls_ecdh_read_public +#define ecdh_side mbedtls_ecdh_side +#define ecdsa_context mbedtls_ecdsa_context +#define ecdsa_free mbedtls_ecdsa_free +#define ecdsa_from_keypair mbedtls_ecdsa_from_keypair +#define ecdsa_genkey mbedtls_ecdsa_genkey +#define ecdsa_info mbedtls_ecdsa_info +#define ecdsa_init mbedtls_ecdsa_init +#define ecdsa_read_signature mbedtls_ecdsa_read_signature +#define ecdsa_sign mbedtls_ecdsa_sign +#define ecdsa_sign_det mbedtls_ecdsa_sign_det +#define ecdsa_verify mbedtls_ecdsa_verify +#define ecdsa_write_signature mbedtls_ecdsa_write_signature +#define ecdsa_write_signature_det mbedtls_ecdsa_write_signature_det +#define eckey_info mbedtls_eckey_info +#define eckeydh_info mbedtls_eckeydh_info +#define ecp_check_privkey mbedtls_ecp_check_privkey +#define ecp_check_pub_priv mbedtls_ecp_check_pub_priv +#define ecp_check_pubkey mbedtls_ecp_check_pubkey +#define ecp_copy mbedtls_ecp_copy +#define ecp_curve_info mbedtls_ecp_curve_info +#define ecp_curve_info_from_grp_id mbedtls_ecp_curve_info_from_grp_id +#define ecp_curve_info_from_name mbedtls_ecp_curve_info_from_name +#define ecp_curve_info_from_tls_id mbedtls_ecp_curve_info_from_tls_id +#define ecp_curve_list mbedtls_ecp_curve_list +#define ecp_gen_key mbedtls_ecp_gen_key +#define ecp_gen_keypair mbedtls_ecp_gen_keypair +#define ecp_group mbedtls_ecp_group +#define ecp_group_copy mbedtls_ecp_group_copy +#define ecp_group_free mbedtls_ecp_group_free +#define ecp_group_id mbedtls_ecp_group_id +#define ecp_group_init mbedtls_ecp_group_init +#define ecp_grp_id_list mbedtls_ecp_grp_id_list +#define ecp_is_zero mbedtls_ecp_is_zero +#define ecp_keypair mbedtls_ecp_keypair +#define ecp_keypair_free mbedtls_ecp_keypair_free +#define ecp_keypair_init mbedtls_ecp_keypair_init +#define ecp_mul mbedtls_ecp_mul +#define ecp_point mbedtls_ecp_point +#define ecp_point_free mbedtls_ecp_point_free +#define ecp_point_init mbedtls_ecp_point_init +#define ecp_point_read_binary mbedtls_ecp_point_read_binary +#define ecp_point_read_string mbedtls_ecp_point_read_string +#define ecp_point_write_binary mbedtls_ecp_point_write_binary +#define ecp_self_test mbedtls_ecp_self_test +#define ecp_set_zero mbedtls_ecp_set_zero +#define ecp_tls_read_group mbedtls_ecp_tls_read_group +#define ecp_tls_read_point mbedtls_ecp_tls_read_point +#define ecp_tls_write_group mbedtls_ecp_tls_write_group +#define ecp_tls_write_point mbedtls_ecp_tls_write_point +#define ecp_use_known_dp mbedtls_ecp_group_load +#define entropy_add_source mbedtls_entropy_add_source +#define entropy_context mbedtls_entropy_context +#define entropy_free mbedtls_entropy_free +#define entropy_func mbedtls_entropy_func +#define entropy_gather mbedtls_entropy_gather +#define entropy_init mbedtls_entropy_init +#define entropy_self_test mbedtls_entropy_self_test +#define entropy_update_manual mbedtls_entropy_update_manual +#define entropy_update_seed_file mbedtls_entropy_update_seed_file +#define entropy_write_seed_file mbedtls_entropy_write_seed_file +#define error_strerror mbedtls_strerror +#define f_source_ptr mbedtls_entropy_f_source_ptr +#define gcm_auth_decrypt mbedtls_gcm_auth_decrypt +#define gcm_context mbedtls_gcm_context +#define gcm_crypt_and_tag mbedtls_gcm_crypt_and_tag +#define gcm_finish mbedtls_gcm_finish +#define gcm_free mbedtls_gcm_free +#define gcm_init mbedtls_gcm_init +#define gcm_self_test mbedtls_gcm_self_test +#define gcm_starts mbedtls_gcm_starts +#define gcm_update mbedtls_gcm_update +#define get_timer mbedtls_timing_get_timer +#define hardclock mbedtls_timing_hardclock +#define hardclock_poll mbedtls_hardclock_poll +#define havege_free mbedtls_havege_free +#define havege_init mbedtls_havege_init +#define havege_poll mbedtls_havege_poll +#define havege_random mbedtls_havege_random +#define havege_state mbedtls_havege_state +#define hmac_drbg_context mbedtls_hmac_drbg_context +#define hmac_drbg_free mbedtls_hmac_drbg_free +#define hmac_drbg_init mbedtls_hmac_drbg_init +#define hmac_drbg_random mbedtls_hmac_drbg_random +#define hmac_drbg_random_with_add mbedtls_hmac_drbg_random_with_add +#define hmac_drbg_reseed mbedtls_hmac_drbg_reseed +#define hmac_drbg_self_test mbedtls_hmac_drbg_self_test +#define hmac_drbg_set_entropy_len mbedtls_hmac_drbg_set_entropy_len +#define hmac_drbg_set_prediction_resistance mbedtls_hmac_drbg_set_prediction_resistance +#define hmac_drbg_set_reseed_interval mbedtls_hmac_drbg_set_reseed_interval +#define hmac_drbg_update mbedtls_hmac_drbg_update +#define hmac_drbg_update_seed_file mbedtls_hmac_drbg_update_seed_file +#define hmac_drbg_write_seed_file mbedtls_hmac_drbg_write_seed_file +#define hr_time mbedtls_timing_hr_time +#define key_exchange_type_t mbedtls_key_exchange_type_t +#define md mbedtls_md +#define md2 mbedtls_md2 +#define md2_context mbedtls_md2_context +#define md2_finish mbedtls_md2_finish +#define md2_free mbedtls_md2_free +#define md2_info mbedtls_md2_info +#define md2_init mbedtls_md2_init +#define md2_process mbedtls_md2_process +#define md2_self_test mbedtls_md2_self_test +#define md2_starts mbedtls_md2_starts +#define md2_update mbedtls_md2_update +#define md4 mbedtls_md4 +#define md4_context mbedtls_md4_context +#define md4_finish mbedtls_md4_finish +#define md4_free mbedtls_md4_free +#define md4_info mbedtls_md4_info +#define md4_init mbedtls_md4_init +#define md4_process mbedtls_md4_process +#define md4_self_test mbedtls_md4_self_test +#define md4_starts mbedtls_md4_starts +#define md4_update mbedtls_md4_update +#define md5 mbedtls_md5 +#define md5_context mbedtls_md5_context +#define md5_finish mbedtls_md5_finish +#define md5_free mbedtls_md5_free +#define md5_info mbedtls_md5_info +#define md5_init mbedtls_md5_init +#define md5_process mbedtls_md5_process +#define md5_self_test mbedtls_md5_self_test +#define md5_starts mbedtls_md5_starts +#define md5_update mbedtls_md5_update +#define md_context_t mbedtls_md_context_t +#define md_file mbedtls_md_file +#define md_finish mbedtls_md_finish +#define md_free mbedtls_md_free +#define md_get_name mbedtls_md_get_name +#define md_get_size mbedtls_md_get_size +#define md_get_type mbedtls_md_get_type +#define md_hmac mbedtls_md_hmac +#define md_hmac_finish mbedtls_md_hmac_finish +#define md_hmac_reset mbedtls_md_hmac_reset +#define md_hmac_starts mbedtls_md_hmac_starts +#define md_hmac_update mbedtls_md_hmac_update +#define md_info_from_string mbedtls_md_info_from_string +#define md_info_from_type mbedtls_md_info_from_type +#define md_info_t mbedtls_md_info_t +#define md_init mbedtls_md_init +#define md_init_ctx mbedtls_md_init_ctx +#define md_list mbedtls_md_list +#define md_process mbedtls_md_process +#define md_starts mbedtls_md_starts +#define md_type_t mbedtls_md_type_t +#define md_update mbedtls_md_update +#define memory_buffer_alloc_cur_get mbedtls_memory_buffer_alloc_cur_get +#define memory_buffer_alloc_free mbedtls_memory_buffer_alloc_free +#define memory_buffer_alloc_init mbedtls_memory_buffer_alloc_init +#define memory_buffer_alloc_max_get mbedtls_memory_buffer_alloc_max_get +#define memory_buffer_alloc_max_reset mbedtls_memory_buffer_alloc_max_reset +#define memory_buffer_alloc_self_test mbedtls_memory_buffer_alloc_self_test +#define memory_buffer_alloc_status mbedtls_memory_buffer_alloc_status +#define memory_buffer_alloc_verify mbedtls_memory_buffer_alloc_verify +#define memory_buffer_set_verify mbedtls_memory_buffer_set_verify +#define mpi mbedtls_mpi +#define mpi_add_abs mbedtls_mpi_add_abs +#define mpi_add_int mbedtls_mpi_add_int +#define mpi_add_mpi mbedtls_mpi_add_mpi +#define mpi_cmp_abs mbedtls_mpi_cmp_abs +#define mpi_cmp_int mbedtls_mpi_cmp_int +#define mpi_cmp_mpi mbedtls_mpi_cmp_mpi +#define mpi_copy mbedtls_mpi_copy +#define mpi_div_int mbedtls_mpi_div_int +#define mpi_div_mpi mbedtls_mpi_div_mpi +#define mpi_exp_mod mbedtls_mpi_exp_mod +#define mpi_fill_random mbedtls_mpi_fill_random +#define mpi_free mbedtls_mpi_free +#define mpi_gcd mbedtls_mpi_gcd +#define mpi_gen_prime mbedtls_mpi_gen_prime +#define mpi_get_bit mbedtls_mpi_get_bit +#define mpi_grow mbedtls_mpi_grow +#define mpi_init mbedtls_mpi_init +#define mpi_inv_mod mbedtls_mpi_inv_mod +#define mpi_is_prime mbedtls_mpi_is_prime +#define mpi_lsb mbedtls_mpi_lsb +#define mpi_lset mbedtls_mpi_lset +#define mpi_mod_int mbedtls_mpi_mod_int +#define mpi_mod_mpi mbedtls_mpi_mod_mpi +#define mpi_msb mbedtls_mpi_bitlen +#define mpi_mul_int mbedtls_mpi_mul_int +#define mpi_mul_mpi mbedtls_mpi_mul_mpi +#define mpi_read_binary mbedtls_mpi_read_binary +#define mpi_read_file mbedtls_mpi_read_file +#define mpi_read_string mbedtls_mpi_read_string +#define mpi_safe_cond_assign mbedtls_mpi_safe_cond_assign +#define mpi_safe_cond_swap mbedtls_mpi_safe_cond_swap +#define mpi_self_test mbedtls_mpi_self_test +#define mpi_set_bit mbedtls_mpi_set_bit +#define mpi_shift_l mbedtls_mpi_shift_l +#define mpi_shift_r mbedtls_mpi_shift_r +#define mpi_shrink mbedtls_mpi_shrink +#define mpi_size mbedtls_mpi_size +#define mpi_sub_abs mbedtls_mpi_sub_abs +#define mpi_sub_int mbedtls_mpi_sub_int +#define mpi_sub_mpi mbedtls_mpi_sub_mpi +#define mpi_swap mbedtls_mpi_swap +#define mpi_write_binary mbedtls_mpi_write_binary +#define mpi_write_file mbedtls_mpi_write_file +#define mpi_write_string mbedtls_mpi_write_string +#define net_accept mbedtls_net_accept +#define net_bind mbedtls_net_bind +#define net_close mbedtls_net_free +#define net_connect mbedtls_net_connect +#define net_recv mbedtls_net_recv +#define net_recv_timeout mbedtls_net_recv_timeout +#define net_send mbedtls_net_send +#define net_set_block mbedtls_net_set_block +#define net_set_nonblock mbedtls_net_set_nonblock +#define net_usleep mbedtls_net_usleep +#define oid_descriptor_t mbedtls_oid_descriptor_t +#define oid_get_attr_short_name mbedtls_oid_get_attr_short_name +#define oid_get_cipher_alg mbedtls_oid_get_cipher_alg +#define oid_get_ec_grp mbedtls_oid_get_ec_grp +#define oid_get_extended_key_usage mbedtls_oid_get_extended_key_usage +#define oid_get_md_alg mbedtls_oid_get_md_alg +#define oid_get_numeric_string mbedtls_oid_get_numeric_string +#define oid_get_oid_by_ec_grp mbedtls_oid_get_oid_by_ec_grp +#define oid_get_oid_by_md mbedtls_oid_get_oid_by_md +#define oid_get_oid_by_pk_alg mbedtls_oid_get_oid_by_pk_alg +#define oid_get_oid_by_sig_alg mbedtls_oid_get_oid_by_sig_alg +#define oid_get_pk_alg mbedtls_oid_get_pk_alg +#define oid_get_pkcs12_pbe_alg mbedtls_oid_get_pkcs12_pbe_alg +#define oid_get_sig_alg mbedtls_oid_get_sig_alg +#define oid_get_sig_alg_desc mbedtls_oid_get_sig_alg_desc +#define oid_get_x509_ext_type mbedtls_oid_get_x509_ext_type +#define operation_t mbedtls_operation_t +#define padlock_supports mbedtls_padlock_has_support +#define padlock_xcryptcbc mbedtls_padlock_xcryptcbc +#define padlock_xcryptecb mbedtls_padlock_xcryptecb +#define pem_context mbedtls_pem_context +#define pem_free mbedtls_pem_free +#define pem_init mbedtls_pem_init +#define pem_read_buffer mbedtls_pem_read_buffer +#define pem_write_buffer mbedtls_pem_write_buffer +#define pk_can_do mbedtls_pk_can_do +#define pk_check_pair mbedtls_pk_check_pair +#define pk_context mbedtls_pk_context +#define pk_debug mbedtls_pk_debug +#define pk_debug_item mbedtls_pk_debug_item +#define pk_debug_type mbedtls_pk_debug_type +#define pk_decrypt mbedtls_pk_decrypt +#define pk_ec mbedtls_pk_ec +#define pk_encrypt mbedtls_pk_encrypt +#define pk_free mbedtls_pk_free +#define pk_get_len mbedtls_pk_get_len +#define pk_get_name mbedtls_pk_get_name +#define pk_get_size mbedtls_pk_get_bitlen +#define pk_get_type mbedtls_pk_get_type +#define pk_info_from_type mbedtls_pk_info_from_type +#define pk_info_t mbedtls_pk_info_t +#define pk_init mbedtls_pk_init +#define pk_init_ctx mbedtls_pk_setup +#define pk_init_ctx_rsa_alt mbedtls_pk_setup_rsa_alt +#define pk_load_file mbedtls_pk_load_file +#define pk_parse_key mbedtls_pk_parse_key +#define pk_parse_keyfile mbedtls_pk_parse_keyfile +#define pk_parse_public_key mbedtls_pk_parse_public_key +#define pk_parse_public_keyfile mbedtls_pk_parse_public_keyfile +#define pk_parse_subpubkey mbedtls_pk_parse_subpubkey +#define pk_rsa mbedtls_pk_rsa +#define pk_rsa_alt_decrypt_func mbedtls_pk_rsa_alt_decrypt_func +#define pk_rsa_alt_key_len_func mbedtls_pk_rsa_alt_key_len_func +#define pk_rsa_alt_sign_func mbedtls_pk_rsa_alt_sign_func +#define pk_rsassa_pss_options mbedtls_pk_rsassa_pss_options +#define pk_sign mbedtls_pk_sign +#define pk_type_t mbedtls_pk_type_t +#define pk_verify mbedtls_pk_verify +#define pk_verify_ext mbedtls_pk_verify_ext +#define pk_write_key_der mbedtls_pk_write_key_der +#define pk_write_key_pem mbedtls_pk_write_key_pem +#define pk_write_pubkey mbedtls_pk_write_pubkey +#define pk_write_pubkey_der mbedtls_pk_write_pubkey_der +#define pk_write_pubkey_pem mbedtls_pk_write_pubkey_pem +#define pkcs11_context mbedtls_pkcs11_context +#define pkcs11_decrypt mbedtls_pkcs11_decrypt +#define pkcs11_priv_key_free mbedtls_pkcs11_priv_key_free +#define pkcs11_priv_key_init mbedtls_pkcs11_priv_key_bind +#define pkcs11_sign mbedtls_pkcs11_sign +#define pkcs11_x509_cert_init mbedtls_pkcs11_x509_cert_bind +#define pkcs12_derivation mbedtls_pkcs12_derivation +#define pkcs12_pbe mbedtls_pkcs12_pbe +#define pkcs12_pbe_sha1_rc4_128 mbedtls_pkcs12_pbe_sha1_rc4_128 +#define pkcs5_pbes2 mbedtls_pkcs5_pbes2 +#define pkcs5_pbkdf2_hmac mbedtls_pkcs5_pbkdf2_hmac +#define pkcs5_self_test mbedtls_pkcs5_self_test +#define platform_entropy_poll mbedtls_platform_entropy_poll +#define platform_set_exit mbedtls_platform_set_exit +#define platform_set_fprintf mbedtls_platform_set_fprintf +#define platform_set_printf mbedtls_platform_set_printf +#define platform_set_snprintf mbedtls_platform_set_snprintf +#define polarssl_exit mbedtls_exit +#define polarssl_fprintf mbedtls_fprintf +#define polarssl_free mbedtls_free +#define polarssl_mutex_free mbedtls_mutex_free +#define polarssl_mutex_init mbedtls_mutex_init +#define polarssl_mutex_lock mbedtls_mutex_lock +#define polarssl_mutex_unlock mbedtls_mutex_unlock +#define polarssl_printf mbedtls_printf +#define polarssl_snprintf mbedtls_snprintf +#define polarssl_strerror mbedtls_strerror +#define ripemd160 mbedtls_ripemd160 +#define ripemd160_context mbedtls_ripemd160_context +#define ripemd160_finish mbedtls_ripemd160_finish +#define ripemd160_free mbedtls_ripemd160_free +#define ripemd160_info mbedtls_ripemd160_info +#define ripemd160_init mbedtls_ripemd160_init +#define ripemd160_process mbedtls_ripemd160_process +#define ripemd160_self_test mbedtls_ripemd160_self_test +#define ripemd160_starts mbedtls_ripemd160_starts +#define ripemd160_update mbedtls_ripemd160_update +#define rsa_alt_context mbedtls_rsa_alt_context +#define rsa_alt_info mbedtls_rsa_alt_info +#define rsa_check_privkey mbedtls_rsa_check_privkey +#define rsa_check_pub_priv mbedtls_rsa_check_pub_priv +#define rsa_check_pubkey mbedtls_rsa_check_pubkey +#define rsa_context mbedtls_rsa_context +#define rsa_copy mbedtls_rsa_copy +#define rsa_free mbedtls_rsa_free +#define rsa_gen_key mbedtls_rsa_gen_key +#define rsa_info mbedtls_rsa_info +#define rsa_init mbedtls_rsa_init +#define rsa_pkcs1_decrypt mbedtls_rsa_pkcs1_decrypt +#define rsa_pkcs1_encrypt mbedtls_rsa_pkcs1_encrypt +#define rsa_pkcs1_sign mbedtls_rsa_pkcs1_sign +#define rsa_pkcs1_verify mbedtls_rsa_pkcs1_verify +#define rsa_private mbedtls_rsa_private +#define rsa_public mbedtls_rsa_public +#define rsa_rsaes_oaep_decrypt mbedtls_rsa_rsaes_oaep_decrypt +#define rsa_rsaes_oaep_encrypt mbedtls_rsa_rsaes_oaep_encrypt +#define rsa_rsaes_pkcs1_v15_decrypt mbedtls_rsa_rsaes_pkcs1_v15_decrypt +#define rsa_rsaes_pkcs1_v15_encrypt mbedtls_rsa_rsaes_pkcs1_v15_encrypt +#define rsa_rsassa_pkcs1_v15_sign mbedtls_rsa_rsassa_pkcs1_v15_sign +#define rsa_rsassa_pkcs1_v15_verify mbedtls_rsa_rsassa_pkcs1_v15_verify +#define rsa_rsassa_pss_sign mbedtls_rsa_rsassa_pss_sign +#define rsa_rsassa_pss_verify mbedtls_rsa_rsassa_pss_verify +#define rsa_rsassa_pss_verify_ext mbedtls_rsa_rsassa_pss_verify_ext +#define rsa_self_test mbedtls_rsa_self_test +#define rsa_set_padding mbedtls_rsa_set_padding +#define safer_memcmp mbedtls_ssl_safer_memcmp +#define set_alarm mbedtls_set_alarm +#define sha1 mbedtls_sha1 +#define sha1_context mbedtls_sha1_context +#define sha1_finish mbedtls_sha1_finish +#define sha1_free mbedtls_sha1_free +#define sha1_info mbedtls_sha1_info +#define sha1_init mbedtls_sha1_init +#define sha1_process mbedtls_sha1_process +#define sha1_self_test mbedtls_sha1_self_test +#define sha1_starts mbedtls_sha1_starts +#define sha1_update mbedtls_sha1_update +#define sha224_info mbedtls_sha224_info +#define sha256 mbedtls_sha256 +#define sha256_context mbedtls_sha256_context +#define sha256_finish mbedtls_sha256_finish +#define sha256_free mbedtls_sha256_free +#define sha256_info mbedtls_sha256_info +#define sha256_init mbedtls_sha256_init +#define sha256_process mbedtls_sha256_process +#define sha256_self_test mbedtls_sha256_self_test +#define sha256_starts mbedtls_sha256_starts +#define sha256_update mbedtls_sha256_update +#define sha384_info mbedtls_sha384_info +#define sha512 mbedtls_sha512 +#define sha512_context mbedtls_sha512_context +#define sha512_finish mbedtls_sha512_finish +#define sha512_free mbedtls_sha512_free +#define sha512_info mbedtls_sha512_info +#define sha512_init mbedtls_sha512_init +#define sha512_process mbedtls_sha512_process +#define sha512_self_test mbedtls_sha512_self_test +#define sha512_starts mbedtls_sha512_starts +#define sha512_update mbedtls_sha512_update +#define source_state mbedtls_entropy_source_state +#define ssl_cache_context mbedtls_ssl_cache_context +#define ssl_cache_entry mbedtls_ssl_cache_entry +#define ssl_cache_free mbedtls_ssl_cache_free +#define ssl_cache_get mbedtls_ssl_cache_get +#define ssl_cache_init mbedtls_ssl_cache_init +#define ssl_cache_set mbedtls_ssl_cache_set +#define ssl_cache_set_max_entries mbedtls_ssl_cache_set_max_entries +#define ssl_cache_set_timeout mbedtls_ssl_cache_set_timeout +#define ssl_check_cert_usage mbedtls_ssl_check_cert_usage +#define ssl_ciphersuite_from_id mbedtls_ssl_ciphersuite_from_id +#define ssl_ciphersuite_from_string mbedtls_ssl_ciphersuite_from_string +#define ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t +#define ssl_ciphersuite_uses_ec mbedtls_ssl_ciphersuite_uses_ec +#define ssl_ciphersuite_uses_psk mbedtls_ssl_ciphersuite_uses_psk +#define ssl_close_notify mbedtls_ssl_close_notify +#define ssl_context mbedtls_ssl_context +#define ssl_cookie_check mbedtls_ssl_cookie_check +#define ssl_cookie_check_t mbedtls_ssl_cookie_check_t +#define ssl_cookie_ctx mbedtls_ssl_cookie_ctx +#define ssl_cookie_free mbedtls_ssl_cookie_free +#define ssl_cookie_init mbedtls_ssl_cookie_init +#define ssl_cookie_set_timeout mbedtls_ssl_cookie_set_timeout +#define ssl_cookie_setup mbedtls_ssl_cookie_setup +#define ssl_cookie_write mbedtls_ssl_cookie_write +#define ssl_cookie_write_t mbedtls_ssl_cookie_write_t +#define ssl_derive_keys mbedtls_ssl_derive_keys +#define ssl_dtls_replay_check mbedtls_ssl_dtls_replay_check +#define ssl_dtls_replay_update mbedtls_ssl_dtls_replay_update +#define ssl_fetch_input mbedtls_ssl_fetch_input +#define ssl_flight_item mbedtls_ssl_flight_item +#define ssl_flush_output mbedtls_ssl_flush_output +#define ssl_free mbedtls_ssl_free +#define ssl_get_alpn_protocol mbedtls_ssl_get_alpn_protocol +#define ssl_get_bytes_avail mbedtls_ssl_get_bytes_avail +#define ssl_get_ciphersuite mbedtls_ssl_get_ciphersuite +#define ssl_get_ciphersuite_id mbedtls_ssl_get_ciphersuite_id +#define ssl_get_ciphersuite_name mbedtls_ssl_get_ciphersuite_name +#define ssl_get_ciphersuite_sig_pk_alg mbedtls_ssl_get_ciphersuite_sig_pk_alg +#define ssl_get_peer_cert mbedtls_ssl_get_peer_cert +#define ssl_get_record_expansion mbedtls_ssl_get_record_expansion +#define ssl_get_session mbedtls_ssl_get_session +#define ssl_get_verify_result mbedtls_ssl_get_verify_result +#define ssl_get_version mbedtls_ssl_get_version +#define ssl_handshake mbedtls_ssl_handshake +#define ssl_handshake_client_step mbedtls_ssl_handshake_client_step +#define ssl_handshake_free mbedtls_ssl_handshake_free +#define ssl_handshake_params mbedtls_ssl_handshake_params +#define ssl_handshake_server_step mbedtls_ssl_handshake_server_step +#define ssl_handshake_step mbedtls_ssl_handshake_step +#define ssl_handshake_wrapup mbedtls_ssl_handshake_wrapup +#define ssl_hdr_len mbedtls_ssl_hdr_len +#define ssl_hs_hdr_len mbedtls_ssl_hs_hdr_len +#define ssl_hw_record_activate mbedtls_ssl_hw_record_activate +#define ssl_hw_record_finish mbedtls_ssl_hw_record_finish +#define ssl_hw_record_init mbedtls_ssl_hw_record_init +#define ssl_hw_record_read mbedtls_ssl_hw_record_read +#define ssl_hw_record_reset mbedtls_ssl_hw_record_reset +#define ssl_hw_record_write mbedtls_ssl_hw_record_write +#define ssl_init mbedtls_ssl_init +#define ssl_key_cert mbedtls_ssl_key_cert +#define ssl_legacy_renegotiation mbedtls_ssl_conf_legacy_renegotiation +#define ssl_list_ciphersuites mbedtls_ssl_list_ciphersuites +#define ssl_md_alg_from_hash mbedtls_ssl_md_alg_from_hash +#define ssl_optimize_checksum mbedtls_ssl_optimize_checksum +#define ssl_own_cert mbedtls_ssl_own_cert +#define ssl_own_key mbedtls_ssl_own_key +#define ssl_parse_certificate mbedtls_ssl_parse_certificate +#define ssl_parse_change_cipher_spec mbedtls_ssl_parse_change_cipher_spec +#define ssl_parse_finished mbedtls_ssl_parse_finished +#define ssl_pk_alg_from_sig mbedtls_ssl_pk_alg_from_sig +#define ssl_pkcs11_decrypt mbedtls_ssl_pkcs11_decrypt +#define ssl_pkcs11_key_len mbedtls_ssl_pkcs11_key_len +#define ssl_pkcs11_sign mbedtls_ssl_pkcs11_sign +#define ssl_psk_derive_premaster mbedtls_ssl_psk_derive_premaster +#define ssl_read mbedtls_ssl_read +#define ssl_read_record mbedtls_ssl_read_record +#define ssl_read_version mbedtls_ssl_read_version +#define ssl_recv_flight_completed mbedtls_ssl_recv_flight_completed +#define ssl_renegotiate mbedtls_ssl_renegotiate +#define ssl_resend mbedtls_ssl_resend +#define ssl_reset_checksum mbedtls_ssl_reset_checksum +#define ssl_send_alert_message mbedtls_ssl_send_alert_message +#define ssl_send_fatal_handshake_failure mbedtls_ssl_send_fatal_handshake_failure +#define ssl_send_flight_completed mbedtls_ssl_send_flight_completed +#define ssl_session mbedtls_ssl_session +#define ssl_session_free mbedtls_ssl_session_free +#define ssl_session_init mbedtls_ssl_session_init +#define ssl_session_reset mbedtls_ssl_session_reset +#define ssl_set_alpn_protocols mbedtls_ssl_conf_alpn_protocols +#define ssl_set_arc4_support mbedtls_ssl_conf_arc4_support +#define ssl_set_authmode mbedtls_ssl_conf_authmode +#define ssl_set_bio mbedtls_ssl_set_bio +#define ssl_set_ca_chain mbedtls_ssl_conf_ca_chain +#define ssl_set_cbc_record_splitting mbedtls_ssl_conf_cbc_record_splitting +#define ssl_set_ciphersuites mbedtls_ssl_conf_ciphersuites +#define ssl_set_ciphersuites_for_version mbedtls_ssl_conf_ciphersuites_for_version +#define ssl_set_client_transport_id mbedtls_ssl_set_client_transport_id +#define ssl_set_curves mbedtls_ssl_conf_curves +#define ssl_set_dbg mbedtls_ssl_conf_dbg +#define ssl_set_dh_param mbedtls_ssl_conf_dh_param +#define ssl_set_dh_param_ctx mbedtls_ssl_conf_dh_param_ctx +#define ssl_set_dtls_anti_replay mbedtls_ssl_conf_dtls_anti_replay +#define ssl_set_dtls_badmac_limit mbedtls_ssl_conf_dtls_badmac_limit +#define ssl_set_dtls_cookies mbedtls_ssl_conf_dtls_cookies +#define ssl_set_encrypt_then_mac mbedtls_ssl_conf_encrypt_then_mac +#define ssl_set_endpoint mbedtls_ssl_conf_endpoint +#define ssl_set_extended_master_secret mbedtls_ssl_conf_extended_master_secret +#define ssl_set_fallback mbedtls_ssl_conf_fallback +#define ssl_set_handshake_timeout mbedtls_ssl_conf_handshake_timeout +#define ssl_set_hostname mbedtls_ssl_set_hostname +#define ssl_set_max_frag_len mbedtls_ssl_conf_max_frag_len +#define ssl_set_max_version mbedtls_ssl_conf_max_version +#define ssl_set_min_version mbedtls_ssl_conf_min_version +#define ssl_set_own_cert mbedtls_ssl_conf_own_cert +#define ssl_set_psk mbedtls_ssl_conf_psk +#define ssl_set_psk_cb mbedtls_ssl_conf_psk_cb +#define ssl_set_renegotiation mbedtls_ssl_conf_renegotiation +#define ssl_set_renegotiation_enforced mbedtls_ssl_conf_renegotiation_enforced +#define ssl_set_renegotiation_period mbedtls_ssl_conf_renegotiation_period +#define ssl_set_rng mbedtls_ssl_conf_rng +#define ssl_set_session mbedtls_ssl_set_session +#define ssl_set_session_cache mbedtls_ssl_conf_session_cache +#define ssl_set_session_tickets mbedtls_ssl_conf_session_tickets +#define ssl_set_sni mbedtls_ssl_conf_sni +#define ssl_set_transport mbedtls_ssl_conf_transport +#define ssl_set_truncated_hmac mbedtls_ssl_conf_truncated_hmac +#define ssl_set_verify mbedtls_ssl_conf_verify +#define ssl_sig_from_pk mbedtls_ssl_sig_from_pk +#define ssl_states mbedtls_ssl_states +#define ssl_transform mbedtls_ssl_transform +#define ssl_transform_free mbedtls_ssl_transform_free +#define ssl_write mbedtls_ssl_write +#define ssl_write_certificate mbedtls_ssl_write_certificate +#define ssl_write_change_cipher_spec mbedtls_ssl_write_change_cipher_spec +#define ssl_write_finished mbedtls_ssl_write_finished +#define ssl_write_record mbedtls_ssl_write_record +#define ssl_write_version mbedtls_ssl_write_version +#define supported_ciphers mbedtls_cipher_supported +#define t_sint mbedtls_mpi_sint +#define t_udbl mbedtls_t_udbl +#define t_uint mbedtls_mpi_uint +#define test_ca_crt mbedtls_test_ca_crt +#define test_ca_crt_ec mbedtls_test_ca_crt_ec +#define test_ca_crt_rsa mbedtls_test_ca_crt_rsa +#define test_ca_key mbedtls_test_ca_key +#define test_ca_key_ec mbedtls_test_ca_key_ec +#define test_ca_key_rsa mbedtls_test_ca_key_rsa +#define test_ca_list mbedtls_test_cas_pem +#define test_ca_pwd mbedtls_test_ca_pwd +#define test_ca_pwd_ec mbedtls_test_ca_pwd_ec +#define test_ca_pwd_rsa mbedtls_test_ca_pwd_rsa +#define test_cli_crt mbedtls_test_cli_crt +#define test_cli_crt_ec mbedtls_test_cli_crt_ec +#define test_cli_crt_rsa mbedtls_test_cli_crt_rsa +#define test_cli_key mbedtls_test_cli_key +#define test_cli_key_ec mbedtls_test_cli_key_ec +#define test_cli_key_rsa mbedtls_test_cli_key_rsa +#define test_srv_crt mbedtls_test_srv_crt +#define test_srv_crt_ec mbedtls_test_srv_crt_ec +#define test_srv_crt_rsa mbedtls_test_srv_crt_rsa +#define test_srv_key mbedtls_test_srv_key +#define test_srv_key_ec mbedtls_test_srv_key_ec +#define test_srv_key_rsa mbedtls_test_srv_key_rsa +#define threading_mutex_t mbedtls_threading_mutex_t +#define threading_set_alt mbedtls_threading_set_alt +#define timing_self_test mbedtls_timing_self_test +#define version_check_feature mbedtls_version_check_feature +#define version_get_number mbedtls_version_get_number +#define version_get_string mbedtls_version_get_string +#define version_get_string_full mbedtls_version_get_string_full +#define x509_bitstring mbedtls_x509_bitstring +#define x509_buf mbedtls_x509_buf +#define x509_crl mbedtls_x509_crl +#define x509_crl_entry mbedtls_x509_crl_entry +#define x509_crl_free mbedtls_x509_crl_free +#define x509_crl_info mbedtls_x509_crl_info +#define x509_crl_init mbedtls_x509_crl_init +#define x509_crl_parse mbedtls_x509_crl_parse +#define x509_crl_parse_der mbedtls_x509_crl_parse_der +#define x509_crl_parse_file mbedtls_x509_crl_parse_file +#define x509_crt mbedtls_x509_crt +#define x509_crt_check_extended_key_usage mbedtls_x509_crt_check_extended_key_usage +#define x509_crt_check_key_usage mbedtls_x509_crt_check_key_usage +#define x509_crt_free mbedtls_x509_crt_free +#define x509_crt_info mbedtls_x509_crt_info +#define x509_crt_init mbedtls_x509_crt_init +#define x509_crt_parse mbedtls_x509_crt_parse +#define x509_crt_parse_der mbedtls_x509_crt_parse_der +#define x509_crt_parse_file mbedtls_x509_crt_parse_file +#define x509_crt_parse_path mbedtls_x509_crt_parse_path +#define x509_crt_revoked mbedtls_x509_crt_is_revoked +#define x509_crt_verify mbedtls_x509_crt_verify +#define x509_csr mbedtls_x509_csr +#define x509_csr_free mbedtls_x509_csr_free +#define x509_csr_info mbedtls_x509_csr_info +#define x509_csr_init mbedtls_x509_csr_init +#define x509_csr_parse mbedtls_x509_csr_parse +#define x509_csr_parse_der mbedtls_x509_csr_parse_der +#define x509_csr_parse_file mbedtls_x509_csr_parse_file +#define x509_dn_gets mbedtls_x509_dn_gets +#define x509_get_alg mbedtls_x509_get_alg +#define x509_get_alg_null mbedtls_x509_get_alg_null +#define x509_get_ext mbedtls_x509_get_ext +#define x509_get_name mbedtls_x509_get_name +#define x509_get_rsassa_pss_params mbedtls_x509_get_rsassa_pss_params +#define x509_get_serial mbedtls_x509_get_serial +#define x509_get_sig mbedtls_x509_get_sig +#define x509_get_sig_alg mbedtls_x509_get_sig_alg +#define x509_get_time mbedtls_x509_get_time +#define x509_key_size_helper mbedtls_x509_key_size_helper +#define x509_name mbedtls_x509_name +#define x509_self_test mbedtls_x509_self_test +#define x509_sequence mbedtls_x509_sequence +#define x509_serial_gets mbedtls_x509_serial_gets +#define x509_set_extension mbedtls_x509_set_extension +#define x509_sig_alg_gets mbedtls_x509_sig_alg_gets +#define x509_string_to_names mbedtls_x509_string_to_names +#define x509_time mbedtls_x509_time +#define x509_time_expired mbedtls_x509_time_is_past +#define x509_time_future mbedtls_x509_time_is_future +#define x509_write_extensions mbedtls_x509_write_extensions +#define x509_write_names mbedtls_x509_write_names +#define x509_write_sig mbedtls_x509_write_sig +#define x509write_cert mbedtls_x509write_cert +#define x509write_crt_der mbedtls_x509write_crt_der +#define x509write_crt_free mbedtls_x509write_crt_free +#define x509write_crt_init mbedtls_x509write_crt_init +#define x509write_crt_pem mbedtls_x509write_crt_pem +#define x509write_crt_set_authority_key_identifier mbedtls_x509write_crt_set_authority_key_identifier +#define x509write_crt_set_basic_constraints mbedtls_x509write_crt_set_basic_constraints +#define x509write_crt_set_extension mbedtls_x509write_crt_set_extension +#define x509write_crt_set_issuer_key mbedtls_x509write_crt_set_issuer_key +#define x509write_crt_set_issuer_name mbedtls_x509write_crt_set_issuer_name +#define x509write_crt_set_key_usage mbedtls_x509write_crt_set_key_usage +#define x509write_crt_set_md_alg mbedtls_x509write_crt_set_md_alg +#define x509write_crt_set_ns_cert_type mbedtls_x509write_crt_set_ns_cert_type +#define x509write_crt_set_serial mbedtls_x509write_crt_set_serial +#define x509write_crt_set_subject_key mbedtls_x509write_crt_set_subject_key +#define x509write_crt_set_subject_key_identifier mbedtls_x509write_crt_set_subject_key_identifier +#define x509write_crt_set_subject_name mbedtls_x509write_crt_set_subject_name +#define x509write_crt_set_validity mbedtls_x509write_crt_set_validity +#define x509write_crt_set_version mbedtls_x509write_crt_set_version +#define x509write_csr mbedtls_x509write_csr +#define x509write_csr_der mbedtls_x509write_csr_der +#define x509write_csr_free mbedtls_x509write_csr_free +#define x509write_csr_init mbedtls_x509write_csr_init +#define x509write_csr_pem mbedtls_x509write_csr_pem +#define x509write_csr_set_extension mbedtls_x509write_csr_set_extension +#define x509write_csr_set_key mbedtls_x509write_csr_set_key +#define x509write_csr_set_key_usage mbedtls_x509write_csr_set_key_usage +#define x509write_csr_set_md_alg mbedtls_x509write_csr_set_md_alg +#define x509write_csr_set_ns_cert_type mbedtls_x509write_csr_set_ns_cert_type +#define x509write_csr_set_subject_name mbedtls_x509write_csr_set_subject_name +#define xtea_context mbedtls_xtea_context +#define xtea_crypt_cbc mbedtls_xtea_crypt_cbc +#define xtea_crypt_ecb mbedtls_xtea_crypt_ecb +#define xtea_free mbedtls_xtea_free +#define xtea_init mbedtls_xtea_init +#define xtea_self_test mbedtls_xtea_self_test +#define xtea_setup mbedtls_xtea_setup + +#endif /* compat-1.3.h */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ diff --git a/external/mbedtls/include/mbedtls/config.h b/external/mbedtls/include/mbedtls/config.h new file mode 100644 index 0000000..fff4240 --- /dev/null +++ b/external/mbedtls/include/mbedtls/config.h @@ -0,0 +1,3444 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/aria.c + * library/timing.c + * include/mbedtls/bn_mul.h + * + * Required by: + * MBEDTLS_AESNI_C + * MBEDTLS_PADLOCK_C + * + * Comment to disable the use of assembly code. + */ +#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \def MBEDTLS_NO_64BIT_MULTIPLICATION + * + * The platform lacks support for 32x32 -> 64-bit multiplication. + * + * Used in: + * library/poly1305.c + * + * Some parts of the library may use multiplication of two unsigned 32-bit + * operands with a 64-bit result in order to speed up computations. On some + * platforms, this is not available in hardware and has to be implemented in + * software, usually in a library provided by the toolchain. + * + * Sometimes it is not desirable to have to link to that library. This option + * removes the dependency of that library on platforms that lack a hardware + * 64-bit multiplier by embedding a software implementation in Mbed TLS. + * + * Note that depending on the compiler, this may decrease performance compared + * to using the library function provided by the toolchain. + */ +//#define MBEDTLS_NO_64BIT_MULTIPLICATION + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, + * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and + * MBEDTLS_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions + */ +#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h, time(), and an implementation for + * mbedtls_platform_gmtime_r() (see below). + * The time needs to be correct (not necessarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + * + * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that + * behaves similarly to the gmtime_r() function from the C standard. Refer to + * the documentation for mbedtls_platform_gmtime_r() for more information. + * + * \note It is possible to configure an implementation for + * mbedtls_platform_gmtime_r() at compile-time by using the macro + * MBEDTLS_PLATFORM_GMTIME_R_ALT. + */ +#define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +//#define MBEDTLS_PLATFORM_MEMORY + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_EXIT_ALT + * + * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT + +/** + * \def MBEDTLS_DEPRECATED_WARNING + * + * Mark deprecated functions so that they generate a warning if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_DEPRECATED_REMOVED + * + * Remove deprecated functions so that they generate an error if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * Uncomment to get errors on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_REMOVED + +/** + * \def MBEDTLS_CHECK_PARAMS + * + * This configuration option controls whether the library validates more of + * the parameters passed to it. + * + * When this flag is not defined, the library only attempts to validate an + * input parameter if: (1) they may come from the outside world (such as the + * network, the filesystem, etc.) or (2) not validating them could result in + * internal memory errors such as overflowing a buffer controlled by the + * library. On the other hand, it doesn't attempt to validate parameters whose + * values are fully controlled by the application (such as pointers). + * + * When this flag is defined, the library additionally attempts to validate + * parameters that are fully controlled by the application, and should always + * be valid if the application code is fully correct and trusted. + * + * For example, when a function accepts as input a pointer to a buffer that may + * contain untrusted data, and its documentation mentions that this pointer + * must not be NULL: + * - The pointer is checked to be non-NULL only if this option is enabled. + * - The content of the buffer is always validated. + * + * When this flag is defined, if a library function receives a parameter that + * is invalid: + * 1. The function will invoke the macro MBEDTLS_PARAM_FAILED(). + * 2. If MBEDTLS_PARAM_FAILED() did not terminate the program, the function + * will immediately return. If the function returns an Mbed TLS error code, + * the error code in this case is MBEDTLS_ERR_xxx_BAD_INPUT_DATA. + * + * When defining this flag, you also need to arrange a definition for + * MBEDTLS_PARAM_FAILED(). You can do this by any of the following methods: + * - By default, the library defines MBEDTLS_PARAM_FAILED() to call a + * function mbedtls_param_failed(), but the library does not define this + * function. If you do not make any other arrangements, you must provide + * the function mbedtls_param_failed() in your application. + * See `platform_util.h` for its prototype. + * - If you enable the macro #MBEDTLS_CHECK_PARAMS_ASSERT, then the + * library defines #MBEDTLS_PARAM_FAILED(\c cond) to be `assert(cond)`. + * You can still supply an alternative definition of + * MBEDTLS_PARAM_FAILED(), which may call `assert`. + * - If you define a macro MBEDTLS_PARAM_FAILED() before including `config.h` + * or you uncomment the definition of MBEDTLS_PARAM_FAILED() in `config.h`, + * the library will call the macro that you defined and will not supply + * its own version. Note that if MBEDTLS_PARAM_FAILED() calls `assert`, + * you need to enable #MBEDTLS_CHECK_PARAMS_ASSERT so that library source + * files include ``. + * + * Uncomment to enable validation of application-controlled parameters. + */ +//#define MBEDTLS_CHECK_PARAMS + +/** + * \def MBEDTLS_CHECK_PARAMS_ASSERT + * + * Allow MBEDTLS_PARAM_FAILED() to call `assert`, and make it default to + * `assert`. This macro is only used if #MBEDTLS_CHECK_PARAMS is defined. + * + * If this macro is not defined, then MBEDTLS_PARAM_FAILED() defaults to + * calling a function mbedtls_param_failed(). See the documentation of + * #MBEDTLS_CHECK_PARAMS for details. + * + * Uncomment to allow MBEDTLS_PARAM_FAILED() to call `assert`. + */ +//#define MBEDTLS_CHECK_PARAMS_ASSERT + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def MBEDTLS_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS_AES_ALT + * + * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternate core implementation of a symmetric crypto, an arithmetic or hash + * module (e.g. platform specific assembly optimized implementations). Keep + * in mind that the function prototypes should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base + * function declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + * + * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their + * use constitutes a security risk. If possible, we recommend + * avoiding dependencies on them, and considering stronger message + * digests and ciphers instead. + * + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_ARIA_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CHACHA20_ALT +//#define MBEDTLS_CHACHAPOLY_ALT +//#define MBEDTLS_CMAC_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_DHM_ALT +//#define MBEDTLS_ECJPAKE_ALT +//#define MBEDTLS_GCM_ALT +//#define MBEDTLS_NIST_KW_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_POLY1305_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_RSA_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT +//#define MBEDTLS_XTEA_ALT + +/* + * When replacing the elliptic curve module, pleace consider, that it is + * implemented with two .c files: + * - ecp.c + * - ecp_curves.c + * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT + * macros as described above. The only difference is that you have to make sure + * that you provide functionality for both .c files. + */ +//#define MBEDTLS_ECP_ALT + +/** + * \def MBEDTLS_MD2_PROCESS_ALT + * + * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you + * alternate core implementation of symmetric crypto or hash function. Keep in + * mind that function prototypes should remain the same. + * + * This replaces only one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will + * no longer provide the mbedtls_sha1_process() function, but it will still provide + * the other function (using your mbedtls_sha1_process() function) and the definition + * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible + * with this definition. + * + * \note Because of a signature change, the core AES encryption and decryption routines are + * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, + * respectively. When setting up alternative implementations, these functions should + * be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt + * must stay untouched. + * + * \note If you use the AES_xxx_ALT macros, then is is recommended to also set + * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + * + * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use + * constitutes a security risk. If possible, we recommend avoiding + * dependencies on them, and considering stronger message digests + * and ciphers instead. + * + * \warning If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are + * enabled, then the deterministic ECDH signature functions pass the + * the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore + * alternative implementations should use the RNG only for generating + * the ephemeral key and nothing else. If this is not possible, then + * MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative + * implementation should be provided for mbedtls_ecdsa_sign_det_ext() + * (and for mbedtls_ecdsa_sign_det() too if backward compatibility is + * desirable). + * + */ +//#define MBEDTLS_MD2_PROCESS_ALT +//#define MBEDTLS_MD4_PROCESS_ALT +//#define MBEDTLS_MD5_PROCESS_ALT +//#define MBEDTLS_RIPEMD160_PROCESS_ALT +//#define MBEDTLS_SHA1_PROCESS_ALT +//#define MBEDTLS_SHA256_PROCESS_ALT +//#define MBEDTLS_SHA512_PROCESS_ALT +//#define MBEDTLS_DES_SETKEY_ALT +//#define MBEDTLS_DES_CRYPT_ECB_ALT +//#define MBEDTLS_DES3_CRYPT_ECB_ALT +//#define MBEDTLS_AES_SETKEY_ENC_ALT +//#define MBEDTLS_AES_SETKEY_DEC_ALT +//#define MBEDTLS_AES_ENCRYPT_ALT +//#define MBEDTLS_AES_DECRYPT_ALT +//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT +//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT +//#define MBEDTLS_ECDSA_VERIFY_ALT +//#define MBEDTLS_ECDSA_SIGN_ALT +//#define MBEDTLS_ECDSA_GENKEY_ALT + +/** + * \def MBEDTLS_ECP_INTERNAL_ALT + * + * Expose a part of the internal interface of the Elliptic Curve Point module. + * + * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternative core implementation of elliptic curve arithmetic. Keep in mind + * that function prototypes should remain the same. + * + * This partially replaces one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation + * is still present and it is used for group structures not supported by the + * alternative. + * + * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT + * and implementing the following functions: + * unsigned char mbedtls_internal_ecp_grp_capable( + * const mbedtls_ecp_group *grp ) + * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) + * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ) + * The mbedtls_internal_ecp_grp_capable function should return 1 if the + * replacement functions implement arithmetic for the given group and 0 + * otherwise. + * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are + * called before and after each point operation and provide an opportunity to + * implement optimized set up and tear down instructions. + * + * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and + * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac + * function, but will use your mbedtls_internal_ecp_double_jac if the group is + * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when + * receives it as an argument). If the group is not supported then the original + * implementation is used. The other functions and the definition of + * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your + * implementation of mbedtls_internal_ecp_double_jac and + * mbedtls_internal_ecp_grp_capable must be compatible with this definition. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +/* Required for all the functions in this section */ +//#define MBEDTLS_ECP_INTERNAL_ALT +/* Support for Weierstrass curves with Jacobi representation */ +//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT +//#define MBEDTLS_ECP_ADD_MIXED_ALT +//#define MBEDTLS_ECP_DOUBLE_JAC_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT +/* Support for curves with Montgomery arithmetic */ +//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT +//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT +//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT + +/** + * \def MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN + * + * Enable testing of the constant-flow nature of some sensitive functions with + * clang's MemorySanitizer. This causes some existing tests to also test + * this non-functional property of the code under test. + * + * This setting requires compiling with clang -fsanitize=memory. The test + * suites can then be run normally. + * + * \warning This macro is only used for extended testing; it is not considered + * part of the library's API, so it may change or disappear at any time. + * + * Uncomment to enable testing of the constant-flow nature of selected code. + */ +//#define MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN + +/** + * \def MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND + * + * Enable testing of the constant-flow nature of some sensitive functions with + * valgrind's memcheck tool. This causes some existing tests to also test + * this non-functional property of the code under test. + * + * This setting requires valgrind headers for building, and is only useful for + * testing if the tests suites are run with valgrind's memcheck. This can be + * done for an individual test suite with 'valgrind ./test_suite_xxx', or when + * using CMake, this can be done for all test suites with 'make memcheck'. + * + * \warning This macro is only used for extended testing; it is not considered + * part of the library's API, so it may change or disappear at any time. + * + * Uncomment to enable testing of the constant-flow nature of selected code. + */ +//#define MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND + +/** + * \def MBEDTLS_TEST_NULL_ENTROPY + * + * Enables testing and use of mbed TLS without any configured entropy sources. + * This permits use of the library on platforms before an entropy source has + * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the + * MBEDTLS_ENTROPY_NV_SEED switches). + * + * WARNING! This switch MUST be disabled in production builds, and is suitable + * only for development. + * Enabling the switch negates any security provided by the library. + * + * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + */ +//#define MBEDTLS_TEST_NULL_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * + * Uncomment to use your own hardware entropy collector. + */ +//#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Use precomputed AES tables stored in ROM. + * + * Uncomment this macro to use precomputed AES tables stored in ROM. + * Comment this macro to generate AES tables in RAM at runtime. + * + * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb + * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the + * initialization time before the first AES operation can be performed. + * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c + * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded + * performance if ROM access is slower than RAM access. + * + * This option is independent of \c MBEDTLS_AES_FEWER_TABLES. + * + */ +//#define MBEDTLS_AES_ROM_TABLES + +/** + * \def MBEDTLS_AES_FEWER_TABLES + * + * Use less ROM/RAM for AES tables. + * + * Uncommenting this macro omits 75% of the AES tables from + * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES) + * by computing their values on the fly during operations + * (the tables are entry-wise rotations of one another). + * + * Tradeoff: Uncommenting this reduces the RAM / ROM footprint + * by ~6kb but at the cost of more arithmetic operations during + * runtime. Specifically, one has to compare 4 accesses within + * different tables to 4 accesses with additional arithmetic + * operations within the same table. The performance gain/loss + * depends on the system and memory details. + * + * This option is independent of \c MBEDTLS_AES_ROM_TABLES. + * + */ +//#define MBEDTLS_AES_FEWER_TABLES + +/** + * \def MBEDTLS_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define MBEDTLS_CAMELLIA_SMALL_MEMORY + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_CIPHER_MODE_OFB + * + * Enable Output Feedback mode (OFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_OFB + +/** + * \def MBEDTLS_CIPHER_MODE_XTS + * + * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. + */ +#define MBEDTLS_CIPHER_MODE_XTS + +/** + * \def MBEDTLS_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define MBEDTLS_CIPHER_NULL_CIPHER + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + * + * Uncomment this macro to use a 128-bit key in the CTR_DRBG module. + * By default, CTR_DRBG uses a 256-bit key. + */ +//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + +/** + * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_3DES_CIPHERSUITES + * + * Remove 3DES ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on 3DES from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible + * to enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including + * them explicitly. + * + * A man-in-the-browser attacker can recover authentication tokens sent through + * a TLS connection using a 3DES based cipher suite (see "On the Practical + * (In-)Security of 64-bit Block Ciphers" by Karthikeyan Bhargavan and Gaëtan + * Leurent, see https://sweet32.info/SWEET32_CCS16.pdf). If this attack falls + * in your threat model or you are unsure, then you should keep this option + * enabled to remove 3DES based cipher suites. + * + * Comment this macro to keep 3DES in the default ciphersuite list. + */ +#define MBEDTLS_REMOVE_3DES_CIPHERSUITES + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_DP_CURVE448_ENABLED + +/** + * \def MBEDTLS_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#define MBEDTLS_ECP_NIST_OPTIM + +/** + * \def MBEDTLS_ECP_NO_INTERNAL_RNG + * + * When this option is disabled, mbedtls_ecp_mul() will make use of an + * internal RNG when called with a NULL \c f_rng argument, in order to protect + * against some side-channel attacks. + * + * This protection introduces a dependency of the ECP module on one of the + * DRBG or SHA modules (HMAC-DRBG, CTR-DRBG, SHA-512 or SHA-256.) For very + * constrained applications that don't require this protection (for example, + * because you're only doing signature verification, so not manipulating any + * secret, or because local/physical side-channel attacks are outside your + * threat model), it might be desirable to get rid of that dependency. + * + * \warning Enabling this option makes some uses of ECP vulnerable to some + * side-channel attacks. Only enable it if you know that's not a problem for + * your use case. + * + * Uncomment this macro to disable some counter-measures in ECP. + */ +//#define MBEDTLS_ECP_NO_INTERNAL_RNG + +/** + * \def MBEDTLS_ECP_RESTARTABLE + * + * Enable "non-blocking" ECC operations that can return early and be resumed. + * + * This allows various functions to pause by returning + * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in + * order to further progress and eventually complete their operation. This is + * controlled through mbedtls_ecp_set_max_ops() which limits the maximum + * number of ECC operations a function may perform before pausing; see + * mbedtls_ecp_set_max_ops() for more information. + * + * This is useful in non-threaded environments if you want to avoid blocking + * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. + * + * Uncomment this macro to enable restartable ECC computations. + * + * \note This option only works with the default software implementation of + * elliptic curve functionality. It is incompatible with + * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT and MBEDTLS_ECDSA_XXX_ALT. + */ +//#define MBEDTLS_ECP_RESTARTABLE + +/** + * \def MBEDTLS_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: MBEDTLS_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +#define MBEDTLS_ECDSA_DETERMINISTIC + +/** + * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + */ +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + * + * Enable the ECJPAKE based ciphersuite modes in SSL / TLS. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Requires: MBEDTLS_ECJPAKE_C + * MBEDTLS_SHA256_C + * MBEDTLS_ECP_DP_SECP256R1_ENABLED + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + +/** + * \def MBEDTLS_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +#define MBEDTLS_PK_PARSE_EC_EXTENDED + +/** + * \def MBEDTLS_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when MBEDTLS_ERROR_C is disabled + * (no effect when MBEDTLS_ERROR_C is enabled). + * + * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're + * not using mbedtls_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * mbedtls_strerror() + */ +#define MBEDTLS_ERROR_STRERROR_DUMMY + +/** + * \def MBEDTLS_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: MBEDTLS_BIGNUM_C + */ +#define MBEDTLS_GENPRIME + +/** + * \def MBEDTLS_FS_IO + * + * Enable functions that use the filesystem. + */ +#define MBEDTLS_FS_IO + +/** + * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * mbedtls_timing_hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def MBEDTLS_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +//#define MBEDTLS_NO_PLATFORM_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: MBEDTLS_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both MBEDTLS_SHA256_C and + * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. + */ +//#define MBEDTLS_ENTROPY_FORCE_SHA256 + +/** + * \def MBEDTLS_ENTROPY_NV_SEED + * + * Enable the non-volatile (NV) seed file-based entropy source. + * (Also enables the NV seed read/write functions in the platform layer) + * + * This is crucial (if not required) on systems that do not have a + * cryptographic entropy source (in hardware or kernel) available. + * + * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C + * + * \note The read/write functions that are used by the entropy source are + * determined in the platform layer, and can be modified at runtime and/or + * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used. + * + * \note If you use the default implementation functions that read a seedfile + * with regular fopen(), please make sure you make a seedfile with the + * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at + * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from + * and written to or you will get an entropy source error! The default + * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE + * bytes from the file. + * + * \note The entropy collector will write to the seed file before entropy is + * given to an external source, to update it. + */ +//#define MBEDTLS_ENTROPY_NV_SEED + +/** + * \def MBEDTLS_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define MBEDTLS_MEMORY_DEBUG + +/** + * \def MBEDTLS_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define MBEDTLS_MEMORY_BACKTRACE + +/** + * \def MBEDTLS_PK_RSA_ALT_SUPPORT + * + * Support external private RSA keys (eg from a HSM) in the PK layer. + * + * Comment this macro to disable support for external private RSA keys. + */ +#define MBEDTLS_PK_RSA_ALT_SUPPORT + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define MBEDTLS_PKCS1_V15 + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define MBEDTLS_PKCS1_V21 + +/** + * \def MBEDTLS_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem + * for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define MBEDTLS_RSA_NO_CRT + +/** + * \def MBEDTLS_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +#define MBEDTLS_SELF_TEST + +/** + * \def MBEDTLS_SHA256_SMALLER + * + * Enable an implementation of SHA-256 that has lower ROM footprint but also + * lower performance. + * + * The default implementation is meant to be a reasonnable compromise between + * performance and size. This version optimizes more aggressively for size at + * the expense of performance. Eg on Cortex-M4 it reduces the size of + * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about + * 30%. + * + * Uncomment to enable the smaller implementation of SHA256. + */ +//#define MBEDTLS_SHA256_SMALLER + +/** + * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define MBEDTLS_SSL_ALL_ALERT_MESSAGES + +/** + * \def MBEDTLS_SSL_ASYNC_PRIVATE + * + * Enable asynchronous external private key operations in SSL. This allows + * you to configure an SSL connection to call an external cryptographic + * module to perform private key operations instead of performing the + * operation inside the library. + * + */ +//#define MBEDTLS_SSL_ASYNC_PRIVATE + +/** + * \def MBEDTLS_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define MBEDTLS_SSL_DEBUG_ALL + +/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +#define MBEDTLS_SSL_ENCRYPT_THEN_MAC + +/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for Extended Master Secret, aka Session Hash + * (draft-ietf-tls-session-hash-02). + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET + +/** + * \def MBEDTLS_SSL_FALLBACK_SCSV + * + * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00). + * + * For servers, it is recommended to always enable this, unless you support + * only one version of TLS, or know for sure that none of your clients + * implements a fallback strategy. + * + * For clients, you only need this if you're using a fallback strategy, which + * is not recommended in the first place, unless you absolutely need it to + * interoperate with buggy (version-intolerant) servers. + * + * Comment this macro to disable support for FALLBACK_SCSV + */ +#define MBEDTLS_SSL_FALLBACK_SCSV + +/** + * \def MBEDTLS_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define MBEDTLS_SSL_HW_RECORD_ACCEL + +/** + * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING + * + * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. + * + * This is a countermeasure to the BEAST attack, which also minimizes the risk + * of interoperability issues compared to sending 0-length records. + * + * Comment this macro to disable 1/n-1 record splitting. + */ +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING + +/** + * \def MBEDTLS_SSL_RENEGOTIATION + * + * Enable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Comment this to disable support for renegotiation. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * + */ +#define MBEDTLS_SSL_RENEGOTIATION + +/** + * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to enable support for SSLv2 Client Hello messages. + */ +//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def MBEDTLS_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +//#define MBEDTLS_SSL_PROTO_SSL3 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +#define MBEDTLS_SSL_PROTO_TLS1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled). + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 / DTLS 1.0 + */ +#define MBEDTLS_SSL_PROTO_TLS1_1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/** + * \def MBEDTLS_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0, + * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_1 + * or MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +#define MBEDTLS_SSL_PROTO_DTLS + +/** + * \def MBEDTLS_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +#define MBEDTLS_SSL_ALPN + +/** + * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: MBEDTLS_SSL_TLS_C + * MBEDTLS_SSL_PROTO_DTLS + * + * \warning Disabling this is often a security risk! + * See mbedtls_ssl_conf_dtls_anti_replay() for details. + * + * Comment this to disable anti-replay in DTLS. + */ +#define MBEDTLS_SSL_DTLS_ANTI_REPLAY + +/** + * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Enable support for HelloVerifyRequest on DTLS servers. + * + * This feature is highly recommended to prevent DTLS servers being used as + * amplifiers in DoS attacks against other hosts. It should always be enabled + * unless you know for sure amplification cannot be a problem in the + * environment in which your server operates. + * + * \warning Disabling this can ba a security risk! (see above) + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY + +/** + * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + * + * Enable server-side support for clients that reconnect from the same port. + * + * Some clients unexpectedly close the connection and try to reconnect using the + * same source port. This needs special support from the server to handle the + * new connection securely, as described in section 4.2.8 of RFC 6347. This + * flag enables that support. + * + * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + +/** + * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT + * + * Enable support for a limit of records with bad MAC. + * + * See mbedtls_ssl_conf_dtls_badmac_limit(). + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + */ +#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT + +/** + * \def MBEDTLS_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * Client-side, provides full support for session tickets (maintenance of a + * session store remains the responsibility of the application, though). + * Server-side, you also need to provide callbacks for writing and parsing + * tickets, including authenticated encryption and key management. Example + * callbacks are provided by MBEDTLS_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +#define MBEDTLS_SSL_SESSION_TICKETS + +/** + * \def MBEDTLS_SSL_EXPORT_KEYS + * + * Enable support for exporting key block and master secret. + * This is required for certain users of TLS, e.g. EAP-TLS. + * + * Comment this macro to disable support for key export + */ +#define MBEDTLS_SSL_EXPORT_KEYS + +/** + * \def MBEDTLS_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +#define MBEDTLS_SSL_TRUNCATED_HMAC + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + * + * Fallback to old (pre-2.7), non-conforming implementation of the truncated + * HMAC extension which also truncates the HMAC key. Note that this option is + * only meant for a transitory upgrade period and is likely to be removed in + * a future version of the library. + * + * \warning The old implementation is non-compliant and has a security weakness + * (2^80 brute force attack on the HMAC key used for a single, + * uninterrupted connection). This should only be enabled temporarily + * when (1) the use of truncated HMAC is essential in order to save + * bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use + * the fixed implementation yet (pre-2.7). + * + * \deprecated This option is deprecated and will likely be removed in a + * future version of Mbed TLS. + * + * Uncomment to fallback to old, non-compliant truncated HMAC implementation. + * + * Requires: MBEDTLS_SSL_TRUNCATED_HMAC + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + +/** + * \def MBEDTLS_TEST_HOOKS + * + * Enable features for invasive testing such as introspection functions and + * hooks for fault injection. This enables additional unit tests. + * + * Merely enabling this feature should not change the behavior of the product. + * It only adds new code, and new branching points where the default behavior + * is the same as when this feature is disabled. + * However, this feature increases the attack surface: there is an added + * risk of vulnerabilities, and more gadgets that can make exploits easier. + * Therefore this feature must never be enabled in production. + * + * Uncomment to enable invasive tests. + */ +//#define MBEDTLS_TEST_HOOKS + +/** + * \def MBEDTLS_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define MBEDTLS_THREADING_ALT + +/** + * \def MBEDTLS_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define MBEDTLS_THREADING_PTHREAD + +/** + * \def MBEDTLS_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via mbedtls_version_check_feature(). + * + * Requires: MBEDTLS_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +#define MBEDTLS_VERSION_FEATURES + +/** + * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * \warning Depending on your PKI use, enabling this can be a security risk! + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def MBEDTLS_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +#define MBEDTLS_X509_CHECK_KEY_USAGE + +/** + * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +#define MBEDTLS_X509_RSASSA_PSS_SUPPORT + +/** + * \def MBEDTLS_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * \warning TLS-level compression MAY REDUCE SECURITY! See for example the + * CRIME attack. Before enabling this option, you should examine with care if + * CRIME or similar exploits may be applicable to your use case. + * + * \note Currently compression can't be used with DTLS. + * + * \deprecated This feature is deprecated and will be removed + * in the next major revision of the library. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define MBEDTLS_ZLIB_SUPPORT +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/cipher.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define MBEDTLS_AES_C + +/** + * \def MBEDTLS_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. If possible, we recommend avoidng dependencies on + * it, and considering stronger ciphers instead. + * + */ +#define MBEDTLS_ARC4_C + +/** + * \def MBEDTLS_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define MBEDTLS_ASN1_PARSE_C + +/** + * \def MBEDTLS_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +#define MBEDTLS_ASN1_WRITE_C + +/** + * \def MBEDTLS_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define MBEDTLS_BASE64_C + +/** + * \def MBEDTLS_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/rsa_internal.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define MBEDTLS_BIGNUM_C + +/** + * \def MBEDTLS_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +#define MBEDTLS_BLOWFISH_C + +/** + * \def MBEDTLS_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +#define MBEDTLS_CAMELLIA_C + +/** + * \def MBEDTLS_ARIA_C + * + * Enable the ARIA block cipher. + * + * Module: library/aria.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * + * MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 + */ +//#define MBEDTLS_ARIA_C + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +#define MBEDTLS_CCM_C + +/** + * \def MBEDTLS_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +#define MBEDTLS_CERTS_C + +/** + * \def MBEDTLS_CHACHA20_C + * + * Enable the ChaCha20 stream cipher. + * + * Module: library/chacha20.c + */ +#define MBEDTLS_CHACHA20_C + +/** + * \def MBEDTLS_CHACHAPOLY_C + * + * Enable the ChaCha20-Poly1305 AEAD algorithm. + * + * Module: library/chachapoly.c + * + * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C + */ +#define MBEDTLS_CHACHAPOLY_C + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define MBEDTLS_CIPHER_C + +/** + * \def MBEDTLS_CMAC_C + * + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. + * + * Module: library/cmac.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C + * + */ +//#define MBEDTLS_CMAC_C + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-based random generator. + * The CTR_DRBG generator uses AES-256 by default. + * To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above. + * + * \note To achieve a 256-bit security strength with CTR_DRBG, + * you must use AES-256 *and* use sufficient entropy. + * See ctr_drbg.h for more details. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES random number generator. + */ +#define MBEDTLS_CTR_DRBG_C + +/** + * \def MBEDTLS_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +#define MBEDTLS_DEBUG_C + +/** + * \def MBEDTLS_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +#define MBEDTLS_DES_C + +/** + * \def MBEDTLS_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#define MBEDTLS_DHM_C + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +#define MBEDTLS_ECDH_C + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C + */ +#define MBEDTLS_ECDSA_C + +/** + * \def MBEDTLS_ECJPAKE_C + * + * Enable the elliptic curve J-PAKE library. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Module: library/ecjpake.c + * Caller: + * + * This module is used by the following key exchanges: + * ECJPAKE + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C + */ +//#define MBEDTLS_ECJPAKE_C + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +#define MBEDTLS_ECP_C + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +#define MBEDTLS_ERROR_C + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#define MBEDTLS_GCM_C + +/** + * \def MBEDTLS_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: MBEDTLS_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define MBEDTLS_HAVEGE_C + +/** + * \def MBEDTLS_HKDF_C + * + * Enable the HKDF algorithm (RFC 5869). + * + * Module: library/hkdf.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the Hashed Message Authentication Code + * (HMAC)-based key derivation function (HKDF). + */ +#define MBEDTLS_HKDF_C + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_NIST_KW_C + * + * Enable the Key Wrapping mode for 128-bit block ciphers, + * as defined in NIST SP 800-38F. Only KW and KWP modes + * are supported. At the moment, only AES is approved by NIST. + * + * Module: library/nist_kw.c + * + * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_NIST_KW_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD2_C + +/** + * \def MBEDTLS_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD4_C + +/** + * \def MBEDTLS_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2 + * depending on the handshake parameters. Further, it is used for checking + * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded + * encrypted keys. + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: MBEDTLS_PLATFORM_C + * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +/** + * \def MBEDTLS_NET_C + * + * Enable the TCP and UDP over IPv6/IPv4 networking routines. + * + * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) + * and Windows. For other platforms, you'll want to disable it, and write your + * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/net_sockets.c + * + * This module provides networking routines. + */ +#define MBEDTLS_NET_C + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define MBEDTLS_PEM_PARSE_C + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +#define MBEDTLS_PEM_WRITE_C + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: MBEDTLS_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define MBEDTLS_PKCS11_C + +/** + * \def MBEDTLS_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * Can use: MBEDTLS_ARC4_C + * + * This module enables PKCS#12 functions. + */ +#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_POLY1305_C + * + * Enable the Poly1305 MAC algorithm. + * + * Module: library/poly1305.c + * Caller: library/chachapoly.c + */ +#define MBEDTLS_POLY1305_C + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +#define MBEDTLS_RIPEMD160_C + +/** + * \def MBEDTLS_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * library/rsa_internal.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS up to version 1.1, for TLS 1.2 + * depending on the handshake parameters, and for SHA1-signed certificates. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +#define MBEDTLS_SSL_TICKET_C + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define MBEDTLS_SSL_CLI_C + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +#define MBEDTLS_SSL_SRV_C + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +#define MBEDTLS_SSL_TLS_C + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by + * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide + * your own implementation of the whole module by setting + * \c MBEDTLS_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +#define MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define MBEDTLS_X509_USE_C + +/** + * \def MBEDTLS_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define MBEDTLS_X509_CRT_PARSE_C + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +#define MBEDTLS_X509_CRL_PARSE_C + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +#define MBEDTLS_X509_CSR_PARSE_C + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +#define MBEDTLS_X509_CREATE_C + +/** + * \def MBEDTLS_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +#define MBEDTLS_X509_CRT_WRITE_C + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +#define MBEDTLS_X509_CSR_WRITE_C + +/** + * \def MBEDTLS_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +#define MBEDTLS_XTEA_C + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */ +//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* HMAC_DRBG options */ +//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ + +/* Memory buffer allocator options */ +//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ + +/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ + +/** + * \brief This macro is invoked by the library when an invalid parameter + * is detected that is only checked with #MBEDTLS_CHECK_PARAMS + * (see the documentation of that option for context). + * + * When you leave this undefined here, the library provides + * a default definition. If the macro #MBEDTLS_CHECK_PARAMS_ASSERT + * is defined, the default definition is `assert(cond)`, + * otherwise the default definition calls a function + * mbedtls_param_failed(). This function is declared in + * `platform_util.h` for the benefit of the library, but + * you need to define in your application. + * + * When you define this here, this replaces the default + * definition in platform_util.h (which no longer declares the + * function mbedtls_param_failed()) and it is your responsibility + * to make sure this macro expands to something suitable (in + * particular, that all the necessary declarations are visible + * from within the library - you can ensure that by providing + * them in this file next to the macro definition). + * If you define this macro to call `assert`, also define + * #MBEDTLS_CHECK_PARAMS_ASSERT so that library source files + * include ``. + * + * Note that you may define this macro to expand to nothing, in + * which case you don't have to worry about declarations or + * definitions. However, you will then be notified about invalid + * parameters only in non-void functions, and void function will + * just silently return early on invalid parameters, which + * partially negates the benefits of enabling + * #MBEDTLS_CHECK_PARAMS in the first place, so is discouraged. + * + * \param cond The expression that should evaluate to true, but doesn't. + */ +//#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) + +/* SSL Cache options */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ + +/** \def MBEDTLS_SSL_MAX_CONTENT_LEN + * + * Maximum length (in bytes) of incoming and outgoing plaintext fragments. + * + * This determines the size of both the incoming and outgoing TLS I/O buffers + * in such a way that both are capable of holding the specified amount of + * plaintext data, regardless of the protection mechanism used. + * + * To configure incoming and outgoing I/O buffers separately, use + * #MBEDTLS_SSL_IN_CONTENT_LEN and #MBEDTLS_SSL_OUT_CONTENT_LEN, + * which overwrite the value set by this option. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of both + * incoming and outgoing I/O buffers. + */ +//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_IN_CONTENT_LEN + * + * Maximum length (in bytes) of incoming plaintext fragments. + * + * This determines the size of the incoming TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option is undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of the incoming I/O buffer + * independently of the outgoing I/O buffer. + */ +//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_OUT_CONTENT_LEN + * + * Maximum length (in bytes) of outgoing plaintext fragments. + * + * This determines the size of the outgoing TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * It is possible to save RAM by setting a smaller outward buffer, while keeping + * the default inward 16384 byte buffer to conform to the TLS specification. + * + * The minimum required outward buffer size is determined by the handshake + * protocol's usage. Handshaking will fail if the outward buffer is too small. + * The specific size requirement depends on the configured ciphers and any + * certificate data which is sent during the handshake. + * + * Uncomment to set the maximum plaintext size of the outgoing I/O buffer + * independently of the incoming I/O buffer. + */ +//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING + * + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + * + * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN + * to account for a reassembled handshake message of maximum size, + * together with its reassembly bitmap. + * + * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default) + * should be sufficient for all practical situations as it allows + * to reassembly a large handshake message (such as a certificate) + * while buffering multiple smaller handshake messages. + * + */ +//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 + +//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ +//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +//#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ +//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ + +/** + * Allow SHA-1 in the default TLS configuration for certificate signing. + * Without this build-time option, SHA-1 support must be activated explicitly + * through mbedtls_ssl_conf_cert_profile. Turning on this option is not + * recommended because of it is possible to generate SHA-1 collisions, however + * this may be safe for legacy infrastructure where additional controls apply. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +// #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES + +/** + * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake + * signature and ciphersuite selection. Without this build-time option, SHA-1 + * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. + * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by + * default. At the time of writing, there is no practical attack on the use + * of SHA-1 in handshake signatures, hence this option is turned on by default + * to preserve compatibility with existing peers, but the general + * warning applies nonetheless: + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +/** + * Uncomment the macro to let mbed TLS use your alternate implementation of + * mbedtls_platform_zeroize(). This replaces the default implementation in + * platform_util.c. + * + * mbedtls_platform_zeroize() is a widely used function across the library to + * zero a block of memory. The implementation is expected to be secure in the + * sense that it has been written to prevent the compiler from removing calls + * to mbedtls_platform_zeroize() as part of redundant code elimination + * optimizations. However, it is difficult to guarantee that calls to + * mbedtls_platform_zeroize() will not be optimized by the compiler as older + * versions of the C language standards do not provide a secure implementation + * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to + * configure their own implementation of mbedtls_platform_zeroize(), for + * example by using directives specific to their compiler, features from newer + * C standards (e.g using memset_s() in C11) or calling a secure memset() from + * their system (e.g explicit_bzero() in BSD). + */ +//#define MBEDTLS_PLATFORM_ZEROIZE_ALT + +/** + * Uncomment the macro to let Mbed TLS use your alternate implementation of + * mbedtls_platform_gmtime_r(). This replaces the default implementation in + * platform_util.c. + * + * gmtime() is not a thread-safe function as defined in the C standard. The + * library will try to use safer implementations of this function, such as + * gmtime_r() when available. However, if Mbed TLS cannot identify the target + * system, the implementation of mbedtls_platform_gmtime_r() will default to + * using the standard gmtime(). In this case, calls from the library to + * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex + * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the + * library are also guarded with this mutex to avoid race conditions. However, + * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will + * unconditionally use the implementation for mbedtls_platform_gmtime_r() + * supplied at compile time. + */ +//#define MBEDTLS_PLATFORM_GMTIME_R_ALT + +/* \} name SECTION: Customisation configuration options */ + +/* Target and application specific configurations + * + * Allow user to override any previous default. + * + */ +#if defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +#include "check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external/mbedtls/include/mbedtls/ctr_drbg.h b/external/mbedtls/include/mbedtls/ctr_drbg.h new file mode 100644 index 0000000..6c099ad --- /dev/null +++ b/external/mbedtls/include/mbedtls/ctr_drbg.h @@ -0,0 +1,584 @@ +/** + * \file ctr_drbg.h + * + * \brief This file contains definitions and functions for the + * CTR_DRBG pseudorandom generator. + * + * CTR_DRBG is a standardized way of building a PRNG from a block-cipher + * in counter mode operation, as defined in NIST SP 800-90A: + * Recommendation for Random Number Generation Using Deterministic Random + * Bit Generators. + * + * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128 + * (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time) + * as the underlying block cipher, with a derivation function. + * The initial seeding grabs #MBEDTLS_CTR_DRBG_ENTROPY_LEN bytes of entropy. + * See the documentation of mbedtls_ctr_drbg_seed() for more details. + * + * Based on NIST SP 800-90A §10.2.1 table 3 and NIST SP 800-57 part 1 table 2, + * here are the security strengths achieved in typical configuration: + * - 256 bits under the default configuration of the library, with AES-256 + * and with #MBEDTLS_CTR_DRBG_ENTROPY_LEN set to 48 or more. + * - 256 bits if AES-256 is used, #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set + * to 32 or more, and the DRBG is initialized with an explicit + * nonce in the \c custom parameter to mbedtls_ctr_drbg_seed(). + * - 128 bits if AES-256 is used but #MBEDTLS_CTR_DRBG_ENTROPY_LEN is + * between 24 and 47 and the DRBG is not initialized with an explicit + * nonce (see mbedtls_ctr_drbg_seed()). + * - 128 bits if AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled) + * and #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set to 24 or more (which is + * always the case unless it is explicitly set to a different value + * in config.h). + * + * Note that the value of #MBEDTLS_CTR_DRBG_ENTROPY_LEN defaults to: + * - \c 48 if the module \c MBEDTLS_SHA512_C is enabled and the symbol + * \c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled at compile time. + * This is the default configuration of the library. + * - \c 32 if the module \c MBEDTLS_SHA512_C is disabled at compile time. + * - \c 32 if \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled at compile time. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_CTR_DRBG_H +#define MBEDTLS_CTR_DRBG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "aes.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ +#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< The requested random buffer length is too big. */ +#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< The input (entropy + additional data) is too large. */ +#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */ + +#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ + +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +#define MBEDTLS_CTR_DRBG_KEYSIZE 16 +/**< The key size in bytes used by the cipher. + * + * Compile-time choice: 16 bytes (128 bits) + * because #MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled. + */ +#else +#define MBEDTLS_CTR_DRBG_KEYSIZE 32 +/**< The key size in bytes used by the cipher. + * + * Compile-time choice: 32 bytes (256 bits) + * because \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled. + */ +#endif + +#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */ +#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them using the compiler command + * line. + * \{ + */ + +/** \def MBEDTLS_CTR_DRBG_ENTROPY_LEN + * + * \brief The amount of entropy used per seed by default, in bytes. + */ +#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +/** This is 48 bytes because the entropy module uses SHA-512 + * (\c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled). + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 + +#else /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ + +/** This is 32 bytes because the entropy module uses SHA-256 + * (the SHA512 module is disabled or + * \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled). + */ +#if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +/** \warning To achieve a 256-bit security strength, you must pass a nonce + * to mbedtls_ctr_drbg_seed(). + */ +#endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */ +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 +#endif /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ +#endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */ + +#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) +#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 +/**< The interval before reseed is performed by default. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 +/**< The maximum number of additional input Bytes. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) +#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 +/**< The maximum number of requested Bytes per call. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 +/**< The maximum size of seed or reseed buffer in bytes. */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_CTR_DRBG_PR_OFF 0 +/**< Prediction resistance is disabled. */ +#define MBEDTLS_CTR_DRBG_PR_ON 1 +/**< Prediction resistance is enabled. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The CTR_DRBG context structure. + */ +typedef struct mbedtls_ctr_drbg_context +{ + unsigned char counter[16]; /*!< The counter (V). */ + int reseed_counter; /*!< The reseed counter. */ + int prediction_resistance; /*!< This determines whether prediction + resistance is enabled, that is + whether to systematically reseed before + each random generation. */ + size_t entropy_len; /*!< The amount of entropy grabbed on each + seed or reseed operation. */ + int reseed_interval; /*!< The reseed interval. */ + + mbedtls_aes_context aes_ctx; /*!< The AES context. */ + + /* + * Callbacks (Entropy) + */ + int (*f_entropy)(void *, unsigned char *, size_t); + /*!< The entropy callback function. */ + + void *p_entropy; /*!< The context for the entropy function. */ + +#if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized if and only if f_entropy != NULL. + * This means that the mutex is initialized during the initial seeding + * in mbedtls_ctr_drbg_seed() and freed in mbedtls_ctr_drbg_free(). + * + * Note that this invariant may change without notice. Do not rely on it + * and do not access the mutex directly in application code. + */ + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ctr_drbg_context; + +/** + * \brief This function initializes the CTR_DRBG context, + * and prepares it for mbedtls_ctr_drbg_seed() + * or mbedtls_ctr_drbg_free(). + * + * \note The reseed interval is + * #MBEDTLS_CTR_DRBG_RESEED_INTERVAL by default. + * You can override it by calling + * mbedtls_ctr_drbg_set_reseed_interval(). + * + * \param ctx The CTR_DRBG context to initialize. + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function seeds and sets up the CTR_DRBG + * entropy source for future reseeds. + * + * A typical choice for the \p f_entropy and \p p_entropy parameters is + * to use the entropy module: + * - \p f_entropy is mbedtls_entropy_func(); + * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized + * with mbedtls_entropy_init() (which registers the platform's default + * entropy sources). + * + * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default. + * You can override it by calling mbedtls_ctr_drbg_set_entropy_len(). + * + * You can provide a personalization string in addition to the + * entropy source, to make this instantiation as unique as possible. + * + * \note The _seed_material_ value passed to the derivation + * function in the CTR_DRBG Instantiate Process + * described in NIST SP 800-90A §10.2.1.3.2 + * is the concatenation of the string obtained from + * calling \p f_entropy and the \p custom string. + * The origin of the nonce depends on the value of + * the entropy length relative to the security strength. + * - If the entropy length is at least 1.5 times the + * security strength then the nonce is taken from the + * string obtained with \p f_entropy. + * - If the entropy length is less than the security + * strength, then the nonce is taken from \p custom. + * In this case, for compliance with SP 800-90A, + * you must pass a unique value of \p custom at + * each invocation. See SP 800-90A §8.6.7 for more + * details. + */ +#if MBEDTLS_CTR_DRBG_ENTROPY_LEN < MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 +/** \warning When #MBEDTLS_CTR_DRBG_ENTROPY_LEN is less than + * #MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2, to achieve the + * maximum security strength permitted by CTR_DRBG, + * you must pass a value of \p custom that is a nonce: + * this value must never be repeated in subsequent + * runs of the same application or on a different + * device. + */ +#endif +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param ctx The CTR_DRBG context to seed. + * It must have been initialized with + * mbedtls_ctr_drbg_init(). + * After a successful call to mbedtls_ctr_drbg_seed(), + * you may not call mbedtls_ctr_drbg_seed() again on + * the same context unless you call + * mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init() + * again first. + * After a failed call to mbedtls_ctr_drbg_seed(), + * you must call mbedtls_ctr_drbg_free(). + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + * length of the buffer. + * \p f_entropy is always called with a buffer size + * equal to the entropy length. + * \param p_entropy The entropy context to pass to \p f_entropy. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * This must be at most + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * - #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief This function resets CTR_DRBG context to the state immediately + * after initial call of mbedtls_ctr_drbg_init(). + * + * \param ctx The CTR_DRBG context to clear. + */ +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function turns prediction resistance on or off. + * The default value is off. + * + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_ctr_drbg_random_with_add() + * or mbedtls_ctr_drbg_random(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The CTR_DRBG context. + * \param resistance #MBEDTLS_CTR_DRBG_PR_ON or #MBEDTLS_CTR_DRBG_PR_OFF. + */ +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, + int resistance ); + +/** + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. + * + * The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \note The security strength of CTR_DRBG is bounded by the + * entropy length. Thus: + * - When using AES-256 + * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled, + * which is the default), + * \p len must be at least 32 (in bytes) + * to achieve a 256-bit strength. + * - When using AES-128 + * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled) + * \p len must be at least 16 (in bytes) + * to achieve a 128-bit strength. + * + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab, in bytes. + * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + */ +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief This function sets the reseed interval. + * + * The reseed interval is the number of calls to mbedtls_ctr_drbg_random() + * or mbedtls_ctr_drbg_random_with_add() after which the entropy function + * is called again. + * + * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. + * + * \param ctx The CTR_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, + int interval ); + +/** + * \brief This function reseeds the CTR_DRBG context, that is + * extracts data from the entropy source. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The CTR_DRBG context. + * \param additional Additional data to add to the state. Can be \c NULL. + * \param len The length of the additional data. + * This must be less than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len + * where \c entropy_len is the entropy length + * configured for the context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. This must not be + * \c NULL unless \p add_len is \c 0. + * \param add_len Length of \p additional in bytes. This must be at + * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if + * \p add_len is more than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * \return An error from the underlying AES cipher on failure. + */ +int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief This function updates a CTR_DRBG instance with additional + * data and uses it to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * \param additional Additional data to update. Can be \c NULL, in which + * case the additional data is empty regardless of + * the value of \p add_len. + * \param add_len The length of the additional data + * if \p additional is not \c NULL. + * This must be less than #MBEDTLS_CTR_DRBG_MAX_INPUT + * and less than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len + * where \c entropy_len is the entropy length + * configured for the context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function uses CTR_DRBG to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ); + + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \deprecated Superseded by mbedtls_ctr_drbg_update_ret() + * in 2.16.0. + * + * \note If \p add_len is greater than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. + * The remaining Bytes are silently discarded. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. + * \param add_len Length of \p additional data. + */ +MBEDTLS_DEPRECATED void mbedtls_ctr_drbg_update( + mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on reseed + * failure. + */ +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); + +/** + * \brief This function reads and updates a seed file. The seed + * is added to this instance. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on + * reseed failure. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if the existing + * seed file is too large. + */ +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The CTR_DRBG checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ctr_drbg_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +/* Internal functions (do not call directly) */ +int mbedtls_ctr_drbg_seed_entropy_len( mbedtls_ctr_drbg_context *, + int (*)(void *, unsigned char *, size_t), void *, + const unsigned char *, size_t, size_t ); + +#ifdef __cplusplus +} +#endif + +#endif /* ctr_drbg.h */ diff --git a/external/mbedtls/include/mbedtls/debug.h b/external/mbedtls/include/mbedtls/debug.h new file mode 100644 index 0000000..abc2d4f --- /dev/null +++ b/external/mbedtls/include/mbedtls/debug.h @@ -0,0 +1,290 @@ +/** + * \file debug.h + * + * \brief Functions for controlling and providing debug output from the library. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_DEBUG_H +#define MBEDTLS_DEBUG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" + +#if defined(MBEDTLS_ECP_C) +#include "ecp.h" +#endif + +#if defined(MBEDTLS_DEBUG_C) + +#define MBEDTLS_DEBUG_STRIP_PARENS( ... ) __VA_ARGS__ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) \ + mbedtls_debug_print_msg( ssl, level, __FILE__, __LINE__, \ + MBEDTLS_DEBUG_STRIP_PARENS args ) + +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) \ + mbedtls_debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret ) + +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) \ + mbedtls_debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len ) + +#if defined(MBEDTLS_BIGNUM_C) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) \ + mbedtls_debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_ECP_C) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) \ + mbedtls_debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) \ + mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ) +#endif + +#if defined(MBEDTLS_ECDH_C) +#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) \ + mbedtls_debug_printf_ecdh( ssl, level, __FILE__, __LINE__, ecdh, attr ) +#endif + +#else /* MBEDTLS_DEBUG_C */ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) do { } while( 0 ) + +#endif /* MBEDTLS_DEBUG_C */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Set the threshold error level to handle globally all debug output. + * Debug messages that have a level over the threshold value are + * discarded. + * (Default value: 0 = No debug ) + * + * \param threshold theshold level of messages to filter on. Messages at a + * higher level will be discarded. + * - Debug levels + * - 0 No debug + * - 1 Error + * - 2 State change + * - 3 Informational + * - 4 Verbose + */ +void mbedtls_debug_set_threshold( int threshold ); + +/** + * \brief Print a message to the debug output. This function is always used + * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl + * context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the message has occurred in + * \param line line number the message has occurred at + * \param format format specifier, in printf format + * \param ... variables used by the format specifier + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ... ); + +/** + * \brief Print the return value of a function to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text the name of the function that returned the error + * \param ret the return code value + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ); + +/** + * \brief Output a buffer of size len bytes to the debug output. This function + * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the buffer being dumped. Normally the + * variable or buffer name + * \param buf the buffer to be outputted + * \param len length of the buffer + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Print a MPI variable to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the MPI being output. Normally the + * variable name + * \param X the MPI variable + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X ); +#endif + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Print an ECP point to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the ECP point being output. Normally the + * variable name + * \param X the ECP point + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X ); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Print a X.509 certificate structure to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the certificate being output + * \param crt X.509 certificate structure + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt ); +#endif + +#if defined(MBEDTLS_ECDH_C) +typedef enum +{ + MBEDTLS_DEBUG_ECDH_Q, + MBEDTLS_DEBUG_ECDH_QP, + MBEDTLS_DEBUG_ECDH_Z, +} mbedtls_debug_ecdh_attr; + +/** + * \brief Print a field of the ECDH structure in the SSL context to the debug + * output. This function is always used through the + * MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file + * and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param ecdh the ECDH context + * \param attr the identifier of the attribute being output + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* debug.h */ + diff --git a/external/mbedtls/include/mbedtls/des.h b/external/mbedtls/include/mbedtls/des.h new file mode 100644 index 0000000..ee24f65 --- /dev/null +++ b/external/mbedtls/include/mbedtls/des.h @@ -0,0 +1,381 @@ +/** + * \file des.h + * + * \brief DES block cipher + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * + */ +#ifndef MBEDTLS_DES_H +#define MBEDTLS_DES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_DES_ENCRYPT 1 +#define MBEDTLS_DES_DECRYPT 0 + +#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ + +/* MBEDTLS_ERR_DES_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */ + +#define MBEDTLS_DES_KEY_SIZE 8 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// + +/** + * \brief DES context structure + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +typedef struct mbedtls_des_context +{ + uint32_t sk[32]; /*!< DES subkeys */ +} +mbedtls_des_context; + +/** + * \brief Triple-DES context structure + */ +typedef struct mbedtls_des3_context +{ + uint32_t sk[96]; /*!< 3DES subkeys */ +} +mbedtls_des3_context; + +#else /* MBEDTLS_DES_ALT */ +#include "des_alt.h" +#endif /* MBEDTLS_DES_ALT */ + +/** + * \brief Initialize DES context + * + * \param ctx DES context to be initialized + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_init( mbedtls_des_context *ctx ); + +/** + * \brief Clear DES context + * + * \param ctx DES context to be cleared + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_free( mbedtls_des_context *ctx ); + +/** + * \brief Initialize Triple-DES context + * + * \param ctx DES3 context to be initialized + */ +void mbedtls_des3_init( mbedtls_des3_context *ctx ); + +/** + * \brief Clear Triple-DES context + * + * \param ctx DES3 context to be cleared + */ +void mbedtls_des3_free( mbedtls_des3_context *ctx ); + +/** + * \brief Set key parity on the given key to odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key parity on the given key is odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \return 0 is parity was ok, 1 if parity was not correct. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key is not a weak or semi-weak DES key + * + * \param key 8-byte secret key + * + * \return 0 if no weak key was found, 1 if a weak key was identified. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Triple-DES key schedule (112-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (112-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (168-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief Triple-DES key schedule (168-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief 3DES-ECB block encryption/decryption + * + * \param ctx 3DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief 3DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx 3DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief Internal function for key expansion. + * (Only exposed to allow overriding it, + * see MBEDTLS_DES_SETKEY_ALT) + * + * \param SK Round keys + * \param key Base key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_setkey( uint32_t SK[32], + const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_des_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* des.h */ diff --git a/external/mbedtls/include/mbedtls/dhm.h b/external/mbedtls/include/mbedtls/dhm.h new file mode 100644 index 0000000..11042ef --- /dev/null +++ b/external/mbedtls/include/mbedtls/dhm.h @@ -0,0 +1,1121 @@ +/** + * \file dhm.h + * + * \brief This file contains Diffie-Hellman-Merkle (DHM) key exchange + * definitions and functions. + * + * Diffie-Hellman-Merkle (DHM) key exchange is defined in + * RFC-2631: Diffie-Hellman Key Agreement Method and + * Public-Key Cryptography Standards (PKCS) #3: Diffie + * Hellman Key Agreement Standard. + * + * RFC-3526: More Modular Exponential (MODP) Diffie-Hellman groups for + * Internet Key Exchange (IKE) defines a number of standardized + * Diffie-Hellman groups for IKE. + * + * RFC-5114: Additional Diffie-Hellman Groups for Use with IETF + * Standards defines a number of standardized Diffie-Hellman + * groups that can be used. + * + * \warning The security of the DHM key exchange relies on the proper choice + * of prime modulus - optimally, it should be a safe prime. The usage + * of non-safe primes both decreases the difficulty of the underlying + * discrete logarithm problem and can lead to small subgroup attacks + * leaking private exponent bits when invalid public keys are used + * and not detected. This is especially relevant if the same DHM + * parameters are reused for multiple key exchanges as in static DHM, + * while the criticality of small-subgroup attacks is lower for + * ephemeral DHM. + * + * \warning For performance reasons, the code does neither perform primality + * nor safe primality tests, nor the expensive checks for invalid + * subgroups. Moreover, even if these were performed, non-standardized + * primes cannot be trusted because of the possibility of backdoors + * that can't be effectively checked for. + * + * \warning Diffie-Hellman-Merkle is therefore a security risk when not using + * standardized primes generated using a trustworthy ("nothing up + * my sleeve") method, such as the RFC 3526 / 7919 primes. In the TLS + * protocol, DH parameters need to be negotiated, so using the default + * primes systematically is not always an option. If possible, use + * Elliptic Curve Diffie-Hellman (ECDH), which has better performance, + * and for which the TLS protocol mandates the use of standard + * parameters. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_DHM_H +#define MBEDTLS_DHM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include "bignum.h" + +/* + * DHM Error codes + */ +#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters. */ +#define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED -0x3100 /**< Reading of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /**< Making of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /**< Reading of the public values failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /**< Making of the public value failed. */ +#define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED -0x3300 /**< Calculation of the DHM secret failed. */ +#define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 /**< The ASN.1 data is not formatted correctly. */ +#define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read or write of file failed. */ + +/* MBEDTLS_ERR_DHM_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED -0x3500 /**< DHM hardware accelerator failed. */ + +#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 /**< Setting the modulus and generator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DHM_ALT) + +/** + * \brief The DHM context structure. + */ +typedef struct mbedtls_dhm_context +{ + size_t len; /*!< The size of \p P in Bytes. */ + mbedtls_mpi P; /*!< The prime modulus. */ + mbedtls_mpi G; /*!< The generator. */ + mbedtls_mpi X; /*!< Our secret value. */ + mbedtls_mpi GX; /*!< Our public key = \c G^X mod \c P. */ + mbedtls_mpi GY; /*!< The public key of the peer = \c G^Y mod \c P. */ + mbedtls_mpi K; /*!< The shared secret = \c G^(XY) mod \c P. */ + mbedtls_mpi RP; /*!< The cached value = \c R^2 mod \c P. */ + mbedtls_mpi Vi; /*!< The blinding value. */ + mbedtls_mpi Vf; /*!< The unblinding value. */ + mbedtls_mpi pX; /*!< The previous \c X. */ +} +mbedtls_dhm_context; + +#else /* MBEDTLS_DHM_ALT */ +#include "dhm_alt.h" +#endif /* MBEDTLS_DHM_ALT */ + +/** + * \brief This function initializes the DHM context. + * + * \param ctx The DHM context to initialize. + */ +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ); + +/** + * \brief This function parses the DHM parameters in a + * TLS ServerKeyExchange handshake message + * (DHM modulus, generator, and public key). + * + * \note In a TLS handshake, this is the how the client + * sets up its DHM context from the server's public + * DHM key material. + * + * \param ctx The DHM context to use. This must be initialized. + * \param p On input, *p must be the start of the input buffer. + * On output, *p is updated to point to the end of the data + * that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ); + +/** + * \brief This function generates a DHM key pair and exports its + * public part together with the DHM parameters in the format + * used in a TLS ServerKeyExchange handshake message. + * + * \note This function assumes that the DHM parameters \c ctx->P + * and \c ctx->G have already been properly set. For that, use + * mbedtls_dhm_set_group() below in conjunction with + * mbedtls_mpi_read_binary() and mbedtls_mpi_read_string(). + * + * \note In a TLS handshake, this is the how the server generates + * and exports its DHM key material. + * + * \param ctx The DHM context to use. This must be initialized + * and have the DHM parameters set. It may or may not + * already have imported the peer's public key. + * \param x_size The private key size in Bytes. + * \param olen The address at which to store the number of Bytes + * written on success. This must not be \c NULL. + * \param output The destination buffer. This must be a writable buffer of + * sufficient size to hold the reduced binary presentation of + * the modulus, the generator and the public key, each wrapped + * with a 2-byte length field. It is the responsibility of the + * caller to ensure that enough space is available. Refer to + * mbedtls_mpi_size() to computing the byte-size of an MPI. + * \param f_rng The RNG function. Must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function sets the prime modulus and generator. + * + * \note This function can be used to set \c ctx->P, \c ctx->G + * in preparation for mbedtls_dhm_make_params(). + * + * \param ctx The DHM context to configure. This must be initialized. + * \param P The MPI holding the DHM prime modulus. This must be + * an initialized MPI. + * \param G The MPI holding the DHM generator. This must be an + * initialized MPI. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ); + +/** + * \brief This function imports the raw public value of the peer. + * + * \note In a TLS handshake, this is the how the server imports + * the Client's public DHM key. + * + * \param ctx The DHM context to use. This must be initialized and have + * its DHM parameters set, e.g. via mbedtls_dhm_set_group(). + * It may or may not already have generated its own private key. + * \param input The input buffer containing the \c G^Y value of the peer. + * This must be a readable buffer of size \p ilen Bytes. + * \param ilen The size of the input buffer \p input in Bytes. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function creates a DHM key pair and exports + * the raw public key in big-endian format. + * + * \note The destination buffer is always fully written + * so as to contain a big-endian representation of G^X mod P. + * If it is larger than \c ctx->len, it is padded accordingly + * with zero-bytes at the beginning. + * + * \param ctx The DHM context to use. This must be initialized and + * have the DHM parameters set. It may or may not already + * have imported the peer's public key. + * \param x_size The private key size in Bytes. + * \param output The destination buffer. This must be a writable buffer of + * size \p olen Bytes. + * \param olen The length of the destination buffer. This must be at least + * equal to `ctx->len` (the size of \c P). + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function derives and exports the shared secret + * \c (G^Y)^X mod \c P. + * + * \note If \p f_rng is not \c NULL, it is used to blind the input as + * a countermeasure against timing attacks. Blinding is used + * only if our private key \c X is re-used, and not used + * otherwise. We recommend always passing a non-NULL + * \p f_rng argument. + * + * \param ctx The DHM context to use. This must be initialized + * and have its own private key generated and the peer's + * public key imported. + * \param output The buffer to write the generated shared key to. This + * must be a writable buffer of size \p output_size Bytes. + * \param output_size The size of the destination buffer. This must be at + * least the size of \c ctx->len (the size of \c P). + * \param olen On exit, holds the actual number of Bytes written. + * \param f_rng The RNG function, for blinding purposes. This may + * b \c NULL if blinding isn't needed. + * \param p_rng The RNG context. This may be \c NULL if \p f_rng + * doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function frees and clears the components + * of a DHM context. + * + * \param ctx The DHM context to free and clear. This may be \c NULL, + * in which case this function is a no-op. If it is not \c NULL, + * it must point to an initialized DHM context. + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ); + +#if defined(MBEDTLS_ASN1_PARSE_C) +/** \ingroup x509_module */ +/** + * \brief This function parses DHM parameters in PEM or DER format. + * + * \param dhm The DHM context to import the DHM parameters into. + * This must be initialized. + * \param dhmin The input buffer. This must be a readable buffer of + * length \p dhminlen Bytes. + * \param dhminlen The size of the input buffer \p dhmin, including the + * terminating \c NULL Byte for PEM data. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error + * code on failure. + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup x509_module */ +/** + * \brief This function loads and parses DHM parameters from a file. + * + * \param dhm The DHM context to load the parameters to. + * This must be initialized. + * \param path The filename to read the DHM parameters from. + * This must not be \c NULL. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX + * error code on failure. + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The DMH checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_dhm_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ +#ifdef __cplusplus +} +#endif + +/** + * RFC 3526, RFC 5114 and RFC 7919 standardize a number of + * Diffie-Hellman groups, some of which are included here + * for use within the SSL/TLS module and the user's convenience + * when configuring the Diffie-Hellman parameters by hand + * through \c mbedtls_ssl_conf_dh_param. + * + * The following lists the source of the above groups in the standards: + * - RFC 5114 section 2.2: 2048-bit MODP Group with 224-bit Prime Order Subgroup + * - RFC 3526 section 3: 2048-bit MODP Group + * - RFC 3526 section 4: 3072-bit MODP Group + * - RFC 3526 section 5: 4096-bit MODP Group + * - RFC 7919 section A.1: ffdhe2048 + * - RFC 7919 section A.2: ffdhe3072 + * - RFC 7919 section A.3: ffdhe4096 + * - RFC 7919 section A.4: ffdhe6144 + * - RFC 7919 section A.5: ffdhe8192 + * + * The constants with suffix "_p" denote the chosen prime moduli, while + * the constants with suffix "_g" denote the chosen generator + * of the associated prime field. + * + * The constants further suffixed with "_bin" are provided in binary format, + * while all other constants represent null-terminated strings holding the + * hexadecimal presentation of the respective numbers. + * + * The primes from RFC 3526 and RFC 7919 have been generating by the following + * trust-worthy procedure: + * - Fix N in { 2048, 3072, 4096, 6144, 8192 } and consider the N-bit number + * the first and last 64 bits are all 1, and the remaining N - 128 bits of + * which are 0x7ff...ff. + * - Add the smallest multiple of the first N - 129 bits of the binary expansion + * of pi (for RFC 5236) or e (for RFC 7919) to this intermediate bit-string + * such that the resulting integer is a safe-prime. + * - The result is the respective RFC 3526 / 7919 prime, and the corresponding + * generator is always chosen to be 2 (which is a square for these prime, + * hence the corresponding subgroup has order (p-1)/2 and avoids leaking a + * bit in the private exponent). + * + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +/** + * \warning The origin of the primes in RFC 5114 is not documented and + * their use therefore constitutes a security risk! + * + * \deprecated The hex-encoded primes from RFC 5114 are deprecated and are + * likely to be removed in a future version of the library without + * replacement. + */ + +/** + * The hexadecimal presentation of the prime underlying the + * 2048-bit MODP Group with 224-bit Prime Order Subgroup, as defined + * in RFC-5114: Additional Diffie-Hellman Groups for Use with + * IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \ + "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \ + "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \ + "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \ + "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \ + "B3BF8A317091883681286130BC8985DB1602E714415D9330" \ + "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \ + "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \ + "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \ + "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \ + "CF9DE5384E71B81C0AC4DFFE0C10E64F" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group with 224-bit Prime Order Subgroup, as defined in RFC-5114: + * Additional Diffie-Hellman Groups for Use with IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF" \ + "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA" \ + "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7" \ + "C17669101999024AF4D027275AC1348BB8A762D0521BC98A" \ + "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE" \ + "F180EB34118E98D119529A45D6F834566E3025E316A330EF" \ + "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB" \ + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" \ + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269" \ + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" \ + "81BC087F2A7065B384B890D3191F2BFA" ) + +/** + * The hexadecimal presentation of the prime underlying the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + * + * \deprecated The hex-encoded primes from RFC 3625 are deprecated and + * superseded by the corresponding macros providing them as + * binary constants. Their hex-encoded constants are likely + * to be removed in a future version of the library. + * + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 3072-bit MODP + * Group, as defined in RFC-3072: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 3072-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ + "FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* + * Trustworthy DHM parameters in binary form + */ + +#define MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, \ + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, \ + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, \ + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, \ + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, \ + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, \ + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, \ + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, \ + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, \ + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, \ + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, \ + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, \ + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, \ + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, \ + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, \ + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, \ + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, \ + 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, \ + 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, \ + 0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, \ + 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, \ + 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, \ + 0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, \ + 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, \ + 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, \ + 0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, \ + 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, \ + 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, \ + 0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, \ + 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, \ + 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, \ + 0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, \ + 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, \ + 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, \ + 0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, \ + 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, \ + 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, \ + 0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, \ + 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, \ + 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, \ + 0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, \ + 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, \ + 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, \ + 0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, \ + 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, \ + 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, \ + 0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, \ + 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, \ + 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN { 0x02 } + +#endif /* dhm.h */ diff --git a/external/mbedtls/include/mbedtls/ecdh.h b/external/mbedtls/include/mbedtls/ecdh.h new file mode 100644 index 0000000..b9324bc --- /dev/null +++ b/external/mbedtls/include/mbedtls/ecdh.h @@ -0,0 +1,465 @@ +/** + * \file ecdh.h + * + * \brief This file contains ECDH definitions and functions. + * + * The Elliptic Curve Diffie-Hellman (ECDH) protocol is an anonymous + * key agreement protocol allowing two parties to establish a shared + * secret over an insecure channel. Each party must have an + * elliptic-curve public–private key pair. + * + * For more information, see NIST SP 800-56A Rev. 2: Recommendation for + * Pair-Wise Key Establishment Schemes Using Discrete Logarithm + * Cryptography. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_ECDH_H +#define MBEDTLS_ECDH_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ecp.h" + +/* + * Use a backward compatible ECDH context. + * + * This flag is always enabled for now and future versions might add a + * configuration option that conditionally undefines this flag. + * The configuration option in question may have a different name. + * + * Features undefining this flag, must have a warning in their description in + * config.h stating that the feature breaks backward compatibility. + */ +#define MBEDTLS_ECDH_LEGACY_CONTEXT + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Defines the source of the imported EC key. + */ +typedef enum +{ + MBEDTLS_ECDH_OURS, /**< Our key. */ + MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */ +} mbedtls_ecdh_side; + +#if !defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +/** + * Defines the ECDH implementation used. + * + * Later versions of the library may add new variants, therefore users should + * not make any assumptions about them. + */ +typedef enum +{ + MBEDTLS_ECDH_VARIANT_NONE = 0, /*!< Implementation not defined. */ + MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */ +} mbedtls_ecdh_variant; + +/** + * The context used by the default ECDH implementation. + * + * Later versions might change the structure of this context, therefore users + * should not make any assumptions about the structure of + * mbedtls_ecdh_context_mbed. + */ +typedef struct mbedtls_ecdh_context_mbed +{ + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ +#endif +} mbedtls_ecdh_context_mbed; +#endif + +/** + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. + * \brief The ECDH context structure. + */ +typedef struct mbedtls_ecdh_context +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ + int point_format; /*!< The format of point export in TLS messages. */ + mbedtls_ecp_point Vi; /*!< The blinding value. */ + mbedtls_ecp_point Vf; /*!< The unblinding value. */ + mbedtls_mpi _d; /*!< The previous \p d. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + int restart_enabled; /*!< The flag for restartable mode. */ + mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#else + uint8_t point_format; /*!< The format of point export in TLS messages + as defined in RFC 4492. */ + mbedtls_ecp_group_id grp_id;/*!< The elliptic curve used. */ + mbedtls_ecdh_variant var; /*!< The ECDH implementation/structure used. */ + union + { + mbedtls_ecdh_context_mbed mbed_ecdh; + } ctx; /*!< Implementation-specific context. The + context in use is specified by the \c var + field. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + uint8_t restart_enabled; /*!< The flag for restartable mode. Functions of + an alternative implementation not supporting + restartable mode must return + MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error + if this flag is set. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ +} +mbedtls_ecdh_context; + +/** + * \brief This function generates an ECDH keypair on an elliptic + * curve. + * + * This function performs the first of two core computations + * implemented during the ECDH key exchange. The second core + * computation is performed by mbedtls_ecdh_compute_shared(). + * + * \see ecp.h + * + * \param grp The ECP group to use. This must be initialized and have + * domain parameters loaded, for example through + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). + * \param d The destination MPI (private key). + * This must be initialized. + * \param Q The destination point (public key). + * This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function computes the shared secret. + * + * This function performs the second of two core computations + * implemented during the ECDH key exchange. The first core + * computation is performed by mbedtls_ecdh_gen_public(). + * + * \see ecp.h + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against side-channel attacks. + * For more information, see mbedtls_ecp_mul(). + * + * \param grp The ECP group to use. This must be initialized and have + * domain parameters loaded, for example through + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). + * \param z The destination MPI (shared secret). + * This must be initialized. + * \param Q The public key from another party. + * This must be initialized. + * \param d Our secret exponent (private key). + * This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results during the ECP computations is + * not needed (discouraged). See the documentation of + * mbedtls_ecp_mul() for more. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a + * context argument. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function initializes an ECDH context. + * + * \param ctx The ECDH context to initialize. This must not be \c NULL. + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function sets up the ECDH context with the information + * given. + * + * This function should be called after mbedtls_ecdh_init() but + * before mbedtls_ecdh_make_params(). There is no need to call + * this function before mbedtls_ecdh_read_params(). + * + * This is the first function used by a TLS server for ECDHE + * ciphersuites. + * + * \param ctx The ECDH context to set up. This must be initialized. + * \param grp_id The group id of the group to set up the context for. + * + * \return \c 0 on success. + */ +int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, + mbedtls_ecp_group_id grp_id ); + +/** + * \brief This function frees a context. + * + * \param ctx The context to free. This may be \c NULL, in which + * case this function does nothing. If it is not \c NULL, + * it must point to an initialized ECDH context. + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function generates an EC key pair and exports its + * in the format used in a TLS ServerKeyExchange handshake + * message. + * + * This is the second function used by a TLS server for ECDHE + * ciphersuites. (It is called after mbedtls_ecdh_setup().) + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, for example via mbedtls_ecdh_setup(). + * \param olen The address at which to store the number of Bytes written. + * \param buf The destination buffer. This must be a writable buffer of + * length \p blen Bytes. + * \param blen The length of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function parses the ECDHE parameters in a + * TLS ServerKeyExchange handshake message. + * + * \note In a TLS handshake, this is the how the client + * sets up its ECDHE context from the server's public + * ECDHE key material. + * + * \see ecp.h + * + * \param ctx The ECDHE context to use. This must be initialized. + * \param buf On input, \c *buf must be the start of the input buffer. + * On output, \c *buf is updated to point to the end of the + * data that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. + * + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, + const unsigned char *end ); + +/** + * \brief This function sets up an ECDH context from an EC key. + * + * It is used by clients and servers in place of the + * ServerKeyEchange for static ECDH, and imports ECDH + * parameters from the EC key information of a certificate. + * + * \see ecp.h + * + * \param ctx The ECDH context to set up. This must be initialized. + * \param key The EC key to use. This must be initialized. + * \param side Defines the source of the key. Possible values are: + * - #MBEDTLS_ECDH_OURS: The key is ours. + * - #MBEDTLS_ECDH_THEIRS: The key is that of the peer. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + * + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ); + +/** + * \brief This function generates a public key and exports it + * as a TLS ClientKeyExchange payload. + * + * This is the second function used by a TLS client for ECDH(E) + * ciphersuites. + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, the latter usually by + * mbedtls_ecdh_read_params(). + * \param olen The address at which to store the number of Bytes written. + * This must not be \c NULL. + * \param buf The destination buffer. This must be a writable buffer + * of length \p blen Bytes. + * \param blen The size of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function parses and processes the ECDHE payload of a + * TLS ClientKeyExchange message. + * + * This is the third function used by a TLS server for ECDH(E) + * ciphersuites. (It is called after mbedtls_ecdh_setup() and + * mbedtls_ecdh_make_params().) + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, for example via mbedtls_ecdh_setup(). + * \param buf The pointer to the ClientKeyExchange payload. This must + * be a readable buffer of length \p blen Bytes. + * \param blen The length of the input buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ); + +/** + * \brief This function derives and exports the shared secret. + * + * This is the last function used by both TLS client + * and servers. + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against side-channel attacks. + * For more information, see mbedtls_ecp_mul(). + * + * \see ecp.h + + * \param ctx The ECDH context to use. This must be initialized + * and have its own private key generated and the peer's + * public key imported. + * \param olen The address at which to store the total number of + * Bytes written on success. This must not be \c NULL. + * \param buf The buffer to write the generated shared key to. This + * must be a writable buffer of size \p blen Bytes. + * \param blen The length of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function, for blinding purposes. This may + * b \c NULL if blinding isn't needed. + * \param p_rng The RNG context. This may be \c NULL if \p f_rng + * doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief This function enables restartable EC computations for this + * context. (Default: disabled.) + * + * \see \c mbedtls_ecp_set_max_ops() + * + * \note It is not possible to safely disable restartable + * computations once enabled, except by free-ing the context, + * which cancels possible in-progress operations. + * + * \param ctx The ECDH context to use. This must be initialized. + */ +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecdh.h */ diff --git a/external/mbedtls/include/mbedtls/ecdsa.h b/external/mbedtls/include/mbedtls/ecdsa.h new file mode 100644 index 0000000..da02b27 --- /dev/null +++ b/external/mbedtls/include/mbedtls/ecdsa.h @@ -0,0 +1,629 @@ +/** + * \file ecdsa.h + * + * \brief This file contains ECDSA definitions and functions. + * + * The Elliptic Curve Digital Signature Algorithm (ECDSA) is defined in + * Standards for Efficient Cryptography Group (SECG): + * SEC1 Elliptic Curve Cryptography. + * The use of ECDSA for TLS is defined in RFC-4492: Elliptic Curve + * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS). + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_ECDSA_H +#define MBEDTLS_ECDSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ecp.h" +#include "md.h" + +/* + * RFC-4492 page 20: + * + * Ecdsa-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * Size is at most + * 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s, + * twice that + 1 (tag) + 2 (len) for the sequence + * (assuming ECP_MAX_BYTES is less than 126 for r and s, + * and less than 124 (total len <= 255) for the sequence) + */ +#if MBEDTLS_ECP_MAX_BYTES > 124 +#error "MBEDTLS_ECP_MAX_BYTES bigger than expected, please fix MBEDTLS_ECDSA_MAX_LEN" +#endif +/** The maximal size of an ECDSA signature in Bytes. */ +#define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The ECDSA context structure. + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. + */ +typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Internal restart context for ecdsa_verify() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx; + +/** + * \brief Internal restart context for ecdsa_sign() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/** + * \brief Internal restart context for ecdsa_sign_det() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx; +#endif + +/** + * \brief General context for resuming ECDSA operations + */ +typedef struct +{ + mbedtls_ecp_restart_ctx ecp; /*!< base context for ECP restart and + shared administrative info */ + mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */ + mbedtls_ecdsa_restart_sig_ctx *sig; /*!< ecdsa_sign() sub-context */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */ +#endif +} mbedtls_ecdsa_restart_ctx; + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_ecdsa_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message. + * + * \note The deterministic version implemented in + * mbedtls_ecdsa_sign_det() is usually preferred. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated + * as defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized. + * \param buf The content to be signed. This is usually the hash of + * the original data to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX + * or \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. + * + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \warning Since the output of the internal RNG is always the same for + * the same key and message, this limits the efficiency of + * blinding and leaks information through side channels. For + * secure behavior use mbedtls_ecdsa_sign_det_ext() instead. + * + * (Optimally the blinding is a random value that is different + * on every execution. In this case the blinding is still + * random from the attackers perspective, but is the same on + * each execution. This means that this blinding does not + * prevent attackers from recovering secrets by combining + * several measurement traces, but may prevent some attacks + * that exploit relationships between secret data.) + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param md_alg The hash algorithm used to hash the original data. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ); +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. + * + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param md_alg The hash algorithm used to hash the original data. + * \param f_rng_blind The RNG function used for blinding. This must not be + * \c NULL. + * \param p_rng_blind The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, + size_t), + void *p_rng_blind ); +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function verifies the ECDSA signature of a + * previously-hashed message. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \see ecp.h + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param buf The hashed content that was signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param Q The public key to use for verification. This must be + * initialized and setup. + * \param r The first integer of the signature. + * This must be initialized. + * \param s The second integer of the signature. + * This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature + * is invalid. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, + const mbedtls_mpi *s); + +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + * + * \note The deterministic version is used if + * #MBEDTLS_ECDSA_DETERMINISTIC is defined. For more + * information, see RFC-6979: Deterministic Usage + * of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param f_rng The RNG function. This must not be \c NULL if + * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, + * it is unused and may be set to \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't use a context. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, in a restartable way. + * + * \see \c mbedtls_ecdsa_write_signature() + * + * \note This function is like \c mbedtls_ecdsa_write_signature() + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param f_rng The RNG function. This must not be \c NULL if + * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, + * it is unused and may be set to \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't use a context. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function computes an ECDSA signature and writes + * it to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). + * + * The deterministic version is defined in RFC-6979: + * Deterministic Usage of the Digital Signature Algorithm (DSA) + * and Elliptic Curve Digital Signature Algorithm (ECDSA). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \deprecated Superseded by mbedtls_ecdsa_write_signature() in + * Mbed TLS version 2.0 and later. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param md_alg The message digest that was used to hash the message. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function reads and verifies an ECDSA signature. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \see ecp.h + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and public key bound to it. + * \param hash The message hash that was signed. This must be a readable + * buffer of length \p size Bytes. + * \param hlen The size of the hash \p hash. + * \param sig The signature to read and verify. This must be a readable + * buffer of length \p slen Bytes. + * \param slen The size of \p sig in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ); + +/** + * \brief This function reads and verifies an ECDSA signature, + * in a restartable way. + * + * \see \c mbedtls_ecdsa_read_signature() + * + * \note This function is like \c mbedtls_ecdsa_read_signature() + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and public key bound to it. + * \param hash The message hash that was signed. This must be a readable + * buffer of length \p size Bytes. + * \param hlen The size of the hash \p hash. + * \param sig The signature to read and verify. This must be a readable + * buffer of length \p slen Bytes. + * \param slen The size of \p sig in Bytes. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + +/** + * \brief This function generates an ECDSA keypair on the given curve. + * + * \see ecp.h + * + * \param ctx The ECDSA context to store the keypair in. + * This must be initialized. + * \param gid The elliptic curve to use. One of the various + * \c MBEDTLS_ECP_DP_XXX macros depending on configuration. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function sets up an ECDSA context from an EC key pair. + * + * \see ecp.h + * + * \param ctx The ECDSA context to setup. This must be initialized. + * \param key The EC key to use. This must be initialized and hold + * a private-public key pair or a public key. In the former + * case, the ECDSA context may be used for signature creation + * and verification after this call. In the latter case, it + * may be used for signature verification. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, + const mbedtls_ecp_keypair *key ); + +/** + * \brief This function initializes an ECDSA context. + * + * \param ctx The ECDSA context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); + +/** + * \brief This function frees an ECDSA context. + * + * \param ctx The ECDSA context to free. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must be initialized. + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context. + * + * \param ctx The restart context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context. + * + * \param ctx The restart context to free. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must be initialized. + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecdsa.h */ diff --git a/external/mbedtls/include/mbedtls/ecjpake.h b/external/mbedtls/include/mbedtls/ecjpake.h new file mode 100644 index 0000000..a9b68d0 --- /dev/null +++ b/external/mbedtls/include/mbedtls/ecjpake.h @@ -0,0 +1,302 @@ +/** + * \file ecjpake.h + * + * \brief Elliptic curve J-PAKE + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_ECJPAKE_H +#define MBEDTLS_ECJPAKE_H + +/* + * J-PAKE is a password-authenticated key exchange that allows deriving a + * strong shared secret from a (potentially low entropy) pre-shared + * passphrase, with forward secrecy and mutual authentication. + * https://en.wikipedia.org/wiki/Password_Authenticated_Key_Exchange_by_Juggling + * + * This file implements the Elliptic Curve variant of J-PAKE, + * as defined in Chapter 7.4 of the Thread v1.0 Specification, + * available to members of the Thread Group http://threadgroup.org/ + * + * As the J-PAKE algorithm is inherently symmetric, so is our API. + * Each party needs to send its first round message, in any order, to the + * other party, then each sends its second round message, in any order. + * The payloads are serialized in a way suitable for use in TLS, but could + * also be use outside TLS. + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ecp.h" +#include "md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Roles in the EC J-PAKE exchange + */ +typedef enum { + MBEDTLS_ECJPAKE_CLIENT = 0, /**< Client */ + MBEDTLS_ECJPAKE_SERVER, /**< Server */ +} mbedtls_ecjpake_role; + +#if !defined(MBEDTLS_ECJPAKE_ALT) +/** + * EC J-PAKE context structure. + * + * J-PAKE is a symmetric protocol, except for the identifiers used in + * Zero-Knowledge Proofs, and the serialization of the second message + * (KeyExchange) as defined by the Thread spec. + * + * In order to benefit from this symmetry, we choose a different naming + * convetion from the Thread v1.0 spec. Correspondance is indicated in the + * description as a pair C: client name, S: server name + */ +typedef struct mbedtls_ecjpake_context +{ + const mbedtls_md_info_t *md_info; /**< Hash to use */ + mbedtls_ecp_group grp; /**< Elliptic curve */ + mbedtls_ecjpake_role role; /**< Are we client or server? */ + int point_format; /**< Format for point export */ + + mbedtls_ecp_point Xm1; /**< My public key 1 C: X1, S: X3 */ + mbedtls_ecp_point Xm2; /**< My public key 2 C: X2, S: X4 */ + mbedtls_ecp_point Xp1; /**< Peer public key 1 C: X3, S: X1 */ + mbedtls_ecp_point Xp2; /**< Peer public key 2 C: X4, S: X2 */ + mbedtls_ecp_point Xp; /**< Peer public key C: Xs, S: Xc */ + + mbedtls_mpi xm1; /**< My private key 1 C: x1, S: x3 */ + mbedtls_mpi xm2; /**< My private key 2 C: x2, S: x4 */ + + mbedtls_mpi s; /**< Pre-shared secret (passphrase) */ +} mbedtls_ecjpake_context; + +#else /* MBEDTLS_ECJPAKE_ALT */ +#include "ecjpake_alt.h" +#endif /* MBEDTLS_ECJPAKE_ALT */ + +/** + * \brief Initialize an ECJPAKE context. + * + * \param ctx The ECJPAKE context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ); + +/** + * \brief Set up an ECJPAKE context for use. + * + * \note Currently the only values for hash/curve allowed by the + * standard are #MBEDTLS_MD_SHA256/#MBEDTLS_ECP_DP_SECP256R1. + * + * \param ctx The ECJPAKE context to set up. This must be initialized. + * \param role The role of the caller. This must be either + * #MBEDTLS_ECJPAKE_CLIENT or #MBEDTLS_ECJPAKE_SERVER. + * \param hash The identifier of the hash function to use, + * for example #MBEDTLS_MD_SHA256. + * \param curve The identifier of the elliptic curve to use, + * for example #MBEDTLS_ECP_DP_SECP256R1. + * \param secret The pre-shared secret (passphrase). This must be + * a readable buffer of length \p len Bytes. It need + * only be valid for the duration of this call. + * \param len The length of the pre-shared secret \p secret. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, + mbedtls_ecjpake_role role, + mbedtls_md_type_t hash, + mbedtls_ecp_group_id curve, + const unsigned char *secret, + size_t len ); + +/** + * \brief Check if an ECJPAKE context is ready for use. + * + * \param ctx The ECJPAKE context to check. This must be + * initialized. + * + * \return \c 0 if the context is ready for use. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise. + */ +int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ); + +/** + * \brief Generate and write the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes). + * + * \param ctx The ECJPAKE context to use. This must be + * initialized and set up. + * \param buf The buffer to write the contents to. This must be a + * writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number + * of Bytes written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes). + * + * \param ctx The ECJPAKE context to use. This must be initialized + * and set up. + * \param buf The buffer holding the first round message. This must + * be a readable buffer of length \p len Bytes. + * \param len The length in Bytes of \p buf. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Generate and write the second round message + * (TLS: contents of the Client/ServerKeyExchange). + * + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up, and already have performed round one. + * \param buf The buffer to write the round two contents to. + * This must be a writable buffer of length \p len Bytes. + * \param len The size of \p buf in Bytes. + * \param olen The address at which to store the total number of Bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the second round message + * (TLS: contents of the Client/ServerKeyExchange). + * + * \param ctx The ECJPAKE context to use. This must be initialized + * and set up and already have performed round one. + * \param buf The buffer holding the second round message. This must + * be a readable buffer of length \p len Bytes. + * \param len The length in Bytes of \p buf. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Derive the shared secret + * (TLS: Pre-Master Secret). + * + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up and have performed both round one and two. + * \param buf The buffer to write the derived secret to. This must + * be a writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number of Bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This clears an ECJPAKE context and frees any + * embedded data structure. + * + * \param ctx The ECJPAKE context to free. This may be \c NULL, + * in which case this function does nothing. If it is not + * \c NULL, it must point to an initialized ECJPAKE context. + */ +void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_ecjpake_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + + +#endif /* ecjpake.h */ diff --git a/external/mbedtls/include/mbedtls/ecp.h b/external/mbedtls/include/mbedtls/ecp.h new file mode 100644 index 0000000..bdc750e --- /dev/null +++ b/external/mbedtls/include/mbedtls/ecp.h @@ -0,0 +1,1160 @@ +/** + * \file ecp.h + * + * \brief This file provides an API for Elliptic Curves over GF(P) (ECP). + * + * The use of ECP in cryptography and TLS is defined in + * Standards for Efficient Cryptography Group (SECG): SEC1 + * Elliptic Curve Cryptography and + * RFC-4492: Elliptic Curve Cryptography (ECC) Cipher Suites + * for Transport Layer Security (TLS). + * + * RFC-2409: The Internet Key Exchange (IKE) defines ECP + * group types. + * + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_ECP_H +#define MBEDTLS_ECP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" + +/* + * ECP error codes + */ +#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< The requested feature is not available, for example, the requested curve is not supported. */ +#define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */ +#define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as ephemeral key, failed. */ +#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ +#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< The buffer contains a valid signature followed by more data. */ + +/* MBEDTLS_ERR_ECP_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< The ECP hardware accelerator failed. */ + +#define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 /**< Operation in progress, call again with the same parameters to continue. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Domain-parameter identifiers: curve, subgroup, and generator. + * + * \note Only curves over prime fields are supported. + * + * \warning This library does not support validation of arbitrary domain + * parameters. Therefore, only standardized domain parameters from trusted + * sources should be used. See mbedtls_ecp_group_load(). + */ +typedef enum +{ + MBEDTLS_ECP_DP_NONE = 0, /*!< Curve not defined. */ + MBEDTLS_ECP_DP_SECP192R1, /*!< Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP224R1, /*!< Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP256R1, /*!< Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP384R1, /*!< Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP521R1, /*!< Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_BP256R1, /*!< Domain parameters for 256-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP384R1, /*!< Domain parameters for 384-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP512R1, /*!< Domain parameters for 512-bit Brainpool curve. */ + MBEDTLS_ECP_DP_CURVE25519, /*!< Domain parameters for Curve25519. */ + MBEDTLS_ECP_DP_SECP192K1, /*!< Domain parameters for 192-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP224K1, /*!< Domain parameters for 224-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP256K1, /*!< Domain parameters for 256-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_CURVE448, /*!< Domain parameters for Curve448. */ +} mbedtls_ecp_group_id; + +/** + * The number of supported curves, plus one for #MBEDTLS_ECP_DP_NONE. + * + * \note Montgomery curves are currently excluded. + */ +#define MBEDTLS_ECP_DP_MAX 12 + +/** + * Curve information, for use by other modules. + */ +typedef struct mbedtls_ecp_curve_info +{ + mbedtls_ecp_group_id grp_id; /*!< An internal identifier. */ + uint16_t tls_id; /*!< The TLS NamedCurve identifier. */ + uint16_t bit_size; /*!< The curve size in bits. */ + const char *name; /*!< A human-friendly name. */ +} mbedtls_ecp_curve_info; + +/** + * \brief The ECP point structure, in Jacobian coordinates. + * + * \note All functions expect and return points satisfying + * the following condition: Z == 0 or + * Z == 1. Other values of \p Z are + * used only by internal functions. + * The point is zero, or "at infinity", if Z == 0. + * Otherwise, \p X and \p Y are its standard (affine) + * coordinates. + */ +typedef struct mbedtls_ecp_point +{ + mbedtls_mpi X; /*!< The X coordinate of the ECP point. */ + mbedtls_mpi Y; /*!< The Y coordinate of the ECP point. */ + mbedtls_mpi Z; /*!< The Z coordinate of the ECP point. */ +} +mbedtls_ecp_point; + +#if !defined(MBEDTLS_ECP_ALT) +/* + * default mbed TLS elliptic curve arithmetic implementation + * + * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an + * alternative implementation for the whole module and it will replace this + * one.) + */ + +/** + * \brief The ECP group structure. + * + * We consider two types of curve equations: + *
  • Short Weierstrass: y^2 = x^3 + A x + B mod P + * (SEC1 + RFC-4492)
  • + *
  • Montgomery: y^2 = x^3 + A x^2 + x mod P (Curve25519, + * Curve448)
+ * In both cases, the generator (\p G) for a prime-order subgroup is fixed. + * + * For Short Weierstrass, this subgroup is the whole curve, and its + * cardinality is denoted by \p N. Our code requires that \p N is an + * odd prime as mbedtls_ecp_mul() requires an odd number, and + * mbedtls_ecdsa_sign() requires that it is prime for blinding purposes. + * + * For Montgomery curves, we do not store \p A, but (A + 2) / 4, + * which is the quantity used in the formulas. Additionally, \p nbits is + * not the size of \p N but the required size for private keys. + * + * If \p modp is NULL, reduction modulo \p P is done using a generic algorithm. + * Otherwise, \p modp must point to a function that takes an \p mbedtls_mpi in the + * range of 0..2^(2*pbits)-1, and transforms it in-place to an integer + * which is congruent mod \p P to the given MPI, and is close enough to \p pbits + * in size, so that it may be efficiently brought in the 0..P-1 range by a few + * additions or subtractions. Therefore, it is only an approximative modular + * reduction. It must return 0 on success and non-zero on failure. + * + * \note Alternative implementations must keep the group IDs distinct. If + * two group structures have the same ID, then they must be + * identical. + * + */ +typedef struct mbedtls_ecp_group +{ + mbedtls_ecp_group_id id; /*!< An internal group identifier. */ + mbedtls_mpi P; /*!< The prime modulus of the base field. */ + mbedtls_mpi A; /*!< For Short Weierstrass: \p A in the equation. For + Montgomery curves: (A + 2) / 4. */ + mbedtls_mpi B; /*!< For Short Weierstrass: \p B in the equation. + For Montgomery curves: unused. */ + mbedtls_ecp_point G; /*!< The generator of the subgroup used. */ + mbedtls_mpi N; /*!< The order of \p G. */ + size_t pbits; /*!< The number of bits in \p P.*/ + size_t nbits; /*!< For Short Weierstrass: The number of bits in \p P. + For Montgomery curves: the number of bits in the + private keys. */ + unsigned int h; /*!< \internal 1 if the constants are static. */ + int (*modp)(mbedtls_mpi *); /*!< The function for fast pseudo-reduction + mod \p P (see above).*/ + int (*t_pre)(mbedtls_ecp_point *, void *); /*!< Unused. */ + int (*t_post)(mbedtls_ecp_point *, void *); /*!< Unused. */ + void *t_data; /*!< Unused. */ + mbedtls_ecp_point *T; /*!< Pre-computed points for ecp_mul_comb(). */ + size_t T_size; /*!< The number of pre-computed points. */ +} +mbedtls_ecp_group; + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h, or define them using the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ECP_MAX_BITS) +/** + * The maximum size of the groups, that is, of \c N and \c P. + */ +#define MBEDTLS_ECP_MAX_BITS 521 /**< The maximum size of groups, in bits. */ +#endif + +#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 ) +#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 ) + +#if !defined(MBEDTLS_ECP_WINDOW_SIZE) +/* + * Maximum "window" size used for point multiplication. + * Default: 6. + * Minimum value: 2. Maximum value: 7. + * + * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + * points used for point multiplication. This value is directly tied to EC + * peak memory usage, so decreasing it by one should roughly cut memory usage + * by two (if large curves are in use). + * + * Reduction in size may reduce speed, but larger curves are impacted first. + * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): + * w-size: 6 5 4 3 2 + * 521 145 141 135 120 97 + * 384 214 209 198 177 146 + * 256 320 320 303 262 226 + * 224 475 475 453 398 342 + * 192 640 640 633 587 476 + */ +#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< The maximum window size used. */ +#endif /* MBEDTLS_ECP_WINDOW_SIZE */ + +#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) +/* + * Trade memory for speed on fixed-point multiplication. + * + * This speeds up repeated multiplication of the generator (that is, the + * multiplication in ECDSA signatures, and half of the multiplications in + * ECDSA verification and ECDHE) by a factor roughly 3 to 4. + * + * The cost is increasing EC peak memory usage by a factor roughly 2. + * + * Change this value to 0 to reduce peak memory usage. + */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */ +#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ + +/* \} name SECTION: Module settings */ + +#else /* MBEDTLS_ECP_ALT */ +#include "ecp_alt.h" +#endif /* MBEDTLS_ECP_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Internal restart context for multiplication + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; + +/** + * \brief Internal restart context for ecp_muladd() + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx; + +/** + * \brief General context for resuming ECC operations + */ +typedef struct +{ + unsigned ops_done; /*!< current ops count */ + unsigned depth; /*!< call depth (0 = top-level) */ + mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */ + mbedtls_ecp_restart_muladd_ctx *ma; /*!< ecp_muladd() sub-context */ +} mbedtls_ecp_restart_ctx; + +/* + * Operation counts for restartable functions + */ +#define MBEDTLS_ECP_OPS_CHK 3 /*!< basic ops count for ecp_check_pubkey() */ +#define MBEDTLS_ECP_OPS_DBL 8 /*!< basic ops count for ecp_double_jac() */ +#define MBEDTLS_ECP_OPS_ADD 11 /*!< basic ops count for see ecp_add_mixed() */ +#define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv() */ + +/** + * \brief Internal; for restartable functions in other modules. + * Check and update basic ops budget. + * + * \param grp Group structure + * \param rs_ctx Restart context + * \param ops Number of basic ops to do + * + * \return \c 0 if doing \p ops basic ops is still allowed, + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise. + */ +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ); + +/* Utility macro for checking and updating ops budget */ +#define MBEDTLS_ECP_BUDGET( ops ) \ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, rs_ctx, \ + (unsigned) (ops) ) ); + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define MBEDTLS_ECP_BUDGET( ops ) /* no-op; for compatibility */ + +/* We want to declare restartable versions of existing functions anyway */ +typedef void mbedtls_ecp_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief The ECP key-pair structure. + * + * A generic key-pair that may be used for ECDSA and fixed ECDH, for example. + * + * \note Members are deliberately in the same order as in the + * ::mbedtls_ecdsa_context structure. + */ +typedef struct mbedtls_ecp_keypair +{ + mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ + mbedtls_mpi d; /*!< our secret value */ + mbedtls_ecp_point Q; /*!< our public value */ +} +mbedtls_ecp_keypair; + +/* + * Point formats, from RFC 4492's enum ECPointFormat + */ +#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format. */ +#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format. */ + +/* + * Some other constants from RFC 4492 + */ +#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Set the maximum number of basic operations done in a row. + * + * If more operations are needed to complete a computation, + * #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the + * function performing the computation. It is then the + * caller's responsibility to either call again with the same + * parameters until it returns 0 or an error code; or to free + * the restart context if the operation is to be aborted. + * + * It is strictly required that all input parameters and the + * restart context be the same on successive calls for the + * same operation, but output parameters need not be the + * same; they must not be used until the function finally + * returns 0. + * + * This only applies to functions whose documentation + * mentions they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS for functions in the + * SSL module). For functions that accept a "restart context" + * argument, passing NULL disables restart and makes the + * function equivalent to the function with the same name + * with \c _restartable removed. For functions in the ECDH + * module, restart is disabled unless the function accepts + * an "ECDH context" argument and + * mbedtls_ecdh_enable_restart() was previously called on + * that context. For function in the SSL module, restart is + * only enabled for specific sides and key exchanges + * (currently only for clients and ECDHE-ECDSA). + * + * \param max_ops Maximum number of basic operations done in a row. + * Default: 0 (unlimited). + * Lower (non-zero) values mean ECC functions will block for + * a lesser maximum amount of time. + * + * \note A "basic operation" is defined as a rough equivalent of a + * multiplication in GF(p) for the NIST P-256 curve. + * As an indication, with default settings, a scalar + * multiplication (full run of \c mbedtls_ecp_mul()) is: + * - about 3300 basic operations for P-256 + * - about 9400 basic operations for P-384 + * + * \note Very low values are not always respected: sometimes + * functions need to block for a minimum number of + * operations, and will do so even if max_ops is set to a + * lower value. That minimum depends on the curve size, and + * can be made lower by decreasing the value of + * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, here is the + * lowest effective value for various curves and values of + * that parameter (w for short): + * w=6 w=5 w=4 w=3 w=2 + * P-256 208 208 160 136 124 + * P-384 682 416 320 272 248 + * P-521 1364 832 640 544 496 + * + * \note This setting is currently ignored by Curve25519. + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ); + +/** + * \brief Check if restart is enabled (max_ops != 0) + * + * \return \c 0 if \c max_ops == 0 (restart disabled) + * \return \c 1 otherwise (restart enabled) + */ +int mbedtls_ecp_restart_is_enabled( void ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief This function retrieves the information defined in + * mbedtls_ecp_curve_info() for all supported curves in order + * of preference. + * + * \return A statically allocated array. The last entry is 0. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); + +/** + * \brief This function retrieves the list of internal group + * identifiers of all supported curves in the order of + * preference. + * + * \return A statically allocated array, + * terminated with MBEDTLS_ECP_DP_NONE. + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); + +/** + * \brief This function retrieves curve information from an internal + * group identifier. + * + * \param grp_id An \c MBEDTLS_ECP_DP_XXX value. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ); + +/** + * \brief This function retrieves curve information from a TLS + * NamedCurve value. + * + * \param tls_id An \c MBEDTLS_ECP_DP_XXX value. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ); + +/** + * \brief This function retrieves curve information from a + * human-readable name. + * + * \param name The human-readable name. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ); + +/** + * \brief This function initializes a point as zero. + * + * \param pt The point to initialize. + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ); + +/** + * \brief This function initializes an ECP group context + * without loading any domain parameters. + * + * \note After this function is called, domain parameters + * for various ECP groups can be loaded through the + * mbedtls_ecp_group_load() or mbedtls_ecp_tls_read_group() + * functions. + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); + +/** + * \brief This function initializes a key pair as an invalid one. + * + * \param key The key pair to initialize. + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ); + +/** + * \brief This function frees the components of a point. + * + * \param pt The point to free. + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); + +/** + * \brief This function frees the components of an ECP group. + * + * \param grp The group to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized ECP group. + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); + +/** + * \brief This function frees the components of a key pair. + * + * \param key The key pair to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized ECP key pair. + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context. + * + * \param ctx The restart context to initialize. This must + * not be \c NULL. + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context. + * + * \param ctx The restart context to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized restart context. + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief This function copies the contents of point \p Q into + * point \p P. + * + * \param P The destination point. This must be initialized. + * \param Q The source point. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code for other kinds of failure. + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); + +/** + * \brief This function copies the contents of group \p src into + * group \p dst. + * + * \param dst The destination group. This must be initialized. + * \param src The source group. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, + const mbedtls_ecp_group *src ); + +/** + * \brief This function sets a point to the point at infinity. + * + * \param pt The point to set. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); + +/** + * \brief This function checks if a point is the point at infinity. + * + * \param pt The point to test. This must be initialized. + * + * \return \c 1 if the point is zero. + * \return \c 0 if the point is non-zero. + * \return A negative error code on failure. + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); + +/** + * \brief This function compares two points. + * + * \note This assumes that the points are normalized. Otherwise, + * they may compare as "not equal" even if they are. + * + * \param P The first point to compare. This must be initialized. + * \param Q The second point to compare. This must be initialized. + * + * \return \c 0 if the points are equal. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the points are not equal. + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); + +/** + * \brief This function imports a non-zero point from two ASCII + * strings. + * + * \param P The destination point. This must be initialized. + * \param radix The numeric base of the input. + * \param x The first affine coordinate, as a null-terminated string. + * \param y The second affine coordinate, as a null-terminated string. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on failure. + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ); + +/** + * \brief This function exports a point into unsigned binary data. + * + * \param grp The group to which the point should belong. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param P The point to export. This must be initialized. + * \param format The point format. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * \param olen The address at which to store the length of + * the output in Bytes. This must not be \c NULL. + * \param buf The output buffer. This must be a writable buffer + * of length \p buflen Bytes. + * \param buflen The length of the output buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer + * is too small to hold the point. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ); + +/** + * \brief This function imports a point from unsigned binary data. + * + * \note This function does not check that the point actually + * belongs to the given group, see mbedtls_ecp_check_pubkey() + * for that. + * + * \param grp The group to which the point should belong. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param P The destination context to import the point to. + * This must be initialized. + * \param buf The input buffer. This must be a readable buffer + * of length \p ilen Bytes. + * \param ilen The length of the input buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * is not implemented. + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, + const unsigned char *buf, size_t ilen ); + +/** + * \brief This function imports a point from a TLS ECPoint record. + * + * \note On function return, \p *buf is updated to point immediately + * after the ECPoint record. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The destination point. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization + * failure. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char **buf, size_t len ); + +/** + * \brief This function exports a point as a TLS ECPoint record + * defined in RFC 4492, Section 5.4. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The point to be exported. This must be initialized. + * \param format The point format to use. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * \param olen The address at which to store the length in Bytes + * of the data written. + * \param buf The target buffer. This must be a writable buffer of + * length \p blen Bytes. + * \param blen The length of the target buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the target buffer + * is too small to hold the exported point. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function sets up an ECP group context + * from a standardized set of domain parameters. + * + * \note The index should be a value of the NamedCurve enum, + * as defined in RFC-4492: Elliptic Curve Cryptography + * (ECC) Cipher Suites for Transport Layer Security (TLS), + * usually in the form of an \c MBEDTLS_ECP_DP_XXX macro. + * + * \param grp The group context to setup. This must be initialized. + * \param id The identifier of the domain parameter set to load. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p id doesn't + * correspond to a known group. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ); + +/** + * \brief This function sets up an ECP group context from a TLS + * ECParameters record as defined in RFC 4492, Section 5.4. + * + * \note The read pointer \p buf is updated to point right after + * the ECParameters record on exit. + * + * \param grp The group context to setup. This must be initialized. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the input buffer \c *buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not + * recognized. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, + const unsigned char **buf, size_t len ); + +/** + * \brief This function extracts an elliptic curve group ID from a + * TLS ECParameters record as defined in RFC 4492, Section 5.4. + * + * \note The read pointer \p buf is updated to point right after + * the ECParameters record on exit. + * + * \param grp The address at which to store the group id. + * This must not be \c NULL. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the input buffer \c *buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not + * recognized. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp, + const unsigned char **buf, + size_t len ); +/** + * \brief This function exports an elliptic curve as a TLS + * ECParameters record as defined in RFC 4492, Section 5.4. + * + * \param grp The ECP group to be exported. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param olen The address at which to store the number of Bytes written. + * This must not be \c NULL. + * \param buf The buffer to write to. This must be a writable buffer + * of length \p blen Bytes. + * \param blen The length of the output buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output + * buffer is too small to hold the exported group. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, + size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function performs a scalar multiplication of a point + * by an integer: \p R = \p m * \p P. + * + * It is not thread-safe to use same group in multiple threads. + * + * \note To prevent timing attacks, this function + * executes the exact same sequence of base-field + * operations for any valid \p m. It avoids any if-branch or + * array index depending on the value of \p m. + * + * \note If \p f_rng is not NULL, it is used to randomize + * intermediate results to prevent potential timing attacks + * targeting these results. We recommend always providing + * a non-NULL \p f_rng. The overhead is negligible. + * Note: unless #MBEDTLS_ECP_NO_INTERNAL_RNG is defined, when + * \p f_rng is NULL, an internal RNG (seeded from the value + * of \p m) will be used instead. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply. This must be initialized. + * \param P The point to multiply. This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results isn't desired (discouraged). + * \param p_rng The RNG context to be passed to \p p_rng. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function performs multiplication of a point by + * an integer: \p R = \p m * \p P in a restartable way. + * + * \see mbedtls_ecp_mul() + * + * \note This function does the same as \c mbedtls_ecp_mul(), but + * it can return early and restart according to the limit set + * with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply. This must be initialized. + * \param P The point to multiply. This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results isn't desired (discouraged). + * \param p_rng The RNG context to be passed to \p p_rng. + * \param rs_ctx The restart context (NULL disables restart). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ); + +/** + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q + * + * It is not thread-safe to use same group in multiple threads. + * + * \note In contrast to mbedtls_ecp_mul(), this function does not + * guarantee a constant execution flow and timing. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply \p P. + * This must be initialized. + * \param P The point to multiply by \p m. This must be initialized. + * \param n The integer by which to multiply \p Q. + * This must be initialized. + * \param Q The point to be multiplied by \p n. + * This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); + +/** + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q in a + * restartable way. + * + * \see \c mbedtls_ecp_muladd() + * + * \note This function works the same as \c mbedtls_ecp_muladd(), + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply \p P. + * This must be initialized. + * \param P The point to multiply by \p m. This must be initialized. + * \param n The integer by which to multiply \p Q. + * This must be initialized. + * \param Q The point to be multiplied by \p n. + * This must be initialized. + * \param rs_ctx The restart context (NULL disables restart). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ); + +/** + * \brief This function checks that a point is a valid public key + * on this curve. + * + * It only checks that the point is non-zero, has + * valid coordinates and lies on the curve. It does not verify + * that it is indeed a multiple of \p G. This additional + * check is computationally more expensive, is not required + * by standards, and should not be necessary if the group + * used has a small cofactor. In particular, it is useless for + * the NIST groups which all have a cofactor of 1. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure, to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group the point should belong to. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The point to check. This must be initialized. + * + * \return \c 0 if the point is a valid public key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not + * a valid public key for the given curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ); + +/** + * \brief This function checks that an \p mbedtls_mpi is a + * valid private key for this curve. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group the private key should belong to. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The integer to check. This must be initialized. + * + * \return \c 0 if the point is a valid private key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not a valid + * private key for the given curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, + const mbedtls_mpi *d ); + +/** + * \brief This function generates a private key. + * + * \param grp The ECP group to generate a private key for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The destination MPI (secret part). This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates a keypair with a configurable base + * point. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group to generate a key pair for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param G The base point to use. This must be initialized + * and belong to \p grp. It replaces the default base + * point \c grp->G used by mbedtls_ecp_gen_keypair(). + * \param d The destination MPI (secret part). + * This must be initialized. + * \param Q The destination point (public part). + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates an ECP keypair. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group to generate a key pair for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The destination MPI (secret part). + * This must be initialized. + * \param Q The destination point (public part). + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, + mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates an ECP key. + * + * \param grp_id The ECP group identifier. + * \param key The destination key. This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function checks that the keypair objects + * \p pub and \p prv have the same group and the + * same public point, and that the private key in + * \p prv is consistent with the public key. + * + * \param pub The keypair structure holding the public key. This + * must be initialized. If it contains a private key, that + * part is ignored. + * \param prv The keypair structure holding the full keypair. + * This must be initialized. + * + * \return \c 0 on success, meaning that the keys are valid and match. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match. + * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX + * error code on calculation failure. + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, + const mbedtls_ecp_keypair *prv ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The ECP checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ecp_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecp.h */ diff --git a/external/mbedtls/include/mbedtls/ecp_internal.h b/external/mbedtls/include/mbedtls/ecp_internal.h new file mode 100644 index 0000000..0047bd4 --- /dev/null +++ b/external/mbedtls/include/mbedtls/ecp_internal.h @@ -0,0 +1,324 @@ +/** + * \file ecp_internal.h + * + * \brief Function declarations for alternative implementation of elliptic curve + * point arithmetic. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * References: + * + * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records. + * + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + * + * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters. + * + * + * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic + * Curve Cryptography. + * + * [6] Digital Signature Standard (DSS), FIPS 186-4. + * + * + * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer + * Security (TLS), RFC 4492. + * + * + * [8] + * + * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory. + * Springer Science & Business Media, 1 Aug 2000 + */ + +#ifndef MBEDTLS_ECP_INTERNAL_H +#define MBEDTLS_ECP_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + +/** + * \brief Indicate if the Elliptic Curve Point module extension can + * handle the group. + * + * \param grp The pointer to the elliptic curve group that will be the + * basis of the cryptographic computations. + * + * \return Non-zero if successful. + */ +unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp ); + +/** + * \brief Initialise the Elliptic Curve Point module extension. + * + * If mbedtls_internal_ecp_grp_capable returns true for a + * group, this function has to be able to initialise the + * module for it. + * + * This module can be a driver to a crypto hardware + * accelerator, for which this could be an initialise function. + * + * \param grp The pointer to the group the module needs to be + * initialised for. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ); + +/** + * \brief Frees and deallocates the Elliptic Curve Point module + * extension. + * + * \param grp The pointer to the group the module was initialised for. + */ +void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ); + +#if defined(ECP_SHORTWEIERSTRASS) + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) +/** + * \brief Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l. + * + * \param grp Pointer to the group representing the curve. + * + * \param pt The point on the curve to be randomised, given with Jacobian + * coordinates. + * + * \param f_rng A function pointer to the random number generator. + * + * \param p_rng A pointer to the random number generator state. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) +/** + * \brief Addition: R = P + Q, mixed affine-Jacobian coordinates. + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Special cases: (1) P or Q is zero, (2) R is zero, + * (3) P == Q. + * None of these cases can happen as intermediate step in + * ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base + * point, the factor being less than its order, so none of + * them is zero; + * - Q is an odd multiple of the base point, P an even + * multiple, due to the choice of precomputed points in the + * modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as + * meaning 1. + * + * Cost in field operations if done by [5] 3.22: + * 1A := 8M + 3S + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the first summand, given with Jacobian + * coordinates + * + * \param Q Pointer to the second summand, given with affine + * coordinates. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); +#endif + +/** + * \brief Point doubling R = 2 P, Jacobian coordinates. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + * when the implementation is based on the "dbl-1998-cmo-2" + * doubling formulas in [8] and standard optimizations are + * applied when curve parameter A is one of { 0, -3 }. + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the point that has to be doubled, given with + * Jacobian coordinates. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) +int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P ); +#endif + +/** + * \brief Normalize jacobian coordinates of an array of (pointers to) + * points. + * + * Using Montgomery's trick to perform only one inversion mod P + * the cost is: + * 1N(t) := 1I + (6t - 3)M + 1S + * (See for example Algorithm 10.3.4. in [9]) + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Warning: fails (returning an error) if one of the points is + * zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * \param grp Pointer to the group representing the curve. + * + * \param T Array of pointers to the points to normalise. + * + * \param t_len Number of elements in the array. + * + * \return 0 if successful, + * an error if one of the points is zero. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) +int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t t_len ); +#endif + +/** + * \brief Normalize jacobian coordinates so that Z == 0 || Z == 1. + * + * Cost in field operations if done by [5] 3.2.1: + * 1N := 1I + 3M + 1S + * + * \param grp Pointer to the group representing the curve. + * + * \param pt pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) +int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt ); +#endif + +#endif /* ECP_SHORTWEIERSTRASS */ + +#if defined(ECP_MONTGOMERY) + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) +int mbedtls_internal_ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d ); +#endif + +/** + * \brief Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * + * \param grp pointer to the group representing the curve + * + * \param P the point on the curve to be randomised given with + * projective coordinates. This is an input/output parameter. + * + * \param f_rng a function pointer to the random number generator + * + * \param p_rng a pointer to the random number generator state + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) +int mbedtls_internal_ecp_randomize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +/** + * \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1. + * + * \param grp pointer to the group representing the curve + * + * \param P pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) +int mbedtls_internal_ecp_normalize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P ); +#endif + +#endif /* ECP_MONTGOMERY */ + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#endif /* ecp_internal.h */ + diff --git a/external/mbedtls/include/mbedtls/entropy.h b/external/mbedtls/include/mbedtls/entropy.h new file mode 100644 index 0000000..1d6e9b8 --- /dev/null +++ b/external/mbedtls/include/mbedtls/entropy.h @@ -0,0 +1,316 @@ +/** + * \file entropy.h + * + * \brief Entropy accumulator implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_ENTROPY_H +#define MBEDTLS_ENTROPY_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +#include "sha512.h" +#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#else +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#include "sha256.h" +#endif +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +#if defined(MBEDTLS_HAVEGE_C) +#include "havege.h" +#endif + +#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ +#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */ +#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D /**< No strong sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -0x003F /**< Read/write error in file. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ENTROPY_MAX_SOURCES) +#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +#endif + +#if !defined(MBEDTLS_ENTROPY_MAX_GATHER) +#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +#endif + +/* \} name SECTION: Module settings */ + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) +#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ +#else +#define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ +#endif + +#define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ +#define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES + +#define MBEDTLS_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */ +#define MBEDTLS_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Entropy poll callback pointer + * + * \param data Callback-specific data pointer + * \param output Data to fill + * \param len Maximum size to provide + * \param olen The actual amount of bytes put into the buffer (Can be 0) + * + * \return 0 if no critical failures occurred, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise + */ +typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, + size_t *olen); + +/** + * \brief Entropy source state + */ +typedef struct mbedtls_entropy_source_state +{ + mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ + void * p_source; /**< The callback data pointer */ + size_t size; /**< Amount received in bytes */ + size_t threshold; /**< Minimum bytes required before release */ + int strong; /**< Is the source strong? */ +} +mbedtls_entropy_source_state; + +/** + * \brief Entropy context structure + */ +typedef struct mbedtls_entropy_context +{ + int accumulator_started; /* 0 after init. + * 1 after the first update. + * -1 after free. */ +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_context accumulator; +#else + mbedtls_sha256_context accumulator; +#endif + int source_count; /* Number of entries used in source. */ + mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_state havege_data; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + int initial_entropy_run; +#endif +} +mbedtls_entropy_context; + +/** + * \brief Initialize the context + * + * \param ctx Entropy context to initialize + */ +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ); + +/** + * \brief Free the data in the context + * + * \param ctx Entropy context to free + */ +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); + +/** + * \brief Adds an entropy source to poll + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param f_source Entropy function + * \param p_source Function data + * \param threshold Minimum required from source before entropy is released + * ( with mbedtls_entropy_func() ) (in bytes) + * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or + * MBEDTLS_ENTROPY_SOURCE_WEAK. + * At least one strong source needs to be added. + * Weaker sources (such as the cycle counter) can be used as + * a complement. + * + * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES + */ +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ); + +/** + * \brief Trigger an extra gather poll for the accumulator + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ); + +/** + * \brief Retrieve entropy from the accumulator + * (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE) + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data Entropy context + * \param output Buffer to fill + * \param len Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ); + +/** + * \brief Add data to the accumulator manually + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param data Data to add + * \param len Length of data + * + * \return 0 if successful + */ +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Trigger an update of the seed file in NV by using the + * current entropy pool. + * + * \param ctx Entropy context + * + * \return 0 if successful + */ +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ); +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are + * read from the seed file. The rest is ignored. + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * This module self-test also calls the entropy self-test, + * mbedtls_entropy_source_self_test(); + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_self_test( int verbose ); + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Checkup routine + * + * Verifies the integrity of the hardware entropy source + * provided by the function 'mbedtls_hardware_poll()'. + * + * Note this is the only hardware entropy source that is known + * at link time, and other entropy sources configured + * dynamically at runtime by the function + * mbedtls_entropy_add_source() will not be tested. + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_source_self_test( int verbose ); +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* entropy.h */ diff --git a/external/mbedtls/include/mbedtls/entropy_poll.h b/external/mbedtls/include/mbedtls/entropy_poll.h new file mode 100644 index 0000000..c348fe5 --- /dev/null +++ b/external/mbedtls/include/mbedtls/entropy_poll.h @@ -0,0 +1,135 @@ +/** + * \file entropy_poll.h + * + * \brief Platform-specific and custom entropy polling functions + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_ENTROPY_POLL_H +#define MBEDTLS_ENTROPY_POLL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default thresholds for built-in sources, in bytes + */ +#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ +#define MBEDTLS_ENTROPY_MIN_HAVEGE 32 /**< Minimum for HAVEGE */ +#define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */ +#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) +#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ +#endif + +/** + * \brief Entropy poll callback that provides 0 entropy. + */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) +/** + * \brief Platform-specific entropy poll callback + */ +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_HAVEGE_C) +/** + * \brief HAVEGE based entropy poll callback + * + * Requires an HAVEGE state as its data pointer. + */ +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_TIMING_C) +/** + * \brief mbedtls_timing_hardclock-based entropy poll callback + */ +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Entropy poll callback for a hardware source + * + * \warning This is not provided by mbed TLS! + * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in config.h. + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_hardware_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Entropy poll callback for a non-volatile seed file + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* entropy_poll.h */ diff --git a/external/mbedtls/include/mbedtls/error.h b/external/mbedtls/include/mbedtls/error.h new file mode 100644 index 0000000..fa8582a --- /dev/null +++ b/external/mbedtls/include/mbedtls/error.h @@ -0,0 +1,155 @@ +/** + * \file error.h + * + * \brief Error to string translation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_ERROR_H +#define MBEDTLS_ERROR_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/** + * Error code layout. + * + * Currently we try to keep all error codes within the negative space of 16 + * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In + * addition we'd like to give two layers of information on the error if + * possible. + * + * For that purpose the error codes are segmented in the following manner: + * + * 16 bit error code bit-segmentation + * + * 1 bit - Unused (sign bit) + * 3 bits - High level module ID + * 5 bits - Module-dependent error code + * 7 bits - Low level module errors + * + * For historical reasons, low-level error codes are divided in even and odd, + * even codes were assigned first, and -1 is reserved for other errors. + * + * Low-level module errors (0x0002-0x007E, 0x0003-0x007F) + * + * Module Nr Codes assigned + * MPI 7 0x0002-0x0010 + * GCM 3 0x0012-0x0014 0x0013-0x0013 + * BLOWFISH 3 0x0016-0x0018 0x0017-0x0017 + * THREADING 3 0x001A-0x001E + * AES 5 0x0020-0x0022 0x0021-0x0025 + * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 + * XTEA 2 0x0028-0x0028 0x0029-0x0029 + * BASE64 2 0x002A-0x002C + * OID 1 0x002E-0x002E 0x000B-0x000B + * PADLOCK 1 0x0030-0x0030 + * DES 2 0x0032-0x0032 0x0033-0x0033 + * CTR_DBRG 4 0x0034-0x003A + * ENTROPY 3 0x003C-0x0040 0x003D-0x003F + * NET 13 0x0042-0x0052 0x0043-0x0049 + * ARIA 4 0x0058-0x005E + * ASN1 7 0x0060-0x006C + * CMAC 1 0x007A-0x007A + * PBKDF2 1 0x007C-0x007C + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 3 0x000D-0x0011 + * ARC4 1 0x0019-0x0019 + * MD2 1 0x002B-0x002B + * MD4 1 0x002D-0x002D + * MD5 1 0x002F-0x002F + * RIPEMD160 1 0x0031-0x0031 + * SHA1 1 0x0035-0x0035 0x0073-0x0073 + * SHA256 1 0x0037-0x0037 0x0074-0x0074 + * SHA512 1 0x0039-0x0039 0x0075-0x0075 + * CHACHA20 3 0x0051-0x0055 + * POLY1305 3 0x0057-0x005B + * CHACHAPOLY 2 0x0054-0x0056 + * PLATFORM 1 0x0070-0x0072 + * + * High-level module nr (3 bits - 0x0...-0x7...) + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 20 + * PKCS5 2 4 (Started from top) + * DHM 3 11 + * PK 3 15 (Started from top) + * RSA 4 11 + * ECP 4 10 (Started from top) + * MD 5 5 + * HKDF 5 1 (Started from top) + * SSL 5 1 (Started from 0x5E80) + * CIPHER 6 8 + * SSL 6 23 (Started from top) + * SSL 7 32 + * + * Module dependent error code (5 bits 0x.00.-0x.F8.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Translate a mbed TLS error code into a string representation, + * Result is truncated if necessary and always includes a terminating + * null byte. + * + * \param errnum error code + * \param buffer buffer to place representation in + * \param buflen length of the buffer + */ +void mbedtls_strerror( int errnum, char *buffer, size_t buflen ); + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ diff --git a/external/mbedtls/include/mbedtls/gcm.h b/external/mbedtls/include/mbedtls/gcm.h new file mode 100644 index 0000000..1201fbd --- /dev/null +++ b/external/mbedtls/include/mbedtls/gcm.h @@ -0,0 +1,351 @@ +/** + * \file gcm.h + * + * \brief This file contains GCM definitions and functions. + * + * The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined + * in D. McGrew, J. Viega, The Galois/Counter Mode of Operation + * (GCM), Natl. Inst. Stand. Technol. + * + * For more information on GCM, see NIST SP 800-38D: Recommendation for + * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_GCM_H +#define MBEDTLS_GCM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "cipher.h" + +#include + +#define MBEDTLS_GCM_ENCRYPT 1 +#define MBEDTLS_GCM_DECRYPT 0 + +#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ + +/* MBEDTLS_ERR_GCM_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */ + +#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_GCM_ALT) + +/** + * \brief The GCM context structure. + */ +typedef struct mbedtls_gcm_context +{ + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ + uint64_t HL[16]; /*!< Precalculated HTable low. */ + uint64_t HH[16]; /*!< Precalculated HTable high. */ + uint64_t len; /*!< The total length of the encrypted data. */ + uint64_t add_len; /*!< The total length of the additional data. */ + unsigned char base_ectr[16]; /*!< The first ECTR for tag. */ + unsigned char y[16]; /*!< The Y working value. */ + unsigned char buf[16]; /*!< The buf working value. */ + int mode; /*!< The operation to perform: + #MBEDTLS_GCM_ENCRYPT or + #MBEDTLS_GCM_DECRYPT. */ +} +mbedtls_gcm_context; + +#else /* !MBEDTLS_GCM_ALT */ +#include "gcm_alt.h" +#endif /* !MBEDTLS_GCM_ALT */ + +/** + * \brief This function initializes the specified GCM context, + * to make references valid, and prepares the context + * for mbedtls_gcm_setkey() or mbedtls_gcm_free(). + * + * The function does not bind the GCM context to a particular + * cipher, nor set the key. For this purpose, use + * mbedtls_gcm_setkey(). + * + * \param ctx The GCM context to initialize. This must not be \c NULL. + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); + +/** + * \brief This function associates a GCM context with a + * cipher algorithm and a key. + * + * \param ctx The GCM context. This must be initialized. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. This must be a readable buffer of at + * least \p keybits bits. + * \param keybits The key size in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A cipher-specific error code on failure. + */ +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs GCM encryption or decryption of a buffer. + * + * \note For encryption, the output buffer can be the same as the + * input buffer. For decryption, the output buffer cannot be + * the same as input buffer. If the buffers overlap, the output + * buffer must trail at least 8 Bytes behind the input buffer. + * + * \warning When this function performs a decryption, it outputs the + * authentication tag and does not verify that the data is + * authentic. You should use this function to perform encryption + * only. For decryption, use mbedtls_gcm_auth_decrypt() instead. + * + * \param ctx The GCM context to use for encryption or decryption. This + * must be initialized. + * \param mode The operation to perform: + * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption. + * The ciphertext is written to \p output and the + * authentication tag is written to \p tag. + * - #MBEDTLS_GCM_DECRYPT to perform decryption. + * The plaintext is written to \p output and the + * authentication tag is written to \p tag. + * Note that this mode is not recommended, because it does + * not verify the authenticity of the data. For this reason, + * you should use mbedtls_gcm_auth_decrypt() instead of + * calling this function in decryption mode. + * \param length The length of the input data, which is equal to the length + * of the output data. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. This must be of at + * least that size in Bytes. + * \param add_len The length of the additional data. + * \param input The buffer holding the input data. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size in Bytes. + * \param output The buffer for holding the output data. If \p length is greater + * than zero, this must be a writable buffer of at least that + * size in Bytes. + * \param tag_len The length of the tag to generate. + * \param tag The buffer for holding the tag. This must be a writable + * buffer of at least \p tag_len Bytes. + * + * \return \c 0 if the encryption or decryption was performed + * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode, + * this does not indicate that the data is authentic. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are + * not valid or a cipher-specific error code if the encryption + * or decryption failed. + */ +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ); + +/** + * \brief This function performs a GCM authenticated decryption of a + * buffer. + * + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. + * + * \param ctx The GCM context. This must be initialized. + * \param length The length of the ciphertext to decrypt, which is also + * the length of the decrypted plaintext. + * \param iv The initialization vector. This must be a readable buffer + * of at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. This must be of at + * least that size in Bytes. + * \param add_len The length of the additional data. + * \param tag The buffer holding the tag to verify. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to verify. + * \param input The buffer holding the ciphertext. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size. + * \param output The buffer for holding the decrypted plaintext. If \p length + * is greater than zero, this must be a writable buffer of at + * least that size. + * + * \return \c 0 if successful and authenticated. + * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are + * not valid or a cipher-specific error code if the decryption + * failed. + */ +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function starts a GCM encryption or decryption + * operation. + * + * \param ctx The GCM context. This must be initialized. + * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or + * #MBEDTLS_GCM_DECRYPT. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data, or \c NULL + * if \p add_len is \c 0. + * \param add_len The length of the additional data. If \c 0, + * \p add may be \c NULL. + * + * \return \c 0 on success. + */ +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ); + +/** + * \brief This function feeds an input buffer into an ongoing GCM + * encryption or decryption operation. + * + * ` The function expects input to be a multiple of 16 + * Bytes. Only the last call before calling + * mbedtls_gcm_finish() can be less than 16 Bytes. + * + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. + * + * \param ctx The GCM context. This must be initialized. + * \param length The length of the input data. This must be a multiple of + * 16 except in the last call before mbedtls_gcm_finish(). + * \param input The buffer holding the input data. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size in Bytes. + * \param output The buffer for holding the output data. If \p length is + * greater than zero, this must be a writable buffer of at + * least that size in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + */ +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finishes the GCM operation and generates + * the authentication tag. + * + * It wraps up the GCM stream, and generates the + * tag. The tag can have a maximum length of 16 Bytes. + * + * \param ctx The GCM context. This must be initialized. + * \param tag The buffer for holding the tag. This must be a writable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to generate. This must be at least + * four. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + */ +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len ); + +/** + * \brief This function clears a GCM context and the underlying + * cipher sub-context. + * + * \param ctx The GCM context to clear. If this is \c NULL, the call has + * no effect. Otherwise, this must be initialized. + */ +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The GCM checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_gcm_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + + +#endif /* gcm.h */ diff --git a/external/mbedtls/include/mbedtls/havege.h b/external/mbedtls/include/mbedtls/havege.h new file mode 100644 index 0000000..e90839d --- /dev/null +++ b/external/mbedtls/include/mbedtls/havege.h @@ -0,0 +1,106 @@ +/** + * \file havege.h + * + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_HAVEGE_H +#define MBEDTLS_HAVEGE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#define MBEDTLS_HAVEGE_COLLECT_SIZE 1024 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief HAVEGE state structure + */ +typedef struct mbedtls_havege_state +{ + int PT1, PT2, offset[2]; + int pool[MBEDTLS_HAVEGE_COLLECT_SIZE]; + int WALK[8192]; +} +mbedtls_havege_state; + +/** + * \brief HAVEGE initialization + * + * \param hs HAVEGE state to be initialized + */ +void mbedtls_havege_init( mbedtls_havege_state *hs ); + +/** + * \brief Clear HAVEGE state + * + * \param hs HAVEGE state to be cleared + */ +void mbedtls_havege_free( mbedtls_havege_state *hs ); + +/** + * \brief HAVEGE rand function + * + * \param p_rng A HAVEGE state + * \param output Buffer to fill + * \param len Length of buffer + * + * \return 0 + */ +int mbedtls_havege_random( void *p_rng, unsigned char *output, size_t len ); + +#ifdef __cplusplus +} +#endif + +#endif /* havege.h */ diff --git a/external/mbedtls/include/mbedtls/hkdf.h b/external/mbedtls/include/mbedtls/hkdf.h new file mode 100644 index 0000000..07ffe83 --- /dev/null +++ b/external/mbedtls/include/mbedtls/hkdf.h @@ -0,0 +1,166 @@ +/** + * \file hkdf.h + * + * \brief This file contains the HKDF interface. + * + * The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is + * specified by RFC 5869. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_HKDF_H +#define MBEDTLS_HKDF_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" + +/** + * \name HKDF Error codes + * \{ + */ +#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This is the HMAC-based Extract-and-Expand Key Derivation Function + * (HKDF). + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros of + * md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ); + +/** + * \brief Take the input keying material \p ikm and extract from it a + * fixed-length pseudorandom key \p prk. + * + * \warning This function should only be used if the security of it has been + * studied and established in that particular context (eg. TLS 1.3 + * key schedule). For standard HKDF security guarantees use + * \c mbedtls_hkdf instead. + * + * \param md A hash function; md.size denotes the length of the + * hash function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros + * of md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param[out] prk A pseudorandom key of at least md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ); + +/** + * \brief Expand the supplied \p prk into several additional pseudorandom + * keys, which is the output of the HKDF. + * + * \warning This function should only be used if the security of it has been + * studied and established in that particular context (eg. TLS 1.3 + * key schedule). For standard HKDF security guarantees use + * \c mbedtls_hkdf instead. + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param prk A pseudorandom key of at least md.size bytes. \p prk is + * usually the output from the HKDF extract step. + * \param prk_len The length in bytes of \p prk. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* hkdf.h */ diff --git a/external/mbedtls/include/mbedtls/hmac_drbg.h b/external/mbedtls/include/mbedtls/hmac_drbg.h new file mode 100644 index 0000000..5718e18 --- /dev/null +++ b/external/mbedtls/include/mbedtls/hmac_drbg.h @@ -0,0 +1,497 @@ +/** + * \file hmac_drbg.h + * + * \brief The HMAC_DRBG pseudorandom generator. + * + * This module implements the HMAC_DRBG pseudorandom generator described + * in NIST SP 800-90A: Recommendation for Random Number Generation Using + * Deterministic Random Bit Generators. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_HMAC_DRBG_H +#define MBEDTLS_HMAC_DRBG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +/* + * Error codes + */ +#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */ +#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */ +#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */ +#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /**< The entropy source failed. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) +#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST) +#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * HMAC_DRBG context. + */ +typedef struct mbedtls_hmac_drbg_context +{ + /* Working state: the key K is not stored explicitly, + * but is implied by the HMAC context */ + mbedtls_md_context_t md_ctx; /*!< HMAC context (inc. K) */ + unsigned char V[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ + int reseed_counter; /*!< reseed counter */ + + /* Administrative state */ + size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */ + int prediction_resistance; /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + int reseed_interval; /*!< reseed interval */ + + /* Callbacks */ + int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */ + void *p_entropy; /*!< context for the entropy function */ + +#if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized if and only if + * md_ctx->md_info != NULL. This means that the mutex is initialized + * during the initial seeding in mbedtls_hmac_drbg_seed() or + * mbedtls_hmac_drbg_seed_buf() and freed in mbedtls_ctr_drbg_free(). + * + * Note that this invariant may change without notice. Do not rely on it + * and do not access the mutex directly in application code. + */ + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_hmac_drbg_context; + +/** + * \brief HMAC_DRBG context initialization. + * + * This function makes the context ready for mbedtls_hmac_drbg_seed(), + * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free(). + * + * \note The reseed interval is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL + * by default. Override this value by calling + * mbedtls_hmac_drbg_set_reseed_interval(). + * + * \param ctx HMAC_DRBG context to be initialized. + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); + +/** + * \brief HMAC_DRBG initial seeding. + * + * Set the initial seed and set up the entropy source for future reseeds. + * + * A typical choice for the \p f_entropy and \p p_entropy parameters is + * to use the entropy module: + * - \p f_entropy is mbedtls_entropy_func(); + * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized + * with mbedtls_entropy_init() (which registers the platform's default + * entropy sources). + * + * You can provide a personalization string in addition to the + * entropy source, to make this instantiation as unique as possible. + * + * \note By default, the security strength as defined by NIST is: + * - 128 bits if \p md_info is SHA-1; + * - 192 bits if \p md_info is SHA-224; + * - 256 bits if \p md_info is SHA-256, SHA-384 or SHA-512. + * Note that SHA-256 is just as efficient as SHA-224. + * The security strength can be reduced if a smaller + * entropy length is set with + * mbedtls_hmac_drbg_set_entropy_len(). + * + * \note The default entropy length is the security strength + * (converted from bits to bytes). You can override + * it by calling mbedtls_hmac_drbg_set_entropy_len(). + * + * \note During the initial seeding, this function calls + * the entropy source to obtain a nonce + * whose length is half the entropy length. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_hmac_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param ctx HMAC_DRBG context to be seeded. + * \param md_info MD algorithm to use for HMAC_DRBG. + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + * length of the buffer. + * \p f_entropy is always called with a length that is + * less than or equal to the entropy length. + * \param p_entropy The entropy context to pass to \p f_entropy. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT + * and also at most + * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len * 3 / 2 + * where \p entropy_len is the entropy length + * described above. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is + * invalid. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough + * memory to allocate context data. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if the call to \p f_entropy failed. + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief Initilisation of simpified HMAC_DRBG (never reseeds). + * + * This function is meant for use in algorithms that need a pseudorandom + * input such as deterministic ECDSA. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_hmac_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param ctx HMAC_DRBG context to be initialised. + * \param md_info MD algorithm to use for HMAC_DRBG. + * \param data Concatenation of the initial entropy string and + * the additional data. + * \param data_len Length of \p data in bytes. + * + * \return \c 0 if successful. or + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is + * invalid. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough + * memory to allocate context data. + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ); + +/** + * \brief This function turns prediction resistance on or off. + * The default value is off. + * + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_hmac_drbg_random_with_add() + * or mbedtls_hmac_drbg_random(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The HMAC_DRBG context. + * \param resistance #MBEDTLS_HMAC_DRBG_PR_ON or #MBEDTLS_HMAC_DRBG_PR_OFF. + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ); + +/** + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. + * + * See the documentation of mbedtls_hmac_drbg_seed() for the default value. + * + * \param ctx The HMAC_DRBG context. + * \param len The amount of entropy to grab, in bytes. + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, + size_t len ); + +/** + * \brief Set the reseed interval. + * + * The reseed interval is the number of calls to mbedtls_hmac_drbg_random() + * or mbedtls_hmac_drbg_random_with_add() after which the entropy function + * is called again. + * + * The default value is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL. + * + * \param ctx The HMAC_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, + int interval ); + +/** + * \brief This function updates the state of the HMAC_DRBG context. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The HMAC_DRBG context. + * \param additional The data to update the state with. + * If this is \c NULL, there is no additional data. + * \param add_len Length of \p additional in bytes. + * Unused if \p additional is \c NULL. + * + * \return \c 0 on success, or an error from the underlying + * hash calculation. + */ +int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function reseeds the HMAC_DRBG context, that is + * extracts data from the entropy source. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The HMAC_DRBG context. + * \param additional Additional data to add to the state. + * If this is \c NULL, there is no additional data + * and \p len should be \c 0. + * \param len The length of the additional data. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT + * and also at most + * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len + * where \p entropy_len is the entropy length + * (see mbedtls_hmac_drbg_set_entropy_len()). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy function failed. + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates an HMAC_DRBG instance with additional + * data and uses it to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param p_rng The HMAC_DRBG context. This must be a pointer to a + * #mbedtls_hmac_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \param additional Additional data to update with. + * If this is \c NULL, there is no additional data + * and \p add_len should be \c 0. + * \param add_len The length of the additional data. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy source failed. + * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if + * \p output_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if + * \p add_len > #MBEDTLS_HMAC_DRBG_MAX_INPUT. + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief This function uses HMAC_DRBG to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param p_rng The HMAC_DRBG context. This must be a pointer to a + * #mbedtls_hmac_drbg_context structure. + * \param output The buffer to fill. + * \param out_len The length of the buffer in bytes. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy source failed. + * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if + * \p out_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); + +/** + * \brief This function resets HMAC_DRBG context to the state immediately + * after initial call of mbedtls_hmac_drbg_init(). + * + * \param ctx The HMAC_DRBG context to free. + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function updates the state of the HMAC_DRBG context. + * + * \deprecated Superseded by mbedtls_hmac_drbg_update_ret() + * in 2.16.0. + * + * \param ctx The HMAC_DRBG context. + * \param additional The data to update the state with. + * If this is \c NULL, there is no additional data. + * \param add_len Length of \p additional in bytes. + * Unused if \p additional is \c NULL. + */ +MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update( + mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The HMAC_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on reseed + * failure. + */ +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); + +/** + * \brief This function reads and updates a seed file. The seed + * is added to this instance. + * + * \param ctx The HMAC_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on + * reseed failure. + * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if the existing + * seed file is too large. + */ +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The HMAC_DRBG Checkup routine. + * + * \return \c 0 if successful. + * \return \c 1 if the test failed. + */ +int mbedtls_hmac_drbg_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* hmac_drbg.h */ diff --git a/external/mbedtls/include/mbedtls/md.h b/external/mbedtls/include/mbedtls/md.h new file mode 100644 index 0000000..2ba8d9e --- /dev/null +++ b/external/mbedtls/include/mbedtls/md.h @@ -0,0 +1,495 @@ + /** + * \file md.h + * + * \brief This file contains the generic message-digest wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_MD_H +#define MBEDTLS_MD_H + +#include + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ + +/* MBEDTLS_ERR_MD_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Supported message digests. + * + * \warning MD2, MD4, MD5 and SHA-1 are considered weak message digests and + * their use constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef enum { + MBEDTLS_MD_NONE=0, /**< None. */ + MBEDTLS_MD_MD2, /**< The MD2 message digest. */ + MBEDTLS_MD_MD4, /**< The MD4 message digest. */ + MBEDTLS_MD_MD5, /**< The MD5 message digest. */ + MBEDTLS_MD_SHA1, /**< The SHA-1 message digest. */ + MBEDTLS_MD_SHA224, /**< The SHA-224 message digest. */ + MBEDTLS_MD_SHA256, /**< The SHA-256 message digest. */ + MBEDTLS_MD_SHA384, /**< The SHA-384 message digest. */ + MBEDTLS_MD_SHA512, /**< The SHA-512 message digest. */ + MBEDTLS_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */ +} mbedtls_md_type_t; + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#else +#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ +#endif + +/** + * Opaque struct defined in md_internal.h. + */ +typedef struct mbedtls_md_info_t mbedtls_md_info_t; + +/** + * The generic message-digest context. + */ +typedef struct mbedtls_md_context_t +{ + /** Information about the associated message digest. */ + const mbedtls_md_info_t *md_info; + + /** The digest-specific context. */ + void *md_ctx; + + /** The HMAC part of the context. */ + void *hmac_ctx; +} mbedtls_md_context_t; + +/** + * \brief This function returns the list of digests supported by the + * generic digest module. + * + * \note The list starts with the strongest available hashes. + * + * \return A statically allocated array of digests. Each element + * in the returned list is an integer belonging to the + * message-digest enumeration #mbedtls_md_type_t. + * The last entry is 0. + */ +const int *mbedtls_md_list( void ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest name. + * + * \param md_name The name of the digest to search for. + * + * \return The message-digest information associated with \p md_name. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest type. + * + * \param md_type The type of digest to search for. + * + * \return The message-digest information associated with \p md_type. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); + +/** + * \brief This function initializes a message-digest context without + * binding it to a particular message-digest algorithm. + * + * This function should always be called first. It prepares the + * context for mbedtls_md_setup() for binding it to a + * message-digest algorithm. + */ +void mbedtls_md_init( mbedtls_md_context_t *ctx ); + +/** + * \brief This function clears the internal structure of \p ctx and + * frees any embedded internal structure, but does not free + * \p ctx itself. + * + * If you have called mbedtls_md_setup() on \p ctx, you must + * call mbedtls_md_free() when you are no longer using the + * context. + * Calling this function if you have previously + * called mbedtls_md_init() and nothing else is optional. + * You must not call this function if you have not called + * mbedtls_md_init(). + */ +void mbedtls_md_free( mbedtls_md_context_t *ctx ); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or mbedtls_md_free(). + * Makes it necessary to call mbedtls_md_free() later. + * + * \deprecated Superseded by mbedtls_md_setup() in 2.0.0 + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or + * mbedtls_md_free(). Makes it necessary to call + * mbedtls_md_free() later. + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param hmac Defines if HMAC is used. 0: HMAC is not used (saves some memory), + * or non-zero: HMAC is used with this context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); + +/** + * \brief This function clones the state of an message-digest + * context. + * + * \note You must call mbedtls_md_setup() on \c dst before calling + * this function. + * + * \note The two contexts must have the same type, + * for example, both are SHA-256. + * + * \warning This function clones the message-digest state, not the + * HMAC state. + * + * \param dst The destination context. + * \param src The context to be cloned. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure. + */ +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ); + +/** + * \brief This function extracts the message-digest size from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The size of the message-digest output in Bytes. + */ +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest type from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The type of the message digest. + */ +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest name from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The name of the message digest. + */ +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function starts a message-digest computation. + * + * You must call this function after setting up the context + * with mbedtls_md_setup(), and before passing data with + * mbedtls_md_update(). + * + * \param ctx The generic message-digest context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_starts( mbedtls_md_context_t *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing + * message-digest computation. + * + * You must call mbedtls_md_starts() before calling this + * function. You may call this function multiple times. + * Afterwards, call mbedtls_md_finish(). + * + * \param ctx The generic message-digest context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes the digest operation, + * and writes the result to the output buffer. + * + * Call this function after a call to mbedtls_md_starts(), + * followed by any number of calls to mbedtls_md_update(). + * Afterwards, you may either clear the context with + * mbedtls_md_free(), or call mbedtls_md_starts() to reuse + * the context for another digest operation with the same + * algorithm. + * + * \param ctx The generic message-digest context. + * \param output The buffer for the generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); + +/** + * \brief This function calculates the message-digest of a buffer, + * with respect to a configurable message-digest algorithm + * in a single call. + * + * The result is calculated as + * Output = message_digest(input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function calculates the message-digest checksum + * result of the contents of the provided file. + * + * The result is calculated as + * Output = message_digest(file contents). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param path The input file name. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_FILE_IO_ERROR on an I/O error accessing + * the file pointed by \p path. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. + */ +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, + unsigned char *output ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief This function sets the HMAC key and prepares to + * authenticate a new message. + * + * Call this function after mbedtls_md_setup(), to use + * the MD context for an HMAC calculation, then call + * mbedtls_md_hmac_update() to provide the input data, and + * mbedtls_md_hmac_finish() to get the HMAC value. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC key in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief This function feeds an input buffer into an ongoing HMAC + * computation. + * + * Call mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() + * before calling this function. + * You may call this function multiple times to pass the + * input piecewise. + * Afterwards, call mbedtls_md_hmac_finish(). + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the HMAC operation, and writes + * the result to the output buffer. + * + * Call this function after mbedtls_md_hmac_starts() and + * mbedtls_md_hmac_update() to get the HMAC value. Afterwards + * you may either call mbedtls_md_free() to clear the context, + * or call mbedtls_md_hmac_reset() to reuse the context with + * the same HMAC key. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param output The generic HMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); + +/** + * \brief This function prepares to authenticate a new message with + * the same key as the previous HMAC operation. + * + * You may call this function after mbedtls_md_hmac_finish(). + * Afterwards call mbedtls_md_hmac_update() to pass the new + * input. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); + +/** + * \brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The HMAC result is calculated as + * output = generic HMAC(hmac key, input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC secret key in Bytes. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The generic HMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +/* Internal use */ +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_H */ diff --git a/external/mbedtls/include/mbedtls/md2.h b/external/mbedtls/include/mbedtls/md2.h new file mode 100644 index 0000000..9607df6 --- /dev/null +++ b/external/mbedtls/include/mbedtls/md2.h @@ -0,0 +1,331 @@ +/** + * \file md2.h + * + * \brief MD2 message digest algorithm (hash function) + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * + */ +#ifndef MBEDTLS_MD2_H +#define MBEDTLS_MD2_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/* MBEDTLS_ERR_MD2_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B /**< MD2 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD2_ALT) +// Regular implementation +// + +/** + * \brief MD2 context structure + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md2_context +{ + unsigned char cksum[16]; /*!< checksum of the data block */ + unsigned char state[48]; /*!< intermediate digest state */ + unsigned char buffer[16]; /*!< data block being processed */ + size_t left; /*!< amount of data in buffer */ +} +mbedtls_md2_context; + +#else /* MBEDTLS_MD2_ALT */ +#include "md2_alt.h" +#endif /* MBEDTLS_MD2_ALT */ + +/** + * \brief Initialize MD2 context + * + * \param ctx MD2 context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_init( mbedtls_md2_context *ctx ); + +/** + * \brief Clear MD2 context + * + * \param ctx MD2 context to be cleared + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_free( mbedtls_md2_context *ctx ); + +/** + * \brief Clone (the state of) an MD2 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_clone( mbedtls_md2_context *dst, + const mbedtls_md2_context *src ); + +/** + * \brief MD2 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 final digest + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \param ctx MD2 context + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md2_process( mbedtls_md2_context *ctx ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD2 context setup + * + * \deprecated Superseded by mbedtls_md2_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_starts( mbedtls_md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \deprecated Superseded by mbedtls_md2_update_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_update( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 final digest + * + * \deprecated Superseded by mbedtls_md2_finish_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_finish( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md2_process() in 2.7.0 + * + * \param ctx MD2 context + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_process( mbedtls_md2_context *ctx ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = MD2( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD2( input buffer ) + * + * \deprecated Superseded by mbedtls_md2_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md2.h */ diff --git a/external/mbedtls/include/mbedtls/md4.h b/external/mbedtls/include/mbedtls/md4.h new file mode 100644 index 0000000..6ceaf7a --- /dev/null +++ b/external/mbedtls/include/mbedtls/md4.h @@ -0,0 +1,336 @@ +/** + * \file md4.h + * + * \brief MD4 message digest algorithm (hash function) + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * + */ +#ifndef MBEDTLS_MD4_H +#define MBEDTLS_MD4_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_MD4_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D /**< MD4 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD4_ALT) +// Regular implementation +// + +/** + * \brief MD4 context structure + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md4_context +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md4_context; + +#else /* MBEDTLS_MD4_ALT */ +#include "md4_alt.h" +#endif /* MBEDTLS_MD4_ALT */ + +/** + * \brief Initialize MD4 context + * + * \param ctx MD4 context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_init( mbedtls_md4_context *ctx ); + +/** + * \brief Clear MD4 context + * + * \param ctx MD4 context to be cleared + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_free( mbedtls_md4_context *ctx ); + +/** + * \brief Clone (the state of) an MD4 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_clone( mbedtls_md4_context *dst, + const mbedtls_md4_context *src ); + +/** + * \brief MD4 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + */ +int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 final digest + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD4 context setup + * + * \deprecated Superseded by mbedtls_md4_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_starts( mbedtls_md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \deprecated Superseded by mbedtls_md4_update_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_update( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 final digest + * + * \deprecated Superseded by mbedtls_md4_finish_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_finish( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md4_process() in 2.7.0 + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = MD4( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD4( input buffer ) + * + * \deprecated Superseded by mbedtls_md4_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md4.h */ diff --git a/external/mbedtls/include/mbedtls/md5.h b/external/mbedtls/include/mbedtls/md5.h new file mode 100644 index 0000000..b9d0ca9 --- /dev/null +++ b/external/mbedtls/include/mbedtls/md5.h @@ -0,0 +1,336 @@ +/** + * \file md5.h + * + * \brief MD5 message digest algorithm (hash function) + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_MD5_H +#define MBEDTLS_MD5_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD5_ALT) +// Regular implementation +// + +/** + * \brief MD5 context structure + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md5_context +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md5_context; + +#else /* MBEDTLS_MD5_ALT */ +#include "md5_alt.h" +#endif /* MBEDTLS_MD5_ALT */ + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_init( mbedtls_md5_context *ctx ); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_free( mbedtls_md5_context *ctx ); + +/** + * \brief Clone (the state of) an MD5 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD5 context setup + * + * \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_starts( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0 + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD5( input buffer ) + * + * \deprecated Superseded by mbedtls_md5_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md5.h */ diff --git a/external/mbedtls/include/mbedtls/md_internal.h b/external/mbedtls/include/mbedtls/md_internal.h new file mode 100644 index 0000000..847f50a --- /dev/null +++ b/external/mbedtls/include/mbedtls/md_internal.h @@ -0,0 +1,140 @@ +/** + * \file md_internal.h + * + * \brief Message digest wrappers. + * + * \warning This in an internal header. Do not include directly. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_MD_WRAP_H +#define MBEDTLS_MD_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Message digest information. + * Allows message digest functions to be called in a generic way. + */ +struct mbedtls_md_info_t +{ + /** Digest identifier */ + mbedtls_md_type_t type; + + /** Name of the message digest */ + const char * name; + + /** Output length of the digest function in bytes */ + int size; + + /** Block length of the digest function in bytes */ + int block_size; + + /** Digest initialisation function */ + int (*starts_func)( void *ctx ); + + /** Digest update function */ + int (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); + + /** Digest finalisation function */ + int (*finish_func)( void *ctx, unsigned char *output ); + + /** Generic digest function */ + int (*digest_func)( const unsigned char *input, size_t ilen, + unsigned char *output ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Clone state from a context */ + void (*clone_func)( void *dst, const void *src ); + + /** Internal use only */ + int (*process_func)( void *ctx, const unsigned char *input ); +}; + +#if defined(MBEDTLS_MD2_C) +extern const mbedtls_md_info_t mbedtls_md2_info; +#endif +#if defined(MBEDTLS_MD4_C) +extern const mbedtls_md_info_t mbedtls_md4_info; +#endif +#if defined(MBEDTLS_MD5_C) +extern const mbedtls_md_info_t mbedtls_md5_info; +#endif +#if defined(MBEDTLS_RIPEMD160_C) +extern const mbedtls_md_info_t mbedtls_ripemd160_info; +#endif +#if defined(MBEDTLS_SHA1_C) +extern const mbedtls_md_info_t mbedtls_sha1_info; +#endif +#if defined(MBEDTLS_SHA256_C) +extern const mbedtls_md_info_t mbedtls_sha224_info; +extern const mbedtls_md_info_t mbedtls_sha256_info; +#endif +#if defined(MBEDTLS_SHA512_C) +extern const mbedtls_md_info_t mbedtls_sha384_info; +extern const mbedtls_md_info_t mbedtls_sha512_info; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_WRAP_H */ diff --git a/external/mbedtls/include/mbedtls/memory_buffer_alloc.h b/external/mbedtls/include/mbedtls/memory_buffer_alloc.h new file mode 100644 index 0000000..89c0617 --- /dev/null +++ b/external/mbedtls/include/mbedtls/memory_buffer_alloc.h @@ -0,0 +1,176 @@ +/** + * \file memory_buffer_alloc.h + * + * \brief Buffer-based memory allocator + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H +#define MBEDTLS_MEMORY_BUFFER_ALLOC_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE) +#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_MEMORY_VERIFY_NONE 0 +#define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0) +#define MBEDTLS_MEMORY_VERIFY_FREE (1 << 1) +#define MBEDTLS_MEMORY_VERIFY_ALWAYS (MBEDTLS_MEMORY_VERIFY_ALLOC | MBEDTLS_MEMORY_VERIFY_FREE) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize use of stack-based memory allocator. + * The stack-based allocator does memory management inside the + * presented buffer and does not call calloc() and free(). + * It sets the global mbedtls_calloc() and mbedtls_free() pointers + * to its own functions. + * (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if + * MBEDTLS_THREADING_C is defined) + * + * \note This code is not optimized and provides a straight-forward + * implementation of a stack-based memory allocator. + * + * \param buf buffer to use as heap + * \param len size of the buffer + */ +void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ); + +/** + * \brief Free the mutex for thread-safety and clear remaining memory + */ +void mbedtls_memory_buffer_alloc_free( void ); + +/** + * \brief Determine when the allocator should automatically verify the state + * of the entire chain of headers / meta-data. + * (Default: MBEDTLS_MEMORY_VERIFY_NONE) + * + * \param verify One of MBEDTLS_MEMORY_VERIFY_NONE, MBEDTLS_MEMORY_VERIFY_ALLOC, + * MBEDTLS_MEMORY_VERIFY_FREE or MBEDTLS_MEMORY_VERIFY_ALWAYS + */ +void mbedtls_memory_buffer_set_verify( int verify ); + +#if defined(MBEDTLS_MEMORY_DEBUG) +/** + * \brief Print out the status of the allocated memory (primarily for use + * after a program should have de-allocated all memory) + * Prints out a list of 'still allocated' blocks and their stack + * trace if MBEDTLS_MEMORY_BACKTRACE is defined. + */ +void mbedtls_memory_buffer_alloc_status( void ); + +/** + * \brief Get the peak heap usage so far + * + * \param max_used Peak number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param max_blocks Peak number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ); + +/** + * \brief Reset peak statistics + */ +void mbedtls_memory_buffer_alloc_max_reset( void ); + +/** + * \brief Get the current heap usage + * + * \param cur_used Current number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param cur_blocks Current number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ); +#endif /* MBEDTLS_MEMORY_DEBUG */ + +/** + * \brief Verifies that all headers in the memory buffer are correct + * and contain sane values. Helps debug buffer-overflow errors. + * + * Prints out first failure if MBEDTLS_MEMORY_DEBUG is defined. + * Prints out full header information if MBEDTLS_MEMORY_DEBUG + * is defined. (Includes stack trace information for each block if + * MBEDTLS_MEMORY_BACKTRACE is defined as well). + * + * \return 0 if verified, 1 otherwise + */ +int mbedtls_memory_buffer_alloc_verify( void ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_memory_buffer_alloc_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* memory_buffer_alloc.h */ diff --git a/external/mbedtls/include/mbedtls/net.h b/external/mbedtls/include/mbedtls/net.h new file mode 100644 index 0000000..6c7a49d --- /dev/null +++ b/external/mbedtls/include/mbedtls/net.h @@ -0,0 +1,62 @@ +/** + * \file net.h + * + * \brief Deprecated header file that includes net_sockets.h + * + * \deprecated Superseded by mbedtls/net_sockets.h + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#include "net_sockets.h" +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ diff --git a/external/mbedtls/include/mbedtls/net_sockets.h b/external/mbedtls/include/mbedtls/net_sockets.h new file mode 100644 index 0000000..c6e1a02 --- /dev/null +++ b/external/mbedtls/include/mbedtls/net_sockets.h @@ -0,0 +1,308 @@ +/** + * \file net_sockets.h + * + * \brief Network sockets abstraction layer to integrate Mbed TLS into a + * BSD-style sockets API. + * + * The network sockets module provides an example integration of the + * Mbed TLS library into a BSD sockets implementation. The module is + * intended to be an example of how Mbed TLS can be integrated into a + * networking stack, as well as to be Mbed TLS's network integration + * for its supported platforms. + * + * The module is intended only to be used with the Mbed TLS library and + * is not intended to be used by third party application software + * directly. + * + * The supported platforms are as follows: + * * Microsoft Windows and Windows CE + * * POSIX/Unix platforms including Linux, OS X + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_NET_SOCKETS_H +#define MBEDTLS_NET_SOCKETS_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" + +#include +#include + +#define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ +#define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ +#define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ +#define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */ +#define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */ +#define MBEDTLS_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */ +#define MBEDTLS_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */ +#define MBEDTLS_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ +#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */ +#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */ +#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */ +#define MBEDTLS_ERR_NET_POLL_FAILED -0x0047 /**< Polling the net context failed. */ +#define MBEDTLS_ERR_NET_BAD_INPUT_DATA -0x0049 /**< Input invalid. */ + +#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ + +#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ +#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ + +#define MBEDTLS_NET_POLL_READ 1 /**< Used in \c mbedtls_net_poll to check for pending data */ +#define MBEDTLS_NET_POLL_WRITE 2 /**< Used in \c mbedtls_net_poll to check if write possible */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Wrapper type for sockets. + * + * Currently backed by just a file descriptor, but might be more in the future + * (eg two file descriptors for combined IPv4 + IPv6 support, or additional + * structures for hand-made UDP demultiplexing). + */ +typedef struct mbedtls_net_context +{ + int fd; /**< The underlying file descriptor */ +} +mbedtls_net_context; + +/** + * \brief Initialize a context + * Just makes the context ready to be used or freed safely. + * + * \param ctx Context to initialize + */ +void mbedtls_net_init( mbedtls_net_context *ctx ); + +/** + * \brief Initiate a connection with host:port in the given protocol + * + * \param ctx Socket to use + * \param host Host to connect to + * \param port Port to connect to + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_UNKNOWN_HOST, + * MBEDTLS_ERR_NET_CONNECT_FAILED + * + * \note Sets the socket in connected mode even with UDP. + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ); + +/** + * \brief Create a receiving socket on bind_ip:port in the chosen + * protocol. If bind_ip == NULL, all interfaces are bound. + * + * \param ctx Socket to use + * \param bind_ip IP to bind to, can be NULL + * \param port Port number to use + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_UNKNOWN_HOST, + * MBEDTLS_ERR_NET_BIND_FAILED, + * MBEDTLS_ERR_NET_LISTEN_FAILED + * + * \note Regardless of the protocol, opens the sockets and binds it. + * In addition, make the socket listening if protocol is TCP. + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ); + +/** + * \brief Accept a connection from a remote client + * + * \param bind_ctx Relevant socket + * \param client_ctx Will contain the connected client socket + * \param client_ip Will contain the client IP address, can be NULL + * \param buf_size Size of the client_ip buffer + * \param ip_len Will receive the size of the client IP written, + * can be NULL if client_ip is null + * + * \return 0 if successful, or + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_BIND_FAILED, + * MBEDTLS_ERR_NET_ACCEPT_FAILED, or + * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, + * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to + * non-blocking and accept() would block. + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ); + +/** + * \brief Check and wait for the context to be ready for read/write + * + * \note The current implementation of this function uses + * select() and returns an error if the file descriptor + * is \c FD_SETSIZE or greater. + * + * \param ctx Socket to check + * \param rw Bitflag composed of MBEDTLS_NET_POLL_READ and + * MBEDTLS_NET_POLL_WRITE specifying the events + * to wait for: + * - If MBEDTLS_NET_POLL_READ is set, the function + * will return as soon as the net context is available + * for reading. + * - If MBEDTLS_NET_POLL_WRITE is set, the function + * will return as soon as the net context is available + * for writing. + * \param timeout Maximal amount of time to wait before returning, + * in milliseconds. If \c timeout is zero, the + * function returns immediately. If \c timeout is + * -1u, the function blocks potentially indefinitely. + * + * \return Bitmask composed of MBEDTLS_NET_POLL_READ/WRITE + * on success or timeout, or a negative return code otherwise. + */ +int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ); + +/** + * \brief Set the socket blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ); + +/** + * \brief Set the socket non-blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ); + +/** + * \brief Portable usleep helper + * + * \param usec Amount of microseconds to sleep + * + * \note Real amount of time slept will not be less than + * select()'s timeout granularity (typically, 10ms). + */ +void mbedtls_net_usleep( unsigned long usec ); + +/** + * \brief Read at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * + * \return the number of bytes received, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_READ indicates read() would block. + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ); + +/** + * \brief Write at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to read from + * \param len The length of the buffer + * + * \return the number of bytes sent, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block. + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); + +/** + * \brief Read at most 'len' characters, blocking for at most + * 'timeout' seconds. If no error occurs, the actual amount + * read is returned. + * + * \note The current implementation of this function uses + * select() and returns an error if the file descriptor + * is \c FD_SETSIZE or greater. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * \param timeout Maximum number of milliseconds to wait for data + * 0 means no timeout (wait forever) + * + * \return The number of bytes received if successful. + * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out. + * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * Another negative error code (MBEDTLS_ERR_NET_xxx) + * for other failures. + * + * \note This function will block (until data becomes available or + * timeout is reached) even if the socket is set to + * non-blocking. Handling timeouts with non-blocking reads + * requires a different strategy. + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, + uint32_t timeout ); + +/** + * \brief Gracefully shutdown the connection and free associated data + * + * \param ctx The context to free + */ +void mbedtls_net_free( mbedtls_net_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* net_sockets.h */ diff --git a/external/mbedtls/include/mbedtls/nist_kw.h b/external/mbedtls/include/mbedtls/nist_kw.h new file mode 100644 index 0000000..9435656 --- /dev/null +++ b/external/mbedtls/include/mbedtls/nist_kw.h @@ -0,0 +1,209 @@ +/** + * \file nist_kw.h + * + * \brief This file provides an API for key wrapping (KW) and key wrapping with + * padding (KWP) as defined in NIST SP 800-38F. + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * + * Key wrapping specifies a deterministic authenticated-encryption mode + * of operation, according to NIST SP 800-38F: Recommendation for + * Block Cipher Modes of Operation: Methods for Key Wrapping. Its + * purpose is to protect cryptographic keys. + * + * Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP. + * https://tools.ietf.org/html/rfc3394 + * https://tools.ietf.org/html/rfc5649 + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_NIST_KW_H +#define MBEDTLS_NIST_KW_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_KW_MODE_KW = 0, + MBEDTLS_KW_MODE_KWP = 1 +} mbedtls_nist_kw_mode_t; + +#if !defined(MBEDTLS_NIST_KW_ALT) +// Regular implementation +// + +/** + * \brief The key wrapping context-type definition. The key wrapping context is passed + * to the APIs called. + * + * \note The definition of this type may change in future library versions. + * Don't make any assumptions on this context! + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ +} mbedtls_nist_kw_context; + +#else /* MBEDTLS_NIST_key wrapping_ALT */ +#include "nist_kw_alt.h" +#endif /* MBEDTLS_NIST_KW_ALT */ + +/** + * \brief This function initializes the specified key wrapping context + * to make references valid and prepare the context + * for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free(). + * + * \param ctx The key wrapping context to initialize. + * + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function initializes the key wrapping context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The key wrapping context. + * \param cipher The 128-bit block cipher to use. Only AES is supported. + * \param key The Key Encryption Key (KEK). + * \param keybits The KEK size in bits. This must be acceptable by the cipher. + * \param is_wrap Specify whether the operation within the context is wrapping or unwrapping + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input. + * \return \c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers + * which are not supported. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ); + +/** + * \brief This function releases and clears the specified key wrapping context + * and underlying cipher sub-context. + * + * \param ctx The key wrapping context to clear. + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function encrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for encryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + *
  • For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive.
  • + *
  • For KWP mode: any length between 1 and 2^32-1 inclusive.
+ * \param[out] output The buffer holding the output data. + *
  • For KW mode: Must be at least 8 bytes larger than \p in_len.
  • + *
  • For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of + * 8 bytes for KWP (15 bytes at most).
+ * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size ); + +/** + * \brief This function decrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for decryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + * The input must be a multiple of semiblocks. + *
  • For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive.
  • + *
  • For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.
+ * \param[out] output The buffer holding the output data. + * The output buffer's minimal length is 8 bytes shorter than \p in_len. + * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * For KWP mode, the length could be up to 15 bytes shorter than \p in_len, + * depending on how much padding was added to the data. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return \c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size); + + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The key wrapping checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_nist_kw_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_NIST_KW_H */ diff --git a/external/mbedtls/include/mbedtls/oid.h b/external/mbedtls/include/mbedtls/oid.h new file mode 100644 index 0000000..4a7e3b4 --- /dev/null +++ b/external/mbedtls/include/mbedtls/oid.h @@ -0,0 +1,630 @@ +/** + * \file oid.h + * + * \brief Object Identifier (OID) database + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_OID_H +#define MBEDTLS_OID_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "asn1.h" +#include "pk.h" + +#include + +#if defined(MBEDTLS_CIPHER_C) +#include "cipher.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "md.h" +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "x509.h" +#endif + +#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */ +#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */ + +/* + * Top level OID tuples + */ +#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ +#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ +#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ +#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ + +/* + * ISO Member bodies OID parts + */ +#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ +#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ +#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ +#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ +#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_ANSI_X9_62 + +/* + * ISO Identified organization OID parts + */ +#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ +#define MBEDTLS_OID_ORG_OIW "\x0e" +#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" +#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" +#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" +#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_CERTICOM +#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ +#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_TELETRUST + +/* + * ISO ITU OID parts + */ +#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ +#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ + +#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ +#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ + +#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ +#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ + +/* ISO arc for standard certificate and CRL extensions */ +#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ + +#define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */ + +/** + * Private Internet Extensions + * { iso(1) identified-organization(3) dod(6) internet(1) + * security(5) mechanisms(5) pkix(7) } + */ +#define MBEDTLS_OID_PKIX MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x05\x05\x07" + +/* + * Arc for standard naming attributes + */ +#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ +#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ +#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ +#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ +#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ +#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ +#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ +#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ +#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ +#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ +#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ +#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ +#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ +#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ +#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ +#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */ +#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ +#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ + +#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ + +/* + * OIDs for standard certificate extensions + */ +#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ +#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ +#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ +#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ +#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ +#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ +#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ +#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ +#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ +#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ +#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ +#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ +#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ +#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ + +/* + * Netscape certificate extensions + */ +#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" +#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" +#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" +#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" +#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" +#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" +#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" +#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" +#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" +#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" +#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" + +/* + * OIDs for CRL extensions + */ +#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" +#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ + +/* + * X.509 v3 Extended key usage OIDs + */ +#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ + +#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ +#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ +#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ +#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ +#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ +#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ +#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ + +/* + * PKCS definition OIDs + */ + +#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ +#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ +#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ +#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ + +/* + * PKCS#1 OIDs + */ +#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ +#define MBEDTLS_OID_PKCS1_MD2 MBEDTLS_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ +#define MBEDTLS_OID_PKCS1_MD4 MBEDTLS_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ +#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ +#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ +#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ +#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ +#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ +#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ + +#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" + +#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ + +/* RFC 4055 */ +#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ +#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ + +/* + * Digest algorithms + */ +#define MBEDTLS_OID_DIGEST_ALG_MD2 MBEDTLS_OID_RSA_COMPANY "\x02\x02" /**< id-mbedtls_md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ + +#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ + +#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ + +#define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ + +#define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ + +#define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ + +/* + * Encryption algorithms + */ +#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ +#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ +#define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ + +/* + * Key Wrapping algorithms + */ +/* + * RFC 5649 + */ +#define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ +#define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ +#define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ +#define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ +#define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ +#define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ +/* + * PKCS#5 OIDs + */ +#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ +#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ +#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ + +/* + * PKCS#5 PBES1 algorithms + */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ + +/* + * PKCS#8 OIDs + */ +#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + +/* + * PKCS#12 PBE OIDs + */ +#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ + +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ + +/* + * EC key algorithms from RFC 5480 + */ + +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" + +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" + +/* + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 + */ + +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" + +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" + +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" + +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" + +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" + +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" + +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" + +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" + +/* RFC 5639 4.1 + * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) + * identified-organization(3) teletrust(36) algorithm(3) signature- + * algorithm(3) ecSign(2) 8} + * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} + * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ +#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" + +/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ +#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" + +/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ +#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" + +/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ +#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" + +/* + * SEC1 C.1 + * + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} + */ +#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" +#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" + +/* + * ECDSA signature identifiers, from RFC 5480 + */ +#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ +#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ + +/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" + +/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" + +/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 2 } */ +#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" + +/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 3 } */ +#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" + +/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 4 } */ +#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Base OID descriptor structure + */ +typedef struct mbedtls_oid_descriptor_t +{ + const char *asn1; /*!< OID ASN.1 representation */ + size_t asn1_len; /*!< length of asn1 */ + const char *name; /*!< official name (e.g. from RFC) */ + const char *description; /*!< human friendly description */ +} mbedtls_oid_descriptor_t; + +/** + * \brief Translate an ASN.1 OID into its numeric representation + * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") + * + * \param buf buffer to put representation in + * \param size size of the buffer + * \param oid OID to translate + * + * \return Length of the string written (excluding final NULL) or + * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error + */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid ); + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +/** + * \brief Translate an X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); +#endif + +/** + * \brief Translate an X.509 attribute type OID into the short name + * (e.g. the OID for an X520 Common Name into "CN") + * + * \param oid OID to use + * \param short_name place to store the string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **short_name ); + +/** + * \brief Translate PublicKeyAlgorithm OID into pk_type + * + * \param oid OID to use + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg, + const char **oid, size_t *olen ); + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Translate NamedCurve OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id ); + +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id, + const char **oid, size_t *olen ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) +/** + * \brief Translate SignatureAlgorithm OID into md_type and pk_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate SignatureAlgorithm OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type and pk_type into SignatureAlgorithm OID + * + * \param md_alg message digest algorithm + * \param pk_alg public key algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const char **oid, size_t *olen ); + +/** + * \brief Translate hash algorithm OID into md_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); + +/** + * \brief Translate hmac algorithm OID into md_type + * + * \param oid OID to use + * \param md_hmac place to store message hmac algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_hmac( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac ); +#endif /* MBEDTLS_MD_C */ + +/** + * \brief Translate Extended Key Usage OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type into hash algorithm OID + * + * \param md_alg message digest algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_C) +/** + * \brief Translate encryption algorithm OID into cipher_type + * + * \param oid OID to use + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_PKCS12_C) +/** + * \brief Translate PKCS#12 PBE algorithm OID into md_type and + * cipher_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pkcs12_pbe_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, + mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_PKCS12_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* oid.h */ diff --git a/external/mbedtls/include/mbedtls/padlock.h b/external/mbedtls/include/mbedtls/padlock.h new file mode 100644 index 0000000..d8246e2 --- /dev/null +++ b/external/mbedtls/include/mbedtls/padlock.h @@ -0,0 +1,151 @@ +/** + * \file padlock.h + * + * \brief VIA PadLock ACE for HW encryption/decryption supported by some + * processors + * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PADLOCK_H +#define MBEDTLS_PADLOCK_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "aes.h" + +#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define MBEDTLS_HAVE_ASAN +#endif +#endif + +/* Some versions of ASan result in errors about not enough registers */ +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \ + !defined(MBEDTLS_HAVE_ASAN) + +#ifndef MBEDTLS_HAVE_X86 +#define MBEDTLS_HAVE_X86 +#endif + +#include + +#define MBEDTLS_PADLOCK_RNG 0x000C +#define MBEDTLS_PADLOCK_ACE 0x00C0 +#define MBEDTLS_PADLOCK_PHE 0x0C00 +#define MBEDTLS_PADLOCK_PMM 0x3000 + +#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) (x) & ~15)) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal PadLock detection routine + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param feature The feature to detect + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_padlock_has_support( int feature ); + +/** + * \brief Internal PadLock AES-ECB block en(de)cryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal PadLock AES-CBC buffer en(de)cryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_X86 */ + +#endif /* padlock.h */ diff --git a/external/mbedtls/include/mbedtls/pem.h b/external/mbedtls/include/mbedtls/pem.h new file mode 100644 index 0000000..c9df7ca --- /dev/null +++ b/external/mbedtls/include/mbedtls/pem.h @@ -0,0 +1,171 @@ +/** + * \file pem.h + * + * \brief Privacy Enhanced Mail (PEM) decoding + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PEM_H +#define MBEDTLS_PEM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/** + * \name PEM Error codes + * These error codes are returned in case of errors reading the + * PEM data. + * \{ + */ +#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /**< No PEM header or footer found. */ +#define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */ +#define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */ +#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */ +#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */ +#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/** + * \brief PEM context structure + */ +typedef struct mbedtls_pem_context +{ + unsigned char *buf; /*!< buffer for decoded data */ + size_t buflen; /*!< length of the buffer */ + unsigned char *info; /*!< buffer for extra header information */ +} +mbedtls_pem_context; + +/** + * \brief PEM context setup + * + * \param ctx context to be initialized + */ +void mbedtls_pem_init( mbedtls_pem_context *ctx ); + +/** + * \brief Read a buffer for PEM information and store the resulting + * data into the specified context buffers. + * + * \param ctx context to use + * \param header header string to seek and expect + * \param footer footer string to seek and expect + * \param data source data to look in (must be nul-terminated) + * \param pwd password for decryption (can be NULL) + * \param pwdlen length of password + * \param use_len destination for total length used (set after header is + * correctly read, so unless you get + * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or + * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is + * the length to skip) + * + * \note Attempts to check password correctness by verifying if + * the decrypted text starts with an ASN.1 sequence of + * appropriate length + * + * \return 0 on success, or a specific PEM error code + */ +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, + const unsigned char *pwd, + size_t pwdlen, size_t *use_len ); + +/** + * \brief PEM context memory freeing + * + * \param ctx context to be freed + */ +void mbedtls_pem_free( mbedtls_pem_context *ctx ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a buffer of PEM information from a DER encoded + * buffer. + * + * \param header The header string to write. + * \param footer The footer string to write. + * \param der_data The DER data to encode. + * \param der_len The length of the DER data \p der_data in Bytes. + * \param buf The buffer to write to. + * \param buf_len The length of the output buffer \p buf in Bytes. + * \param olen The address at which to store the total length written + * or required (if \p buf_len is not enough). + * + * \note You may pass \c NULL for \p buf and \c 0 for \p buf_len + * to request the length of the resulting PEM buffer in + * `*olen`. + * + * \note This function may be called with overlapping \p der_data + * and \p buf buffers. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL if \p buf isn't large + * enough to hold the PEM buffer. In this case, `*olen` holds + * the required minimum size of \p buf. + * \return Another PEM or BASE64 error code on other kinds of failure. + */ +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ); +#endif /* MBEDTLS_PEM_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* pem.h */ diff --git a/external/mbedtls/include/mbedtls/pk.h b/external/mbedtls/include/mbedtls/pk.h new file mode 100644 index 0000000..20d51d4 --- /dev/null +++ b/external/mbedtls/include/mbedtls/pk.h @@ -0,0 +1,780 @@ +/** + * \file pk.h + * + * \brief Public Key abstraction layer + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_PK_H +#define MBEDTLS_PK_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" + +#if defined(MBEDTLS_RSA_C) +#include "rsa.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "ecdsa.h" +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */ +#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 /**< Unsupported key version */ +#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 /**< Invalid key tag or value. */ +#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 /**< Key algorithm is unsupported (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 /**< The pubkey tag or value is invalid (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ +#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ +#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The buffer contains a valid signature followed by more data. */ + +/* MBEDTLS_ERR_PK_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Public key types + */ +typedef enum { + MBEDTLS_PK_NONE=0, + MBEDTLS_PK_RSA, + MBEDTLS_PK_ECKEY, + MBEDTLS_PK_ECKEY_DH, + MBEDTLS_PK_ECDSA, + MBEDTLS_PK_RSA_ALT, + MBEDTLS_PK_RSASSA_PSS, +} mbedtls_pk_type_t; + +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c mbedtls_rsa_rsassa_pss_verify_ext() + */ +typedef struct mbedtls_pk_rsassa_pss_options +{ + mbedtls_md_type_t mgf1_hash_id; + int expected_salt_len; + +} mbedtls_pk_rsassa_pss_options; + +/** + * \brief Types for interfacing with the debug module + */ +typedef enum +{ + MBEDTLS_PK_DEBUG_NONE = 0, + MBEDTLS_PK_DEBUG_MPI, + MBEDTLS_PK_DEBUG_ECP, +} mbedtls_pk_debug_type; + +/** + * \brief Item to send to the debug module + */ +typedef struct mbedtls_pk_debug_item +{ + mbedtls_pk_debug_type type; + const char *name; + void *value; +} mbedtls_pk_debug_item; + +/** Maximum number of item send for debugging, plus 1 */ +#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 + +/** + * \brief Public key information and operations + */ +typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; + +/** + * \brief Public key container + */ +typedef struct mbedtls_pk_context +{ + const mbedtls_pk_info_t * pk_info; /**< Public key information */ + void * pk_ctx; /**< Underlying public key context */ +} mbedtls_pk_context; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Context for resuming operations + */ +typedef struct +{ + const mbedtls_pk_info_t * pk_info; /**< Public key information */ + void * rs_ctx; /**< Underlying restart context */ +} mbedtls_pk_restart_ctx; +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_pk_restart_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \warning You must make sure the PK context actually holds an RSA context + * before using this function! + */ +static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) +{ + return( (mbedtls_rsa_context *) (pk).pk_ctx ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \warning You must make sure the PK context actually holds an EC context + * before using this function! + */ +static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) +{ + return( (mbedtls_ecp_keypair *) (pk).pk_ctx ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Types for RSA-alt abstraction + */ +typedef int (*mbedtls_pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*mbedtls_pk_rsa_alt_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Return information associated with the given PK type + * + * \param pk_type PK type to search for. + * + * \return The PK info associated with the type or NULL if not found. + */ +const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); + +/** + * \brief Initialize a #mbedtls_pk_context (as NONE). + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ); + +/** + * \brief Free the components of a #mbedtls_pk_context. + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief Initialize a PK context with the information given + * and allocates the type-specific PK subcontext. + * + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). + * \param info Information to use + * + * \return 0 on success, + * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, + * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + * + * \note For contexts holding an RSA-alt key, use + * \c mbedtls_pk_setup_rsa_alt() instead. + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Initialize an RSA-alt context + * + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length in bytes + * + * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Get the size in bits of the underlying key + * + * \param ctx The context to query. It must have been initialized. + * + * \return Key size in bits, or 0 on error + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the length in bytes of the underlying key + * + * \param ctx The context to query. It must have been initialized. + * + * \return Key length in bytes, or 0 on error + */ +static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) +{ + return( ( mbedtls_pk_get_bitlen( ctx ) + 7 ) / 8 ); +} + +/** + * \brief Tell if a context can do the operation given by type + * + * \param ctx The context to query. It must have been initialized. + * \param type The desired type. + * + * \return 1 if the context can do operations on the given type. + * \return 0 if the context cannot do the operations on the given + * type. This is always the case for a context that has + * been initialized but not set up, or that has been + * cleared with mbedtls_pk_free(). + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); + +/** + * \brief Verify signature (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, + * or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) + * to verify RSASSA_PSS signatures. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Restartable version of \c mbedtls_pk_verify() + * + * \note Performs the same job as \c mbedtls_pk_verify(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_verify(). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_verify(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ); + +/** + * \brief Verify signature, with options. + * (Includes verification of the padding depending on type.) + * + * \param type Signature type (inc. possible padding type) to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + * + * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point + * to a mbedtls_pk_rsassa_pss_options structure, + * otherwise it must be NULL. + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Make signature, including padding if relevant. + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature + * \param sig_len Number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * There is no interface in the PK module to make RSASSA-PSS + * signatures yet. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. + * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. + * + * \note In order to ensure enough space for the signature, the + * \p sig buffer size must be of at least + * `max(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)` bytes. + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Restartable version of \c mbedtls_pk_sign() + * + * \note Performs the same job as \c mbedtls_pk_sign(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_sign(). + * + * \note In order to ensure enough space for the signature, the + * \p sig buffer size must be of at least + * `max(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)` bytes. + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature + * \param sig_len Number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_sign(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ); + +/** + * \brief Decrypt message (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param input Input to decrypt + * \param ilen Input size + * \param output Decrypted output + * \param olen Decrypted message length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Encrypt message (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up. + * \param input Message to encrypt + * \param ilen Message size + * \param output Encrypted output + * \param olen Encrypted output length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check if a public-private pair of keys matches. + * + * \param pub Context holding a public key. + * \param prv Context holding a private (and public) key. + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ); + +/** + * \brief Export debug information + * + * \param ctx The PK context to use. It must have been initialized. + * \param items Place to write debug items + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ); + +/** + * \brief Access the type name + * + * \param ctx The PK context to use. It must have been initialized. + * + * \return Type name on success, or "invalid PK" + */ +const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the key type + * + * \param ctx The PK context to use. It must have been initialized. + * + * \return Type on success. + * \return #MBEDTLS_PK_NONE for a context that has not been set up. + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); + +#if defined(MBEDTLS_PK_PARSE_C) +/** \ingroup pk_module */ +/** + * \brief Parse a private key in PEM or DER format + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * \param pwd Optional password for decryption. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a string of \p pwdlen bytes if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * \param pwdlen Size of the password in bytes. + * Ignored if \p pwd is \c NULL. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ); + +/** \ingroup pk_module */ +/** + * \brief Parse a public key in PEM or DER format + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup pk_module */ +/** + * \brief Load and parse a private key + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param path filename to read the private key from + * \param password Optional password to decrypt the file. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a null-terminated string if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *password ); + +/** \ingroup pk_module */ +/** + * \brief Load and parse a public key + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param path filename to read the public key from + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If + * you need a specific key type, check the result with + * mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a private key to a PKCS#1 or SEC1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx PK context which must contain a valid private key. + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a public key to a SubjectPublicKeyInfo DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx PK context which must contain a valid public or private key. + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a public key to a PEM string + * + * \param ctx PK context which must contain a valid public or private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a private key to a PKCS#1 or SEC1 PEM string + * + * \param ctx PK context which must contain a valid private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * WARNING: Low-level functions. You probably do not want to use these unless + * you are certain you do ;) + */ + +#if defined(MBEDTLS_PK_PARSE_C) +/** + * \brief Parse a SubjectPublicKeyInfo DER structure + * + * \param p the position in the ASN.1 data + * \param end end of the buffer + * \param pk The PK context to fill. It must have been initialized + * but not set up. + * + * \return 0 if successful, or a specific PK error code + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ); +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a subjectPublicKey to ASN.1 data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param key PK context which must contain a valid public or private key. + * + * \return the length written or a negative error code + */ +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ); +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +#if defined(MBEDTLS_FS_IO) +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PK_H */ diff --git a/external/mbedtls/include/mbedtls/pk_internal.h b/external/mbedtls/include/mbedtls/pk_internal.h new file mode 100644 index 0000000..3f84cdf --- /dev/null +++ b/external/mbedtls/include/mbedtls/pk_internal.h @@ -0,0 +1,163 @@ +/** + * \file pk_internal.h + * + * \brief Public Key abstraction layer: wrapper functions + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_PK_WRAP_H +#define MBEDTLS_PK_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "pk.h" + +struct mbedtls_pk_info_t +{ + /** Public key type */ + mbedtls_pk_type_t type; + + /** Type name */ + const char *name; + + /** Get key size in bits */ + size_t (*get_bitlen)( const void * ); + + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + int (*can_do)( mbedtls_pk_type_t type ); + + /** Verify signature */ + int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + + /** Make signature */ + int (*sign_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Verify signature (restartable) */ + int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + + /** Make signature (restartable) */ + int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + /** Decrypt message */ + int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Encrypt message */ + int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Check public-private key pair */ + int (*check_pair_func)( const void *pub, const void *prv ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Allocate the restart context */ + void * (*rs_alloc_func)( void ); + + /** Free the restart context */ + void (*rs_free_func)( void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + /** Interface with the debug module */ + void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); + +}; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Container for RSA-alt */ +typedef struct +{ + void *key; + mbedtls_pk_rsa_alt_decrypt_func decrypt_func; + mbedtls_pk_rsa_alt_sign_func sign_func; + mbedtls_pk_rsa_alt_key_len_func key_len_func; +} mbedtls_rsa_alt_context; +#endif + +#if defined(MBEDTLS_RSA_C) +extern const mbedtls_pk_info_t mbedtls_rsa_info; +#endif + +#if defined(MBEDTLS_ECP_C) +extern const mbedtls_pk_info_t mbedtls_eckey_info; +extern const mbedtls_pk_info_t mbedtls_eckeydh_info; +#endif + +#if defined(MBEDTLS_ECDSA_C) +extern const mbedtls_pk_info_t mbedtls_ecdsa_info; +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; +#endif + +#endif /* MBEDTLS_PK_WRAP_H */ diff --git a/external/mbedtls/include/mbedtls/pkcs11.h b/external/mbedtls/include/mbedtls/pkcs11.h new file mode 100644 index 0000000..3874d4a --- /dev/null +++ b/external/mbedtls/include/mbedtls/pkcs11.h @@ -0,0 +1,200 @@ +/** + * \file pkcs11.h + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PKCS11_H +#define MBEDTLS_PKCS11_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PKCS11_C) + +#include "x509_crt.h" + +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Context for PKCS #11 private keys. + */ +typedef struct mbedtls_pkcs11_context +{ + pkcs11h_certificate_t pkcs11h_cert; + int len; +} mbedtls_pkcs11_context; + +/** + * Initialize a mbedtls_pkcs11_context. + * (Just making memory references valid.) + */ +void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ); + +/** + * Fill in a mbed TLS certificate, based on the given PKCS11 helper certificate. + * + * \param cert X.509 certificate to fill + * \param pkcs11h_cert PKCS #11 helper certificate + * + * \return 0 on success. + */ +int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11h_cert ); + +/** + * Set up a mbedtls_pkcs11_context storing the given certificate. Note that the + * mbedtls_pkcs11_context will take over control of the certificate, freeing it when + * done. + * + * \param priv_key Private key structure to fill. + * \param pkcs11_cert PKCS #11 helper certificate + * + * \return 0 on success + */ +int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ); + +/** + * Free the contents of the given private key context. Note that the structure + * itself is not freed. + * + * \param priv_key Private key structure to cleanup + */ +void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ); + +/** + * \brief Do an RSA private key decrypt, then remove the message + * padding + * + * \param ctx PKCS #11 context + * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param olen will contain the plaintext length + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Do a private RSA to sign a message digest + * + * \param ctx PKCS #11 context + * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature + * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) + * \param hashlen message digest length (for MBEDTLS_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * SSL/TLS wrappers for PKCS#11 functions + */ +static inline int mbedtls_ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ) +{ + return mbedtls_pkcs11_decrypt( (mbedtls_pkcs11_context *) ctx, mode, olen, input, output, + output_max_len ); +} + +static inline int mbedtls_ssl_pkcs11_sign( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ) +{ + ((void) f_rng); + ((void) p_rng); + return mbedtls_pkcs11_sign( (mbedtls_pkcs11_context *) ctx, mode, md_alg, + hashlen, hash, sig ); +} + +static inline size_t mbedtls_ssl_pkcs11_key_len( void *ctx ) +{ + return ( (mbedtls_pkcs11_context *) ctx )->len; +} + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PKCS11_C */ + +#endif /* MBEDTLS_PKCS11_H */ diff --git a/external/mbedtls/include/mbedtls/pkcs12.h b/external/mbedtls/include/mbedtls/pkcs12.h new file mode 100644 index 0000000..9cbcb17 --- /dev/null +++ b/external/mbedtls/include/mbedtls/pkcs12.h @@ -0,0 +1,155 @@ +/** + * \file pkcs12.h + * + * \brief PKCS#12 Personal Information Exchange Syntax + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PKCS12_H +#define MBEDTLS_PKCS12_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" +#include "cipher.h" +#include "asn1.h" + +#include + +#define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 /**< Feature not available, e.g. unsupported encryption scheme. */ +#define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 /**< PBE ASN.1 data not as expected. */ +#define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 /**< Given private key password does not allow for correct decryption. */ + +#define MBEDTLS_PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */ +#define MBEDTLS_PKCS12_DERIVE_IV 2 /**< initialization vector */ +#define MBEDTLS_PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ + +#define MBEDTLS_PKCS12_PBE_DECRYPT 0 +#define MBEDTLS_PKCS12_PBE_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for pbeWithSHAAnd128BitRC4 + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for cipher-based and mbedtls_md-based PBE's + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param cipher_type the cipher used + * \param md_type the mbedtls_md used + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +/** + * \brief The PKCS#12 derivation function uses a password and a salt + * to produce pseudo-random bits for a particular "purpose". + * + * Depending on the given id, this function can produce an + * encryption/decryption key, an nitialization vector or an + * integrity key. + * + * \param data buffer to store the derived data in + * \param datalen length to fill + * \param pwd password to use (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param salt salt buffer to use + * \param saltlen length of the salt + * \param mbedtls_md mbedtls_md type to use during the derivation + * \param id id that describes the purpose (can be MBEDTLS_PKCS12_DERIVE_KEY, + * MBEDTLS_PKCS12_DERIVE_IV or MBEDTLS_PKCS12_DERIVE_MAC_KEY) + * \param iterations number of iterations + * + * \return 0 if successful, or a MD, BIGNUM type error. + */ +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t mbedtls_md, int id, int iterations ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs12.h */ diff --git a/external/mbedtls/include/mbedtls/pkcs5.h b/external/mbedtls/include/mbedtls/pkcs5.h new file mode 100644 index 0000000..328633c --- /dev/null +++ b/external/mbedtls/include/mbedtls/pkcs5.h @@ -0,0 +1,134 @@ +/** + * \file pkcs5.h + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PKCS5_H +#define MBEDTLS_PKCS5_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "asn1.h" +#include "md.h" + +#include +#include + +#define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -0x2f80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS5_INVALID_FORMAT -0x2f00 /**< Unexpected ASN.1 data. */ +#define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -0x2e80 /**< Requested encryption or digest alg not available. */ +#define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 /**< Given private key password does not allow for correct decryption. */ + +#define MBEDTLS_PKCS5_DECRYPT 0 +#define MBEDTLS_PKCS5_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +/** + * \brief PKCS#5 PBES2 function + * + * \param pbe_params the ASN.1 algorithm parameters + * \param mode either MBEDTLS_PKCS5_DECRYPT or MBEDTLS_PKCS5_ENCRYPT + * \param pwd password to use when generating key + * \param pwdlen length of password + * \param data data to process + * \param datalen length of data + * \param output output buffer + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ); + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +/** + * \brief PKCS#5 PBKDF2 using HMAC + * + * \param ctx Generic HMAC context + * \param password Password to use when generating key + * \param plen Length of password + * \param salt Salt to use when generating key + * \param slen Length of salt + * \param iteration_count Iteration count + * \param key_length Length of generated key in bytes + * \param output Generated key. Must be at least as big as key_length + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_pkcs5_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs5.h */ diff --git a/external/mbedtls/include/mbedtls/platform.h b/external/mbedtls/include/mbedtls/platform.h new file mode 100644 index 0000000..689cfc6 --- /dev/null +++ b/external/mbedtls/include/mbedtls/platform.h @@ -0,0 +1,392 @@ +/** + * \file platform.h + * + * \brief This file contains the definitions and functions of the + * Mbed TLS platform abstraction layer. + * + * The platform abstraction layer removes the need for the library + * to directly link to standard C library functions or operating + * system services, making the library easier to port and embed. + * Application developers and users of the library can provide their own + * implementations of these functions, or implementations specific to + * their platform, which can be statically linked to the library or + * dynamically configured at runtime. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PLATFORM_H +#define MBEDTLS_PLATFORM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "platform_time.h" +#endif + +#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 /**< Hardware accelerator failed */ +#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 /**< The requested feature is not supported by the platform */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#include +#include +#include +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +#if defined(_WIN32) +#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< The default \c calloc function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +#define MBEDTLS_PLATFORM_STD_FREE free /**< The default \c free function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +#define MBEDTLS_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +#define MBEDTLS_PLATFORM_STD_TIME time /**< The default \c time function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< The default exit value to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< The default exit value to use. */ +#endif +#if defined(MBEDTLS_FS_IO) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" +#endif +#endif /* MBEDTLS_FS_IO */ +#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) +#include MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + + +/* \} name SECTION: Module settings */ + +/* + * The function pointers for calloc and free. + */ +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ + defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO +#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO +#else +/* For size_t */ +#include +extern void *mbedtls_calloc( size_t n, size_t size ); +extern void mbedtls_free( void *ptr ); + +/** + * \brief This function dynamically sets the memory-management + * functions used by the library, during runtime. + * + * \param calloc_func The \c calloc function implementation. + * \param free_func The \c free function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ); +#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ +#else /* !MBEDTLS_PLATFORM_MEMORY */ +#define mbedtls_free free +#define mbedtls_calloc calloc +#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ + +/* + * The function pointers for fprintf + */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +/* We need FILE * */ +#include +extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); + +/** + * \brief This function dynamically configures the fprintf + * function that is called when the + * mbedtls_fprintf() function is invoked by the library. + * + * \param fprintf_func The \c fprintf function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, + ... ) ); +#else +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) +#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO +#else +#define mbedtls_fprintf fprintf +#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +/* + * The function pointers for printf + */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +extern int (*mbedtls_printf)( const char *format, ... ); + +/** + * \brief This function dynamically configures the snprintf + * function that is called when the mbedtls_snprintf() + * function is invoked by the library. + * + * \param printf_func The \c printf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); +#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) +#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO +#else +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +/* + * The function pointers for snprintf + * + * The snprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(_WIN32) +/* For Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); + +/** + * \brief This function allows configuring a custom + * \c snprintf function pointer. + * + * \param snprintf_func The \c snprintf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, ... ) ); +#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO +#else +#define mbedtls_snprintf MBEDTLS_PLATFORM_STD_SNPRINTF +#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +/* + * The function pointers for exit + */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +extern void (*mbedtls_exit)( int status ); + +/** + * \brief This function dynamically configures the exit + * function that is called when the mbedtls_exit() + * function is invoked by the library. + * + * \param exit_func The \c exit function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); +#else +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) +#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO +#else +#define mbedtls_exit exit +#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +/* + * The default exit values + */ +#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS +#else +#define MBEDTLS_EXIT_SUCCESS 0 +#endif +#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE +#else +#define MBEDTLS_EXIT_FAILURE 1 +#endif + +/* + * The function pointers for reading from and writing a seed file to + * Non-Volatile storage (NV) in a platform-independent way + * + * Only enabled when the NV seed entropy source is enabled + */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Internal standard platform definitions */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ); +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ); +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ); +extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); + +/** + * \brief This function allows configuring custom seed file writing and + * reading functions. + * + * \param nv_seed_read_func The seed reading function implementation. + * \param nv_seed_write_func The seed writing function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) + ); +#else +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ + defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) +#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO +#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO +#else +#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read +#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write +#endif +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + +/** + * \brief The platform context structure. + * + * \note This structure may be used to assist platform-specific + * setup or teardown operations. + */ +typedef struct mbedtls_platform_context +{ + char dummy; /**< A placeholder member, as empty structs are not portable. */ +} +mbedtls_platform_context; + +#else +#include "platform_alt.h" +#endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +/** + * \brief This function performs any platform-specific initialization + * operations. + * + * \note This function should be called before any other library functions. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + * \return \c 0 on success. + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ); +/** + * \brief This function performs any platform teardown operations. + * + * \note This function should be called after every other Mbed TLS module + * has been correctly freed using the appropriate free function. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* platform.h */ diff --git a/external/mbedtls/include/mbedtls/platform_time.h b/external/mbedtls/include/mbedtls/platform_time.h new file mode 100644 index 0000000..e132f6a --- /dev/null +++ b/external/mbedtls/include/mbedtls/platform_time.h @@ -0,0 +1,107 @@ +/** + * \file platform_time.h + * + * \brief mbed TLS Platform time abstraction + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PLATFORM_TIME_H +#define MBEDTLS_PLATFORM_TIME_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +/* + * The time_t datatype + */ +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) +typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; +#else +/* For time_t */ +#include +typedef time_t mbedtls_time_t; +#endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ + +/* + * The function pointers for time + */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +extern mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* time ); + +/** + * \brief Set your own time function pointer + * + * \param time_func the time function implementation + * + * \return 0 + */ +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* time ) ); +#else +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) +#define mbedtls_time MBEDTLS_PLATFORM_TIME_MACRO +#else +#define mbedtls_time time +#endif /* MBEDTLS_PLATFORM_TIME_MACRO */ +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif /* platform_time.h */ diff --git a/external/mbedtls/include/mbedtls/platform_util.h b/external/mbedtls/include/mbedtls/platform_util.h new file mode 100644 index 0000000..426afaf --- /dev/null +++ b/external/mbedtls/include/mbedtls/platform_util.h @@ -0,0 +1,221 @@ +/** + * \file platform_util.h + * + * \brief Common and shared functions used by multiple modules in the Mbed TLS + * library. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PLATFORM_UTIL_H +#define MBEDTLS_PLATFORM_UTIL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "platform_time.h" +#include +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_CHECK_PARAMS) + +#if defined(MBEDTLS_CHECK_PARAMS_ASSERT) +/* Allow the user to define MBEDTLS_PARAM_FAILED to something like assert + * (which is what our config.h suggests). */ +#include +#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */ + +#if defined(MBEDTLS_PARAM_FAILED) +/** An alternative definition of MBEDTLS_PARAM_FAILED has been set in config.h. + * + * This flag can be used to check whether it is safe to assume that + * MBEDTLS_PARAM_FAILED() will expand to a call to mbedtls_param_failed(). + */ +#define MBEDTLS_PARAM_FAILED_ALT + +#elif defined(MBEDTLS_CHECK_PARAMS_ASSERT) +#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) +#define MBEDTLS_PARAM_FAILED_ALT + +#else /* MBEDTLS_PARAM_FAILED */ +#define MBEDTLS_PARAM_FAILED( cond ) \ + mbedtls_param_failed( #cond, __FILE__, __LINE__ ) + +/** + * \brief User supplied callback function for parameter validation failure. + * See #MBEDTLS_CHECK_PARAMS for context. + * + * This function will be called unless an alternative treatement + * is defined through the #MBEDTLS_PARAM_FAILED macro. + * + * This function can return, and the operation will be aborted, or + * alternatively, through use of setjmp()/longjmp() can resume + * execution in the application code. + * + * \param failure_condition The assertion that didn't hold. + * \param file The file where the assertion failed. + * \param line The line in the file where the assertion failed. + */ +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ); +#endif /* MBEDTLS_PARAM_FAILED */ + +/* Internal macro meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) \ + do { \ + if( !(cond) ) \ + { \ + MBEDTLS_PARAM_FAILED( cond ); \ + return( ret ); \ + } \ + } while( 0 ) + +/* Internal macro meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE( cond ) \ + do { \ + if( !(cond) ) \ + { \ + MBEDTLS_PARAM_FAILED( cond ); \ + return; \ + } \ + } while( 0 ) + +#else /* MBEDTLS_CHECK_PARAMS */ + +/* Internal macros meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 ) +#define MBEDTLS_INTERNAL_VALIDATE( cond ) do { } while( 0 ) + +#endif /* MBEDTLS_CHECK_PARAMS */ + +/* Internal helper macros for deprecating API constants. */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +/* Deliberately don't (yet) export MBEDTLS_DEPRECATED here + * to avoid conflict with other headers which define and use + * it, too. We might want to move all these definitions here at + * some point for uniformity. */ +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +MBEDTLS_DEPRECATED typedef char const * mbedtls_deprecated_string_constant_t; +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_string_constant_t) ( VAL ) ) +MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t; +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_numeric_constant_t) ( VAL ) ) +#undef MBEDTLS_DEPRECATED +#else /* MBEDTLS_DEPRECATED_WARNING */ +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) VAL +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) VAL +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Securely zeroize a buffer + * + * The function is meant to wipe the data contained in a buffer so + * that it can no longer be recovered even if the program memory + * is later compromised. Call this function on sensitive data + * stored on the stack before returning from a function, and on + * sensitive data stored on the heap before freeing the heap + * object. + * + * It is extremely difficult to guarantee that calls to + * mbedtls_platform_zeroize() are not removed by aggressive + * compiler optimizations in a portable way. For this reason, Mbed + * TLS provides the configuration option + * MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for + * their platform and needs + * + * \param buf Buffer to be zeroized + * \param len Length of the buffer in bytes + * + */ +void mbedtls_platform_zeroize( void *buf, size_t len ); + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/** + * \brief Platform-specific implementation of gmtime_r() + * + * The function is a thread-safe abstraction that behaves + * similarly to the gmtime_r() function from Unix/POSIX. + * + * Mbed TLS will try to identify the underlying platform and + * make use of an appropriate underlying implementation (e.g. + * gmtime_r() for POSIX and gmtime_s() for Windows). If this is + * not possible, then gmtime() will be used. In this case, calls + * from the library to gmtime() will be guarded by the mutex + * mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is + * enabled. It is recommended that calls from outside the library + * are also guarded by this mutex. + * + * If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will + * unconditionally use the alternative implementation for + * mbedtls_platform_gmtime_r() supplied by the user at compile time. + * + * \param tt Pointer to an object containing time (in seconds) since the + * epoch to be converted + * \param tm_buf Pointer to an object where the results will be stored + * + * \return Pointer to an object of type struct tm on success, otherwise + * NULL + */ +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ); +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PLATFORM_UTIL_H */ diff --git a/external/mbedtls/include/mbedtls/poly1305.h b/external/mbedtls/include/mbedtls/poly1305.h new file mode 100644 index 0000000..b337aa8 --- /dev/null +++ b/external/mbedtls/include/mbedtls/poly1305.h @@ -0,0 +1,218 @@ +/** + * \file poly1305.h + * + * \brief This file contains Poly1305 definitions and functions. + * + * Poly1305 is a one-time message authenticator that can be used to + * authenticate messages. Poly1305-AES was created by Daniel + * Bernstein https://cr.yp.to/mac/poly1305-20050329.pdf The generic + * Poly1305 algorithm (not tied to AES) was also standardized in RFC + * 7539. + * + * \author Daniel King + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_POLY1305_H +#define MBEDTLS_POLY1305_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 /**< Invalid input parameter(s). */ + +/* MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ +#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE -0x0059 /**< Feature not available. For example, s part of the API is not implemented. */ + +/* MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED -0x005B /**< Poly1305 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_POLY1305_ALT) + +typedef struct mbedtls_poly1305_context +{ + uint32_t r[4]; /** The value for 'r' (low 128 bits of the key). */ + uint32_t s[4]; /** The value for 's' (high 128 bits of the key). */ + uint32_t acc[5]; /** The accumulator number. */ + uint8_t queue[16]; /** The current partial block of data. */ + size_t queue_len; /** The number of bytes stored in 'queue'. */ +} +mbedtls_poly1305_context; + +#else /* MBEDTLS_POLY1305_ALT */ +#include "poly1305_alt.h" +#endif /* MBEDTLS_POLY1305_ALT */ + +/** + * \brief This function initializes the specified Poly1305 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by a call to + * \c mbedtls_poly1305_starts(), then one or more calls to + * \c mbedtls_poly1305_update(), then one call to + * \c mbedtls_poly1305_finish(), then finally + * \c mbedtls_poly1305_free(). + * + * \param ctx The Poly1305 context to initialize. This must + * not be \c NULL. + */ +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function releases and clears the specified + * Poly1305 context. + * + * \param ctx The Poly1305 context to clear. This may be \c NULL, in which + * case this function is a no-op. If it is not \c NULL, it must + * point to an initialized Poly1305 context. + */ +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function sets the one-time authentication key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param ctx The Poly1305 context to which the key should be bound. + * This must be initialized. + * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This functions feeds an input buffer into an ongoing + * Poly1305 computation. + * + * It is called between \c mbedtls_cipher_poly1305_starts() and + * \c mbedtls_cipher_poly1305_finish(). + * It can be called repeatedly to process a stream of data. + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * This must be initialized and bound to a key. + * \param ilen The length of the input data in Bytes. + * Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `ilen == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function generates the Poly1305 Message + * Authentication Code (MAC). + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * This must be initialized and bound to a key. + * \param mac The buffer to where the MAC is written. This must + * be a writable buffer of length \c 16 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function calculates the Poly1305 MAC of the input + * buffer with the provided key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. + * \param ilen The length of the input data in Bytes. + * Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `ilen == 0`. + * \param mac The buffer to where the MAC is written. This must be + * a writable buffer of length \c 16 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_poly1305_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_POLY1305_H */ diff --git a/external/mbedtls/include/mbedtls/ripemd160.h b/external/mbedtls/include/mbedtls/ripemd160.h new file mode 100644 index 0000000..31c6637 --- /dev/null +++ b/external/mbedtls/include/mbedtls/ripemd160.h @@ -0,0 +1,262 @@ +/** + * \file ripemd160.h + * + * \brief RIPE MD-160 message digest + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_RIPEMD160_H +#define MBEDTLS_RIPEMD160_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 /**< RIPEMD160 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_RIPEMD160_ALT) +// Regular implementation +// + +/** + * \brief RIPEMD-160 context structure + */ +typedef struct mbedtls_ripemd160_context +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_ripemd160_context; + +#else /* MBEDTLS_RIPEMD160_ALT */ +#include "ripemd160.h" +#endif /* MBEDTLS_RIPEMD160_ALT */ + +/** + * \brief Initialize RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be initialized + */ +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clear RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be cleared + */ +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clone (the state of) an RIPEMD-160 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ); + +/** + * \brief RIPEMD-160 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + */ +int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + */ +int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + * + * \return 0 if successful + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief RIPEMD-160 context setup + * + * \deprecated Superseded by mbedtls_ripemd160_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_starts( + mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \deprecated Superseded by mbedtls_ripemd160_update_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_update( + mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \deprecated Superseded by mbedtls_ripemd160_finish_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_finish( + mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_ripemd160_process() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_process( + mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \deprecated Superseded by mbedtls_ripemd160_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_ripemd160_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_ripemd160.h */ diff --git a/external/mbedtls/include/mbedtls/rsa.h b/external/mbedtls/include/mbedtls/rsa.h new file mode 100644 index 0000000..b2f6533 --- /dev/null +++ b/external/mbedtls/include/mbedtls/rsa.h @@ -0,0 +1,1303 @@ +/** + * \file rsa.h + * + * \brief This file provides an API for the RSA public-key cryptosystem. + * + * The RSA public-key cryptosystem is defined in Public-Key + * Cryptography Standards (PKCS) #1 v1.5: RSA Encryption + * and Public-Key Cryptography Standards (PKCS) #1 v2.1: + * RSA Cryptography Specifications. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_RSA_H +#define MBEDTLS_RSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" +#include "md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +/* + * RSA Error codes + */ +#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ +#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the validity check of the library. */ +#define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ +#define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ +#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ +#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ +#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ + +/* MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION is deprecated and should not be used. + */ +#define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */ + +/* MBEDTLS_ERR_RSA_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED -0x4580 /**< RSA hardware accelerator failed. */ + +/* + * RSA constants + */ +#define MBEDTLS_RSA_PUBLIC 0 /**< Request private key operation. */ +#define MBEDTLS_RSA_PRIVATE 1 /**< Request public key operation. */ + +#define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS#1 v1.5 encoding. */ +#define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS#1 v2.1 encoding. */ + +#define MBEDTLS_RSA_SIGN 1 /**< Identifier for RSA signature operations. */ +#define MBEDTLS_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */ + +#define MBEDTLS_RSA_SALT_LEN_ANY -1 + +/* + * The above constants may be used even if the RSA module is compile out, + * eg for alternative (PKCS#11) RSA implemenations in the PK layers. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_RSA_ALT) +// Regular implementation +// + +/** + * \brief The RSA context structure. + * + * \note Direct manipulation of the members of this structure + * is deprecated. All manipulation should instead be done through + * the public interface functions. + */ +typedef struct mbedtls_rsa_context +{ + int ver; /*!< Reserved for internal purposes. + * Do not set this field in application + * code. Its meaning might change without + * notice. */ + size_t len; /*!< The size of \p N in Bytes. */ + + mbedtls_mpi N; /*!< The public modulus. */ + mbedtls_mpi E; /*!< The public exponent. */ + + mbedtls_mpi D; /*!< The private exponent. */ + mbedtls_mpi P; /*!< The first prime factor. */ + mbedtls_mpi Q; /*!< The second prime factor. */ + + mbedtls_mpi DP; /*!< D % (P - 1). */ + mbedtls_mpi DQ; /*!< D % (Q - 1). */ + mbedtls_mpi QP; /*!< 1 / (Q % P). */ + + mbedtls_mpi RN; /*!< cached R^2 mod N. */ + + mbedtls_mpi RP; /*!< cached R^2 mod P. */ + mbedtls_mpi RQ; /*!< cached R^2 mod Q. */ + + mbedtls_mpi Vi; /*!< The cached blinding value. */ + mbedtls_mpi Vf; /*!< The cached un-blinding value. */ + + int padding; /*!< Selects padding mode: + #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ + int hash_id; /*!< Hash identifier of mbedtls_md_type_t type, + as specified in md.h for use in the MGF + mask generating function used in the + EME-OAEP and EMSA-PSS encodings. */ +#if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized iff ver != 0. */ + mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex. */ +#endif +} +mbedtls_rsa_context; + +#else /* MBEDTLS_RSA_ALT */ +#include "rsa_alt.h" +#endif /* MBEDTLS_RSA_ALT */ + +/** + * \brief This function initializes an RSA context. + * + * \note Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \note The \p hash_id parameter is ignored when using + * #MBEDTLS_RSA_PKCS_V15 padding. + * + * \note The choice of padding mode is strictly enforced for private key + * operations, since there might be security concerns in + * mixing padding modes. For public key operations it is + * a default value, which can be overridden by calling specific + * \c rsa_rsaes_xxx or \c rsa_rsassa_xxx functions. + * + * \note The hash selected in \p hash_id is always used for OEAP + * encryption. For PSS signatures, it is always used for + * making signatures, but can be overridden for verifying them. + * If set to #MBEDTLS_MD_NONE, it is always overridden. + * + * \param ctx The RSA context to initialize. This must not be \c NULL. + * \param padding The padding mode to use. This must be either + * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The hash identifier of ::mbedtls_md_type_t type, if + * \p padding is #MBEDTLS_RSA_PKCS_V21. It is unused + * otherwise. + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id ); + +/** + * \brief This function imports a set of core parameters into an + * RSA context. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus. This may be \c NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param D The private exponent. This may be \c NULL. + * \param E The public exponent. This may be \c NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ); + +/** + * \brief This function imports core RSA parameters, in raw big-endian + * binary format, into an RSA context. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus. This may be \c NULL. + * \param N_len The Byte length of \p N; it is ignored if \p N == NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param P_len The Byte length of \p P; it ns ignored if \p P == NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param Q_len The Byte length of \p Q; it is ignored if \p Q == NULL. + * \param D The private exponent. This may be \c NULL. + * \param D_len The Byte length of \p D; it is ignored if \p D == NULL. + * \param E The public exponent. This may be \c NULL. + * \param E_len The Byte length of \p E; it is ignored if \p E == NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ); + +/** + * \brief This function completes an RSA context from + * a set of imported core parameters. + * + * To setup an RSA public key, precisely \p N and \p E + * must have been imported. + * + * To setup an RSA private key, sufficient information must + * be present for the other parameters to be derivable. + * + * The default implementation supports the following: + *
  • Derive \p P, \p Q from \p N, \p D, \p E.
  • + *
  • Derive \p N, \p D from \p P, \p Q, \p E.
+ * Alternative implementations need not support these. + * + * If this function runs successfully, it guarantees that + * the RSA context can be used for RSA operations without + * the risk of failure or crash. + * + * \warning This function need not perform consistency checks + * for the imported parameters. In particular, parameters that + * are not needed by the implementation might be silently + * discarded and left unchecked. To check the consistency + * of the key material, see mbedtls_rsa_check_privkey(). + * + * \param ctx The initialized RSA context holding imported parameters. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the attempted derivations + * failed. + * + */ +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); + +/** + * \brief This function exports the core parameters of an RSA key. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * + * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \param ctx The initialized RSA context. + * \param N The MPI to hold the RSA modulus. + * This may be \c NULL if this field need not be exported. + * \param P The MPI to hold the first prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param Q The MPI to hold the second prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param D The MPI to hold the private exponent. + * This may be \c NULL if this field need not be exported. + * \param E The MPI to hold the public exponent. + * This may be \c NULL if this field need not be exported. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + * + */ +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ); + +/** + * \brief This function exports core parameters of an RSA key + * in raw big-endian binary format. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \note The length parameters are ignored if the corresponding + * buffer pointers are NULL. + * + * \param ctx The initialized RSA context. + * \param N The Byte array to store the RSA modulus, + * or \c NULL if this field need not be exported. + * \param N_len The size of the buffer for the modulus. + * \param P The Byte array to hold the first prime factor of \p N, + * or \c NULL if this field need not be exported. + * \param P_len The size of the buffer for the first prime factor. + * \param Q The Byte array to hold the second prime factor of \p N, + * or \c NULL if this field need not be exported. + * \param Q_len The size of the buffer for the second prime factor. + * \param D The Byte array to hold the private exponent, + * or \c NULL if this field need not be exported. + * \param D_len The size of the buffer for the private exponent. + * \param E The Byte array to hold the public exponent, + * or \c NULL if this field need not be exported. + * \param E_len The size of the buffer for the public exponent. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + */ +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ); + +/** + * \brief This function exports CRT parameters of a private RSA key. + * + * \note Alternative RSA implementations not using CRT-parameters + * internally can implement this function based on + * mbedtls_rsa_deduce_opt(). + * + * \param ctx The initialized RSA context. + * \param DP The MPI to hold \c D modulo `P-1`, + * or \c NULL if it need not be exported. + * \param DQ The MPI to hold \c D modulo `Q-1`, + * or \c NULL if it need not be exported. + * \param QP The MPI to hold modular inverse of \c Q modulo \c P, + * or \c NULL if it need not be exported. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + * + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ); + +/** + * \brief This function sets padding for an already initialized RSA + * context. See mbedtls_rsa_init() for details. + * + * \param ctx The initialized RSA context to be configured. + * \param padding The padding mode to use. This must be either + * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The #MBEDTLS_RSA_PKCS_V21 hash identifier. + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id ); + +/** + * \brief This function retrieves the length of RSA modulus in Bytes. + * + * \param ctx The initialized RSA context. + * + * \return The length of the RSA modulus in Bytes. + * + */ +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function generates an RSA keypair. + * + * \note mbedtls_rsa_init() must be called before this function, + * to set up the RSA context. + * + * \param ctx The initialized RSA context used to hold the key. + * \param f_rng The RNG function to be used for key generation. + * This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't need a context. + * \param nbits The size of the public key in bits. + * \param exponent The public exponent to use. For example, \c 65537. + * This must be odd and greater than \c 1. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); + +/** + * \brief This function checks if a context contains at least an RSA + * public key. + * + * If the function runs successfully, it is guaranteed that + * enough information is present to perform an RSA public key + * operation using mbedtls_rsa_public(). + * + * \param ctx The initialized RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks if a context contains an RSA private key + * and perform basic consistency checks. + * + * \note The consistency checks performed by this function not only + * ensure that mbedtls_rsa_private() can be called successfully + * on the given context, but that the various parameters are + * mutually consistent with high probability, in the sense that + * mbedtls_rsa_public() and mbedtls_rsa_private() are inverses. + * + * \warning This function should catch accidental misconfigurations + * like swapping of parameters, but it cannot establish full + * trust in neither the quality nor the consistency of the key + * material that was used to setup the given RSA context: + *
  • Consistency: Imported parameters that are irrelevant + * for the implementation might be silently dropped. If dropped, + * the current function does not have access to them, + * and therefore cannot check them. See mbedtls_rsa_complete(). + * If you want to check the consistency of the entire + * content of an PKCS1-encoded RSA private key, for example, you + * should use mbedtls_rsa_validate_params() before setting + * up the RSA context. + * Additionally, if the implementation performs empirical checks, + * these checks substantiate but do not guarantee consistency.
  • + *
  • Quality: This function is not expected to perform + * extended quality assessments like checking that the prime + * factors are safe. Additionally, it is the responsibility of the + * user to ensure the trustworthiness of the source of his RSA + * parameters, which goes beyond what is effectively checkable + * by the library.
+ * + * \param ctx The initialized RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks a public-private RSA key pair. + * + * It checks each of the contexts, and makes sure they match. + * + * \param pub The initialized RSA context holding the public key. + * \param prv The initialized RSA context holding the private key. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ); + +/** + * \brief This function performs an RSA public key operation. + * + * \param ctx The initialized RSA context to use. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \note This function does not handle message padding. + * + * \note Make sure to set \p input[0] = 0 or ensure that + * input is smaller than \p N. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA private key operation. + * + * \note Blinding is used if and only if a PRNG is provided. + * + * \note If blinding is used, both the base of exponentation + * and the exponent are blinded, providing protection + * against some side-channel attacks. + * + * \warning It is deprecated and a security risk to not provide + * a PRNG here and thereby prevent the use of blinding. + * Future versions of the library may enforce the presence + * of a PRNG. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function, used for blinding. It is discouraged + * and deprecated to pass \c NULL here, in which case + * blinding will be omitted. + * \param p_rng The RNG context to pass to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or if \p f_rng doesn't need a context. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function adds the message padding, then performs an RSA + * operation. + * + * It is the generic wrapper for performing a PKCS#1 encryption + * operation using the \p mode from the context. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG to use. It is mandatory for PKCS#1 v2.1 padding + * encoding, and for PKCS#1 v1.5 padding encoding when used + * with \p mode set to #MBEDTLS_RSA_PUBLIC. For PKCS#1 v1.5 + * padding encoding and \p mode set to #MBEDTLS_RSA_PRIVATE, + * it is used for blinding and should be provided in this + * case; see mbedtls_rsa_private() for more. + * \param p_rng The RNG context to be passed to \p f_rng. May be + * \c NULL if \p f_rng is \c NULL or if \p f_rng doesn't + * need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. This must not be \c NULL. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v1.5 encryption operation + * (RSAES-PKCS1-v1_5-ENCRYPT). + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. It is needed for padding generation + * if \p mode is #MBEDTLS_RSA_PUBLIC. If \p mode is + * #MBEDTLS_RSA_PRIVATE (discouraged), it is used for + * blinding and should be provided; see mbedtls_rsa_private(). + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng is \c NULL or if \p f_rng + * doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. This must not be \c NULL. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP encryption + * operation (RSAES-OAEP-ENCRYPT). + * + * \note The output buffer must be as large as the size + * of ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initnialized RSA context to use. + * \param f_rng The RNG function to use. This is needed for padding + * generation and must be provided. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param label The buffer holding the custom label to use. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param ilen The length of the plaintext buffer \p input in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. This must not be \c NULL. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA operation, then removes the + * message padding. + * + * It is the generic wrapper for performing a PKCS#1 decryption + * operation using the \p mode from the context. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N (for example, + * 128 Bytes if RSA-1024 is used) to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v1.5 decryption + * operation (RSAES-PKCS1-v1_5-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for example, + * 128 Bytes if RSA-1024 is used, to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP decryption + * operation (RSAES-OAEP-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for + * example, 128 Bytes if RSA-1024 is used, to be able to + * hold an arbitrary decrypted message. If it is not + * large enough to hold the decryption of the particular + * ciphertext provided, the function returns + * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param label The buffer holding the custom label to use. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a private RSA operation to sign + * a message digest using PKCS#1. + * + * It is the generic wrapper for performing a PKCS#1 + * signature using the \p mode from the context. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_sign() for details on + * \p md_alg and \p hash_id. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. If the padding mode is PKCS#1 v2.1, + * this must be provided. If the padding mode is PKCS#1 v1.5 and + * \p mode is #MBEDTLS_RSA_PRIVATE, it is used for blinding + * and should be provided; see mbedtls_rsa_private() for more + * more. It is ignored otherwise. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 signature + * operation (RSASSA-PKCS1-v1_5-SIGN). + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS signature + * operation (RSASSA-PSS-SIGN). + * + * \note The \p hash_id in the RSA context is the one used for the + * encoding. \p md_alg in the function call is the type of hash + * that is encoded. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. + * + * \note This function always uses the maximum possible salt size, + * up to the length of the payload hash. This choice of salt + * size complies with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 + * v2.2) §9.1.1 step 3. Furthermore this function enforces a + * minimum salt size which is the hash size minus 2 bytes. If + * this minimum size is too large given the key size (the salt + * size, plus the hash size, plus 2 bytes must be no more than + * the key size in bytes), this function returns + * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. It must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a public RSA operation and checks + * the message digest. + * + * This is the generic wrapper for performing a PKCS#1 + * verification using the mode from the context. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and + * \p hash_id. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 verification + * operation (RSASSA-PKCS1-v1_5-VERIFY). + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * The hash function for the MGF mask generating function + * is that specified in the RSA context. + * + * \note The \p hash_id in the RSA context is the one used for the + * verification. \p md_alg in the function call is the type of + * hash that is verified. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. If \p hash_id in the RSA context is unset, + * the \p md_alg from the function call is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * The hash function for the MGF mask generating function + * is that specified in \p mgf1_hash_id. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is ignored. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param mgf1_hash_id The message digest used for mask generation. + * \param expected_salt_len The length of the salt used in padding. Use + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ); + +/** + * \brief This function copies the components of an RSA context. + * + * \param dst The destination context. This must be initialized. + * \param src The source context. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ); + +/** + * \brief This function frees the components of an RSA key. + * + * \param ctx The RSA context to free. May be \c NULL, in which case + * this function is a no-op. If it is not \c NULL, it must + * point to an initialized RSA context. + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The RSA checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_rsa_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* rsa.h */ diff --git a/external/mbedtls/include/mbedtls/rsa_internal.h b/external/mbedtls/include/mbedtls/rsa_internal.h new file mode 100644 index 0000000..953cb7b --- /dev/null +++ b/external/mbedtls/include/mbedtls/rsa_internal.h @@ -0,0 +1,251 @@ +/** + * \file rsa_internal.h + * + * \brief Context-independent RSA helper functions + * + * This module declares some RSA-related helper functions useful when + * implementing the RSA interface. These functions are provided in a separate + * compilation unit in order to make it easy for designers of alternative RSA + * implementations to use them in their own code, as it is conceived that the + * functionality they provide will be necessary for most complete + * implementations. + * + * End-users of Mbed TLS who are not providing their own alternative RSA + * implementations should not use these functions directly, and should instead + * use only the functions declared in rsa.h. + * + * The interface provided by this module will be maintained through LTS (Long + * Term Support) branches of Mbed TLS, but may otherwise be subject to change, + * and must be considered an internal interface of the library. + * + * There are two classes of helper functions: + * + * (1) Parameter-generating helpers. These are: + * - mbedtls_rsa_deduce_primes + * - mbedtls_rsa_deduce_private_exponent + * - mbedtls_rsa_deduce_crt + * Each of these functions takes a set of core RSA parameters and + * generates some other, or CRT related parameters. + * + * (2) Parameter-checking helpers. These are: + * - mbedtls_rsa_validate_params + * - mbedtls_rsa_validate_crt + * They take a set of core or CRT related RSA parameters and check their + * validity. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * + */ + +#ifndef MBEDTLS_RSA_INTERNAL_H +#define MBEDTLS_RSA_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * \brief Compute RSA prime moduli P, Q from public modulus N=PQ + * and a pair of private and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ, with P, Q to be found + * \param E RSA public exponent + * \param D RSA private exponent + * \param P Pointer to MPI holding first prime factor of N on success + * \param Q Pointer to MPI holding second prime factor of N on success + * + * \return + * - 0 if successful. In this case, P and Q constitute a + * factorization of N. + * - A non-zero error code otherwise. + * + * \note It is neither checked that P, Q are prime nor that + * D, E are modular inverses wrt. P-1 and Q-1. For that, + * use the helper function \c mbedtls_rsa_validate_params. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, mbedtls_mpi const *E, + mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ); + +/** + * \brief Compute RSA private exponent from + * prime moduli and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param E RSA public exponent + * \param D Pointer to MPI holding the private exponent on success. + * + * \return + * - 0 if successful. In this case, D is set to a simultaneous + * modular inverse of E modulo both P-1 and Q-1. + * - A non-zero error code otherwise. + * + * \note This function does not check whether P and Q are primes. + * + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ); + + +/** + * \brief Generate RSA-CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param DP Output variable for D modulo P-1 + * \param DQ Output variable for D modulo Q-1 + * \param QP Output variable for the modular inverse of Q modulo P. + * + * \return 0 on success, non-zero error code otherwise. + * + * \note This function does not check whether P, Q are + * prime and whether D is a valid private exponent. + * + */ +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ); + + +/** + * \brief Check validity of core RSA parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param E RSA public exponent + * \param f_rng PRNG to be used for primality check, or NULL + * \param p_rng PRNG context for f_rng, or NULL + * + * \return + * - 0 if the following conditions are satisfied + * if all relevant parameters are provided: + * - P prime if f_rng != NULL (%) + * - Q prime if f_rng != NULL (%) + * - 1 < N = P * Q + * - 1 < D, E < N + * - D and E are modular inverses modulo P-1 and Q-1 + * (%) This is only done if MBEDTLS_GENPRIME is defined. + * - A non-zero error code otherwise. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with + * (-,P,-,-,-) and a PRNG amounts to a primality check for P. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Check validity of RSA CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param D RSA private exponent + * \param DP MPI to check for D modulo P-1 + * \param DQ MPI to check for D modulo P-1 + * \param QP MPI to check for the modular inverse of Q modulo P. + * + * \return + * - 0 if the following conditions are satisfied: + * - D = DP mod P-1 if P, D, DP != NULL + * - Q = DQ mod P-1 if P, D, DQ != NULL + * - QP = Q^-1 mod P if P, Q, QP != NULL + * - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed, + * potentially including \c MBEDTLS_ERR_MPI_XXX if some + * MPI calculations failed. + * - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient + * data was provided to check DP, DQ or QP. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with the + * parameters (P, -, D, DP, -, -) will check DP = D mod P-1. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ); + +#ifdef __cplusplus +} +#endif + +#endif /* rsa_internal.h */ diff --git a/external/mbedtls/include/mbedtls/sha1.h b/external/mbedtls/include/mbedtls/sha1.h new file mode 100644 index 0000000..60c514a --- /dev/null +++ b/external/mbedtls/include/mbedtls/sha1.h @@ -0,0 +1,377 @@ +/** + * \file sha1.h + * + * \brief This file contains SHA-1 definitions and functions. + * + * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in + * FIPS 180-4: Secure Hash Standard (SHS). + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SHA1_H +#define MBEDTLS_SHA1_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA -0x0073 /**< SHA-1 input data was malformed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// + +/** + * \brief The SHA-1 context structure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_sha1_context +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[5]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ +} +mbedtls_sha1_context; + +#else /* MBEDTLS_SHA1_ALT */ +#include "sha1_alt.h" +#endif /* MBEDTLS_SHA1_ALT */ + +/** + * \brief This function initializes a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. + * This must not be \c NULL. + * + */ +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clears a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to clear. This may be \c NULL, + * in which case this function does nothing. If it is + * not \c NULL, it must point to an initialized + * SHA-1 context. + * + */ +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clones the state of a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param dst The SHA-1 context to clone to. This must be initialized. + * \param src The SHA-1 context to clone from. This must be initialized. + * + */ +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ); + +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. This must be initialized. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized. + * \param data The data block being processed. This must be a + * readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0. + * + * \param ctx The SHA-1 context to initialize. This must be initialized. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized and + * have a hash operation started. + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized. + * \param data The data block being processed. + * This must be a readable buffer of length \c 64 bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0 + * + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of size \c 20 Bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The SHA-1 checkup routine. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \return \c 0 on success. + * \return \c 1 on failure. + * + */ +int mbedtls_sha1_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha1.h */ diff --git a/external/mbedtls/include/mbedtls/sha256.h b/external/mbedtls/include/mbedtls/sha256.h new file mode 100644 index 0000000..b1881e1 --- /dev/null +++ b/external/mbedtls/include/mbedtls/sha256.h @@ -0,0 +1,322 @@ +/** + * \file sha256.h + * + * \brief This file contains SHA-224 and SHA-256 definitions and functions. + * + * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SHA256_H +#define MBEDTLS_SHA256_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 /**< SHA-256 input data was malformed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + +/** + * \brief The SHA-256 context structure. + * + * The structure is used both for SHA-256 and for SHA-224 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha256_starts_ret(). + */ +typedef struct mbedtls_sha256_context +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ + int is224; /*!< Determines which function to use: + 0: Use SHA-256, or 1: Use SHA-224. */ +} +mbedtls_sha256_context; + +#else /* MBEDTLS_SHA256_ALT */ +#include "sha256_alt.h" +#endif /* MBEDTLS_SHA256_ALT */ + +/** + * \brief This function initializes a SHA-256 context. + * + * \param ctx The SHA-256 context to initialize. This must not be \c NULL. + */ +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clears a SHA-256 context. + * + * \param ctx The SHA-256 context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized SHA-256 context. + */ +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clones the state of a SHA-256 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ); + +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \param ctx The context to use. This must be initialized. + * \param is224 This determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. + * This must be a writable buffer of length \c 32 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must + * be a readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. + * + * \param ctx The context to use. This must be initialized. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0. + * + * \param ctx The SHA-256 context to use. This must be + * initialized and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. + * + * \param ctx The SHA-256 context. This must be initialized and + * have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. This must be + * a writable buffer of length \c 32 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0. + * + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must be + * a readable buffer of size \c 64 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-224 or SHA-256 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. This must + * be a writable buffer of length \c 32 Bytes. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function calculates the SHA-224 or SHA-256 checksum + * of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0. + * + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. This must be + * a writable buffer of length \c 32 Bytes. + * \param is224 Determines which function to use. This must be either + * \c 0 for SHA-256, or \c 1 for SHA-224. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The SHA-224 and SHA-256 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha256_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha256.h */ diff --git a/external/mbedtls/include/mbedtls/sha512.h b/external/mbedtls/include/mbedtls/sha512.h new file mode 100644 index 0000000..5e5a15e --- /dev/null +++ b/external/mbedtls/include/mbedtls/sha512.h @@ -0,0 +1,325 @@ +/** + * \file sha512.h + * \brief This file contains SHA-384 and SHA-512 definitions and functions. + * + * The Secure Hash Algorithms 384 and 512 (SHA-384 and SHA-512) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SHA512_H +#define MBEDTLS_SHA512_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /**< SHA-512 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA -0x0075 /**< SHA-512 input data was malformed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA512_ALT) +// Regular implementation +// + +/** + * \brief The SHA-512 context structure. + * + * The structure is used both for SHA-384 and for SHA-512 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha512_starts_ret(). + */ +typedef struct mbedtls_sha512_context +{ + uint64_t total[2]; /*!< The number of Bytes processed. */ + uint64_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[128]; /*!< The data block being processed. */ + int is384; /*!< Determines which function to use: + 0: Use SHA-512, or 1: Use SHA-384. */ +} +mbedtls_sha512_context; + +#else /* MBEDTLS_SHA512_ALT */ +#include "sha512_alt.h" +#endif /* MBEDTLS_SHA512_ALT */ + +/** + * \brief This function initializes a SHA-512 context. + * + * \param ctx The SHA-512 context to initialize. This must + * not be \c NULL. + */ +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clears a SHA-512 context. + * + * \param ctx The SHA-512 context to clear. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must point to an initialized + * SHA-512 context. + */ +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clones the state of a SHA-512 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ); + +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \param ctx The SHA-512 context to use. This must be initialized. + * \param is384 Determines which function to use. This must be + * either \c for SHA-512, or \c 1 for SHA-384. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. + * This function is for internal use only. + * + * \param ctx The SHA-512 context. This must be initialized. + * \param data The buffer holding one block of data. This + * must be a readable buffer of length \c 128 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ); +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha512_starts_ret() in 2.7.0 + * + * \param ctx The SHA-512 context to use. This must be initialized. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512 or \c 1 for SHA-384. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-384 or SHA-512 checksum result. This must + * be a writable buffer of size \c 64 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized. + * \param data The buffer holding one block of data. This must be + * a readable buffer of length \c 128 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_process( + mbedtls_sha512_context *ctx, + const unsigned char data[128] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \param input The buffer holding the input data. This must be + * a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 Bytes. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \deprecated Superseded by mbedtls_sha512_ret() in 2.7.0 + * + * \param input The buffer holding the data. This must be a + * readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-384 or SHA-512 checksum result. This must + * be a writable buffer of length \c 64 Bytes. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + + /** + * \brief The SHA-384 or SHA-512 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha512_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha512.h */ diff --git a/external/mbedtls/include/mbedtls/ssl.h b/external/mbedtls/include/mbedtls/ssl.h new file mode 100644 index 0000000..fe33ac8 --- /dev/null +++ b/external/mbedtls/include/mbedtls/ssl.h @@ -0,0 +1,3291 @@ +/** + * \file ssl.h + * + * \brief SSL/TLS functions. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SSL_H +#define MBEDTLS_SSL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" +#include "ecp.h" + +#include "ssl_ciphersuites.h" + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "x509_crt.h" +#include "x509_crl.h" +#endif + +#if defined(MBEDTLS_DHM_C) +#include "dhm.h" +#endif + +#if defined(MBEDTLS_ECDH_C) +#include "ecdh.h" +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and will be removed in the next major revision of the library" +#endif + +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and cannot be used if MBEDTLS_DEPRECATED_REMOVED is set" +#endif + +#include "zlib.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "platform_time.h" +#endif + +/* + * SSL Error codes + */ +#define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */ +#define MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */ +#define MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */ +#define MBEDTLS_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */ +#define MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */ +#define MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */ +#define MBEDTLS_ERR_SSL_NO_RNG -0x7400 /**< No RNG was provided to the SSL module. */ +#define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */ +#define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key or pre-shared key is not set, but needed. */ +#define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */ +#define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */ +#define MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */ +#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */ +#define MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00 /**< Memory allocation failed */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /**< Hardware acceleration function returned with error */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /**< Hardware acceleration function skipped / left alone data */ +#define MBEDTLS_ERR_SSL_COMPRESSION_FAILED -0x6F00 /**< Processing of the compression / decompression failed */ +#define MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 /**< Handshake protocol not within min/max boundaries */ +#define MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 /**< Processing of the NewSessionTicket handshake message failed. */ +#define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /**< Session ticket has expired. */ +#define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ +#define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /**< Unknown identity received (eg, PSK identity) */ +#define MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00 /**< Internal error (eg, unexpected failure in lower-level module) */ +#define MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80 /**< A counter would wrap (eg, too many messages exchanged). */ +#define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 /**< Unexpected message at ServerHello in renegotiation. */ +#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /**< DTLS client must retry for hello verification */ +#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /**< A buffer is too small to receive or write a message */ +#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */ +#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< No data of requested type currently available on underlying transport. */ +#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */ +#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */ +#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */ +#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */ +#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ +#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */ +#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */ +#define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 /**< Internal-only message signaling that a message arrived early. */ +#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 /**< A cryptographic operation is in progress. Try again later. */ +#define MBEDTLS_ERR_SSL_BAD_CONFIG -0x5E80 /**< Invalid value in SSL config */ + +/* + * Various constants + */ +#define MBEDTLS_SSL_MAJOR_VERSION_3 3 +#define MBEDTLS_SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ +#define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ + +#define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ +#define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ + +#define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ +#define MBEDTLS_SSL_MAX_ALPN_NAME_LEN 255 /*!< Maximum size in bytes of a protocol name in alpn ext., RFC 7301 */ + +#define MBEDTLS_SSL_MAX_ALPN_LIST_LEN 65535 /*!< Maximum size in bytes of list in alpn ext., RFC 7301 */ + +/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c + * NONE must be zero so that memset()ing structure to zero works */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ + +#define MBEDTLS_SSL_IS_CLIENT 0 +#define MBEDTLS_SSL_IS_SERVER 1 + +#define MBEDTLS_SSL_IS_NOT_FALLBACK 0 +#define MBEDTLS_SSL_IS_FALLBACK 1 + +#define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 +#define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 + +#define MBEDTLS_SSL_ETM_DISABLED 0 +#define MBEDTLS_SSL_ETM_ENABLED 1 + +#define MBEDTLS_SSL_COMPRESS_NULL 0 +#define MBEDTLS_SSL_COMPRESS_DEFLATE 1 + +#define MBEDTLS_SSL_VERIFY_NONE 0 +#define MBEDTLS_SSL_VERIFY_OPTIONAL 1 +#define MBEDTLS_SSL_VERIFY_REQUIRED 2 +#define MBEDTLS_SSL_VERIFY_UNSET 3 /* Used only for sni_authmode */ + +#define MBEDTLS_SSL_LEGACY_RENEGOTIATION 0 +#define MBEDTLS_SSL_SECURE_RENEGOTIATION 1 + +#define MBEDTLS_SSL_RENEGOTIATION_DISABLED 0 +#define MBEDTLS_SSL_RENEGOTIATION_ENABLED 1 + +#define MBEDTLS_SSL_ANTI_REPLAY_DISABLED 0 +#define MBEDTLS_SSL_ANTI_REPLAY_ENABLED 1 + +#define MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -1 +#define MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT 16 + +#define MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION 0 +#define MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION 1 +#define MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE 2 + +#define MBEDTLS_SSL_TRUNC_HMAC_DISABLED 0 +#define MBEDTLS_SSL_TRUNC_HMAC_ENABLED 1 +#define MBEDTLS_SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ + +#define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0 +#define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1 + +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED 0 +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED 1 + +#define MBEDTLS_SSL_ARC4_ENABLED 0 +#define MBEDTLS_SSL_ARC4_DISABLED 1 + +#define MBEDTLS_SSL_PRESET_DEFAULT 0 +#define MBEDTLS_SSL_PRESET_SUITEB 2 + +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1 +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0 + +/* + * Default range for DTLS retransmission timer value, in milliseconds. + * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. + */ +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN 1000 +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX 60000 + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME) +#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +#endif + +/* + * Maximum fragment length in bytes, + * determines the size of each of the two internal I/O buffers. + * + * Note: the RFC defines the default size of SSL / TLS messages. If you + * change the value here, other clients / servers may not be able to + * communicate with you anymore. Only change this value if you control + * both sides of the connection and have it reduced at both sides, or + * if you're using the Max Fragment Length extension and you know all your + * peers are using it too! + */ +#if !defined(MBEDTLS_SSL_MAX_CONTENT_LEN) +#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ +#endif + +#if !defined(MBEDTLS_SSL_IN_CONTENT_LEN) +#define MBEDTLS_SSL_IN_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#endif + +#if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN) +#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#endif + +/* + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + */ +#if !defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING) +#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 +#endif + +/* \} name SECTION: Module settings */ + +/* + * Length of the verify data for secure renegotiation + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 36 +#else +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 +#endif + +/* + * Signaling ciphersuite values (SCSV) + */ +#define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ +#define MBEDTLS_SSL_FALLBACK_SCSV_VALUE 0x5600 /**< RFC 7507 section 2 */ + +/* + * Supported Signature and Hash algorithms (For TLS 1.2) + * RFC 5246 section 7.4.1.4.1 + */ +#define MBEDTLS_SSL_HASH_NONE 0 +#define MBEDTLS_SSL_HASH_MD5 1 +#define MBEDTLS_SSL_HASH_SHA1 2 +#define MBEDTLS_SSL_HASH_SHA224 3 +#define MBEDTLS_SSL_HASH_SHA256 4 +#define MBEDTLS_SSL_HASH_SHA384 5 +#define MBEDTLS_SSL_HASH_SHA512 6 + +#define MBEDTLS_SSL_SIG_ANON 0 +#define MBEDTLS_SSL_SIG_RSA 1 +#define MBEDTLS_SSL_SIG_ECDSA 3 + +/* + * Client Certificate Types + * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 + */ +#define MBEDTLS_SSL_CERT_TYPE_RSA_SIGN 1 +#define MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN 64 + +/* + * Message, alert and handshake types + */ +#define MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC 20 +#define MBEDTLS_SSL_MSG_ALERT 21 +#define MBEDTLS_SSL_MSG_HANDSHAKE 22 +#define MBEDTLS_SSL_MSG_APPLICATION_DATA 23 + +#define MBEDTLS_SSL_ALERT_LEVEL_WARNING 1 +#define MBEDTLS_SSL_ALERT_LEVEL_FATAL 2 + +#define MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ +#define MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ +#define MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ +#define MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ +#define MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ +#define MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ +#define MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ +#define MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ +#define MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ +#define MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ +#define MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ +#define MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ +#define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ +#define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ +#define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ +#define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ + +#define MBEDTLS_SSL_HS_HELLO_REQUEST 0 +#define MBEDTLS_SSL_HS_CLIENT_HELLO 1 +#define MBEDTLS_SSL_HS_SERVER_HELLO 2 +#define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 +#define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 +#define MBEDTLS_SSL_HS_CERTIFICATE 11 +#define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 +#define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 +#define MBEDTLS_SSL_HS_SERVER_HELLO_DONE 14 +#define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY 15 +#define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE 16 +#define MBEDTLS_SSL_HS_FINISHED 20 + +/* + * TLS extensions + */ +#define MBEDTLS_TLS_EXT_SERVERNAME 0 +#define MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME 0 + +#define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH 1 + +#define MBEDTLS_TLS_EXT_TRUNCATED_HMAC 4 + +#define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 + +#define MBEDTLS_TLS_EXT_SIG_ALG 13 + +#define MBEDTLS_TLS_EXT_ALPN 16 + +#define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ +#define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ + +#define MBEDTLS_TLS_EXT_SESSION_TICKET 35 + +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ + +#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 + +/* + * Size defines + */ +#if !defined(MBEDTLS_PSK_MAX_LEN) +#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ +#endif + +/* Dummy type used only for its size */ +union mbedtls_ssl_premaster_secret +{ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + unsigned char _pms_dhm[MBEDTLS_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + unsigned char _pms_psk[4 + 2 * MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + unsigned char _pms_dhe_psk[4 + MBEDTLS_MPI_MAX_SIZE + + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 3 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + unsigned char _pms_rsa_psk[52 + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 4 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + unsigned char _pms_ecdhe_psk[4 + MBEDTLS_ECP_MAX_BYTES + + MBEDTLS_PSK_MAX_LEN]; /* RFC 5489 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + unsigned char _pms_ecjpake[32]; /* Thread spec: SHA-256 output */ +#endif +}; + +#define MBEDTLS_PREMASTER_SIZE sizeof( union mbedtls_ssl_premaster_secret ) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SSL state machine + */ +typedef enum +{ + MBEDTLS_SSL_HELLO_REQUEST, + MBEDTLS_SSL_CLIENT_HELLO, + MBEDTLS_SSL_SERVER_HELLO, + MBEDTLS_SSL_SERVER_CERTIFICATE, + MBEDTLS_SSL_SERVER_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_REQUEST, + MBEDTLS_SSL_SERVER_HELLO_DONE, + MBEDTLS_SSL_CLIENT_CERTIFICATE, + MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_VERIFY, + MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_CLIENT_FINISHED, + MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_SERVER_FINISHED, + MBEDTLS_SSL_FLUSH_BUFFERS, + MBEDTLS_SSL_HANDSHAKE_WRAPUP, + MBEDTLS_SSL_HANDSHAKE_OVER, + MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET, + MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, +} +mbedtls_ssl_states; + +/** + * \brief Callback type: send data on the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the send callback (typically a file descriptor) + * \param buf Buffer holding the data to send + * \param len Length of the data to send + * + * \return The callback must return the number of bytes sent if any, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE + * must be returned when the operation would block. + * + * \note The callback is allowed to send fewer bytes than requested. + * It must always return the number of bytes actually sent. + */ +typedef int mbedtls_ssl_send_t( void *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the receive callback (typically a file + * descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * + * \return The callback must return the number of bytes received, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ + * must be returned when the operation would block. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_t( void *ctx, + unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network, with timeout + * + * \note That callback must block until data is received, or the + * timeout delay expires, or the operation is interrupted by a + * signal. + * + * \param ctx Context for the receive callback (typically a file descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * \param timeout Maximum nomber of millisecondes to wait for data + * 0 means no timeout (potentially waiting forever) + * + * \return The callback must return the number of bytes received, + * or a non-zero error code: + * \c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * \c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_timeout_t( void *ctx, + unsigned char *buf, + size_t len, + uint32_t timeout ); +/** + * \brief Callback type: set a pair of timers/delays to watch + * + * \param ctx Context pointer + * \param int_ms Intermediate delay in milliseconds + * \param fin_ms Final delay in milliseconds + * 0 cancels the current timer. + * + * \note This callback must at least store the necessary information + * for the associated \c mbedtls_ssl_get_timer_t callback to + * return correct information. + * + * \note If using a event-driven style of programming, an event must + * be generated when the final delay is passed. The event must + * cause a call to \c mbedtls_ssl_handshake() with the proper + * SSL context to be scheduled. Care must be taken to ensure + * that at most one such call happens at a time. + * + * \note Only one timer at a time must be running. Calling this + * function while a timer is running must cancel it. Cancelled + * timers must not generate any event. + */ +typedef void mbedtls_ssl_set_timer_t( void * ctx, + uint32_t int_ms, + uint32_t fin_ms ); + +/** + * \brief Callback type: get status of timers/delays + * + * \param ctx Context pointer + * + * \return This callback must return: + * -1 if cancelled (fin_ms == 0), + * 0 if none of the delays have passed, + * 1 if only the intermediate delay has passed, + * 2 if the final delay has passed. + */ +typedef int mbedtls_ssl_get_timer_t( void * ctx ); + +/* Defined below */ +typedef struct mbedtls_ssl_session mbedtls_ssl_session; +typedef struct mbedtls_ssl_context mbedtls_ssl_context; +typedef struct mbedtls_ssl_config mbedtls_ssl_config; + +/* Defined in ssl_internal.h */ +typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; +typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; +typedef struct mbedtls_ssl_sig_hash_set_t mbedtls_ssl_sig_hash_set_t; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) +typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; +#endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Callback type: start external signature operation. + * + * This callback is called during an SSL handshake to start + * a signature decryption operation using an + * external processor. The parameter \p cert contains + * the public key; it is up to the callback function to + * determine how to access the associated private key. + * + * This function typically sends or enqueues a request, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * The parameters \p ssl and \p cert are guaranteed to remain + * valid throughout the handshake. On the other hand, this + * function must save the contents of \p hash if the value + * is needed for later processing, because the \p hash buffer + * is no longer valid after this function returns. + * + * This function may call mbedtls_ssl_set_async_operation_data() + * to store an operation context for later retrieval + * by the resume or cancel callback. + * + * \note For RSA signatures, this function must produce output + * that is consistent with PKCS#1 v1.5 in the same way as + * mbedtls_rsa_pkcs1_sign(). Before the private key operation, + * apply the padding steps described in RFC 8017, section 9.2 + * "EMSA-PKCS1-v1_5" as follows. + * - If \p md_alg is #MBEDTLS_MD_NONE, apply the PKCS#1 v1.5 + * encoding, treating \p hash as the DigestInfo to be + * padded. In other words, apply EMSA-PKCS1-v1_5 starting + * from step 3, with `T = hash` and `tLen = hash_len`. + * - If `md_alg != MBEDTLS_MD_NONE`, apply the PKCS#1 v1.5 + * encoding, treating \p hash as the hash to be encoded and + * padded. In other words, apply EMSA-PKCS1-v1_5 starting + * from step 2, with `digestAlgorithm` obtained by calling + * mbedtls_oid_get_oid_by_md() on \p md_alg. + * + * \note For ECDSA signatures, the output format is the DER encoding + * `Ecdsa-Sig-Value` defined in + * [RFC 4492 section 5.4](https://tools.ietf.org/html/rfc4492#section-5.4). + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param cert Certificate containing the public key. + * In simple cases, this is one of the pointers passed to + * mbedtls_ssl_conf_own_cert() when configuring the SSL + * connection. However, if other callbacks are used, this + * property may not hold. For example, if an SNI callback + * is registered with mbedtls_ssl_conf_sni(), then + * this callback determines what certificate is used. + * \param md_alg Hash algorithm. + * \param hash Buffer containing the hash. This buffer is + * no longer valid when the function returns. + * \param hash_len Size of the \c hash buffer in bytes. + * + * \return 0 if the operation was started successfully and the SSL + * stack should call the resume callback immediately. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * was started successfully and the SSL stack should return + * immediately without calling the resume callback yet. + * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the private key object instead. + * \return Any other error indicates a fatal failure and is + * propagated up the call chain. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_sign_t( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + mbedtls_md_type_t md_alg, + const unsigned char *hash, + size_t hash_len ); + +/** + * \brief Callback type: start external decryption operation. + * + * This callback is called during an SSL handshake to start + * an RSA decryption operation using an + * external processor. The parameter \p cert contains + * the public key; it is up to the callback function to + * determine how to access the associated private key. + * + * This function typically sends or enqueues a request, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * The parameters \p ssl and \p cert are guaranteed to remain + * valid throughout the handshake. On the other hand, this + * function must save the contents of \p input if the value + * is needed for later processing, because the \p input buffer + * is no longer valid after this function returns. + * + * This function may call mbedtls_ssl_set_async_operation_data() + * to store an operation context for later retrieval + * by the resume or cancel callback. + * + * \warning RSA decryption as used in TLS is subject to a potential + * timing side channel attack first discovered by Bleichenbacher + * in 1998. This attack can be remotely exploitable + * in practice. To avoid this attack, you must ensure that + * if the callback performs an RSA decryption, the time it + * takes to execute and return the result does not depend + * on whether the RSA decryption succeeded or reported + * invalid padding. + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param cert Certificate containing the public key. + * In simple cases, this is one of the pointers passed to + * mbedtls_ssl_conf_own_cert() when configuring the SSL + * connection. However, if other callbacks are used, this + * property may not hold. For example, if an SNI callback + * is registered with mbedtls_ssl_conf_sni(), then + * this callback determines what certificate is used. + * \param input Buffer containing the input ciphertext. This buffer + * is no longer valid when the function returns. + * \param input_len Size of the \p input buffer in bytes. + * + * \return 0 if the operation was started successfully and the SSL + * stack should call the resume callback immediately. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * was started successfully and the SSL stack should return + * immediately without calling the resume callback yet. + * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the private key object instead. + * \return Any other error indicates a fatal failure and is + * propagated up the call chain. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_decrypt_t( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + const unsigned char *input, + size_t input_len ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Callback type: resume external operation. + * + * This callback is called during an SSL handshake to resume + * an external operation started by the + * ::mbedtls_ssl_async_sign_t or + * ::mbedtls_ssl_async_decrypt_t callback. + * + * This function typically checks the status of a pending + * request or causes the request queue to make progress, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * This function may call mbedtls_ssl_get_async_operation_data() + * to retrieve an operation context set by the start callback. + * It may call mbedtls_ssl_set_async_operation_data() to modify + * this context. + * + * Note that when this function returns a status other than + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, it must free any + * resources associated with the operation. + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param output Buffer containing the output (signature or decrypted + * data) on success. + * \param output_len On success, number of bytes written to \p output. + * \param output_size Size of the \p output buffer in bytes. + * + * \return 0 if output of the operation is available in the + * \p output buffer. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * is still in progress. Subsequent requests for progress + * on the SSL connection will call the resume callback + * again. + * \return Any other error means that the operation is aborted. + * The SSL handshake is aborted. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_resume_t( mbedtls_ssl_context *ssl, + unsigned char *output, + size_t *output_len, + size_t output_size ); + +/** + * \brief Callback type: cancel external operation. + * + * This callback is called if an SSL connection is closed + * while an asynchronous operation is in progress. Note that + * this callback is not called if the + * ::mbedtls_ssl_async_resume_t callback has run and has + * returned a value other than + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, since in that case + * the asynchronous operation has already completed. + * + * This function may call mbedtls_ssl_get_async_operation_data() + * to retrieve an operation context set by the start callback. + * + * \param ssl The SSL connection instance. It should not be + * modified. + */ +typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +/* + * This structure is used for storing current session data. + */ +struct mbedtls_ssl_session +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t start; /*!< starting time */ +#endif + int ciphersuite; /*!< chosen ciphersuite */ + int compression; /*!< chosen compression */ + size_t id_len; /*!< session id length */ + unsigned char id[32]; /*!< session identifier */ + unsigned char master[48]; /*!< the master secret */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + uint32_t verify_result; /*!< verification result */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + unsigned char *ticket; /*!< RFC 5077 session ticket */ + size_t ticket_len; /*!< session ticket length */ + uint32_t ticket_lifetime; /*!< ticket lifetime hint */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */ +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + int trunc_hmac; /*!< flag for truncated hmac activation */ +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac; /*!< flag for EtM activation */ +#endif +}; + +/** + * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. + */ +struct mbedtls_ssl_config +{ + /* Group items by size (largest first) to minimize padding overhead */ + + /* + * Pointers + */ + + const int *ciphersuite_list[4]; /*!< allowed ciphersuites per version */ + + /** Callback for printing debug output */ + void (*f_dbg)(void *, int, const char *, int, const char *); + void *p_dbg; /*!< context for the debug function */ + + /** Callback for getting (pseudo-)random numbers */ + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; /*!< context for the RNG function */ + + /** Callback to retrieve a session from the cache */ + int (*f_get_cache)(void *, mbedtls_ssl_session *); + /** Callback to store a session into the cache */ + int (*f_set_cache)(void *, const mbedtls_ssl_session *); + void *p_cache; /*!< context for cache callbacks */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /** Callback for setting cert according to SNI extension */ + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *p_sni; /*!< context for SNI callback */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /** Callback to customize X.509 certificate chain verification */ + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); + void *p_vrfy; /*!< context for X.509 verify calllback */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + /** Callback to retrieve PSK key from identity */ + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *p_psk; /*!< context for PSK callback */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a cookie for ClientHello veirifcation */ + int (*f_cookie_write)( void *, unsigned char **, unsigned char *, + const unsigned char *, size_t ); + /** Callback to verify validity of a ClientHello cookie */ + int (*f_cookie_check)( void *, const unsigned char *, size_t, + const unsigned char *, size_t ); + void *p_cookie; /*!< context for the cookie callbacks */ +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a session ticket */ + int (*f_ticket_write)( void *, const mbedtls_ssl_session *, + unsigned char *, const unsigned char *, size_t *, uint32_t * ); + /** Callback to parse a session ticket into a session structure */ + int (*f_ticket_parse)( void *, mbedtls_ssl_session *, unsigned char *, size_t); + void *p_ticket; /*!< context for the ticket callbacks */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + /** Callback to export key block and master secret */ + int (*f_export_keys)( void *, const unsigned char *, + const unsigned char *, size_t, size_t, size_t ); + void *p_export_keys; /*!< context for key export callback */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + const mbedtls_x509_crt_profile *cert_profile; /*!< verification profile */ + mbedtls_ssl_key_cert *key_cert; /*!< own certificate/key pair(s) */ + mbedtls_x509_crt *ca_chain; /*!< trusted CAs */ + mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_async_sign_t *f_async_sign_start; /*!< start asynchronous signature operation */ + mbedtls_ssl_async_decrypt_t *f_async_decrypt_start; /*!< start asynchronous decryption operation */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + mbedtls_ssl_async_resume_t *f_async_resume; /*!< resume asynchronous operation */ + mbedtls_ssl_async_cancel_t *f_async_cancel; /*!< cancel asynchronous operation */ + void *p_async_config_data; /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + const int *sig_hashes; /*!< allowed signature hashes */ +#endif + +#if defined(MBEDTLS_ECP_C) + const mbedtls_ecp_group_id *curve_list; /*!< allowed curves */ +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi dhm_P; /*!< prime modulus for DHM */ + mbedtls_mpi dhm_G; /*!< generator for DHM */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + unsigned char *psk; /*!< pre-shared key. This field should + only be set via + mbedtls_ssl_conf_psk() */ + size_t psk_len; /*!< length of the pre-shared key. This + field should only be set via + mbedtls_ssl_conf_psk() */ + unsigned char *psk_identity; /*!< identity for PSK negotiation. This + field should only be set via + mbedtls_ssl_conf_psk() */ + size_t psk_identity_len;/*!< length of identity. This field should + only be set via + mbedtls_ssl_conf_psk() */ +#endif + +#if defined(MBEDTLS_SSL_ALPN) + const char **alpn_list; /*!< ordered list of protocols */ +#endif + + /* + * Numerical settings (int then char) + */ + + uint32_t read_timeout; /*!< timeout for mbedtls_ssl_read (ms) */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint32_t hs_timeout_min; /*!< initial value of the handshake + retransmission timeout (ms) */ + uint32_t hs_timeout_max; /*!< maximum value of the handshake + retransmission timeout (ms) */ +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_max_records; /*!< grace period for renegotiation */ + unsigned char renego_period[8]; /*!< value of the record counters + that triggers renegotiation */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + unsigned int badmac_limit; /*!< limit of records with a bad MAC */ +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + unsigned int dhm_min_bitlen; /*!< min. bit length of the DHM prime */ +#endif + + unsigned char max_major_ver; /*!< max. major version used */ + unsigned char max_minor_ver; /*!< max. minor version used */ + unsigned char min_major_ver; /*!< min. major version used */ + unsigned char min_minor_ver; /*!< min. minor version used */ + + /* + * Flags (bitfields) + */ + + unsigned int endpoint : 1; /*!< 0: client, 1: server */ + unsigned int transport : 1; /*!< stream (TLS) or datagram (DTLS) */ + unsigned int authmode : 2; /*!< MBEDTLS_SSL_VERIFY_XXX */ + /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ + unsigned int allow_legacy_renegotiation : 2 ; /*!< MBEDTLS_LEGACY_XXX */ +#if defined(MBEDTLS_ARC4_C) + unsigned int arc4_disabled : 1; /*!< blacklist RC4 ciphersuites? */ +#endif +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + unsigned int mfl_code : 3; /*!< desired fragment length */ +#endif +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + unsigned int encrypt_then_mac : 1 ; /*!< negotiate encrypt-then-mac? */ +#endif +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + unsigned int extended_ms : 1; /*!< negotiate extended master secret? */ +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + unsigned int anti_replay : 1; /*!< detect and prevent replay? */ +#endif +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + unsigned int cbc_record_splitting : 1; /*!< do cbc record splitting */ +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + unsigned int disable_renegotiation : 1; /*!< disable renegotiation? */ +#endif +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + unsigned int trunc_hmac : 1; /*!< negotiate truncated hmac? */ +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + unsigned int session_tickets : 1; /*!< use session tickets? */ +#endif +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) + unsigned int fallback : 1; /*!< is this a fallback? */ +#endif +#if defined(MBEDTLS_SSL_SRV_C) + unsigned int cert_req_ca_list : 1; /*!< enable sending CA list in + Certificate Request messages? */ +#endif +}; + + +struct mbedtls_ssl_context +{ + const mbedtls_ssl_config *conf; /*!< configuration information */ + + /* + * Miscellaneous + */ + int state; /*!< SSL handshake: current state */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_status; /*!< Initial, in progress, pending? */ + int renego_records_seen; /*!< Records since renego request, or with DTLS, + number of retransmissions of request if + renego_max_records is < 0 */ +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */ + int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + unsigned badmac_seen; /*!< records with a bad MAC received */ +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + + mbedtls_ssl_send_t *f_send; /*!< Callback for network send */ + mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */ + mbedtls_ssl_recv_timeout_t *f_recv_timeout; + /*!< Callback for network receive with timeout */ + + void *p_bio; /*!< context for I/O operations */ + + /* + * Session layer + */ + mbedtls_ssl_session *session_in; /*!< current session data (in) */ + mbedtls_ssl_session *session_out; /*!< current session data (out) */ + mbedtls_ssl_session *session; /*!< negotiated session data */ + mbedtls_ssl_session *session_negotiate; /*!< session data in negotiation */ + + mbedtls_ssl_handshake_params *handshake; /*!< params required only during + the handshake process */ + + /* + * Record layer transformations + */ + mbedtls_ssl_transform *transform_in; /*!< current transform params (in) */ + mbedtls_ssl_transform *transform_out; /*!< current transform params (in) */ + mbedtls_ssl_transform *transform; /*!< negotiated transform params */ + mbedtls_ssl_transform *transform_negotiate; /*!< transform params in negotiation */ + + /* + * Timers + */ + void *p_timer; /*!< context for the timer callbacks */ + + mbedtls_ssl_set_timer_t *f_set_timer; /*!< set timer callback */ + mbedtls_ssl_get_timer_t *f_get_timer; /*!< get timer callback */ + + /* + * Record layer (incoming data) + */ + unsigned char *in_buf; /*!< input buffer */ + unsigned char *in_ctr; /*!< 64-bit incoming message counter + TLS: maintained by us + DTLS: read from peer */ + unsigned char *in_hdr; /*!< start of record header */ + unsigned char *in_len; /*!< two-bytes message length field */ + unsigned char *in_iv; /*!< ivlen-byte IV */ + unsigned char *in_msg; /*!< message contents (in_iv+ivlen) */ + unsigned char *in_offt; /*!< read offset in application data */ + + int in_msgtype; /*!< record header: message type */ + size_t in_msglen; /*!< record header: message length */ + size_t in_left; /*!< amount of data read so far */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t in_epoch; /*!< DTLS epoch for incoming records */ + size_t next_record_offset; /*!< offset of the next record in datagram + (equal to in_left if none) */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + uint64_t in_window_top; /*!< last validated record seq_num */ + uint64_t in_window; /*!< bitmask for replay detection */ +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + + size_t in_hslen; /*!< current handshake message length, + including the handshake header */ + int nb_zero; /*!< # of 0-length encrypted messages */ + + int keep_current_message; /*!< drop or reuse current message + on next call to record layer? */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint8_t disable_datagram_packing; /*!< Disable packing multiple records + * within a single datagram. */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Record layer (outgoing data) + */ + unsigned char *out_buf; /*!< output buffer */ + unsigned char *out_ctr; /*!< 64-bit outgoing message counter */ + unsigned char *out_hdr; /*!< start of record header */ + unsigned char *out_len; /*!< two-bytes message length field */ + unsigned char *out_iv; /*!< ivlen-byte IV */ + unsigned char *out_msg; /*!< message contents (out_iv+ivlen) */ + + int out_msgtype; /*!< record header: message type */ + size_t out_msglen; /*!< record header: message length */ + size_t out_left; /*!< amount of data not yet written */ + + unsigned char cur_out_ctr[8]; /*!< Outgoing record sequence number. */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t mtu; /*!< path mtu, used to fragment outgoing messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_ZLIB_SUPPORT) + unsigned char *compress_buf; /*!< zlib data buffer */ +#endif /* MBEDTLS_ZLIB_SUPPORT */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + signed char split_done; /*!< current record already splitted? */ +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + + /* + * PKI layer + */ + int client_auth; /*!< flag for client auth. */ + + /* + * User settings + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + char *hostname; /*!< expected peer CN for verification + (and SNI if available) */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_ALPN) + const char *alpn_chosen; /*!< negotiated protocol */ +#endif /* MBEDTLS_SSL_ALPN */ + + /* + * Information for DTLS hello verify + */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + unsigned char *cli_id; /*!< transport-level ID of the client */ + size_t cli_id_len; /*!< length of cli_id */ +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + + /* + * Secure renegotiation + */ + /* needed to know when to send extension on server */ + int secure_renegotiation; /*!< does peer support legacy or + secure renegotiation */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + size_t verify_data_len; /*!< length of verify data stored */ + char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ + char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ +#endif /* MBEDTLS_SSL_RENEGOTIATION */ +}; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + +#define MBEDTLS_SSL_CHANNEL_OUTBOUND 0 +#define MBEDTLS_SSL_CHANNEL_INBOUND 1 + +extern int (*mbedtls_ssl_hw_record_init)(mbedtls_ssl_context *ssl, + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen); +extern int (*mbedtls_ssl_hw_record_activate)(mbedtls_ssl_context *ssl, int direction); +extern int (*mbedtls_ssl_hw_record_reset)(mbedtls_ssl_context *ssl); +extern int (*mbedtls_ssl_hw_record_write)(mbedtls_ssl_context *ssl); +extern int (*mbedtls_ssl_hw_record_read)(mbedtls_ssl_context *ssl); +extern int (*mbedtls_ssl_hw_record_finish)(mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +/** + * \brief Return the name of the ciphersuite associated with the + * given ID + * + * \param ciphersuite_id SSL ciphersuite ID + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ); + +/** + * \brief Return the ID of the ciphersuite associated with the + * given name + * + * \param ciphersuite_name SSL ciphersuite name + * + * \return the ID with the ciphersuite or 0 if not found + */ +int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ); + +/** + * \brief Initialize an SSL context + * Just makes the context ready for mbedtls_ssl_setup() or + * mbedtls_ssl_free() + * + * \param ssl SSL context + */ +void mbedtls_ssl_init( mbedtls_ssl_context *ssl ); + +/** + * \brief Set up an SSL context for use + * + * \note No copy of the configuration context is made, it can be + * shared by many mbedtls_ssl_context structures. + * + * \warning The conf structure will be accessed during the session. + * It must not be modified or freed as long as the session + * is active. + * + * \warning This function must be called exactly once per context. + * Calling mbedtls_ssl_setup again is not supported, even + * if no session is active. + * + * \param ssl SSL context + * \param conf SSL configuration to use + * + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED if + * memory allocation failed + */ +int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf ); + +/** + * \brief Reset an already initialized SSL context for re-use + * while retaining application-set variables, function + * pointers and data. + * + * \param ssl SSL context + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED, + MBEDTLS_ERR_SSL_HW_ACCEL_FAILED or + * MBEDTLS_ERR_SSL_COMPRESSION_FAILED + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ); + +/** + * \brief Set the current endpoint type + * + * \param conf SSL configuration + * \param endpoint must be MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + */ +void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ); + +/** + * \brief Set the transport type (TLS or DTLS). + * Default: TLS + * + * \note For DTLS, you must either provide a recv callback that + * doesn't block, or one that handles timeouts, see + * \c mbedtls_ssl_set_bio(). You also need to provide timer + * callbacks with \c mbedtls_ssl_set_timer_cb(). + * + * \param conf SSL configuration + * \param transport transport type: + * MBEDTLS_SSL_TRANSPORT_STREAM for TLS, + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS. + */ +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ); + +/** + * \brief Set the certificate verification mode + * Default: NONE on server, REQUIRED on client + * + * \param conf SSL configuration + * \param authmode can be: + * + * MBEDTLS_SSL_VERIFY_NONE: peer certificate is not checked + * (default on server) + * (insecure on client) + * + * MBEDTLS_SSL_VERIFY_OPTIONAL: peer certificate is checked, however the + * handshake continues even if verification failed; + * mbedtls_ssl_get_verify_result() can be called after the + * handshake is complete. + * + * MBEDTLS_SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, + * handshake is aborted if verification failed. + * (default on client) + * + * \note On client, MBEDTLS_SSL_VERIFY_REQUIRED is the recommended mode. + * With MBEDTLS_SSL_VERIFY_OPTIONAL, the user needs to call mbedtls_ssl_get_verify_result() at + * the right time(s), which may not be obvious, while REQUIRED always perform + * the verification as soon as possible. For example, REQUIRED was protecting + * against the "triple handshake" attack even before it was found. + */ +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the verification callback (Optional). + * + * If set, the verify callback is called for each + * certificate in the chain. For implementation + * information, please see \c mbedtls_x509_crt_verify() + * + * \param conf SSL configuration + * \param f_vrfy verification function + * \param p_vrfy verification parameter + */ +void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Set the random number generator callback + * + * \param conf SSL configuration + * \param f_rng RNG function + * \param p_rng RNG parameter + */ +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set the debug callback + * + * The callback has the following argument: + * void * opaque context for the callback + * int debug level + * const char * file name + * int line number + * const char * message + * + * \param conf SSL configuration + * \param f_dbg debug function + * \param p_dbg debug parameter + */ +void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg ); + +/** + * \brief Set the underlying BIO callbacks for write, read and + * read-with-timeout. + * + * \param ssl SSL context + * \param p_bio parameter (context) shared by BIO callbacks + * \param f_send write callback + * \param f_recv read callback + * \param f_recv_timeout blocking read callback with timeout. + * + * \note One of f_recv or f_recv_timeout can be NULL, in which case + * the other is used. If both are non-NULL, f_recv_timeout is + * used and f_recv is ignored (as if it were NULL). + * + * \note The two most common use cases are: + * - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL + * - blocking I/O, f_recv == NULL, f_recv_timout != NULL + * + * \note For DTLS, you need to provide either a non-NULL + * f_recv_timeout callback, or a f_recv that doesn't block. + * + * \note See the documentations of \c mbedtls_ssl_send_t, + * \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for + * the conventions those callbacks must follow. + * + * \note On some platforms, net_sockets.c provides + * \c mbedtls_net_send(), \c mbedtls_net_recv() and + * \c mbedtls_net_recv_timeout() that are suitable to be used + * here. + */ +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/** + * \brief Set the Maximum Tranport Unit (MTU). + * Special value: 0 means unset (no limit). + * This represents the maximum size of a datagram payload + * handled by the transport layer (usually UDP) as determined + * by the network link and stack. In practice, this controls + * the maximum size datagram the DTLS layer will pass to the + * \c f_send() callback set using \c mbedtls_ssl_set_bio(). + * + * \note The limit on datagram size is converted to a limit on + * record payload by subtracting the current overhead of + * encapsulation and encryption/authentication if any. + * + * \note This can be called at any point during the connection, for + * example when a Path Maximum Transfer Unit (PMTU) + * estimate becomes available from other sources, + * such as lower (or higher) protocol layers. + * + * \note This setting only controls the size of the packets we send, + * and does not restrict the size of the datagrams we're + * willing to receive. Client-side, you can request the + * server to use smaller records with \c + * mbedtls_ssl_conf_max_frag_len(). + * + * \note If both a MTU and a maximum fragment length have been + * configured (or negotiated with the peer), the resulting + * lower limit on record payload (see first note) is used. + * + * \note This can only be used to decrease the maximum size + * of datagrams (hence records, see first note) sent. It + * cannot be used to increase the maximum size of records over + * the limit set by #MBEDTLS_SSL_OUT_CONTENT_LEN. + * + * \note Values lower than the current record layer expansion will + * result in an error when trying to send data. + * + * \note Using record compression together with a non-zero MTU value + * will result in an error when trying to send data. + * + * \param ssl SSL context + * \param mtu Value of the path MTU in bytes + */ +void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/** + * \brief Set the timeout period for mbedtls_ssl_read() + * (Default: no timeout.) + * + * \param conf SSL configuration context + * \param timeout Timeout value in milliseconds. + * Use 0 for no timeout (default). + * + * \note With blocking I/O, this will only work if a non-NULL + * \c f_recv_timeout was set with \c mbedtls_ssl_set_bio(). + * With non-blocking I/O, this will only work if timer + * callbacks were set with \c mbedtls_ssl_set_timer_cb(). + * + * \note With non-blocking I/O, you may also skip this function + * altogether and handle timeouts at the application layer. + */ +void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ); + +/** + * \brief Set the timer callbacks (Mandatory for DTLS.) + * + * \param ssl SSL context + * \param p_timer parameter (context) shared by timer callbacks + * \param f_set_timer set timer callback + * \param f_get_timer get timer callback. Must return: + * + * \note See the documentation of \c mbedtls_ssl_set_timer_t and + * \c mbedtls_ssl_get_timer_t for the conventions this pair of + * callbacks must follow. + * + * \note On some platforms, timing.c provides + * \c mbedtls_timing_set_delay() and + * \c mbedtls_timing_get_delay() that are suitable for using + * here, except if using an event-driven style. + * + * \note See also the "DTLS tutorial" article in our knowledge base. + * https://tls.mbed.org/kb/how-to/dtls-tutorial + */ +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer ); + +/** + * \brief Callback type: generate and write session ticket + * + * \note This describes what a callback implementation should do. + * This callback should generate an encrypted and + * authenticated ticket for the session and write it to the + * output buffer. Here, ticket means the opaque ticket part + * of the NewSessionTicket structure of RFC 5077. + * + * \param p_ticket Context for the callback + * \param session SSL session to be written in the ticket + * \param start Start of the output buffer + * \param end End of the output buffer + * \param tlen On exit, holds the length written + * \param lifetime On exit, holds the lifetime of the ticket in seconds + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_ticket_write_t( void *p_ticket, + const mbedtls_ssl_session *session, + unsigned char *start, + const unsigned char *end, + size_t *tlen, + uint32_t *lifetime ); + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +/** + * \brief Callback type: Export key block and master secret + * + * \note This is required for certain uses of TLS, e.g. EAP-TLS + * (RFC 5216) and Thread. The key pointers are ephemeral and + * therefore must not be stored. The master secret and keys + * should not be used directly except as an input to a key + * derivation function. + * + * \param p_expkey Context for the callback + * \param ms Pointer to master secret (fixed length: 48 bytes) + * \param kb Pointer to key block, see RFC 5246 section 6.3 + * (variable length: 2 * maclen + 2 * keylen + 2 * ivlen). + * \param maclen MAC length + * \param keylen Key length + * \param ivlen IV length + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_export_keys_t( void *p_expkey, + const unsigned char *ms, + const unsigned char *kb, + size_t maclen, + size_t keylen, + size_t ivlen ); +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +/** + * \brief Callback type: parse and load session ticket + * + * \note This describes what a callback implementation should do. + * This callback should parse a session ticket as generated + * by the corresponding mbedtls_ssl_ticket_write_t function, + * and, if the ticket is authentic and valid, load the + * session. + * + * \note The implementation is allowed to modify the first len + * bytes of the input buffer, eg to use it as a temporary + * area for the decrypted ticket contents. + * + * \param p_ticket Context for the callback + * \param session SSL session to be loaded + * \param buf Start of the buffer containing the ticket + * \param len Length of the ticket. + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_INVALID_MAC if not authentic, or + * MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED if expired, or + * any other non-zero code for other failures. + */ +typedef int mbedtls_ssl_ticket_parse_t( void *p_ticket, + mbedtls_ssl_session *session, + unsigned char *buf, + size_t len ); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Configure SSL session ticket callbacks (server only). + * (Default: none.) + * + * \note On server, session tickets are enabled by providing + * non-NULL callbacks. + * + * \note On client, use \c mbedtls_ssl_conf_session_tickets(). + * + * \param conf SSL configuration context + * \param f_ticket_write Callback for writing a ticket + * \param f_ticket_parse Callback for parsing a ticket + * \param p_ticket Context shared by the two callbacks + */ +void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +/** + * \brief Configure key export callback. + * (Default: none.) + * + * \note See \c mbedtls_ssl_export_keys_t. + * + * \param conf SSL configuration context + * \param f_export_keys Callback for exporting keys + * \param p_export_keys Context for the callback + */ +void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ); +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +/** + * \brief Configure asynchronous private key operation callbacks. + * + * \param conf SSL configuration context + * \param f_async_sign Callback to start a signature operation. See + * the description of ::mbedtls_ssl_async_sign_t + * for more information. This may be \c NULL if the + * external processor does not support any signature + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_decrypt Callback to start a decryption operation. See + * the description of ::mbedtls_ssl_async_decrypt_t + * for more information. This may be \c NULL if the + * external processor does not support any decryption + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_resume Callback to resume an asynchronous operation. See + * the description of ::mbedtls_ssl_async_resume_t + * for more information. This may not be \c NULL unless + * \p f_async_sign and \p f_async_decrypt are both + * \c NULL. + * \param f_async_cancel Callback to cancel an asynchronous operation. See + * the description of ::mbedtls_ssl_async_cancel_t + * for more information. This may be \c NULL if + * no cleanup is needed. + * \param config_data A pointer to configuration data which can be + * retrieved with + * mbedtls_ssl_conf_get_async_config_data(). The + * library stores this value without dereferencing it. + */ +void mbedtls_ssl_conf_async_private_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *config_data ); + +/** + * \brief Retrieve the configuration data set by + * mbedtls_ssl_conf_async_private_cb(). + * + * \param conf SSL configuration context + * \return The configuration data set by + * mbedtls_ssl_conf_async_private_cb(). + */ +void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ); + +/** + * \brief Retrieve the asynchronous operation user context. + * + * \note This function may only be called while a handshake + * is in progress. + * + * \param ssl The SSL context to access. + * + * \return The asynchronous operation user context that was last + * set during the current handshake. If + * mbedtls_ssl_set_async_operation_data() has not yet been + * called during the current handshake, this function returns + * \c NULL. + */ +void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ); + +/** + * \brief Retrieve the asynchronous operation user context. + * + * \note This function may only be called while a handshake + * is in progress. + * + * \param ssl The SSL context to access. + * \param ctx The new value of the asynchronous operation user context. + * Call mbedtls_ssl_get_async_operation_data() later during the + * same handshake to retrieve this value. + */ +void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, + void *ctx ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +/** + * \brief Callback type: generate a cookie + * + * \param ctx Context for the callback + * \param p Buffer to write to, + * must be updated to point right after the cookie + * \param end Pointer to one past the end of the output buffer + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \return The callback must return 0 on success, + * or a negative error code. + */ +typedef int mbedtls_ssl_cookie_write_t( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *info, size_t ilen ); + +/** + * \brief Callback type: verify a cookie + * + * \param ctx Context for the callback + * \param cookie Cookie to verify + * \param clen Length of cookie + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \return The callback must return 0 if cookie is valid, + * or a negative error code. + */ +typedef int mbedtls_ssl_cookie_check_t( void *ctx, + const unsigned char *cookie, size_t clen, + const unsigned char *info, size_t ilen ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Register callbacks for DTLS cookies + * (Server only. DTLS only.) + * + * Default: dummy callbacks that fail, in order to force you to + * register working callbacks (and initialize their context). + * + * To disable HelloVerifyRequest, register NULL callbacks. + * + * \warning Disabling hello verification allows your server to be used + * for amplification in DoS attacks against other hosts. + * Only disable if you known this can't happen in your + * particular environment. + * + * \note See comments on \c mbedtls_ssl_handshake() about handling + * the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected + * on the first handshake attempt when this is enabled. + * + * \note This is also necessary to handle client reconnection from + * the same port as described in RFC 6347 section 4.2.8 (only + * the variant with cookies is supported currently). See + * comments on \c mbedtls_ssl_read() for details. + * + * \param conf SSL configuration + * \param f_cookie_write Cookie write callback + * \param f_cookie_check Cookie check callback + * \param p_cookie Context for both callbacks + */ +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ); + +/** + * \brief Set client's transport-level identification info. + * (Server only. DTLS only.) + * + * This is usually the IP address (and port), but could be + * anything identify the client depending on the underlying + * network stack. Used for HelloVerifyRequest with DTLS. + * This is *not* used to route the actual packets. + * + * \param ssl SSL context + * \param info Transport-level info identifying the client (eg IP + port) + * \param ilen Length of info in bytes + * + * \note An internal copy is made, so the info buffer can be reused. + * + * \return 0 on success, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used on client, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if out of memory. + */ +int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen ); + +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +/** + * \brief Enable or disable anti-replay protection for DTLS. + * (DTLS only, no effect on TLS.) + * Default: enabled. + * + * \param conf SSL configuration + * \param mode MBEDTLS_SSL_ANTI_REPLAY_ENABLED or MBEDTLS_SSL_ANTI_REPLAY_DISABLED. + * + * \warning Disabling this is a security risk unless the application + * protocol handles duplicated packets in a safe way. You + * should not disable this without careful consideration. + * However, if your application already detects duplicated + * packets and needs information about them to adjust its + * transmission strategy, then you'll want to disable this. + */ +void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ); +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +/** + * \brief Set a limit on the number of records with a bad MAC + * before terminating the connection. + * (DTLS only, no effect on TLS.) + * Default: 0 (disabled). + * + * \param conf SSL configuration + * \param limit Limit, or 0 to disable. + * + * \note If the limit is N, then the connection is terminated when + * the Nth non-authentic record is seen. + * + * \note Records with an invalid header are not counted, only the + * ones going through the authentication-decryption phase. + * + * \note This is a security trade-off related to the fact that it's + * often relatively easy for an active attacker ot inject UDP + * datagrams. On one hand, setting a low limit here makes it + * easier for such an attacker to forcibly terminated a + * connection. On the other hand, a high limit or no limit + * might make us waste resources checking authentication on + * many bogus packets. + */ +void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ); +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +/** + * \brief Allow or disallow packing of multiple handshake records + * within a single datagram. + * + * \param ssl The SSL context to configure. + * \param allow_packing This determines whether datagram packing may + * be used or not. A value of \c 0 means that every + * record will be sent in a separate datagram; a + * value of \c 1 means that, if space permits, + * multiple handshake messages (including CCS) belonging to + * a single flight may be packed within a single datagram. + * + * \note This is enabled by default and should only be disabled + * for test purposes, or if datagram packing causes + * interoperability issues with peers that don't support it. + * + * \note Allowing datagram packing reduces the network load since + * there's less overhead if multiple messages share the same + * datagram. Also, it increases the handshake efficiency + * since messages belonging to a single datagram will not + * be reordered in transit, and so future message buffering + * or flight retransmission (if no buffering is used) as + * means to deal with reordering are needed less frequently. + * + * \note Application records are not affected by this option and + * are currently always sent in separate datagrams. + * + */ +void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ); + +/** + * \brief Set retransmit timeout values for the DTLS handshake. + * (DTLS only, no effect on TLS.) + * + * \param conf SSL configuration + * \param min Initial timeout value in milliseconds. + * Default: 1000 (1 second). + * \param max Maximum timeout value in milliseconds. + * Default: 60000 (60 seconds). + * + * \note Default values are from RFC 6347 section 4.2.4.1. + * + * \note The 'min' value should typically be slightly above the + * expected round-trip time to your peer, plus whatever time + * it takes for the peer to process the message. For example, + * if your RTT is about 600ms and you peer needs up to 1s to + * do the cryptographic operations in the handshake, then you + * should set 'min' slightly above 1600. Lower values of 'min' + * might cause spurious resends which waste network resources, + * while larger value of 'min' will increase overall latency + * on unreliable network links. + * + * \note The more unreliable your network connection is, the larger + * your max / min ratio needs to be in order to achieve + * reliable handshakes. + * + * \note Messages are retransmitted up to log2(ceil(max/min)) times. + * For example, if min = 1s and max = 5s, the retransmit plan + * goes: send ... 1s -> resend ... 2s -> resend ... 4s -> + * resend ... 5s -> give up and return a timeout error. + */ +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Set the session cache callbacks (server-side only) + * If not set, no session resuming is done (except if session + * tickets are enabled too). + * + * The session cache has the responsibility to check for stale + * entries based on timeout. See RFC 5246 for recommendations. + * + * Warning: session.peer_cert is cleared by the SSL/TLS layer on + * connection shutdown, so do not cache the pointer! Either set + * it to NULL or make a full copy of the certificate. + * + * The get callback is called once during the initial handshake + * to enable session resuming. The get function has the + * following parameters: (void *parameter, mbedtls_ssl_session *session) + * If a valid entry is found, it should fill the master of + * the session object with the cached values and return 0, + * return 1 otherwise. Optionally peer_cert can be set as well + * if it is properly present in cache entry. + * + * The set callback is called once during the initial handshake + * to enable session resuming after the entire handshake has + * been finished. The set function has the following parameters: + * (void *parameter, const mbedtls_ssl_session *session). The function + * should create a cache entry for future retrieval based on + * the data in the session structure and should keep in mind + * that the mbedtls_ssl_session object presented (and all its referenced + * data) is cleared by the SSL/TLS layer when the connection is + * terminated. It is recommended to add metadata to determine if + * an entry is still valid in the future. Return 0 if + * successfully cached, return 1 otherwise. + * + * \param conf SSL configuration + * \param p_cache parmater (context) for both callbacks + * \param f_get_cache session get callback + * \param f_set_cache session set callback + */ +void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, + void *p_cache, + int (*f_get_cache)(void *, mbedtls_ssl_session *), + int (*f_set_cache)(void *, const mbedtls_ssl_session *) ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Request resumption of session (client-side only) + * Session data is copied from presented session structure. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa mbedtls_ssl_get_session() + */ +int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Set the list of allowed ciphersuites and the preference + * order. First in the list has the highest preference. + * (Overrides all version-specific lists) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_config. + * + * Note: The server uses its own preferences + * over the preference of the client unless + * MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE is defined! + * + * \param conf SSL configuration + * \param ciphersuites 0-terminated list of allowed ciphersuites + */ +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, + const int *ciphersuites ); + +/** + * \brief Set the list of allowed ciphersuites and the + * preference order for a specific version of the protocol. + * (Only useful on the server side) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_config. + * + * \param conf SSL configuration + * \param ciphersuites 0-terminated list of allowed ciphersuites + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 + * supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 + * and MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + */ +void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, + const int *ciphersuites, + int major, int minor ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the X.509 security profile used for verification + * + * \note The restrictions are enforced for all certificates in the + * chain. However, signatures in the handshake are not covered + * by this setting but by \b mbedtls_ssl_conf_sig_hashes(). + * + * \param conf SSL configuration + * \param profile Profile to use + */ +void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile ); + +/** + * \brief Set the data required to verify peer certificate + * + * \note See \c mbedtls_x509_crt_verify() for notes regarding the + * parameters ca_chain (maps to trust_ca for that function) + * and ca_crl. + * + * \param conf SSL configuration + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + */ +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ); + +/** + * \brief Set own certificate chain and private key + * + * \note own_cert should contain in order from the bottom up your + * certificate chain. The top certificate (self-signed) + * can be omitted. + * + * \note On server, this function can be called multiple times to + * provision more than one cert/key pair (eg one ECDSA, one + * RSA with SHA-256, one RSA with SHA-1). An adequate + * certificate will be selected according to the client's + * advertised capabilities. In case multiple certificates are + * adequate, preference is given to the one set by the first + * call to this function, then second, etc. + * + * \note On client, only the first call has any effect. That is, + * only one client certificate can be provisioned. The + * server's preferences in its CertficateRequest message will + * be ignored and our only cert will be sent regardless of + * whether it matches those preferences - the server can then + * decide what it wants to do with it. + * + * \note The provided \p pk_key needs to match the public key in the + * first certificate in \p own_cert, or all handshakes using + * that certificate will fail. It is your responsibility + * to ensure that; this function will not perform any check. + * You may use mbedtls_pk_check_pair() in order to perform + * this check yourself, but be aware that this function can + * be computationally expensive on some key types. + * + * \param conf SSL configuration + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +/** + * \brief Set the Pre Shared Key (PSK) and the expected identity name + * + * \note This is mainly useful for clients. Servers will usually + * want to use \c mbedtls_ssl_conf_psk_cb() instead. + * + * \note Currently clients can only register one pre-shared key. + * In other words, the servers' identity hint is ignored. + * Support for setting multiple PSKs on clients and selecting + * one based on the identity hint is not a planned feature but + * feedback is welcomed. + * + * \param conf SSL configuration + * \param psk pointer to the pre-shared key + * \param psk_len pre-shared key length + * \param psk_identity pointer to the pre-shared key identity + * \param psk_identity_len identity key length + * + * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ); + + +/** + * \brief Set the Pre Shared Key (PSK) for the current handshake + * + * \note This should only be called inside the PSK callback, + * ie the function passed to \c mbedtls_ssl_conf_psk_cb(). + * + * \param ssl SSL context + * \param psk pointer to the pre-shared key + * \param psk_len pre-shared key length + * + * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len ); + +/** + * \brief Set the PSK callback (server-side only). + * + * If set, the PSK callback is called for each + * handshake where a PSK ciphersuite was negotiated. + * The caller provides the identity received and wants to + * receive the actual PSK data and length. + * + * The callback has the following parameters: (void *parameter, + * mbedtls_ssl_context *ssl, const unsigned char *psk_identity, + * size_t identity_len) + * If a valid PSK identity is found, the callback should use + * \c mbedtls_ssl_set_hs_psk() on the ssl context to set the + * correct PSK and return 0. + * Any other return value will result in a denied PSK identity. + * + * \note If you set a PSK callback using this function, then you + * don't need to set a PSK key and identity using + * \c mbedtls_ssl_conf_psk(). + * + * \param conf SSL configuration + * \param f_psk PSK identity function + * \param p_psk PSK identity parameter + */ +void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_psk ); +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief Set the Diffie-Hellman public P and G values, + * read as hexadecimal strings (server-side only) + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus + * \param dhm_G Diffie-Hellman-Merkle generator + * + * \deprecated Superseded by \c mbedtls_ssl_conf_dh_param_bin. + * + * \return 0 if successful + */ +MBEDTLS_DEPRECATED int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, + const char *dhm_P, + const char *dhm_G ); + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Set the Diffie-Hellman public P and G values + * from big-endian binary presentations. + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]_BIN) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus in big-endian binary form + * \param P_len Length of DHM modulus + * \param dhm_G Diffie-Hellman-Merkle generator in big-endian binary form + * \param G_len Length of DHM generator + * + * \return 0 if successful + */ +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ); + +/** + * \brief Set the Diffie-Hellman public P and G values, + * read from existing context (server-side only) + * + * \param conf SSL configuration + * \param dhm_ctx Diffie-Hellman-Merkle context + * + * \return 0 if successful + */ +int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ); +#endif /* MBEDTLS_DHM_C && defined(MBEDTLS_SSL_SRV_C) */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Set the minimum length for Diffie-Hellman parameters. + * (Client-side only.) + * (Default: 1024 bits.) + * + * \param conf SSL configuration + * \param bitlen Minimum bit length of the DHM prime + */ +void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, + unsigned int bitlen ); +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Set the allowed curves in order of preference. + * (Default: all defined curves.) + * + * On server: this only affects selection of the ECDHE curve; + * the curves used for ECDH and ECDSA are determined by the + * list of available certificates instead. + * + * On client: this affects the list of curves offered for any + * use. The server can override our preference order. + * + * Both sides: limits the set of curves accepted for use in + * ECDHE and in the peer's end-entity certificate. + * + * \note This has no influence on which curves are allowed inside the + * certificate chains, see \c mbedtls_ssl_conf_cert_profile() + * for that. For the end-entity certificate however, the key + * will be accepted only if it is allowed both by this list + * and by the cert profile. + * + * \note This list should be ordered by decreasing preference + * (preferred curve first). + * + * \param conf SSL configuration + * \param curves Ordered list of allowed curves, + * terminated by MBEDTLS_ECP_DP_NONE. + */ +void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curves ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/** + * \brief Set the allowed hashes for signatures during the handshake. + * (Default: all available hashes except MD5.) + * + * \note This only affects which hashes are offered and can be used + * for signatures during the handshake. Hashes for message + * authentication and the TLS PRF are controlled by the + * ciphersuite, see \c mbedtls_ssl_conf_ciphersuites(). Hashes + * used for certificate signature are controlled by the + * verification profile, see \c mbedtls_ssl_conf_cert_profile(). + * + * \note This list should be ordered by decreasing preference + * (preferred hash first). + * + * \param conf SSL configuration + * \param hashes Ordered list of allowed signature hashes, + * terminated by \c MBEDTLS_MD_NONE. + */ +void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, + const int *hashes ); +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set or reset the hostname to check against the received + * server certificate. It sets the ServerName TLS extension, + * too, if that extension is enabled. (client-side only) + * + * \param ssl SSL context + * \param hostname the server hostname, may be NULL to clear hostname + + * \note Maximum hostname length MBEDTLS_SSL_MAX_HOST_NAME_LEN. + * + * \return 0 if successful, MBEDTLS_ERR_SSL_ALLOC_FAILED on + * allocation failure, MBEDTLS_ERR_SSL_BAD_INPUT_DATA on + * too long input hostname. + * + * Hostname set to the one provided on success (cleared + * when NULL). On allocation failure hostname is cleared. + * On too long input failure, old hostname is unchanged. + */ +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +/** + * \brief Set own certificate and key for the current handshake + * + * \note Same as \c mbedtls_ssl_conf_own_cert() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ); + +/** + * \brief Set the data required to verify peer certificate for the + * current handshake + * + * \note Same as \c mbedtls_ssl_conf_ca_chain() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + */ +void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ); + +/** + * \brief Set authmode for the current handshake. + * + * \note Same as \c mbedtls_ssl_conf_authmode() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param authmode MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL or + * MBEDTLS_SSL_VERIFY_REQUIRED + */ +void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, + int authmode ); + +/** + * \brief Set server side ServerName TLS extension callback + * (optional, server-side only). + * + * If set, the ServerName callback is called whenever the + * server receives a ServerName TLS extension from the client + * during a handshake. The ServerName callback has the + * following parameters: (void *parameter, mbedtls_ssl_context *ssl, + * const unsigned char *hostname, size_t len). If a suitable + * certificate is found, the callback must set the + * certificate(s) and key(s) to use with \c + * mbedtls_ssl_set_hs_own_cert() (can be called repeatedly), + * and may optionally adjust the CA and associated CRL with \c + * mbedtls_ssl_set_hs_ca_chain() as well as the client + * authentication mode with \c mbedtls_ssl_set_hs_authmode(), + * then must return 0. If no matching name is found, the + * callback must either set a default cert, or + * return non-zero to abort the handshake at this point. + * + * \param conf SSL configuration + * \param f_sni verification function + * \param p_sni verification parameter + */ +void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_sni ); +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/** + * \brief Set the EC J-PAKE password for current handshake. + * + * \note An internal copy is made, and destroyed as soon as the + * handshake is completed, or when the SSL context is reset or + * freed. + * + * \note The SSL context needs to be already set up. The right place + * to call this function is between \c mbedtls_ssl_setup() or + * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). + * + * \param ssl SSL context + * \param pw EC J-PAKE password (pre-shared secret) + * \param pw_len length of pw in bytes + * + * \return 0 on success, or a negative error code. + */ +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ); +#endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +/** + * \brief Set the supported Application Layer Protocols. + * + * \param conf SSL configuration + * \param protos Pointer to a NULL-terminated list of supported protocols, + * in decreasing preference order. The pointer to the list is + * recorded by the library for later reference as required, so + * the lifetime of the table must be atleast as long as the + * lifetime of the SSL configuration structure. + * + * \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA. + */ +int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ); + +/** + * \brief Get the name of the negotiated Application Layer Protocol. + * This function should be called after the handshake is + * completed. + * + * \param ssl SSL context + * + * \return Protcol name, or NULL if no protocol was negotiated. + */ +const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_ALPN */ + +/** + * \brief Set the maximum supported version sent from the client side + * and/or accepted at the server side + * (Default: MBEDTLS_SSL_MAX_MAJOR_VERSION, MBEDTLS_SSL_MAX_MINOR_VERSION) + * + * \note This ignores ciphersuites from higher versions. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and + * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + */ +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ); + +/** + * \brief Set the minimum accepted SSL/TLS protocol version + * (Default: TLS 1.0) + * + * \note Input outside of the SSL_MAX_XXXXX_VERSION and + * SSL_MIN_XXXXX_VERSION range is ignored. + * + * \note MBEDTLS_SSL_MINOR_VERSION_0 (SSL v3) should be avoided. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and + * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + */ +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ); + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Set the fallback flag (client-side only). + * (Default: MBEDTLS_SSL_IS_NOT_FALLBACK). + * + * \note Set to MBEDTLS_SSL_IS_FALLBACK when preparing a fallback + * connection, that is a connection with max_version set to a + * lower value than the value you're willing to use. Such + * fallback connections are not recommended but are sometimes + * necessary to interoperate with buggy (version-intolerant) + * servers. + * + * \warning You should NOT set this to MBEDTLS_SSL_IS_FALLBACK for + * non-fallback connections! This would appear to work for a + * while, then cause failures when the server is upgraded to + * support a newer TLS version. + * + * \param conf SSL configuration + * \param fallback MBEDTLS_SSL_IS_NOT_FALLBACK or MBEDTLS_SSL_IS_FALLBACK + */ +void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ); +#endif /* MBEDTLS_SSL_FALLBACK_SCSV && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +/** + * \brief Enable or disable Encrypt-then-MAC + * (Default: MBEDTLS_SSL_ETM_ENABLED) + * + * \note This should always be enabled, it is a security + * improvement, and should not cause any interoperability + * issue (used only if the peer supports it too). + * + * \param conf SSL configuration + * \param etm MBEDTLS_SSL_ETM_ENABLED or MBEDTLS_SSL_ETM_DISABLED + */ +void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ); +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +/** + * \brief Enable or disable Extended Master Secret negotiation. + * (Default: MBEDTLS_SSL_EXTENDED_MS_ENABLED) + * + * \note This should always be enabled, it is a security fix to the + * protocol, and should not cause any interoperability issue + * (used only if the peer supports it too). + * + * \param conf SSL configuration + * \param ems MBEDTLS_SSL_EXTENDED_MS_ENABLED or MBEDTLS_SSL_EXTENDED_MS_DISABLED + */ +void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ); +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_ARC4_C) +/** + * \brief Disable or enable support for RC4 + * (Default: MBEDTLS_SSL_ARC4_DISABLED) + * + * \warning Use of RC4 in DTLS/TLS has been prohibited by RFC 7465 + * for security reasons. Use at your own risk. + * + * \note This function is deprecated and will likely be removed in + * a future version of the library. + * RC4 is disabled by default at compile time and needs to be + * actively enabled for use with legacy systems. + * + * \param conf SSL configuration + * \param arc4 MBEDTLS_SSL_ARC4_ENABLED or MBEDTLS_SSL_ARC4_DISABLED + */ +void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ); +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Whether to send a list of acceptable CAs in + * CertificateRequest messages. + * (Default: do send) + * + * \param conf SSL configuration + * \param cert_req_ca_list MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or + * MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED + */ +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Set the maximum fragment length to emit and/or negotiate. + * (Typical: the smaller of #MBEDTLS_SSL_IN_CONTENT_LEN and + * #MBEDTLS_SSL_OUT_CONTENT_LEN, usually `2^14` bytes) + * (Server: set maximum fragment length to emit, + * usually negotiated by the client during handshake) + * (Client: set maximum fragment length to emit *and* + * negotiate with the server during handshake) + * (Default: #MBEDTLS_SSL_MAX_FRAG_LEN_NONE) + * + * \note On the client side, the maximum fragment length extension + * *will not* be used, unless the maximum fragment length has + * been set via this function to a value different than + * #MBEDTLS_SSL_MAX_FRAG_LEN_NONE. + * + * \note This sets the maximum length for a record's payload, + * excluding record overhead that will be added to it, see + * \c mbedtls_ssl_get_record_expansion(). + * + * \note With TLS, this currently only affects ApplicationData (sent + * with \c mbedtls_ssl_read()), not handshake messages. + * With DTLS, this affects both ApplicationData and handshake. + * + * \note For DTLS, it is also possible to set a limit for the total + * size of daragrams passed to the transport layer, including + * record overhead, see \c mbedtls_ssl_set_mtu(). + * + * \param conf SSL configuration + * \param mfl_code Code for maximum fragment length (allowed values: + * MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024, + * MBEDTLS_SSL_MAX_FRAG_LEN_2048, MBEDTLS_SSL_MAX_FRAG_LEN_4096) + * + * \return 0 if successful or MBEDTLS_ERR_SSL_BAD_INPUT_DATA + */ +int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +/** + * \brief Activate negotiation of truncated HMAC + * (Default: MBEDTLS_SSL_TRUNC_HMAC_DISABLED) + * + * \param conf SSL configuration + * \param truncate Enable or disable (MBEDTLS_SSL_TRUNC_HMAC_ENABLED or + * MBEDTLS_SSL_TRUNC_HMAC_DISABLED) + */ +void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ); +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +/** + * \brief Enable / Disable 1/n-1 record splitting + * (Default: MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED) + * + * \note Only affects SSLv3 and TLS 1.0, not higher versions. + * Does not affect non-CBC ciphersuites in any version. + * + * \param conf SSL configuration + * \param split MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED or + * MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED + */ +void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ); +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Enable / Disable session tickets (client only). + * (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.) + * + * \note On server, use \c mbedtls_ssl_conf_session_tickets_cb(). + * + * \param conf SSL configuration + * \param use_tickets Enable or disable (MBEDTLS_SSL_SESSION_TICKETS_ENABLED or + * MBEDTLS_SSL_SESSION_TICKETS_DISABLED) + */ +void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enable / Disable renegotiation support for connection when + * initiated by peer + * (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED) + * + * \warning It is recommended to always disable renegotation unless you + * know you need it and you know what you're doing. In the + * past, there have been several issues associated with + * renegotiation or a poor understanding of its properties. + * + * \note Server-side, enabling renegotiation also makes the server + * susceptible to a resource DoS by a malicious client. + * + * \param conf SSL configuration + * \param renegotiation Enable or disable (MBEDTLS_SSL_RENEGOTIATION_ENABLED or + * MBEDTLS_SSL_RENEGOTIATION_DISABLED) + */ +void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Prevent or allow legacy renegotiation. + * (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) + * + * MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION allows connections to + * be established even if the peer does not support + * secure renegotiation, but does not allow renegotiation + * to take place if not secure. + * (Interoperable and secure option) + * + * MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations + * with non-upgraded peers. Allowing legacy renegotiation + * makes the connection vulnerable to specific man in the + * middle attacks. (See RFC 5746) + * (Most interoperable and least secure option) + * + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE breaks off connections + * if peer does not support secure renegotiation. Results + * in interoperability issues with non-upgraded peers + * that do not support renegotiation altogether. + * (Most secure option, interoperability issues) + * + * \param conf SSL configuration + * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION, + * SSL_ALLOW_LEGACY_RENEGOTIATION or + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) + */ +void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enforce renegotiation requests. + * (Default: enforced, max_records = 16) + * + * When we request a renegotiation, the peer can comply or + * ignore the request. This function allows us to decide + * whether to enforce our renegotiation requests by closing + * the connection if the peer doesn't comply. + * + * However, records could already be in transit from the peer + * when the request is emitted. In order to increase + * reliability, we can accept a number of records before the + * expected handshake records. + * + * The optimal value is highly dependent on the specific usage + * scenario. + * + * \note With DTLS and server-initiated renegotiation, the + * HelloRequest is retransmited every time mbedtls_ssl_read() times + * out or receives Application Data, until: + * - max_records records have beens seen, if it is >= 0, or + * - the number of retransmits that would happen during an + * actual handshake has been reached. + * Please remember the request might be lost a few times + * if you consider setting max_records to a really low value. + * + * \warning On client, the grace period can only happen during + * mbedtls_ssl_read(), as opposed to mbedtls_ssl_write() and mbedtls_ssl_renegotiate() + * which always behave as if max_record was 0. The reason is, + * if we receive application data from the server, we need a + * place to write it, which only happens during mbedtls_ssl_read(). + * + * \param conf SSL configuration + * \param max_records Use MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to + * enforce renegotiation, or a non-negative value to enforce + * it but allow for a grace period of max_records records. + */ +void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ); + +/** + * \brief Set record counter threshold for periodic renegotiation. + * (Default: 2^48 - 1) + * + * Renegotiation is automatically triggered when a record + * counter (outgoing or ingoing) crosses the defined + * threshold. The default value is meant to prevent the + * connection from being closed when the counter is about to + * reached its maximal value (it is not allowed to wrap). + * + * Lower values can be used to enforce policies such as "keys + * must be refreshed every N packets with cipher X". + * + * The renegotiation period can be disabled by setting + * conf->disable_renegotiation to + * MBEDTLS_SSL_RENEGOTIATION_DISABLED. + * + * \note When the configured transport is + * MBEDTLS_SSL_TRANSPORT_DATAGRAM the maximum renegotiation + * period is 2^48 - 1, and for MBEDTLS_SSL_TRANSPORT_STREAM, + * the maximum renegotiation period is 2^64 - 1. + * + * \param conf SSL configuration + * \param period The threshold value: a big-endian 64-bit number. + */ +void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Check if there is data already read from the + * underlying transport but not yet processed. + * + * \param ssl SSL context + * + * \return 0 if nothing's pending, 1 otherwise. + * + * \note This is different in purpose and behaviour from + * \c mbedtls_ssl_get_bytes_avail in that it considers + * any kind of unprocessed data, not only unread + * application data. If \c mbedtls_ssl_get_bytes + * returns a non-zero value, this function will + * also signal pending data, but the converse does + * not hold. For example, in DTLS there might be + * further records waiting to be processed from + * the current underlying transport's datagram. + * + * \note If this function returns 1 (data pending), this + * does not imply that a subsequent call to + * \c mbedtls_ssl_read will provide any data; + * e.g., the unprocessed data might turn out + * to be an alert or a handshake message. + * + * \note This function is useful in the following situation: + * If the SSL/TLS module successfully returns from an + * operation - e.g. a handshake or an application record + * read - and you're awaiting incoming data next, you + * must not immediately idle on the underlying transport + * to have data ready, but you need to check the value + * of this function first. The reason is that the desired + * data might already be read but not yet processed. + * If, in contrast, a previous call to the SSL/TLS module + * returned MBEDTLS_ERR_SSL_WANT_READ, it is not necessary + * to call this function, as the latter error code entails + * that all internal data has been processed. + * + */ +int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the number of application data bytes + * remaining to be read from the current record. + * + * \param ssl SSL context + * + * \return How many bytes are available in the application + * data record read buffer. + * + * \note When working over a datagram transport, this is + * useful to detect the current datagram's boundary + * in case \c mbedtls_ssl_read has written the maximal + * amount of data fitting into the input buffer. + * + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the result of the certificate verification + * + * \param ssl The SSL context to use. + * + * \return \c 0 if the certificate verification was successful. + * \return \c -1u if the result is not available. This may happen + * e.g. if the handshake aborts early, or a verification + * callback returned a fatal error. + * \return A bitwise combination of \c MBEDTLS_X509_BADCERT_XXX + * and \c MBEDTLS_X509_BADCRL_XXX failure flags; see x509.h. + */ +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the name of the current ciphersuite + * + * \param ssl SSL context + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the current SSL version (SSLv3/TLSv1/etc) + * + * \param ssl SSL context + * + * \return a string containing the SSL version + */ +const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the (maximum) number of bytes added by the record + * layer: header + encryption/MAC overhead (inc. padding) + * + * \note This function is not available (always returns an error) + * when record compression is enabled. + * + * \param ssl SSL context + * + * \return Current maximum record expansion in bytes, or + * MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if compression is + * enabled, which makes expansion much less predictable + */ +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Return the maximum fragment length (payload, in bytes). + * This is the value negotiated with peer if any, + * or the locally configured value. + * + * \sa mbedtls_ssl_conf_max_frag_len() + * \sa mbedtls_ssl_get_max_record_payload() + * + * \param ssl SSL context + * + * \return Current maximum fragment length. + */ +size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +/** + * \brief Return the current maximum outgoing record payload in bytes. + * This takes into account the config.h setting \c + * MBEDTLS_SSL_OUT_CONTENT_LEN, the configured and negotiated + * max fragment length extension if used, and for DTLS the + * path MTU as configured and current record expansion. + * + * \note With DTLS, \c mbedtls_ssl_write() will return an error if + * called with a larger length value. + * With TLS, \c mbedtls_ssl_write() will fragment the input if + * necessary and return the number of bytes written; it is up + * to the caller to call \c mbedtls_ssl_write() again in + * order to send the remaining bytes if any. + * + * \note This function is not available (always returns an error) + * when record compression is enabled. + * + * \sa mbedtls_ssl_set_mtu() + * \sa mbedtls_ssl_get_max_frag_len() + * \sa mbedtls_ssl_get_record_expansion() + * + * \param ssl SSL context + * + * \return Current maximum payload for an outgoing record, + * or a negative error code. + */ +int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Return the peer certificate from the current connection + * + * Note: Can be NULL in case no certificate was sent during + * the handshake. Different calls for the same connection can + * return the same or different pointers for the same + * certificate and even a different certificate altogether. + * The peer cert CAN change in a single connection if + * renegotiation is performed. + * + * \param ssl SSL context + * + * \return the current peer certificate + */ +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Save session in order to resume it later (client-side only) + * Session data is copied to presented session structure. + * + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid. + * + * \note Only the server certificate is copied, and not the full chain, + * so you should not attempt to validate the certificate again + * by calling \c mbedtls_x509_crt_verify() on it. + * Instead, you should use the results from the verification + * in the original handshake by calling \c mbedtls_ssl_get_verify_result() + * after loading the session again into a new SSL context + * using \c mbedtls_ssl_set_session(). + * + * \note Once the session object is not needed anymore, you should + * free it by calling \c mbedtls_ssl_session_free(). + * + * \sa mbedtls_ssl_set_session() + */ +int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session ); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Perform the SSL handshake + * + * \param ssl SSL context + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use + * and the client did not demonstrate reachability yet - in + * this case you must stop using the context (see below). + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. + * + * \note If DTLS is in use, then you may choose to handle + * #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging + * purposes, as it is an expected return value rather than an + * actual error, but you still need to reset/free the context. + * + * \note Remarks regarding event-driven DTLS: + * If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram + * from the underlying transport layer is currently being processed, + * and it is safe to idle until the timer or the underlying transport + * signal a new event. This is not true for a successful handshake, + * in which case the datagram of the underlying transport that is + * currently being processed might or might not contain further + * DTLS records. + */ +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); + +/** + * \brief Perform a single step of the SSL handshake + * + * \note The state of the context (ssl->state) will be at + * the next state after this function returns \c 0. Do not + * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. + * + * \param ssl SSL context + * + * \return See mbedtls_ssl_handshake(). + * + * \warning If this function returns something other than \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * the SSL context for reading or writing, and either free it + * or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. + */ +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Initiate an SSL renegotiation on the running connection. + * Client: perform the renegotiation right now. + * Server: request renegotiation, which will be performed + * during the next call to mbedtls_ssl_read() if honored by + * client. + * + * \param ssl SSL context + * + * \return 0 if successful, or any mbedtls_ssl_handshake() return + * value except #MBEDTLS_ERR_SSL_CLIENT_RECONNECT that can't + * happen during a renegotiation. + * + * \warning If this function returns something other than \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * the SSL context for reading or writing, and either free it + * or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. + * + */ +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Read at most 'len' application data bytes + * + * \param ssl SSL context + * \param buf buffer that will hold the data + * \param len maximum number of bytes to read + * + * \return The (positive) number of bytes read if successful. + * \return \c 0 if the read end of the underlying transport was closed + * - in this case you must stop using the context (see below). + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server + * side of a DTLS connection and the client is initiating a + * new connection using the same source port. See below. + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * a positive value, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CLIENT_RECONNECT, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. + * + * \note When this function returns #MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * (which can only happen server-side), it means that a client + * is initiating a new connection using the same source port. + * You can either treat that as a connection close and wait + * for the client to resend a ClientHello, or directly + * continue with \c mbedtls_ssl_handshake() with the same + * context (as it has been reset internally). Either way, you + * must make sure this is seen by the application as a new + * connection: application state, if any, should be reset, and + * most importantly the identity of the client must be checked + * again. WARNING: not validating the identity of the client + * again, or not transmitting the new identity to the + * application layer, would allow authentication bypass! + * + * \note Remarks regarding event-driven DTLS: + * - If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram + * from the underlying transport layer is currently being processed, + * and it is safe to idle until the timer or the underlying transport + * signal a new event. + * - This function may return MBEDTLS_ERR_SSL_WANT_READ even if data was + * initially available on the underlying transport, as this data may have + * been only e.g. duplicated messages or a renegotiation request. + * Therefore, you must be prepared to receive MBEDTLS_ERR_SSL_WANT_READ even + * when reacting to an incoming-data event from the underlying transport. + * - On success, the datagram of the underlying transport that is currently + * being processed may contain further DTLS records. You should call + * \c mbedtls_ssl_check_pending to check for remaining records. + * + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ); + +/** + * \brief Try to write exactly 'len' application data bytes + * + * \warning This function will do partial writes in some cases. If the + * return value is non-negative but less than length, the + * function must be called again with updated arguments: + * buf + ret, len - ret (if ret is the return value) until + * it returns a value equal to the last 'len' argument. + * + * \param ssl SSL context + * \param buf buffer holding the data + * \param len how many bytes must be written + * + * \return The (non-negative) number of bytes actually written if + * successful (may be less than \p len). + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * a non-negative value, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. + * + * \note When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ, + * it must be called later with the *same* arguments, + * until it returns a value greater that or equal to 0. When + * the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be + * some partial data in the output buffer, however this is not + * yet sent. + * + * \note If the requested length is greater than the maximum + * fragment length (either the built-in limit or the one set + * or negotiated with the peer), then: + * - with TLS, less bytes than requested are written. + * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. + * \c mbedtls_ssl_get_max_frag_len() may be used to query the + * active maximum fragment length. + * + * \note Attempting to write 0 bytes will result in an empty TLS + * application record being sent. + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ); + +/** + * \brief Send an alert message + * + * \param ssl SSL context + * \param level The alert level of the message + * (MBEDTLS_SSL_ALERT_LEVEL_WARNING or MBEDTLS_SSL_ALERT_LEVEL_FATAL) + * \param message The alert message (SSL_ALERT_MSG_*) + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. + */ +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ); +/** + * \brief Notify the peer that the connection is being closed + * + * \param ssl SSL context + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); + +/** + * \brief Free referenced items in an SSL context and clear memory + * + * \param ssl SSL context + */ +void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); + +/** + * \brief Initialize an SSL configuration context + * Just makes the context ready for + * mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free(). + * + * \note You need to call mbedtls_ssl_config_defaults() unless you + * manually set all of the relevant fields yourself. + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ); + +/** + * \brief Load reasonnable default SSL configuration values. + * (You need to call mbedtls_ssl_config_init() first.) + * + * \param conf SSL configuration context + * \param endpoint MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + * \param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS + * \param preset a MBEDTLS_SSL_PRESET_XXX value + * + * \note See \c mbedtls_ssl_conf_transport() for notes on DTLS. + * + * \return 0 if successful, or + * MBEDTLS_ERR_XXX_ALLOC_FAILED on memory allocation error. + */ +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, + int endpoint, int transport, int preset ); + +/** + * \brief Free an SSL configuration context + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ); + +/** + * \brief Initialize SSL session structure + * + * \param session SSL session + */ +void mbedtls_ssl_session_init( mbedtls_ssl_session *session ); + +/** + * \brief Free referenced items in an SSL session including the + * peer certificate and clear memory + * + * \note A session object can be freed even if the SSL context + * that was used to retrieve the session is still in use. + * + * \param session SSL session + */ +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl.h */ diff --git a/external/mbedtls/include/mbedtls/ssl_cache.h b/external/mbedtls/include/mbedtls/ssl_cache.h new file mode 100644 index 0000000..612d817 --- /dev/null +++ b/external/mbedtls/include/mbedtls/ssl_cache.h @@ -0,0 +1,175 @@ +/** + * \file ssl_cache.h + * + * \brief SSL session cache implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SSL_CACHE_H +#define MBEDTLS_SSL_CACHE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT) +#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */ +#endif + +#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES) +#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mbedtls_ssl_cache_context mbedtls_ssl_cache_context; +typedef struct mbedtls_ssl_cache_entry mbedtls_ssl_cache_entry; + +/** + * \brief This structure is used for storing cache entries + */ +struct mbedtls_ssl_cache_entry +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t timestamp; /*!< entry timestamp */ +#endif + mbedtls_ssl_session session; /*!< entry session */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_buf peer_cert; /*!< entry peer_cert */ +#endif + mbedtls_ssl_cache_entry *next; /*!< chain pointer */ +}; + +/** + * \brief Cache context + */ +struct mbedtls_ssl_cache_context +{ + mbedtls_ssl_cache_entry *chain; /*!< start of the chain */ + int timeout; /*!< cache entry timeout */ + int max_entries; /*!< maximum entries */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +}; + +/** + * \brief Initialize an SSL cache context + * + * \param cache SSL cache context + */ +void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ); + +/** + * \brief Cache get callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to retrieve entry for + */ +int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ); + +/** + * \brief Cache set callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to store entry for + */ +int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ); + +#if defined(MBEDTLS_HAVE_TIME) +/** + * \brief Set the cache timeout + * (Default: MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT (1 day)) + * + * A timeout of 0 indicates no timeout. + * + * \param cache SSL cache context + * \param timeout cache entry timeout in seconds + */ +void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ); +#endif /* MBEDTLS_HAVE_TIME */ + +/** + * \brief Set the maximum number of cache entries + * (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50)) + * + * \param cache SSL cache context + * \param max cache entry maximum + */ +void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ); + +/** + * \brief Free referenced items in a cache context and clear memory + * + * \param cache SSL cache context + */ +void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cache.h */ diff --git a/external/mbedtls/include/mbedtls/ssl_ciphersuites.h b/external/mbedtls/include/mbedtls/ssl_ciphersuites.h new file mode 100644 index 0000000..ab8e601 --- /dev/null +++ b/external/mbedtls/include/mbedtls/ssl_ciphersuites.h @@ -0,0 +1,565 @@ +/** + * \file ssl_ciphersuites.h + * + * \brief SSL Ciphersuites for mbed TLS + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SSL_CIPHERSUITES_H +#define MBEDTLS_SSL_CIPHERSUITES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "pk.h" +#include "cipher.h" +#include "md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Supported ciphersuites (Official IANA names) + */ +#define MBEDTLS_TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 0x04 +#define MBEDTLS_TLS_RSA_WITH_RC4_128_SHA 0x05 +#define MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A + +#define MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 + +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA 0x2F + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA 0x35 +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 + +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 + +#define MBEDTLS_TLS_PSK_WITH_RC4_128_SHA 0x8A +#define MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA 0x8B +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA 0x8C +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D + +#define MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA 0x8E +#define MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x8F +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 + +#define MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA 0x92 +#define MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x93 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 + +#define MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ + +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA 0xC033 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0xC034 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 0xC03C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 0xC03D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC044 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC045 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC048 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC049 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC04A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC04B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC04C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC04D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 0xC04E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 0xC04F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 0xC050 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 0xC051 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC052 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC053 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC060 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC061 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 0xC062 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 0xC063 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 0xC064 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 0xC065 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC066 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC067 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 0xC068 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 0xC069 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 0xC06A /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 0xC06B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 0xC06C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 0xC06D /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 0xC06E /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 0xC06F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC070 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC071 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ +/* The last two are named with PSK_DHE in the RFC, which looks like a typo */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ + +/* RFC 7905 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE /**< TLS 1.2 */ + +/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. + * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below + */ +typedef enum { + MBEDTLS_KEY_EXCHANGE_NONE = 0, + MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_KEY_EXCHANGE_ECJPAKE, +} mbedtls_key_exchange_type_t; + +/* Key exchanges using a certificate */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED +#endif + +/* Key exchanges allowing client certificate requests */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED +#endif + +/* Key exchanges involving server signature in ServerKeyExchange */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED +#endif + +/* Key exchanges using ECDH */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED +#endif + +/* Key exchanges that don't involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED +#endif + +/* Key exchanges that involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED +#endif + +/* Key exchanges using a PSK */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED +#endif + +/* Key exchanges using DHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED +#endif + +/* Key exchanges using ECDHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED +#endif + +typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; + +#define MBEDTLS_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ +#define MBEDTLS_CIPHERSUITE_SHORT_TAG 0x02 /**< Short authentication tag, + eg for CCM_8 */ +#define MBEDTLS_CIPHERSUITE_NODTLS 0x04 /**< Can't be used with DTLS */ + +/** + * \brief This structure is used for storing ciphersuite information + */ +struct mbedtls_ssl_ciphersuite_t +{ + int id; + const char * name; + + mbedtls_cipher_type_t cipher; + mbedtls_md_type_t mac; + mbedtls_key_exchange_type_t key_exchange; + + int min_major_ver; + int min_minor_ver; + int max_major_ver; + int max_minor_ver; + + unsigned char flags; +}; + +const int *mbedtls_ssl_list_ciphersuites( void ); + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( const char *ciphersuite_name ); +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite_id ); + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ); +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ); +#endif + +int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ); +int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) +static inline int mbedtls_ssl_ciphersuite_has_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) +static inline int mbedtls_ssl_ciphersuite_no_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdh( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ + +static inline int mbedtls_ssl_ciphersuite_cert_req_allowed( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_dhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_server_signature( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ciphersuites.h */ diff --git a/external/mbedtls/include/mbedtls/ssl_cookie.h b/external/mbedtls/include/mbedtls/ssl_cookie.h new file mode 100644 index 0000000..9c2d5b6 --- /dev/null +++ b/external/mbedtls/include/mbedtls/ssl_cookie.h @@ -0,0 +1,140 @@ +/** + * \file ssl_cookie.h + * + * \brief DTLS cookie callbacks implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SSL_COOKIE_H +#define MBEDTLS_SSL_COOKIE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ +#ifndef MBEDTLS_SSL_COOKIE_TIMEOUT +#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Context for the default cookie functions. + */ +typedef struct mbedtls_ssl_cookie_ctx +{ + mbedtls_md_context_t hmac_ctx; /*!< context for the HMAC portion */ +#if !defined(MBEDTLS_HAVE_TIME) + unsigned long serial; /*!< serial number for expiration */ +#endif + unsigned long timeout; /*!< timeout delay, in seconds if HAVE_TIME, + or in number of tickets issued */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_ssl_cookie_ctx; + +/** + * \brief Initialize cookie context + */ +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ); + +/** + * \brief Setup cookie context (generate keys) + */ +int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set expiration delay for cookies + * (Default MBEDTLS_SSL_COOKIE_TIMEOUT) + * + * \param ctx Cookie contex + * \param delay Delay, in seconds if HAVE_TIME, or in number of cookies + * issued in the meantime. + * 0 to disable expiration (NOT recommended) + */ +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ); + +/** + * \brief Free cookie context + */ +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ); + +/** + * \brief Generate cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_write_t mbedtls_ssl_cookie_write; + +/** + * \brief Verify cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_check_t mbedtls_ssl_cookie_check; + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cookie.h */ diff --git a/external/mbedtls/include/mbedtls/ssl_internal.h b/external/mbedtls/include/mbedtls/ssl_internal.h new file mode 100644 index 0000000..6ba6c2a --- /dev/null +++ b/external/mbedtls/include/mbedtls/ssl_internal.h @@ -0,0 +1,933 @@ +/** + * \file ssl_internal.h + * + * \brief Internal functions shared by the SSL modules + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SSL_INTERNAL_H +#define MBEDTLS_SSL_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" +#include "cipher.h" + +#if defined(MBEDTLS_MD5_C) +#include "md5.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "sha512.h" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#include "ecjpake.h" +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Determine minimum supported version */ +#define MBEDTLS_SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#define MBEDTLS_SSL_MIN_VALID_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#define MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +/* Determine maximum supported version */ +#define MBEDTLS_SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#else +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +/* Shorthand for restartable ECC */ +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_SSL__ECP_RESTARTABLE +#endif + +#define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 +#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ +#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ +#define MBEDTLS_SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ + +/* + * DTLS retransmission states, see RFC 6347 4.2.4 + * + * The SENDING state is merged in PREPARING for initial sends, + * but is distinct for resends. + * + * Note: initial state is wrong for server, but is not used anyway. + */ +#define MBEDTLS_SSL_RETRANS_PREPARING 0 +#define MBEDTLS_SSL_RETRANS_SENDING 1 +#define MBEDTLS_SSL_RETRANS_WAITING 2 +#define MBEDTLS_SSL_RETRANS_FINISHED 3 + +/* This macro determines whether CBC is supported. */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || \ + defined(MBEDTLS_CAMELLIA_C) || \ + defined(MBEDTLS_ARIA_C) || \ + defined(MBEDTLS_DES_C) ) +#define MBEDTLS_SSL_SOME_SUITES_USE_CBC +#endif + +/* This macro determines whether the CBC construct used in TLS 1.0-1.2 (as + * opposed to the very different CBC construct used in SSLv3) is supported. */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ + ( defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) ) +#define MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC +#endif + +/* + * Allow extra bytes for record, authentication and encryption overhead: + * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256) + * and allow for a maximum of 1024 of compression expansion if + * enabled. + */ +#if defined(MBEDTLS_ZLIB_SUPPORT) +#define MBEDTLS_SSL_COMPRESSION_ADD 1024 +#else +#define MBEDTLS_SSL_COMPRESSION_ADD 0 +#endif + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_MODE_CBC) +/* Ciphersuites using HMAC */ +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ +#elif defined(MBEDTLS_SHA256_C) +#define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ +#else +#define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ +#endif +#else +/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ +#define MBEDTLS_SSL_MAC_ADD 16 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_SSL_PADDING_ADD 256 +#else +#define MBEDTLS_SSL_PADDING_ADD 0 +#endif + +#define MBEDTLS_SSL_PAYLOAD_OVERHEAD ( MBEDTLS_SSL_COMPRESSION_ADD + \ + MBEDTLS_MAX_IV_LENGTH + \ + MBEDTLS_SSL_MAC_ADD + \ + MBEDTLS_SSL_PADDING_ADD \ + ) + +#define MBEDTLS_SSL_IN_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + ( MBEDTLS_SSL_IN_CONTENT_LEN ) ) + +#define MBEDTLS_SSL_OUT_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + ( MBEDTLS_SSL_OUT_CONTENT_LEN ) ) + +/* The maximum number of buffered handshake messages. */ +#define MBEDTLS_SSL_MAX_BUFFERED_HS 4 + +/* Maximum length we can advertise as our max content length for + RFC 6066 max_fragment_length extension negotiation purposes + (the lesser of both sizes, if they are unequal.) + */ +#define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ( \ + (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN) \ + ? ( MBEDTLS_SSL_OUT_CONTENT_LEN ) \ + : ( MBEDTLS_SSL_IN_CONTENT_LEN ) \ + ) + +/* Maximum size in bytes of list in sig-hash algorithm ext., RFC 5246 */ +#define MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN 65534 + +/* Maximum size in bytes of list in supported elliptic curve ext., RFC 4492 */ +#define MBEDTLS_SSL_MAX_CURVE_LIST_LEN 65535 + +/* + * Check that we obey the standard's message size bounds + */ + +#if MBEDTLS_SSL_MAX_CONTENT_LEN > 16384 +#error "Bad configuration - record content too large." +#endif + +#if MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN +#error "Bad configuration - incoming record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN." +#endif + +#if MBEDTLS_SSL_OUT_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN +#error "Bad configuration - outgoing record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN." +#endif + +#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048 +#error "Bad configuration - incoming protected record payload too large." +#endif + +#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048 +#error "Bad configuration - outgoing protected record payload too large." +#endif + +/* Calculate buffer sizes */ + +/* Note: Even though the TLS record header is only 5 bytes + long, we're internally using 8 bytes to store the + implicit sequence number. */ +#define MBEDTLS_SSL_HEADER_LEN 13 + +#define MBEDTLS_SSL_IN_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) ) + +#define MBEDTLS_SSL_OUT_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) ) + +#ifdef MBEDTLS_ZLIB_SUPPORT +/* Compression buffer holds both IN and OUT buffers, so should be size of the larger */ +#define MBEDTLS_SSL_COMPRESS_BUFFER_LEN ( \ + ( MBEDTLS_SSL_IN_BUFFER_LEN > MBEDTLS_SSL_OUT_BUFFER_LEN ) \ + ? MBEDTLS_SSL_IN_BUFFER_LEN \ + : MBEDTLS_SSL_OUT_BUFFER_LEN \ + ) +#endif + +/* + * TLS extension flags (for extensions with outgoing ServerHello content + * that need it (e.g. for RENEGOTIATION_INFO the server already knows because + * of state of the renegotiation flag, so no indicator is required) + */ +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) + +/** + * \brief This function checks if the remaining size in a buffer is + * greater or equal than a needed space. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed space in bytes. + * + * \return Zero if the needed space is available in the buffer, non-zero + * otherwise. + */ +static inline int mbedtls_ssl_chk_buf_ptr( const uint8_t *cur, + const uint8_t *end, size_t need ) +{ + return( ( cur > end ) || ( need > (size_t)( end - cur ) ) ); +} + +/** + * \brief This macro checks if the remaining size in a buffer is + * greater or equal than a needed space. If it is not the case, + * it returns an SSL_BUFFER_TOO_SMALL error. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed space in bytes. + * + */ +#define MBEDTLS_SSL_CHK_BUF_PTR( cur, end, need ) \ + do { \ + if( mbedtls_ssl_chk_buf_ptr( ( cur ), ( end ), ( need ) ) != 0 ) \ + { \ + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); \ + } \ + } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/* + * Abstraction for a grid of allowed signature-hash-algorithm pairs. + */ +struct mbedtls_ssl_sig_hash_set_t +{ + /* At the moment, we only need to remember a single suitable + * hash algorithm per signature algorithm. As long as that's + * the case - and we don't need a general lookup function - + * we can implement the sig-hash-set as a map from signatures + * to hash algorithms. */ + mbedtls_md_type_t rsa; + mbedtls_md_type_t ecdsa; +}; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +/* + * This structure contains the parameters only needed during handshake. + */ +struct mbedtls_ssl_handshake_params +{ + /* + * Handshake specific crypto variables + */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + mbedtls_ssl_sig_hash_set_t hash_algs; /*!< Set of suitable sig-hash pairs */ +#endif +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ +#if defined(MBEDTLS_SSL_CLI_C) + unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ + size_t ecjpake_cache_len; /*!< Length of cached data */ +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + unsigned char *psk; /*!< PSK from the callback */ + size_t psk_len; /*!< Length of PSK from callback */ +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + int sni_authmode; /*!< authmode from SNI callback */ + mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ + mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ + mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + int ecrs_enabled; /*!< Handshake supports EC restart? */ + mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */ + enum { /* this complements ssl->state with info on intra-state operations */ + ssl_ecrs_none = 0, /*!< nothing going on (yet) */ + ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */ + ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */ + ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */ + ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */ + } ecrs_state; /*!< current (or last) operation */ + size_t ecrs_n; /*!< place for saving a length */ +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) + unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ + unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ + + unsigned char *verify_cookie; /*!< Cli: HelloVerifyRequest cookie + Srv: unused */ + unsigned char verify_cookie_len; /*!< Cli: cookie length + Srv: flag for sending a cookie */ + + uint32_t retransmit_timeout; /*!< Current value of timeout */ + unsigned char retransmit_state; /*!< Retransmission state */ + mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ + mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ + unsigned char *cur_msg_p; /*!< Position in current message */ + unsigned int in_flight_start_seq; /*!< Minimum message sequence in the + flight being received */ + mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for + resending messages */ + unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter + for resending messages */ + + struct + { + size_t total_bytes_buffered; /*!< Cumulative size of heap allocated + * buffers used for message buffering. */ + + uint8_t seen_ccs; /*!< Indicates if a CCS message has + * been seen in the current flight. */ + + struct mbedtls_ssl_hs_buffer + { + unsigned is_valid : 1; + unsigned is_fragmented : 1; + unsigned is_complete : 1; + unsigned char *data; + size_t data_len; + } hs[MBEDTLS_SSL_MAX_BUFFERED_HS]; + + struct + { + unsigned char *data; + size_t len; + unsigned epoch; + } future_record; + + } buffering; + + uint16_t mtu; /*!< Handshake mtu, used to fragment outgoing messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Checksum contexts + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_context fin_md5; + mbedtls_sha1_context fin_sha1; +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_context fin_sha256; +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_context fin_sha512; +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); + void (*calc_verify)(mbedtls_ssl_context *, unsigned char *); + void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); + int (*tls_prf)(const unsigned char *, size_t, const char *, + const unsigned char *, size_t, + unsigned char *, size_t); + + size_t pmslen; /*!< premaster length */ + + unsigned char randbytes[64]; /*!< random bytes */ + unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; + /*!< premaster secret */ + + int resume; /*!< session resume indicator*/ + int max_major_ver; /*!< max. major version client*/ + int max_minor_ver; /*!< max. minor version client*/ + int cli_exts; /*!< client extension presence*/ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + int new_session_ticket; /*!< use NewSessionTicket? */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + int extended_ms; /*!< use Extended Master Secret? */ +#endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + unsigned int async_in_progress : 1; /*!< an asynchronous operation is in progress */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /** Asynchronous operation context. This field is meant for use by the + * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start, + * mbedtls_ssl_config::f_async_decrypt_start, + * mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel). + * The library does not use it internally. */ + void *user_async_ctx; +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +}; + +typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer; + +/* + * This structure contains a full set of runtime transform parameters + * either in negotiation or active. + */ +struct mbedtls_ssl_transform +{ + /* + * Session specific crypto layer + */ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + /*!< Chosen cipersuite_info */ + unsigned int keylen; /*!< symmetric key length (bytes) */ + size_t minlen; /*!< min. ciphertext length */ + size_t ivlen; /*!< IV length */ + size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ + size_t maclen; /*!< MAC length */ + + unsigned char iv_enc[16]; /*!< IV (encryption) */ + unsigned char iv_dec[16]; /*!< IV (decryption) */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* Needed only for SSL v3.0 secret */ + unsigned char mac_enc[20]; /*!< SSL v3.0 secret (enc) */ + unsigned char mac_dec[20]; /*!< SSL v3.0 secret (dec) */ +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + + mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ + mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ + + mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ + mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ + + /* + * Session specific compression layer + */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + z_stream ctx_deflate; /*!< compression context */ + z_stream ctx_inflate; /*!< decompression context */ +#endif +}; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * List of certificate + private key pairs + */ +struct mbedtls_ssl_key_cert +{ + mbedtls_x509_crt *cert; /*!< cert */ + mbedtls_pk_context *key; /*!< private key */ + mbedtls_ssl_key_cert *next; /*!< next key/cert pair */ +}; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * List of handshake messages kept around for resending + */ +struct mbedtls_ssl_flight_item +{ + unsigned char *p; /*!< message, including handshake headers */ + size_t len; /*!< length of p */ + unsigned char type; /*!< type of the message: handshake or CCS */ + mbedtls_ssl_flight_item *next; /*!< next handshake message(s) */ +}; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ); +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ); +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ); + +/* Setup an empty signature-hash set */ +static inline void mbedtls_ssl_sig_hash_set_init( mbedtls_ssl_sig_hash_set_t *set ) +{ + mbedtls_ssl_sig_hash_set_const_hash( set, MBEDTLS_MD_NONE ); +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +/** + * \brief Free referenced items in an SSL transform context and clear + * memory + * + * \param transform SSL transform context + */ +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); + +/** + * \brief Free referenced items in an SSL handshake context and clear + * memory + * + * \param ssl SSL context + */ +void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); + +/** + * \brief Update record layer + * + * This function roughly separates the implementation + * of the logic of (D)TLS from the implementation + * of the secure transport. + * + * \param ssl The SSL context to use. + * \param update_hs_digest This indicates if the handshake digest + * should be automatically updated in case + * a handshake message is found. + * + * \return 0 or non-zero error code. + * + * \note A clarification on what is called 'record layer' here + * is in order, as many sensible definitions are possible: + * + * The record layer takes as input an untrusted underlying + * transport (stream or datagram) and transforms it into + * a serially multiplexed, secure transport, which + * conceptually provides the following: + * + * (1) Three datagram based, content-agnostic transports + * for handshake, alert and CCS messages. + * (2) One stream- or datagram-based transport + * for application data. + * (3) Functionality for changing the underlying transform + * securing the contents. + * + * The interface to this functionality is given as follows: + * + * a Updating + * [Currently implemented by mbedtls_ssl_read_record] + * + * Check if and on which of the four 'ports' data is pending: + * Nothing, a controlling datagram of type (1), or application + * data (2). In any case data is present, internal buffers + * provide access to the data for the user to process it. + * Consumption of type (1) datagrams is done automatically + * on the next update, invalidating that the internal buffers + * for previous datagrams, while consumption of application + * data (2) is user-controlled. + * + * b Reading of application data + * [Currently manual adaption of ssl->in_offt pointer] + * + * As mentioned in the last paragraph, consumption of data + * is different from the automatic consumption of control + * datagrams (1) because application data is treated as a stream. + * + * c Tracking availability of application data + * [Currently manually through decreasing ssl->in_msglen] + * + * For efficiency and to retain datagram semantics for + * application data in case of DTLS, the record layer + * provides functionality for checking how much application + * data is still available in the internal buffer. + * + * d Changing the transformation securing the communication. + * + * Given an opaque implementation of the record layer in the + * above sense, it should be possible to implement the logic + * of (D)TLS on top of it without the need to know anything + * about the record layer's internals. This is done e.g. + * in all the handshake handling functions, and in the + * application data reading function mbedtls_ssl_read. + * + * \note The above tries to give a conceptual picture of the + * record layer, but the current implementation deviates + * from it in some places. For example, our implementation of + * the update functionality through mbedtls_ssl_read_record + * discards datagrams depending on the current state, which + * wouldn't fall under the record layer's responsibility + * following the above definition. + * + */ +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, + unsigned update_hs_digest ); +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ); + +int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ); +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ); +#endif + +#if defined(MBEDTLS_PK_C) +unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ); +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ); +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ); +#endif + +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ); +unsigned char mbedtls_ssl_hash_from_md_alg( int md ); +int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ); + +#if defined(MBEDTLS_ECP_C) +int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md ); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static inline mbedtls_pk_context *mbedtls_ssl_own_key( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_key_cert *key_cert; + + if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + key_cert = ssl->handshake->key_cert; + else + key_cert = ssl->conf->key_cert; + + return( key_cert == NULL ? NULL : key_cert->key ); +} + +static inline mbedtls_x509_crt *mbedtls_ssl_own_cert( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_key_cert *key_cert; + + if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + key_cert = ssl->handshake->key_cert; + else + key_cert = ssl->conf->key_cert; + + return( key_cert == NULL ? NULL : key_cert->cert ); +} + +/* + * Check usage of a certificate wrt extensions: + * keyUsage, extendedKeyUsage (later), and nSCertType (later). + * + * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we + * check a cert we received from them)! + * + * Return 0 if everything is OK, -1 if not. + */ +int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ); +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ); + +static inline size_t mbedtls_ssl_hdr_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 13 ); +#else + ((void) ssl); +#endif + return( 5 ); +} + +static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 12 ); +#else + ((void) ssl); +#endif + return( 4 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ); +#endif + +/* Visible for testing purposes only */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ); +#endif + +/* constant-time buffer comparison */ +static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } + + return( diff ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len ); +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ); +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) +/** \brief Compute the HMAC of variable-length data with constant flow. + * + * This function computes the HMAC of the concatenation of \p add_data and \p + * data, and does with a code flow and memory access pattern that does not + * depend on \p data_len_secret, but only on \p min_data_len and \p + * max_data_len. In particular, this function always reads exactly \p + * max_data_len bytes from \p data. + * + * \param ctx The HMAC context. It must have keys configured + * with mbedtls_md_hmac_starts() and use one of the + * following hashes: SHA-384, SHA-256, SHA-1 or MD-5. + * It is reset using mbedtls_md_hmac_reset() after + * the computation is complete to prepare for the + * next computation. + * \param add_data The additional data prepended to \p data. This + * must point to a readable buffer of \p add_data_len + * bytes. + * \param add_data_len The length of \p add_data in bytes. + * \param data The data appended to \p add_data. This must point + * to a readable buffer of \p max_data_len bytes. + * \param data_len_secret The length of the data to process in \p data. + * This must be no less than \p min_data_len and no + * greater than \p max_data_len. + * \param min_data_len The minimal length of \p data in bytes. + * \param max_data_len The maximal length of \p data in bytes. + * \param output The HMAC will be written here. This must point to + * a writable buffer of sufficient size to hold the + * HMAC value. + * + * \retval 0 + * Success. + * \retval MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED + * The hardware accelerator failed. + */ +int mbedtls_ssl_cf_hmac( + mbedtls_md_context_t *ctx, + const unsigned char *add_data, size_t add_data_len, + const unsigned char *data, size_t data_len_secret, + size_t min_data_len, size_t max_data_len, + unsigned char *output ); + +/** \brief Copy data from a secret position with constant flow. + * + * This function copies \p len bytes from \p src_base + \p offset_secret to \p + * dst, with a code flow and memory access pattern that does not depend on \p + * offset_secret, but only on \p offset_min, \p offset_max and \p len. + * + * \param dst The destination buffer. This must point to a writable + * buffer of at least \p len bytes. + * \param src_base The base of the source buffer. This must point to a + * readable buffer of at least \p offset_max + \p len + * bytes. + * \param offset_secret The offset in the source buffer from which to copy. + * This must be no less than \p offset_min and no greater + * than \p offset_max. + * \param offset_min The minimal value of \p offset_secret. + * \param offset_max The maximal value of \p offset_secret. + * \param len The number of bytes to copy. + */ +void mbedtls_ssl_cf_memcpy_offset( unsigned char *dst, + const unsigned char *src_base, + size_t offset_secret, + size_t offset_min, size_t offset_max, + size_t len ); +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_internal.h */ diff --git a/external/mbedtls/include/mbedtls/ssl_ticket.h b/external/mbedtls/include/mbedtls/ssl_ticket.h new file mode 100644 index 0000000..a10a434 --- /dev/null +++ b/external/mbedtls/include/mbedtls/ssl_ticket.h @@ -0,0 +1,167 @@ +/** + * \file ssl_ticket.h + * + * \brief TLS server ticket callbacks implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SSL_TICKET_H +#define MBEDTLS_SSL_TICKET_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* + * This implementation of the session ticket callbacks includes key + * management, rotating the keys periodically in order to preserve forward + * secrecy, when MBEDTLS_HAVE_TIME is defined. + */ + +#include "ssl.h" +#include "cipher.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Information for session ticket protection + */ +typedef struct mbedtls_ssl_ticket_key +{ + unsigned char name[4]; /*!< random key identifier */ + uint32_t generation_time; /*!< key generation timestamp (seconds) */ + mbedtls_cipher_context_t ctx; /*!< context for auth enc/decryption */ +} +mbedtls_ssl_ticket_key; + +/** + * \brief Context for session ticket handling functions + */ +typedef struct mbedtls_ssl_ticket_context +{ + mbedtls_ssl_ticket_key keys[2]; /*!< ticket protection keys */ + unsigned char active; /*!< index of the currently active key */ + + uint32_t ticket_lifetime; /*!< lifetime of tickets in seconds */ + + /** Callback for getting (pseudo-)random numbers */ + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; /*!< context for the RNG function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ssl_ticket_context; + +/** + * \brief Initialize a ticket context. + * (Just make it ready for mbedtls_ssl_ticket_setup() + * or mbedtls_ssl_ticket_free().) + * + * \param ctx Context to be initialized + */ +void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ); + +/** + * \brief Prepare context to be actually used + * + * \param ctx Context to be set up + * \param f_rng RNG callback function + * \param p_rng RNG callback context + * \param cipher AEAD cipher to use for ticket protection. + * Recommended value: MBEDTLS_CIPHER_AES_256_GCM. + * \param lifetime Tickets lifetime in seconds + * Recommended value: 86400 (one day). + * + * \note It is highly recommended to select a cipher that is at + * least as strong as the the strongest ciphersuite + * supported. Usually that means a 256-bit key. + * + * \note The lifetime of the keys is twice the lifetime of tickets. + * It is recommended to pick a reasonnable lifetime so as not + * to negate the benefits of forward secrecy. + * + * \return 0 if successful, + * or a specific MBEDTLS_ERR_XXX error code + */ +int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_cipher_type_t cipher, + uint32_t lifetime ); + +/** + * \brief Implementation of the ticket write callback + * + * \note See \c mbedtls_ssl_ticket_write_t for description + */ +mbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write; + +/** + * \brief Implementation of the ticket parse callback + * + * \note See \c mbedtls_ssl_ticket_parse_t for description + */ +mbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse; + +/** + * \brief Free a context's content and zeroize it. + * + * \param ctx Context to be cleaned up + */ +void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ticket.h */ diff --git a/external/mbedtls/include/mbedtls/threading.h b/external/mbedtls/include/mbedtls/threading.h new file mode 100644 index 0000000..45161ce --- /dev/null +++ b/external/mbedtls/include/mbedtls/threading.h @@ -0,0 +1,150 @@ +/** + * \file threading.h + * + * \brief Threading abstraction layer + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_THREADING_H +#define MBEDTLS_THREADING_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ +#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */ + +#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */ + +#if defined(MBEDTLS_THREADING_PTHREAD) +#include +typedef struct mbedtls_threading_mutex_t +{ + pthread_mutex_t mutex; + /* is_valid is 0 after a failed init or a free, and nonzero after a + * successful init. This field is not considered part of the public + * API of Mbed TLS and may change without notice. */ + char is_valid; +} mbedtls_threading_mutex_t; +#endif + +#if defined(MBEDTLS_THREADING_ALT) +/* You should define the mbedtls_threading_mutex_t type in your header */ +#include "threading_alt.h" + +/** + * \brief Set your alternate threading implementation function + * pointers and initialize global mutexes. If used, this + * function must be called once in the main thread before any + * other mbed TLS function is called, and + * mbedtls_threading_free_alt() must be called once in the main + * thread after all other mbed TLS functions. + * + * \note mutex_init() and mutex_free() don't return a status code. + * If mutex_init() fails, it should leave its argument (the + * mutex) in a state such that mutex_lock() will fail when + * called with this argument. + * + * \param mutex_init the init function implementation + * \param mutex_free the free function implementation + * \param mutex_lock the lock function implementation + * \param mutex_unlock the unlock function implementation + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ); + +/** + * \brief Free global mutexes. + */ +void mbedtls_threading_free_alt( void ); +#endif /* MBEDTLS_THREADING_ALT */ + +#if defined(MBEDTLS_THREADING_C) +/* + * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock + * + * All these functions are expected to work or the result will be undefined. + */ +extern void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t *mutex ); +extern void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); + +/* + * Global mutexes + */ +#if defined(MBEDTLS_FS_IO) +extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +/* This mutex may or may not be used in the default definition of + * mbedtls_platform_gmtime_r(), but in order to determine that, + * we need to check POSIX features, hence modify _POSIX_C_SOURCE. + * With the current approach, this declaration is orphaned, lacking + * an accompanying definition, in case mbedtls_platform_gmtime_r() + * doesn't need it, but that's not a problem. */ +extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + +#endif /* MBEDTLS_THREADING_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* threading.h */ diff --git a/external/mbedtls/include/mbedtls/timing.h b/external/mbedtls/include/mbedtls/timing.h new file mode 100644 index 0000000..8611ba9 --- /dev/null +++ b/external/mbedtls/include/mbedtls/timing.h @@ -0,0 +1,178 @@ +/** + * \file timing.h + * + * \brief Portable interface to timeouts and to the CPU cycle counter + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_TIMING_H +#define MBEDTLS_TIMING_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_TIMING_ALT) +// Regular implementation +// + +/** + * \brief timer structure + */ +struct mbedtls_timing_hr_time +{ + unsigned char opaque[32]; +}; + +/** + * \brief Context for mbedtls_timing_set/get_delay() + */ +typedef struct mbedtls_timing_delay_context +{ + struct mbedtls_timing_hr_time timer; + uint32_t int_ms; + uint32_t fin_ms; +} mbedtls_timing_delay_context; + +#else /* MBEDTLS_TIMING_ALT */ +#include "timing_alt.h" +#endif /* MBEDTLS_TIMING_ALT */ + +extern volatile int mbedtls_timing_alarmed; + +/** + * \brief Return the CPU cycle counter value + * + * \warning This is only a best effort! Do not rely on this! + * In particular, it is known to be unreliable on virtual + * machines. + * + * \note This value starts at an unspecified origin and + * may wrap around. + */ +unsigned long mbedtls_timing_hardclock( void ); + +/** + * \brief Return the elapsed time in milliseconds + * + * \param val points to a timer structure + * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. + * + * \return Elapsed time since the previous reset in ms. When + * restarting, this is always 0. + * + * \note To initialize a timer, call this function with reset=1. + * + * Determining the elapsed time and resetting the timer is not + * atomic on all platforms, so after the sequence + * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = + * get_timer(0) }` the value time1+time2 is only approximately + * the delay since the first reset. + */ +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ); + +/** + * \brief Setup an alarm clock + * + * \param seconds delay before the "mbedtls_timing_alarmed" flag is set + * (must be >=0) + * + * \warning Only one alarm at a time is supported. In a threaded + * context, this means one for the whole process, not one per + * thread. + */ +void mbedtls_set_alarm( int seconds ); + +/** + * \brief Set a pair of delays to watch + * (See \c mbedtls_timing_get_delay().) + * + * \param data Pointer to timing data. + * Must point to a valid \c mbedtls_timing_delay_context struct. + * \param int_ms First (intermediate) delay in milliseconds. + * The effect if int_ms > fin_ms is unspecified. + * \param fin_ms Second (final) delay in milliseconds. + * Pass 0 to cancel the current delay. + * + * \note To set a single delay, either use \c mbedtls_timing_set_timer + * directly or use this function with int_ms == fin_ms. + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); + +/** + * \brief Get the status of delays + * (Memory helper: number of delays passed.) + * + * \param data Pointer to timing data + * Must point to a valid \c mbedtls_timing_delay_context struct. + * + * \return -1 if cancelled (fin_ms = 0), + * 0 if none of the delays are passed, + * 1 if only the intermediate delay is passed, + * 2 if the final delay is passed. + */ +int mbedtls_timing_get_delay( void *data ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_timing_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* timing.h */ diff --git a/external/mbedtls/include/mbedtls/version.h b/external/mbedtls/include/mbedtls/version.h new file mode 100644 index 0000000..bd5c730 --- /dev/null +++ b/external/mbedtls/include/mbedtls/version.h @@ -0,0 +1,137 @@ +/** + * \file version.h + * + * \brief Run-time version information + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * This set of compile-time defines and run-time variables can be used to + * determine the version number of the mbed TLS library used. + */ +#ifndef MBEDTLS_VERSION_H +#define MBEDTLS_VERSION_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define MBEDTLS_VERSION_MAJOR 2 +#define MBEDTLS_VERSION_MINOR 16 +#define MBEDTLS_VERSION_PATCH 10 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define MBEDTLS_VERSION_NUMBER 0x02100A00 +#define MBEDTLS_VERSION_STRING "2.16.10" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.10" + +#if defined(MBEDTLS_VERSION_C) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get the version number. + * + * \return The constructed version number in the format + * MMNNPP00 (Major, Minor, Patch). + */ +unsigned int mbedtls_version_get_number( void ); + +/** + * Get the version string ("x.y.z"). + * + * \param string The string that will receive the value. + * (Should be at least 9 bytes in size) + */ +void mbedtls_version_get_string( char *string ); + +/** + * Get the full version string ("mbed TLS x.y.z"). + * + * \param string The string that will receive the value. The mbed TLS version + * string will use 18 bytes AT MOST including a terminating + * null byte. + * (So the buffer should be at least 18 bytes to receive this + * version string). + */ +void mbedtls_version_get_string_full( char *string ); + +/** + * \brief Check if support for a feature was compiled into this + * mbed TLS binary. This allows you to see at runtime if the + * library was for instance compiled with or without + * Multi-threading support. + * + * \note only checks against defines in the sections "System + * support", "mbed TLS modules" and "mbed TLS feature + * support" in config.h + * + * \param feature The string for the define to check (e.g. "MBEDTLS_AES_C") + * + * \return 0 if the feature is present, + * -1 if the feature is not present and + * -2 if support for feature checking as a whole was not + * compiled in. + */ +int mbedtls_version_check_feature( const char *feature ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_VERSION_C */ + +#endif /* version.h */ diff --git a/external/mbedtls/include/mbedtls/x509.h b/external/mbedtls/include/mbedtls/x509.h new file mode 100644 index 0000000..5bb9b00 --- /dev/null +++ b/external/mbedtls/include/mbedtls/x509.h @@ -0,0 +1,362 @@ +/** + * \file x509.h + * + * \brief X.509 generic defines and structures + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_X509_H +#define MBEDTLS_X509_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "asn1.h" +#include "pk.h" + +#if defined(MBEDTLS_RSA_C) +#include "rsa.h" +#endif + +/** + * \addtogroup x509_module + * \{ + */ + +#if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) +/** + * Maximum number of intermediate CAs in a verification chain. + * That is, maximum length of the chain, excluding the end-entity certificate + * and the trusted root certificate. + * + * Set this to a low value to prevent an adversary from making you waste + * resources verifying an overlong certificate chain. + */ +#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 +#endif + +/** + * \name X509 Error codes + * \{ + */ +#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */ +#define MBEDTLS_ERR_X509_UNKNOWN_OID -0x2100 /**< Requested OID is unknown. */ +#define MBEDTLS_ERR_X509_INVALID_FORMAT -0x2180 /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */ +#define MBEDTLS_ERR_X509_INVALID_VERSION -0x2200 /**< The CRT/CRL/CSR version element is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SIGNATURE -0x2480 /**< The signature tag or value invalid. */ +#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS -0x2500 /**< The extension tag or value is invalid. */ +#define MBEDTLS_ERR_X509_UNKNOWN_VERSION -0x2580 /**< CRT/CRL/CSR has an unsupported version number. */ +#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /**< Signature algorithm (oid) is unsupported. */ +#define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 /**< Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ +#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ +#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /**< Format not recognized as DER or PEM. */ +#define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 /**< Input invalid. */ +#define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /**< Destination buffer is too small. */ +#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 /**< A fatal error occurred, eg the chain is too long or the vrfy callback failed. */ +/* \} name */ + +/** + * \name X509 Verify codes + * \{ + */ +/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ +#define MBEDTLS_X509_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ +#define MBEDTLS_X509_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ +#define MBEDTLS_X509_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ +#define MBEDTLS_X509_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ +#define MBEDTLS_X509_BADCERT_MISSING 0x40 /**< Certificate was missing. */ +#define MBEDTLS_X509_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ +#define MBEDTLS_X509_BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ +#define MBEDTLS_X509_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ +#define MBEDTLS_X509_BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ +#define MBEDTLS_X509_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ +#define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ +#define MBEDTLS_X509_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ +#define MBEDTLS_X509_BADCERT_BAD_MD 0x4000 /**< The certificate is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCERT_BAD_PK 0x8000 /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCERT_BAD_KEY 0x010000 /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ +#define MBEDTLS_X509_BADCRL_BAD_MD 0x020000 /**< The CRL is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ + +/* \} name */ +/* \} addtogroup x509_module */ + +/* + * X.509 v3 Key Usage Extension flags + * Reminder: update x509_info_key_usage() when adding new flags. + */ +#define MBEDTLS_X509_KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ +#define MBEDTLS_X509_KU_NON_REPUDIATION (0x40) /* bit 1 */ +#define MBEDTLS_X509_KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ +#define MBEDTLS_X509_KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ +#define MBEDTLS_X509_KU_KEY_AGREEMENT (0x08) /* bit 4 */ +#define MBEDTLS_X509_KU_KEY_CERT_SIGN (0x04) /* bit 5 */ +#define MBEDTLS_X509_KU_CRL_SIGN (0x02) /* bit 6 */ +#define MBEDTLS_X509_KU_ENCIPHER_ONLY (0x01) /* bit 7 */ +#define MBEDTLS_X509_KU_DECIPHER_ONLY (0x8000) /* bit 8 */ + +/* + * Netscape certificate types + * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) + */ + +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ +#define MBEDTLS_X509_NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ + +/* + * X.509 extension types + * + * Comments refer to the status for using certificates. Status can be + * different for writing certificates or reading CRLs or CSRs. + */ +#define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) +#define MBEDTLS_X509_EXT_KEY_USAGE (1 << 2) +#define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES (1 << 3) +#define MBEDTLS_X509_EXT_POLICY_MAPPINGS (1 << 4) +#define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME (1 << 5) /* Supported (DNS) */ +#define MBEDTLS_X509_EXT_ISSUER_ALT_NAME (1 << 6) +#define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) +#define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS (1 << 8) /* Supported */ +#define MBEDTLS_X509_EXT_NAME_CONSTRAINTS (1 << 9) +#define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS (1 << 10) +#define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) +#define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) +#define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) +#define MBEDTLS_X509_EXT_FRESHEST_CRL (1 << 14) + +#define MBEDTLS_X509_EXT_NS_CERT_TYPE (1 << 16) + +/* + * Storage format identifiers + * Recognized formats: PEM and DER + */ +#define MBEDTLS_X509_FORMAT_DER 1 +#define MBEDTLS_X509_FORMAT_PEM 2 + +#define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures for parsing X.509 certificates, CRLs and CSRs + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef mbedtls_asn1_buf mbedtls_x509_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef mbedtls_asn1_bitstring mbedtls_x509_bitstring; + +/** + * Container for ASN1 named information objects. + * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). + */ +typedef mbedtls_asn1_named_data mbedtls_x509_name; + +/** + * Container for a sequence of ASN.1 items + */ +typedef mbedtls_asn1_sequence mbedtls_x509_sequence; + +/** Container for date and time (precision in seconds). */ +typedef struct mbedtls_x509_time +{ + int year, mon, day; /**< Date. */ + int hour, min, sec; /**< Time. */ +} +mbedtls_x509_time; + +/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ +/** \} addtogroup x509_module */ + +/** + * \brief Store the certificate DN in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param dn The X509 name to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ); + +/** + * \brief Store the certificate serial in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param serial The X509 serial to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the past. + * + * \note Intended usage is "if( is_past( valid_to ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param to mbedtls_x509_time to check + * + * \return 1 if the given time is in the past or an error occurred, + * 0 otherwise. + */ +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the future. + * + * \note Intended usage is "if( is_future( valid_from ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param from mbedtls_x509_time to check + * + * \return 1 if the given time is in the future or an error occurred, + * 0 otherwise. + */ +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_x509_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ); +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ); +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ); +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ); +#endif +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ); +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ); +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *t ); +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ); +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ); +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ); +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ); +int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ); +int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, + size_t val_len ); +int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ); + +#define MBEDTLS_X509_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +#ifdef __cplusplus +} +#endif + +#endif /* x509.h */ diff --git a/external/mbedtls/include/mbedtls/x509_crl.h b/external/mbedtls/include/mbedtls/x509_crl.h new file mode 100644 index 0000000..2ade47c --- /dev/null +++ b/external/mbedtls/include/mbedtls/x509_crl.h @@ -0,0 +1,199 @@ +/** + * \file x509_crl.h + * + * \brief X.509 certificate revocation list parsing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_X509_CRL_H +#define MBEDTLS_X509_CRL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for parsing CRLs + * \{ + */ + +/** + * Certificate revocation list entry. + * Contains the CA-specific serial numbers and revocation dates. + */ +typedef struct mbedtls_x509_crl_entry +{ + mbedtls_x509_buf raw; + + mbedtls_x509_buf serial; + + mbedtls_x509_time revocation_date; + + mbedtls_x509_buf entry_ext; + + struct mbedtls_x509_crl_entry *next; +} +mbedtls_x509_crl_entry; + +/** + * Certificate revocation list structure. + * Every CRL may have multiple entries. + */ +typedef struct mbedtls_x509_crl +{ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< CRL version (1=v1, 2=v2) */ + mbedtls_x509_buf sig_oid; /**< CRL signature type identifier */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + + mbedtls_x509_time this_update; + mbedtls_x509_time next_update; + + mbedtls_x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ + + mbedtls_x509_buf crl_ext; + + mbedtls_x509_buf sig_oid2; + mbedtls_x509_buf sig; + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crl *next; +} +mbedtls_x509_crl; + +/** + * \brief Parse a DER-encoded CRL and append it to the chained list + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ); +/** + * \brief Parse one or more CRLs and append them to the chained list + * + * \note Multiple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more CRLs and append them to the chained list + * + * \note Multiple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param path filename to read the CRLs from (in PEM or DER encoding) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the CRL. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crl The X509 CRL to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ); + +/** + * \brief Initialize a CRL (chain) + * + * \param crl CRL chain to initialize + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ); + +/** + * \brief Unallocate all CRL data + * + * \param crl CRL chain to free + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ); + +/* \} name */ +/* \} addtogroup x509_module */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crl.h */ diff --git a/external/mbedtls/include/mbedtls/x509_crt.h b/external/mbedtls/include/mbedtls/x509_crt.h new file mode 100644 index 0000000..c38e0c0 --- /dev/null +++ b/external/mbedtls/include/mbedtls/x509_crt.h @@ -0,0 +1,810 @@ +/** + * \file x509_crt.h + * + * \brief X.509 certificate parsing and writing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_X509_CRT_H +#define MBEDTLS_X509_CRT_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "x509.h" +#include "x509_crl.h" + +/** + * \addtogroup x509_module + * \{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Structures and functions for parsing and writing X.509 certificates + * \{ + */ + +/** + * Container for an X.509 certificate. The certificate may be chained. + */ +typedef struct mbedtls_x509_crt +{ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ + mbedtls_x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ + mbedtls_x509_buf sig_oid; /**< Signature algorithm, e.g. sha1RSA */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_x509_time valid_from; /**< Start time of certificate validity. */ + mbedtls_x509_time valid_to; /**< End time of certificate validity. */ + + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ + mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ + mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ + mbedtls_x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */ + + int ext_types; /**< Bit string containing detected and parsed extensions */ + int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ + int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ + + unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ + + mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ + + unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ + + mbedtls_x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */ +} +mbedtls_x509_crt; + +/** + * Build flag from an algorithm/curve identifier (pk, md, ecp) + * Since 0 is always XXX_NONE, ignore it. + */ +#define MBEDTLS_X509_ID_FLAG( id ) ( 1 << ( (id) - 1 ) ) + +/** + * Security profile for certificate verification. + * + * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). + */ +typedef struct mbedtls_x509_crt_profile +{ + uint32_t allowed_mds; /**< MDs for signatures */ + uint32_t allowed_pks; /**< PK algs for signatures */ + uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ + uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ +} +mbedtls_x509_crt_profile; + +#define MBEDTLS_X509_CRT_VERSION_1 0 +#define MBEDTLS_X509_CRT_VERSION_2 1 +#define MBEDTLS_X509_CRT_VERSION_3 2 + +#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 32 +#define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 + +#if !defined( MBEDTLS_X509_MAX_FILE_PATH_LEN ) +#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 +#endif + +/** + * Container for writing a certificate (CRT) + */ +typedef struct mbedtls_x509write_cert +{ + int version; + mbedtls_mpi serial; + mbedtls_pk_context *subject_key; + mbedtls_pk_context *issuer_key; + mbedtls_asn1_named_data *subject; + mbedtls_asn1_named_data *issuer; + mbedtls_md_type_t md_alg; + char not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + char not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_cert; + +/** + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *crt; + uint32_t flags; +} mbedtls_x509_crt_verify_chain_item; + +/** + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) + +/** + * Verification chain as built by \c mbedtls_crt_verify_chain() + */ +typedef struct +{ + mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE]; + unsigned len; +} mbedtls_x509_crt_verify_chain; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Context for resuming X.509 verify operations + */ +typedef struct +{ + /* for check_signature() */ + mbedtls_pk_restart_ctx pk; + + /* for find_parent_in() */ + mbedtls_x509_crt *parent; /* non-null iff parent_in in progress */ + mbedtls_x509_crt *fallback_parent; + int fallback_signature_is_good; + + /* for find_parent() */ + int parent_is_trusted; /* -1 if find_parent is not in progress */ + + /* for verify_chain() */ + enum { + x509_crt_rs_none, + x509_crt_rs_find_parent, + } in_progress; /* none if no operation is in progress */ + int self_cnt; + mbedtls_x509_crt_verify_chain ver_chain; + +} mbedtls_x509_crt_restart_ctx; + +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_x509_crt_restart_ctx; + +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * Default security profile. Should provide a good balance between security + * and compatibility with current deployments. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; + +/** + * Expected next default profile. Recommended for new deployments. + * Currently targets a 128-bit security level, except for RSA-2048. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; + +/** + * NSA Suite B profile. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; + +/** + * \brief Parse a single DER formatted certificate and add it + * to the chained list. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate DER data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, + size_t buflen ); + +/** + * \brief Parse one DER-encoded or one or more concatenated PEM-encoded + * certificates and add them to the chained list. + * + * For CRTs in PEM encoding, the function parses permissively: + * if at least one certificate can be parsed, the function + * returns the number of certificates for which parsing failed + * (hence \c 0 if all certificates were parsed successfully). + * If no certificate could be parsed, the function returns + * the first (negative) error encountered during parsing. + * + * PEM encoded certificates may be interleaved by other data + * such as human readable descriptions of their content, as + * long as the certificates are enclosed in the PEM specific + * '-----{BEGIN/END} CERTIFICATE-----' delimiters. + * + * \param chain The chain to which to add the parsed certificates. + * \param buf The buffer holding the certificate data in PEM or DER format. + * For certificates in PEM encoding, this may be a concatenation + * of multiple certificates; for DER encoding, the buffer must + * comprise exactly one certificate. + * \param buflen The size of \p buf, including the terminating \c NULL byte + * in case of PEM encoded data. + * + * \return \c 0 if all certificates were parsed successfully. + * \return The (positive) number of certificates that couldn't + * be parsed if parsing was partly successful (see above). + * \return A negative X509 or PEM error code otherwise. + * + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path filename to read the certificates from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ); + +/** + * \brief Load one or more certificate files from a path and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path directory / folder to read the certificate files from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the + * certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crt The X509 certificate to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ); + +/** + * \brief Returns an informational string about the + * verification status of a certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param flags Verification flags created by mbedtls_x509_crt_verify() + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ); + +/** + * \brief Verify the certificate signature + * + * The verify callback is a user-supplied callback that + * can clear / modify / add flags for a certificate. If set, + * the verification callback is called for each + * certificate in the chain (from the trust-ca down to the + * presented crt). The parameters for the callback are: + * (void *parameter, mbedtls_x509_crt *crt, int certificate_depth, + * int *flags). With the flags representing current flags for + * that specific certificate and the certificate depth from + * the bottom (Peer cert depth = 0). + * + * All flags left after returning from the callback + * are also returned to the application. The function should + * return 0 for anything (including invalid certificates) + * other than fatal error, as a non-zero return code + * immediately aborts the verification process. For fatal + * errors, a specific error code should be used (different + * from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not + * be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR + * can be used if no better code is available. + * + * \note In case verification failed, the results can be displayed + * using \c mbedtls_x509_crt_verify_info() + * + * \note Same as \c mbedtls_x509_crt_verify_with_profile() with the + * default security profile. + * + * \note It is your responsibility to provide up-to-date CRLs for + * all trusted CAs. If no CRL is provided for the CA that was + * used to sign the certificate, CRL verification is skipped + * silently, that is *without* setting any flag. + * + * \note The \c trust_ca list can contain two types of certificates: + * (1) those of trusted root CAs, so that certificates + * chaining up to those CAs will be trusted, and (2) + * self-signed end-entity certificates to be trusted (for + * specific peers you know) - in that case, the self-signed + * certificate doesn't need to have the CA bit set. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs (see note above) + * \param ca_crl the list of CRLs for trusted CAs (see note above) + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 (and flags set to 0) if the chain was verified and valid, + * MBEDTLS_ERR_X509_CERT_VERIFY_FAILED if the chain was verified + * but found to be invalid, in which case *flags will have one + * or more MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX + * flags set, or another error (and flags set to 0xffffffff) + * in case of a fatal error encountered during the + * verification process. + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +/** + * \brief Verify the certificate signature according to profile + * + * \note Same as \c mbedtls_x509_crt_verify(), but with explicit + * security profile. + * + * \note The restrictions on keys (RSA minimum size, allowed curves + * for ECDSA) apply to all certificates: trusted root, + * intermediate CAs if any, and end entity certificate. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs + * \param ca_crl the list of CRLs for trusted CAs + * \param profile security profile for verification + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED + * in which case *flags will have one or more + * MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags + * set, + * or another error in case of a fatal error encountered + * during the verification process. + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +/** + * \brief Restartable version of \c mbedtls_crt_verify_with_profile() + * + * \note Performs the same job as \c mbedtls_crt_verify_with_profile() + * but can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs + * \param ca_crl the list of CRLs for trusted CAs + * \param profile security profile for verification + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * \param rs_ctx restart context (NULL to disable restart) + * + * \return See \c mbedtls_crt_verify_with_profile(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ); + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +/** + * \brief Check usage of certificate against keyUsage extension. + * + * \param crt Leaf certificate used. + * \param usage Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT + * before using the certificate to perform an RSA key + * exchange). + * + * \note Except for decipherOnly and encipherOnly, a bit set in the + * usage argument means this bit MUST be set in the + * certificate. For decipherOnly and encipherOnly, it means + * that bit MAY be set. + * + * \return 0 is these uses of the certificate are allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension + * is present but does not match the usage argument. + * + * \note You should only call this function on leaf certificates, on + * (intermediate) CAs the keyUsage extension is automatically + * checked by \c mbedtls_x509_crt_verify(). + */ +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ); +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE) */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +/** + * \brief Check usage of certificate against extendedKeyUsage. + * + * \param crt Leaf certificate used. + * \param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or + * MBEDTLS_OID_CLIENT_AUTH). + * \param usage_len Length of usage_oid (eg given by MBEDTLS_OID_SIZE()). + * + * \return 0 if this use of the certificate is allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if not. + * + * \note Usually only makes sense on leaf certificates. + */ +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ); +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/** + * \brief Verify the certificate revocation status + * + * \param crt a certificate to be verified + * \param crl the CRL to verify against + * + * \return 1 if the certificate is revoked, 0 otherwise + * + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ); +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/** + * \brief Initialize a certificate (chain) + * + * \param crt Certificate chain to initialize + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ); + +/** + * \brief Unallocate all certificate data + * + * \param crt Certificate chain to free + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + */ +void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(MBEDTLS_X509_CRT_WRITE_C) +/** + * \brief Initialize a CRT writing context + * + * \param ctx CRT context to initialize + */ +void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ); + +/** + * \brief Set the verion for a Certificate + * Default: MBEDTLS_X509_CRT_VERSION_3 + * + * \param ctx CRT context to use + * \param version version to set (MBEDTLS_X509_CRT_VERSION_1, MBEDTLS_X509_CRT_VERSION_2 or + * MBEDTLS_X509_CRT_VERSION_3) + */ +void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ); + +/** + * \brief Set the serial number for a Certificate. + * + * \param ctx CRT context to use + * \param serial serial number to set + * + * \return 0 if successful + */ +int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ); + +/** + * \brief Set the validity period for a Certificate + * Timestamps should be in string format for UTC timezone + * i.e. "YYYYMMDDhhmmss" + * e.g. "20131231235959" for December 31st 2013 + * at 23:59:59 + * + * \param ctx CRT context to use + * \param not_before not_before timestamp + * \param not_after not_after timestamp + * + * \return 0 if timestamp was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, + const char *not_after ); + +/** + * \brief Set the issuer name for a Certificate + * Issuer names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS CA" + * + * \param ctx CRT context to use + * \param issuer_name issuer name to set + * + * \return 0 if issuer name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, + const char *issuer_name ); + +/** + * \brief Set the subject name for a Certificate + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CRT context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, + const char *subject_name ); + +/** + * \brief Set the subject public key for the certificate + * + * \param ctx CRT context to use + * \param key public key to include + */ +void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the issuer key used for signing the certificate + * + * \param ctx CRT context to use + * \param key private key to sign with + */ +void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \param ctx CRT context to use + * \param md_alg MD algorithm to use + */ +void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ); + +/** + * \brief Generic function to add to or replace an extension in the + * CRT + * + * \param ctx CRT context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param critical if the extension is critical (per the RFC's definition) + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ); + +/** + * \brief Set the basicConstraints extension for a CRT + * + * \param ctx CRT context to use + * \param is_ca is this a CA certificate + * \param max_pathlen maximum length of certificate chains below this + * certificate (only for CA certificates, -1 is + * inlimited) + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, + int is_ca, int max_pathlen ); + +#if defined(MBEDTLS_SHA1_C) +/** + * \brief Set the subjectKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_subject_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ); + +/** + * \brief Set the authorityKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_issuer_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ); +#endif /* MBEDTLS_SHA1_C */ + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CRT context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, + unsigned int key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CRT context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Free the contents of a CRT write context + * + * \param ctx CRT context to free + */ +void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ); + +/** + * \brief Write a built up certificate to a X509 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a built up certificate to a X509 PEM string + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CRT_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crt.h */ diff --git a/external/mbedtls/include/mbedtls/x509_csr.h b/external/mbedtls/include/mbedtls/x509_csr.h new file mode 100644 index 0000000..5dfb421 --- /dev/null +++ b/external/mbedtls/include/mbedtls/x509_csr.h @@ -0,0 +1,332 @@ +/** + * \file x509_csr.h + * + * \brief X.509 certificate signing request parsing and writing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_X509_CSR_H +#define MBEDTLS_X509_CSR_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for X.509 Certificate Signing Requests (CSR) + * \{ + */ + +/** + * Certificate Signing Request (CSR) structure. + */ +typedef struct mbedtls_x509_csr +{ + mbedtls_x509_buf raw; /**< The raw CSR data (DER). */ + mbedtls_x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */ + + int version; /**< CSR version (1=v1). */ + + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf sig_oid; + mbedtls_x509_buf sig; + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ +} +mbedtls_x509_csr; + +/** + * Container for writing a CSR + */ +typedef struct mbedtls_x509write_csr +{ + mbedtls_pk_context *key; + mbedtls_asn1_named_data *subject; + mbedtls_md_type_t md_alg; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_csr; + +#if defined(MBEDTLS_X509_CSR_PARSE_C) +/** + * \brief Load a Certificate Signing Request (CSR) in DER format + * + * \note CSR attributes (if any) are currently silently ignored. + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 error code + */ +int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen ); + +/** + * \brief Load a Certificate Signing Request (CSR), DER or PEM format + * + * \note See notes for \c mbedtls_x509_csr_parse_der() + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load a Certificate Signing Request (CSR) + * + * \note See notes for \c mbedtls_x509_csr_parse() + * + * \param csr CSR context to fill + * \param path filename to read the CSR from + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the + * CSR. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param csr The X509 CSR to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_csr *csr ); + +/** + * \brief Initialize a CSR + * + * \param csr CSR to initialize + */ +void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ); + +/** + * \brief Unallocate all CSR data + * + * \param csr CSR to free + */ +void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ); +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(MBEDTLS_X509_CSR_WRITE_C) +/** + * \brief Initialize a CSR context + * + * \param ctx CSR context to initialize + */ +void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ); + +/** + * \brief Set the subject name for a CSR + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CSR context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, + const char *subject_name ); + +/** + * \brief Set the key for a CSR (public key will be included, + * private key used to sign the CSR when writing it) + * + * \param ctx CSR context to use + * \param key Asymetric key to include + */ +void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \param ctx CSR context to use + * \param md_alg MD algorithm to use + */ +void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ); + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CSR context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + * + * \note The decipherOnly flag from the Key Usage + * extension is represented by bit 8 (i.e. + * 0x8000), which cannot typically be represented + * in an unsigned char. Therefore, the flag + * decipherOnly (i.e. + * #MBEDTLS_X509_KU_DECIPHER_ONLY) cannot be set using this + * function. + */ +int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CSR context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Generic function to add to or replace an extension in the + * CSR + * + * \param ctx CSR context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ); + +/** + * \brief Free the contents of a CSR context + * + * \param ctx CSR context to free + */ +void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ); + +/** + * \brief Write a CSR (Certificate Signing Request) to a + * DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a CSR (Certificate Signing Request) to a + * PEM string + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CSR_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_csr.h */ diff --git a/external/mbedtls/include/mbedtls/xtea.h b/external/mbedtls/include/mbedtls/xtea.h new file mode 100644 index 0000000..cd6d375 --- /dev/null +++ b/external/mbedtls/include/mbedtls/xtea.h @@ -0,0 +1,164 @@ +/** + * \file xtea.h + * + * \brief XTEA block cipher (32-bit) + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_XTEA_H +#define MBEDTLS_XTEA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_XTEA_ENCRYPT 1 +#define MBEDTLS_XTEA_DECRYPT 0 + +#define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */ + +/* MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED -0x0029 /**< XTEA hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_XTEA_ALT) +// Regular implementation +// + +/** + * \brief XTEA context structure + */ +typedef struct mbedtls_xtea_context +{ + uint32_t k[4]; /*!< key */ +} +mbedtls_xtea_context; + +#else /* MBEDTLS_XTEA_ALT */ +#include "xtea_alt.h" +#endif /* MBEDTLS_XTEA_ALT */ + +/** + * \brief Initialize XTEA context + * + * \param ctx XTEA context to be initialized + */ +void mbedtls_xtea_init( mbedtls_xtea_context *ctx ); + +/** + * \brief Clear XTEA context + * + * \param ctx XTEA context to be cleared + */ +void mbedtls_xtea_free( mbedtls_xtea_context *ctx ); + +/** + * \brief XTEA key schedule + * + * \param ctx XTEA context to be initialized + * \param key the secret key + */ +void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ); + +/** + * \brief XTEA cipher function + * + * \param ctx XTEA context + * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, + int mode, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief XTEA CBC cipher function + * + * \param ctx XTEA context + * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT + * \param length the length of input, multiple of 8 + * \param iv initialization vector for CBC mode + * \param input input block + * \param output output block + * + * \return 0 if successful, + * MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0 + */ +int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_xtea_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* xtea.h */ diff --git a/external/mbedtls/library/CMakeLists.txt b/external/mbedtls/library/CMakeLists.txt new file mode 100644 index 0000000..4f61f99 --- /dev/null +++ b/external/mbedtls/library/CMakeLists.txt @@ -0,0 +1,187 @@ +option(USE_STATIC_MBEDTLS_LIBRARY "Build mbed TLS static library." ON) +option(USE_SHARED_MBEDTLS_LIBRARY "Build mbed TLS shared library." OFF) +option(LINK_WITH_PTHREAD "Explicitly link mbed TLS library to pthread." OFF) + +set(src_crypto + aes.c + aesni.c + arc4.c + aria.c + asn1parse.c + asn1write.c + base64.c + bignum.c + blowfish.c + camellia.c + ccm.c + chacha20.c + chachapoly.c + cipher.c + cipher_wrap.c + cmac.c + ctr_drbg.c + des.c + dhm.c + ecdh.c + ecdsa.c + ecjpake.c + ecp.c + ecp_curves.c + entropy.c + entropy_poll.c + error.c + gcm.c + havege.c + hkdf.c + hmac_drbg.c + md.c + md2.c + md4.c + md5.c + md_wrap.c + memory_buffer_alloc.c + nist_kw.c + oid.c + padlock.c + pem.c + pk.c + pk_wrap.c + pkcs12.c + pkcs5.c + pkparse.c + pkwrite.c + platform.c + platform_util.c + poly1305.c + ripemd160.c + rsa.c + rsa_internal.c + sha1.c + sha256.c + sha512.c + threading.c + timing.c + version.c + version_features.c + xtea.c +) + +set(src_x509 + certs.c + pkcs11.c + x509.c + x509_create.c + x509_crl.c + x509_crt.c + x509_csr.c + x509write_crt.c + x509write_csr.c +) + +set(src_tls + debug.c + net_sockets.c + ssl_cache.c + ssl_ciphersuites.c + ssl_cli.c + ssl_cookie.c + ssl_srv.c + ssl_ticket.c + ssl_tls.c +) + +if(CMAKE_COMPILER_IS_GNUCC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes") +endif(CMAKE_COMPILER_IS_GNUCC) + +if(CMAKE_COMPILER_IS_CLANG) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes -Wdocumentation -Wno-documentation-deprecated-sync -Wunreachable-code") +endif(CMAKE_COMPILER_IS_CLANG) + +if(UNSAFE_BUILD) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error") + set(CMAKE_C_FLAGS_ASAN "${CMAKE_C_FLAGS_ASAN} -Wno-error") + set(CMAKE_C_FLAGS_ASANDBG "${CMAKE_C_FLAGS_ASANDBG} -Wno-error") +endif(UNSAFE_BUILD) + +if(WIN32) + set(libs ${libs} ws2_32) +endif(WIN32) + +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + SET(CMAKE_C_ARCHIVE_CREATE " Scr ") + SET(CMAKE_CXX_ARCHIVE_CREATE " Scr ") + SET(CMAKE_C_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") + SET(CMAKE_CXX_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") +endif() + +if(HAIKU) + set(libs ${libs} network) +endif(HAIKU) + +if(USE_PKCS11_HELPER_LIBRARY) + set(libs ${libs} pkcs11-helper) +endif(USE_PKCS11_HELPER_LIBRARY) + +if(ENABLE_ZLIB_SUPPORT) + set(libs ${libs} ${ZLIB_LIBRARIES}) +endif(ENABLE_ZLIB_SUPPORT) + +if(LINK_WITH_PTHREAD) + set(libs ${libs} pthread) +endif() + +if (NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY) + message(FATAL_ERROR "Need to choose static or shared mbedtls build!") +endif(NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY) + +if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) + set(mbedtls_static_target "mbedtls_static") + set(mbedx509_static_target "mbedx509_static") + set(mbedcrypto_static_target "mbedcrypto_static") +elseif(USE_STATIC_MBEDTLS_LIBRARY) + set(mbedtls_static_target "mbedtls") + set(mbedx509_static_target "mbedx509") + set(mbedcrypto_static_target "mbedcrypto") +endif() + +if(USE_STATIC_MBEDTLS_LIBRARY) + add_library(${mbedcrypto_static_target} STATIC ${src_crypto}) + set_target_properties(${mbedcrypto_static_target} PROPERTIES OUTPUT_NAME mbedcrypto) + target_link_libraries(${mbedcrypto_static_target} ${libs}) + + add_library(${mbedx509_static_target} STATIC ${src_x509}) + set_target_properties(${mbedx509_static_target} PROPERTIES OUTPUT_NAME mbedx509) + target_link_libraries(${mbedx509_static_target} ${libs} ${mbedcrypto_static_target}) + + add_library(${mbedtls_static_target} STATIC ${src_tls}) + set_target_properties(${mbedtls_static_target} PROPERTIES OUTPUT_NAME mbedtls) + target_link_libraries(${mbedtls_static_target} ${libs} ${mbedx509_static_target}) + + install(TARGETS ${mbedtls_static_target} ${mbedx509_static_target} ${mbedcrypto_static_target} + DESTINATION ${LIB_INSTALL_DIR} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +endif(USE_STATIC_MBEDTLS_LIBRARY) + +if(USE_SHARED_MBEDTLS_LIBRARY) + add_library(mbedcrypto SHARED ${src_crypto}) + set_target_properties(mbedcrypto PROPERTIES VERSION 2.16.10 SOVERSION 3) + target_link_libraries(mbedcrypto ${libs}) + + add_library(mbedx509 SHARED ${src_x509}) + set_target_properties(mbedx509 PROPERTIES VERSION 2.16.10 SOVERSION 0) + target_link_libraries(mbedx509 ${libs} mbedcrypto) + + add_library(mbedtls SHARED ${src_tls}) + set_target_properties(mbedtls PROPERTIES VERSION 2.16.10 SOVERSION 12) + target_link_libraries(mbedtls ${libs} mbedx509) + + install(TARGETS mbedtls mbedx509 mbedcrypto + DESTINATION ${LIB_INSTALL_DIR} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +endif(USE_SHARED_MBEDTLS_LIBRARY) + +add_custom_target(lib DEPENDS mbedcrypto mbedx509 mbedtls) +if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) + add_dependencies(lib mbedcrypto_static mbedx509_static mbedtls_static) +endif() diff --git a/external/mbedtls/library/Makefile b/external/mbedtls/library/Makefile new file mode 100644 index 0000000..1e1b035 --- /dev/null +++ b/external/mbedtls/library/Makefile @@ -0,0 +1,203 @@ + +# Also see "include/mbedtls/config.h" + +CFLAGS ?= -O2 +WARNING_CFLAGS ?= -Wall -W -Wdeclaration-after-statement +LDFLAGS ?= + +LOCAL_CFLAGS = $(WARNING_CFLAGS) -I../include -D_FILE_OFFSET_BITS=64 +LOCAL_LDFLAGS = + +ifdef DEBUG +LOCAL_CFLAGS += -g3 +endif + +# MicroBlaze specific options: +# CFLAGS += -mno-xl-soft-mul -mxl-barrel-shift + +# To compile on Plan9: +# CFLAGS += -D_BSD_EXTENSION + +# if were running on Windows build for Windows +ifdef WINDOWS +WINDOWS_BUILD=1 +else ifeq ($(shell uname -s),Darwin) +ifeq ($(AR),ar) +APPLE_BUILD ?= 1 +endif +endif + +# To compile as a shared library: +ifdef SHARED +# all code is position-indep with mingw, avoid warning about useless flag +ifndef WINDOWS_BUILD +LOCAL_CFLAGS += -fPIC -fpic +endif +endif + +SOEXT_TLS=so.12 +SOEXT_X509=so.0 +SOEXT_CRYPTO=so.3 + +# Set AR_DASH= (empty string) to use an ar implementation that does not accept +# the - prefix for command line options (e.g. llvm-ar) +AR_DASH ?= - + +ARFLAGS = $(AR_DASH)src +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) +ARFLAGS = $(AR_DASH)Src +RLFLAGS = -no_warning_for_no_symbols -c +RL ?= ranlib +endif +endif + +DLEXT ?= so +ifdef WINDOWS_BUILD +# Windows shared library extension: +DLEXT = dll +else ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) +# Mac OS X shared library extension: +DLEXT = dylib +endif +endif + +OBJS_CRYPTO= aes.o aesni.o arc4.o \ + aria.o asn1parse.o asn1write.o \ + base64.o bignum.o blowfish.o \ + camellia.o ccm.o chacha20.o \ + chachapoly.o cipher.o cipher_wrap.o \ + cmac.o ctr_drbg.o des.o \ + dhm.o ecdh.o ecdsa.o \ + ecjpake.o ecp.o \ + ecp_curves.o entropy.o entropy_poll.o \ + error.o gcm.o havege.o \ + hkdf.o \ + hmac_drbg.o md.o md2.o \ + md4.o md5.o md_wrap.o \ + memory_buffer_alloc.o nist_kw.o \ + oid.o padlock.o pem.o \ + pk.o pk_wrap.o pkcs12.o \ + pkcs5.o pkparse.o pkwrite.o \ + platform.o platform_util.o poly1305.o \ + ripemd160.o rsa_internal.o rsa.o \ + sha1.o sha256.o sha512.o \ + threading.o timing.o version.o \ + version_features.o xtea.o + +OBJS_X509= certs.o pkcs11.o x509.o \ + x509_create.o x509_crl.o x509_crt.o \ + x509_csr.o x509write_crt.o x509write_csr.o + +OBJS_TLS= debug.o net_sockets.o \ + ssl_cache.o ssl_ciphersuites.o \ + ssl_cli.o ssl_cookie.o \ + ssl_srv.o ssl_ticket.o \ + ssl_tls.o + +.SILENT: + +.PHONY: all static shared clean + +ifndef SHARED +all: static +else +all: shared static +endif + +static: libmbedcrypto.a libmbedx509.a libmbedtls.a + +shared: libmbedcrypto.$(DLEXT) libmbedx509.$(DLEXT) libmbedtls.$(DLEXT) + +# tls +libmbedtls.a: $(OBJS_TLS) + echo " AR $@" + $(AR) $(ARFLAGS) $@ $(OBJS_TLS) +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) + echo " RL $@" + $(RL) $(RLFLAGS) $@ +endif +endif + +libmbedtls.$(SOEXT_TLS): $(OBJS_TLS) libmbedx509.so + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto -lmbedx509 $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_TLS) + +libmbedtls.so: libmbedtls.$(SOEXT_TLS) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedtls.dylib: $(OBJS_TLS) libmbedx509.dylib + echo " LD $@" + $(CC) -dynamiclib -L. -lmbedcrypto -lmbedx509 $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_TLS) + +libmbedtls.dll: $(OBJS_TLS) libmbedx509.dll + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_TLS) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -lmbedx509 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +# x509 +libmbedx509.a: $(OBJS_X509) + echo " AR $@" + $(AR) $(ARFLAGS) $@ $(OBJS_X509) +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) + echo " RL $@" + $(RL) $(RLFLAGS) $@ +endif +endif + +libmbedx509.$(SOEXT_X509): $(OBJS_X509) libmbedcrypto.so + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509) + +libmbedx509.so: libmbedx509.$(SOEXT_X509) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedx509.dylib: $(OBJS_X509) libmbedcrypto.dylib + echo " LD $@" + $(CC) -dynamiclib -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509) + +libmbedx509.dll: $(OBJS_X509) libmbedcrypto.dll + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_X509) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +# crypto +libmbedcrypto.a: $(OBJS_CRYPTO) + echo " AR $@" + $(AR) $(ARFLAGS) $@ $(OBJS_CRYPTO) +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) + echo " RL $@" + $(RL) $(RLFLAGS) $@ +endif +endif + +libmbedcrypto.$(SOEXT_CRYPTO): $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO) + +libmbedcrypto.so: libmbedcrypto.$(SOEXT_CRYPTO) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedcrypto.dylib: $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -dynamiclib $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO) + +libmbedcrypto.dll: $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_CRYPTO) -lws2_32 -lwinmm -lgdi32 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +.c.o: + echo " CC $<" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -c $< + +clean: +ifndef WINDOWS + rm -f *.o libmbed* +else + del /Q /F *.o libmbed* +endif diff --git a/external/mbedtls/library/aes.c b/external/mbedtls/library/aes.c new file mode 100644 index 0000000..da0e5b6 --- /dev/null +++ b/external/mbedtls/library/aes.c @@ -0,0 +1,2243 @@ +/* + * FIPS-197 compliant AES implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_AES_C) + +#include + +#include "mbedtls/aes.h" +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif +#if defined(MBEDTLS_AESNI_C) +#include "mbedtls/aesni.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_AES_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define AES_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA ) +#define AES_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +#if defined(MBEDTLS_PADLOCK_C) && \ + ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) ) +static int aes_padlock_ace = -1; +#endif + +#if defined(MBEDTLS_AES_ROM_TABLES) +/* + * Forward S-box + */ +static const unsigned char FSb[256] = +{ + 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 +}; + +/* + * Forward tables + */ +#define FT \ +\ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t FT0[256] = { FT }; +#undef V + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t FT3[256] = { FT }; +#undef V + +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = +{ + 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 +}; + +/* + * Reverse tables + */ +#define RT \ +\ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t RT0[256] = { RT }; +#undef V + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t RT3[256] = { RT }; +#undef V + +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +#undef RT + +/* + * Round constants + */ +static const uint32_t RCON[10] = +{ + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +#else /* MBEDTLS_AES_ROM_TABLES */ + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static uint32_t FT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) +static uint32_t FT1[256]; +static uint32_t FT2[256]; +static uint32_t FT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static uint32_t RT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) +static uint32_t RT1[256]; +static uint32_t RT2[256]; +static uint32_t RT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +/* + * Round constants + */ +static uint32_t RCON[10]; + +/* + * Tables generation code + */ +#define ROTL8(x) ( ( (x) << 8 ) & 0xFFFFFFFF ) | ( (x) >> 24 ) +#define XTIME(x) ( ( (x) << 1 ) ^ ( ( (x) & 0x80 ) ? 0x1B : 0x00 ) ) +#define MUL(x,y) ( ( (x) && (y) ) ? pow[(log[(x)]+log[(y)]) % 255] : 0 ) + +static int aes_init_done = 0; + +static void aes_gen_tables( void ) +{ + int i, x, y, z; + int pow[256]; + int log[256]; + + /* + * compute pow and log tables over GF(2^8) + */ + for( i = 0, x = 1; i < 256; i++ ) + { + pow[i] = x; + log[x] = i; + x = ( x ^ XTIME( x ) ) & 0xFF; + } + + /* + * calculate the round constants + */ + for( i = 0, x = 1; i < 10; i++ ) + { + RCON[i] = (uint32_t) x; + x = XTIME( x ) & 0xFF; + } + + /* + * generate the forward and reverse S-boxes + */ + FSb[0x00] = 0x63; + RSb[0x63] = 0x00; + + for( i = 1; i < 256; i++ ) + { + x = pow[255 - log[i]]; + + y = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y ^ 0x63; + + FSb[i] = (unsigned char) x; + RSb[x] = (unsigned char) i; + } + + /* + * generate the forward and reverse tables + */ + for( i = 0; i < 256; i++ ) + { + x = FSb[i]; + y = XTIME( x ) & 0xFF; + z = ( y ^ x ) & 0xFF; + + FT0[i] = ( (uint32_t) y ) ^ + ( (uint32_t) x << 8 ) ^ + ( (uint32_t) x << 16 ) ^ + ( (uint32_t) z << 24 ); + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + FT1[i] = ROTL8( FT0[i] ); + FT2[i] = ROTL8( FT1[i] ); + FT3[i] = ROTL8( FT2[i] ); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + + x = RSb[i]; + + RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ + ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ + ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ + ( (uint32_t) MUL( 0x0B, x ) << 24 ); + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + RT1[i] = ROTL8( RT0[i] ); + RT2[i] = ROTL8( RT1[i] ); + RT3[i] = ROTL8( RT2[i] ); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + } +} + +#undef ROTL8 + +#endif /* MBEDTLS_AES_ROM_TABLES */ + +#if defined(MBEDTLS_AES_FEWER_TABLES) + +#define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) ) +#define ROTL16(x) ( (uint32_t)( ( x ) << 16 ) + (uint32_t)( ( x ) >> 16 ) ) +#define ROTL24(x) ( (uint32_t)( ( x ) << 24 ) + (uint32_t)( ( x ) >> 8 ) ) + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) ROTL8( RT0[idx] ) +#define AES_RT2(idx) ROTL16( RT0[idx] ) +#define AES_RT3(idx) ROTL24( RT0[idx] ) + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) ROTL8( FT0[idx] ) +#define AES_FT2(idx) ROTL16( FT0[idx] ) +#define AES_FT3(idx) ROTL24( FT0[idx] ) + +#else /* MBEDTLS_AES_FEWER_TABLES */ + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) RT1[idx] +#define AES_RT2(idx) RT2[idx] +#define AES_RT3(idx) RT3[idx] + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) FT1[idx] +#define AES_FT2(idx) FT2[idx] +#define AES_FT3(idx) FT3[idx] + +#endif /* MBEDTLS_AES_FEWER_TABLES */ + +void mbedtls_aes_init( mbedtls_aes_context *ctx ) +{ + AES_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_aes_context ) ); +} + +void mbedtls_aes_free( mbedtls_aes_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ) +{ + AES_VALIDATE( ctx != NULL ); + + mbedtls_aes_init( &ctx->crypt ); + mbedtls_aes_init( &ctx->tweak ); +} + +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_aes_free( &ctx->crypt ); + mbedtls_aes_free( &ctx->tweak ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* + * AES key schedule (encryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i; + uint32_t *RK; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + switch( keybits ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if !defined(MBEDTLS_AES_ROM_TABLES) + if( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + } +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) ); +#endif + + for( i = 0; i < ( keybits >> 5 ); i++ ) + { + GET_UINT32_LE( RK[i], key, i << 2 ); + } + + switch( ctx->nr ) + { + case 10: + + for( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 12: + + for( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 14: + + for( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + } + + return( 0 ); +} +#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ + +/* + * AES key schedule (decryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int i, j, ret; + mbedtls_aes_context cty; + uint32_t *RK; + uint32_t *SK; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + mbedtls_aes_init( &cty ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + + /* Also checks keybits */ + if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + { + mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk, + (const unsigned char *) cty.rk, ctx->nr ); + goto exit; + } +#endif + + SK = cty.rk + cty.nr * 4; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) + { + for( j = 0; j < 4; j++, SK++ ) + { + *RK++ = AES_RT0( FSb[ ( *SK ) & 0xFF ] ) ^ + AES_RT1( FSb[ ( *SK >> 8 ) & 0xFF ] ) ^ + AES_RT2( FSb[ ( *SK >> 16 ) & 0xFF ] ) ^ + AES_RT3( FSb[ ( *SK >> 24 ) & 0xFF ] ); + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_aes_free( &cty ); + + return( ret ); +} +#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int mbedtls_aes_xts_decode_keys( const unsigned char *key, + unsigned int keybits, + const unsigned char **key1, + unsigned int *key1bits, + const unsigned char **key2, + unsigned int *key2bits ) +{ + const unsigned int half_keybits = keybits / 2; + const unsigned int half_keybytes = half_keybits / 8; + + switch( keybits ) + { + case 256: break; + case 512: break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + *key1bits = half_keybits; + *key2bits = half_keybits; + *key1 = &key[0]; + *key2 = &key[half_keybytes]; + + return 0; +} + +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for the encryption mode. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for encryption. */ + return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits ); +} + +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for encryption. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for decryption. */ + return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do \ + { \ + (X0) = *RK++ ^ AES_FT0( ( (Y0) ) & 0xFF ) ^ \ + AES_FT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y3) >> 24 ) & 0xFF ); \ + \ + (X1) = *RK++ ^ AES_FT0( ( (Y1) ) & 0xFF ) ^ \ + AES_FT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y0) >> 24 ) & 0xFF ); \ + \ + (X2) = *RK++ ^ AES_FT0( ( (Y2) ) & 0xFF ) ^ \ + AES_FT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y1) >> 24 ) & 0xFF ); \ + \ + (X3) = *RK++ ^ AES_FT0( ( (Y3) ) & 0xFF ) ^ \ + AES_FT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y2) >> 24 ) & 0xFF ); \ + } while( 0 ) + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do \ + { \ + (X0) = *RK++ ^ AES_RT0( ( (Y0) ) & 0xFF ) ^ \ + AES_RT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y1) >> 24 ) & 0xFF ); \ + \ + (X1) = *RK++ ^ AES_RT0( ( (Y1) ) & 0xFF ) ^ \ + AES_RT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y2) >> 24 ) & 0xFF ); \ + \ + (X2) = *RK++ ^ AES_RT0( ( (Y2) ) & 0xFF ) ^ \ + AES_RT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y3) >> 24 ) & 0xFF ); \ + \ + (X3) = *RK++ ^ AES_RT0( ( (Y3) ) & 0xFF ) ^ \ + AES_RT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y0) >> 24 ) & 0xFF ); \ + } while( 0 ) + +/* + * AES-ECB block encryption + */ +#if !defined(MBEDTLS_AES_ENCRYPT_ALT) +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK = ctx->rk; + struct + { + uint32_t X[4]; + uint32_t Y[4]; + } t; + + GET_UINT32_LE( t.X[0], input, 0 ); t.X[0] ^= *RK++; + GET_UINT32_LE( t.X[1], input, 4 ); t.X[1] ^= *RK++; + GET_UINT32_LE( t.X[2], input, 8 ); t.X[2] ^= *RK++; + GET_UINT32_LE( t.X[3], input, 12 ); t.X[3] ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + AES_FROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] ); + } + + AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + + t.X[0] = *RK++ ^ \ + ( (uint32_t) FSb[ ( t.Y[0] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( t.Y[1] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( t.Y[2] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( t.Y[3] >> 24 ) & 0xFF ] << 24 ); + + t.X[1] = *RK++ ^ \ + ( (uint32_t) FSb[ ( t.Y[1] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( t.Y[2] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( t.Y[3] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( t.Y[0] >> 24 ) & 0xFF ] << 24 ); + + t.X[2] = *RK++ ^ \ + ( (uint32_t) FSb[ ( t.Y[2] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( t.Y[3] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( t.Y[0] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( t.Y[1] >> 24 ) & 0xFF ] << 24 ); + + t.X[3] = *RK++ ^ \ + ( (uint32_t) FSb[ ( t.Y[3] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( t.Y[0] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( t.Y[1] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( t.Y[2] >> 24 ) & 0xFF ] << 24 ); + + PUT_UINT32_LE( t.X[0], output, 0 ); + PUT_UINT32_LE( t.X[1], output, 4 ); + PUT_UINT32_LE( t.X[2], output, 8 ); + PUT_UINT32_LE( t.X[3], output, 12 ); + + mbedtls_platform_zeroize( &t, sizeof( t ) ); + + return( 0 ); +} +#endif /* !MBEDTLS_AES_ENCRYPT_ALT */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + mbedtls_internal_aes_encrypt( ctx, input, output ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block decryption + */ +#if !defined(MBEDTLS_AES_DECRYPT_ALT) +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK = ctx->rk; + struct + { + uint32_t X[4]; + uint32_t Y[4]; + } t; + + GET_UINT32_LE( t.X[0], input, 0 ); t.X[0] ^= *RK++; + GET_UINT32_LE( t.X[1], input, 4 ); t.X[1] ^= *RK++; + GET_UINT32_LE( t.X[2], input, 8 ); t.X[2] ^= *RK++; + GET_UINT32_LE( t.X[3], input, 12 ); t.X[3] ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + AES_RROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] ); + } + + AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + + t.X[0] = *RK++ ^ \ + ( (uint32_t) RSb[ ( t.Y[0] ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( t.Y[3] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( t.Y[2] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( t.Y[1] >> 24 ) & 0xFF ] << 24 ); + + t.X[1] = *RK++ ^ \ + ( (uint32_t) RSb[ ( t.Y[1] ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( t.Y[0] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( t.Y[3] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( t.Y[2] >> 24 ) & 0xFF ] << 24 ); + + t.X[2] = *RK++ ^ \ + ( (uint32_t) RSb[ ( t.Y[2] ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( t.Y[1] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( t.Y[0] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( t.Y[3] >> 24 ) & 0xFF ] << 24 ); + + t.X[3] = *RK++ ^ \ + ( (uint32_t) RSb[ ( t.Y[3] ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( t.Y[2] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( t.Y[1] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( t.Y[0] >> 24 ) & 0xFF ] << 24 ); + + PUT_UINT32_LE( t.X[0], output, 0 ); + PUT_UINT32_LE( t.X[1], output, 4 ); + PUT_UINT32_LE( t.X[2], output, 8 ); + PUT_UINT32_LE( t.X[3], output, 12 ); + + mbedtls_platform_zeroize( &t, sizeof( t ) ); + + return( 0 ); +} +#endif /* !MBEDTLS_AES_DECRYPT_ALT */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + mbedtls_internal_aes_decrypt( ctx, input, output ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block encryption/decryption + */ +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace ) + { + if( mbedtls_padlock_xcryptecb( ctx, mode, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_ENCRYPT ) + return( mbedtls_internal_aes_encrypt( ctx, input, output ) ); + else + return( mbedtls_internal_aes_decrypt( ctx, input, output ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * AES-CBC buffer encryption/decryption + */ +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + if( length % 16 ) + return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace ) + { + if( mbedtls_padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + mbedtls_aes_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_aes_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + +/* Endianess with 64 bits values */ +#ifndef GET_UINT64_LE +#define GET_UINT64_LE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \ + | ( (uint64_t) (b)[(i) + 6] << 48 ) \ + | ( (uint64_t) (b)[(i) + 5] << 40 ) \ + | ( (uint64_t) (b)[(i) + 4] << 32 ) \ + | ( (uint64_t) (b)[(i) + 3] << 24 ) \ + | ( (uint64_t) (b)[(i) + 2] << 16 ) \ + | ( (uint64_t) (b)[(i) + 1] << 8 ) \ + | ( (uint64_t) (b)[(i) ] ); \ +} +#endif + +#ifndef PUT_UINT64_LE +#define PUT_UINT64_LE(n,b,i) \ +{ \ + (b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) ] = (unsigned char) ( (n) ); \ +} +#endif + +typedef unsigned char mbedtls_be128[16]; + +/* + * GF(2^128) multiplication function + * + * This function multiplies a field element by x in the polynomial field + * representation. It uses 64-bit word operations to gain speed but compensates + * for machine endianess and hence works correctly on both big and little + * endian machines. + */ +static void mbedtls_gf128mul_x_ble( unsigned char r[16], + const unsigned char x[16] ) +{ + uint64_t a, b, ra, rb; + + GET_UINT64_LE( a, x, 0 ); + GET_UINT64_LE( b, x, 8 ); + + ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) ); + rb = ( a >> 63 ) | ( b << 1 ); + + PUT_UINT64_LE( ra, r, 0 ); + PUT_UINT64_LE( rb, r, 8 ); +} + +/* + * AES-XTS buffer encryption/decryption + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t blocks = length / 16; + size_t leftover = length % 16; + unsigned char tweak[16]; + unsigned char prev_tweak[16]; + unsigned char tmp[16]; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( data_unit != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + /* Data units must be at least 16 bytes long. */ + if( length < 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */ + if( length > ( 1 << 20 ) * 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* Compute the tweak. */ + ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT, + data_unit, tweak ); + if( ret != 0 ) + return( ret ); + + while( blocks-- ) + { + size_t i; + + if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 ) + { + /* We are on the last block in a decrypt operation that has + * leftover bytes, so we need to use the next tweak for this block, + * and this tweak for the lefover bytes. Save the current tweak for + * the leftovers and then update the current tweak for use on this, + * the last full block. */ + memcpy( prev_tweak, tweak, sizeof( tweak ) ); + mbedtls_gf128mul_x_ble( tweak, tweak ); + } + + for( i = 0; i < 16; i++ ) + tmp[i] = input[i] ^ tweak[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return( ret ); + + for( i = 0; i < 16; i++ ) + output[i] = tmp[i] ^ tweak[i]; + + /* Update the tweak for the next block. */ + mbedtls_gf128mul_x_ble( tweak, tweak ); + + output += 16; + input += 16; + } + + if( leftover ) + { + /* If we are on the leftover bytes in a decrypt operation, we need to + * use the previous tweak for these bytes (as saved in prev_tweak). */ + unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; + + /* We are now on the final part of the data unit, which doesn't divide + * evenly by 16. It's time for ciphertext stealing. */ + size_t i; + unsigned char *prev_output = output - 16; + + /* Copy ciphertext bytes from the previous block to our output for each + * byte of cyphertext we won't steal. At the same time, copy the + * remainder of the input for this final round (since the loop bounds + * are the same). */ + for( i = 0; i < leftover; i++ ) + { + output[i] = prev_output[i]; + tmp[i] = input[i] ^ t[i]; + } + + /* Copy ciphertext bytes from the previous block for input in this + * round. */ + for( ; i < 16; i++ ) + tmp[i] = prev_output[i] ^ t[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return ret; + + /* Write the result back to the previous block, overriding the previous + * output we copied. */ + for( i = 0; i < 16; i++ ) + prev_output[i] = tmp[i] ^ t[i]; + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv_off != NULL ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *iv_off; + + if( n > 15 ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} + +/* + * AES-CFB8 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + unsigned char c; + unsigned char ov[17]; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + while( length-- ) + { + memcpy( ov, iv, 16 ); + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + if( mode == MBEDTLS_AES_DECRYPT ) + ov[16] = *input; + + c = *output++ = (unsigned char)( iv[0] ^ *input++ ); + + if( mode == MBEDTLS_AES_ENCRYPT ) + ov[16] = c; + + memcpy( iv, ov + 1, 16 ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB (Output Feedback Mode) buffer encryption/decryption + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = 0; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( iv_off != NULL ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *iv_off; + + if( n > 15 ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) + { + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ret != 0 ) + goto exit; + } + *output++ = *input++ ^ iv[n]; + + n = ( n + 1 ) & 0x0F; + } + + *iv_off = n; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR buffer encryption/decryption + */ +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( nc_off != NULL ); + AES_VALIDATE_RET( nonce_counter != NULL ); + AES_VALIDATE_RET( stream_block != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *nc_off; + + if ( n > 0x0F ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#endif /* !MBEDTLS_AES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * AES test vectors from: + * + * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip + */ +static const unsigned char aes_test_ecb_dec[3][16] = +{ + { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, + 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, + { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, + 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, + { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, + 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } +}; + +static const unsigned char aes_test_ecb_enc[3][16] = +{ + { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, + 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, + { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, + 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, + { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, + 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char aes_test_cbc_dec[3][16] = +{ + { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, + 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, + { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, + 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, + { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, + 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } +}; + +static const unsigned char aes_test_cbc_enc[3][16] = +{ + { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, + 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, + { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, + 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, + { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, + 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 test vectors from: + * + * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + */ +static const unsigned char aes_test_cfb128_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_cfb128_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_cfb128_pt[64] = +{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_cfb128_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, + 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, + 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, + 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, + 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, + 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, + 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, + 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, + 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, + 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, + 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, + 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, + 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, + 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, + 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, + 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB test vectors from: + * + * https://csrc.nist.gov/publications/detail/sp/800-38a/final + */ +static const unsigned char aes_test_ofb_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_ofb_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_ofb_pt[64] = +{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_ofb_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, + 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25, + 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, + 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, + 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, + 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, + 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01, + 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, + 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2, + 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, + 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, + 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d, + 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, + 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, + 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, + 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 } +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc3686.html + */ + +static const unsigned char aes_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char aes_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char aes_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 } +}; + +static const unsigned char aes_test_ctr_ct[3][48] = +{ + { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, + 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, + { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, + 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, + 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, + 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, + { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, + 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, + 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, + 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, + 0x25, 0xB2, 0x07, 0x2F } +}; + +static const int aes_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/* + * AES-XTS test vectors from: + * + * IEEE P1619/D16 Annex B + * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf + * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf) + */ +static const unsigned char aes_test_xts_key[][32] = +{ + { 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 }, + { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, + { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, +}; + +static const unsigned char aes_test_xts_pt32[][32] = +{ + { 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 }, + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, +}; + +static const unsigned char aes_test_xts_ct32[][32] = +{ + { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec, + 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92, + 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85, + 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e }, + { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e, + 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b, + 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4, + 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 }, + { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, + 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, + 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, + 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 }, +}; + +static const unsigned char aes_test_xts_data_unit[][16] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +}; + +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* + * Checkup routine + */ +int mbedtls_aes_self_test( int verbose ) +{ + int ret = 0, i, j, u, mode; + unsigned int keybits; + unsigned char key[32]; + unsigned char buf[64]; + const unsigned char *aes_tests; +#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_OFB) + size_t offset; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS) + int len; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + mbedtls_aes_context ctx; + + memset( key, 0, 32 ); + mbedtls_aes_init( &ctx ); + + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-ECB-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( buf, 0, 16 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_ecb_dec[u]; + } + else + { + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + aes_tests = aes_test_ecb_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + ret = mbedtls_aes_crypt_ecb( &ctx, mode, buf, buf ); + if( ret != 0 ) + goto exit; + } + + if( memcmp( buf, aes_tests, 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CBC-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( iv , 0, 16 ); + memset( prv, 0, 16 ); + memset( buf, 0, 16 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_cbc_dec[u]; + } + else + { + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + aes_tests = aes_test_cbc_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + if( mode == MBEDTLS_AES_ENCRYPT ) + { + unsigned char tmp[16]; + + memcpy( tmp, prv, 16 ); + memcpy( prv, buf, 16 ); + memcpy( buf, tmp, 16 ); + } + + ret = mbedtls_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + } + + if( memcmp( buf, aes_tests, 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /* + * CFB128 mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CFB128-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_cfb128_iv, 16 ); + memcpy( key, aes_test_cfb128_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_cfb128_ct[u], 64 ); + aes_tests = aes_test_cfb128_pt; + } + else + { + memcpy( buf, aes_test_cfb128_pt, 64 ); + aes_tests = aes_test_cfb128_ct[u]; + } + + ret = mbedtls_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /* + * OFB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-OFB-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_ofb_iv, 16 ); + memcpy( key, aes_test_ofb_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_ofb_ct[u], 64 ); + aes_tests = aes_test_ofb_pt; + } + else + { + memcpy( buf, aes_test_ofb_pt, 64 ); + aes_tests = aes_test_ofb_ct[u]; + } + + ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CTR-128 (%s): ", + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); + memcpy( key, aes_test_ctr_key[u], 16 ); + + offset = 0; + if( ( ret = mbedtls_aes_setkey_enc( &ctx, key, 128 ) ) != 0 ) + goto exit; + + len = aes_test_ctr_len[u]; + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_ctr_ct[u], len ); + aes_tests = aes_test_ctr_pt[u]; + } + else + { + memcpy( buf, aes_test_ctr_pt[u], len ); + aes_tests = aes_test_ctr_ct[u]; + } + + ret = mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, + stream_block, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { + static const int num_tests = + sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key); + mbedtls_aes_xts_context ctx_xts; + + /* + * XTS mode + */ + mbedtls_aes_xts_init( &ctx_xts ); + + for( i = 0; i < num_tests << 1; i++ ) + { + const unsigned char *data_unit; + u = i >> 1; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-XTS-128 (%s): ", + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( key, 0, sizeof( key ) ); + memcpy( key, aes_test_xts_key[u], 32 ); + data_unit = aes_test_xts_data_unit[u]; + + len = sizeof( *aes_test_xts_ct32 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_ct32[u], len ); + aes_tests = aes_test_xts_pt32[u]; + } + else + { + ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_pt32[u], len ); + aes_tests = aes_test_xts_ct32[u]; + } + + + ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit, + buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + mbedtls_aes_xts_free( &ctx_xts ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + + ret = 0; + +exit: + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "failed\n" ); + + mbedtls_aes_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_AES_C */ diff --git a/external/mbedtls/library/aesni.c b/external/mbedtls/library/aesni.c new file mode 100644 index 0000000..358d4ad --- /dev/null +++ b/external/mbedtls/library/aesni.c @@ -0,0 +1,495 @@ +/* + * AES-NI support functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set + * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/ + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_AESNI_C) + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#warning "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code." +#endif +#endif + +#include "mbedtls/aesni.h" + +#include + +#ifndef asm +#define asm __asm +#endif + +#if defined(MBEDTLS_HAVE_X86_64) + +/* + * AES-NI support detection routine + */ +int mbedtls_aesni_has_support( unsigned int what ) +{ + static int done = 0; + static unsigned int c = 0; + + if( ! done ) + { + asm( "movl $1, %%eax \n\t" + "cpuid \n\t" + : "=c" (c) + : + : "eax", "ebx", "edx" ); + done = 1; + } + + return( ( c & what ) != 0 ); +} + +/* + * Binutils needs to be at least 2.19 to support AES-NI instructions. + * Unfortunately, a lot of users have a lower version now (2014-04). + * Emit bytecode directly in order to support "old" version of gas. + * + * Opcodes from the Intel architecture reference manual, vol. 3. + * We always use registers, so we don't need prefixes for memory operands. + * Operand macros are in gas order (src, dst) as opposed to Intel order + * (dst, src) in order to blend better into the surrounding assembly code. + */ +#define AESDEC ".byte 0x66,0x0F,0x38,0xDE," +#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF," +#define AESENC ".byte 0x66,0x0F,0x38,0xDC," +#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD," +#define AESIMC ".byte 0x66,0x0F,0x38,0xDB," +#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF," +#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44," + +#define xmm0_xmm0 "0xC0" +#define xmm0_xmm1 "0xC8" +#define xmm0_xmm2 "0xD0" +#define xmm0_xmm3 "0xD8" +#define xmm0_xmm4 "0xE0" +#define xmm1_xmm0 "0xC1" +#define xmm1_xmm2 "0xD1" + +/* + * AES-NI AES-ECB block en(de)cryption + */ +int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + asm( "movdqu (%3), %%xmm0 \n\t" // load input + "movdqu (%1), %%xmm1 \n\t" // load round key 0 + "pxor %%xmm1, %%xmm0 \n\t" // round 0 + "add $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // normal rounds = nr - 1 + "test %2, %2 \n\t" // mode? + "jz 2f \n\t" // 0 = decrypt + + "1: \n\t" // encryption loop + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENC xmm1_xmm0 "\n\t" // do round + "add $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // loop + "jnz 1b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENCLAST xmm1_xmm0 "\n\t" // last round + "jmp 3f \n\t" + + "2: \n\t" // decryption loop + "movdqu (%1), %%xmm1 \n\t" + AESDEC xmm1_xmm0 "\n\t" // do round + "add $16, %1 \n\t" + "subl $1, %0 \n\t" + "jnz 2b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESDECLAST xmm1_xmm0 "\n\t" // last round + + "3: \n\t" + "movdqu %%xmm0, (%4) \n\t" // export output + : + : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output) + : "memory", "cc", "xmm0", "xmm1" ); + + + return( 0 ); +} + +/* + * GCM multiplication: c = a times b in GF(2^128) + * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. + */ +void mbedtls_aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ) +{ + unsigned char aa[16], bb[16], cc[16]; + size_t i; + + /* The inputs are in big-endian order, so byte-reverse them */ + for( i = 0; i < 16; i++ ) + { + aa[i] = a[15 - i]; + bb[i] = b[15 - i]; + } + + asm( "movdqu (%0), %%xmm0 \n\t" // a1:a0 + "movdqu (%1), %%xmm1 \n\t" // b1:b0 + + /* + * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1 + * using [CLMUL-WP] algorithm 1 (p. 13). + */ + "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0 + "movdqa %%xmm1, %%xmm3 \n\t" // same + "movdqa %%xmm1, %%xmm4 \n\t" // same + PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0 + PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0 + PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0 + PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0 + "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 + "movdqa %%xmm4, %%xmm3 \n\t" // same + "psrldq $8, %%xmm4 \n\t" // 0:e1+f1 + "pslldq $8, %%xmm3 \n\t" // e0+f0:0 + "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 + "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 + + /* + * Now shift the result one bit to the left, + * taking advantage of [CLMUL-WP] eq 27 (p. 20) + */ + "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 + "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 + "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 + "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 + "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 + "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 + "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 + "pslldq $8, %%xmm3 \n\t" // r0>>63:0 + "pslldq $8, %%xmm4 \n\t" // r2>>63:0 + "psrldq $8, %%xmm5 \n\t" // 0:r1>>63 + "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 + "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 + "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 + + /* + * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 + * using [CLMUL-WP] algorithm 5 (p. 20). + * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted). + */ + /* Step 2 (1) */ + "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 + "movdqa %%xmm1, %%xmm4 \n\t" // same + "movdqa %%xmm1, %%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a + "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b + "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c + + /* Step 2 (2) */ + "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b + "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c + "pslldq $8, %%xmm3 \n\t" // a+b+c:0 + "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 + + /* Steps 3 and 4 */ + "movdqa %%xmm1,%%xmm0 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' + "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' + "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' + "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' + "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' + // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing + // bits carried from d. Now get those\t bits back in. + "movdqa %%xmm1,%%xmm3 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // d<<63:stuff + "psllq $62, %%xmm4 \n\t" // d<<62:stuff + "psllq $57, %%xmm5 \n\t" // d<<57:stuff + "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff + "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff + "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d + "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 + "pxor %%xmm1, %%xmm0 \n\t" // h1:h0 + "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 + + "movdqu %%xmm0, (%2) \n\t" // done + : + : "r" (aa), "r" (bb), "r" (cc) + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" ); + + /* Now byte-reverse the outputs */ + for( i = 0; i < 16; i++ ) + c[i] = cc[15 - i]; + + return; +} + +/* + * Compute decryption round keys from encryption round keys + */ +void mbedtls_aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, int nr ) +{ + unsigned char *ik = invkey; + const unsigned char *fk = fwdkey + 16 * nr; + + memcpy( ik, fk, 16 ); + + for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 ) + asm( "movdqu (%0), %%xmm0 \n\t" + AESIMC xmm0_xmm0 "\n\t" + "movdqu %%xmm0, (%1) \n\t" + : + : "r" (fk), "r" (ik) + : "memory", "xmm0" ); + + memcpy( ik, fk, 16 ); +} + +/* + * Key expansion, 128-bit case + */ +static void aesni_setkey_enc_128( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" // copy the original key + "movdqu %%xmm0, (%0) \n\t" // as round key 0 + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next round key. + * + * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff + * with X = rot( sub( r3 ) ) ^ RCON. + * + * On exit, xmm0 is r7:r6:r5:r4 + * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 + * and those are written to the round key buffer. + */ + "1: \n\t" + "pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X + "pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4 + "pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0 + "pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4 + "pslldq $4, %%xmm0 \n\t" // etc + "pxor %%xmm0, %%xmm1 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time! + "add $16, %0 \n\t" // point to next round key + "movdqu %%xmm0, (%0) \n\t" // write it + "ret \n\t" + + /* Main "loop" */ + "2: \n\t" + AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, 192-bit case + */ +static void aesni_setkey_enc_192( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" // copy original round key + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "movq 16(%1), %%xmm1 \n\t" + "movq %%xmm1, (%0) \n\t" + "add $8, %0 \n\t" + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next 6 quarter-keys. + * + * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4 + * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON. + * + * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10 + * and those are written to the round key buffer. + */ + "1: \n\t" + "pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X + "pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4 + "pslldq $4, %%xmm0 \n\t" // etc + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6 + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9 + "pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10 + "pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0 + "pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10 + "movq %%xmm1, (%0) \n\t" + "add $8, %0 \n\t" + "ret \n\t" + + "2: \n\t" + AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t" + + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, 256-bit case + */ +static void aesni_setkey_enc_256( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "movdqu 16(%1), %%xmm1 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next two round keys. + * + * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and + * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON + * + * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12 + * and those have been written to the output buffer. + */ + "1: \n\t" + "pshufd $0xff, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm2, %%xmm0 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm0, (%0) \n\t" + + /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 ) + * and proceed to generate next round key from there */ + AESKEYGENA xmm0_xmm2 ",0x00 \n\t" + "pshufd $0xaa, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm2, %%xmm1 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "ret \n\t" + + /* + * Main "loop" - Generating one more key than necessary, + * see definition of mbedtls_aes_context.buf + */ + "2: \n\t" + AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, wrapper + */ +int mbedtls_aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ) +{ + switch( bits ) + { + case 128: aesni_setkey_enc_128( rk, key ); break; + case 192: aesni_setkey_enc_192( rk, key ); break; + case 256: aesni_setkey_enc_256( rk, key ); break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_HAVE_X86_64 */ + +#endif /* MBEDTLS_AESNI_C */ diff --git a/external/mbedtls/library/arc4.c b/external/mbedtls/library/arc4.c new file mode 100644 index 0000000..6729bab --- /dev/null +++ b/external/mbedtls/library/arc4.c @@ -0,0 +1,226 @@ +/* + * An implementation of the ARCFOUR algorithm + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The ARCFOUR algorithm was publicly disclosed on 94/09. + * + * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ARC4_C) + +#include "mbedtls/arc4.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_ARC4_ALT) + +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_arc4_context ) ); +} + +void mbedtls_arc4_free( mbedtls_arc4_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_arc4_context ) ); +} + +/* + * ARC4 key schedule + */ +void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, + unsigned int keylen ) +{ + int i, j, a; + unsigned int k; + unsigned char *m; + + ctx->x = 0; + ctx->y = 0; + m = ctx->m; + + for( i = 0; i < 256; i++ ) + m[i] = (unsigned char) i; + + j = k = 0; + + for( i = 0; i < 256; i++, k++ ) + { + if( k >= keylen ) k = 0; + + a = m[i]; + j = ( j + a + key[k] ) & 0xFF; + m[i] = m[j]; + m[j] = (unsigned char) a; + } +} + +/* + * ARC4 cipher function + */ +int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ) +{ + int x, y, a, b; + size_t i; + unsigned char *m; + + x = ctx->x; + y = ctx->y; + m = ctx->m; + + for( i = 0; i < length; i++ ) + { + x = ( x + 1 ) & 0xFF; a = m[x]; + y = ( y + a ) & 0xFF; b = m[y]; + + m[x] = (unsigned char) b; + m[y] = (unsigned char) a; + + output[i] = (unsigned char) + ( input[i] ^ m[(unsigned char)( a + b )] ); + } + + ctx->x = x; + ctx->y = y; + + return( 0 ); +} + +#endif /* !MBEDTLS_ARC4_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994: + * + * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0 + */ +static const unsigned char arc4_test_key[3][8] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char arc4_test_pt[3][8] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char arc4_test_ct[3][8] = +{ + { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 }, + { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 }, + { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A } +}; + +/* + * Checkup routine + */ +int mbedtls_arc4_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char ibuf[8]; + unsigned char obuf[8]; + mbedtls_arc4_context ctx; + + mbedtls_arc4_init( &ctx ); + + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ARC4 test #%d: ", i + 1 ); + + memcpy( ibuf, arc4_test_pt[i], 8 ); + + mbedtls_arc4_setup( &ctx, arc4_test_key[i], 8 ); + mbedtls_arc4_crypt( &ctx, 8, ibuf, obuf ); + + if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_arc4_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ARC4_C */ diff --git a/external/mbedtls/library/aria.c b/external/mbedtls/library/aria.c new file mode 100644 index 0000000..ef0392f --- /dev/null +++ b/external/mbedtls/library/aria.c @@ -0,0 +1,1104 @@ +/* + * ARIA implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * This implementation is based on the following standards: + * [1] http://210.104.33.10/ARIA/doc/ARIA-specification-e.pdf + * [2] https://tools.ietf.org/html/rfc5794 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ARIA_C) + +#include "mbedtls/aria.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_ARIA_ALT) + +#include "mbedtls/platform_util.h" + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define ARIA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ) +#define ARIA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE( n, b, i ) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE( n, b, i ) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +/* + * modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes + * + * This is submatrix P1 in [1] Appendix B.1 + * + * Common compilers fail to translate this to minimal number of instructions, + * so let's provide asm versions for common platforms with C fallback. + */ +#if defined(MBEDTLS_HAVE_ASM) +#if defined(__arm__) /* rev16 available from v6 up */ +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \ + __ARM_ARCH >= 6 +static inline uint32_t aria_p1( uint32_t x ) +{ + uint32_t r; + __asm( "rev16 %0, %1" : "=l" (r) : "l" (x) ); + return( r ); +} +#define ARIA_P1 aria_p1 +#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ + ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 ) +static inline uint32_t aria_p1( uint32_t x ) +{ + uint32_t r; + __asm( "rev16 r, x" ); + return( r ); +} +#define ARIA_P1 aria_p1 +#endif +#endif /* arm */ +#if defined(__GNUC__) && \ + defined(__i386__) || defined(__amd64__) || defined( __x86_64__) +/* I couldn't find an Intel equivalent of rev16, so two instructions */ +#define ARIA_P1(x) ARIA_P2( ARIA_P3( x ) ) +#endif /* x86 gnuc */ +#endif /* MBEDTLS_HAVE_ASM && GNUC */ +#if !defined(ARIA_P1) +#define ARIA_P1(x) ((((x) >> 8) & 0x00FF00FF) ^ (((x) & 0x00FF00FF) << 8)) +#endif + +/* + * modify byte order: ( A B C D ) -> ( C D A B ), i.e. rotate by 16 bits + * + * This is submatrix P2 in [1] Appendix B.1 + * + * Common compilers will translate this to a single instruction. + */ +#define ARIA_P2(x) (((x) >> 16) ^ ((x) << 16)) + +/* + * modify byte order: ( A B C D ) -> ( D C B A ), i.e. change endianness + * + * This is submatrix P3 in [1] Appendix B.1 + * + * Some compilers fail to translate this to a single instruction, + * so let's provide asm versions for common platforms with C fallback. + */ +#if defined(MBEDTLS_HAVE_ASM) +#if defined(__arm__) /* rev available from v6 up */ +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \ + __ARM_ARCH >= 6 +static inline uint32_t aria_p3( uint32_t x ) +{ + uint32_t r; + __asm( "rev %0, %1" : "=l" (r) : "l" (x) ); + return( r ); +} +#define ARIA_P3 aria_p3 +#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ + ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 ) +static inline uint32_t aria_p3( uint32_t x ) +{ + uint32_t r; + __asm( "rev r, x" ); + return( r ); +} +#define ARIA_P3 aria_p3 +#endif +#endif /* arm */ +#if defined(__GNUC__) && \ + defined(__i386__) || defined(__amd64__) || defined( __x86_64__) +static inline uint32_t aria_p3( uint32_t x ) +{ + __asm( "bswap %0" : "=r" (x) : "0" (x) ); + return( x ); +} +#define ARIA_P3 aria_p3 +#endif /* x86 gnuc */ +#endif /* MBEDTLS_HAVE_ASM && GNUC */ +#if !defined(ARIA_P3) +#define ARIA_P3(x) ARIA_P2( ARIA_P1 ( x ) ) +#endif + +/* + * ARIA Affine Transform + * (a, b, c, d) = state in/out + * + * If we denote the first byte of input by 0, ..., the last byte by f, + * then inputs are: a = 0123, b = 4567, c = 89ab, d = cdef. + * + * Reading [1] 2.4 or [2] 2.4.3 in columns and performing simple + * rearrangements on adjacent pairs, output is: + * + * a = 3210 + 4545 + 6767 + 88aa + 99bb + dccd + effe + * = 3210 + 4567 + 6745 + 89ab + 98ba + dcfe + efcd + * b = 0101 + 2323 + 5476 + 8998 + baab + eecc + ffdd + * = 0123 + 2301 + 5476 + 89ab + ba98 + efcd + fedc + * c = 0022 + 1133 + 4554 + 7667 + ab89 + dcdc + fefe + * = 0123 + 1032 + 4567 + 7654 + ab89 + dcfe + fedc + * d = 1001 + 2332 + 6644 + 7755 + 9898 + baba + cdef + * = 1032 + 2301 + 6745 + 7654 + 98ba + ba98 + cdef + * + * Note: another presentation of the A transform can be found as the first + * half of App. B.1 in [1] in terms of 4-byte operators P1, P2, P3 and P4. + * The implementation below uses only P1 and P2 as they are sufficient. + */ +static inline void aria_a( uint32_t *a, uint32_t *b, + uint32_t *c, uint32_t *d ) +{ + uint32_t ta, tb, tc; + ta = *b; // 4567 + *b = *a; // 0123 + *a = ARIA_P2( ta ); // 6745 + tb = ARIA_P2( *d ); // efcd + *d = ARIA_P1( *c ); // 98ba + *c = ARIA_P1( tb ); // fedc + ta ^= *d; // 4567+98ba + tc = ARIA_P2( *b ); // 2301 + ta = ARIA_P1( ta ) ^ tc ^ *c; // 2301+5476+89ab+fedc + tb ^= ARIA_P2( *d ); // ba98+efcd + tc ^= ARIA_P1( *a ); // 2301+7654 + *b ^= ta ^ tb; // 0123+2301+5476+89ab+ba98+efcd+fedc OUT + tb = ARIA_P2( tb ) ^ ta; // 2301+5476+89ab+98ba+cdef+fedc + *a ^= ARIA_P1( tb ); // 3210+4567+6745+89ab+98ba+dcfe+efcd OUT + ta = ARIA_P2( ta ); // 0123+7654+ab89+dcfe + *d ^= ARIA_P1( ta ) ^ tc; // 1032+2301+6745+7654+98ba+ba98+cdef OUT + tc = ARIA_P2( tc ); // 0123+5476 + *c ^= ARIA_P1( tc ) ^ ta; // 0123+1032+4567+7654+ab89+dcfe+fedc OUT +} + +/* + * ARIA Substitution Layer SL1 / SL2 + * (a, b, c, d) = state in/out + * (sa, sb, sc, sd) = 256 8-bit S-Boxes (see below) + * + * By passing sb1, sb2, is1, is2 as S-Boxes you get SL1 + * By passing is1, is2, sb1, sb2 as S-Boxes you get SL2 + */ +static inline void aria_sl( uint32_t *a, uint32_t *b, + uint32_t *c, uint32_t *d, + const uint8_t sa[256], const uint8_t sb[256], + const uint8_t sc[256], const uint8_t sd[256] ) +{ + *a = ( (uint32_t) sa[ *a & 0xFF] ) ^ + (((uint32_t) sb[(*a >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*a >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *a >> 24 ]) << 24); + *b = ( (uint32_t) sa[ *b & 0xFF] ) ^ + (((uint32_t) sb[(*b >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*b >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *b >> 24 ]) << 24); + *c = ( (uint32_t) sa[ *c & 0xFF] ) ^ + (((uint32_t) sb[(*c >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*c >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *c >> 24 ]) << 24); + *d = ( (uint32_t) sa[ *d & 0xFF] ) ^ + (((uint32_t) sb[(*d >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*d >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *d >> 24 ]) << 24); +} + +/* + * S-Boxes + */ +static const uint8_t aria_sb1[256] = +{ + 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 const uint8_t aria_sb2[256] = +{ + 0xE2, 0x4E, 0x54, 0xFC, 0x94, 0xC2, 0x4A, 0xCC, 0x62, 0x0D, 0x6A, 0x46, + 0x3C, 0x4D, 0x8B, 0xD1, 0x5E, 0xFA, 0x64, 0xCB, 0xB4, 0x97, 0xBE, 0x2B, + 0xBC, 0x77, 0x2E, 0x03, 0xD3, 0x19, 0x59, 0xC1, 0x1D, 0x06, 0x41, 0x6B, + 0x55, 0xF0, 0x99, 0x69, 0xEA, 0x9C, 0x18, 0xAE, 0x63, 0xDF, 0xE7, 0xBB, + 0x00, 0x73, 0x66, 0xFB, 0x96, 0x4C, 0x85, 0xE4, 0x3A, 0x09, 0x45, 0xAA, + 0x0F, 0xEE, 0x10, 0xEB, 0x2D, 0x7F, 0xF4, 0x29, 0xAC, 0xCF, 0xAD, 0x91, + 0x8D, 0x78, 0xC8, 0x95, 0xF9, 0x2F, 0xCE, 0xCD, 0x08, 0x7A, 0x88, 0x38, + 0x5C, 0x83, 0x2A, 0x28, 0x47, 0xDB, 0xB8, 0xC7, 0x93, 0xA4, 0x12, 0x53, + 0xFF, 0x87, 0x0E, 0x31, 0x36, 0x21, 0x58, 0x48, 0x01, 0x8E, 0x37, 0x74, + 0x32, 0xCA, 0xE9, 0xB1, 0xB7, 0xAB, 0x0C, 0xD7, 0xC4, 0x56, 0x42, 0x26, + 0x07, 0x98, 0x60, 0xD9, 0xB6, 0xB9, 0x11, 0x40, 0xEC, 0x20, 0x8C, 0xBD, + 0xA0, 0xC9, 0x84, 0x04, 0x49, 0x23, 0xF1, 0x4F, 0x50, 0x1F, 0x13, 0xDC, + 0xD8, 0xC0, 0x9E, 0x57, 0xE3, 0xC3, 0x7B, 0x65, 0x3B, 0x02, 0x8F, 0x3E, + 0xE8, 0x25, 0x92, 0xE5, 0x15, 0xDD, 0xFD, 0x17, 0xA9, 0xBF, 0xD4, 0x9A, + 0x7E, 0xC5, 0x39, 0x67, 0xFE, 0x76, 0x9D, 0x43, 0xA7, 0xE1, 0xD0, 0xF5, + 0x68, 0xF2, 0x1B, 0x34, 0x70, 0x05, 0xA3, 0x8A, 0xD5, 0x79, 0x86, 0xA8, + 0x30, 0xC6, 0x51, 0x4B, 0x1E, 0xA6, 0x27, 0xF6, 0x35, 0xD2, 0x6E, 0x24, + 0x16, 0x82, 0x5F, 0xDA, 0xE6, 0x75, 0xA2, 0xEF, 0x2C, 0xB2, 0x1C, 0x9F, + 0x5D, 0x6F, 0x80, 0x0A, 0x72, 0x44, 0x9B, 0x6C, 0x90, 0x0B, 0x5B, 0x33, + 0x7D, 0x5A, 0x52, 0xF3, 0x61, 0xA1, 0xF7, 0xB0, 0xD6, 0x3F, 0x7C, 0x6D, + 0xED, 0x14, 0xE0, 0xA5, 0x3D, 0x22, 0xB3, 0xF8, 0x89, 0xDE, 0x71, 0x1A, + 0xAF, 0xBA, 0xB5, 0x81 +}; + +static const uint8_t aria_is1[256] = +{ + 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 uint8_t aria_is2[256] = +{ + 0x30, 0x68, 0x99, 0x1B, 0x87, 0xB9, 0x21, 0x78, 0x50, 0x39, 0xDB, 0xE1, + 0x72, 0x09, 0x62, 0x3C, 0x3E, 0x7E, 0x5E, 0x8E, 0xF1, 0xA0, 0xCC, 0xA3, + 0x2A, 0x1D, 0xFB, 0xB6, 0xD6, 0x20, 0xC4, 0x8D, 0x81, 0x65, 0xF5, 0x89, + 0xCB, 0x9D, 0x77, 0xC6, 0x57, 0x43, 0x56, 0x17, 0xD4, 0x40, 0x1A, 0x4D, + 0xC0, 0x63, 0x6C, 0xE3, 0xB7, 0xC8, 0x64, 0x6A, 0x53, 0xAA, 0x38, 0x98, + 0x0C, 0xF4, 0x9B, 0xED, 0x7F, 0x22, 0x76, 0xAF, 0xDD, 0x3A, 0x0B, 0x58, + 0x67, 0x88, 0x06, 0xC3, 0x35, 0x0D, 0x01, 0x8B, 0x8C, 0xC2, 0xE6, 0x5F, + 0x02, 0x24, 0x75, 0x93, 0x66, 0x1E, 0xE5, 0xE2, 0x54, 0xD8, 0x10, 0xCE, + 0x7A, 0xE8, 0x08, 0x2C, 0x12, 0x97, 0x32, 0xAB, 0xB4, 0x27, 0x0A, 0x23, + 0xDF, 0xEF, 0xCA, 0xD9, 0xB8, 0xFA, 0xDC, 0x31, 0x6B, 0xD1, 0xAD, 0x19, + 0x49, 0xBD, 0x51, 0x96, 0xEE, 0xE4, 0xA8, 0x41, 0xDA, 0xFF, 0xCD, 0x55, + 0x86, 0x36, 0xBE, 0x61, 0x52, 0xF8, 0xBB, 0x0E, 0x82, 0x48, 0x69, 0x9A, + 0xE0, 0x47, 0x9E, 0x5C, 0x04, 0x4B, 0x34, 0x15, 0x79, 0x26, 0xA7, 0xDE, + 0x29, 0xAE, 0x92, 0xD7, 0x84, 0xE9, 0xD2, 0xBA, 0x5D, 0xF3, 0xC5, 0xB0, + 0xBF, 0xA4, 0x3B, 0x71, 0x44, 0x46, 0x2B, 0xFC, 0xEB, 0x6F, 0xD5, 0xF6, + 0x14, 0xFE, 0x7C, 0x70, 0x5A, 0x7D, 0xFD, 0x2F, 0x18, 0x83, 0x16, 0xA5, + 0x91, 0x1F, 0x05, 0x95, 0x74, 0xA9, 0xC1, 0x5B, 0x4A, 0x85, 0x6D, 0x13, + 0x07, 0x4F, 0x4E, 0x45, 0xB2, 0x0F, 0xC9, 0x1C, 0xA6, 0xBC, 0xEC, 0x73, + 0x90, 0x7B, 0xCF, 0x59, 0x8F, 0xA1, 0xF9, 0x2D, 0xF2, 0xB1, 0x00, 0x94, + 0x37, 0x9F, 0xD0, 0x2E, 0x9C, 0x6E, 0x28, 0x3F, 0x80, 0xF0, 0x3D, 0xD3, + 0x25, 0x8A, 0xB5, 0xE7, 0x42, 0xB3, 0xC7, 0xEA, 0xF7, 0x4C, 0x11, 0x33, + 0x03, 0xA2, 0xAC, 0x60 +}; + +/* + * Helper for key schedule: r = FO( p, k ) ^ x + */ +static void aria_fo_xor( uint32_t r[4], const uint32_t p[4], + const uint32_t k[4], const uint32_t x[4] ) +{ + uint32_t a, b, c, d; + + a = p[0] ^ k[0]; + b = p[1] ^ k[1]; + c = p[2] ^ k[2]; + d = p[3] ^ k[3]; + + aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 ); + aria_a( &a, &b, &c, &d ); + + r[0] = a ^ x[0]; + r[1] = b ^ x[1]; + r[2] = c ^ x[2]; + r[3] = d ^ x[3]; +} + +/* + * Helper for key schedule: r = FE( p, k ) ^ x + */ +static void aria_fe_xor( uint32_t r[4], const uint32_t p[4], + const uint32_t k[4], const uint32_t x[4] ) +{ + uint32_t a, b, c, d; + + a = p[0] ^ k[0]; + b = p[1] ^ k[1]; + c = p[2] ^ k[2]; + d = p[3] ^ k[3]; + + aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 ); + aria_a( &a, &b, &c, &d ); + + r[0] = a ^ x[0]; + r[1] = b ^ x[1]; + r[2] = c ^ x[2]; + r[3] = d ^ x[3]; +} + +/* + * Big endian 128-bit rotation: r = a ^ (b <<< n), used only in key setup. + * + * We chose to store bytes into 32-bit words in little-endian format (see + * GET/PUT_UINT32_LE) so we need to reverse bytes here. + */ +static void aria_rot128( uint32_t r[4], const uint32_t a[4], + const uint32_t b[4], uint8_t n ) +{ + uint8_t i, j; + uint32_t t, u; + + const uint8_t n1 = n % 32; // bit offset + const uint8_t n2 = n1 ? 32 - n1 : 0; // reverse bit offset + + j = ( n / 32 ) % 4; // initial word offset + t = ARIA_P3( b[j] ); // big endian + for( i = 0; i < 4; i++ ) + { + j = ( j + 1 ) % 4; // get next word, big endian + u = ARIA_P3( b[j] ); + t <<= n1; // rotate + t |= u >> n2; + t = ARIA_P3( t ); // back to little endian + r[i] = a[i] ^ t; // store + t = u; // move to next word + } +} + +/* + * Set encryption key + */ +int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, + const unsigned char *key, unsigned int keybits ) +{ + /* round constant masks */ + const uint32_t rc[3][4] = + { + { 0xB7C17C51, 0x940A2227, 0xE8AB13FE, 0xE06E9AFA }, + { 0xCC4AB16D, 0x20C8219E, 0xD5B128FF, 0xB0E25DEF }, + { 0x1D3792DB, 0x70E92621, 0x75972403, 0x0EC9E804 } + }; + + int i; + uint32_t w[4][4], *w2; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( key != NULL ); + + if( keybits != 128 && keybits != 192 && keybits != 256 ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + /* Copy key to W0 (and potential remainder to W1) */ + GET_UINT32_LE( w[0][0], key, 0 ); + GET_UINT32_LE( w[0][1], key, 4 ); + GET_UINT32_LE( w[0][2], key, 8 ); + GET_UINT32_LE( w[0][3], key, 12 ); + + memset( w[1], 0, 16 ); + if( keybits >= 192 ) + { + GET_UINT32_LE( w[1][0], key, 16 ); // 192 bit key + GET_UINT32_LE( w[1][1], key, 20 ); + } + if( keybits == 256 ) + { + GET_UINT32_LE( w[1][2], key, 24 ); // 256 bit key + GET_UINT32_LE( w[1][3], key, 28 ); + } + + i = ( keybits - 128 ) >> 6; // index: 0, 1, 2 + ctx->nr = 12 + 2 * i; // no. rounds: 12, 14, 16 + + aria_fo_xor( w[1], w[0], rc[i], w[1] ); // W1 = FO(W0, CK1) ^ KR + i = i < 2 ? i + 1 : 0; + aria_fe_xor( w[2], w[1], rc[i], w[0] ); // W2 = FE(W1, CK2) ^ W0 + i = i < 2 ? i + 1 : 0; + aria_fo_xor( w[3], w[2], rc[i], w[1] ); // W3 = FO(W2, CK3) ^ W1 + + for( i = 0; i < 4; i++ ) // create round keys + { + w2 = w[(i + 1) & 3]; + aria_rot128( ctx->rk[i ], w[i], w2, 128 - 19 ); + aria_rot128( ctx->rk[i + 4], w[i], w2, 128 - 31 ); + aria_rot128( ctx->rk[i + 8], w[i], w2, 61 ); + aria_rot128( ctx->rk[i + 12], w[i], w2, 31 ); + } + aria_rot128( ctx->rk[16], w[0], w[1], 19 ); + + /* w holds enough info to reconstruct the round keys */ + mbedtls_platform_zeroize( w, sizeof( w ) ); + + return( 0 ); +} + +/* + * Set decryption key + */ +int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, + const unsigned char *key, unsigned int keybits ) +{ + int i, j, k, ret; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aria_setkey_enc( ctx, key, keybits ); + if( ret != 0 ) + return( ret ); + + /* flip the order of round keys */ + for( i = 0, j = ctx->nr; i < j; i++, j-- ) + { + for( k = 0; k < 4; k++ ) + { + uint32_t t = ctx->rk[i][k]; + ctx->rk[i][k] = ctx->rk[j][k]; + ctx->rk[j][k] = t; + } + } + + /* apply affine transform to middle keys */ + for( i = 1; i < ctx->nr; i++ ) + { + aria_a( &ctx->rk[i][0], &ctx->rk[i][1], + &ctx->rk[i][2], &ctx->rk[i][3] ); + } + + return( 0 ); +} + +/* + * Encrypt a block + */ +int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, + const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] ) +{ + int i; + + uint32_t a, b, c, d; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( input != NULL ); + ARIA_VALIDATE_RET( output != NULL ); + + GET_UINT32_LE( a, input, 0 ); + GET_UINT32_LE( b, input, 4 ); + GET_UINT32_LE( c, input, 8 ); + GET_UINT32_LE( d, input, 12 ); + + i = 0; + while( 1 ) + { + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + i++; + + aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 ); + aria_a( &a, &b, &c, &d ); + + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + i++; + + aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 ); + if( i >= ctx->nr ) + break; + aria_a( &a, &b, &c, &d ); + } + + /* final key mixing */ + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + + PUT_UINT32_LE( a, output, 0 ); + PUT_UINT32_LE( b, output, 4 ); + PUT_UINT32_LE( c, output, 8 ); + PUT_UINT32_LE( d, output, 12 ); + + return( 0 ); +} + +/* Initialize context */ +void mbedtls_aria_init( mbedtls_aria_context *ctx ) +{ + ARIA_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_aria_context ) ); +} + +/* Clear context */ +void mbedtls_aria_free( mbedtls_aria_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aria_context ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * ARIA-CBC buffer encryption/decryption + */ +int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE]; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT || + mode == MBEDTLS_ARIA_DECRYPT ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( iv != NULL ); + + if( length % MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_ARIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, MBEDTLS_ARIA_BLOCKSIZE ); + mbedtls_aria_crypt_ecb( ctx, input, output ); + + for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, MBEDTLS_ARIA_BLOCKSIZE ); + + input += MBEDTLS_ARIA_BLOCKSIZE; + output += MBEDTLS_ARIA_BLOCKSIZE; + length -= MBEDTLS_ARIA_BLOCKSIZE; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_aria_crypt_ecb( ctx, output, output ); + memcpy( iv, output, MBEDTLS_ARIA_BLOCKSIZE ); + + input += MBEDTLS_ARIA_BLOCKSIZE; + output += MBEDTLS_ARIA_BLOCKSIZE; + length -= MBEDTLS_ARIA_BLOCKSIZE; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * ARIA-CFB128 buffer encryption/decryption + */ +int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + unsigned char c; + size_t n; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT || + mode == MBEDTLS_ARIA_DECRYPT ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( iv != NULL ); + ARIA_VALIDATE_RET( iv_off != NULL ); + + n = *iv_off; + + /* An overly large value of n can lead to an unlimited + * buffer overflow. Therefore, guard against this + * outside of parameter validation. */ + if( n >= MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_ARIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aria_crypt_ecb( ctx, iv, iv ); + + c = *input++; + *output++ = c ^ iv[n]; + iv[n] = c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aria_crypt_ecb( ctx, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * ARIA-CTR buffer encryption/decryption + */ +int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( nonce_counter != NULL ); + ARIA_VALIDATE_RET( stream_block != NULL ); + ARIA_VALIDATE_RET( nc_off != NULL ); + + n = *nc_off; + /* An overly large value of n can lead to an unlimited + * buffer overflow. Therefore, guard against this + * outside of parameter validation. */ + if( n >= MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_aria_crypt_ecb( ctx, nonce_counter, + stream_block ); + + for( i = MBEDTLS_ARIA_BLOCKSIZE; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* !MBEDTLS_ARIA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Basic ARIA ECB test vectors from RFC 5794 + */ +static const uint8_t aria_test1_ecb_key[32] = // test key +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 128 bit + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // 192 bit + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F // 256 bit +}; + +static const uint8_t aria_test1_ecb_pt[MBEDTLS_ARIA_BLOCKSIZE] = // plaintext +{ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // same for all + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF // key sizes +}; + +static const uint8_t aria_test1_ecb_ct[3][MBEDTLS_ARIA_BLOCKSIZE] = // ciphertext +{ + { 0xD7, 0x18, 0xFB, 0xD6, 0xAB, 0x64, 0x4C, 0x73, // 128 bit + 0x9D, 0xA9, 0x5F, 0x3B, 0xE6, 0x45, 0x17, 0x78 }, + { 0x26, 0x44, 0x9C, 0x18, 0x05, 0xDB, 0xE7, 0xAA, // 192 bit + 0x25, 0xA4, 0x68, 0xCE, 0x26, 0x3A, 0x9E, 0x79 }, + { 0xF9, 0x2B, 0xD7, 0xC7, 0x9F, 0xB7, 0x2E, 0x2F, // 256 bit + 0x2B, 0x8F, 0x80, 0xC1, 0x97, 0x2D, 0x24, 0xFC } +}; + +/* + * Mode tests from "Test Vectors for ARIA" Version 1.0 + * http://210.104.33.10/ARIA/doc/ARIA-testvector-e.pdf + */ +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_CTR)) +static const uint8_t aria_test2_key[32] = +{ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 128 bit + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 192 bit + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff // 256 bit +}; + +static const uint8_t aria_test2_pt[48] = +{ + 0x11, 0x11, 0x11, 0x11, 0xaa, 0xaa, 0xaa, 0xaa, // same for all + 0x11, 0x11, 0x11, 0x11, 0xbb, 0xbb, 0xbb, 0xbb, + 0x11, 0x11, 0x11, 0x11, 0xcc, 0xcc, 0xcc, 0xcc, + 0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd, + 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, + 0x22, 0x22, 0x22, 0x22, 0xbb, 0xbb, 0xbb, 0xbb, +}; +#endif + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)) +static const uint8_t aria_test2_iv[MBEDTLS_ARIA_BLOCKSIZE] = +{ + 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78, // same for CBC, CFB + 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0 // CTR has zero IV +}; +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const uint8_t aria_test2_cbc_ct[3][48] = // CBC ciphertext +{ + { 0x49, 0xd6, 0x18, 0x60, 0xb1, 0x49, 0x09, 0x10, // 128-bit key + 0x9c, 0xef, 0x0d, 0x22, 0xa9, 0x26, 0x81, 0x34, + 0xfa, 0xdf, 0x9f, 0xb2, 0x31, 0x51, 0xe9, 0x64, + 0x5f, 0xba, 0x75, 0x01, 0x8b, 0xdb, 0x15, 0x38, + 0xb5, 0x33, 0x34, 0x63, 0x4b, 0xbf, 0x7d, 0x4c, + 0xd4, 0xb5, 0x37, 0x70, 0x33, 0x06, 0x0c, 0x15 }, + { 0xaf, 0xe6, 0xcf, 0x23, 0x97, 0x4b, 0x53, 0x3c, // 192-bit key + 0x67, 0x2a, 0x82, 0x62, 0x64, 0xea, 0x78, 0x5f, + 0x4e, 0x4f, 0x7f, 0x78, 0x0d, 0xc7, 0xf3, 0xf1, + 0xe0, 0x96, 0x2b, 0x80, 0x90, 0x23, 0x86, 0xd5, + 0x14, 0xe9, 0xc3, 0xe7, 0x72, 0x59, 0xde, 0x92, + 0xdd, 0x11, 0x02, 0xff, 0xab, 0x08, 0x6c, 0x1e }, + { 0x52, 0x3a, 0x8a, 0x80, 0x6a, 0xe6, 0x21, 0xf1, // 256-bit key + 0x55, 0xfd, 0xd2, 0x8d, 0xbc, 0x34, 0xe1, 0xab, + 0x7b, 0x9b, 0x42, 0x43, 0x2a, 0xd8, 0xb2, 0xef, + 0xb9, 0x6e, 0x23, 0xb1, 0x3f, 0x0a, 0x6e, 0x52, + 0xf3, 0x61, 0x85, 0xd5, 0x0a, 0xd0, 0x02, 0xc5, + 0xf6, 0x01, 0xbe, 0xe5, 0x49, 0x3f, 0x11, 0x8b } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const uint8_t aria_test2_cfb_ct[3][48] = // CFB ciphertext +{ + { 0x37, 0x20, 0xe5, 0x3b, 0xa7, 0xd6, 0x15, 0x38, // 128-bit key + 0x34, 0x06, 0xb0, 0x9f, 0x0a, 0x05, 0xa2, 0x00, + 0xc0, 0x7c, 0x21, 0xe6, 0x37, 0x0f, 0x41, 0x3a, + 0x5d, 0x13, 0x25, 0x00, 0xa6, 0x82, 0x85, 0x01, + 0x7c, 0x61, 0xb4, 0x34, 0xc7, 0xb7, 0xca, 0x96, + 0x85, 0xa5, 0x10, 0x71, 0x86, 0x1e, 0x4d, 0x4b }, + { 0x41, 0x71, 0xf7, 0x19, 0x2b, 0xf4, 0x49, 0x54, // 192-bit key + 0x94, 0xd2, 0x73, 0x61, 0x29, 0x64, 0x0f, 0x5c, + 0x4d, 0x87, 0xa9, 0xa2, 0x13, 0x66, 0x4c, 0x94, + 0x48, 0x47, 0x7c, 0x6e, 0xcc, 0x20, 0x13, 0x59, + 0x8d, 0x97, 0x66, 0x95, 0x2d, 0xd8, 0xc3, 0x86, + 0x8f, 0x17, 0xe3, 0x6e, 0xf6, 0x6f, 0xd8, 0x4b }, + { 0x26, 0x83, 0x47, 0x05, 0xb0, 0xf2, 0xc0, 0xe2, // 256-bit key + 0x58, 0x8d, 0x4a, 0x7f, 0x09, 0x00, 0x96, 0x35, + 0xf2, 0x8b, 0xb9, 0x3d, 0x8c, 0x31, 0xf8, 0x70, + 0xec, 0x1e, 0x0b, 0xdb, 0x08, 0x2b, 0x66, 0xfa, + 0x40, 0x2d, 0xd9, 0xc2, 0x02, 0xbe, 0x30, 0x0c, + 0x45, 0x17, 0xd1, 0x96, 0xb1, 0x4d, 0x4c, 0xe1 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext +{ + { 0xac, 0x5d, 0x7d, 0xe8, 0x05, 0xa0, 0xbf, 0x1c, // 128-bit key + 0x57, 0xc8, 0x54, 0x50, 0x1a, 0xf6, 0x0f, 0xa1, + 0x14, 0x97, 0xe2, 0xa3, 0x45, 0x19, 0xde, 0xa1, + 0x56, 0x9e, 0x91, 0xe5, 0xb5, 0xcc, 0xae, 0x2f, + 0xf3, 0xbf, 0xa1, 0xbf, 0x97, 0x5f, 0x45, 0x71, + 0xf4, 0x8b, 0xe1, 0x91, 0x61, 0x35, 0x46, 0xc3 }, + { 0x08, 0x62, 0x5c, 0xa8, 0xfe, 0x56, 0x9c, 0x19, // 192-bit key + 0xba, 0x7a, 0xf3, 0x76, 0x0a, 0x6e, 0xd1, 0xce, + 0xf4, 0xd1, 0x99, 0x26, 0x3e, 0x99, 0x9d, 0xde, + 0x14, 0x08, 0x2d, 0xbb, 0xa7, 0x56, 0x0b, 0x79, + 0xa4, 0xc6, 0xb4, 0x56, 0xb8, 0x70, 0x7d, 0xce, + 0x75, 0x1f, 0x98, 0x54, 0xf1, 0x88, 0x93, 0xdf }, + { 0x30, 0x02, 0x6c, 0x32, 0x96, 0x66, 0x14, 0x17, // 256-bit key + 0x21, 0x17, 0x8b, 0x99, 0xc0, 0xa1, 0xf1, 0xb2, + 0xf0, 0x69, 0x40, 0x25, 0x3f, 0x7b, 0x30, 0x89, + 0xe2, 0xa3, 0x0e, 0xa8, 0x6a, 0xa3, 0xc8, 0x8f, + 0x59, 0x40, 0xf0, 0x5a, 0xd7, 0xee, 0x41, 0xd7, + 0x13, 0x47, 0xbb, 0x72, 0x61, 0xe3, 0x48, 0xf1 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#define ARIA_SELF_TEST_IF_FAIL \ + { \ + if( verbose ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } else { \ + if( verbose ) \ + mbedtls_printf( "passed\n" ); \ + } + +/* + * Checkup routine + */ +int mbedtls_aria_self_test( int verbose ) +{ + int i; + uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE]; + mbedtls_aria_context ctx; + +#if (defined(MBEDTLS_CIPHER_MODE_CFB) || defined(MBEDTLS_CIPHER_MODE_CTR)) + size_t j; +#endif + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || \ + defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_CTR)) + uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE]; +#endif + + /* + * Test set 1 + */ + for( i = 0; i < 3; i++ ) + { + /* test ECB encryption */ + if( verbose ) + mbedtls_printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test1_ecb_key, 128 + 64 * i ); + mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_pt, blk ); + if( memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* test ECB decryption */ + if( verbose ) + mbedtls_printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_dec( &ctx, aria_test1_ecb_key, 128 + 64 * i ); + mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_ct[i], blk ); + if( memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); + + /* + * Test set 2 + */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) + for( i = 0; i < 3; i++ ) + { + /* Test CBC encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CBC-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0x55, sizeof( buf ) ); + mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_cbc_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CBC decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CBC-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_dec( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0xAA, sizeof( buf ) ); + mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_DECRYPT, 48, iv, + aria_test2_cbc_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); + +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + for( i = 0; i < 3; i++ ) + { + /* Test CFB encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CFB-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0x55, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CFB decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CFB-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0xAA, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_DECRYPT, 48, &j, + iv, aria_test2_cfb_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + for( i = 0; i < 3; i++ ) + { + /* Test CTR encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CTR-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 + memset( buf, 0x55, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CTR decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CTR-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 + memset( buf, 0xAA, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk, + aria_test2_ctr_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ARIA_C */ diff --git a/external/mbedtls/library/asn1parse.c b/external/mbedtls/library/asn1parse.c new file mode 100644 index 0000000..10239fd --- /dev/null +++ b/external/mbedtls/library/asn1parse.c @@ -0,0 +1,414 @@ +/* + * Generic ASN.1 parsing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +#include "mbedtls/asn1.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* + * ASN.1 DER decoding routines + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( **p & 0x80 ) == 0 ) + *len = *(*p)++; + else + { + switch( **p & 0x7F ) + { + case 1: + if( ( end - *p ) < 2 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = (*p)[1]; + (*p) += 2; + break; + + case 2: + if( ( end - *p ) < 3 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2]; + (*p) += 3; + break; + + case 3: + if( ( end - *p ) < 4 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 16 ) | + ( (size_t)(*p)[2] << 8 ) | (*p)[3]; + (*p) += 4; + break; + + case 4: + if( ( end - *p ) < 5 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) | + ( (size_t)(*p)[3] << 8 ) | (*p)[4]; + (*p) += 5; + break; + + default: + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + } + } + + if( *len > (size_t) ( end - *p ) ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + return( 0 ); +} + +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != tag ) + return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + + return( mbedtls_asn1_get_len( p, end, len ) ); +} + +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 ) + return( ret ); + + if( len != 1 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = ( **p != 0 ) ? 1 : 0; + (*p)++; + + return( 0 ); +} + +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( ret ); + + if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = 0; + + while( len-- > 0 ) + { + *val = ( *val << 8 ) | **p; + (*p)++; + } + + return( 0 ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( ret ); + + ret = mbedtls_mpi_read_binary( X, *p, len ); + + *p += len; + + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs) +{ + int ret; + + /* Certificate type is a single byte bitstring */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + /* Check length, subtract one for actual bit string length */ + if( bs->len < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + bs->len -= 1; + + /* Get number of unused bits, ensure unused bits <= 7 */ + bs->unused_bits = **p; + if( bs->unused_bits > 7 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + (*p)++; + + /* Get actual bitstring */ + bs->p = *p; + *p += bs->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Get a bit string without unused bits + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + if( (*len)-- < 2 || *(*p)++ != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + + + +/* + * Parses and splits an ASN.1 "SEQUENCE OF " + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag) +{ + int ret; + size_t len; + mbedtls_asn1_buf *buf; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + buf = &(cur->buf); + buf->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) + return( ret ); + + buf->p = *p; + *p += buf->len; + + /* Allocate and assign next pointer */ + if( *p < end ) + { + cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1, + sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + alg->tag = **p; + end = *p + len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + alg->p = *p; + *p += alg->len; + + if( *p == end ) + { + mbedtls_platform_zeroize( params, sizeof(mbedtls_asn1_buf) ); + return( 0 ); + } + + params->tag = **p; + (*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, ¶ms->len ) ) != 0 ) + return( ret ); + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ) +{ + int ret; + mbedtls_asn1_buf params; + + memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) + return( ret ); + + if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur ) +{ + if( cur == NULL ) + return; + + mbedtls_free( cur->oid.p ); + mbedtls_free( cur->val.p ); + + mbedtls_platform_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); +} + +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ) +{ + mbedtls_asn1_named_data *cur; + + while( ( cur = *head ) != NULL ) + { + *head = cur->next; + mbedtls_asn1_free_named_data( cur ); + mbedtls_free( cur ); + } +} + +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +#endif /* MBEDTLS_ASN1_PARSE_C */ diff --git a/external/mbedtls/library/asn1write.c b/external/mbedtls/library/asn1write.c new file mode 100644 index 0000000..d94d0a7 --- /dev/null +++ b/external/mbedtls/library/asn1write.c @@ -0,0 +1,446 @@ +/* + * ASN.1 buffer writing functionality + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ASN1_WRITE_C) + +#include "mbedtls/asn1write.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) +{ + if( len < 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + return( 1 ); + } + + if( len <= 0xFF ) + { + if( *p - start < 2 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + *--(*p) = 0x81; + return( 2 ); + } + + if( len <= 0xFFFF ) + { + if( *p - start < 3 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = 0x82; + return( 3 ); + } + + if( len <= 0xFFFFFF ) + { + if( *p - start < 4 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = ( len >> 16 ) & 0xFF; + *--(*p) = 0x83; + return( 4 ); + } + +#if SIZE_MAX > 0xFFFFFFFF + if( len <= 0xFFFFFFFF ) +#endif + { + if( *p - start < 5 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = ( len >> 16 ) & 0xFF; + *--(*p) = ( len >> 24 ) & 0xFF; + *--(*p) = 0x84; + return( 5 ); + } + +#if SIZE_MAX > 0xFFFFFFFF + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); +#endif +} + +int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) +{ + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = tag; + + return( 1 ); +} + +int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + size_t len = 0; + + if( *p < start || (size_t)( *p - start ) < size ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) +{ + int ret; + size_t len = 0; + + // Write the MPI + // + len = mbedtls_mpi_size( X ); + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + (*p) -= len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); + + // DER format assumes 2s complement for numbers, so the leftmost bit + // should be 0 for positive numbers and 1 for negative numbers. + // + if( X->s ==1 && **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); + + ret = (int) len; + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) +{ + int ret; + size_t len = 0; + + // Write NULL + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) oid, oid_len ) ); + MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ) +{ + int ret; + size_t len = 0; + + if( par_len == 0 ) + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); + else + len += par_len; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) +{ + int ret; + size_t len = 0; + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (boolean) ? 255 : 0; + len++; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) +{ + int ret; + size_t len = 0; + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len += 1; + *--(*p) = val; + + if( val > 0 && **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag, + const char *text, size_t text_len ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) text, text_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) ); +} + +int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) ); +} + +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) ); +} + +int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ) +{ + int ret; + size_t len = 0; + size_t unused_bits, byte_len; + + byte_len = ( bits + 7 ) / 8; + unused_bits = ( byte_len * 8 ) - bits; + + if( *p < start || (size_t)( *p - start ) < byte_len + 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = byte_len + 1; + + /* Write the bitstring. Ensure the unused bits are zeroed */ + if( byte_len > 0 ) + { + byte_len--; + *--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 ); + ( *p ) -= byte_len; + memcpy( *p, buf, byte_len ); + } + + /* Write unused bits */ + *--( *p ) = (unsigned char)unused_bits; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); + + return( (int) len ); +} + + +/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), + * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ +static mbedtls_asn1_named_data *asn1_find_named_data( + mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( + mbedtls_asn1_named_data **head, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ) +{ + mbedtls_asn1_named_data *cur; + + if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) + { + // Add new entry if not present yet based on OID + // + cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, + sizeof(mbedtls_asn1_named_data) ); + if( cur == NULL ) + return( NULL ); + + cur->oid.len = oid_len; + cur->oid.p = mbedtls_calloc( 1, oid_len ); + if( cur->oid.p == NULL ) + { + mbedtls_free( cur ); + return( NULL ); + } + + memcpy( cur->oid.p, oid, oid_len ); + + cur->val.len = val_len; + cur->val.p = mbedtls_calloc( 1, val_len ); + if( cur->val.p == NULL ) + { + mbedtls_free( cur->oid.p ); + mbedtls_free( cur ); + return( NULL ); + } + + cur->next = *head; + *head = cur; + } + else if( cur->val.len < val_len ) + { + /* + * Enlarge existing value buffer if needed + * Preserve old data until the allocation succeeded, to leave list in + * a consistent state in case allocation fails. + */ + void *p = mbedtls_calloc( 1, val_len ); + if( p == NULL ) + return( NULL ); + + mbedtls_free( cur->val.p ); + cur->val.p = p; + cur->val.len = val_len; + } + + if( val != NULL ) + memcpy( cur->val.p, val, val_len ); + + return( cur ); +} +#endif /* MBEDTLS_ASN1_WRITE_C */ diff --git a/external/mbedtls/library/base64.c b/external/mbedtls/library/base64.c new file mode 100644 index 0000000..692e11e --- /dev/null +++ b/external/mbedtls/library/base64.c @@ -0,0 +1,427 @@ +/* + * RFC 1521 base64 encoding/decoding + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_BASE64_C) + +#include "mbedtls/base64.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#include +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +static const unsigned char base64_enc_map[64] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' +}; + +static const unsigned char base64_dec_map[128] = +{ + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, + 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 127, 127, 127, 127, 127 +}; + +#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Constant flow conditional assignment to unsigned char + */ +static void mbedtls_base64_cond_assign_uchar( unsigned char * dest, const unsigned char * const src, + unsigned char condition ) +{ + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + /* Generate bitmask from condition, mask will either be 0xFF or 0 */ + unsigned char mask = ( condition | -condition ); + mask >>= 7; + mask = -mask; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + *dest = ( ( *src ) & mask ) | ( ( *dest ) & ~mask ); +} + +/* + * Constant flow conditional assignment to uint_32 + */ +static void mbedtls_base64_cond_assign_uint32( uint32_t * dest, const uint32_t src, + uint32_t condition ) +{ + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + /* Generate bitmask from condition, mask will either be 0xFFFFFFFF or 0 */ + uint32_t mask = ( condition | -condition ); + mask >>= 31; + mask = -mask; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + *dest = ( src & mask ) | ( ( *dest ) & ~mask ); +} + +/* + * Constant flow check for equality + */ +static unsigned char mbedtls_base64_eq( size_t in_a, size_t in_b ) +{ + size_t difference = in_a ^ in_b; + + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + difference |= -difference; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + /* cope with the varying size of size_t per platform */ + difference >>= ( sizeof( difference ) * 8 - 1 ); + + return (unsigned char) ( 1 ^ difference ); +} + +/* + * Constant flow lookup into table. + */ +static unsigned char mbedtls_base64_table_lookup( const unsigned char * const table, + const size_t table_size, const size_t table_index ) +{ + size_t i; + unsigned char result = 0; + + for( i = 0; i < table_size; ++i ) + { + mbedtls_base64_cond_assign_uchar( &result, &table[i], mbedtls_base64_eq( i, table_index ) ); + } + + return result; +} + +/* + * Encode a buffer into base64 format + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + { + *olen = 0; + return( 0 ); + } + + n = slen / 3 + ( slen % 3 != 0 ); + + if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 ) + { + *olen = BASE64_SIZE_T_MAX; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n *= 4; + + if( ( dlen < n + 1 ) || ( NULL == dst ) ) + { + *olen = n + 1; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n = ( slen / 3 ) * 3; + + for( i = 0, p = dst; i < n; i += 3 ) + { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( C1 >> 2 ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( C3 & 0x3F ) ); + } + + if( i < slen ) + { + C1 = *src++; + C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( C1 >> 2 ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) ); + + if( ( i + 1 ) < slen ) + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( C2 & 15 ) << 2 ) & 0x3F ) ); + else *p++ = '='; + + *p++ = '='; + } + + *olen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + uint32_t j, x; + unsigned char *p; + unsigned char dec_map_lookup; + + /* First pass: check for validity and get output length */ + for( i = n = j = 0; i < slen; i++ ) + { + /* Skip spaces before checking for EOL */ + x = 0; + while( i < slen && src[i] == ' ' ) + { + ++i; + ++x; + } + + /* Spaces at end of buffer are OK */ + if( i == slen ) + break; + + if( ( slen - i ) >= 2 && + src[i] == '\r' && src[i + 1] == '\n' ) + continue; + + if( src[i] == '\n' ) + continue; + + /* Space inside a line is an error */ + if( x != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] == '=' && ++j > 2 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), src[i] ); + + if( src[i] > 127 || dec_map_lookup == 127 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( dec_map_lookup < 64 && j != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + n++; + } + + if( n == 0 ) + { + *olen = 0; + return( 0 ); + } + + /* The following expression is to calculate the following formula without + * risk of integer overflow in n: + * n = ( ( n * 6 ) + 7 ) >> 3; + */ + n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 ); + n -= j; + + if( dst == NULL || dlen < n ) + { + *olen = n; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) + { + if( *src == '\r' || *src == '\n' || *src == ' ' ) + continue; + + dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), *src ); + + mbedtls_base64_cond_assign_uint32( &j, j - 1, mbedtls_base64_eq( dec_map_lookup, 64 ) ); + x = ( x << 6 ) | ( dec_map_lookup & 0x3F ); + + if( ++n == 4 ) + { + n = 0; + if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); + if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); + if( j > 2 ) *p++ = (unsigned char)( x ); + } + } + + *olen = p - dst; + + return( 0 ); +} + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char base64_test_dec[64] = +{ + 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, + 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, + 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, + 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, + 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, + 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, + 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, + 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 +}; + +static const unsigned char base64_test_enc[] = + "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" + "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; + +/* + * Checkup routine + */ +int mbedtls_base64_self_test( int verbose ) +{ + size_t len; + const unsigned char *src; + unsigned char buffer[128]; + + if( verbose != 0 ) + mbedtls_printf( " Base64 encoding test: " ); + + src = base64_test_dec; + + if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 || + memcmp( base64_test_enc, buffer, 88 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n Base64 decoding test: " ); + + src = base64_test_enc; + + if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 || + memcmp( base64_test_dec, buffer, 64 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BASE64_C */ diff --git a/external/mbedtls/library/bignum.c b/external/mbedtls/library/bignum.c new file mode 100644 index 0000000..f133f6c --- /dev/null +++ b/external/mbedtls/library/bignum.c @@ -0,0 +1,2966 @@ +/* + * Multi-precision integer library + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * The following sources were referenced in the design of this Multi-precision + * Integer library: + * + * [1] Handbook of Applied Cryptography - 1997 + * Menezes, van Oorschot and Vanstone + * + * [2] Multi-Precision Math + * Tom St Denis + * https://github.com/libtom/libtommath/blob/develop/tommath.pdf + * + * [3] GNU Multi-Precision Arithmetic Library + * https://gmplib.org/manual/index.html + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_BIGNUM_C) + +#include "mbedtls/bignum.h" +#include "mbedtls/bn_mul.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define MPI_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA ) +#define MPI_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows + */ +#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) +#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) +{ + mbedtls_platform_zeroize( v, ciL * n ); +} + +/* + * Initialize one MPI + */ +void mbedtls_mpi_init( mbedtls_mpi *X ) +{ + MPI_VALIDATE( X != NULL ); + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mbedtls_mpi_free( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + if( X->p != NULL ) + { + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + MPI_VALIDATE_RET( X != NULL ); + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->n < nblimbs ) + { + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Resize down as much as possible, + * while keeping at least the specified number of limbs + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + size_t i; + MPI_VALIDATE_RET( X != NULL ); + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + /* Actually resize up if there are currently fewer than nblimbs limbs. */ + if( X->n <= nblimbs ) + return( mbedtls_mpi_grow( X, nblimbs ) ); + /* After this point, then X->n > nblimbs and in particular X->n > 0. */ + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + i++; + + if( i < nblimbs ) + i = nblimbs; + + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); +} + +/* + * Copy the contents of Y into X + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + int ret = 0; + size_t i; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + if( X == Y ) + return( 0 ); + + if( Y->n == 0 ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + if( X->n < i ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + } + else + { + memset( X->p + i, 0, ( X->n - i ) * ciL ); + } + + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) +{ + mbedtls_mpi T; + MPI_VALIDATE( X != NULL ); + MPI_VALIDATE( Y != NULL ); + + memcpy( &T, X, sizeof( mbedtls_mpi ) ); + memcpy( X, Y, sizeof( mbedtls_mpi ) ); + memcpy( Y, &T, sizeof( mbedtls_mpi ) ); +} + +/* + * Conditionally assign dest = src, without leaking information + * about whether the assignment was made or not. + * dest and src must be arrays of limbs of size n. + * assign must be 0 or 1. + */ +static void mpi_safe_cond_assign( size_t n, + mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *src, + unsigned char assign ) +{ + size_t i; + for( i = 0; i < n; i++ ) + dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign; +} + +/* + * Conditionally assign X = Y, without leaking information + * about whether the assignment was made or not. + * (Leaking information about the respective sizes of X and Y is ok however.) + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) +{ + int ret = 0; + size_t i; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + /* make sure assign is 0 or 1 in a time-constant manner */ + assign = (assign | (unsigned char)-assign) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + + X->s = X->s * ( 1 - assign ) + Y->s * assign; + + mpi_safe_cond_assign( Y->n, X->p, Y->p, assign ); + + for( i = Y->n; i < X->n; i++ ) + X->p[i] *= ( 1 - assign ); + +cleanup: + return( ret ); +} + +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which whould lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) +{ + int ret, s; + size_t i; + mbedtls_mpi_uint tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + if( X == Y ) + return( 0 ); + + /* make sure swap is 0 or 1 in a time-constant manner */ + swap = (swap | (unsigned char)-swap) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); + + s = X->s; + X->s = X->s * ( 1 - swap ) + Y->s * swap; + Y->s = Y->s * ( 1 - swap ) + s * swap; + + + for( i = 0; i < X->n; i++ ) + { + tmp = X->p[i]; + X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; + Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; + } + +cleanup: + return( ret ); +} + +/* + * Set value from integer + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + int ret; + MPI_VALIDATE_RET( X != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) +{ + MPI_VALIDATE_RET( X != NULL ); + + if( X->n * biL <= pos ) + return( 0 ); + + return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); +} + +/* Get a specific byte, without range checks. */ +#define GET_BYTE( X, i ) \ + ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff ) + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + MPI_VALIDATE_RET( X != NULL ); + + if( val != 0 && val != 1 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( X->n * biL <= pos ) + { + if( val == 0 ) + return( 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); + } + + X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); + X->p[off] |= (mbedtls_mpi_uint) val << idx; + +cleanup: + + return( ret ); +} + +/* + * Return the number of less significant zero-bits + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) +{ + size_t i, j, count = 0; + MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 ); + + for( i = 0; i < X->n; i++ ) + for( j = 0; j < biL; j++, count++ ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Count leading zero bits in a given integer + */ +static size_t mbedtls_clz( const mbedtls_mpi_uint x ) +{ + size_t j; + mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); + + for( j = 0; j < biL; j++ ) + { + if( x & mask ) break; + + mask >>= 1; + } + + return j; +} + +/* + * Return the number of bits + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) +{ + size_t i, j; + + if( X->n == 0 ) + return( 0 ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + + j = biL - mbedtls_clz( X->p[i] ); + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ) +{ + return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) +{ + *d = 255; + + if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if( *d >= (mbedtls_mpi_uint) radix ) + return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) +{ + int ret; + size_t i, j, slen, n; + mbedtls_mpi_uint d; + mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( s != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + + slen = strlen( s ); + + if( radix == 16 ) + { + if( slen > MPI_SIZE_T_MAX >> 2 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = BITS_TO_LIMBS( slen << 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = slen, j = 0; i > 0; i--, j++ ) + { + if( i == 1 && s[i - 1] == '-' ) + { + X->s = -1; + break; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = 0; i < slen; i++ ) + { + if( i == 0 && s[i] == '-' ) + { + X->s = -1; + continue; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); + + if( X->s == 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first. + */ +static int mpi_write_hlp( mbedtls_mpi *X, int radix, + char **p, const size_t buflen ) +{ + int ret; + mbedtls_mpi_uint r; + size_t length = 0; + char *p_end = *p + buflen; + + do + { + if( length >= buflen ) + { + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + /* + * Write the residue in the current position, as an ASCII character. + */ + if( r < 0xA ) + *(--p_end) = (char)( '0' + r ); + else + *(--p_end) = (char)( 'A' + ( r - 0xA ) ); + + length++; + } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 ); + + memmove( *p, p_end, length ); + *p += length; + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ) +{ + int ret = 0; + size_t n; + char *p; + mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( olen != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */ + if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present + * `n`. If radix > 4, this might be a strict + * overapproximation of the number of + * radix-adic digits needed to present `n`. */ + if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to + * present `n`. */ + + n += 1; /* Terminating null byte */ + n += 1; /* Compensate for the divisions above, which round down `n` + * in case it's not even. */ + n += 1; /* Potential '-'-sign. */ + n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing, + * which always uses an even number of hex-digits. */ + + if( buflen < n ) + { + *olen = n; + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = buf; + mbedtls_mpi_init( &T ); + + if( X->s == -1 ) + { + *p++ = '-'; + buflen--; + } + + if( radix == 16 ) + { + int c; + size_t i, j, k; + + for( i = X->n, k = 0; i > 0; i-- ) + { + for( j = ciL; j > 0; j-- ) + { + c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; + + if( c == 0 && k == 0 && ( i + j ) != 2 ) + continue; + + *(p++) = "0123456789ABCDEF" [c / 16]; + *(p++) = "0123456789ABCDEF" [c % 16]; + k = 1; + } + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); + + if( T.s == -1 ) + T.s = 1; + + MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) ); + } + + *p++ = '\0'; + *olen = p - buf; + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Read X from an opened file + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) +{ + mbedtls_mpi_uint d; + size_t slen; + char *p; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( fin != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( s, 0, sizeof( s ) ); + if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if( slen == sizeof( s ) - 2 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + + p = s + slen; + while( p-- > s ) + if( mpi_get_digit( &d, radix, *p ) != 0 ) + break; + + return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) +{ + int ret; + size_t n, slen, plen; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + MPI_VALIDATE_RET( X != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( s, 0, sizeof( s ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); + + if( p == NULL ) p = ""; + + plen = strlen( p ); + slen = strlen( s ); + s[slen++] = '\r'; + s[slen++] = '\n'; + + if( fout != NULL ) + { + if( fwrite( p, 1, plen, fout ) != plen || + fwrite( s, 1, slen, fout ) != slen ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + } + else + mbedtls_printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + + +/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint + * into the storage form used by mbedtls_mpi. */ + +static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x ) +{ + uint8_t i; + unsigned char *x_ptr; + mbedtls_mpi_uint tmp = 0; + + for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ ) + { + tmp <<= CHAR_BIT; + tmp |= (mbedtls_mpi_uint) *x_ptr; + } + + return( tmp ); +} + +static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x ) +{ +#if defined(__BYTE_ORDER__) + +/* Nothing to do on bigendian systems. */ +#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) + return( x ); +#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */ + +#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) + +/* For GCC and Clang, have builtins for byte swapping. */ +#if defined(__GNUC__) && defined(__GNUC_PREREQ) +#if __GNUC_PREREQ(4,3) +#define have_bswap +#endif +#endif + +#if defined(__clang__) && defined(__has_builtin) +#if __has_builtin(__builtin_bswap32) && \ + __has_builtin(__builtin_bswap64) +#define have_bswap +#endif +#endif + +#if defined(have_bswap) + /* The compiler is hopefully able to statically evaluate this! */ + switch( sizeof(mbedtls_mpi_uint) ) + { + case 4: + return( __builtin_bswap32(x) ); + case 8: + return( __builtin_bswap64(x) ); + } +#endif +#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ +#endif /* __BYTE_ORDER__ */ + + /* Fall back to C-based reordering if we don't know the byte order + * or we couldn't use a compiler-specific builtin. */ + return( mpi_uint_bigendian_to_host_c( x ) ); +} + +static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs ) +{ + mbedtls_mpi_uint *cur_limb_left; + mbedtls_mpi_uint *cur_limb_right; + if( limbs == 0 ) + return; + + /* + * Traverse limbs and + * - adapt byte-order in each limb + * - swap the limbs themselves. + * For that, simultaneously traverse the limbs from left to right + * and from right to left, as long as the left index is not bigger + * than the right index (it's not a problem if limbs is odd and the + * indices coincide in the last iteration). + */ + for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 ); + cur_limb_left <= cur_limb_right; + cur_limb_left++, cur_limb_right-- ) + { + mbedtls_mpi_uint tmp; + /* Note that if cur_limb_left == cur_limb_right, + * this code effectively swaps the bytes only once. */ + tmp = mpi_uint_bigendian_to_host( *cur_limb_left ); + *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right ); + *cur_limb_right = tmp; + } +} + +/* + * Import X from unsigned binary data, big endian + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + size_t const overhead = ( limbs * ciL ) - buflen; + unsigned char *Xp; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + if( X->n != limbs ) + { + mbedtls_mpi_free( X ); + mbedtls_mpi_init( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + /* Avoid calling `memcpy` with NULL source argument, + * even if buflen is 0. */ + if( buf != NULL ) + { + Xp = (unsigned char*) X->p; + memcpy( Xp + overhead, buf, buflen ); + + mpi_bigendian_to_host( X->p, limbs ); + } + +cleanup: + + return( ret ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ) +{ + size_t stored_bytes; + size_t bytes_to_copy; + unsigned char *p; + size_t i; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + stored_bytes = X->n * ciL; + + if( stored_bytes < buflen ) + { + /* There is enough space in the output buffer. Write initial + * null bytes and record the position at which to start + * writing the significant bytes. In this case, the execution + * trace of this function does not depend on the value of the + * number. */ + bytes_to_copy = stored_bytes; + p = buf + buflen - stored_bytes; + memset( buf, 0, buflen - stored_bytes ); + } + else + { + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + bytes_to_copy = buflen; + p = buf; + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } + + for( i = 0; i < bytes_to_copy; i++ ) + p[bytes_to_copy - i - 1] = GET_BYTE( X, i ); + + return( 0 ); +} + +/* + * Left-shift: X <<= count + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) +{ + int ret; + size_t i, v0, t1; + mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mbedtls_mpi_bitlen( X ) + count; + + if( X->n * biL < i ) + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = X->n; i > v0; i-- ) + X->p[i - 1] = X->p[i - v0 - 1]; + + for( ; i > 0; i-- ) + X->p[i - 1] = 0; + } + + /* + * shift by count % limb_size + */ + if( t1 > 0 ) + { + for( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + +/* + * Right-shift: X >>= count + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) +{ + size_t i, v0, v1; + mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); + + v0 = count / biL; + v1 = count & (biL - 1); + + if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) + return mbedtls_mpi_lset( X, 0 ); + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = 0; i < X->n - v0; i++ ) + X->p[i] = X->p[i + v0]; + + for( ; i < X->n; i++ ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if( v1 > 0 ) + { + for( i = X->n; i > 0; i-- ) + { + r1 = X->p[i - 1] << (biL - v1); + X->p[i - 1] >>= v1; + X->p[i - 1] |= r0; + r0 = r1; + } + } + + return( 0 ); +} + +/* + * Compare unsigned values + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( 1 ); + if( j > i ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( X->s ); + if( j > i ) return( -Y->s ); + + if( X->s > 0 && Y->s < 0 ) return( 1 ); + if( Y->s > 0 && X->s < 0 ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); + } + + return( 0 ); +} + +/** Decide if an integer is less than the other, without branches. + * + * \param x First integer. + * \param y Second integer. + * + * \return 1 if \p x is less than \p y, 0 otherwise + */ +static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x, + const mbedtls_mpi_uint y ) +{ + mbedtls_mpi_uint ret; + mbedtls_mpi_uint cond; + + /* + * Check if the most significant bits (MSB) of the operands are different. + */ + cond = ( x ^ y ); + /* + * If the MSB are the same then the difference x-y will be negative (and + * have its MSB set to 1 during conversion to unsigned) if and only if x> ( biL - 1 ); + + return (unsigned) ret; +} + +/* + * Compare signed values in constant time + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, + unsigned *ret ) +{ + size_t i; + /* The value of any of these variables is either 0 or 1 at all times. */ + unsigned cond, done, X_is_negative, Y_is_negative; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + MPI_VALIDATE_RET( ret != NULL ); + + if( X->n != Y->n ) + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + + /* + * Set sign_N to 1 if N >= 0, 0 if N < 0. + * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. + */ + X_is_negative = ( X->s & 2 ) >> 1; + Y_is_negative = ( Y->s & 2 ) >> 1; + + /* + * If the signs are different, then the positive operand is the bigger. + * That is if X is negative (X_is_negative == 1), then X < Y is true and it + * is false if X is positive (X_is_negative == 0). + */ + cond = ( X_is_negative ^ Y_is_negative ); + *ret = cond & X_is_negative; + + /* + * This is a constant-time function. We might have the result, but we still + * need to go through the loop. Record if we have the result already. + */ + done = cond; + + for( i = X->n; i > 0; i-- ) + { + /* + * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both + * X and Y are negative. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] ); + *ret |= cond & ( 1 - done ) & X_is_negative; + done |= cond; + + /* + * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both + * X and Y are positive. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] ); + *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative ); + done |= cond; + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + mbedtls_mpi Y; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mbedtls_mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t i, j; + mbedtls_mpi_uint *o, *p, c, tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( X == B ) + { + const mbedtls_mpi *T = A; A = X; B = T; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned additions. + */ + X->s = 1; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + + o = B->p; p = X->p; c = 0; + + /* + * tmp is used because it might happen that p == o + */ + for( i = 0; i < j; i++, o++, p++ ) + { + tmp= *o; + *p += c; c = ( *p < c ); + *p += tmp; c += ( *p < tmp ); + } + + while( c != 0 ) + { + if( i >= X->n ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; p++; + } + +cleanup: + + return( ret ); +} + +/** + * Helper for mbedtls_mpi subtraction. + * + * Calculate d - s where d and s have the same size. + * This function operates modulo (2^ciL)^n and returns the carry + * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise). + * + * \param n Number of limbs of \p d and \p s. + * \param[in,out] d On input, the left operand. + * On output, the result of the subtraction: + * \param[in] s The right operand. + * + * \return 1 if `d < s`. + * 0 if `d >= s`. + */ +static mbedtls_mpi_uint mpi_sub_hlp( size_t n, + mbedtls_mpi_uint *d, + const mbedtls_mpi_uint *s ) +{ + size_t i; + mbedtls_mpi_uint c, z; + + for( i = c = 0; i < n; i++, s++, d++ ) + { + z = ( *d < c ); *d -= c; + c = ( *d < *s ) + z; *d -= *s; + } + + return( c ); +} + +/* + * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10) + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + mbedtls_mpi TB; + int ret; + size_t n; + mbedtls_mpi_uint carry; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init( &TB ); + + if( X == B ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + B = &TB; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned subtractions. + */ + X->s = 1; + + ret = 0; + + for( n = B->n; n > 0; n-- ) + if( B->p[n - 1] != 0 ) + break; + if( n > A->n ) + { + /* B >= (2^ciL)^n > A */ + ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; + goto cleanup; + } + + carry = mpi_sub_hlp( n, X->p, B->p ); + if( carry != 0 ) + { + /* Propagate the carry to the first nonzero limb of X. */ + for( ; n < X->n && X->p[n] == 0; n++ ) + --X->p[n]; + /* If we ran out of space for the carry, it means that the result + * is negative. */ + if( n == X->n ) + { + ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; + goto cleanup; + } + --X->p[n]; + } + +cleanup: + + mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + s = A->s; + if( A->s * B->s < 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed subtraction: X = A - B + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + s = A->s; + if( A->s * B->s > 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_add_mpi( X, A, &_B ) ); +} + +/* + * Signed subtraction: X = A - b + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_sub_mpi( X, A, &_B ) ); +} + +/* + * Helper for mbedtls_mpi multiplication + */ +static +#if defined(__APPLE__) && defined(__arm__) +/* + * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) + * appears to need this to prevent bad ARM code generation at -O3. + */ +__attribute__ ((noinline)) +#endif +void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) +{ + mbedtls_mpi_uint c = 0, t = 0; + +#if defined(MULADDC_HUIT) + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else /* MULADDC_HUIT */ + for( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif /* MULADDC_HUIT */ + + t++; + + do { + *d += c; c = ( *d < c ); d++; + } + while( c != 0 ); +} + +/* + * Baseline multiplication: X = A * B (HAC 14.12) + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t i, j; + mbedtls_mpi TA, TB; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } + if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } + + for( i = A->n; i > 0; i-- ) + if( A->p[i - 1] != 0 ) + break; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( ; j > 0; j-- ) + mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] ); + + X->s = A->s * B->s; + +cleanup: + + mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + _B.s = 1; + _B.n = 1; + _B.p = p; + p[0] = b; + + return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); +} + +/* + * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and + * mbedtls_mpi_uint divisor, d + */ +static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, + mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) +{ +#if defined(MBEDTLS_HAVE_UDBL) + mbedtls_t_udbl dividend, quotient; +#else + const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; + const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; + mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; + mbedtls_mpi_uint u0_msw, u0_lsw; + size_t s; +#endif + + /* + * Check for overflow + */ + if( 0 == d || u1 >= d ) + { + if (r != NULL) *r = ~0; + + return ( ~0 ); + } + +#if defined(MBEDTLS_HAVE_UDBL) + dividend = (mbedtls_t_udbl) u1 << biL; + dividend |= (mbedtls_t_udbl) u0; + quotient = dividend / d; + if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) + quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; + + if( r != NULL ) + *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); + + return (mbedtls_mpi_uint) quotient; +#else + + /* + * Algorithm D, Section 4.3.1 - The Art of Computer Programming + * Vol. 2 - Seminumerical Algorithms, Knuth + */ + + /* + * Normalize the divisor, d, and dividend, u0, u1 + */ + s = mbedtls_clz( d ); + d = d << s; + + u1 = u1 << s; + u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); + u0 = u0 << s; + + d1 = d >> biH; + d0 = d & uint_halfword_mask; + + u0_msw = u0 >> biH; + u0_lsw = u0 & uint_halfword_mask; + + /* + * Find the first quotient and remainder + */ + q1 = u1 / d1; + r0 = u1 - d1 * q1; + + while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) + { + q1 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); + q0 = rAX / d1; + r0 = rAX - q0 * d1; + + while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) + { + q0 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + if (r != NULL) + *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; + + quotient = q1 * radix + q0; + + return quotient; +#endif +} + +/* + * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ) +{ + int ret; + size_t i, n, t, k; + mbedtls_mpi X, Y, Z, T1, T2; + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); + + if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) + { + if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); + if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); + return( 0 ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); + X.s = Y.s = 1; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) ); + + k = mbedtls_mpi_bitlen( &Y ) % biL; + if( k < biL - 1 ) + { + k = biL - 1 - k; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); + + while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); + + for( i = n; i > t ; i-- ) + { + if( X.p[i] >= Y.p[t] ) + Z.p[i - t - 1] = ~0; + else + { + Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], + Y.p[t], NULL); + } + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); + T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) ); + T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; + T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + } + while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); + + if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if( Q != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); + Q->s = A->s * B->s; + } + + if( R != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); + X.s = A->s; + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); + + if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } + +cleanup: + + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); + + return( ret ); +} + +/* + * Division by int: A = Q * b + R + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, + const mbedtls_mpi *A, + mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) ); +} + +/* + * Modulo: R = A mod B + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + MPI_VALIDATE_RET( R != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); + + while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); + + while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + size_t i; + mbedtls_mpi_uint x, y, z; + MPI_VALIDATE_RET( r != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + if( b == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + if( b < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + /* + * handle trivial cases + */ + if( b == 1 ) + { + *r = 0; + return( 0 ); + } + + if( b == 2 ) + { + *r = A->p[0] & 1; + return( 0 ); + } + + /* + * general case + */ + for( i = A->n, y = 0; i > 0; i-- ) + { + x = A->p[i - 1]; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + + x <<= biH; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + } + + /* + * If A is negative, then the current y represents a negative value. + * Flipping it to the positive side. + */ + if( A->s < 0 && y != 0 ) + y = b - y; + + *r = y; + + return( 0 ); +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) +{ + mbedtls_mpi_uint x, m0 = N->p[0]; + unsigned int i; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + + for( i = biL; i >= 8; i /= 2 ) + x *= ( 2 - ( m0 * x ) ); + + *mm = ~x + 1; +} + +/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + * + * \param[in,out] A One of the numbers to multiply. + * It must have at least as many limbs as N + * (A->n >= N->n), and any limbs beyond n are ignored. + * On successful completion, A contains the result of + * the multiplication A * B * R^-1 mod N where + * R = (2^ciL)^n. + * \param[in] B One of the numbers to multiply. + * It must be nonzero and must not have more limbs than N + * (B->n <= N->n). + * \param[in] N The modulo. N must be odd. + * \param mm The value calculated by `mpi_montg_init(&mm, N)`. + * This is -N^-1 mod 2^ciL. + * \param[in,out] T A bignum for temporary storage. + * It must be at least twice the limb size of N plus 2 + * (T->n >= 2 * (N->n + 1)). + * Its initial content is unused and + * its final content is indeterminate. + * Note that unlike the usual convention in the library + * for `const mbedtls_mpi*`, the content of T can change. + */ +static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, + const mbedtls_mpi *T ) +{ + size_t i, n, m; + mbedtls_mpi_uint u0, u1, *d; + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + /* At this point, d is either the desired result or the desired result + * plus N. We now potentially subtract N, avoiding leaking whether the + * subtraction is performed through side channels. */ + + /* Copy the n least significant limbs of d to A, so that + * A = d if d < N (recall that N has n limbs). */ + memcpy( A->p, d, n * ciL ); + /* If d >= N then we want to set A to d - N. To prevent timing attacks, + * do the calculation without using conditional tests. */ + /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */ + d[n] += 1; + d[n] -= mpi_sub_hlp( n, d, N->p ); + /* If d0 < N then d < (2^biL)^n + * so d[n] == 0 and we want to keep A as it is. + * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n + * so d[n] == 1 and we want to set A to the result of the subtraction + * which is d - (2^biL)^n, i.e. the n least significant limbs of d. + * This exactly corresponds to a conditional assignment. */ + mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + * + * See mpi_montmul() regarding constraints and guarantees on the parameters. + */ +static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, + mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +{ + mbedtls_mpi_uint z = 1; + mbedtls_mpi U; + + U.n = U.s = (int) z; + U.p = &z; + + mpi_montmul( A, &U, N, mm, T ); +} + +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *_RR ) +{ + int ret; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + mbedtls_mpi_uint ei, mm, state; + mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; + int neg; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( E != NULL ); + MPI_VALIDATE_RET( N != NULL ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS || + mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS ) + return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); + mbedtls_mpi_init( &Apos ); + memset( W, 0, sizeof( W ) ); + + i = mbedtls_mpi_bitlen( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + +#if( MBEDTLS_MPI_WINDOW_SIZE < 6 ) + if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) + wsize = MBEDTLS_MPI_WINDOW_SIZE; +#endif + + j = N->n + 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + if( neg ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if( _RR == NULL || _RR->p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); + + if( _RR != NULL ) + memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); + } + else + memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); + + mpi_montmul( &W[1], &RR, N, mm, &T ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); + mpi_montred( X, N, mm, &T ); + + if( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << ( wsize - 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); + + for( i = 0; i < wsize - 1; i++ ) + mpi_montmul( &W[j], &W[j], N, mm, &T ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for( i = j + 1; i < ( one << wsize ); i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); + + mpi_montmul( &W[i], &W[1], N, mm, &T ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while( 1 ) + { + if( bufsize == 0 ) + { + if( nblimbs == 0 ) + break; + + nblimbs--; + + bufsize = sizeof( mbedtls_mpi_uint ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if( ei == 0 && state == 0 ) + continue; + + if( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + mpi_montmul( X, X, N, mm, &T ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= ( ei << ( wsize - nbits ) ); + + if( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for( i = 0; i < wsize; i++ ) + mpi_montmul( X, X, N, mm, &T ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + mpi_montmul( X, &W[wbits], N, mm, &T ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) + { + mpi_montmul( X, X, N, mm, &T ); + + wbits <<= 1; + + if( ( wbits & ( one << wsize ) ) != 0 ) + mpi_montmul( X, &W[1], N, mm, &T ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + mpi_montred( X, N, mm, &T ); + + if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) + { + X->s = -1; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); + } + +cleanup: + + for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) + mbedtls_mpi_free( &W[i] ); + + mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); + + if( _RR == NULL || _RR->p == NULL ) + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Greatest common divisor: G = gcd(A, B) (HAC 14.54) + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t lz, lzt; + mbedtls_mpi TG, TA, TB; + + MPI_VALIDATE_RET( G != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + + lz = mbedtls_mpi_lsb( &TA ); + lzt = mbedtls_mpi_lsb( &TB ); + + if( lzt < lz ) + lz = lzt; + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) ); + + TA.s = TB.s = 1; + + while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); + + if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); + +cleanup: + + mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* + * Fill X with size bytes of random. + * + * Use a temporary bytes representation to make sure the result is the same + * regardless of the platform endianness (useful when f_rng is actually + * deterministic, eg for tests). + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t const limbs = CHARS_TO_LIMBS( size ); + size_t const overhead = ( limbs * ciL ) - size; + unsigned char *Xp; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + if( X->n != limbs ) + { + mbedtls_mpi_free( X ); + mbedtls_mpi_init( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + Xp = (unsigned char*) X->p; + MBEDTLS_MPI_CHK( f_rng( p_rng, Xp + overhead, size ) ); + + mpi_bigendian_to_host( X->p, limbs ); + +cleanup: + return( ret ); +} + +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) +{ + int ret; + mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( N != NULL ); + + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); + mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); + mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); + + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); + + do + { + while( ( TU.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); + + if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); + } + + while( ( TV.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); + + if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); + } + + if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); + + while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); + + while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); + +cleanup: + + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); + mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); + mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); + + return( ret ); +} + +#if defined(MBEDTLS_GENPRIME) + +static const int small_prime[] = +{ + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, + 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, + 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, + 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, + 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, -103 +}; + +/* + * Small divisors test (X must be positive) + * + * Return values: + * 0: no small factor (possible prime, more tests needed) + * 1: certain prime + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime + * other negative: error + */ +static int mpi_check_small_factors( const mbedtls_mpi *X ) +{ + int ret = 0; + size_t i; + mbedtls_mpi_uint r; + + if( ( X->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + for( i = 0; small_prime[i] > 0; i++ ) + { + if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); + + if( r == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + +cleanup: + return( ret ); +} + +/* + * Miller-Rabin pseudo-primality test (HAC 4.24) + */ +static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count; + size_t i, j, k, s; + mbedtls_mpi W, R, T, A, RR; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); + mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); + mbedtls_mpi_init( &RR ); + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); + s = mbedtls_mpi_lsb( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); + + for( i = 0; i < rounds; i++ ) + { + /* + * pick a random A, 1 < A < |X| - 1 + */ + count = 0; + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + j = mbedtls_mpi_bitlen( &A ); + k = mbedtls_mpi_bitlen( &W ); + if (j > k) { + A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1; + } + + if (count++ > 30) { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || + mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); + + /* + * A = A^R mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); + + if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + continue; + + j = 1; + while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); + + if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + break; + + j++; + } + + /* + * not prime if A != |X| - 1 or A == 1 + */ + if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } + +cleanup: + mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); + mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Pseudo-primality test: small factors, then Miller-Rabin + */ +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi XX; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + XX.s = 1; + XX.n = X->n; + XX.p = X->p; + + if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || + mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) + return( 0 ); + + if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) + { + if( ret == 1 ) + return( 0 ); + + return( ret ); + } + + return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/* + * Pseudo-primality test, error probability 2^-80 + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + /* + * In the past our key generation aimed for an error rate of at most + * 2^-80. Since this function is deprecated, aim for the same certainty + * here as well. + */ + return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) ); +} +#endif + +/* + * Prime number generation + * + * To generate an RSA key in a way recommended by FIPS 186-4, both primes must + * be either 1024 bits or 1536 bits long, and flags must contain + * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ +#ifdef MBEDTLS_HAVE_INT64 +// ceil(2^63.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL +#else +// ceil(2^31.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U +#endif + int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + size_t k, n; + int rounds; + mbedtls_mpi_uint r; + mbedtls_mpi Y; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &Y ); + + n = BITS_TO_LIMBS( nbits ); + + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 ) + { + /* + * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 + */ + rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 : + ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 : + ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 ); + } + else + { + /* + * 2^-100 error probability, number of rounds computed based on HAC, + * fact 4.48 + */ + rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 : + ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 : + ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 : + ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 ); + } + + while( 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ + if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue; + + k = n * biL; + if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); + X->p[0] |= 1; + + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 ) + { + ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng ); + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + } + else + { + /* + * An necessary condition for Y and X = 2Y + 1 to be prime + * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). + * Make sure it is satisfied, while keeping X = 3 mod 4 + */ + + X->p[0] |= 2; + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); + if( r == 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); + else if( r == 1 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); + + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); + + while( 1 ) + { + /* + * First, check small factors for X and Y + * before doing Miller-Rabin on any of them + */ + if( ( ret = mpi_check_small_factors( X ) ) == 0 && + ( ret = mpi_check_small_factors( &Y ) ) == 0 && + ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) ) + == 0 && + ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) ) + == 0 ) + goto cleanup; + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + /* + * Next candidates. We want to preserve Y = (X-1) / 2 and + * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) + * so up Y by 6 and X by 12. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &Y ); + + return( ret ); +} + +#endif /* MBEDTLS_GENPRIME */ + +#if defined(MBEDTLS_SELF_TEST) + +#define GCD_PAIR_COUNT 3 + +static const int gcd_pairs[GCD_PAIR_COUNT][3] = +{ + { 693, 609, 21 }, + { 1764, 868, 28 }, + { 768454923, 542167814, 1 } +}; + +/* + * Checkup routine + */ +int mbedtls_mpi_self_test( int verbose ) +{ + int ret, i; + mbedtls_mpi A, E, N, X, Y, U, V; + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); + mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, + "EFE021C2645FD1DC586E69184AF4A31E" \ + "D5F53E93B5F123FA41680867BA110131" \ + "944FE7952E2517337780CB0DB80E61AA" \ + "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, + "B2E7EFD37075B9F03FF989C7C5051C20" \ + "34D2A323810251127E7BF8625A4F49A5" \ + "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ + "5B5C25763222FEFCCFC38B832366C29E" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, + "0066A198186C18C10B2F5ED9B522752A" \ + "9830B69916E535C8F047518A889A43A5" \ + "94B6BED27A168D31D4A52F88925AA8F5" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "602AB7ECA597A3D6B56FF9829A5E8B85" \ + "9E857EA95A03512E2BAE7391688D264A" \ + "A5663B0341DB9CCFD2C4C5F421FEC814" \ + "8001B72E848A38CAE1C65F78E56ABDEF" \ + "E12D3C039B8A02D6BE593F0BBBDA56F1" \ + "ECF677152EF804370C1A305CAF3B5BF1" \ + "30879B56C61DE584A0F53A2447A51E" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #1 (mul_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "256567336059E52CAE22925474705F39A94" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, + "6613F26162223DF488E9CD48CC132C7A" \ + "0AC93C701B001B092E4E5B9F73BCD27B" \ + "9EE50D0657C77F374E903CDFA4C642" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #2 (div_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || + mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "36E139AEA55215609D2816998ED020BB" \ + "BD96C37890F65171D948E9BC7CBAA4D9" \ + "325D24D6A3C12710F10A09FA08AB87" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #3 (exp_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ + "C3DBA76456363A10869622EAC2DD84EC" \ + "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #4 (inv_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #5 (simple gcd): " ); + + for( i = 0; i < GCD_PAIR_COUNT; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); + + if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed at %d\n", i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); + + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); + mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BIGNUM_C */ diff --git a/external/mbedtls/library/blowfish.c b/external/mbedtls/library/blowfish.c new file mode 100644 index 0000000..a3f9be9 --- /dev/null +++ b/external/mbedtls/library/blowfish.c @@ -0,0 +1,721 @@ +/* + * Blowfish implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The Blowfish block cipher was designed by Bruce Schneier in 1993. + * http://www.schneier.com/blowfish.html + * http://en.wikipedia.org/wiki/Blowfish_%28cipher%29 + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + +#include "mbedtls/blowfish.h" +#include "mbedtls/platform_util.h" + +#include + +#if !defined(MBEDTLS_BLOWFISH_ALT) + +/* Parameter validation macros */ +#define BLOWFISH_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ) +#define BLOWFISH_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +static const uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2] = { + 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, + 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, + 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, + 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, + 0x9216D5D9L, 0x8979FB1BL +}; + +/* declarations of data at the end of this file */ +static const uint32_t S[4][256]; + +static uint32_t F( mbedtls_blowfish_context *ctx, uint32_t x ) +{ + unsigned short a, b, c, d; + uint32_t y; + + d = (unsigned short)(x & 0xFF); + x >>= 8; + c = (unsigned short)(x & 0xFF); + x >>= 8; + b = (unsigned short)(x & 0xFF); + x >>= 8; + a = (unsigned short)(x & 0xFF); + y = ctx->S[0][a] + ctx->S[1][b]; + y = y ^ ctx->S[2][c]; + y = y + ctx->S[3][d]; + + return( y ); +} + +static void blowfish_enc( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS; ++i ) + { + Xl = Xl ^ ctx->P[i]; + Xr = F( ctx, Xl ) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS]; + Xl = Xl ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS + 1]; + + *xl = Xl; + *xr = Xr; +} + +static void blowfish_dec( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = MBEDTLS_BLOWFISH_ROUNDS + 1; i > 1; --i ) + { + Xl = Xl ^ ctx->P[i]; + Xr = F( ctx, Xl ) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[1]; + Xl = Xl ^ ctx->P[0]; + + *xl = Xl; + *xr = Xr; +} + +void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ) +{ + BLOWFISH_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_blowfish_context ) ); +} + +void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_blowfish_context ) ); +} + +/* + * Blowfish key schedule + */ +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, + const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i, j, k; + uint32_t data, datal, datar; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( key != NULL ); + + if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || + keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || + keybits % 8 != 0 ) + { + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); + } + + keybits >>= 3; + + for( i = 0; i < 4; i++ ) + { + for( j = 0; j < 256; j++ ) + ctx->S[i][j] = S[i][j]; + } + + j = 0; + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; ++i ) + { + data = 0x00000000; + for( k = 0; k < 4; ++k ) + { + data = ( data << 8 ) | key[j++]; + if( j >= keybits ) + j = 0; + } + ctx->P[i] = P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; i += 2 ) + { + blowfish_enc( ctx, &datal, &datar ); + ctx->P[i] = datal; + ctx->P[i + 1] = datar; + } + + for( i = 0; i < 4; i++ ) + { + for( j = 0; j < 256; j += 2 ) + { + blowfish_enc( ctx, &datal, &datar ); + ctx->S[i][j] = datal; + ctx->S[i][j + 1] = datar; + } + } + return( 0 ); +} + +/* + * Blowfish-ECB block encryption/decryption + */ +int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, + int mode, + const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ) +{ + uint32_t X0, X1; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( input != NULL ); + BLOWFISH_VALIDATE_RET( output != NULL ); + + GET_UINT32_BE( X0, input, 0 ); + GET_UINT32_BE( X1, input, 4 ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + blowfish_dec( ctx, &X0, &X1 ); + } + else /* MBEDTLS_BLOWFISH_ENCRYPT */ + { + blowfish_enc( ctx, &X0, &X1 ); + } + + PUT_UINT32_BE( X0, output, 0 ); + PUT_UINT32_BE( X1, output, 4 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * Blowfish-CBC buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE]; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( iv != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); + + if( length % MBEDTLS_BLOWFISH_BLOCKSIZE ) + return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, MBEDTLS_BLOWFISH_BLOCKSIZE ); + mbedtls_blowfish_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE;i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, MBEDTLS_BLOWFISH_BLOCKSIZE ); + + input += MBEDTLS_BLOWFISH_BLOCKSIZE; + output += MBEDTLS_BLOWFISH_BLOCKSIZE; + length -= MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_blowfish_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, MBEDTLS_BLOWFISH_BLOCKSIZE ); + + input += MBEDTLS_BLOWFISH_BLOCKSIZE; + output += MBEDTLS_BLOWFISH_BLOCKSIZE; + length -= MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * Blowfish CFB buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n; + + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( iv != NULL ); + BLOWFISH_VALIDATE_RET( iv_off != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); + + n = *iv_off; + if( n >= 8 ) + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Blowfish CTR buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( nonce_counter != NULL ); + BLOWFISH_VALIDATE_RET( stream_block != NULL ); + BLOWFISH_VALIDATE_RET( nc_off != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); + + n = *nc_off; + if( n >= 8 ) + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, nonce_counter, + stream_block ); + + for( i = MBEDTLS_BLOWFISH_BLOCKSIZE; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static const uint32_t S[4][256] = { + { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, + 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, + 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, + 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, + 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, + 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, + 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, + 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, + 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, + 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, + 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, + 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, + 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, + 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, + 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, + 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, + 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, + 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, + 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, + 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, + 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, + 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, + 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, + 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, + 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, + 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, + 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, + 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, + 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, + 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, + 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, + 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, + 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, + 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, + 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, + 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, + 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, + 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, + 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, + 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, + 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, + 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, + 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, + 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, + 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, + 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, + 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, + 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, + 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, + 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, + 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, + 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, + 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, + 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, + 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, + 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, + 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, + 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, + 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, + 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, + 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, + 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, + 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, + 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL }, + { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, + 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, + 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, + 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, + 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, + 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, + 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, + 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, + 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, + 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, + 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, + 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, + 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, + 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, + 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, + 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, + 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, + 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, + 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, + 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, + 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, + 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, + 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, + 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, + 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, + 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, + 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, + 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, + 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, + 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, + 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, + 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, + 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, + 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, + 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, + 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, + 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, + 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, + 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, + 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, + 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, + 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, + 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, + 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, + 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, + 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, + 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, + 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, + 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, + 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, + 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, + 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, + 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, + 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, + 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, + 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, + 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, + 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, + 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, + 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, + 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, + 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, + 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, + 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L }, + { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, + 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, + 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, + 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, + 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, + 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, + 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, + 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, + 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, + 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, + 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, + 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, + 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, + 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, + 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, + 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, + 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, + 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, + 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, + 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, + 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, + 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, + 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, + 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, + 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, + 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, + 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, + 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, + 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, + 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, + 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, + 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, + 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, + 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, + 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, + 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, + 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, + 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, + 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, + 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, + 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, + 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, + 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, + 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, + 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, + 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, + 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, + 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, + 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, + 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, + 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, + 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, + 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, + 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, + 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, + 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, + 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, + 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, + 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, + 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, + 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, + 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, + 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, + 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L }, + { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, + 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, + 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, + 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, + 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, + 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, + 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, + 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, + 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, + 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, + 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, + 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, + 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, + 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, + 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, + 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, + 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, + 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, + 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, + 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, + 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, + 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, + 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, + 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, + 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, + 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, + 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, + 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, + 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, + 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, + 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, + 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, + 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, + 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, + 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, + 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, + 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, + 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, + 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, + 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, + 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, + 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, + 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, + 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, + 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, + 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, + 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, + 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, + 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, + 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, + 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, + 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, + 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, + 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, + 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, + 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, + 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, + 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, + 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, + 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, + 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, + 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, + 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, + 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L } +}; + +#endif /* !MBEDTLS_BLOWFISH_ALT */ +#endif /* MBEDTLS_BLOWFISH_C */ diff --git a/external/mbedtls/library/camellia.c b/external/mbedtls/library/camellia.c new file mode 100644 index 0000000..40d6212 --- /dev/null +++ b/external/mbedtls/library/camellia.c @@ -0,0 +1,1139 @@ +/* + * Camellia implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The Camellia block cipher was designed by NTT and Mitsubishi Electric + * Corporation. + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CAMELLIA_C) + +#include "mbedtls/camellia.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CAMELLIA_ALT) + +/* Parameter validation macros */ +#define CAMELLIA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ) +#define CAMELLIA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +static const unsigned char SIGMA_CHARS[6][8] = +{ + { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, + { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 }, + { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe }, + { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c }, + { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d }, + { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd } +}; + +#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) + +static const unsigned char FSb[256] = +{ + 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65, + 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189, + 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26, + 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77, + 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153, + 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215, + 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34, + 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80, + 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210, + 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148, + 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226, + 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46, + 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89, + 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250, + 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164, + 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff) +#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff) +#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff] + +#else /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char FSb[256] = +{ + 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, + 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, + 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, + 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, + 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, + 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, + 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, + 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, + 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, + 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, + 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, + 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, + 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, + 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, + 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, + 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 +}; + +static const unsigned char FSb2[256] = +{ + 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, + 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, + 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, + 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154, + 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, + 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, + 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, + 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160, + 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, + 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, + 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, + 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, + 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, + 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, + 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73, + 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 +}; + +static const unsigned char FSb3[256] = +{ + 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, + 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222, + 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, + 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166, + 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, + 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, + 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, + 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, + 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, + 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, + 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113, + 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, + 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, + 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, + 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, + 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79 +}; + +static const unsigned char FSb4[256] = +{ + 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, + 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, + 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4, + 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, + 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, + 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99, + 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141, + 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, + 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, + 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, + 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, + 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, + 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148, + 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, + 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250, + 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) FSb2[(n)] +#define SBOX3(n) FSb3[(n)] +#define SBOX4(n) FSb4[(n)] + +#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char shifts[2][4][4] = +{ + { + { 1, 1, 1, 1 }, /* KL */ + { 0, 0, 0, 0 }, /* KR */ + { 1, 1, 1, 1 }, /* KA */ + { 0, 0, 0, 0 } /* KB */ + }, + { + { 1, 0, 1, 1 }, /* KL */ + { 1, 1, 0, 1 }, /* KR */ + { 1, 1, 1, 0 }, /* KA */ + { 1, 1, 0, 1 } /* KB */ + } +}; + +static const signed char indexes[2][4][20] = +{ + { + { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39, + 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */ + { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, + 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */ + }, + { + { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1, + -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */ + { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, + 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */ + { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, + 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */ + { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, + 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */ + } +}; + +static const signed char transposes[2][20] = +{ + { + 21, 22, 23, 20, + -1, -1, -1, -1, + 18, 19, 16, 17, + 11, 8, 9, 10, + 15, 12, 13, 14 + }, + { + 25, 26, 27, 24, + 29, 30, 31, 28, + 18, 19, 16, 17, + -1, -1, -1, -1, + -1, -1, -1, -1 + } +}; + +/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */ +#define ROTL(DEST, SRC, SHIFT) \ +{ \ + (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \ + (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \ + (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \ + (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \ +} + +#define FL(XL, XR, KL, KR) \ +{ \ + (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \ + (XL) = ((XR) | (KR)) ^ (XL); \ +} + +#define FLInv(YL, YR, KL, KR) \ +{ \ + (YL) = ((YR) | (KR)) ^ (YL); \ + (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \ +} + +#define SHIFT_AND_PLACE(INDEX, OFFSET) \ +{ \ + TK[0] = KC[(OFFSET) * 4 + 0]; \ + TK[1] = KC[(OFFSET) * 4 + 1]; \ + TK[2] = KC[(OFFSET) * 4 + 2]; \ + TK[3] = KC[(OFFSET) * 4 + 3]; \ + \ + for( i = 1; i <= 4; i++ ) \ + if( shifts[(INDEX)][(OFFSET)][i -1] ) \ + ROTL(TK + i * 4, TK, ( 15 * i ) % 32); \ + \ + for( i = 0; i < 20; i++ ) \ + if( indexes[(INDEX)][(OFFSET)][i] != -1 ) { \ + RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \ + } \ +} + +static void camellia_feistel( const uint32_t x[2], const uint32_t k[2], + uint32_t z[2]) +{ + uint32_t I0, I1; + I0 = x[0] ^ k[0]; + I1 = x[1] ^ k[1]; + + I0 = ((uint32_t) SBOX1((I0 >> 24) & 0xFF) << 24) | + ((uint32_t) SBOX2((I0 >> 16) & 0xFF) << 16) | + ((uint32_t) SBOX3((I0 >> 8) & 0xFF) << 8) | + ((uint32_t) SBOX4((I0 ) & 0xFF) ); + I1 = ((uint32_t) SBOX2((I1 >> 24) & 0xFF) << 24) | + ((uint32_t) SBOX3((I1 >> 16) & 0xFF) << 16) | + ((uint32_t) SBOX4((I1 >> 8) & 0xFF) << 8) | + ((uint32_t) SBOX1((I1 ) & 0xFF) ); + + I0 ^= (I1 << 8) | (I1 >> 24); + I1 ^= (I0 << 16) | (I0 >> 16); + I0 ^= (I1 >> 8) | (I1 << 24); + I1 ^= (I0 >> 8) | (I0 << 24); + + z[0] ^= I1; + z[1] ^= I0; +} + +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ) +{ + CAMELLIA_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_camellia_context ) ); +} + +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_camellia_context ) ); +} + +/* + * Camellia key schedule (encryption) + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ) +{ + int idx; + size_t i; + uint32_t *RK; + unsigned char t[64]; + uint32_t SIGMA[6][2]; + uint32_t KC[16]; + uint32_t TK[20]; + + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( key != NULL ); + + RK = ctx->rk; + + memset( t, 0, 64 ); + memset( RK, 0, sizeof(ctx->rk) ); + + switch( keybits ) + { + case 128: ctx->nr = 3; idx = 0; break; + case 192: + case 256: ctx->nr = 4; idx = 1; break; + default : return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); + } + + for( i = 0; i < keybits / 8; ++i ) + t[i] = key[i]; + + if( keybits == 192 ) { + for( i = 0; i < 8; i++ ) + t[24 + i] = ~t[16 + i]; + } + + /* + * Prepare SIGMA values + */ + for( i = 0; i < 6; i++ ) { + GET_UINT32_BE( SIGMA[i][0], SIGMA_CHARS[i], 0 ); + GET_UINT32_BE( SIGMA[i][1], SIGMA_CHARS[i], 4 ); + } + + /* + * Key storage in KC + * Order: KL, KR, KA, KB + */ + memset( KC, 0, sizeof(KC) ); + + /* Store KL, KR */ + for( i = 0; i < 8; i++ ) + GET_UINT32_BE( KC[i], t, i * 4 ); + + /* Generate KA */ + for( i = 0; i < 4; ++i ) + KC[8 + i] = KC[i] ^ KC[4 + i]; + + camellia_feistel( KC + 8, SIGMA[0], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[1], KC + 8 ); + + for( i = 0; i < 4; ++i ) + KC[8 + i] ^= KC[i]; + + camellia_feistel( KC + 8, SIGMA[2], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[3], KC + 8 ); + + if( keybits > 128 ) { + /* Generate KB */ + for( i = 0; i < 4; ++i ) + KC[12 + i] = KC[4 + i] ^ KC[8 + i]; + + camellia_feistel( KC + 12, SIGMA[4], KC + 14 ); + camellia_feistel( KC + 14, SIGMA[5], KC + 12 ); + } + + /* + * Generating subkeys + */ + + /* Manipulating KL */ + SHIFT_AND_PLACE( idx, 0 ); + + /* Manipulating KR */ + if( keybits > 128 ) { + SHIFT_AND_PLACE( idx, 1 ); + } + + /* Manipulating KA */ + SHIFT_AND_PLACE( idx, 2 ); + + /* Manipulating KB */ + if( keybits > 128 ) { + SHIFT_AND_PLACE( idx, 3 ); + } + + /* Do transpositions */ + for( i = 0; i < 20; i++ ) { + if( transposes[idx][i] != -1 ) { + RK[32 + 12 * idx + i] = RK[transposes[idx][i]]; + } + } + + return( 0 ); +} + +/* + * Camellia key schedule (decryption) + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ) +{ + int idx, ret; + size_t i; + mbedtls_camellia_context cty; + uint32_t *RK; + uint32_t *SK; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( key != NULL ); + + mbedtls_camellia_init( &cty ); + + /* Also checks keybits */ + if( ( ret = mbedtls_camellia_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + idx = ( ctx->nr == 4 ); + + RK = ctx->rk; + SK = cty.rk + 24 * 2 + 8 * idx * 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4 ) + { + *RK++ = *SK++; + *RK++ = *SK++; + } + + SK -= 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_camellia_free( &cty ); + + return( ret ); +} + +/* + * Camellia-ECB block encryption/decryption + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int NR; + uint32_t *RK, X[4]; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( input != NULL ); + CAMELLIA_VALIDATE_RET( output != NULL ); + + ( (void) mode ); + + NR = ctx->nr; + RK = ctx->rk; + + GET_UINT32_BE( X[0], input, 0 ); + GET_UINT32_BE( X[1], input, 4 ); + GET_UINT32_BE( X[2], input, 8 ); + GET_UINT32_BE( X[3], input, 12 ); + + X[0] ^= *RK++; + X[1] ^= *RK++; + X[2] ^= *RK++; + X[3] ^= *RK++; + + while( NR ) { + --NR; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + + if( NR ) { + FL(X[0], X[1], RK[0], RK[1]); + RK += 2; + FLInv(X[2], X[3], RK[0], RK[1]); + RK += 2; + } + } + + X[2] ^= *RK++; + X[3] ^= *RK++; + X[0] ^= *RK++; + X[1] ^= *RK++; + + PUT_UINT32_BE( X[2], output, 0 ); + PUT_UINT32_BE( X[3], output, 4 ); + PUT_UINT32_BE( X[0], output, 8 ); + PUT_UINT32_BE( X[1], output, 12 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * Camellia-CBC buffer encryption/decryption + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( iv != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + if( length % 16 ) + return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_CAMELLIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + mbedtls_camellia_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_camellia_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * Camellia-CFB128 buffer encryption/decryption + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( iv != NULL ); + CAMELLIA_VALIDATE_RET( iv_off != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + n = *iv_off; + if( n >= 16 ) + return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_CAMELLIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Camellia-CTR buffer encryption/decryption + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( nonce_counter != NULL ); + CAMELLIA_VALIDATE_RET( stream_block != NULL ); + CAMELLIA_VALIDATE_RET( nc_off != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + n = *nc_off; + if( n >= 16 ) + return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter, + stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* !MBEDTLS_CAMELLIA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Camellia test vectors from: + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html: + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt + * (For each bitlength: Key 0, Nr 39) + */ +#define CAMELLIA_TESTS_ECB 2 + +static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] = +{ + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 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 } + }, +}; + +static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = +{ + { + { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, + 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }, + { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE, + 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 } + }, + { + { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, + 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }, + { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9, + 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 } + }, + { + { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, + 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }, + { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C, + 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 } + } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define CAMELLIA_TESTS_CBC 3 + +static const unsigned char camellia_test_cbc_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } + , + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B } + , + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char camellia_test_cbc_iv[16] = + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } +; + +static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] = +{ + { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A }, + { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 }, + { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF } + +}; + +static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = +{ + { + { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0, + 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB }, + { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78, + 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 }, + { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B, + 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 } + }, + { + { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2, + 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 }, + { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42, + 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 }, + { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8, + 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 } + }, + { + { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A, + 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA }, + { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40, + 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 }, + { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA, + 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 } + } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Camellia-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc5528.html + */ + +static const unsigned char camellia_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char camellia_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char camellia_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 } +}; + +static const unsigned char camellia_test_ctr_ct[3][48] = +{ + { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, + 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F }, + { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, + 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, + 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, + 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 }, + { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88, + 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73, + 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1, + 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD, + 0xDF, 0x50, 0x86, 0x96 } +}; + +static const int camellia_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int mbedtls_camellia_self_test( int verbose ) +{ + int i, j, u, v; + unsigned char key[32]; + unsigned char buf[64]; + unsigned char src[16]; + unsigned char dst[16]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + size_t offset, len; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + + mbedtls_camellia_context ctx; + + memset( key, 0, 32 ); + + for( j = 0; j < 6; j++ ) { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, + (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); + + for( i = 0; i < CAMELLIA_TESTS_ECB; i++ ) { + memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_cipher[u][i], 16 ); + memcpy( dst, camellia_test_ecb_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_plain[i], 16 ); + memcpy( dst, camellia_test_ecb_cipher[u][i], 16 ); + } + + mbedtls_camellia_crypt_ecb( &ctx, v, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( j = 0; j < 6; j++ ) + { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, + ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( src, camellia_test_cbc_iv, 16 ); + memcpy( dst, camellia_test_cbc_iv, 16 ); + memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + } else { + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + } + + for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + memcpy( iv , src, 16 ); + memcpy( src, camellia_test_cbc_cipher[u][i], 16 ); + memcpy( dst, camellia_test_cbc_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + memcpy( iv , dst, 16 ); + memcpy( src, camellia_test_cbc_plain[i], 16 ); + memcpy( dst, camellia_test_cbc_cipher[u][i], 16 ); + } + + mbedtls_camellia_crypt_cbc( &ctx, v, 16, iv, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-CTR-128 (%s): ", + ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 ); + memcpy( key, camellia_test_ctr_key[u], 16 ); + + offset = 0; + mbedtls_camellia_setkey_enc( &ctx, key, 128 ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_ct[u], len ); + + mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + else + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_pt[u], len ); + + mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CAMELLIA_C */ diff --git a/external/mbedtls/library/ccm.c b/external/mbedtls/library/ccm.c new file mode 100644 index 0000000..b2e5a47 --- /dev/null +++ b/external/mbedtls/library/ccm.c @@ -0,0 +1,570 @@ +/* + * NIST SP800-38C compliant CCM implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CCM_C) + +#include "mbedtls/ccm.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_CCM_ALT) + +#define CCM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT ) +#define CCM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define CCM_ENCRYPT 0 +#define CCM_DECRYPT 1 + +/* + * Initialize context + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ) +{ + CCM_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_ccm_context ) ); +} + +int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( key != NULL ); + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) +{ + if( ctx == NULL ) + return; + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); +} + +/* + * Macros for common operations. + * Results in smaller compiled code than static inline functions. + */ + +/* + * Update the CBC-MAC state in y using a block in b + * (Always using b as the source helps the compiler optimise a bit better.) + */ +#define UPDATE_CBC_MAC \ + for( i = 0; i < 16; i++ ) \ + y[i] ^= b[i]; \ + \ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \ + return( ret ); + +/* + * Encrypt or decrypt a partial block with CTR + * Warning: using b for temporary storage! src and dst must not be b! + * This avoids allocating one more 16 bytes buffer while allowing src == dst. + */ +#define CTR_CRYPT( dst, src, len ) \ + do \ + { \ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr, \ + 16, b, &olen ) ) != 0 ) \ + { \ + return( ret ); \ + } \ + \ + for( i = 0; i < (len); i++ ) \ + (dst)[i] = (src)[i] ^ b[i]; \ + } while( 0 ) + +/* + * Authenticated encryption or decryption + */ +static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + int ret; + unsigned char i; + unsigned char q; + size_t len_left, olen; + unsigned char b[16]; + unsigned char y[16]; + unsigned char ctr[16]; + const unsigned char *src; + unsigned char *dst; + + /* + * Check length requirements: SP800-38C A.1 + * Additional requirement: a < 2^16 - 2^8 to simplify the code. + * 'length' checked later (when writing it to the first block) + * + * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). + */ + if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + /* Also implies q is within bounds */ + if( iv_len < 7 || iv_len > 13 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + if( add_len > 0xFF00 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + q = 16 - 1 - (unsigned char) iv_len; + + /* + * First block B_0: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 length + * + * With flags as (bits): + * 7 0 + * 6 add present? + * 5 .. 3 (t - 2) / 2 + * 2 .. 0 q - 1 + */ + b[0] = 0; + b[0] |= ( add_len > 0 ) << 6; + b[0] |= ( ( tag_len - 2 ) / 2 ) << 3; + b[0] |= q - 1; + + memcpy( b + 1, iv, iv_len ); + + for( i = 0, len_left = length; i < q; i++, len_left >>= 8 ) + b[15-i] = (unsigned char)( len_left & 0xFF ); + + if( len_left > 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + + /* Start CBC-MAC with first block */ + memset( y, 0, 16 ); + UPDATE_CBC_MAC; + + /* + * If there is additional data, update CBC-MAC with + * add_len, add, 0 (padding to a block boundary) + */ + if( add_len > 0 ) + { + size_t use_len; + len_left = add_len; + src = add; + + memset( b, 0, 16 ); + b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF ); + b[1] = (unsigned char)( ( add_len ) & 0xFF ); + + use_len = len_left < 16 - 2 ? len_left : 16 - 2; + memcpy( b + 2, src, use_len ); + len_left -= use_len; + src += use_len; + + UPDATE_CBC_MAC; + + while( len_left > 0 ) + { + use_len = len_left > 16 ? 16 : len_left; + + memset( b, 0, 16 ); + memcpy( b, src, use_len ); + UPDATE_CBC_MAC; + + len_left -= use_len; + src += use_len; + } + } + + /* + * Prepare counter block for encryption: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 counter (initially 1) + * + * With flags as (bits): + * 7 .. 3 0 + * 2 .. 0 q - 1 + */ + ctr[0] = q - 1; + memcpy( ctr + 1, iv, iv_len ); + memset( ctr + 1 + iv_len, 0, q ); + ctr[15] = 1; + + /* + * Authenticate and {en,de}crypt the message. + * + * The only difference between encryption and decryption is + * the respective order of authentication and {en,de}cryption. + */ + len_left = length; + src = input; + dst = output; + + while( len_left > 0 ) + { + size_t use_len = len_left > 16 ? 16 : len_left; + + if( mode == CCM_ENCRYPT ) + { + memset( b, 0, 16 ); + memcpy( b, src, use_len ); + UPDATE_CBC_MAC; + } + + CTR_CRYPT( dst, src, use_len ); + + if( mode == CCM_DECRYPT ) + { + memset( b, 0, 16 ); + memcpy( b, dst, use_len ); + UPDATE_CBC_MAC; + } + + dst += use_len; + src += use_len; + len_left -= use_len; + + /* + * Increment counter. + * No need to check for overflow thanks to the length check above. + */ + for( i = 0; i < q; i++ ) + if( ++ctr[15-i] != 0 ) + break; + } + + /* + * Authentication: reset counter and crypt/mask internal tag + */ + for( i = 0; i < q; i++ ) + ctr[15-i] = 0; + + CTR_CRYPT( y, y, 16 ); + memcpy( tag, y, tag_len ); + + return( 0 ); +} + +/* + * Authenticated encryption + */ +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len, + add, add_len, input, output, tag, tag_len ) ); +} + +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( tag_len == 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add, + add_len, input, output, tag, tag_len ) ); +} + +/* + * Authenticated decryption + */ +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + int ret; + unsigned char check_tag[16]; + unsigned char i; + int diff; + + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + + if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, check_tag, tag_len ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( MBEDTLS_ERR_CCM_AUTH_FAILED ); + } + + return( 0 ); +} + +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + + if( tag_len == 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add, + add_len, input, output, tag, tag_len ) ); +} +#endif /* !MBEDTLS_CCM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/* + * Examples 1 to 3 from SP800-38C Appendix C + */ + +#define NB_TESTS 3 +#define CCM_SELFTEST_PT_MAX_LEN 24 +#define CCM_SELFTEST_CT_MAX_LEN 32 +/* + * The data is the same for all tests, only the used length changes + */ +static const unsigned char key[] = { + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f +}; + +static const unsigned char iv[] = { + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b +}; + +static const unsigned char ad[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char msg[CCM_SELFTEST_PT_MAX_LEN] = { + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, +}; + +static const size_t iv_len [NB_TESTS] = { 7, 8, 12 }; +static const size_t add_len[NB_TESTS] = { 8, 16, 20 }; +static const size_t msg_len[NB_TESTS] = { 4, 16, 24 }; +static const size_t tag_len[NB_TESTS] = { 4, 6, 8 }; + +static const unsigned char res[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = { + { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, + { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, + 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, + 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd }, + { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a, + 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b, + 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5, + 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 } +}; + +int mbedtls_ccm_self_test( int verbose ) +{ + mbedtls_ccm_context ctx; + /* + * Some hardware accelerators require the input and output buffers + * would be in RAM, because the flash is not accessible. + * Use buffers on the stack to hold the test vectors data. + */ + unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN]; + unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN]; + size_t i; + int ret; + + mbedtls_ccm_init( &ctx ); + + if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " CCM: setup failed" ); + + return( 1 ); + } + + for( i = 0; i < NB_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 ); + + memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); + memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN ); + memcpy( plaintext, msg, msg_len[i] ); + + ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i], + iv, iv_len[i], ad, add_len[i], + plaintext, ciphertext, + ciphertext + msg_len[i], tag_len[i] ); + + if( ret != 0 || + memcmp( ciphertext, res[i], msg_len[i] + tag_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); + + ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i], + iv, iv_len[i], ad, add_len[i], + ciphertext, plaintext, + ciphertext + msg_len[i], tag_len[i] ); + + if( ret != 0 || + memcmp( plaintext, msg, msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + mbedtls_ccm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_CCM_C */ diff --git a/external/mbedtls/library/certs.c b/external/mbedtls/library/certs.c new file mode 100644 index 0000000..cb43f53 --- /dev/null +++ b/external/mbedtls/library/certs.c @@ -0,0 +1,1778 @@ +/* + * X.509 test certificates + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/certs.h" + +#if defined(MBEDTLS_CERTS_C) + +/* + * Test CA Certificates + * + * We define test CA certificates for each choice of the following parameters: + * - PEM or DER encoding + * - SHA-1 or SHA-256 hash + * - RSA or EC key + * + * Things to add: + * - multiple EC curve types + * + */ + +/* This is taken from tests/data_files/test-ca2.crt */ +/* BEGIN FILE string macro TEST_CA_CRT_EC_PEM tests/data_files/test-ca2.crt */ +#define TEST_CA_CRT_EC_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIICBDCCAYigAwIBAgIJAMFD4n5iQ8zoMAwGCCqGSM49BAMCBQAwPjELMAkGA1UE\r\n" \ + "BhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xhcnNzbCBUZXN0\r\n" \ + "IEVDIENBMB4XDTE5MDIxMDE0NDQwMFoXDTI5MDIxMDE0NDQwMFowPjELMAkGA1UE\r\n" \ + "BhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xhcnNzbCBUZXN0\r\n" \ + "IEVDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEw9orNEE3WC+HVv78ibopQ0tO\r\n" \ + "4G7DDldTMzlY1FK0kZU5CyPfXxckYkj8GpUpziwth8KIUoCv1mqrId240xxuWLjK\r\n" \ + "6LJpjvNBrSnDtF91p0dv1RkpVWmaUzsgtGYWYDMeo1AwTjAMBgNVHRMEBTADAQH/\r\n" \ + "MB0GA1UdDgQWBBSdbSAkSQE/K8t4tRm8fiTJ2/s2fDAfBgNVHSMEGDAWgBSdbSAk\r\n" \ + "SQE/K8t4tRm8fiTJ2/s2fDAMBggqhkjOPQQDAgUAA2gAMGUCMFHKrjAPpHB0BN1a\r\n" \ + "LH8TwcJ3vh0AxeKZj30mRdOKBmg/jLS3rU3g8VQBHpn8sOTTBwIxANxPO5AerimZ\r\n" \ + "hCjMe0d4CTHf1gFZMF70+IqEP+o5VHsIp2Cqvflb0VGWFC5l9a4cQg==\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/test-ca2.crt.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CA_CRT_EC_DER tests/data_files/test-ca2.crt.der */ +#define TEST_CA_CRT_EC_DER { \ + 0x30, 0x82, 0x02, 0x04, 0x30, 0x82, 0x01, 0x88, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x09, 0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, \ + 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, \ + 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, \ + 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, \ + 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x50, \ + 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, \ + 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, \ + 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x17, \ + 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, \ + 0x30, 0x5a, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, \ + 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, \ + 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x50, \ + 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, \ + 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, \ + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, \ + 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xc3, 0xda, 0x2b, 0x34, 0x41, 0x37, \ + 0x58, 0x2f, 0x87, 0x56, 0xfe, 0xfc, 0x89, 0xba, 0x29, 0x43, 0x4b, 0x4e, \ + 0xe0, 0x6e, 0xc3, 0x0e, 0x57, 0x53, 0x33, 0x39, 0x58, 0xd4, 0x52, 0xb4, \ + 0x91, 0x95, 0x39, 0x0b, 0x23, 0xdf, 0x5f, 0x17, 0x24, 0x62, 0x48, 0xfc, \ + 0x1a, 0x95, 0x29, 0xce, 0x2c, 0x2d, 0x87, 0xc2, 0x88, 0x52, 0x80, 0xaf, \ + 0xd6, 0x6a, 0xab, 0x21, 0xdd, 0xb8, 0xd3, 0x1c, 0x6e, 0x58, 0xb8, 0xca, \ + 0xe8, 0xb2, 0x69, 0x8e, 0xf3, 0x41, 0xad, 0x29, 0xc3, 0xb4, 0x5f, 0x75, \ + 0xa7, 0x47, 0x6f, 0xd5, 0x19, 0x29, 0x55, 0x69, 0x9a, 0x53, 0x3b, 0x20, \ + 0xb4, 0x66, 0x16, 0x60, 0x33, 0x1e, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x0c, \ + 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, \ + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9d, \ + 0x6d, 0x20, 0x24, 0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, \ + 0x7e, 0x24, 0xc9, 0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x1f, 0x06, 0x03, 0x55, \ + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, \ + 0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, \ + 0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ + 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, \ + 0x30, 0x51, 0xca, 0xae, 0x30, 0x0f, 0xa4, 0x70, 0x74, 0x04, 0xdd, 0x5a, \ + 0x2c, 0x7f, 0x13, 0xc1, 0xc2, 0x77, 0xbe, 0x1d, 0x00, 0xc5, 0xe2, 0x99, \ + 0x8f, 0x7d, 0x26, 0x45, 0xd3, 0x8a, 0x06, 0x68, 0x3f, 0x8c, 0xb4, 0xb7, \ + 0xad, 0x4d, 0xe0, 0xf1, 0x54, 0x01, 0x1e, 0x99, 0xfc, 0xb0, 0xe4, 0xd3, \ + 0x07, 0x02, 0x31, 0x00, 0xdc, 0x4f, 0x3b, 0x90, 0x1e, 0xae, 0x29, 0x99, \ + 0x84, 0x28, 0xcc, 0x7b, 0x47, 0x78, 0x09, 0x31, 0xdf, 0xd6, 0x01, 0x59, \ + 0x30, 0x5e, 0xf4, 0xf8, 0x8a, 0x84, 0x3f, 0xea, 0x39, 0x54, 0x7b, 0x08, \ + 0xa7, 0x60, 0xaa, 0xbd, 0xf9, 0x5b, 0xd1, 0x51, 0x96, 0x14, 0x2e, 0x65, \ + 0xf5, 0xae, 0x1c, 0x42 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/test-ca2.key.enc */ +/* BEGIN FILE string macro TEST_CA_KEY_EC_PEM tests/data_files/test-ca2.key.enc */ +#define TEST_CA_KEY_EC_PEM \ + "-----BEGIN EC PRIVATE KEY-----\r\n" \ + "Proc-Type: 4,ENCRYPTED\r\n" \ + "DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n" \ + "\r\n" \ + "IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n" \ + "ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n" \ + "UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n" \ + "a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n" \ + "-----END EC PRIVATE KEY-----\r\n" +/* END FILE */ + +#define TEST_CA_PWD_EC_PEM "PolarSSLTest" + +/* This is generated from tests/data_files/test-ca2.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CA_KEY_EC_DER tests/data_files/test-ca2.key.der */ +#define TEST_CA_KEY_EC_DER { \ + 0x30, 0x81, 0xa4, 0x02, 0x01, 0x01, 0x04, 0x30, 0x83, 0xd9, 0x15, 0x0e, \ + 0xa0, 0x71, 0xf0, 0x57, 0x10, 0x33, 0xa3, 0x38, 0xb8, 0x86, 0xc1, 0xa6, \ + 0x11, 0x5d, 0x6d, 0xb4, 0x03, 0xe1, 0x29, 0x76, 0x45, 0xd7, 0x87, 0x6f, \ + 0x23, 0xab, 0x44, 0x20, 0xea, 0x64, 0x7b, 0x85, 0xb1, 0x76, 0xe7, 0x85, \ + 0x95, 0xaa, 0x74, 0xd6, 0xd1, 0xa4, 0x5e, 0xea, 0xa0, 0x07, 0x06, 0x05, \ + 0x2b, 0x81, 0x04, 0x00, 0x22, 0xa1, 0x64, 0x03, 0x62, 0x00, 0x04, 0xc3, \ + 0xda, 0x2b, 0x34, 0x41, 0x37, 0x58, 0x2f, 0x87, 0x56, 0xfe, 0xfc, 0x89, \ + 0xba, 0x29, 0x43, 0x4b, 0x4e, 0xe0, 0x6e, 0xc3, 0x0e, 0x57, 0x53, 0x33, \ + 0x39, 0x58, 0xd4, 0x52, 0xb4, 0x91, 0x95, 0x39, 0x0b, 0x23, 0xdf, 0x5f, \ + 0x17, 0x24, 0x62, 0x48, 0xfc, 0x1a, 0x95, 0x29, 0xce, 0x2c, 0x2d, 0x87, \ + 0xc2, 0x88, 0x52, 0x80, 0xaf, 0xd6, 0x6a, 0xab, 0x21, 0xdd, 0xb8, 0xd3, \ + 0x1c, 0x6e, 0x58, 0xb8, 0xca, 0xe8, 0xb2, 0x69, 0x8e, 0xf3, 0x41, 0xad, \ + 0x29, 0xc3, 0xb4, 0x5f, 0x75, 0xa7, 0x47, 0x6f, 0xd5, 0x19, 0x29, 0x55, \ + 0x69, 0x9a, 0x53, 0x3b, 0x20, 0xb4, 0x66, 0x16, 0x60, 0x33, 0x1e \ +} +/* END FILE */ + +/* This is taken from tests/data_files/test-ca-sha256.crt. */ +/* BEGIN FILE string macro TEST_CA_CRT_RSA_SHA256_PEM tests/data_files/test-ca-sha256.crt */ +#define TEST_CA_CRT_RSA_SHA256_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ + "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ + "MTkwMjEwMTQ0NDAwWhcNMjkwMjEwMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ + "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ + "mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ + "50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ + "YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ + "R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ + "KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ + "UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n" \ + "MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBCwUA\r\n" \ + "A4IBAQA4qFSCth2q22uJIdE4KGHJsJjVEfw2/xn+MkTvCMfxVrvmRvqCtjE4tKDl\r\n" \ + "oK4MxFOek07oDZwvtAT9ijn1hHftTNS7RH9zd/fxNpfcHnMZXVC4w4DNA1fSANtW\r\n" \ + "5sY1JB5Je9jScrsLSS+mAjyv0Ow3Hb2Bix8wu7xNNrV5fIf7Ubm+wt6SqEBxu3Kb\r\n" \ + "+EfObAT4huf3czznhH3C17ed6NSbXwoXfby7stWUDeRJv08RaFOykf/Aae7bY5PL\r\n" \ + "yTVrkAnikMntJ9YI+hNNYt3inqq11A5cN0+rVTst8UKCxzQ4GpvroSwPKTFkbMw4\r\n" \ + "/anT1dVxr/BtwJfiESoK3/4CeXR1\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/test-ca-sha256.crt.der + * using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA256_DER tests/data_files/test-ca-sha256.crt.der */ +#define TEST_CA_CRT_RSA_SHA256_DER { \ + 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, \ + 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, \ + 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, \ + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, \ + 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, \ + 0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, \ + 0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, \ + 0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, \ + 0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, \ + 0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, \ + 0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, \ + 0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, \ + 0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, \ + 0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, \ + 0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, \ + 0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, \ + 0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, \ + 0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, \ + 0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, \ + 0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, \ + 0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, \ + 0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, \ + 0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, \ + 0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, \ + 0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, \ + 0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, \ + 0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, \ + 0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, \ + 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, \ + 0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, \ + 0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, \ + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, \ + 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, \ + 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, \ + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, \ + 0x03, 0x82, 0x01, 0x01, 0x00, 0x38, 0xa8, 0x54, 0x82, 0xb6, 0x1d, 0xaa, \ + 0xdb, 0x6b, 0x89, 0x21, 0xd1, 0x38, 0x28, 0x61, 0xc9, 0xb0, 0x98, 0xd5, \ + 0x11, 0xfc, 0x36, 0xff, 0x19, 0xfe, 0x32, 0x44, 0xef, 0x08, 0xc7, 0xf1, \ + 0x56, 0xbb, 0xe6, 0x46, 0xfa, 0x82, 0xb6, 0x31, 0x38, 0xb4, 0xa0, 0xe5, \ + 0xa0, 0xae, 0x0c, 0xc4, 0x53, 0x9e, 0x93, 0x4e, 0xe8, 0x0d, 0x9c, 0x2f, \ + 0xb4, 0x04, 0xfd, 0x8a, 0x39, 0xf5, 0x84, 0x77, 0xed, 0x4c, 0xd4, 0xbb, \ + 0x44, 0x7f, 0x73, 0x77, 0xf7, 0xf1, 0x36, 0x97, 0xdc, 0x1e, 0x73, 0x19, \ + 0x5d, 0x50, 0xb8, 0xc3, 0x80, 0xcd, 0x03, 0x57, 0xd2, 0x00, 0xdb, 0x56, \ + 0xe6, 0xc6, 0x35, 0x24, 0x1e, 0x49, 0x7b, 0xd8, 0xd2, 0x72, 0xbb, 0x0b, \ + 0x49, 0x2f, 0xa6, 0x02, 0x3c, 0xaf, 0xd0, 0xec, 0x37, 0x1d, 0xbd, 0x81, \ + 0x8b, 0x1f, 0x30, 0xbb, 0xbc, 0x4d, 0x36, 0xb5, 0x79, 0x7c, 0x87, 0xfb, \ + 0x51, 0xb9, 0xbe, 0xc2, 0xde, 0x92, 0xa8, 0x40, 0x71, 0xbb, 0x72, 0x9b, \ + 0xf8, 0x47, 0xce, 0x6c, 0x04, 0xf8, 0x86, 0xe7, 0xf7, 0x73, 0x3c, 0xe7, \ + 0x84, 0x7d, 0xc2, 0xd7, 0xb7, 0x9d, 0xe8, 0xd4, 0x9b, 0x5f, 0x0a, 0x17, \ + 0x7d, 0xbc, 0xbb, 0xb2, 0xd5, 0x94, 0x0d, 0xe4, 0x49, 0xbf, 0x4f, 0x11, \ + 0x68, 0x53, 0xb2, 0x91, 0xff, 0xc0, 0x69, 0xee, 0xdb, 0x63, 0x93, 0xcb, \ + 0xc9, 0x35, 0x6b, 0x90, 0x09, 0xe2, 0x90, 0xc9, 0xed, 0x27, 0xd6, 0x08, \ + 0xfa, 0x13, 0x4d, 0x62, 0xdd, 0xe2, 0x9e, 0xaa, 0xb5, 0xd4, 0x0e, 0x5c, \ + 0x37, 0x4f, 0xab, 0x55, 0x3b, 0x2d, 0xf1, 0x42, 0x82, 0xc7, 0x34, 0x38, \ + 0x1a, 0x9b, 0xeb, 0xa1, 0x2c, 0x0f, 0x29, 0x31, 0x64, 0x6c, 0xcc, 0x38, \ + 0xfd, 0xa9, 0xd3, 0xd5, 0xd5, 0x71, 0xaf, 0xf0, 0x6d, 0xc0, 0x97, 0xe2, \ + 0x11, 0x2a, 0x0a, 0xdf, 0xfe, 0x02, 0x79, 0x74, 0x75 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/test-ca-sha1.crt. */ +/* BEGIN FILE string macro TEST_CA_CRT_RSA_SHA1_PEM tests/data_files/test-ca-sha1.crt */ +#define TEST_CA_CRT_RSA_SHA1_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ + "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ + "MTkwMjEwMTQ0NDAwWhcNMjkwMjEwMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ + "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ + "mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ + "50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ + "YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ + "R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ + "KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ + "UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n" \ + "MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBBQUA\r\n" \ + "A4IBAQB0ZiNRFdia6kskaPnhrqejIRq8YMEGAf2oIPnyZ78xoyERgc35lHGyMtsL\r\n" \ + "hWicNjP4d/hS9As4j5KA2gdNGi5ETA1X7SowWOGsryivSpMSHVy1+HdfWlsYQOzm\r\n" \ + "8o+faQNUm8XzPVmttfAVspxeHSxJZ36Oo+QWZ5wZlCIEyjEdLUId+Tm4Bz3B5jRD\r\n" \ + "zZa/SaqDokq66N2zpbgKKAl3GU2O++fBqP2dSkdQykmTxhLLWRN8FJqhYATyQntZ\r\n" \ + "0QSi3W9HfSZPnFTcPIXeoiPd2pLlxt1hZu8dws2LTXE63uP6MM4LHvWxiuJaWkP/\r\n" \ + "mtxyUALj2pQxRitopORFQdn7AOY5\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is taken from tests/data_files/test-ca-sha1.crt.der. */ +/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA1_DER tests/data_files/test-ca-sha1.crt.der */ +#define TEST_CA_CRT_RSA_SHA1_DER { \ + 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, \ + 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, \ + 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, \ + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, \ + 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, \ + 0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, \ + 0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, \ + 0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, \ + 0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, \ + 0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, \ + 0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, \ + 0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, \ + 0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, \ + 0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, \ + 0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, \ + 0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, \ + 0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, \ + 0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, \ + 0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, \ + 0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, \ + 0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, \ + 0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, \ + 0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, \ + 0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, \ + 0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, \ + 0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, \ + 0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, \ + 0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, \ + 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, \ + 0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, \ + 0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, \ + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, \ + 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, \ + 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, \ + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, \ + 0x03, 0x82, 0x01, 0x01, 0x00, 0x74, 0x66, 0x23, 0x51, 0x15, 0xd8, 0x9a, \ + 0xea, 0x4b, 0x24, 0x68, 0xf9, 0xe1, 0xae, 0xa7, 0xa3, 0x21, 0x1a, 0xbc, \ + 0x60, 0xc1, 0x06, 0x01, 0xfd, 0xa8, 0x20, 0xf9, 0xf2, 0x67, 0xbf, 0x31, \ + 0xa3, 0x21, 0x11, 0x81, 0xcd, 0xf9, 0x94, 0x71, 0xb2, 0x32, 0xdb, 0x0b, \ + 0x85, 0x68, 0x9c, 0x36, 0x33, 0xf8, 0x77, 0xf8, 0x52, 0xf4, 0x0b, 0x38, \ + 0x8f, 0x92, 0x80, 0xda, 0x07, 0x4d, 0x1a, 0x2e, 0x44, 0x4c, 0x0d, 0x57, \ + 0xed, 0x2a, 0x30, 0x58, 0xe1, 0xac, 0xaf, 0x28, 0xaf, 0x4a, 0x93, 0x12, \ + 0x1d, 0x5c, 0xb5, 0xf8, 0x77, 0x5f, 0x5a, 0x5b, 0x18, 0x40, 0xec, 0xe6, \ + 0xf2, 0x8f, 0x9f, 0x69, 0x03, 0x54, 0x9b, 0xc5, 0xf3, 0x3d, 0x59, 0xad, \ + 0xb5, 0xf0, 0x15, 0xb2, 0x9c, 0x5e, 0x1d, 0x2c, 0x49, 0x67, 0x7e, 0x8e, \ + 0xa3, 0xe4, 0x16, 0x67, 0x9c, 0x19, 0x94, 0x22, 0x04, 0xca, 0x31, 0x1d, \ + 0x2d, 0x42, 0x1d, 0xf9, 0x39, 0xb8, 0x07, 0x3d, 0xc1, 0xe6, 0x34, 0x43, \ + 0xcd, 0x96, 0xbf, 0x49, 0xaa, 0x83, 0xa2, 0x4a, 0xba, 0xe8, 0xdd, 0xb3, \ + 0xa5, 0xb8, 0x0a, 0x28, 0x09, 0x77, 0x19, 0x4d, 0x8e, 0xfb, 0xe7, 0xc1, \ + 0xa8, 0xfd, 0x9d, 0x4a, 0x47, 0x50, 0xca, 0x49, 0x93, 0xc6, 0x12, 0xcb, \ + 0x59, 0x13, 0x7c, 0x14, 0x9a, 0xa1, 0x60, 0x04, 0xf2, 0x42, 0x7b, 0x59, \ + 0xd1, 0x04, 0xa2, 0xdd, 0x6f, 0x47, 0x7d, 0x26, 0x4f, 0x9c, 0x54, 0xdc, \ + 0x3c, 0x85, 0xde, 0xa2, 0x23, 0xdd, 0xda, 0x92, 0xe5, 0xc6, 0xdd, 0x61, \ + 0x66, 0xef, 0x1d, 0xc2, 0xcd, 0x8b, 0x4d, 0x71, 0x3a, 0xde, 0xe3, 0xfa, \ + 0x30, 0xce, 0x0b, 0x1e, 0xf5, 0xb1, 0x8a, 0xe2, 0x5a, 0x5a, 0x43, 0xff, \ + 0x9a, 0xdc, 0x72, 0x50, 0x02, 0xe3, 0xda, 0x94, 0x31, 0x46, 0x2b, 0x68, \ + 0xa4, 0xe4, 0x45, 0x41, 0xd9, 0xfb, 0x00, 0xe6, 0x39 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/test-ca.key */ +/* BEGIN FILE string macro TEST_CA_KEY_RSA_PEM tests/data_files/test-ca.key */ +#define TEST_CA_KEY_RSA_PEM \ + "-----BEGIN RSA PRIVATE KEY-----\r\n" \ + "Proc-Type: 4,ENCRYPTED\r\n" \ + "DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n" \ + "\r\n" \ + "9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n" \ + "7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n" \ + "Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n" \ + "PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n" \ + "GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n" \ + "gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n" \ + "QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n" \ + "PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n" \ + "vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n" \ + "WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n" \ + "JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n" \ + "KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n" \ + "Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n" \ + "9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n" \ + "iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n" \ + "tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n" \ + "P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n" \ + "1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n" \ + "nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n" \ + "X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n" \ + "rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n" \ + "L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n" \ + "I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n" \ + "wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n" \ + "P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n" \ + "-----END RSA PRIVATE KEY-----\r\n" +/* END FILE */ + +#define TEST_CA_PWD_RSA_PEM "PolarSSLTest" + +/* This was generated from test-ca.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CA_KEY_RSA_DER tests/data_files/test-ca.key.der */ +#define TEST_CA_KEY_RSA_DER { \ + 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ + 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, 0x86, 0xde, \ + 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, 0x99, 0xd4, \ + 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, 0x9b, 0xc5, \ + 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, 0xc0, 0x8d, \ + 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, 0x93, 0xe8, \ + 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, 0xe7, 0x40, \ + 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, 0xf9, 0x3e, \ + 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, 0x29, 0x00, \ + 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, 0xbd, 0x83, \ + 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, 0x60, 0xc3, \ + 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, 0x32, 0xbe, \ + 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, 0xfb, 0xf5, \ + 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, 0xee, 0xe2, \ + 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, 0x47, 0xb1, \ + 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, 0xf1, 0x79, \ + 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, 0x6f, 0x27, \ + 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, 0xa1, 0x30, \ + 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, 0x28, 0xd1, \ + 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, 0x09, 0xea, \ + 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, 0xc9, 0xab, \ + 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, 0x9e, 0x99, \ + 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ + 0x00, 0x3f, 0xf7, 0x07, 0xd3, 0x34, 0x6f, 0xdb, 0xc9, 0x37, 0xb7, 0x84, \ + 0xdc, 0x37, 0x45, 0xe1, 0x63, 0xad, 0xb8, 0xb6, 0x75, 0xb1, 0xc7, 0x35, \ + 0xb4, 0x77, 0x2a, 0x5b, 0x77, 0xf9, 0x7e, 0xe0, 0xc1, 0xa3, 0xd1, 0xb7, \ + 0xcb, 0xa9, 0x5a, 0xc1, 0x87, 0xda, 0x5a, 0xfa, 0x17, 0xe4, 0xd5, 0x38, \ + 0x03, 0xde, 0x68, 0x98, 0x81, 0xec, 0xb5, 0xf2, 0x2a, 0x8d, 0xe9, 0x2c, \ + 0xf3, 0xa6, 0xe5, 0x32, 0x17, 0x7f, 0x33, 0x81, 0xe8, 0x38, 0x72, 0xd5, \ + 0x9c, 0xfa, 0x4e, 0xfb, 0x26, 0xf5, 0x15, 0x0b, 0xaf, 0x84, 0x66, 0xab, \ + 0x02, 0xe0, 0x18, 0xd5, 0x91, 0x7c, 0xd6, 0x8f, 0xc9, 0x4b, 0x76, 0x08, \ + 0x2b, 0x1d, 0x81, 0x68, 0x30, 0xe1, 0xfa, 0x70, 0x6c, 0x13, 0x4e, 0x10, \ + 0x03, 0x35, 0x3e, 0xc5, 0xca, 0x58, 0x20, 0x8a, 0x21, 0x18, 0x38, 0xa0, \ + 0x0f, 0xed, 0xc4, 0xbb, 0x45, 0x6f, 0xf5, 0x84, 0x5b, 0xb0, 0xcf, 0x4e, \ + 0x9d, 0x58, 0x13, 0x6b, 0x35, 0x35, 0x69, 0xa1, 0xd2, 0xc4, 0xf2, 0xc1, \ + 0x48, 0x04, 0x20, 0x51, 0xb9, 0x6b, 0xa4, 0x5d, 0xa5, 0x4b, 0x84, 0x88, \ + 0x43, 0x48, 0x99, 0x2c, 0xbb, 0xa4, 0x97, 0xd6, 0xd6, 0x18, 0xf6, 0xec, \ + 0x5c, 0xd1, 0x31, 0x49, 0xc9, 0xf2, 0x8f, 0x0b, 0x4d, 0xef, 0x09, 0x02, \ + 0xfe, 0x7d, 0xfd, 0xbb, 0xaf, 0x2b, 0x83, 0x94, 0x22, 0xc4, 0xa7, 0x3e, \ + 0x66, 0xf5, 0xe0, 0x57, 0xdc, 0xf2, 0xed, 0x2c, 0x3e, 0x81, 0x74, 0x76, \ + 0x1e, 0x96, 0x6f, 0x74, 0x1e, 0x32, 0x0e, 0x14, 0x31, 0xd0, 0x74, 0xf0, \ + 0xf4, 0x07, 0xbd, 0xc3, 0xd1, 0x22, 0xc2, 0xa8, 0x95, 0x92, 0x06, 0x7f, \ + 0x43, 0x02, 0x91, 0xbc, 0xdd, 0x23, 0x01, 0x89, 0x94, 0x20, 0x44, 0x64, \ + 0xf5, 0x1d, 0x67, 0xd2, 0x8f, 0xe8, 0x69, 0xa5, 0x29, 0x25, 0xe6, 0x50, \ + 0x9c, 0xe3, 0xe9, 0xcb, 0x75, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x29, 0x3e, \ + 0xaa, 0x6b, 0xd5, 0x59, 0x1e, 0x9c, 0xe6, 0x47, 0xd5, 0xb6, 0xd7, 0xe3, \ + 0xf1, 0x8e, 0x9e, 0xe9, 0x83, 0x5f, 0x10, 0x9f, 0x63, 0xec, 0x04, 0x44, \ + 0xcc, 0x3f, 0xf8, 0xd9, 0x3a, 0x17, 0xe0, 0x4f, 0xfe, 0xd8, 0x4d, 0xcd, \ + 0x46, 0x54, 0x74, 0xbf, 0x0a, 0xc4, 0x67, 0x9c, 0xa7, 0xd8, 0x89, 0x65, \ + 0x4c, 0xfd, 0x58, 0x2a, 0x47, 0x0f, 0xf4, 0x37, 0xb6, 0x55, 0xb0, 0x1d, \ + 0xed, 0xa7, 0x39, 0xfc, 0x4f, 0xa3, 0xc4, 0x75, 0x3a, 0xa3, 0x98, 0xa7, \ + 0x45, 0xf5, 0x66, 0xcb, 0x7c, 0x65, 0xfb, 0x80, 0x23, 0xe6, 0xff, 0xfd, \ + 0x99, 0x1f, 0x8e, 0x6b, 0xff, 0x5e, 0x93, 0x66, 0xdf, 0x6c, 0x6f, 0xc3, \ + 0xf6, 0x38, 0x2e, 0xff, 0x69, 0xb5, 0xac, 0xae, 0xbb, 0xc6, 0x71, 0x16, \ + 0x6b, 0xd0, 0xf8, 0x22, 0xd9, 0xf8, 0xa2, 0x72, 0x20, 0xd2, 0xe2, 0x3a, \ + 0x70, 0x4b, 0xde, 0xab, 0x2f, 0x02, 0x81, 0x81, 0x00, 0xda, 0x51, 0x9b, \ + 0xb8, 0xb2, 0x2a, 0x14, 0x75, 0x58, 0x40, 0x8d, 0x27, 0x70, 0xfa, 0x31, \ + 0x48, 0xb0, 0x20, 0x21, 0x34, 0xfa, 0x4c, 0x57, 0xa8, 0x11, 0x88, 0xf3, \ + 0xa7, 0xae, 0x21, 0xe9, 0xb6, 0x2b, 0xd1, 0xcd, 0xa7, 0xf8, 0xd8, 0x0c, \ + 0x8a, 0x76, 0x22, 0x35, 0x44, 0xce, 0x3f, 0x25, 0x29, 0x83, 0x7d, 0x79, \ + 0xa7, 0x31, 0xd6, 0xec, 0xb2, 0xbf, 0xda, 0x34, 0xb6, 0xf6, 0xb2, 0x3b, \ + 0xf3, 0x78, 0x5a, 0x04, 0x83, 0x33, 0x3e, 0xa2, 0xe2, 0x81, 0x82, 0x13, \ + 0xd4, 0x35, 0x17, 0x63, 0x9b, 0x9e, 0xc4, 0x8d, 0x91, 0x4c, 0x03, 0x77, \ + 0xc7, 0x71, 0x5b, 0xee, 0x83, 0x6d, 0xd5, 0x78, 0x88, 0xf6, 0x2c, 0x79, \ + 0xc2, 0x4a, 0xb4, 0x79, 0x90, 0x70, 0xbf, 0xdf, 0x34, 0x56, 0x96, 0x71, \ + 0xe3, 0x0e, 0x68, 0x91, 0xbc, 0xea, 0xcb, 0x33, 0xc0, 0xbe, 0x45, 0xd7, \ + 0xfc, 0x30, 0xfd, 0x01, 0x3b, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x9f, 0x2a, \ + 0xb7, 0x38, 0x19, 0xc7, 0x17, 0x95, 0x73, 0x78, 0xae, 0xf5, 0xcb, 0x75, \ + 0x83, 0x7f, 0x19, 0x4b, 0xcb, 0x86, 0xfb, 0x4a, 0x15, 0x9a, 0xb6, 0x17, \ + 0x04, 0x49, 0x07, 0x8d, 0xf6, 0x66, 0x4a, 0x06, 0xf6, 0x05, 0xa7, 0xdf, \ + 0x66, 0x82, 0x3c, 0xff, 0xb6, 0x1d, 0x57, 0x89, 0x33, 0x5f, 0x9c, 0x05, \ + 0x75, 0x7f, 0xf3, 0x5d, 0xdc, 0x34, 0x65, 0x72, 0x85, 0x22, 0xa4, 0x14, \ + 0x1b, 0x41, 0xc3, 0xe4, 0xd0, 0x9e, 0x69, 0xd5, 0xeb, 0x38, 0x74, 0x70, \ + 0x43, 0xdc, 0xd9, 0x50, 0xe4, 0x97, 0x6d, 0x73, 0xd6, 0xfb, 0xc8, 0xa7, \ + 0xfa, 0xb4, 0xc2, 0xc4, 0x9d, 0x5d, 0x0c, 0xd5, 0x9f, 0x79, 0xb3, 0x54, \ + 0xc2, 0xb7, 0x6c, 0x3d, 0x7d, 0xcb, 0x2d, 0xf8, 0xc4, 0xf3, 0x78, 0x5a, \ + 0x33, 0x2a, 0xb8, 0x0c, 0x6d, 0x06, 0xfa, 0xf2, 0x62, 0xd3, 0x42, 0xd0, \ + 0xbd, 0xc8, 0x4a, 0xa5, 0x0d, 0x02, 0x81, 0x81, 0x00, 0xd4, 0xa9, 0x90, \ + 0x15, 0xde, 0xbf, 0x2c, 0xc4, 0x8d, 0x9d, 0xfb, 0xa1, 0xc2, 0xe4, 0x83, \ + 0xe3, 0x79, 0x65, 0x22, 0xd3, 0xb7, 0x49, 0x6c, 0x4d, 0x94, 0x1f, 0x22, \ + 0xb1, 0x60, 0xe7, 0x3a, 0x00, 0xb1, 0x38, 0xa2, 0xab, 0x0f, 0xb4, 0x6c, \ + 0xaa, 0xe7, 0x9e, 0x34, 0xe3, 0x7c, 0x40, 0x78, 0x53, 0xb2, 0xf9, 0x23, \ + 0xea, 0xa0, 0x9a, 0xea, 0x60, 0xc8, 0x8f, 0xa6, 0xaf, 0xdf, 0x29, 0x09, \ + 0x4b, 0x06, 0x1e, 0x31, 0xad, 0x17, 0xda, 0xd8, 0xd1, 0xe9, 0x33, 0xab, \ + 0x5b, 0x18, 0x08, 0x5b, 0x87, 0xf8, 0xa5, 0x1f, 0xfd, 0xbb, 0xdc, 0xd8, \ + 0xed, 0x97, 0x57, 0xe4, 0xc3, 0x73, 0xd6, 0xf0, 0x9e, 0x01, 0xa6, 0x9b, \ + 0x48, 0x8e, 0x7a, 0xb4, 0xbb, 0xe5, 0x88, 0x91, 0xc5, 0x2a, 0xdf, 0x4b, \ + 0xba, 0xd0, 0x8b, 0x3e, 0x03, 0x97, 0x77, 0x2f, 0x47, 0x7e, 0x51, 0x0c, \ + 0xae, 0x65, 0x8d, 0xde, 0x87, 0x02, 0x81, 0x80, 0x20, 0x24, 0x0f, 0xd2, \ + 0xaf, 0xc2, 0x28, 0x3b, 0x97, 0x20, 0xb2, 0x92, 0x49, 0xeb, 0x09, 0x68, \ + 0x40, 0xb2, 0xbe, 0xd1, 0xc3, 0x83, 0x94, 0x34, 0x38, 0xd6, 0xc9, 0xec, \ + 0x34, 0x09, 0xf9, 0x41, 0x6d, 0x5c, 0x42, 0x94, 0xf7, 0x04, 0xfc, 0x32, \ + 0x39, 0x69, 0xbc, 0x1c, 0xfb, 0x3e, 0x61, 0x98, 0xc0, 0x80, 0xd8, 0x36, \ + 0x47, 0xc3, 0x6d, 0xc2, 0x2e, 0xe7, 0x81, 0x2a, 0x17, 0x34, 0x64, 0x30, \ + 0x4e, 0x96, 0xbb, 0x26, 0x16, 0xb9, 0x41, 0x36, 0xfe, 0x8a, 0xd6, 0x53, \ + 0x7c, 0xaa, 0xec, 0x39, 0x42, 0x50, 0xef, 0xe3, 0xb3, 0x01, 0x28, 0x32, \ + 0xca, 0x6d, 0xf5, 0x9a, 0x1e, 0x9f, 0x37, 0xbe, 0xfe, 0x38, 0x20, 0x22, \ + 0x91, 0x8c, 0xcd, 0x95, 0x02, 0xf2, 0x4d, 0x6f, 0x1a, 0xb4, 0x43, 0xf0, \ + 0x19, 0xdf, 0x65, 0xc0, 0x92, 0xe7, 0x9d, 0x2f, 0x09, 0xe7, 0xec, 0x69, \ + 0xa8, 0xc2, 0x8f, 0x0d \ +} +/* END FILE */ + +/* + * Test server Certificates + * + * Test server certificates are defined for each choice + * of the following parameters: + * - PEM or DER encoding + * - SHA-1 or SHA-256 hash + * - RSA or EC key + * + * Things to add: + * - multiple EC curve types + */ + +/* This is taken from tests/data_files/server5.crt. */ +/* BEGIN FILE string macro TEST_SRV_CRT_EC_PEM tests/data_files/server5.crt */ +#define TEST_SRV_CRT_EC_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" \ + "MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n" \ + "CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n" \ + "2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n" \ + "BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n" \ + "PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh\r\n" \ + "clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n" \ + "CCqGSM49BAMCA2gAMGUCMQCaLFzXptui5WQN8LlO3ddh1hMxx6tzgLvT03MTVK2S\r\n" \ + "C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n" \ + "fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/server5.crt.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_SRV_CRT_EC_DER tests/data_files/server5.crt.der */ +#define TEST_SRV_CRT_EC_DER { \ + 0x30, 0x82, 0x02, 0x1f, 0x30, 0x82, 0x01, 0xa5, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x09, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, \ + 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, \ + 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x33, 0x30, 0x39, 0x32, 0x34, 0x31, 0x35, 0x35, 0x32, 0x30, 0x34, \ + 0x5a, 0x17, 0x0d, 0x32, 0x33, 0x30, 0x39, 0x32, 0x32, 0x31, 0x35, 0x35, \ + 0x32, 0x30, 0x34, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, \ + 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x59, \ + 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, \ + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, \ + 0x04, 0x37, 0xcc, 0x56, 0xd9, 0x76, 0x09, 0x1e, 0x5a, 0x72, 0x3e, 0xc7, \ + 0x59, 0x2d, 0xff, 0x20, 0x6e, 0xee, 0x7c, 0xf9, 0x06, 0x91, 0x74, 0xd0, \ + 0xad, 0x14, 0xb5, 0xf7, 0x68, 0x22, 0x59, 0x62, 0x92, 0x4e, 0xe5, 0x00, \ + 0xd8, 0x23, 0x11, 0xff, 0xea, 0x2f, 0xd2, 0x34, 0x5d, 0x5d, 0x16, 0xbd, \ + 0x8a, 0x88, 0xc2, 0x6b, 0x77, 0x0d, 0x55, 0xcd, 0x8a, 0x2a, 0x0e, 0xfa, \ + 0x01, 0xc8, 0xb4, 0xed, 0xff, 0xa3, 0x81, 0x9d, 0x30, 0x81, 0x9a, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, \ + 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x50, 0x61, 0xa5, \ + 0x8f, 0xd4, 0x07, 0xd9, 0xd7, 0x82, 0x01, 0x0c, 0xe5, 0x65, 0x7f, 0x8c, \ + 0x63, 0x46, 0xa7, 0x13, 0xbe, 0x30, 0x6e, 0x06, 0x03, 0x55, 0x1d, 0x23, \ + 0x04, 0x67, 0x30, 0x65, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, 0x01, \ + 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, 0xfb, \ + 0x36, 0x7c, 0xa1, 0x42, 0xa4, 0x40, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, \ + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ + 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, \ + 0x03, 0x13, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, \ + 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x82, 0x09, \ + 0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, 0x30, 0x0a, 0x06, \ + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x68, 0x00, \ + 0x30, 0x65, 0x02, 0x31, 0x00, 0x9a, 0x2c, 0x5c, 0xd7, 0xa6, 0xdb, 0xa2, \ + 0xe5, 0x64, 0x0d, 0xf0, 0xb9, 0x4e, 0xdd, 0xd7, 0x61, 0xd6, 0x13, 0x31, \ + 0xc7, 0xab, 0x73, 0x80, 0xbb, 0xd3, 0xd3, 0x73, 0x13, 0x54, 0xad, 0x92, \ + 0x0b, 0x5d, 0xab, 0xd0, 0xbc, 0xf7, 0xae, 0x2f, 0xe6, 0xa1, 0x21, 0x29, \ + 0x35, 0x95, 0xaa, 0x3e, 0x39, 0x02, 0x30, 0x21, 0x36, 0x7f, 0x9d, 0xc6, \ + 0x5d, 0xc6, 0x0b, 0xab, 0x27, 0xf2, 0x25, 0x1d, 0x3b, 0xf1, 0xcf, 0xf1, \ + 0x35, 0x25, 0x14, 0xe7, 0xe5, 0xf1, 0x97, 0xb5, 0x59, 0xe3, 0x5e, 0x15, \ + 0x7c, 0x66, 0xb9, 0x90, 0x7b, 0xc7, 0x01, 0x10, 0x4f, 0x73, 0xc6, 0x00, \ + 0x21, 0x52, 0x2a, 0x0e, 0xf1, 0xc7, 0xd5 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/server5.key. */ +/* BEGIN FILE string macro TEST_SRV_KEY_EC_PEM tests/data_files/server5.key */ +#define TEST_SRV_KEY_EC_PEM \ + "-----BEGIN EC PRIVATE KEY-----\r\n" \ + "MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n" \ + "AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n" \ + "6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n" \ + "-----END EC PRIVATE KEY-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/server5.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_SRV_KEY_EC_DER tests/data_files/server5.key.der */ +#define TEST_SRV_KEY_EC_DER { \ + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf1, 0x2a, 0x13, 0x20, 0x76, \ + 0x02, 0x70, 0xa8, 0x3c, 0xbf, 0xfd, 0x53, 0xf6, 0x03, 0x1e, 0xf7, 0x6a, \ + 0x5d, 0x86, 0xc8, 0xa2, 0x04, 0xf2, 0xc3, 0x0c, 0xa9, 0xeb, 0xf5, 0x1f, \ + 0x0f, 0x0e, 0xa7, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ + 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x37, 0xcc, 0x56, \ + 0xd9, 0x76, 0x09, 0x1e, 0x5a, 0x72, 0x3e, 0xc7, 0x59, 0x2d, 0xff, 0x20, \ + 0x6e, 0xee, 0x7c, 0xf9, 0x06, 0x91, 0x74, 0xd0, 0xad, 0x14, 0xb5, 0xf7, \ + 0x68, 0x22, 0x59, 0x62, 0x92, 0x4e, 0xe5, 0x00, 0xd8, 0x23, 0x11, 0xff, \ + 0xea, 0x2f, 0xd2, 0x34, 0x5d, 0x5d, 0x16, 0xbd, 0x8a, 0x88, 0xc2, 0x6b, \ + 0x77, 0x0d, 0x55, 0xcd, 0x8a, 0x2a, 0x0e, 0xfa, 0x01, 0xc8, 0xb4, 0xed, \ + 0xff \ +} +/* END FILE */ + +/* This is taken from tests/data_files/server2-sha256.crt. */ +/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA256_PEM tests/data_files/server2-sha256.crt */ +#define TEST_SRV_CRT_RSA_SHA256_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ + "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ + "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" \ + "AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" \ + "owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" \ + "NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" \ + "tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" \ + "hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" \ + "HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" \ + "VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" \ + "FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQELBQADggEBAC465FJh\r\n" \ + "Pqel7zJngHIHJrqj/wVAxGAFOTF396XKATGAp+HRCqJ81Ry60CNK1jDzk8dv6M6U\r\n" \ + "HoS7RIFiM/9rXQCbJfiPD5xMTejZp5n5UYHAmxsxDaazfA5FuBhkfokKK6jD4Eq9\r\n" \ + "1C94xGKb6X4/VkaPF7cqoBBw/bHxawXc0UEPjqayiBpCYU/rJoVZgLqFVP7Px3sv\r\n" \ + "a1nOrNx8rPPI1hJ+ZOg8maiPTxHZnBVLakSSLQy/sWeWyazO1RnrbxjrbgQtYKz0\r\n" \ + "e3nwGpu1w13vfckFmUSBhHXH7AAS/HpKC4IH7G2GAk3+n8iSSN71sZzpxonQwVbo\r\n" \ + "pMZqLmbBm/7WPLc=\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is taken from tests/data_files/server2-sha256.crt.der. */ +/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA256_DER tests/data_files/server2-sha256.crt.der */ +#define TEST_SRV_CRT_RSA_SHA256_DER { \ + 0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ + 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, \ + 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, \ + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, \ + 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, \ + 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78, \ + 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd, \ + 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90, \ + 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24, \ + 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda, \ + 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3, \ + 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4, \ + 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d, \ + 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49, \ + 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c, \ + 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b, \ + 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08, \ + 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa, \ + 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f, \ + 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7, \ + 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5, \ + 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde, \ + 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a, \ + 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96, \ + 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0, \ + 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02, \ + 0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, \ + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc, \ + 0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b, \ + 0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, \ + 0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, \ + 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, \ + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, \ + 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x2e, 0x3a, 0xe4, 0x52, 0x61, \ + 0x3e, 0xa7, 0xa5, 0xef, 0x32, 0x67, 0x80, 0x72, 0x07, 0x26, 0xba, 0xa3, \ + 0xff, 0x05, 0x40, 0xc4, 0x60, 0x05, 0x39, 0x31, 0x77, 0xf7, 0xa5, 0xca, \ + 0x01, 0x31, 0x80, 0xa7, 0xe1, 0xd1, 0x0a, 0xa2, 0x7c, 0xd5, 0x1c, 0xba, \ + 0xd0, 0x23, 0x4a, 0xd6, 0x30, 0xf3, 0x93, 0xc7, 0x6f, 0xe8, 0xce, 0x94, \ + 0x1e, 0x84, 0xbb, 0x44, 0x81, 0x62, 0x33, 0xff, 0x6b, 0x5d, 0x00, 0x9b, \ + 0x25, 0xf8, 0x8f, 0x0f, 0x9c, 0x4c, 0x4d, 0xe8, 0xd9, 0xa7, 0x99, 0xf9, \ + 0x51, 0x81, 0xc0, 0x9b, 0x1b, 0x31, 0x0d, 0xa6, 0xb3, 0x7c, 0x0e, 0x45, \ + 0xb8, 0x18, 0x64, 0x7e, 0x89, 0x0a, 0x2b, 0xa8, 0xc3, 0xe0, 0x4a, 0xbd, \ + 0xd4, 0x2f, 0x78, 0xc4, 0x62, 0x9b, 0xe9, 0x7e, 0x3f, 0x56, 0x46, 0x8f, \ + 0x17, 0xb7, 0x2a, 0xa0, 0x10, 0x70, 0xfd, 0xb1, 0xf1, 0x6b, 0x05, 0xdc, \ + 0xd1, 0x41, 0x0f, 0x8e, 0xa6, 0xb2, 0x88, 0x1a, 0x42, 0x61, 0x4f, 0xeb, \ + 0x26, 0x85, 0x59, 0x80, 0xba, 0x85, 0x54, 0xfe, 0xcf, 0xc7, 0x7b, 0x2f, \ + 0x6b, 0x59, 0xce, 0xac, 0xdc, 0x7c, 0xac, 0xf3, 0xc8, 0xd6, 0x12, 0x7e, \ + 0x64, 0xe8, 0x3c, 0x99, 0xa8, 0x8f, 0x4f, 0x11, 0xd9, 0x9c, 0x15, 0x4b, \ + 0x6a, 0x44, 0x92, 0x2d, 0x0c, 0xbf, 0xb1, 0x67, 0x96, 0xc9, 0xac, 0xce, \ + 0xd5, 0x19, 0xeb, 0x6f, 0x18, 0xeb, 0x6e, 0x04, 0x2d, 0x60, 0xac, 0xf4, \ + 0x7b, 0x79, 0xf0, 0x1a, 0x9b, 0xb5, 0xc3, 0x5d, 0xef, 0x7d, 0xc9, 0x05, \ + 0x99, 0x44, 0x81, 0x84, 0x75, 0xc7, 0xec, 0x00, 0x12, 0xfc, 0x7a, 0x4a, \ + 0x0b, 0x82, 0x07, 0xec, 0x6d, 0x86, 0x02, 0x4d, 0xfe, 0x9f, 0xc8, 0x92, \ + 0x48, 0xde, 0xf5, 0xb1, 0x9c, 0xe9, 0xc6, 0x89, 0xd0, 0xc1, 0x56, 0xe8, \ + 0xa4, 0xc6, 0x6a, 0x2e, 0x66, 0xc1, 0x9b, 0xfe, 0xd6, 0x3c, 0xb7 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/server2.crt. */ +/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA1_PEM tests/data_files/server2.crt */ +#define TEST_SRV_CRT_RSA_SHA1_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ + "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ + "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" \ + "AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" \ + "owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" \ + "NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" \ + "tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" \ + "hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" \ + "HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" \ + "VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" \ + "FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJklg3Q4\r\n" \ + "cB7v7BzsxM/vLyKccO6op0/gZzM4ghuLq2Y32kl0sM6kSNUUmduuq3u/+GmUZN2A\r\n" \ + "O/7c+Hw7hDFEIvZk98aBGjCLqn3DmgHIv8ToQ67nellQxx2Uj309PdgjNi/r9HOc\r\n" \ + "KNAYPbBcg6MJGWWj2TI6vNaceios/DhOYx5V0j5nfqSJ/pnU0g9Ign2LAhgYpGJE\r\n" \ + "iEM9wW7hEMkwmk0h/sqZsrJsGH5YsF/VThSq/JVO1e2mZH2vruyZKJVBq+8tDNYp\r\n" \ + "HkK6tSyVYQhzIt3StMJWKMl/o5k2AYz6tSC164+1oG+ML3LWg8XrGKa91H4UOKap\r\n" \ + "Awgk0+4m0T25cNs=\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is taken from tests/data_files/server2.crt.der. */ +/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA1_DER tests/data_files/server2.crt.der */ +#define TEST_SRV_CRT_RSA_SHA1_DER { \ + 0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ + 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, \ + 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, \ + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, \ + 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, \ + 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78, \ + 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd, \ + 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90, \ + 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24, \ + 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda, \ + 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3, \ + 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4, \ + 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d, \ + 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49, \ + 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c, \ + 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b, \ + 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08, \ + 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa, \ + 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f, \ + 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7, \ + 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5, \ + 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde, \ + 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a, \ + 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96, \ + 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0, \ + 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02, \ + 0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, \ + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc, \ + 0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b, \ + 0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, \ + 0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, \ + 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, \ + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, \ + 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x99, 0x25, 0x83, 0x74, 0x38, \ + 0x70, 0x1e, 0xef, 0xec, 0x1c, 0xec, 0xc4, 0xcf, 0xef, 0x2f, 0x22, 0x9c, \ + 0x70, 0xee, 0xa8, 0xa7, 0x4f, 0xe0, 0x67, 0x33, 0x38, 0x82, 0x1b, 0x8b, \ + 0xab, 0x66, 0x37, 0xda, 0x49, 0x74, 0xb0, 0xce, 0xa4, 0x48, 0xd5, 0x14, \ + 0x99, 0xdb, 0xae, 0xab, 0x7b, 0xbf, 0xf8, 0x69, 0x94, 0x64, 0xdd, 0x80, \ + 0x3b, 0xfe, 0xdc, 0xf8, 0x7c, 0x3b, 0x84, 0x31, 0x44, 0x22, 0xf6, 0x64, \ + 0xf7, 0xc6, 0x81, 0x1a, 0x30, 0x8b, 0xaa, 0x7d, 0xc3, 0x9a, 0x01, 0xc8, \ + 0xbf, 0xc4, 0xe8, 0x43, 0xae, 0xe7, 0x7a, 0x59, 0x50, 0xc7, 0x1d, 0x94, \ + 0x8f, 0x7d, 0x3d, 0x3d, 0xd8, 0x23, 0x36, 0x2f, 0xeb, 0xf4, 0x73, 0x9c, \ + 0x28, 0xd0, 0x18, 0x3d, 0xb0, 0x5c, 0x83, 0xa3, 0x09, 0x19, 0x65, 0xa3, \ + 0xd9, 0x32, 0x3a, 0xbc, 0xd6, 0x9c, 0x7a, 0x2a, 0x2c, 0xfc, 0x38, 0x4e, \ + 0x63, 0x1e, 0x55, 0xd2, 0x3e, 0x67, 0x7e, 0xa4, 0x89, 0xfe, 0x99, 0xd4, \ + 0xd2, 0x0f, 0x48, 0x82, 0x7d, 0x8b, 0x02, 0x18, 0x18, 0xa4, 0x62, 0x44, \ + 0x88, 0x43, 0x3d, 0xc1, 0x6e, 0xe1, 0x10, 0xc9, 0x30, 0x9a, 0x4d, 0x21, \ + 0xfe, 0xca, 0x99, 0xb2, 0xb2, 0x6c, 0x18, 0x7e, 0x58, 0xb0, 0x5f, 0xd5, \ + 0x4e, 0x14, 0xaa, 0xfc, 0x95, 0x4e, 0xd5, 0xed, 0xa6, 0x64, 0x7d, 0xaf, \ + 0xae, 0xec, 0x99, 0x28, 0x95, 0x41, 0xab, 0xef, 0x2d, 0x0c, 0xd6, 0x29, \ + 0x1e, 0x42, 0xba, 0xb5, 0x2c, 0x95, 0x61, 0x08, 0x73, 0x22, 0xdd, 0xd2, \ + 0xb4, 0xc2, 0x56, 0x28, 0xc9, 0x7f, 0xa3, 0x99, 0x36, 0x01, 0x8c, 0xfa, \ + 0xb5, 0x20, 0xb5, 0xeb, 0x8f, 0xb5, 0xa0, 0x6f, 0x8c, 0x2f, 0x72, 0xd6, \ + 0x83, 0xc5, 0xeb, 0x18, 0xa6, 0xbd, 0xd4, 0x7e, 0x14, 0x38, 0xa6, 0xa9, \ + 0x03, 0x08, 0x24, 0xd3, 0xee, 0x26, 0xd1, 0x3d, 0xb9, 0x70, 0xdb \ +} +/* END FILE */ + +/* This is taken from tests/data_files/server2.key. */ +/* BEGIN FILE string macro TEST_SRV_KEY_RSA_PEM tests/data_files/server2.key */ +#define TEST_SRV_KEY_RSA_PEM \ + "-----BEGIN RSA PRIVATE KEY-----\r\n" \ + "MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" \ + "lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n" \ + "2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n" \ + "Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n" \ + "GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n" \ + "y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n" \ + "++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n" \ + "Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n" \ + "/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n" \ + "WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n" \ + "GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n" \ + "TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n" \ + "CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" \ + "nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" \ + "AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" \ + "sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" \ + "mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" \ + "BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" \ + "whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" \ + "vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" \ + "3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" \ + "3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" \ + "ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" \ + "4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" \ + "TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" \ + "-----END RSA PRIVATE KEY-----\r\n" +/* END FILE */ + +/* This was generated from tests/data_files/server2.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_SRV_KEY_RSA_DER tests/data_files/server2.key.der */ +#define TEST_SRV_KEY_RSA_DER { \ + 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ + 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, \ + 0xb8, 0x99, 0xac, 0x0e, 0x78, 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, \ + 0x16, 0xd0, 0x5a, 0xe4, 0xcd, 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, \ + 0x96, 0xa7, 0x52, 0xb4, 0x90, 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, \ + 0xfc, 0xb6, 0x34, 0xac, 0x24, 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, \ + 0xb0, 0x28, 0x7d, 0xa1, 0xda, 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, \ + 0xfe, 0xc1, 0x04, 0x52, 0xb3, 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, \ + 0xd8, 0x90, 0xc1, 0x61, 0xb4, 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, \ + 0xab, 0x74, 0x5e, 0x07, 0x7d, 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, \ + 0xd9, 0x0d, 0x1c, 0x2d, 0x49, 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, \ + 0x0b, 0x8a, 0x4f, 0x69, 0x0c, 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, \ + 0x66, 0x7d, 0xae, 0x54, 0x2b, 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, \ + 0xc3, 0xcd, 0x40, 0x49, 0x08, 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, \ + 0x46, 0xbf, 0xd0, 0xb8, 0xaa, 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, \ + 0x1e, 0x44, 0x18, 0x0f, 0x0f, 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, \ + 0x18, 0xc6, 0x62, 0x2f, 0xc7, 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, \ + 0x27, 0x89, 0x29, 0x01, 0xc5, 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, \ + 0x4a, 0x0e, 0xef, 0xd6, 0xde, 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, \ + 0x7a, 0xc4, 0x02, 0x3c, 0x9a, 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, \ + 0xcb, 0x73, 0x4b, 0x52, 0x96, 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, \ + 0x39, 0x5a, 0xd3, 0x0f, 0xb0, 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, \ + 0x12, 0x01, 0x30, 0x97, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ + 0x01, 0x00, 0x97, 0x47, 0x44, 0xbc, 0x10, 0x81, 0xc5, 0x18, 0xe4, 0x59, \ + 0xfb, 0xe0, 0x2d, 0x3a, 0x0e, 0x9e, 0x10, 0xdc, 0x43, 0xfb, 0x15, 0x6c, \ + 0xd1, 0xfd, 0x48, 0x78, 0x6c, 0xf9, 0xed, 0x38, 0xe8, 0xdd, 0x09, 0xd7, \ + 0x5f, 0xb5, 0x41, 0x64, 0xd7, 0x63, 0xfa, 0x9d, 0x44, 0x0a, 0xf8, 0x42, \ + 0x13, 0xf1, 0xbb, 0x5e, 0x79, 0x20, 0x53, 0x98, 0x4b, 0x65, 0x7f, 0x86, \ + 0x67, 0x48, 0xe4, 0xcf, 0xfb, 0x6a, 0x24, 0xe2, 0x34, 0xbd, 0x14, 0x9d, \ + 0x2c, 0x16, 0xe2, 0xa4, 0x79, 0xd6, 0xa2, 0xec, 0x81, 0x43, 0x87, 0xbf, \ + 0x03, 0x5c, 0x88, 0x25, 0xd9, 0x41, 0xb6, 0xa5, 0xf1, 0x27, 0x52, 0x84, \ + 0xfe, 0x2b, 0x6e, 0x1d, 0x16, 0xcd, 0x73, 0x88, 0xf8, 0x90, 0xbf, 0x19, \ + 0xfe, 0xbe, 0xa9, 0xbf, 0x09, 0xd3, 0x23, 0x43, 0xd2, 0xc7, 0x61, 0x2a, \ + 0xb3, 0x4e, 0x3c, 0x61, 0xd4, 0xbd, 0xd8, 0xb4, 0xfa, 0xa8, 0x0b, 0xf8, \ + 0x7e, 0x56, 0xcd, 0x0f, 0x13, 0x27, 0xda, 0xe6, 0x3b, 0xb3, 0x8c, 0x9c, \ + 0x4b, 0x84, 0x3c, 0xc3, 0x52, 0x57, 0x9c, 0x27, 0x9a, 0x02, 0x76, 0x26, \ + 0x59, 0x82, 0x39, 0xc3, 0x13, 0xbe, 0x6e, 0xf4, 0x44, 0x2d, 0x1d, 0x8c, \ + 0x73, 0x3e, 0x43, 0x99, 0x59, 0xcb, 0xf2, 0x34, 0x72, 0x9a, 0x5e, 0xa5, \ + 0xeb, 0x9f, 0x36, 0x6d, 0x2b, 0xf9, 0xa2, 0xe7, 0xd1, 0x78, 0x52, 0x1b, \ + 0xc8, 0xf6, 0x5b, 0x41, 0x69, 0x57, 0x81, 0x89, 0xe9, 0xbb, 0xa1, 0xde, \ + 0x19, 0x37, 0x3b, 0x13, 0x5c, 0xca, 0x61, 0x01, 0x86, 0xff, 0xdf, 0x83, \ + 0x41, 0x49, 0x7f, 0xd6, 0xf4, 0x2e, 0x08, 0xfa, 0x90, 0xc2, 0x7c, 0xb4, \ + 0xb5, 0x0a, 0x17, 0xdb, 0x0e, 0x6d, 0x75, 0x8a, 0x5d, 0x31, 0xd5, 0x66, \ + 0xfb, 0x39, 0x0b, 0xb5, 0xb6, 0xa3, 0xcd, 0xd4, 0xef, 0x88, 0x92, 0x5a, \ + 0x4d, 0x6c, 0xcb, 0xea, 0x5b, 0x79, 0x02, 0x81, 0x81, 0x00, 0xdf, 0x3a, \ + 0xf9, 0x25, 0x5e, 0x24, 0x37, 0x26, 0x40, 0x97, 0x2f, 0xe0, 0x4a, 0xba, \ + 0x52, 0x1b, 0x51, 0xaf, 0x84, 0x06, 0x32, 0x24, 0x0c, 0xcf, 0x44, 0xa8, \ + 0x77, 0xa7, 0xad, 0xb5, 0x8c, 0x58, 0xcc, 0xc8, 0x31, 0xb7, 0x0d, 0xbc, \ + 0x08, 0x8a, 0xe0, 0xa6, 0x8c, 0xc2, 0x73, 0xe5, 0x1a, 0x64, 0x92, 0xe8, \ + 0xed, 0x4c, 0x6f, 0x0b, 0xa6, 0xa7, 0xf3, 0x9a, 0xf5, 0x6f, 0x69, 0xca, \ + 0x3c, 0x22, 0xd0, 0x15, 0xa8, 0x20, 0x27, 0x41, 0xf8, 0x43, 0x42, 0x7f, \ + 0xb1, 0x93, 0xa1, 0x04, 0x85, 0xda, 0xa0, 0x1c, 0xd6, 0xc6, 0xf7, 0x8a, \ + 0x9e, 0xea, 0x5c, 0x78, 0xa7, 0x55, 0xc4, 0x6b, 0x05, 0x8b, 0xc0, 0x83, \ + 0xcb, 0xce, 0x83, 0x05, 0xf8, 0xb2, 0x16, 0x2b, 0xdf, 0x06, 0x3f, 0xb8, \ + 0xec, 0x16, 0xda, 0x43, 0x33, 0xc1, 0x8f, 0xb0, 0xb8, 0xac, 0xae, 0xd4, \ + 0x94, 0xb8, 0xda, 0x6f, 0x6a, 0xc3, 0x02, 0x81, 0x81, 0x00, 0xdd, 0xae, \ + 0x00, 0xcd, 0xa0, 0x72, 0x1a, 0x05, 0x8a, 0xee, 0x2f, 0xd4, 0x71, 0x4b, \ + 0xf0, 0x3e, 0xe5, 0xc1, 0xe1, 0x29, 0x8b, 0xa6, 0x67, 0x30, 0x98, 0xe7, \ + 0x12, 0xef, 0xdd, 0x12, 0x01, 0x90, 0x24, 0x58, 0xf0, 0x76, 0x92, 0xe7, \ + 0x3d, 0xbb, 0x23, 0xe1, 0xce, 0xf9, 0xa1, 0xd4, 0x38, 0x1b, 0x3f, 0x20, \ + 0xb3, 0x0f, 0x65, 0x6a, 0x8f, 0x55, 0x57, 0x36, 0xee, 0xb2, 0x84, 0x44, \ + 0xfc, 0x91, 0x88, 0xe1, 0xa4, 0xdd, 0x3b, 0x4a, 0x40, 0x4d, 0x7c, 0x86, \ + 0xed, 0xe1, 0xb5, 0x42, 0xef, 0xb9, 0x61, 0xcd, 0x58, 0x19, 0x77, 0x02, \ + 0xae, 0x58, 0x80, 0xdb, 0x13, 0x3d, 0xc7, 0x1f, 0x9d, 0xed, 0xff, 0xac, \ + 0x98, 0xfc, 0xcd, 0xf9, 0x62, 0x04, 0x83, 0x91, 0x89, 0x0d, 0x86, 0x43, \ + 0x8c, 0x0c, 0xc7, 0x1b, 0x90, 0x4d, 0xbe, 0x2f, 0xc5, 0x7c, 0xcd, 0x42, \ + 0xf5, 0xd3, 0xad, 0x8e, 0xfd, 0x9d, 0x02, 0x81, 0x80, 0x17, 0x4b, 0x79, \ + 0x2a, 0x6c, 0x1b, 0x8d, 0x61, 0xc1, 0x85, 0xc5, 0x6a, 0x3b, 0x82, 0x1c, \ + 0x05, 0x5b, 0xcd, 0xdc, 0x12, 0x25, 0x73, 0x5b, 0x9e, 0xd9, 0x84, 0x57, \ + 0x10, 0x39, 0x71, 0x63, 0x96, 0xf4, 0xaf, 0xc3, 0x78, 0x5d, 0xc7, 0x8c, \ + 0x80, 0xa9, 0x96, 0xd7, 0xc3, 0x87, 0x02, 0x96, 0x71, 0x7e, 0x5f, 0x2e, \ + 0x3c, 0x36, 0xae, 0x59, 0x92, 0xd7, 0x3a, 0x09, 0x78, 0xb9, 0xea, 0x6f, \ + 0xc2, 0x16, 0x42, 0xdc, 0x4b, 0x96, 0xad, 0x2c, 0xb2, 0x20, 0x23, 0x61, \ + 0x2d, 0x8d, 0xb5, 0x02, 0x1e, 0xe1, 0x6c, 0x81, 0x01, 0x3c, 0x5d, 0xcb, \ + 0xdd, 0x9b, 0x0e, 0xc0, 0x2f, 0x94, 0x12, 0xb2, 0xfe, 0x75, 0x75, 0x8b, \ + 0x74, 0x1e, 0x7a, 0x26, 0x0c, 0xb7, 0x81, 0x96, 0x81, 0x79, 0x6e, 0xdb, \ + 0xbc, 0x3a, 0xc4, 0x9e, 0x87, 0x09, 0x6e, 0xa0, 0xa6, 0xec, 0x8b, 0xa4, \ + 0x85, 0x71, 0xce, 0x04, 0xaf, 0x02, 0x81, 0x81, 0x00, 0xc2, 0xa7, 0x47, \ + 0x07, 0x48, 0x6a, 0xc8, 0xd4, 0xb3, 0x20, 0xe1, 0x98, 0xee, 0xff, 0x5a, \ + 0x6f, 0x30, 0x7a, 0xa5, 0x47, 0x40, 0xdc, 0x16, 0x62, 0x42, 0xf1, 0x2c, \ + 0xdc, 0xb8, 0xc7, 0x55, 0xde, 0x07, 0x3c, 0x9d, 0xb1, 0xd0, 0xdf, 0x02, \ + 0x82, 0xb0, 0x48, 0x58, 0xe1, 0x34, 0xab, 0xcf, 0xb4, 0x85, 0x23, 0x26, \ + 0x78, 0x4f, 0x7a, 0x59, 0x6f, 0xfb, 0x8c, 0x3d, 0xdf, 0x3d, 0x6c, 0x02, \ + 0x47, 0x9c, 0xe5, 0x5e, 0x49, 0xf1, 0x05, 0x0b, 0x1f, 0xbf, 0x48, 0x0f, \ + 0xdc, 0x10, 0xb9, 0x3d, 0x1d, 0x10, 0x77, 0x2a, 0x73, 0xf9, 0xdf, 0xbd, \ + 0xcd, 0xf3, 0x1f, 0xeb, 0x6e, 0x64, 0xca, 0x2b, 0x78, 0x4f, 0xf8, 0x73, \ + 0xc2, 0x10, 0xef, 0x79, 0x95, 0x33, 0x1e, 0x79, 0x35, 0x09, 0xff, 0x88, \ + 0x1b, 0xb4, 0x3e, 0x4c, 0xe1, 0x27, 0x2e, 0x75, 0x80, 0x58, 0x11, 0x03, \ + 0x21, 0x23, 0x96, 0x9a, 0xb5, 0x02, 0x81, 0x80, 0x05, 0x12, 0x64, 0x71, \ + 0x83, 0x00, 0x1c, 0xfe, 0xef, 0x83, 0xea, 0xdd, 0x2c, 0xc8, 0x2c, 0x00, \ + 0x62, 0x1e, 0x8f, 0x3a, 0xdb, 0x1c, 0xab, 0xd6, 0x34, 0x8b, 0xd1, 0xb2, \ + 0x5a, 0x4f, 0x3d, 0x37, 0x38, 0x02, 0xe0, 0xd7, 0x70, 0xc1, 0xb0, 0x47, \ + 0xe0, 0x08, 0x1a, 0x84, 0xec, 0x48, 0xc5, 0x7c, 0x76, 0x83, 0x12, 0x67, \ + 0xab, 0x7c, 0x9f, 0x90, 0x97, 0xc8, 0x8f, 0x07, 0xf4, 0xb3, 0x60, 0xf2, \ + 0x3f, 0x49, 0x18, 0xdb, 0x2e, 0x94, 0x6b, 0x53, 0x9e, 0xa2, 0x63, 0xde, \ + 0x63, 0xd9, 0xab, 0x21, 0x2e, 0x2d, 0x0a, 0xe0, 0xd0, 0xe8, 0xba, 0xc4, \ + 0x4c, 0x1e, 0xa5, 0xf5, 0x51, 0xa8, 0xc4, 0x92, 0xf8, 0x7f, 0x21, 0xe7, \ + 0x65, 0xbf, 0x0b, 0xe6, 0x01, 0xaf, 0x9c, 0x1d, 0x5b, 0x6c, 0x3f, 0x1c, \ + 0x2f, 0xa6, 0x0f, 0x68, 0x38, 0x8e, 0x85, 0xc4, 0x6c, 0x78, 0x2f, 0x6f, \ + 0x06, 0x21, 0x2e, 0x56 \ +} +/* END FILE */ + +/* + * Test client Certificates + * + * Test client certificates are defined for each choice + * of the following parameters: + * - PEM or DER encoding + * - RSA or EC key + * + * Things to add: + * - hash type + * - multiple EC curve types + */ + +/* This is taken from tests/data_files/cli2.crt. */ +/* BEGIN FILE string macro TEST_CLI_CRT_EC_PEM tests/data_files/cli2.crt */ +#define TEST_CLI_CRT_EC_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIB3zCCAWOgAwIBAgIBDTAMBggqhkjOPQQDAgUAMD4xCzAJBgNVBAYTAk5MMREw\r\n" \ + "DwYDVQQKDAhQb2xhclNTTDEcMBoGA1UEAwwTUG9sYXJTU0wgVGVzdCBFQyBDQTAe\r\n" \ + "Fw0xOTAyMTAxNDQ0MDBaFw0yOTAyMTAxNDQ0MDBaMEExCzAJBgNVBAYTAk5MMREw\r\n" \ + "DwYDVQQKDAhQb2xhclNTTDEfMB0GA1UEAwwWUG9sYXJTU0wgVGVzdCBDbGllbnQg\r\n" \ + "MjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFflrrFz39Osu5O4gf8Sru7mU6zO\r\n" \ + "VVP2NA7MLuNjJQvfmOLzXGA2lsDVGBRw5X+f1UtFGOWwbNVc+JaPh3Cj5MejTTBL\r\n" \ + "MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMB8GA1Ud\r\n" \ + "IwQYMBaAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8MAwGCCqGSM49BAMCBQADaAAwZQIx\r\n" \ + "AMqme4DKMldUlplDET9Q6Eptre7uUWKhsLOF+zPkKDlfzpIkJYEFgcloDHGYw80u\r\n" \ + "IgIwNftyPXsabTqMM7iEHgVpX/GRozKklY9yQI/5eoA6gGW7Y+imuGR/oao5ySOb\r\n" \ + "a9Vk\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/cli2.crt.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CLI_CRT_EC_DER tests/data_files/cli2.crt.der */ +#define TEST_CLI_CRT_EC_DER { \ + 0x30, 0x82, 0x01, 0xdf, 0x30, 0x82, 0x01, 0x63, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x0d, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ + 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, \ + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ + 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, \ + 0x03, 0x0c, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \ + 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, \ + 0x17, 0x0d, 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, \ + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, \ + 0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x30, 0x41, 0x31, 0x0b, 0x30, 0x09, \ + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ + 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, \ + 0x03, 0x0c, 0x16, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \ + 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, \ + 0x32, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ + 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, \ + 0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, 0xb1, 0x73, 0xdf, 0xd3, 0xac, \ + 0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, 0xee, 0xe6, 0x53, 0xac, 0xce, \ + 0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, 0xe3, 0x63, 0x25, 0x0b, 0xdf, \ + 0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, 0xc0, 0xd5, 0x18, 0x14, 0x70, \ + 0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, 0xe5, 0xb0, 0x6c, 0xd5, 0x5c, \ + 0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, 0xc7, 0xa3, 0x4d, 0x30, 0x4b, \ + 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, \ + 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x7a, 0x00, \ + 0x5f, 0x86, 0x64, 0xfc, 0xe0, 0x5d, 0xe5, 0x11, 0x10, 0x3b, 0xb2, 0xe6, \ + 0x3b, 0xc4, 0x26, 0x3f, 0xcf, 0xe2, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, \ + 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, \ + 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, \ + 0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ + 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, \ + 0x00, 0xca, 0xa6, 0x7b, 0x80, 0xca, 0x32, 0x57, 0x54, 0x96, 0x99, 0x43, \ + 0x11, 0x3f, 0x50, 0xe8, 0x4a, 0x6d, 0xad, 0xee, 0xee, 0x51, 0x62, 0xa1, \ + 0xb0, 0xb3, 0x85, 0xfb, 0x33, 0xe4, 0x28, 0x39, 0x5f, 0xce, 0x92, 0x24, \ + 0x25, 0x81, 0x05, 0x81, 0xc9, 0x68, 0x0c, 0x71, 0x98, 0xc3, 0xcd, 0x2e, \ + 0x22, 0x02, 0x30, 0x35, 0xfb, 0x72, 0x3d, 0x7b, 0x1a, 0x6d, 0x3a, 0x8c, \ + 0x33, 0xb8, 0x84, 0x1e, 0x05, 0x69, 0x5f, 0xf1, 0x91, 0xa3, 0x32, 0xa4, \ + 0x95, 0x8f, 0x72, 0x40, 0x8f, 0xf9, 0x7a, 0x80, 0x3a, 0x80, 0x65, 0xbb, \ + 0x63, 0xe8, 0xa6, 0xb8, 0x64, 0x7f, 0xa1, 0xaa, 0x39, 0xc9, 0x23, 0x9b, \ + 0x6b, 0xd5, 0x64 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/cli2.key. */ +/* BEGIN FILE string macro TEST_CLI_KEY_EC_PEM tests/data_files/cli2.key */ +#define TEST_CLI_KEY_EC_PEM \ + "-----BEGIN EC PRIVATE KEY-----\r\n" \ + "MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n" \ + "AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n" \ + "wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n" \ + "-----END EC PRIVATE KEY-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/cli2.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CLI_KEY_EC_DER tests/data_files/cli2.key.der */ +#define TEST_CLI_KEY_EC_DER { \ + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf6, 0xf7, 0x86, 0x64, 0xf1, \ + 0x67, 0x7f, 0xe6, 0x64, 0x8d, 0xef, 0xca, 0x4e, 0xe9, 0xdd, 0x4d, 0xf0, \ + 0x05, 0xff, 0x96, 0x22, 0x8a, 0x7a, 0x84, 0x38, 0x64, 0x17, 0x32, 0x61, \ + 0x98, 0xb7, 0x2a, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ + 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, \ + 0xb1, 0x73, 0xdf, 0xd3, 0xac, 0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, \ + 0xee, 0xe6, 0x53, 0xac, 0xce, 0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, \ + 0xe3, 0x63, 0x25, 0x0b, 0xdf, 0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, \ + 0xc0, 0xd5, 0x18, 0x14, 0x70, 0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, \ + 0xe5, 0xb0, 0x6c, 0xd5, 0x5c, 0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, \ + 0xc7 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/cli-rsa-sha256.crt. */ +/* BEGIN FILE string macro TEST_CLI_CRT_RSA_PEM tests/data_files/cli-rsa-sha256.crt */ +#define TEST_CLI_CRT_RSA_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ + "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ + "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" \ + "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" \ + "M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" \ + "1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" \ + "MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" \ + "4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" \ + "/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" \ + "o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n" \ + "BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQsFAAOC\r\n" \ + "AQEAXidv1d4pLlBiKWED95rMycBdgDcgyNqJxakFkRfRyA2y1mlyTn7uBXRkNLY5\r\n" \ + "ZFzK82GCjk2Q2OD4RZSCPAJJqLpHHU34t71ciffvy2KK81YvrxczRhMAE64i+qna\r\n" \ + "yP3Td2XuWJR05PVPoSemsNELs9gWttdnYy3ce+EY2Y0n7Rsi7982EeLIAA7H6ca4\r\n" \ + "2Es/NUH//JZJT32OP0doMxeDRA+vplkKqTLLWf7dX26LIriBkBaRCgR5Yv9LBPFc\r\n" \ + "NOtpzu/LbrY7QFXKJMI+JXDudCsOn8KCmiA4d6Emisqfh3V3485l7HEQNcvLTxlD\r\n" \ + "6zDQyi0/ykYUYZkwQTK1N2Nvlw==\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This was generated from tests/data_files/cli-rsa-sha256.crt.der + using `xxd -i.` */ +/* BEGIN FILE binary macro TEST_CLI_CRT_RSA_DER tests/data_files/cli-rsa-sha256.crt.der */ +#define TEST_CLI_CRT_RSA_DER { \ + 0x30, 0x82, 0x03, 0x3f, 0x30, 0x82, 0x02, 0x27, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ + 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x36, 0x5a, 0x30, 0x3c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x11, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x6c, \ + 0x69, 0x65, 0x6e, 0x74, 0x20, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, \ + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, \ + 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, \ + 0x01, 0x01, 0x00, 0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, \ + 0x45, 0xd9, 0x14, 0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, \ + 0x33, 0xad, 0x0d, 0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, \ + 0xcc, 0x66, 0x85, 0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, \ + 0x9e, 0x0a, 0x6e, 0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, \ + 0x93, 0x86, 0x49, 0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, \ + 0xd4, 0x2f, 0x77, 0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, \ + 0x48, 0x70, 0xf5, 0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, \ + 0xe6, 0x43, 0xea, 0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, \ + 0x57, 0x4e, 0xa9, 0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, \ + 0x32, 0x30, 0xd5, 0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, \ + 0x5f, 0xf9, 0x3d, 0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, \ + 0xfb, 0xe5, 0x0c, 0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, \ + 0x7f, 0xca, 0xad, 0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, \ + 0xe0, 0x9b, 0xf8, 0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, \ + 0x04, 0x66, 0xc7, 0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, \ + 0x06, 0x67, 0xf4, 0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, \ + 0x3c, 0x8b, 0x35, 0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, \ + 0xfc, 0x36, 0x6b, 0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, \ + 0x00, 0xcf, 0xaf, 0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, \ + 0xe7, 0x50, 0x71, 0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, \ + 0xe4, 0xc4, 0xfd, 0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, \ + 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, \ + 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, \ + 0x04, 0x14, 0x71, 0xa1, 0x00, 0x73, 0x72, 0x40, 0x2f, 0x54, 0x76, 0x5e, \ + 0x33, 0xfc, 0x52, 0x8f, 0xbc, 0xf1, 0xdd, 0x6b, 0x46, 0x21, 0x30, 0x1f, \ + 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb4, \ + 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, 0xa6, 0x95, \ + 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, \ + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, \ + 0x01, 0x01, 0x00, 0x5e, 0x27, 0x6f, 0xd5, 0xde, 0x29, 0x2e, 0x50, 0x62, \ + 0x29, 0x61, 0x03, 0xf7, 0x9a, 0xcc, 0xc9, 0xc0, 0x5d, 0x80, 0x37, 0x20, \ + 0xc8, 0xda, 0x89, 0xc5, 0xa9, 0x05, 0x91, 0x17, 0xd1, 0xc8, 0x0d, 0xb2, \ + 0xd6, 0x69, 0x72, 0x4e, 0x7e, 0xee, 0x05, 0x74, 0x64, 0x34, 0xb6, 0x39, \ + 0x64, 0x5c, 0xca, 0xf3, 0x61, 0x82, 0x8e, 0x4d, 0x90, 0xd8, 0xe0, 0xf8, \ + 0x45, 0x94, 0x82, 0x3c, 0x02, 0x49, 0xa8, 0xba, 0x47, 0x1d, 0x4d, 0xf8, \ + 0xb7, 0xbd, 0x5c, 0x89, 0xf7, 0xef, 0xcb, 0x62, 0x8a, 0xf3, 0x56, 0x2f, \ + 0xaf, 0x17, 0x33, 0x46, 0x13, 0x00, 0x13, 0xae, 0x22, 0xfa, 0xa9, 0xda, \ + 0xc8, 0xfd, 0xd3, 0x77, 0x65, 0xee, 0x58, 0x94, 0x74, 0xe4, 0xf5, 0x4f, \ + 0xa1, 0x27, 0xa6, 0xb0, 0xd1, 0x0b, 0xb3, 0xd8, 0x16, 0xb6, 0xd7, 0x67, \ + 0x63, 0x2d, 0xdc, 0x7b, 0xe1, 0x18, 0xd9, 0x8d, 0x27, 0xed, 0x1b, 0x22, \ + 0xef, 0xdf, 0x36, 0x11, 0xe2, 0xc8, 0x00, 0x0e, 0xc7, 0xe9, 0xc6, 0xb8, \ + 0xd8, 0x4b, 0x3f, 0x35, 0x41, 0xff, 0xfc, 0x96, 0x49, 0x4f, 0x7d, 0x8e, \ + 0x3f, 0x47, 0x68, 0x33, 0x17, 0x83, 0x44, 0x0f, 0xaf, 0xa6, 0x59, 0x0a, \ + 0xa9, 0x32, 0xcb, 0x59, 0xfe, 0xdd, 0x5f, 0x6e, 0x8b, 0x22, 0xb8, 0x81, \ + 0x90, 0x16, 0x91, 0x0a, 0x04, 0x79, 0x62, 0xff, 0x4b, 0x04, 0xf1, 0x5c, \ + 0x34, 0xeb, 0x69, 0xce, 0xef, 0xcb, 0x6e, 0xb6, 0x3b, 0x40, 0x55, 0xca, \ + 0x24, 0xc2, 0x3e, 0x25, 0x70, 0xee, 0x74, 0x2b, 0x0e, 0x9f, 0xc2, 0x82, \ + 0x9a, 0x20, 0x38, 0x77, 0xa1, 0x26, 0x8a, 0xca, 0x9f, 0x87, 0x75, 0x77, \ + 0xe3, 0xce, 0x65, 0xec, 0x71, 0x10, 0x35, 0xcb, 0xcb, 0x4f, 0x19, 0x43, \ + 0xeb, 0x30, 0xd0, 0xca, 0x2d, 0x3f, 0xca, 0x46, 0x14, 0x61, 0x99, 0x30, \ + 0x41, 0x32, 0xb5, 0x37, 0x63, 0x6f, 0x97 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/cli-rsa.key. */ +/* BEGIN FILE string macro TEST_CLI_KEY_RSA_PEM tests/data_files/cli-rsa.key */ +#define TEST_CLI_KEY_RSA_PEM \ + "-----BEGIN RSA PRIVATE KEY-----\r\n" \ + "MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" \ + "B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n" \ + "bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n" \ + "Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n" \ + "7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n" \ + "dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n" \ + "yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n" \ + "4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n" \ + "ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n" \ + "zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n" \ + "l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n" \ + "DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n" \ + "VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" \ + "Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" \ + "wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" \ + "c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" \ + "33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" \ + "ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" \ + "BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" \ + "KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" \ + "UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" \ + "7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" \ + "gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" \ + "bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" \ + "8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" \ + "-----END RSA PRIVATE KEY-----\r\n"/* END FILE */ + +/* This was generated from tests/data_files/cli-rsa.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CLI_KEY_RSA_DER tests/data_files/cli-rsa.key.der */ +#define TEST_CLI_KEY_RSA_DER { \ + 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ + 0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, 0x45, 0xd9, 0x14, \ + 0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, 0x33, 0xad, 0x0d, \ + 0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, 0xcc, 0x66, 0x85, \ + 0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, 0x9e, 0x0a, 0x6e, \ + 0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, 0x93, 0x86, 0x49, \ + 0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, 0xd4, 0x2f, 0x77, \ + 0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, 0x48, 0x70, 0xf5, \ + 0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, 0xe6, 0x43, 0xea, \ + 0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, 0x57, 0x4e, 0xa9, \ + 0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, 0x32, 0x30, 0xd5, \ + 0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, 0x5f, 0xf9, 0x3d, \ + 0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, 0xfb, 0xe5, 0x0c, \ + 0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, 0x7f, 0xca, 0xad, \ + 0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, 0xe0, 0x9b, 0xf8, \ + 0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, 0x04, 0x66, 0xc7, \ + 0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, 0x06, 0x67, 0xf4, \ + 0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, 0x3c, 0x8b, 0x35, \ + 0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, 0xfc, 0x36, 0x6b, \ + 0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, 0x00, 0xcf, 0xaf, \ + 0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, 0xe7, 0x50, 0x71, \ + 0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, 0xe4, 0xc4, 0xfd, \ + 0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ + 0x00, 0x67, 0x4d, 0xb5, 0xf6, 0x03, 0x89, 0xaa, 0x7a, 0x6f, 0x3b, 0x2d, \ + 0xca, 0x10, 0xa2, 0x23, 0xc9, 0xbd, 0x4e, 0xda, 0xe1, 0x67, 0x0e, 0x0c, \ + 0x8a, 0xc6, 0x84, 0x68, 0xdf, 0xe5, 0x97, 0x75, 0xd2, 0x8d, 0xa3, 0x86, \ + 0xd9, 0xdb, 0xd5, 0xeb, 0x13, 0x19, 0x08, 0xc5, 0x7e, 0xe5, 0x37, 0x97, \ + 0x0c, 0x73, 0x80, 0x66, 0x76, 0x35, 0xf1, 0x88, 0xb5, 0xf2, 0xfc, 0xf3, \ + 0xe1, 0x4b, 0x76, 0x4e, 0x73, 0x45, 0xce, 0x2c, 0xc2, 0x10, 0x26, 0x0d, \ + 0x68, 0x0d, 0x9f, 0x49, 0x3d, 0xd6, 0x80, 0x89, 0xe7, 0xc5, 0x49, 0x15, \ + 0xdd, 0x85, 0xc0, 0xc8, 0xfe, 0x82, 0x37, 0x12, 0x5a, 0x0a, 0x6b, 0xf6, \ + 0x68, 0x0d, 0x32, 0x16, 0xbd, 0xa4, 0x15, 0x54, 0x9e, 0x68, 0xa1, 0xad, \ + 0xca, 0x6b, 0xe5, 0x8c, 0xda, 0x76, 0x35, 0x59, 0x2f, 0x9b, 0xb4, 0xe1, \ + 0xf1, 0xf0, 0x50, 0x04, 0xee, 0xc8, 0xec, 0x05, 0xe1, 0xcf, 0x8d, 0xe4, \ + 0xd2, 0x64, 0x7b, 0x5e, 0x63, 0xe0, 0x7b, 0x07, 0xbc, 0x02, 0x96, 0x4e, \ + 0x1b, 0x78, 0x6c, 0xb6, 0x43, 0x9a, 0x32, 0xf6, 0xd6, 0x02, 0xf5, 0x80, \ + 0xcc, 0x26, 0x6e, 0xa5, 0xd0, 0xe3, 0x65, 0x88, 0xce, 0x26, 0xa9, 0x40, \ + 0xe1, 0xe1, 0x00, 0xe0, 0x7f, 0x3f, 0xc3, 0xb1, 0x7c, 0xde, 0xbe, 0x42, \ + 0xba, 0x07, 0x81, 0x13, 0xc2, 0xe0, 0x11, 0x11, 0x23, 0x2c, 0xf8, 0xb2, \ + 0x7a, 0x3a, 0xd4, 0xe4, 0x7d, 0x5f, 0xb9, 0xb1, 0x18, 0xfa, 0x1d, 0x1d, \ + 0x97, 0x91, 0xd9, 0x04, 0x9e, 0xbc, 0xc9, 0xb4, 0xd7, 0x7d, 0x0e, 0x54, \ + 0xf6, 0x8f, 0xd0, 0x28, 0x0d, 0xdd, 0x77, 0x4b, 0x68, 0x04, 0x48, 0x61, \ + 0x75, 0x15, 0x03, 0x1b, 0x35, 0xad, 0x8e, 0xfc, 0x24, 0x11, 0x07, 0xea, \ + 0x17, 0x5a, 0xde, 0x19, 0x68, 0xff, 0xb6, 0x87, 0x7f, 0x80, 0x2a, 0x5f, \ + 0x0c, 0x58, 0xba, 0x5f, 0x41, 0x02, 0x81, 0x81, 0x00, 0xe3, 0x03, 0xaf, \ + 0xfe, 0x98, 0xd2, 0x0b, 0x7b, 0x72, 0xe9, 0x3b, 0x8e, 0xbc, 0xa5, 0xf6, \ + 0xac, 0xe5, 0x22, 0x06, 0xb2, 0xd7, 0x5e, 0xfd, 0x89, 0x4b, 0x16, 0x67, \ + 0x32, 0x83, 0x22, 0x58, 0x8e, 0x62, 0xa4, 0xb4, 0x2d, 0xf9, 0x16, 0x13, \ + 0x54, 0xf6, 0x9f, 0x2f, 0xf9, 0xbb, 0x0e, 0x7e, 0x8c, 0x6f, 0x08, 0xda, \ + 0xc8, 0xe9, 0x1c, 0x66, 0x10, 0x70, 0x93, 0x90, 0x8d, 0xcf, 0x90, 0x3a, \ + 0x43, 0x89, 0x49, 0xeb, 0x83, 0x2a, 0xfe, 0x5a, 0x87, 0xce, 0x74, 0x42, \ + 0x41, 0x0d, 0x8c, 0x73, 0x51, 0xbc, 0x7b, 0x20, 0xc5, 0xfd, 0xf6, 0x0b, \ + 0x65, 0xed, 0xa9, 0x2e, 0xfc, 0x0f, 0xf5, 0x50, 0xf9, 0x8d, 0x37, 0x36, \ + 0x9a, 0x20, 0xdf, 0xc3, 0xe3, 0x27, 0xbc, 0x98, 0x72, 0xc1, 0x14, 0x4b, \ + 0x71, 0xe9, 0x83, 0x14, 0xff, 0x24, 0xe2, 0x14, 0x15, 0xb6, 0x6f, 0x0f, \ + 0x32, 0x9d, 0xd9, 0x98, 0xd1, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x0c, 0xfb, \ + 0xc3, 0x33, 0x9b, 0x47, 0x88, 0x27, 0xf2, 0x26, 0xde, 0xeb, 0x5e, 0xee, \ + 0x40, 0xf6, 0x63, 0x5b, 0x35, 0x23, 0xf5, 0xd5, 0x07, 0x61, 0xdf, 0xa2, \ + 0x9f, 0x58, 0x30, 0x04, 0x22, 0x2b, 0xb4, 0xd9, 0xda, 0x46, 0x7f, 0x48, \ + 0xf5, 0x4f, 0xd0, 0xea, 0xd7, 0xa0, 0x45, 0x8a, 0x62, 0x8b, 0x8c, 0xac, \ + 0x73, 0x5e, 0xfa, 0x36, 0x65, 0x3e, 0xba, 0x6c, 0xba, 0x5e, 0x6b, 0x92, \ + 0x29, 0x5e, 0x6a, 0x0f, 0xd6, 0xd2, 0xa5, 0x95, 0x86, 0xda, 0x72, 0xc5, \ + 0x9e, 0xc9, 0x6b, 0x37, 0x5e, 0x4b, 0x9b, 0x77, 0xe1, 0x67, 0x1a, 0x1e, \ + 0x30, 0xd8, 0x41, 0x68, 0x40, 0xd3, 0x9c, 0xb4, 0xf6, 0xeb, 0x2a, 0x22, \ + 0xdf, 0x78, 0x29, 0xd2, 0x64, 0x92, 0x5b, 0x2f, 0x78, 0x64, 0x4a, 0xa2, \ + 0xa6, 0x6b, 0x3e, 0x50, 0xb1, 0x7a, 0xb1, 0x8d, 0x59, 0xb4, 0x55, 0xba, \ + 0xb6, 0x91, 0x85, 0xa3, 0x2f, 0x02, 0x81, 0x80, 0x10, 0x1e, 0x19, 0xe7, \ + 0xbc, 0x97, 0xe5, 0x22, 0xcd, 0xa4, 0xcb, 0x8a, 0xb5, 0xd0, 0x1e, 0xb4, \ + 0x65, 0xcc, 0x45, 0xa7, 0x7a, 0xed, 0x0e, 0x99, 0x29, 0xd0, 0x9c, 0x61, \ + 0x14, 0xb8, 0x62, 0x8b, 0x31, 0x6b, 0xba, 0x33, 0x2d, 0x65, 0x28, 0xd8, \ + 0x36, 0x6e, 0x54, 0xec, 0xa9, 0x20, 0x3d, 0x51, 0xe1, 0x2c, 0x42, 0xc4, \ + 0x52, 0xf0, 0xa6, 0x3a, 0x72, 0x93, 0xb7, 0x86, 0xa9, 0xfe, 0xf6, 0x74, \ + 0x07, 0x12, 0x4d, 0x7b, 0x51, 0x99, 0x1f, 0x7a, 0x56, 0xe9, 0x20, 0x2f, \ + 0x18, 0x34, 0x29, 0x97, 0xdb, 0x06, 0xee, 0xeb, 0xbf, 0xbd, 0x31, 0x4f, \ + 0xfa, 0x50, 0xb1, 0xba, 0x49, 0xb3, 0xc4, 0x1d, 0x03, 0xae, 0xb0, 0xdc, \ + 0xbe, 0x8a, 0xc4, 0x90, 0xa3, 0x28, 0x9b, 0xb6, 0x42, 0x09, 0x1b, 0xd6, \ + 0x29, 0x9b, 0x19, 0xe9, 0x87, 0x87, 0xd9, 0x9f, 0x35, 0x05, 0xab, 0x91, \ + 0x8f, 0x6d, 0x7c, 0x91, 0x02, 0x81, 0x81, 0x00, 0x94, 0x57, 0xf0, 0xe0, \ + 0x28, 0xfd, 0xbd, 0xf3, 0x9c, 0x43, 0x4d, 0x3e, 0xfd, 0x37, 0x4f, 0x23, \ + 0x52, 0x8d, 0xe1, 0x4c, 0xfe, 0x4c, 0x55, 0x80, 0x82, 0xba, 0x3f, 0xfe, \ + 0x51, 0xe1, 0x30, 0xd5, 0x3b, 0xd9, 0x73, 0x1d, 0xcb, 0x25, 0xbc, 0xbb, \ + 0x3f, 0xa5, 0xda, 0x77, 0xa6, 0xb5, 0xfc, 0x1a, 0xaf, 0x79, 0xa1, 0xb2, \ + 0x14, 0xa2, 0x1f, 0x10, 0x52, 0x1a, 0x05, 0x40, 0x48, 0xb6, 0x4f, 0x34, \ + 0xd6, 0xc0, 0xc3, 0xa4, 0x36, 0x98, 0x73, 0x88, 0x0b, 0xd3, 0x45, 0xdc, \ + 0xee, 0x51, 0x6e, 0x04, 0x73, 0x99, 0x93, 0x12, 0x58, 0x96, 0xcb, 0x39, \ + 0x42, 0xb1, 0xa9, 0xb8, 0xe1, 0x25, 0xf5, 0x9c, 0x14, 0xb7, 0x92, 0x2b, \ + 0x14, 0xb0, 0x5d, 0x61, 0xa2, 0xaa, 0x34, 0x7c, 0xcd, 0x54, 0x2d, 0x69, \ + 0x08, 0xf7, 0xdb, 0xfc, 0x9c, 0x87, 0xe8, 0x3a, 0xf6, 0x1d, 0x4c, 0x6a, \ + 0x83, 0x15, 0x30, 0x01, 0x02, 0x81, 0x81, 0x00, 0x9c, 0x53, 0xa1, 0xb6, \ + 0x2f, 0xc0, 0x06, 0xf5, 0xdf, 0x5c, 0xd1, 0x4a, 0x4e, 0xc8, 0xbd, 0x6d, \ + 0x32, 0xf1, 0x5e, 0xe5, 0x3b, 0x70, 0xd0, 0xa8, 0xe5, 0x41, 0x57, 0x6c, \ + 0x87, 0x53, 0x0f, 0xeb, 0x28, 0xa0, 0x62, 0x8f, 0x43, 0x62, 0xec, 0x2e, \ + 0x6c, 0x71, 0x55, 0x5b, 0x6a, 0xf4, 0x74, 0x14, 0xea, 0x7a, 0x03, 0xf6, \ + 0xfc, 0xa4, 0xce, 0xc4, 0xac, 0xda, 0x1d, 0xf0, 0xb5, 0xa9, 0xfd, 0x11, \ + 0x18, 0x3b, 0x14, 0xa0, 0x90, 0x8d, 0x26, 0xb7, 0x75, 0x73, 0x0a, 0x02, \ + 0x2c, 0x6f, 0x0f, 0xd8, 0x41, 0x78, 0xc3, 0x73, 0x81, 0xac, 0xaa, 0xaf, \ + 0xf2, 0xee, 0x32, 0xb5, 0x8d, 0x05, 0xf9, 0x59, 0x5a, 0x9e, 0x3e, 0x65, \ + 0x9b, 0x74, 0xda, 0xa0, 0x74, 0x95, 0x17, 0x5f, 0x8d, 0x58, 0xfc, 0x8e, \ + 0x4e, 0x2c, 0x1e, 0xbc, 0x81, 0x02, 0x18, 0xac, 0x12, 0xc6, 0xf9, 0x64, \ + 0x8b, 0x87, 0xc3, 0x00 \ +} +/* END FILE */ + +/* + * + * Test certificates and keys as C variables + * + */ + +/* + * CA + */ + +const char mbedtls_test_ca_crt_ec_pem[] = TEST_CA_CRT_EC_PEM; +const char mbedtls_test_ca_key_ec_pem[] = TEST_CA_KEY_EC_PEM; +const char mbedtls_test_ca_pwd_ec_pem[] = TEST_CA_PWD_EC_PEM; +const char mbedtls_test_ca_key_rsa_pem[] = TEST_CA_KEY_RSA_PEM; +const char mbedtls_test_ca_pwd_rsa_pem[] = TEST_CA_PWD_RSA_PEM; +const char mbedtls_test_ca_crt_rsa_sha1_pem[] = TEST_CA_CRT_RSA_SHA1_PEM; +const char mbedtls_test_ca_crt_rsa_sha256_pem[] = TEST_CA_CRT_RSA_SHA256_PEM; + +const unsigned char mbedtls_test_ca_crt_ec_der[] = TEST_CA_CRT_EC_DER; +const unsigned char mbedtls_test_ca_key_ec_der[] = TEST_CA_KEY_EC_DER; +const unsigned char mbedtls_test_ca_key_rsa_der[] = TEST_CA_KEY_RSA_DER; +const unsigned char mbedtls_test_ca_crt_rsa_sha1_der[] = + TEST_CA_CRT_RSA_SHA1_DER; +const unsigned char mbedtls_test_ca_crt_rsa_sha256_der[] = + TEST_CA_CRT_RSA_SHA256_DER; + +const size_t mbedtls_test_ca_crt_ec_pem_len = + sizeof( mbedtls_test_ca_crt_ec_pem ); +const size_t mbedtls_test_ca_key_ec_pem_len = + sizeof( mbedtls_test_ca_key_ec_pem ); +const size_t mbedtls_test_ca_pwd_ec_pem_len = + sizeof( mbedtls_test_ca_pwd_ec_pem ) - 1; +const size_t mbedtls_test_ca_key_rsa_pem_len = + sizeof( mbedtls_test_ca_key_rsa_pem ); +const size_t mbedtls_test_ca_pwd_rsa_pem_len = + sizeof( mbedtls_test_ca_pwd_rsa_pem ) - 1; +const size_t mbedtls_test_ca_crt_rsa_sha1_pem_len = + sizeof( mbedtls_test_ca_crt_rsa_sha1_pem ); +const size_t mbedtls_test_ca_crt_rsa_sha256_pem_len = + sizeof( mbedtls_test_ca_crt_rsa_sha256_pem ); + +const size_t mbedtls_test_ca_crt_ec_der_len = + sizeof( mbedtls_test_ca_crt_ec_der ); +const size_t mbedtls_test_ca_key_ec_der_len = + sizeof( mbedtls_test_ca_key_ec_der ); +const size_t mbedtls_test_ca_pwd_ec_der_len = 0; +const size_t mbedtls_test_ca_key_rsa_der_len = + sizeof( mbedtls_test_ca_key_rsa_der ); +const size_t mbedtls_test_ca_pwd_rsa_der_len = 0; +const size_t mbedtls_test_ca_crt_rsa_sha1_der_len = + sizeof( mbedtls_test_ca_crt_rsa_sha1_der ); +const size_t mbedtls_test_ca_crt_rsa_sha256_der_len = + sizeof( mbedtls_test_ca_crt_rsa_sha256_der ); + +/* + * Server + */ + +const char mbedtls_test_srv_crt_ec_pem[] = TEST_SRV_CRT_EC_PEM; +const char mbedtls_test_srv_key_ec_pem[] = TEST_SRV_KEY_EC_PEM; +const char mbedtls_test_srv_pwd_ec_pem[] = ""; +const char mbedtls_test_srv_key_rsa_pem[] = TEST_SRV_KEY_RSA_PEM; +const char mbedtls_test_srv_pwd_rsa_pem[] = ""; +const char mbedtls_test_srv_crt_rsa_sha1_pem[] = TEST_SRV_CRT_RSA_SHA1_PEM; +const char mbedtls_test_srv_crt_rsa_sha256_pem[] = TEST_SRV_CRT_RSA_SHA256_PEM; + +const unsigned char mbedtls_test_srv_crt_ec_der[] = TEST_SRV_CRT_EC_DER; +const unsigned char mbedtls_test_srv_key_ec_der[] = TEST_SRV_KEY_EC_DER; +const unsigned char mbedtls_test_srv_key_rsa_der[] = TEST_SRV_KEY_RSA_DER; +const unsigned char mbedtls_test_srv_crt_rsa_sha1_der[] = + TEST_SRV_CRT_RSA_SHA1_DER; +const unsigned char mbedtls_test_srv_crt_rsa_sha256_der[] = + TEST_SRV_CRT_RSA_SHA256_DER; + +const size_t mbedtls_test_srv_crt_ec_pem_len = + sizeof( mbedtls_test_srv_crt_ec_pem ); +const size_t mbedtls_test_srv_key_ec_pem_len = + sizeof( mbedtls_test_srv_key_ec_pem ); +const size_t mbedtls_test_srv_pwd_ec_pem_len = + sizeof( mbedtls_test_srv_pwd_ec_pem ) - 1; +const size_t mbedtls_test_srv_key_rsa_pem_len = + sizeof( mbedtls_test_srv_key_rsa_pem ); +const size_t mbedtls_test_srv_pwd_rsa_pem_len = + sizeof( mbedtls_test_srv_pwd_rsa_pem ) - 1; +const size_t mbedtls_test_srv_crt_rsa_sha1_pem_len = + sizeof( mbedtls_test_srv_crt_rsa_sha1_pem ); +const size_t mbedtls_test_srv_crt_rsa_sha256_pem_len = + sizeof( mbedtls_test_srv_crt_rsa_sha256_pem ); + +const size_t mbedtls_test_srv_crt_ec_der_len = + sizeof( mbedtls_test_srv_crt_ec_der ); +const size_t mbedtls_test_srv_key_ec_der_len = + sizeof( mbedtls_test_srv_key_ec_der ); +const size_t mbedtls_test_srv_pwd_ec_der_len = 0; +const size_t mbedtls_test_srv_key_rsa_der_len = + sizeof( mbedtls_test_srv_key_rsa_der ); +const size_t mbedtls_test_srv_pwd_rsa_der_len = 0; +const size_t mbedtls_test_srv_crt_rsa_sha1_der_len = + sizeof( mbedtls_test_srv_crt_rsa_sha1_der ); +const size_t mbedtls_test_srv_crt_rsa_sha256_der_len = + sizeof( mbedtls_test_srv_crt_rsa_sha256_der ); + +/* + * Client + */ + +const char mbedtls_test_cli_crt_ec_pem[] = TEST_CLI_CRT_EC_PEM; +const char mbedtls_test_cli_key_ec_pem[] = TEST_CLI_KEY_EC_PEM; +const char mbedtls_test_cli_pwd_ec_pem[] = ""; +const char mbedtls_test_cli_key_rsa_pem[] = TEST_CLI_KEY_RSA_PEM; +const char mbedtls_test_cli_pwd_rsa_pem[] = ""; +const char mbedtls_test_cli_crt_rsa_pem[] = TEST_CLI_CRT_RSA_PEM; + +const unsigned char mbedtls_test_cli_crt_ec_der[] = TEST_CLI_CRT_EC_DER; +const unsigned char mbedtls_test_cli_key_ec_der[] = TEST_CLI_KEY_EC_DER; +const unsigned char mbedtls_test_cli_key_rsa_der[] = TEST_CLI_KEY_RSA_DER; +const unsigned char mbedtls_test_cli_crt_rsa_der[] = TEST_CLI_CRT_RSA_DER; + +const size_t mbedtls_test_cli_crt_ec_pem_len = + sizeof( mbedtls_test_cli_crt_ec_pem ); +const size_t mbedtls_test_cli_key_ec_pem_len = + sizeof( mbedtls_test_cli_key_ec_pem ); +const size_t mbedtls_test_cli_pwd_ec_pem_len = + sizeof( mbedtls_test_cli_pwd_ec_pem ) - 1; +const size_t mbedtls_test_cli_key_rsa_pem_len = + sizeof( mbedtls_test_cli_key_rsa_pem ); +const size_t mbedtls_test_cli_pwd_rsa_pem_len = + sizeof( mbedtls_test_cli_pwd_rsa_pem ) - 1; +const size_t mbedtls_test_cli_crt_rsa_pem_len = + sizeof( mbedtls_test_cli_crt_rsa_pem ); + +const size_t mbedtls_test_cli_crt_ec_der_len = + sizeof( mbedtls_test_cli_crt_ec_der ); +const size_t mbedtls_test_cli_key_ec_der_len = + sizeof( mbedtls_test_cli_key_ec_der ); +const size_t mbedtls_test_cli_key_rsa_der_len = + sizeof( mbedtls_test_cli_key_rsa_der ); +const size_t mbedtls_test_cli_crt_rsa_der_len = + sizeof( mbedtls_test_cli_crt_rsa_der ); + +/* + * + * Definitions of test CRTs without specification of all parameters, choosing + * them automatically according to the config. For example, mbedtls_test_ca_crt + * is one of mbedtls_test_ca_crt_{rsa|ec}_{sha1|sha256}_{pem|der}. + * + */ + +/* + * Dispatch between PEM and DER according to config + */ + +#if defined(MBEDTLS_PEM_PARSE_C) + +/* PEM encoded test CA certificates and keys */ + +#define TEST_CA_KEY_RSA TEST_CA_KEY_RSA_PEM +#define TEST_CA_PWD_RSA TEST_CA_PWD_RSA_PEM +#define TEST_CA_CRT_RSA_SHA256 TEST_CA_CRT_RSA_SHA256_PEM +#define TEST_CA_CRT_RSA_SHA1 TEST_CA_CRT_RSA_SHA1_PEM +#define TEST_CA_KEY_EC TEST_CA_KEY_EC_PEM +#define TEST_CA_PWD_EC TEST_CA_PWD_EC_PEM +#define TEST_CA_CRT_EC TEST_CA_CRT_EC_PEM + +/* PEM encoded test server certificates and keys */ + +#define TEST_SRV_KEY_RSA TEST_SRV_KEY_RSA_PEM +#define TEST_SRV_PWD_RSA "" +#define TEST_SRV_CRT_RSA_SHA256 TEST_SRV_CRT_RSA_SHA256_PEM +#define TEST_SRV_CRT_RSA_SHA1 TEST_SRV_CRT_RSA_SHA1_PEM +#define TEST_SRV_KEY_EC TEST_SRV_KEY_EC_PEM +#define TEST_SRV_PWD_EC "" +#define TEST_SRV_CRT_EC TEST_SRV_CRT_EC_PEM + +/* PEM encoded test client certificates and keys */ + +#define TEST_CLI_KEY_RSA TEST_CLI_KEY_RSA_PEM +#define TEST_CLI_PWD_RSA "" +#define TEST_CLI_CRT_RSA TEST_CLI_CRT_RSA_PEM +#define TEST_CLI_KEY_EC TEST_CLI_KEY_EC_PEM +#define TEST_CLI_PWD_EC "" +#define TEST_CLI_CRT_EC TEST_CLI_CRT_EC_PEM + +#else /* MBEDTLS_PEM_PARSE_C */ + +/* DER encoded test CA certificates and keys */ + +#define TEST_CA_KEY_RSA TEST_CA_KEY_RSA_DER +#define TEST_CA_PWD_RSA "" +#define TEST_CA_CRT_RSA_SHA256 TEST_CA_CRT_RSA_SHA256_DER +#define TEST_CA_CRT_RSA_SHA1 TEST_CA_CRT_RSA_SHA1_DER +#define TEST_CA_KEY_EC TEST_CA_KEY_EC_DER +#define TEST_CA_PWD_EC "" +#define TEST_CA_CRT_EC TEST_CA_CRT_EC_DER + +/* DER encoded test server certificates and keys */ + +#define TEST_SRV_KEY_RSA TEST_SRV_KEY_RSA_DER +#define TEST_SRV_PWD_RSA "" +#define TEST_SRV_CRT_RSA_SHA256 TEST_SRV_CRT_RSA_SHA256_DER +#define TEST_SRV_CRT_RSA_SHA1 TEST_SRV_CRT_RSA_SHA1_DER +#define TEST_SRV_KEY_EC TEST_SRV_KEY_EC_DER +#define TEST_SRV_PWD_EC "" +#define TEST_SRV_CRT_EC TEST_SRV_CRT_EC_DER + +/* DER encoded test client certificates and keys */ + +#define TEST_CLI_KEY_RSA TEST_CLI_KEY_RSA_DER +#define TEST_CLI_PWD_RSA "" +#define TEST_CLI_CRT_RSA TEST_CLI_CRT_RSA_DER +#define TEST_CLI_KEY_EC TEST_CLI_KEY_EC_DER +#define TEST_CLI_PWD_EC "" +#define TEST_CLI_CRT_EC TEST_CLI_CRT_EC_DER + +#endif /* MBEDTLS_PEM_PARSE_C */ + +const char mbedtls_test_ca_key_rsa[] = TEST_CA_KEY_RSA; +const char mbedtls_test_ca_pwd_rsa[] = TEST_CA_PWD_RSA; +const char mbedtls_test_ca_crt_rsa_sha256[] = TEST_CA_CRT_RSA_SHA256; +const char mbedtls_test_ca_crt_rsa_sha1[] = TEST_CA_CRT_RSA_SHA1; +const char mbedtls_test_ca_key_ec[] = TEST_CA_KEY_EC; +const char mbedtls_test_ca_pwd_ec[] = TEST_CA_PWD_EC; +const char mbedtls_test_ca_crt_ec[] = TEST_CA_CRT_EC; + +const char mbedtls_test_srv_key_rsa[] = TEST_SRV_KEY_RSA; +const char mbedtls_test_srv_pwd_rsa[] = TEST_SRV_PWD_RSA; +const char mbedtls_test_srv_crt_rsa_sha256[] = TEST_SRV_CRT_RSA_SHA256; +const char mbedtls_test_srv_crt_rsa_sha1[] = TEST_SRV_CRT_RSA_SHA1; +const char mbedtls_test_srv_key_ec[] = TEST_SRV_KEY_EC; +const char mbedtls_test_srv_pwd_ec[] = TEST_SRV_PWD_EC; +const char mbedtls_test_srv_crt_ec[] = TEST_SRV_CRT_EC; + +const char mbedtls_test_cli_key_rsa[] = TEST_CLI_KEY_RSA; +const char mbedtls_test_cli_pwd_rsa[] = TEST_CLI_PWD_RSA; +const char mbedtls_test_cli_crt_rsa[] = TEST_CLI_CRT_RSA; +const char mbedtls_test_cli_key_ec[] = TEST_CLI_KEY_EC; +const char mbedtls_test_cli_pwd_ec[] = TEST_CLI_PWD_EC; +const char mbedtls_test_cli_crt_ec[] = TEST_CLI_CRT_EC; + +const size_t mbedtls_test_ca_key_rsa_len = + sizeof( mbedtls_test_ca_key_rsa ); +const size_t mbedtls_test_ca_pwd_rsa_len = + sizeof( mbedtls_test_ca_pwd_rsa ) - 1; +const size_t mbedtls_test_ca_crt_rsa_sha256_len = + sizeof( mbedtls_test_ca_crt_rsa_sha256 ); +const size_t mbedtls_test_ca_crt_rsa_sha1_len = + sizeof( mbedtls_test_ca_crt_rsa_sha1 ); +const size_t mbedtls_test_ca_key_ec_len = + sizeof( mbedtls_test_ca_key_ec ); +const size_t mbedtls_test_ca_pwd_ec_len = + sizeof( mbedtls_test_ca_pwd_ec ) - 1; +const size_t mbedtls_test_ca_crt_ec_len = + sizeof( mbedtls_test_ca_crt_ec ); + +const size_t mbedtls_test_srv_key_rsa_len = + sizeof( mbedtls_test_srv_key_rsa ); +const size_t mbedtls_test_srv_pwd_rsa_len = + sizeof( mbedtls_test_srv_pwd_rsa ) -1; +const size_t mbedtls_test_srv_crt_rsa_sha256_len = + sizeof( mbedtls_test_srv_crt_rsa_sha256 ); +const size_t mbedtls_test_srv_crt_rsa_sha1_len = + sizeof( mbedtls_test_srv_crt_rsa_sha1 ); +const size_t mbedtls_test_srv_key_ec_len = + sizeof( mbedtls_test_srv_key_ec ); +const size_t mbedtls_test_srv_pwd_ec_len = + sizeof( mbedtls_test_srv_pwd_ec ) - 1; +const size_t mbedtls_test_srv_crt_ec_len = + sizeof( mbedtls_test_srv_crt_ec ); + +const size_t mbedtls_test_cli_key_rsa_len = + sizeof( mbedtls_test_cli_key_rsa ); +const size_t mbedtls_test_cli_pwd_rsa_len = + sizeof( mbedtls_test_cli_pwd_rsa ) - 1; +const size_t mbedtls_test_cli_crt_rsa_len = + sizeof( mbedtls_test_cli_crt_rsa ); +const size_t mbedtls_test_cli_key_ec_len = + sizeof( mbedtls_test_cli_key_ec ); +const size_t mbedtls_test_cli_pwd_ec_len = + sizeof( mbedtls_test_cli_pwd_ec ) - 1; +const size_t mbedtls_test_cli_crt_ec_len = + sizeof( mbedtls_test_cli_crt_ec ); + +/* + * Dispatch between SHA-1 and SHA-256 + */ + +#if defined(MBEDTLS_SHA256_C) +#define TEST_CA_CRT_RSA TEST_CA_CRT_RSA_SHA256 +#define TEST_SRV_CRT_RSA TEST_SRV_CRT_RSA_SHA256 +#else +#define TEST_CA_CRT_RSA TEST_CA_CRT_RSA_SHA1 +#define TEST_SRV_CRT_RSA TEST_SRV_CRT_RSA_SHA1 +#endif /* MBEDTLS_SHA256_C */ + +const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA; +const char mbedtls_test_srv_crt_rsa[] = TEST_SRV_CRT_RSA; + +const size_t mbedtls_test_ca_crt_rsa_len = + sizeof( mbedtls_test_ca_crt_rsa ); +const size_t mbedtls_test_srv_crt_rsa_len = + sizeof( mbedtls_test_srv_crt_rsa ); + +/* + * Dispatch between RSA and EC + */ + +#if defined(MBEDTLS_RSA_C) + +#define TEST_CA_KEY TEST_CA_KEY_RSA +#define TEST_CA_PWD TEST_CA_PWD_RSA +#define TEST_CA_CRT TEST_CA_CRT_RSA + +#define TEST_SRV_KEY TEST_SRV_KEY_RSA +#define TEST_SRV_PWD TEST_SRV_PWD_RSA +#define TEST_SRV_CRT TEST_SRV_CRT_RSA + +#define TEST_CLI_KEY TEST_CLI_KEY_RSA +#define TEST_CLI_PWD TEST_CLI_PWD_RSA +#define TEST_CLI_CRT TEST_CLI_CRT_RSA + +#else /* no RSA, so assume ECDSA */ + +#define TEST_CA_KEY TEST_CA_KEY_EC +#define TEST_CA_PWD TEST_CA_PWD_EC +#define TEST_CA_CRT TEST_CA_CRT_EC + +#define TEST_SRV_KEY TEST_SRV_KEY_EC +#define TEST_SRV_PWD TEST_SRV_PWD_EC +#define TEST_SRV_CRT TEST_SRV_CRT_EC + +#define TEST_CLI_KEY TEST_CLI_KEY_EC +#define TEST_CLI_PWD TEST_CLI_PWD_EC +#define TEST_CLI_CRT TEST_CLI_CRT_EC + +#endif /* MBEDTLS_RSA_C */ + +/* API stability forces us to declare + * mbedtls_test_{ca|srv|cli}_{key|pwd|crt} + * as pointers. */ +static const char test_ca_key[] = TEST_CA_KEY; +static const char test_ca_pwd[] = TEST_CA_PWD; +static const char test_ca_crt[] = TEST_CA_CRT; + +static const char test_srv_key[] = TEST_SRV_KEY; +static const char test_srv_pwd[] = TEST_SRV_PWD; +static const char test_srv_crt[] = TEST_SRV_CRT; + +static const char test_cli_key[] = TEST_CLI_KEY; +static const char test_cli_pwd[] = TEST_CLI_PWD; +static const char test_cli_crt[] = TEST_CLI_CRT; + +const char *mbedtls_test_ca_key = test_ca_key; +const char *mbedtls_test_ca_pwd = test_ca_pwd; +const char *mbedtls_test_ca_crt = test_ca_crt; + +const char *mbedtls_test_srv_key = test_srv_key; +const char *mbedtls_test_srv_pwd = test_srv_pwd; +const char *mbedtls_test_srv_crt = test_srv_crt; + +const char *mbedtls_test_cli_key = test_cli_key; +const char *mbedtls_test_cli_pwd = test_cli_pwd; +const char *mbedtls_test_cli_crt = test_cli_crt; + +const size_t mbedtls_test_ca_key_len = + sizeof( test_ca_key ); +const size_t mbedtls_test_ca_pwd_len = + sizeof( test_ca_pwd ) - 1; +const size_t mbedtls_test_ca_crt_len = + sizeof( test_ca_crt ); + +const size_t mbedtls_test_srv_key_len = + sizeof( test_srv_key ); +const size_t mbedtls_test_srv_pwd_len = + sizeof( test_srv_pwd ) - 1; +const size_t mbedtls_test_srv_crt_len = + sizeof( test_srv_crt ); + +const size_t mbedtls_test_cli_key_len = + sizeof( test_cli_key ); +const size_t mbedtls_test_cli_pwd_len = + sizeof( test_cli_pwd ) - 1; +const size_t mbedtls_test_cli_crt_len = + sizeof( test_cli_crt ); + +/* + * + * Lists of certificates + * + */ + +/* List of CAs in PEM or DER, depending on config */ +const char * mbedtls_test_cas[] = { +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA1_C) + mbedtls_test_ca_crt_rsa_sha1, +#endif +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) + mbedtls_test_ca_crt_rsa_sha256, +#endif +#if defined(MBEDTLS_ECDSA_C) + mbedtls_test_ca_crt_ec, +#endif + NULL +}; +const size_t mbedtls_test_cas_len[] = { +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA1_C) + sizeof( mbedtls_test_ca_crt_rsa_sha1 ), +#endif +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) + sizeof( mbedtls_test_ca_crt_rsa_sha256 ), +#endif +#if defined(MBEDTLS_ECDSA_C) + sizeof( mbedtls_test_ca_crt_ec ), +#endif + 0 +}; + +/* List of all available CA certificates in DER format */ +const unsigned char * mbedtls_test_cas_der[] = { +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_SHA256_C) + mbedtls_test_ca_crt_rsa_sha256_der, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA1_C) + mbedtls_test_ca_crt_rsa_sha1_der, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) + mbedtls_test_ca_crt_ec_der, +#endif /* MBEDTLS_ECDSA_C */ + NULL +}; + +const size_t mbedtls_test_cas_der_len[] = { +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_SHA256_C) + sizeof( mbedtls_test_ca_crt_rsa_sha256_der ), +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA1_C) + sizeof( mbedtls_test_ca_crt_rsa_sha1_der ), +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) + sizeof( mbedtls_test_ca_crt_ec_der ), +#endif /* MBEDTLS_ECDSA_C */ + 0 +}; + +/* Concatenation of all available CA certificates in PEM format */ +#if defined(MBEDTLS_PEM_PARSE_C) +const char mbedtls_test_cas_pem[] = +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_SHA256_C) + TEST_CA_CRT_RSA_SHA256_PEM +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA1_C) + TEST_CA_CRT_RSA_SHA1_PEM +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) + TEST_CA_CRT_EC_PEM +#endif /* MBEDTLS_ECDSA_C */ + ""; +const size_t mbedtls_test_cas_pem_len = sizeof( mbedtls_test_cas_pem ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#endif /* MBEDTLS_CERTS_C */ diff --git a/external/mbedtls/library/chacha20.c b/external/mbedtls/library/chacha20.c new file mode 100644 index 0000000..80fe50c --- /dev/null +++ b/external/mbedtls/library/chacha20.c @@ -0,0 +1,595 @@ +/** + * \file chacha20.c + * + * \brief ChaCha20 cipher. + * + * \author Daniel King + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CHACHA20_C) + +#include "mbedtls/chacha20.h" +#include "mbedtls/platform_util.h" + +#include +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CHACHA20_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define CHACHA20_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) +#define CHACHA20_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define BYTES_TO_U32_LE( data, offset ) \ + ( (uint32_t) (data)[offset] \ + | (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 ) \ + | (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 ) \ + | (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 ) \ + ) + +#define ROTL32( value, amount ) \ + ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) ) + +#define CHACHA20_CTR_INDEX ( 12U ) + +#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U ) + +/** + * \brief ChaCha20 quarter round operation. + * + * The quarter round is defined as follows (from RFC 7539): + * 1. a += b; d ^= a; d <<<= 16; + * 2. c += d; b ^= c; b <<<= 12; + * 3. a += b; d ^= a; d <<<= 8; + * 4. c += d; b ^= c; b <<<= 7; + * + * \param state ChaCha20 state to modify. + * \param a The index of 'a' in the state. + * \param b The index of 'b' in the state. + * \param c The index of 'c' in the state. + * \param d The index of 'd' in the state. + */ +static inline void chacha20_quarter_round( uint32_t state[16], + size_t a, + size_t b, + size_t c, + size_t d ) +{ + /* a += b; d ^= a; d <<<= 16; */ + state[a] += state[b]; + state[d] ^= state[a]; + state[d] = ROTL32( state[d], 16 ); + + /* c += d; b ^= c; b <<<= 12 */ + state[c] += state[d]; + state[b] ^= state[c]; + state[b] = ROTL32( state[b], 12 ); + + /* a += b; d ^= a; d <<<= 8; */ + state[a] += state[b]; + state[d] ^= state[a]; + state[d] = ROTL32( state[d], 8 ); + + /* c += d; b ^= c; b <<<= 7; */ + state[c] += state[d]; + state[b] ^= state[c]; + state[b] = ROTL32( state[b], 7 ); +} + +/** + * \brief Perform the ChaCha20 inner block operation. + * + * This function performs two rounds: the column round and the + * diagonal round. + * + * \param state The ChaCha20 state to update. + */ +static void chacha20_inner_block( uint32_t state[16] ) +{ + chacha20_quarter_round( state, 0, 4, 8, 12 ); + chacha20_quarter_round( state, 1, 5, 9, 13 ); + chacha20_quarter_round( state, 2, 6, 10, 14 ); + chacha20_quarter_round( state, 3, 7, 11, 15 ); + + chacha20_quarter_round( state, 0, 5, 10, 15 ); + chacha20_quarter_round( state, 1, 6, 11, 12 ); + chacha20_quarter_round( state, 2, 7, 8, 13 ); + chacha20_quarter_round( state, 3, 4, 9, 14 ); +} + +/** + * \brief Generates a keystream block. + * + * \param initial_state The initial ChaCha20 state (key, nonce, counter). + * \param keystream Generated keystream bytes are written to this buffer. + */ +static void chacha20_block( const uint32_t initial_state[16], + unsigned char keystream[64] ) +{ + uint32_t working_state[16]; + size_t i; + + memcpy( working_state, + initial_state, + CHACHA20_BLOCK_SIZE_BYTES ); + + for( i = 0U; i < 10U; i++ ) + chacha20_inner_block( working_state ); + + working_state[ 0] += initial_state[ 0]; + working_state[ 1] += initial_state[ 1]; + working_state[ 2] += initial_state[ 2]; + working_state[ 3] += initial_state[ 3]; + working_state[ 4] += initial_state[ 4]; + working_state[ 5] += initial_state[ 5]; + working_state[ 6] += initial_state[ 6]; + working_state[ 7] += initial_state[ 7]; + working_state[ 8] += initial_state[ 8]; + working_state[ 9] += initial_state[ 9]; + working_state[10] += initial_state[10]; + working_state[11] += initial_state[11]; + working_state[12] += initial_state[12]; + working_state[13] += initial_state[13]; + working_state[14] += initial_state[14]; + working_state[15] += initial_state[15]; + + for( i = 0U; i < 16; i++ ) + { + size_t offset = i * 4U; + + keystream[offset ] = (unsigned char)( working_state[i] ); + keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 ); + keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 ); + keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 ); + } + + mbedtls_platform_zeroize( working_state, sizeof( working_state ) ); +} + +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ) +{ + CHACHA20_VALIDATE( ctx != NULL ); + + mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) ); + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; +} + +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) ); + } +} + +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ) +{ + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( key != NULL ); + + /* ChaCha20 constants - the string "expand 32-byte k" */ + ctx->state[0] = 0x61707865; + ctx->state[1] = 0x3320646e; + ctx->state[2] = 0x79622d32; + ctx->state[3] = 0x6b206574; + + /* Set key */ + ctx->state[4] = BYTES_TO_U32_LE( key, 0 ); + ctx->state[5] = BYTES_TO_U32_LE( key, 4 ); + ctx->state[6] = BYTES_TO_U32_LE( key, 8 ); + ctx->state[7] = BYTES_TO_U32_LE( key, 12 ); + ctx->state[8] = BYTES_TO_U32_LE( key, 16 ); + ctx->state[9] = BYTES_TO_U32_LE( key, 20 ); + ctx->state[10] = BYTES_TO_U32_LE( key, 24 ); + ctx->state[11] = BYTES_TO_U32_LE( key, 28 ); + + return( 0 ); +} + +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ) +{ + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( nonce != NULL ); + + /* Counter */ + ctx->state[12] = counter; + + /* Nonce */ + ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 ); + ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 ); + ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 ); + + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; + + return( 0 ); +} + +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ) +{ + size_t offset = 0U; + size_t i; + + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( size == 0 || input != NULL ); + CHACHA20_VALIDATE_RET( size == 0 || output != NULL ); + + /* Use leftover keystream bytes, if available */ + while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) + { + output[offset] = input[offset] + ^ ctx->keystream8[ctx->keystream_bytes_used]; + + ctx->keystream_bytes_used++; + offset++; + size--; + } + + /* Process full blocks */ + while( size >= CHACHA20_BLOCK_SIZE_BYTES ) + { + /* Generate new keystream block and increment counter */ + chacha20_block( ctx->state, ctx->keystream8 ); + ctx->state[CHACHA20_CTR_INDEX]++; + + for( i = 0U; i < 64U; i += 8U ) + { + output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ]; + output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1]; + output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2]; + output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3]; + output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4]; + output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5]; + output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6]; + output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7]; + } + + offset += CHACHA20_BLOCK_SIZE_BYTES; + size -= CHACHA20_BLOCK_SIZE_BYTES; + } + + /* Last (partial) block */ + if( size > 0U ) + { + /* Generate new keystream block and increment counter */ + chacha20_block( ctx->state, ctx->keystream8 ); + ctx->state[CHACHA20_CTR_INDEX]++; + + for( i = 0U; i < size; i++) + { + output[offset + i] = input[offset + i] ^ ctx->keystream8[i]; + } + + ctx->keystream_bytes_used = size; + + } + + return( 0 ); +} + +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t data_len, + const unsigned char* input, + unsigned char* output ) +{ + mbedtls_chacha20_context ctx; + int ret; + + CHACHA20_VALIDATE_RET( key != NULL ); + CHACHA20_VALIDATE_RET( nonce != NULL ); + CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL ); + CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL ); + + mbedtls_chacha20_init( &ctx ); + + ret = mbedtls_chacha20_setkey( &ctx, key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chacha20_starts( &ctx, nonce, counter ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chacha20_update( &ctx, data_len, input, output ); + +cleanup: + mbedtls_chacha20_free( &ctx ); + return( ret ); +} + +#endif /* !MBEDTLS_CHACHA20_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_keys[2][32] = +{ + { + 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 + }, + { + 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, 0x01 + } +}; + +static const unsigned char test_nonces[2][12] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02 + } +}; + +static const uint32_t test_counters[2] = +{ + 0U, + 1U +}; + +static const unsigned char test_input[2][375] = +{ + { + 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, + 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 + }, + { + 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, + 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, + 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, + 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, + 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, + 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, + 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, + 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f + } +}; + +static const unsigned char test_output[2][375] = +{ + { + 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, + 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, + 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, + 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, + 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, + 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, + 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, + 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86 + }, + { + 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde, + 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70, + 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd, + 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec, + 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15, + 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05, + 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f, + 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d, + 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa, + 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e, + 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7, + 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50, + 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05, + 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c, + 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05, + 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a, + 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0, + 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66, + 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4, + 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d, + 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91, + 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28, + 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87, + 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b, + 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2, + 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f, + 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76, + 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c, + 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b, + 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84, + 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd, + 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b, + 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe, + 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0, + 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80, + 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f, + 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3, + 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62, + 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91, + 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6, + 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64, + 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85, + 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41, + 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab, + 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba, + 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd, + 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21 + } +}; + +static const size_t test_lengths[2] = +{ + 64U, + 375U +}; + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_chacha20_self_test( int verbose ) +{ + unsigned char output[381]; + unsigned i; + int ret; + + for( i = 0U; i < 2U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ChaCha20 test %u ", i ); + + ret = mbedtls_chacha20_crypt( test_keys[i], + test_nonces[i], + test_counters[i], + test_lengths[i], + test_input[i], + output ); + + ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ), + ( "failed (output)\n" ) ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* !MBEDTLS_CHACHA20_C */ diff --git a/external/mbedtls/library/chachapoly.c b/external/mbedtls/library/chachapoly.c new file mode 100644 index 0000000..c8b5bba --- /dev/null +++ b/external/mbedtls/library/chachapoly.c @@ -0,0 +1,565 @@ +/** + * \file chachapoly.c + * + * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + +#include "mbedtls/chachapoly.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +/* Parameter validation macros */ +#define CHACHAPOLY_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) +#define CHACHAPOLY_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define CHACHAPOLY_STATE_INIT ( 0 ) +#define CHACHAPOLY_STATE_AAD ( 1 ) +#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */ +#define CHACHAPOLY_STATE_FINISHED ( 3 ) + +/** + * \brief Adds nul bytes to pad the AAD for Poly1305. + * + * \param ctx The ChaCha20-Poly1305 context. + */ +static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx ) +{ + uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U ); + unsigned char zeroes[15]; + + if( partial_block_len == 0U ) + return( 0 ); + + memset( zeroes, 0, sizeof( zeroes ) ); + + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, + zeroes, + 16U - partial_block_len ) ); +} + +/** + * \brief Adds nul bytes to pad the ciphertext for Poly1305. + * + * \param ctx The ChaCha20-Poly1305 context. + */ +static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx ) +{ + uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U ); + unsigned char zeroes[15]; + + if( partial_block_len == 0U ) + return( 0 ); + + memset( zeroes, 0, sizeof( zeroes ) ); + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, + zeroes, + 16U - partial_block_len ) ); +} + +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ) +{ + CHACHAPOLY_VALIDATE( ctx != NULL ); + + mbedtls_chacha20_init( &ctx->chacha20_ctx ); + mbedtls_poly1305_init( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; +} + +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_chacha20_free( &ctx->chacha20_ctx ); + mbedtls_poly1305_free( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; +} + +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ) +{ + int ret; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( key != NULL ); + + ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key ); + + return( ret ); +} + +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ) +{ + int ret; + unsigned char poly1305_key[64]; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + + /* Set counter = 0, will be update to 1 when generating Poly1305 key */ + ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U ); + if( ret != 0 ) + goto cleanup; + + /* Generate the Poly1305 key by getting the ChaCha20 keystream output with + * counter = 0. This is the same as encrypting a buffer of zeroes. + * Only the first 256-bits (32 bytes) of the key is used for Poly1305. + * The other 256 bits are discarded. + */ + memset( poly1305_key, 0, sizeof( poly1305_key ) ); + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ), + poly1305_key, poly1305_key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key ); + + if( ret == 0 ) + { + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_AAD; + ctx->mode = mode; + } + +cleanup: + mbedtls_platform_zeroize( poly1305_key, 64U ); + return( ret ); +} + +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ) +{ + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + + if( ctx->state != CHACHAPOLY_STATE_AAD ) + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + + ctx->aad_len += aad_len; + + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) ); +} + +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL ); + + if( ( ctx->state != CHACHAPOLY_STATE_AAD ) && + ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + if( ctx->state == CHACHAPOLY_STATE_AAD ) + { + ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; + + ret = chachapoly_pad_aad( ctx ); + if( ret != 0 ) + return( ret ); + } + + ctx->ciphertext_len += len; + + if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT ) + { + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len ); + if( ret != 0 ) + return( ret ); + } + else /* DECRYPT */ + { + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); + if( ret != 0 ) + return( ret ); + } + + return( 0 ); +} + +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ) +{ + int ret; + unsigned char len_block[16]; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( mac != NULL ); + + if( ctx->state == CHACHAPOLY_STATE_INIT ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + if( ctx->state == CHACHAPOLY_STATE_AAD ) + { + ret = chachapoly_pad_aad( ctx ); + if( ret != 0 ) + return( ret ); + } + else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT ) + { + ret = chachapoly_pad_ciphertext( ctx ); + if( ret != 0 ) + return( ret ); + } + + ctx->state = CHACHAPOLY_STATE_FINISHED; + + /* The lengths of the AAD and ciphertext are processed by + * Poly1305 as the final 128-bit block, encoded as little-endian integers. + */ + len_block[ 0] = (unsigned char)( ctx->aad_len ); + len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 ); + len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 ); + len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 ); + len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 ); + len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 ); + len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 ); + len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 ); + len_block[ 8] = (unsigned char)( ctx->ciphertext_len ); + len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 ); + len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 ); + len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 ); + len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 ); + len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 ); + len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 ); + len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 ); + + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac ); + + return( ret ); +} + +static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx, + mbedtls_chachapoly_mode_t mode, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ) +{ + int ret; + + ret = mbedtls_chachapoly_starts( ctx, nonce, mode ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_update( ctx, length, input, output ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_finish( ctx, tag ); + +cleanup: + return( ret ); +} + +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ) +{ + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + CHACHAPOLY_VALIDATE_RET( tag != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); + + return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, + length, nonce, aad, aad_len, + input, output, tag ) ); +} + +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret; + unsigned char check_tag[16]; + size_t i; + int diff; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + CHACHAPOLY_VALIDATE_RET( tag != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); + + if( ( ret = chachapoly_crypt_and_tag( ctx, + MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce, + aad, aad_len, input, output, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < sizeof( check_tag ); i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_CHACHAPOLY_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_key[1][32] = +{ + { + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f + } +}; + +static const unsigned char test_nonce[1][12] = +{ + { + 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */ + } +}; + +static const unsigned char test_aad[1][12] = +{ + { + 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7 + } +}; + +static const size_t test_aad_len[1] = +{ + 12U +}; + +static const unsigned char test_input[1][114] = +{ + { + 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, + 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, + 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, + 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, + 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, + 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, + 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, + 0x74, 0x2e + } +}; + +static const unsigned char test_output[1][114] = +{ + { + 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, + 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, + 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, + 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, + 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, + 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, + 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, + 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, + 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, + 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, + 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, + 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, + 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, + 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, + 0x61, 0x16 + } +}; + +static const size_t test_input_len[1] = +{ + 114U +}; + +static const unsigned char test_mac[1][16] = +{ + { + 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, + 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 + } +}; + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_chachapoly_self_test( int verbose ) +{ + mbedtls_chachapoly_context ctx; + unsigned i; + int ret; + unsigned char output[200]; + unsigned char mac[16]; + + for( i = 0U; i < 1U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ChaCha20-Poly1305 test %u ", i ); + + mbedtls_chachapoly_init( &ctx ); + + ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] ); + ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) ); + + ret = mbedtls_chachapoly_encrypt_and_tag( &ctx, + test_input_len[i], + test_nonce[i], + test_aad[i], + test_aad_len[i], + test_input[i], + output, + mac ); + + ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ), + ( "failure (wrong output)\n" ) ); + + ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), + ( "failure (wrong MAC)\n" ) ); + + mbedtls_chachapoly_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CHACHAPOLY_C */ diff --git a/external/mbedtls/library/cipher.c b/external/mbedtls/library/cipher.c new file mode 100644 index 0000000..57da0b9 --- /dev/null +++ b/external/mbedtls/library/cipher.c @@ -0,0 +1,1183 @@ +/** + * \file cipher.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CIPHER_C) + +#include "mbedtls/cipher.h" +#include "mbedtls/cipher_internal.h" +#include "mbedtls/platform_util.h" + +#include +#include + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define CIPHER_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ) +#define CIPHER_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/* Compare the contents of two buffers in constant time. + * Returns 0 if the contents are bitwise identical, otherwise returns + * a non-zero value. + * This is currently only used by GCM and ChaCha20+Poly1305. + */ +static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len ) +{ + const unsigned char *p1 = (const unsigned char*) v1; + const unsigned char *p2 = (const unsigned char*) v2; + size_t i; + unsigned char diff; + + for( diff = 0, i = 0; i < len; i++ ) + diff |= p1[i] ^ p2[i]; + + return( (int)diff ); +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +static int supported_init = 0; + +const int *mbedtls_cipher_list( void ) +{ + const mbedtls_cipher_definition_t *def; + int *type; + + if( ! supported_init ) + { + def = mbedtls_cipher_definitions; + type = mbedtls_cipher_supported; + + while( def->type != 0 ) + *type++ = (*def++).type; + + *type = 0; + + supported_init = 1; + } + + return( mbedtls_cipher_supported ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->type == cipher_type ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ) +{ + const mbedtls_cipher_definition_t *def; + + if( NULL == cipher_name ) + return( NULL ); + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( ! strcmp( def->info->name, cipher_name ) ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->info->base->cipher == cipher_id && + def->info->key_bitlen == (unsigned) key_bitlen && + def->info->mode == mode ) + return( def->info ); + + return( NULL ); +} + +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) +{ + CIPHER_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); +} + +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_CMAC_C) + if( ctx->cmac_ctx ) + { + mbedtls_platform_zeroize( ctx->cmac_ctx, + sizeof( mbedtls_cmac_context_t ) ); + mbedtls_free( ctx->cmac_ctx ); + } +#endif + + if( ctx->cipher_ctx ) + ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); + + mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); +} + +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); + + if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cipher_info = cipher_info; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /* + * Ignore possible errors caused by a cipher mode that doesn't use padding + */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); +#else + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); +#endif +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + + return( 0 ); +} + +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, + const unsigned char *key, + int key_bitlen, + const mbedtls_operation_t operation ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( key != NULL ); + CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT || + operation == MBEDTLS_DECRYPT ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && + (int) ctx->cipher_info->key_bitlen != key_bitlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ctx->key_bitlen = key_bitlen; + ctx->operation = operation; + + /* + * For OFB, CFB and CTR mode always use the encryption key schedule + */ + if( MBEDTLS_ENCRYPT == operation || + MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) + { + return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, + ctx->key_bitlen ) ); + } + + if( MBEDTLS_DECRYPT == operation ) + return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, + ctx->key_bitlen ) ); + + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +} + +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, + size_t iv_len ) +{ + size_t actual_iv_size; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* avoid buffer overflow in ctx->iv */ + if( iv_len > MBEDTLS_MAX_IV_LENGTH ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) + actual_iv_size = iv_len; + else + { + actual_iv_size = ctx->cipher_info->iv_size; + + /* avoid reading past the end of input buffer */ + if( actual_iv_size > iv_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_CHACHA20_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) + { + if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, + iv, + 0U ) ) /* Initial counter value */ + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + } +#endif + + if ( actual_iv_size != 0 ) + { + memcpy( ctx->iv, iv, actual_iv_size ); + ctx->iv_size = actual_iv_size; + } + + return( 0 ); +} + +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + ctx->unprocessed_len = 0; + + return( 0 ); +} + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, + ctx->iv, ctx->iv_size, ad, ad_len ) ); + } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int result; + mbedtls_chachapoly_mode_t mode; + + mode = ( ctx->operation == MBEDTLS_ENCRYPT ) + ? MBEDTLS_CHACHAPOLY_ENCRYPT + : MBEDTLS_CHACHAPOLY_DECRYPT; + + result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ctx->iv, + mode ); + if ( result != 0 ) + return( result ); + + return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ad, ad_len ) ); + } +#endif + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ) +{ + int ret; + size_t block_size; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *olen = 0; + block_size = mbedtls_cipher_get_block_size( ctx ); + if ( 0 == block_size ) + { + return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); + } + + if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) + { + if( ilen != block_size ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + *olen = ilen; + + if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, + ctx->operation, input, output ) ) ) + { + return( ret ); + } + + return( 0 ); + } + +#if defined(MBEDTLS_GCM_C) + if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) + { + *olen = ilen; + return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, + output ) ); + } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) + { + *olen = ilen; + return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ilen, input, output ) ); + } +#endif + + if( input == output && + ( ctx->unprocessed_len != 0 || ilen % block_size ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) + { + size_t copy_len = 0; + + /* + * If there is not enough data for a full block, cache it. + */ + if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && + ilen <= block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && + ilen < block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_ENCRYPT && + ilen < block_size - ctx->unprocessed_len ) ) + { + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + ilen ); + + ctx->unprocessed_len += ilen; + return( 0 ); + } + + /* + * Process cached data first + */ + if( 0 != ctx->unprocessed_len ) + { + copy_len = block_size - ctx->unprocessed_len; + + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + copy_len ); + + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, block_size, ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + *olen += block_size; + output += block_size; + ctx->unprocessed_len = 0; + + input += copy_len; + ilen -= copy_len; + } + + /* + * Cache final, incomplete block + */ + if( 0 != ilen ) + { + /* Encryption: only cache partial blocks + * Decryption w/ padding: always keep at least one whole block + * Decryption w/o padding: only cache partial blocks + */ + copy_len = ilen % block_size; + if( copy_len == 0 && + ctx->operation == MBEDTLS_DECRYPT && + NULL != ctx->add_padding) + { + copy_len = block_size; + } + + memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), + copy_len ); + + ctx->unprocessed_len += copy_len; + ilen -= copy_len; + } + + /* + * Process remaining full blocks + */ + if( ilen ) + { + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen += ilen; + } + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, + ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, + input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) + { + if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, + ctx->unprocessed_data, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS ) + { + if( ctx->unprocessed_len > 0 ) { + /* We can only process an entire data unit at a time. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ); + if( ret != 0 ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) + { + if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, + ilen, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_STREAM */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) +/* + * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len + */ +static void add_pkcs_padding( unsigned char *output, size_t output_len, + size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i; + + for( i = 0; i < padding_len; i++ ) + output[data_len + i] = (unsigned char) padding_len; +} + +static int get_pkcs_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len, + * so pick input_len, which is usually 8 or 16 (one block) */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len; i++ ) + bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ + +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) +/* + * One and zeros padding: fill with 80 00 ... 00 + */ +static void add_one_and_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + output[data_len] = 0x80; + for( i = 1; i < padding_len; i++ ) + output[data_len + i] = 0x00; +} + +static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done, bad; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + bad = 0x80; + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i - 1] != 0 ); + *data_len |= ( i - 1 ) * ( done != prev_done ); + bad ^= input[i - 1] * ( done != prev_done ); + } + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); + +} +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) +/* + * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length + */ +static void add_zeros_and_len_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + for( i = 1; i < padding_len; i++ ) + output[data_len + i - 1] = 0x00; + output[output_len - 1] = (unsigned char) padding_len; +} + +static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len - 1; i++ ) + bad |= input[i] * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) +/* + * Zero padding: fill with 00 ... 00 + */ +static void add_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t i; + + for( i = data_len; i < output_len; i++ ) + output[i] = 0x00; +} + +static int get_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i-1] != 0 ); + *data_len |= i * ( done != prev_done ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ + +/* + * No padding: don't pad :) + * + * There is no add_padding function (check for NULL in mbedtls_cipher_finish) + * but a trivial get_padding function + */ +static int get_no_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = input_len; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *olen = 0; + + if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode || + MBEDTLS_MODE_GCM == ctx->cipher_info->mode || + MBEDTLS_MODE_XTS == ctx->cipher_info->mode || + MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) + { + return( 0 ); + } + + if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) || + ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) ) + { + return( 0 ); + } + + if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) + { + if( ctx->unprocessed_len != 0 ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) + { + int ret = 0; + + if( MBEDTLS_ENCRYPT == ctx->operation ) + { + /* check for 'no padding' mode */ + if( NULL == ctx->add_padding ) + { + if( 0 != ctx->unprocessed_len ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + + ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), + ctx->unprocessed_len ); + } + else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) + { + /* + * For decrypt operations, expect a full block, + * or an empty block if no padding + */ + if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) + return( 0 ); + + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + } + + /* cipher block */ + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + /* Set output size for decryption */ + if( MBEDTLS_DECRYPT == ctx->operation ) + return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), + olen ) ); + + /* Set output size for encryption */ + *olen = mbedtls_cipher_get_block_size( ctx ); + return( 0 ); + } +#else + ((void) output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, + mbedtls_cipher_padding_t mode ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + + if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + switch( mode ) + { +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + case MBEDTLS_PADDING_PKCS7: + ctx->add_padding = add_pkcs_padding; + ctx->get_padding = get_pkcs_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + case MBEDTLS_PADDING_ONE_AND_ZEROS: + ctx->add_padding = add_one_and_zeros_padding; + ctx->get_padding = get_one_and_zeros_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + case MBEDTLS_PADDING_ZEROS_AND_LEN: + ctx->add_padding = add_zeros_and_len_padding; + ctx->get_padding = get_zeros_and_len_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + case MBEDTLS_PADDING_ZEROS: + ctx->add_padding = add_zeros_padding; + ctx->get_padding = get_zeros_padding; + break; +#endif + case MBEDTLS_PADDING_NONE: + ctx->add_padding = NULL; + ctx->get_padding = get_no_padding; + break; + + default: + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_ENCRYPT != ctx->operation ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, + tag, tag_len ) ); +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != 16U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + tag ) ); + } +#endif + + return( 0 ); +} + +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ) +{ + unsigned char check_tag[16]; + int ret; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_DECRYPT != ctx->operation ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + if( tag_len > sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, + check_tag, tag_len ) ) ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + + return( 0 ); + } +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + check_tag ); + if ( ret != 0 ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + + return( 0 ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/* + * Packet-oriented wrapper for non-AEAD modes + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ) +{ + int ret; + size_t finish_olen; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + + if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 ) + return( ret ); + + *olen += finish_olen; + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/* + * Packet-oriented encryption for AEAD modes + */ +int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen, + iv, iv_len, ad, ad_len, input, output, + tag_len, tag ) ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, input, output, + tag, tag_len ) ); + } +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx, + ilen, iv, ad, ad_len, input, output, tag ) ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +/* + * Packet-oriented decryption for AEAD modes + */ +int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + tag, tag_len, input, output ); + + if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + input, output, tag, tag_len ); + + if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int ret; + + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen, + iv, ad, ad_len, tag, input, output ); + + if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#endif /* MBEDTLS_CIPHER_C */ diff --git a/external/mbedtls/library/cipher_wrap.c b/external/mbedtls/library/cipher_wrap.c new file mode 100644 index 0000000..5973ca6 --- /dev/null +++ b/external/mbedtls/library/cipher_wrap.c @@ -0,0 +1,2297 @@ +/** + * \file cipher_wrap.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CIPHER_C) + +#include "mbedtls/cipher_internal.h" + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_GCM_C) +/* shared by all GCM ciphers */ +static void *gcm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_gcm_context ) ); + + if( ctx != NULL ) + mbedtls_gcm_init( (mbedtls_gcm_context *) ctx ); + + return( ctx ); +} + +static void gcm_ctx_free( void *ctx ) +{ + mbedtls_gcm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +/* shared by all CCM ciphers */ +static void *ccm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ccm_context ) ); + + if( ctx != NULL ) + mbedtls_ccm_init( (mbedtls_ccm_context *) ctx ); + + return( ctx ); +} + +static void ccm_ctx_free( void *ctx ) +{ + mbedtls_ccm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_AES_C) + +static int aes_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ecb( (mbedtls_aes_context *) ctx, operation, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aes_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cbc( (mbedtls_aes_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cfb128( (mbedtls_aes_context *) ctx, operation, length, iv_off, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static int aes_crypt_ofb_wrap( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ofb( (mbedtls_aes_context *) ctx, length, iv_off, + iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ctr( (mbedtls_aes_context *) ctx, length, nc_off, nonce_counter, + stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int aes_crypt_xts_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + int mode; + + switch( operation ) + { + case MBEDTLS_ENCRYPT: + mode = MBEDTLS_AES_ENCRYPT; + break; + case MBEDTLS_DECRYPT: + mode = MBEDTLS_AES_DECRYPT; + break; + default: + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } + + return mbedtls_aes_crypt_xts( xts_ctx, mode, length, + data_unit, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_dec( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_enc( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static void * aes_ctx_alloc( void ) +{ + mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) ); + + if( aes == NULL ) + return( NULL ); + + mbedtls_aes_init( aes ); + + return( aes ); +} + +static void aes_ctx_free( void *ctx ) +{ + mbedtls_aes_free( (mbedtls_aes_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t aes_info = { + MBEDTLS_CIPHER_ID_AES, + aes_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aes_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aes_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + aes_crypt_ofb_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aes_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aes_setkey_enc_wrap, + aes_setkey_dec_wrap, + aes_ctx_alloc, + aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_ecb_info = { + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "AES-128-ECB", + 0, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ecb_info = { + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "AES-192-ECB", + 0, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ecb_info = { + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "AES-256-ECB", + 0, + 0, + 16, + &aes_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aes_128_cbc_info = { + MBEDTLS_CIPHER_AES_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "AES-128-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cbc_info = { + MBEDTLS_CIPHER_AES_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "AES-192-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cbc_info = { + MBEDTLS_CIPHER_AES_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "AES-256-CBC", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aes_128_cfb128_info = { + MBEDTLS_CIPHER_AES_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "AES-128-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cfb128_info = { + MBEDTLS_CIPHER_AES_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "AES-192-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cfb128_info = { + MBEDTLS_CIPHER_AES_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "AES-256-CFB128", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static const mbedtls_cipher_info_t aes_128_ofb_info = { + MBEDTLS_CIPHER_AES_128_OFB, + MBEDTLS_MODE_OFB, + 128, + "AES-128-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ofb_info = { + MBEDTLS_CIPHER_AES_192_OFB, + MBEDTLS_MODE_OFB, + 192, + "AES-192-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ofb_info = { + MBEDTLS_CIPHER_AES_256_OFB, + MBEDTLS_MODE_OFB, + 256, + "AES-256-OFB", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aes_128_ctr_info = { + MBEDTLS_CIPHER_AES_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "AES-128-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ctr_info = { + MBEDTLS_CIPHER_AES_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "AES-192-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ctr_info = { + MBEDTLS_CIPHER_AES_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "AES-256-CTR", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int xts_aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_enc( xts_ctx, key, key_bitlen ) ); +} + +static int xts_aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_dec( xts_ctx, key, key_bitlen ) ); +} + +static void *xts_aes_ctx_alloc( void ) +{ + mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc( 1, sizeof( *xts_ctx ) ); + + if( xts_ctx != NULL ) + mbedtls_aes_xts_init( xts_ctx ); + + return( xts_ctx ); +} + +static void xts_aes_ctx_free( void *ctx ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + + if( xts_ctx == NULL ) + return; + + mbedtls_aes_xts_free( xts_ctx ); + mbedtls_free( xts_ctx ); +} + +static const mbedtls_cipher_base_t xts_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + aes_crypt_xts_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + xts_aes_setkey_enc_wrap, + xts_aes_setkey_dec_wrap, + xts_aes_ctx_alloc, + xts_aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_xts_info = { + MBEDTLS_CIPHER_AES_128_XTS, + MBEDTLS_MODE_XTS, + 256, + "AES-128-XTS", + 16, + 0, + 16, + &xts_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_xts_info = { + MBEDTLS_CIPHER_AES_256_XTS, + MBEDTLS_MODE_XTS, + 512, + "AES-256-XTS", + 16, + 0, + 16, + &xts_aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aes_setkey_wrap, + gcm_aes_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_gcm_info = { + MBEDTLS_CIPHER_AES_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "AES-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_gcm_info = { + MBEDTLS_CIPHER_AES_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "AES-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_gcm_info = { + MBEDTLS_CIPHER_AES_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "AES-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aes_setkey_wrap, + ccm_aes_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_ccm_info = { + MBEDTLS_CIPHER_AES_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "AES-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ccm_info = { + MBEDTLS_CIPHER_AES_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "AES-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ccm_info = { + MBEDTLS_CIPHER_AES_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "AES-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + +static int camellia_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ecb( (mbedtls_camellia_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int camellia_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cbc( (mbedtls_camellia_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int camellia_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cfb128( (mbedtls_camellia_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ctr( (mbedtls_camellia_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_dec( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_enc( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static void * camellia_ctx_alloc( void ) +{ + mbedtls_camellia_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_camellia_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_camellia_init( ctx ); + + return( ctx ); +} + +static void camellia_ctx_free( void *ctx ) +{ + mbedtls_camellia_free( (mbedtls_camellia_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + camellia_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + camellia_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + camellia_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + camellia_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + camellia_setkey_enc_wrap, + camellia_setkey_dec_wrap, + camellia_ctx_alloc, + camellia_ctx_free +}; + +static const mbedtls_cipher_info_t camellia_128_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "CAMELLIA-128-ECB", + 0, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "CAMELLIA-192-ECB", + 0, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "CAMELLIA-256-ECB", + 0, + 0, + 16, + &camellia_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t camellia_128_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "CAMELLIA-128-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "CAMELLIA-192-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "CAMELLIA-256-CBC", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t camellia_128_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "CAMELLIA-128-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "CAMELLIA-192-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "CAMELLIA-256-CFB128", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t camellia_128_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "CAMELLIA-128-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "CAMELLIA-192-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "CAMELLIA-256-CTR", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_camellia_setkey_wrap, + gcm_camellia_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "CAMELLIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "CAMELLIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "CAMELLIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_camellia_setkey_wrap, + ccm_camellia_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "CAMELLIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "CAMELLIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "CAMELLIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_ARIA_C) + +static int aria_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + (void) operation; + return mbedtls_aria_crypt_ecb( (mbedtls_aria_context *) ctx, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aria_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_cbc( (mbedtls_aria_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aria_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_cfb128( (mbedtls_aria_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aria_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_ctr( (mbedtls_aria_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int aria_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aria_setkey_dec( (mbedtls_aria_context *) ctx, key, key_bitlen ); +} + +static int aria_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aria_setkey_enc( (mbedtls_aria_context *) ctx, key, key_bitlen ); +} + +static void * aria_ctx_alloc( void ) +{ + mbedtls_aria_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_aria_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_aria_init( ctx ); + + return( ctx ); +} + +static void aria_ctx_free( void *ctx ) +{ + mbedtls_aria_free( (mbedtls_aria_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + aria_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aria_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aria_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aria_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aria_setkey_enc_wrap, + aria_setkey_dec_wrap, + aria_ctx_alloc, + aria_ctx_free +}; + +static const mbedtls_cipher_info_t aria_128_ecb_info = { + MBEDTLS_CIPHER_ARIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "ARIA-128-ECB", + 0, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ecb_info = { + MBEDTLS_CIPHER_ARIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "ARIA-192-ECB", + 0, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ecb_info = { + MBEDTLS_CIPHER_ARIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "ARIA-256-ECB", + 0, + 0, + 16, + &aria_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aria_128_cbc_info = { + MBEDTLS_CIPHER_ARIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "ARIA-128-CBC", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_cbc_info = { + MBEDTLS_CIPHER_ARIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "ARIA-192-CBC", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_cbc_info = { + MBEDTLS_CIPHER_ARIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "ARIA-256-CBC", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aria_128_cfb128_info = { + MBEDTLS_CIPHER_ARIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "ARIA-128-CFB128", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_cfb128_info = { + MBEDTLS_CIPHER_ARIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "ARIA-192-CFB128", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_cfb128_info = { + MBEDTLS_CIPHER_ARIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "ARIA-256-CFB128", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aria_128_ctr_info = { + MBEDTLS_CIPHER_ARIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "ARIA-128-CTR", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ctr_info = { + MBEDTLS_CIPHER_ARIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "ARIA-192-CTR", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ctr_info = { + MBEDTLS_CIPHER_ARIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "ARIA-256-CTR", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aria_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aria_setkey_wrap, + gcm_aria_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aria_128_gcm_info = { + MBEDTLS_CIPHER_ARIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "ARIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_gcm_info = { + MBEDTLS_CIPHER_ARIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "ARIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_gcm_info = { + MBEDTLS_CIPHER_ARIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "ARIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aria_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aria_setkey_wrap, + ccm_aria_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aria_128_ccm_info = { + MBEDTLS_CIPHER_ARIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "ARIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ccm_info = { + MBEDTLS_CIPHER_ARIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "ARIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ccm_info = { + MBEDTLS_CIPHER_ARIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "ARIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_DES_C) + +static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des_crypt_ecb( (mbedtls_des_context *) ctx, input, output ); +} + +static int des3_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des3_crypt_ecb( (mbedtls_des3_context *) ctx, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des_crypt_cbc( (mbedtls_des_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des3_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des3_crypt_cbc( (mbedtls_des3_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_dec( (mbedtls_des_context *) ctx, key ); +} + +static int des_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_enc( (mbedtls_des_context *) ctx, key ); +} + +static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static void * des_ctx_alloc( void ) +{ + mbedtls_des_context *des = mbedtls_calloc( 1, sizeof( mbedtls_des_context ) ); + + if( des == NULL ) + return( NULL ); + + mbedtls_des_init( des ); + + return( des ); +} + +static void des_ctx_free( void *ctx ) +{ + mbedtls_des_free( (mbedtls_des_context *) ctx ); + mbedtls_free( ctx ); +} + +static void * des3_ctx_alloc( void ) +{ + mbedtls_des3_context *des3; + des3 = mbedtls_calloc( 1, sizeof( mbedtls_des3_context ) ); + + if( des3 == NULL ) + return( NULL ); + + mbedtls_des3_init( des3 ); + + return( des3 ); +} + +static void des3_ctx_free( void *ctx ) +{ + mbedtls_des3_free( (mbedtls_des3_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t des_info = { + MBEDTLS_CIPHER_ID_DES, + des_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des_setkey_enc_wrap, + des_setkey_dec_wrap, + des_ctx_alloc, + des_ctx_free +}; + +static const mbedtls_cipher_info_t des_ecb_info = { + MBEDTLS_CIPHER_DES_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES, + "DES-ECB", + 0, + 0, + 8, + &des_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_cbc_info = { + MBEDTLS_CIPHER_DES_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES, + "DES-CBC", + 8, + 0, + 8, + &des_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede_info = { + MBEDTLS_CIPHER_ID_DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set2key_enc_wrap, + des3_set2key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede_ecb_info = { + MBEDTLS_CIPHER_DES_EDE_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-ECB", + 0, + 0, + 8, + &des_ede_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede_cbc_info = { + MBEDTLS_CIPHER_DES_EDE_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-CBC", + 8, + 0, + 8, + &des_ede_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede3_info = { + MBEDTLS_CIPHER_ID_3DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set3key_enc_wrap, + des3_set3key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede3_ecb_info = { + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-ECB", + 0, + 0, + 8, + &des_ede3_info +}; +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede3_cbc_info = { + MBEDTLS_CIPHER_DES_EDE3_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-CBC", + 8, + 0, + 8, + &des_ede3_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + +static int blowfish_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_ecb( (mbedtls_blowfish_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int blowfish_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, const unsigned char *input, + unsigned char *output ) +{ + return mbedtls_blowfish_crypt_cbc( (mbedtls_blowfish_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int blowfish_crypt_cfb64_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_cfb64( (mbedtls_blowfish_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_ctr( (mbedtls_blowfish_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_blowfish_setkey( (mbedtls_blowfish_context *) ctx, key, key_bitlen ); +} + +static void * blowfish_ctx_alloc( void ) +{ + mbedtls_blowfish_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_blowfish_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_blowfish_init( ctx ); + + return( ctx ); +} + +static void blowfish_ctx_free( void *ctx ) +{ + mbedtls_blowfish_free( (mbedtls_blowfish_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t blowfish_info = { + MBEDTLS_CIPHER_ID_BLOWFISH, + blowfish_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + blowfish_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + blowfish_crypt_cfb64_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + blowfish_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + blowfish_setkey_wrap, + blowfish_setkey_wrap, + blowfish_ctx_alloc, + blowfish_ctx_free +}; + +static const mbedtls_cipher_info_t blowfish_ecb_info = { + MBEDTLS_CIPHER_BLOWFISH_ECB, + MBEDTLS_MODE_ECB, + 128, + "BLOWFISH-ECB", + 0, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t blowfish_cbc_info = { + MBEDTLS_CIPHER_BLOWFISH_CBC, + MBEDTLS_MODE_CBC, + 128, + "BLOWFISH-CBC", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t blowfish_cfb64_info = { + MBEDTLS_CIPHER_BLOWFISH_CFB64, + MBEDTLS_MODE_CFB, + 128, + "BLOWFISH-CFB64", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t blowfish_ctr_info = { + MBEDTLS_CIPHER_BLOWFISH_CTR, + MBEDTLS_MODE_CTR, + 128, + "BLOWFISH-CTR", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_ARC4_C) +static int arc4_crypt_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + return( mbedtls_arc4_crypt( (mbedtls_arc4_context *) ctx, length, input, output ) ); +} + +static int arc4_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + /* we get key_bitlen in bits, arc4 expects it in bytes */ + if( key_bitlen % 8 != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_arc4_setup( (mbedtls_arc4_context *) ctx, key, key_bitlen / 8 ); + return( 0 ); +} + +static void * arc4_ctx_alloc( void ) +{ + mbedtls_arc4_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_arc4_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_arc4_init( ctx ); + + return( ctx ); +} + +static void arc4_ctx_free( void *ctx ) +{ + mbedtls_arc4_free( (mbedtls_arc4_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t arc4_base_info = { + MBEDTLS_CIPHER_ID_ARC4, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + arc4_crypt_stream_wrap, +#endif + arc4_setkey_wrap, + arc4_setkey_wrap, + arc4_ctx_alloc, + arc4_ctx_free +}; + +static const mbedtls_cipher_info_t arc4_128_info = { + MBEDTLS_CIPHER_ARC4_128, + MBEDTLS_MODE_STREAM, + 128, + "ARC4-128", + 0, + 0, + 1, + &arc4_base_info +}; +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CHACHA20_C) + +static int chacha20_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chacha20_setkey( (mbedtls_chacha20_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static int chacha20_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + + ret = mbedtls_chacha20_update( ctx, length, input, output ); + if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( ret ); +} + +static void * chacha20_ctx_alloc( void ) +{ + mbedtls_chacha20_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chacha20_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chacha20_init( ctx ); + + return( ctx ); +} + +static void chacha20_ctx_free( void *ctx ) +{ + mbedtls_chacha20_free( (mbedtls_chacha20_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chacha20_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + chacha20_stream_wrap, +#endif + chacha20_setkey_wrap, + chacha20_setkey_wrap, + chacha20_ctx_alloc, + chacha20_ctx_free +}; +static const mbedtls_cipher_info_t chacha20_info = { + MBEDTLS_CIPHER_CHACHA20, + MBEDTLS_MODE_STREAM, + 256, + "CHACHA20", + 12, + 0, + 1, + &chacha20_base_info +}; +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + +static int chachapoly_setkey_wrap( void *ctx, + const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static void * chachapoly_ctx_alloc( void ) +{ + mbedtls_chachapoly_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chachapoly_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chachapoly_init( ctx ); + + return( ctx ); +} + +static void chachapoly_ctx_free( void *ctx ) +{ + mbedtls_chachapoly_free( (mbedtls_chachapoly_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chachapoly_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + chachapoly_setkey_wrap, + chachapoly_setkey_wrap, + chachapoly_ctx_alloc, + chachapoly_ctx_free +}; +static const mbedtls_cipher_info_t chachapoly_info = { + MBEDTLS_CIPHER_CHACHA20_POLY1305, + MBEDTLS_MODE_CHACHAPOLY, + 256, + "CHACHA20-POLY1305", + 12, + 0, + 1, + &chachapoly_base_info +}; +#endif /* MBEDTLS_CHACHAPOLY_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +static int null_crypt_stream( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + ((void) ctx); + memmove( output, input, length ); + return( 0 ); +} + +static int null_setkey( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) ctx); + ((void) key); + ((void) key_bitlen); + + return( 0 ); +} + +static void * null_ctx_alloc( void ) +{ + return( (void *) 1 ); +} + +static void null_ctx_free( void *ctx ) +{ + ((void) ctx); +} + +static const mbedtls_cipher_base_t null_base_info = { + MBEDTLS_CIPHER_ID_NULL, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + null_crypt_stream, +#endif + null_setkey, + null_setkey, + null_ctx_alloc, + null_ctx_free +}; + +static const mbedtls_cipher_info_t null_cipher_info = { + MBEDTLS_CIPHER_NULL, + MBEDTLS_MODE_STREAM, + 0, + "NULL", + 0, + 0, + 1, + &null_base_info +}; +#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ + +const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = +{ +#if defined(MBEDTLS_AES_C) + { MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info }, + { MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info }, + { MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_AES_128_CBC, &aes_128_cbc_info }, + { MBEDTLS_CIPHER_AES_192_CBC, &aes_192_cbc_info }, + { MBEDTLS_CIPHER_AES_256_CBC, &aes_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, + { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, + { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + { MBEDTLS_CIPHER_AES_128_OFB, &aes_128_ofb_info }, + { MBEDTLS_CIPHER_AES_192_OFB, &aes_192_ofb_info }, + { MBEDTLS_CIPHER_AES_256_OFB, &aes_256_ofb_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, + { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, + { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { MBEDTLS_CIPHER_AES_128_XTS, &aes_128_xts_info }, + { MBEDTLS_CIPHER_AES_256_XTS, &aes_256_xts_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, + { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, + { MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_AES_128_CCM, &aes_128_ccm_info }, + { MBEDTLS_CIPHER_AES_192_CCM, &aes_192_ccm_info }, + { MBEDTLS_CIPHER_AES_256_CCM, &aes_256_ccm_info }, +#endif +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + { MBEDTLS_CIPHER_ARC4_128, &arc4_128_info }, +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + { MBEDTLS_CIPHER_BLOWFISH_ECB, &blowfish_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_BLOWFISH_CBC, &blowfish_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_BLOWFISH_CFB64, &blowfish_cfb64_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_BLOWFISH_CTR, &blowfish_ctr_info }, +#endif +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + { MBEDTLS_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, +#endif +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_ARIA_C) + { MBEDTLS_CIPHER_ARIA_128_ECB, &aria_128_ecb_info }, + { MBEDTLS_CIPHER_ARIA_192_ECB, &aria_192_ecb_info }, + { MBEDTLS_CIPHER_ARIA_256_ECB, &aria_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_ARIA_128_CBC, &aria_128_cbc_info }, + { MBEDTLS_CIPHER_ARIA_192_CBC, &aria_192_cbc_info }, + { MBEDTLS_CIPHER_ARIA_256_CBC, &aria_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_ARIA_128_CFB128, &aria_128_cfb128_info }, + { MBEDTLS_CIPHER_ARIA_192_CFB128, &aria_192_cfb128_info }, + { MBEDTLS_CIPHER_ARIA_256_CFB128, &aria_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_ARIA_128_CTR, &aria_128_ctr_info }, + { MBEDTLS_CIPHER_ARIA_192_CTR, &aria_192_ctr_info }, + { MBEDTLS_CIPHER_ARIA_256_CTR, &aria_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_ARIA_128_GCM, &aria_128_gcm_info }, + { MBEDTLS_CIPHER_ARIA_192_GCM, &aria_192_gcm_info }, + { MBEDTLS_CIPHER_ARIA_256_GCM, &aria_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_ARIA_128_CCM, &aria_128_ccm_info }, + { MBEDTLS_CIPHER_ARIA_192_CCM, &aria_192_ccm_info }, + { MBEDTLS_CIPHER_ARIA_256_CCM, &aria_256_ccm_info }, +#endif +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_DES_C) + { MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_DES_CBC, &des_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, +#endif +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_CHACHA20_C) + { MBEDTLS_CIPHER_CHACHA20, &chacha20_info }, +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + { MBEDTLS_CIPHER_CHACHA20_POLY1305, &chachapoly_info }, +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + { MBEDTLS_CIPHER_NULL, &null_cipher_info }, +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + + { MBEDTLS_CIPHER_NONE, NULL } +}; + +#define NUM_CIPHERS sizeof mbedtls_cipher_definitions / sizeof mbedtls_cipher_definitions[0] +int mbedtls_cipher_supported[NUM_CIPHERS]; + +#endif /* MBEDTLS_CIPHER_C */ diff --git a/external/mbedtls/library/cmac.c b/external/mbedtls/library/cmac.c new file mode 100644 index 0000000..409f679 --- /dev/null +++ b/external/mbedtls/library/cmac.c @@ -0,0 +1,1103 @@ +/** + * \file cmac.c + * + * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * References: + * + * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The + * CMAC Mode for Authentication + * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf + * + * - RFC 4493 - The AES-CMAC Algorithm + * https://tools.ietf.org/html/rfc4493 + * + * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message + * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128) + * Algorithm for the Internet Key Exchange Protocol (IKE) + * https://tools.ietf.org/html/rfc4615 + * + * Additional test vectors: ISO/IEC 9797-1 + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CMAC_C) + +#include "mbedtls/cmac.h" +#include "mbedtls/platform_util.h" + +#include + + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#if defined(MBEDTLS_SELF_TEST) +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST */ +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) + +/* + * Multiplication by u in the Galois field of GF(2^n) + * + * As explained in NIST SP 800-38B, this can be computed: + * + * If MSB(p) = 0, then p = (p << 1) + * If MSB(p) = 1, then p = (p << 1) ^ R_n + * with R_64 = 0x1B and R_128 = 0x87 + * + * Input and output MUST NOT point to the same buffer + * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES. + */ +static int cmac_multiply_by_u( unsigned char *output, + const unsigned char *input, + size_t blocksize ) +{ + const unsigned char R_128 = 0x87; + const unsigned char R_64 = 0x1B; + unsigned char R_n, mask; + unsigned char overflow = 0x00; + int i; + + if( blocksize == MBEDTLS_AES_BLOCK_SIZE ) + { + R_n = R_128; + } + else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE ) + { + R_n = R_64; + } + else + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + for( i = (int)blocksize - 1; i >= 0; i-- ) + { + output[i] = input[i] << 1 | overflow; + overflow = input[i] >> 7; + } + + /* mask = ( input[0] >> 7 ) ? 0xff : 0x00 + * using bit operations to avoid branches */ + + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( input[0] >> 7 ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + output[ blocksize - 1 ] ^= R_n & mask; + + return( 0 ); +} + +/* + * Generate subkeys + * + * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm + */ +static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, + unsigned char* K1, unsigned char* K2 ) +{ + int ret; + unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; + size_t olen, block_size; + + mbedtls_platform_zeroize( L, sizeof( L ) ); + + block_size = ctx->cipher_info->block_size; + + /* Calculate Ek(0) */ + if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 ) + goto exit; + + /* + * Generate K1 and K2 + */ + if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 ) + goto exit; + + if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( L, sizeof( L ) ); + + return( ret ); +} +#endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */ + +#if !defined(MBEDTLS_CMAC_ALT) +static void cmac_xor_block( unsigned char *output, const unsigned char *input1, + const unsigned char *input2, + const size_t block_size ) +{ + size_t idx; + + for( idx = 0; idx < block_size; idx++ ) + output[ idx ] = input1[ idx ] ^ input2[ idx ]; +} + +/* + * Create padded last block from (partial) last block. + * + * We can't use the padding option from the cipher layer, as it only works for + * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. + */ +static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX], + size_t padded_block_len, + const unsigned char *last_block, + size_t last_block_len ) +{ + size_t j; + + for( j = 0; j < padded_block_len; j++ ) + { + if( j < last_block_len ) + padded_block[j] = last_block[j]; + else if( j == last_block_len ) + padded_block[j] = 0x80; + else + padded_block[j] = 0x00; + } +} + +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ) +{ + mbedtls_cipher_type_t type; + mbedtls_cmac_context_t *cmac_ctx; + int retval; + + if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + return( retval ); + + type = ctx->cipher_info->type; + + switch( type ) + { + case MBEDTLS_CIPHER_AES_128_ECB: + case MBEDTLS_CIPHER_AES_192_ECB: + case MBEDTLS_CIPHER_AES_256_ECB: + case MBEDTLS_CIPHER_DES_EDE3_ECB: + break; + default: + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* Allocated and initialise in the cipher context memory for the CMAC + * context */ + cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) ); + if( cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cmac_ctx = cmac_ctx; + + mbedtls_platform_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); + + return 0; +} + +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state; + int ret = 0; + size_t n, j, olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || + ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = ctx->cmac_ctx->state; + + /* Is there data still to process from the last call, that's greater in + * size than a block? */ + if( cmac_ctx->unprocessed_len > 0 && + ilen > block_size - cmac_ctx->unprocessed_len ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + block_size - cmac_ctx->unprocessed_len ); + + cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + input += block_size - cmac_ctx->unprocessed_len; + ilen -= block_size - cmac_ctx->unprocessed_len; + cmac_ctx->unprocessed_len = 0; + } + + /* n is the number of blocks including any final partial block */ + n = ( ilen + block_size - 1 ) / block_size; + + /* Iterate across the input data in block sized chunks, excluding any + * final partial or complete block */ + for( j = 1; j < n; j++ ) + { + cmac_xor_block( state, input, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + goto exit; + + ilen -= block_size; + input += block_size; + } + + /* If there is data left over that wasn't aligned to a block */ + if( ilen > 0 ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + ilen ); + cmac_ctx->unprocessed_len += ilen; + } + +exit: + return( ret ); +} + +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state, *last_block; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX]; + int ret; + size_t olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL || + output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = cmac_ctx->state; + + mbedtls_platform_zeroize( K1, sizeof( K1 ) ); + mbedtls_platform_zeroize( K2, sizeof( K2 ) ); + cmac_generate_subkeys( ctx, K1, K2 ); + + last_block = cmac_ctx->unprocessed_block; + + /* Calculate last block */ + if( cmac_ctx->unprocessed_len < block_size ) + { + cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len ); + cmac_xor_block( M_last, M_last, K2, block_size ); + } + else + { + /* Last block is complete block */ + cmac_xor_block( M_last, last_block, K1, block_size ); + } + + + cmac_xor_block( state, M_last, state, block_size ); + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + memcpy( output, state, block_size ); + +exit: + /* Wipe the generated keys on the stack, and any other transients to avoid + * side channel leakage */ + mbedtls_platform_zeroize( K1, sizeof( K1 ) ); + mbedtls_platform_zeroize( K2, sizeof( K2 ) ); + + cmac_ctx->unprocessed_len = 0; + mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + + mbedtls_platform_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); + return( ret ); +} + +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) +{ + mbedtls_cmac_context_t* cmac_ctx; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + + /* Reset the internal state */ + cmac_ctx->unprocessed_len = 0; + mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + mbedtls_platform_zeroize( cmac_ctx->state, + sizeof( cmac_ctx->state ) ); + + return( 0 ); +} + +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_cipher_context_t ctx; + int ret; + + if( cipher_info == NULL || key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_update( &ctx, input, ilen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_finish( &ctx, output ); + +exit: + mbedtls_cipher_free( &ctx ); + + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +/* + * Implementation of AES-CMAC-PRF-128 defined in RFC 4615 + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, + const unsigned char *input, size_t in_len, + unsigned char output[16] ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE]; + unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE]; + + if( key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + if( key_length == MBEDTLS_AES_BLOCK_SIZE ) + { + /* Use key as is */ + memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE ); + } + else + { + memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE ); + + ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key, + key_length, int_key ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len, + output ); + +exit: + mbedtls_platform_zeroize( int_key, sizeof( int_key ) ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* !MBEDTLS_CMAC_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * CMAC test data for SP800-38B + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf + * + * AES-CMAC-PRF-128 test data from RFC 4615 + * https://tools.ietf.org/html/rfc4615#page-4 + */ + +#define NB_CMAC_TESTS_PER_KEY 4 +#define NB_PRF_TESTS 3 + +#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) +/* All CMAC test inputs are truncated from the same 64 byte buffer. */ +static const unsigned char test_message[] = { + /* PT */ + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 +}; +#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* Truncation point of message for AES CMAC tests */ +static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + /* Mlen */ + 0, + 16, + 20, + 64 +}; + +/* CMAC-AES128 Test Data */ +static const unsigned char aes_128_key[16] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; +static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, + 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde + }, + { + /* K2 */ + 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, + 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b + } +}; +static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 + }, + { + /* Example #2 */ + 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c + }, + { + /* Example #3 */ + 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8, + 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde + }, + { + /* Example #4 */ + 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe + } +}; + +/* CMAC-AES192 Test Data */ +static const unsigned char aes_192_key[24] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b +}; +static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, + 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 + }, + { + /* K2 */ + 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, + 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c + } +}; +static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, + 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 + }, + { + /* Example #2 */ + 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, + 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 + }, + { + /* Example #3 */ + 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04, + 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8 + }, + { + /* Example #4 */ + 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, + 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 + } +}; + +/* CMAC-AES256 Test Data */ +static const unsigned char aes_256_key[32] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 +}; +static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, + 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f + }, + { + /* K2 */ + 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, + 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 + } +}; +static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, + 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 + }, + { + /* Example #2 */ + 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, + 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c + }, + { + /* Example #3 */ + 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a, + 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93 + }, + { + /* Example #4 */ + 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, + 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 + } +}; +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) +/* Truncation point of message for 3DES CMAC tests */ +static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + 0, + 16, + 20, + 32 +}; + +/* CMAC-TDES (Generation) - 2 Key Test Data */ +static const unsigned char des3_2key_key[24] = { + /* Key1 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + /* Key2 */ + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01, + /* Key3 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef +}; +static const unsigned char des3_2key_subkeys[2][8] = { + { + /* K1 */ + 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9 + }, + { + /* K2 */ + 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2 + } +}; +static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + /* Sample #1 */ + 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60 + }, + { + /* Sample #2 */ + 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b + }, + { + /* Sample #3 */ + 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69 + }, + { + /* Sample #4 */ + 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb + } +}; + +/* CMAC-TDES (Generation) - 3 Key Test Data */ +static const unsigned char des3_3key_key[24] = { + /* Key1 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef, + /* Key2 */ + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, + /* Key3 */ + 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 +}; +static const unsigned char des3_3key_subkeys[2][8] = { + { + /* K1 */ + 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0 + }, + { + /* K2 */ + 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b + } +}; +static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + /* Sample #1 */ + 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50 + }, + { + /* Sample #2 */ + 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09 + }, + { + /* Sample #3 */ + 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2 + }, + { + /* Sample #4 */ + 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5 + } +}; + +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* AES AES-CMAC-PRF-128 Test Data */ +static const unsigned char PRFK[] = { + /* Key */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xed, 0xcb +}; + +/* Sizes in bytes */ +static const size_t PRFKlen[NB_PRF_TESTS] = { + 18, + 16, + 10 +}; + +/* Message */ +static const unsigned char PRFM[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char PRFT[NB_PRF_TESTS][16] = { + { + 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, + 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a + }, + { + 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, + 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d + }, + { + 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, + 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d + } +}; +#endif /* MBEDTLS_AES_C */ + +static int cmac_test_subkeys( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* subkeys, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + int i, ret = 0; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t *cipher_info; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + ret = cmac_generate_subkeys( &ctx, K1, K2 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 || + ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_cipher_free( &ctx ); + } + + ret = 0; + goto exit; + +cleanup: + mbedtls_cipher_free( &ctx ); + +exit: + return( ret ); +} + +static int cmac_test_wth_cipher( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* messages, + const unsigned int message_lengths[4], + const unsigned char* expected_result, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + const mbedtls_cipher_info_t *cipher_info; + int i, ret = 0; + unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 ); + + if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages, + message_lengths[i], output ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + ret = 0; + +exit: + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +static int test_aes128_cmac_prf( int verbose ) +{ + int i; + int ret; + unsigned char output[MBEDTLS_AES_BLOCK_SIZE]; + + for( i = 0; i < NB_PRF_TESTS; i++ ) + { + mbedtls_printf( " AES CMAC 128 PRF #%u: ", i ); + ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output ); + if( ret != 0 || + memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 ) + { + + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + else if( verbose != 0 ) + { + mbedtls_printf( "passed\n" ); + } + } + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +int mbedtls_cmac_self_test( int verbose ) +{ + int ret; + +#if defined(MBEDTLS_AES_C) + /* AES-128 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 128", + aes_128_key, + 128, + (const unsigned char*)aes_128_subkeys, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 128", + aes_128_key, + 128, + test_message, + aes_message_lengths, + (const unsigned char*)aes_128_expected_result, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-192 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 192", + aes_192_key, + 192, + (const unsigned char*)aes_192_subkeys, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 192", + aes_192_key, + 192, + test_message, + aes_message_lengths, + (const unsigned char*)aes_192_expected_result, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-256 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 256", + aes_256_key, + 256, + (const unsigned char*)aes_256_subkeys, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher ( verbose, + "AES 256", + aes_256_key, + 256, + test_message, + aes_message_lengths, + (const unsigned char*)aes_256_expected_result, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) + /* 3DES 2 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 2 key", + des3_2key_key, + 192, + (const unsigned char*)des3_2key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 2 key", + des3_2key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_2key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* 3DES 3 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 3 key", + des3_3key_key, + 192, + (const unsigned char*)des3_3key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 3 key", + des3_3key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_3key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_AES_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CMAC_C */ diff --git a/external/mbedtls/library/ctr_drbg.c b/external/mbedtls/library/ctr_drbg.c new file mode 100644 index 0000000..90264e8 --- /dev/null +++ b/external/mbedtls/library/ctr_drbg.c @@ -0,0 +1,756 @@ +/* + * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The NIST SP 800-90 DRBGs are described in the following publication. + * + * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) + +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +/* + * CTR_DRBG context initialization + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); + + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; +} + +/* + * This function resets CTR_DRBG context to the state immediately + * after initial call of mbedtls_ctr_drbg_init(). + */ +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + /* The mutex is initialized iff f_entropy is set. */ + if( ctx->f_entropy != NULL ) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_aes_free( &ctx->aes_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; +} + +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval ) +{ + ctx->reseed_interval = interval; +} + +static int block_cipher_df( unsigned char *output, + const unsigned char *data, size_t data_len ) +{ + unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + unsigned char *p, *iv; + mbedtls_aes_context aes_ctx; + int ret = 0; + + int i, j; + size_t buf_len, use_len; + + if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); + mbedtls_aes_init( &aes_ctx ); + + /* + * Construct IV (16 bytes) and S in buffer + * IV = Counter (in 32-bits) padded to 16 with zeroes + * S = Length input string (in 32-bits) || Length of output (in 32-bits) || + * data || 0x80 + * (Total is padded to a multiple of 16-bytes with zeroes) + */ + p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; + *p++ = ( data_len >> 24 ) & 0xff; + *p++ = ( data_len >> 16 ) & 0xff; + *p++ = ( data_len >> 8 ) & 0xff; + *p++ = ( data_len ) & 0xff; + p += 3; + *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; + memcpy( p, data, data_len ); + p[data_len] = 0x80; + + buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; + + for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) + key[i] = i; + + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + + /* + * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data + */ + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + p = buf; + memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + use_len = buf_len; + + while( use_len > 0 ) + { + for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) + chain[i] ^= p[i]; + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? + MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; + + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 ) + { + goto exit; + } + } + + memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + + /* + * Update IV + */ + buf[3]++; + } + + /* + * Do final encryption with reduced data + */ + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; + p = output; + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 ) + { + goto exit; + } + memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } +exit: + mbedtls_aes_free( &aes_ctx ); + /* + * tidy up the stack + */ + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( chain, sizeof( chain ) ); + if( 0 != ret ) + { + /* + * wipe partial seed from memory + */ + mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); + } + + return( ret ); +} + +/* CTR_DRBG_Update (SP 800-90A §10.2.1.2) + * ctr_drbg_update_internal(ctx, provided_data) + * implements + * CTR_DRBG_Update(provided_data, Key, V) + * with inputs and outputs + * ctx->aes_ctx = Key + * ctx->counter = V + */ +static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, + const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) +{ + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = tmp; + int i, j; + int ret = 0; + + memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 ) + goto exit; + + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } + + for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) + tmp[i] ^= data[i]; + + /* + * Update key and counter + */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + goto exit; + memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + +exit: + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + return( ret ); +} + +/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) + * mbedtls_ctr_drbg_update(ctx, additional, add_len) + * implements + * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, + * security_strength) -> initial_working_state + * with inputs + * ctx->counter = all-bits-0 + * ctx->aes_ctx = context from all-bits-0 key + * additional[:add_len] = entropy_input || nonce || personalization_string + * and with outputs + * ctx = initial_working_state + */ +int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + int ret; + + if( add_len == 0 ) + return( 0 ); + + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + goto exit; + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + /* MAX_INPUT would be more logical here, but we have to match + * block_cipher_df()'s limits since we can't propagate errors */ + if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; + (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) + * mbedtls_ctr_drbg_reseed(ctx, additional, len) + * implements + * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) + * -> new_working_state + * with inputs + * ctx contains working_state + * additional[:len] = additional_input + * and entropy_input comes from calling ctx->f_entropy + * and with output + * ctx contains new_working_state + */ +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; + size_t seedlen = 0; + int ret; + + if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT || + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); + + /* + * Gather entropy_len bytes of entropy to seed state + */ + if( 0 != ctx->f_entropy( ctx->p_entropy, seed, + ctx->entropy_len ) ) + { + return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + } + + seedlen += ctx->entropy_len; + + /* + * Add additional data + */ + if( additional && len ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* + * Reduce to 384 bits + */ + if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) + goto exit; + + /* + * Update state + */ + if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) + goto exit; + ctx->reseed_counter = 1; + +exit: + mbedtls_platform_zeroize( seed, sizeof( seed ) ); + return( ret ); +} + +/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) + * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) + * implements + * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, + * security_strength) -> initial_working_state + * with inputs + * custom[:len] = nonce || personalization_string + * where entropy_input comes from f_entropy for ctx->entropy_len bytes + * and with outputs + * ctx = initial_working_state + */ +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + int ret; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + + memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); + + /* The mutex is initialized iff f_entropy is set. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + mbedtls_aes_init( &ctx->aes_ctx ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + if( ctx->entropy_len == 0 ) + ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; + + /* + * Initialize with an empty key + */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +/* Backward compatibility wrapper */ +int mbedtls_ctr_drbg_seed_entropy_len( + mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, + const unsigned char *custom, size_t len, + size_t entropy_len ) +{ + mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len ); + return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) ); +} + +/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) + * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) + * implements + * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) + * -> working_state_after_reseed + * if required, then + * CTR_DRBG_Generate(working_state_after_reseed, + * requested_number_of_bits, additional_input) + * -> status, returned_bits, new_working_state + * with inputs + * ctx contains working_state + * requested_number_of_bits = 8 * output_len + * additional[:add_len] = additional_input + * and entropy_input comes from calling ctx->f_entropy + * and with outputs + * status = SUCCESS (this function does the reseed internally) + * returned_bits = output[:output_len] + * ctx contains new_working_state + */ +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ) +{ + int ret = 0; + mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = output; + unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + int i; + size_t use_len; + + if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) + return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); + + if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + if( ctx->reseed_counter > ctx->reseed_interval || + ctx->prediction_resistance ) + { + if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + { + return( ret ); + } + add_len = 0; + } + + if( add_len > 0 ) + { + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + goto exit; + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + } + + while( output_len > 0 ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 ) + goto exit; + + use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : + output_len; + /* + * Copy random block to destination + */ + memcpy( p, tmp, use_len ); + p += use_len; + output_len -= use_len; + } + + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + + ctx->reseed_counter++; + +exit: + mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + return( ret ); +} + +int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) +{ + int ret; + mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + FILE *f; + unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + + if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT ) + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + else + ret = 0; + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + fclose( f ); + return( ret ); +} + +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) +{ + int ret = 0; + FILE *f = NULL; + size_t n; + unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + unsigned char c; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + + n = fread( buf, 1, sizeof( buf ), f ); + if( fread( &c, 1, 1, f ) != 0 ) + { + ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; + goto exit; + } + if( n == 0 || ferror( f ) ) + { + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + goto exit; + } + fclose( f ); + f = NULL; + + ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n ); + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + if( f != NULL ) + fclose( f ); + if( ret != 0 ) + return( ret ); + return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char entropy_source_pr[96] = + { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16, + 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02, + 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b, + 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb, + 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9, + 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95, + 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63, + 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3, + 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31, + 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4, + 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56, + 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 }; + +static const unsigned char entropy_source_nopr[64] = + { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14, + 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe, + 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d, + 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20, + 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9, + 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46, + 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e, + 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e }; + +static const unsigned char nonce_pers_pr[16] = + { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2, + 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c }; + +static const unsigned char nonce_pers_nopr[16] = + { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5, + 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f }; + +static const unsigned char result_pr[16] = + { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f, + 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 }; + +static const unsigned char result_nopr[16] = + { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88, + 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f }; + +static size_t test_offset; +static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, + size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine + */ +int mbedtls_ctr_drbg_self_test( int verbose ) +{ + mbedtls_ctr_drbg_context ctx; + unsigned char buf[16]; + + mbedtls_ctr_drbg_init( &ctx ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = True) + */ + if( verbose != 0 ) + mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); + + test_offset = 0; + mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); + CHK( mbedtls_ctr_drbg_seed( &ctx, + ctr_drbg_self_test_entropy, + (void *) entropy_source_pr, + nonce_pers_pr, 16 ) ); + mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + + mbedtls_ctr_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = FALSE) + */ + if( verbose != 0 ) + mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); + + mbedtls_ctr_drbg_init( &ctx ); + + test_offset = 0; + mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); + CHK( mbedtls_ctr_drbg_seed( &ctx, + ctr_drbg_self_test_entropy, + (void *) entropy_source_nopr, + nonce_pers_nopr, 16 ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); + CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); + CHK( memcmp( buf, result_nopr, 16 ) ); + + mbedtls_ctr_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CTR_DRBG_C */ diff --git a/external/mbedtls/library/debug.c b/external/mbedtls/library/debug.c new file mode 100644 index 0000000..5f06d0d --- /dev/null +++ b/external/mbedtls/library/debug.c @@ -0,0 +1,475 @@ +/* + * Debugging routines + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_DEBUG_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#define mbedtls_time_t time_t +#define mbedtls_snprintf snprintf +#endif + +#include "mbedtls/debug.h" + +#include +#include +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define DEBUG_BUF_SIZE 512 + +static int debug_threshold = 0; + +void mbedtls_debug_set_threshold( int threshold ) +{ + debug_threshold = threshold; +} + +/* + * All calls to f_dbg must be made via this function + */ +static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *str ) +{ + /* + * If in a threaded environment, we need a thread identifier. + * Since there is no portable way to get one, use the address of the ssl + * context instead, as it shouldn't be shared between threads. + */ +#if defined(MBEDTLS_THREADING_C) + char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ + mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void*)ssl, str ); + ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr ); +#else + ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str ); +#endif +} + +void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ... ) +{ + va_list argp; + char str[DEBUG_BUF_SIZE]; + int ret; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + va_start( argp, format ); +#if defined(_WIN32) +#if defined(_TRUNCATE) && !defined(__MINGW32__) + ret = _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp ); +#else + ret = _vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); + if( ret < 0 || (size_t) ret == DEBUG_BUF_SIZE ) + { + str[DEBUG_BUF_SIZE-1] = '\0'; + ret = -1; + } +#endif +#else + ret = vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); +#endif + va_end( argp ); + + if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 ) + { + str[ret] = '\n'; + str[ret + 1] = '\0'; + } + + debug_send_line( ssl, level, file, line, str ); +} + +void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ) +{ + char str[DEBUG_BUF_SIZE]; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + /* + * With non-blocking I/O and examples that just retry immediately, + * the logs would be quickly flooded with WANT_READ, so ignore that. + * Don't ignore WANT_WRITE however, since is is usually rare. + */ + if( ret == MBEDTLS_ERR_SSL_WANT_READ ) + return; + + mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n", + text, ret, -ret ); + + debug_send_line( ssl, level, file, line, str ); +} + +void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len ) +{ + char str[DEBUG_BUF_SIZE]; + char txt[17]; + size_t i, idx = 0; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n", + text, (unsigned int) len ); + + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + memset( txt, 0, sizeof( txt ) ); + for( i = 0; i < len; i++ ) + { + if( i >= 4096 ) + break; + + if( i % 16 == 0 ) + { + if( i > 0 ) + { + mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + memset( txt, 0, sizeof( txt ) ); + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ", + (unsigned int) i ); + + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", + (unsigned int) buf[i] ); + txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ; + } + + if( len > 0 ) + { + for( /* i = i */; i % 16 != 0; i++ ) + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " " ); + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); + debug_send_line( ssl, level, file, line, str ); + } +} + +#if defined(MBEDTLS_ECP_C) +void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X ) +{ + char str[DEBUG_BUF_SIZE]; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + mbedtls_snprintf( str, sizeof( str ), "%s(X)", text ); + mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X ); + + mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text ); + mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_BIGNUM_C) +void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X ) +{ + char str[DEBUG_BUF_SIZE]; + int j, k, zeros = 1; + size_t i, n, idx = 0; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + NULL == X || + level > debug_threshold ) + { + return; + } + + for( n = X->n - 1; n > 0; n-- ) + if( X->p[n] != 0 ) + break; + + for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- ) + if( ( ( X->p[n] >> j ) & 1 ) != 0 ) + break; + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n", + text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) ); + + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + for( i = n + 1, j = 0; i > 0; i-- ) + { + if( zeros && X->p[i - 1] == 0 ) + continue; + + for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- ) + { + if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 ) + continue; + else + zeros = 0; + + if( j % 16 == 0 ) + { + if( j > 0 ) + { + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); + debug_send_line( ssl, level, file, line, str ); + idx = 0; + } + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int) + ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ); + + j++; + } + + } + + if( zeros == 1 ) + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" ); + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); + debug_send_line( ssl, level, file, line, str ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void debug_print_pk( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_pk_context *pk ) +{ + size_t i; + mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS]; + char name[16]; + + memset( items, 0, sizeof( items ) ); + + if( mbedtls_pk_debug( pk, items ) != 0 ) + { + debug_send_line( ssl, level, file, line, + "invalid PK context\n" ); + return; + } + + for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ ) + { + if( items[i].type == MBEDTLS_PK_DEBUG_NONE ) + return; + + mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name ); + name[sizeof( name ) - 1] = '\0'; + + if( items[i].type == MBEDTLS_PK_DEBUG_MPI ) + mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value ); + else +#if defined(MBEDTLS_ECP_C) + if( items[i].type == MBEDTLS_PK_DEBUG_ECP ) + mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value ); + else +#endif + debug_send_line( ssl, level, file, line, + "should not happen\n" ); + } +} + +static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text ) +{ + char str[DEBUG_BUF_SIZE]; + const char *start, *cur; + + start = text; + for( cur = text; *cur != '\0'; cur++ ) + { + if( *cur == '\n' ) + { + size_t len = cur - start + 1; + if( len > DEBUG_BUF_SIZE - 1 ) + len = DEBUG_BUF_SIZE - 1; + + memcpy( str, start, len ); + str[len] = '\0'; + + debug_send_line( ssl, level, file, line, str ); + + start = cur + 1; + } + } +} + +void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt ) +{ + char str[DEBUG_BUF_SIZE]; + int i = 0; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + NULL == crt || + level > debug_threshold ) + { + return; + } + + while( crt != NULL ) + { + char buf[1024]; + + mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i ); + debug_send_line( ssl, level, file, line, str ); + + mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); + debug_print_line_by_line( ssl, level, file, line, buf ); + + debug_print_pk( ssl, level, file, line, "crt->", &crt->pk ); + + crt = crt->next; + } +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_ECDH_C) +static void mbedtls_debug_printf_ecdh_internal( const mbedtls_ssl_context *ssl, + int level, const char *file, + int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + const mbedtls_ecdh_context* ctx = ecdh; +#else + const mbedtls_ecdh_context_mbed* ctx = &ecdh->ctx.mbed_ecdh; +#endif + + switch( attr ) + { + case MBEDTLS_DEBUG_ECDH_Q: + mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Q", + &ctx->Q ); + break; + case MBEDTLS_DEBUG_ECDH_QP: + mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Qp", + &ctx->Qp ); + break; + case MBEDTLS_DEBUG_ECDH_Z: + mbedtls_debug_print_mpi( ssl, level, file, line, "ECDH: z", + &ctx->z ); + break; + default: + break; + } +} + +void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, attr ); +#else + switch( ecdh->var ) + { + default: + mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, + attr ); + } +#endif +} +#endif /* MBEDTLS_ECDH_C */ + +#endif /* MBEDTLS_DEBUG_C */ diff --git a/external/mbedtls/library/des.c b/external/mbedtls/library/des.c new file mode 100644 index 0000000..623165d --- /dev/null +++ b/external/mbedtls/library/des.c @@ -0,0 +1,1089 @@ +/* + * FIPS-46-3 compliant Triple-DES implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * DES, on which TDES is based, was originally designed by Horst Feistel + * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). + * + * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_DES_C) + +#include "mbedtls/des.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_DES_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * Expanded DES S-boxes + */ +static const uint32_t SB1[64] = +{ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static const uint32_t SB2[64] = +{ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static const uint32_t SB3[64] = +{ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static const uint32_t SB4[64] = +{ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static const uint32_t SB5[64] = +{ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static const uint32_t SB6[64] = +{ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static const uint32_t SB7[64] = +{ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static const uint32_t SB8[64] = +{ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + +/* + * PC1: left and right halves bit-swap + */ +static const uint32_t LHs[16] = +{ + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static const uint32_t RHs[16] = +{ + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100, + 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + +/* + * Initial Permutation macro + */ +#define DES_IP(X,Y) \ + do \ + { \ + T = (((X) >> 4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T << 4); \ + T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \ + T = (((Y) >> 2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T << 2); \ + T = (((Y) >> 8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T << 8); \ + (Y) = (((Y) << 1) | ((Y) >> 31)) & 0xFFFFFFFF; \ + T = ((X) ^ (Y)) & 0xAAAAAAAA; (Y) ^= T; (X) ^= T; \ + (X) = (((X) << 1) | ((X) >> 31)) & 0xFFFFFFFF; \ + } while( 0 ) + +/* + * Final Permutation macro + */ +#define DES_FP(X,Y) \ + do \ + { \ + (X) = (((X) << 31) | ((X) >> 1)) & 0xFFFFFFFF; \ + T = ((X) ^ (Y)) & 0xAAAAAAAA; (X) ^= T; (Y) ^= T; \ + (Y) = (((Y) << 31) | ((Y) >> 1)) & 0xFFFFFFFF; \ + T = (((Y) >> 8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T << 8); \ + T = (((Y) >> 2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T << 2); \ + T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \ + T = (((X) >> 4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T << 4); \ + } while( 0 ) + +/* + * DES round macro + */ +#define DES_ROUND(X,Y) \ + do \ + { \ + T = *SK++ ^ (X); \ + (Y) ^= SB8[ (T ) & 0x3F ] ^ \ + SB6[ (T >> 8) & 0x3F ] ^ \ + SB4[ (T >> 16) & 0x3F ] ^ \ + SB2[ (T >> 24) & 0x3F ]; \ + \ + T = *SK++ ^ (((X) << 28) | ((X) >> 4)); \ + (Y) ^= SB7[ (T ) & 0x3F ] ^ \ + SB5[ (T >> 8) & 0x3F ] ^ \ + SB3[ (T >> 16) & 0x3F ] ^ \ + SB1[ (T >> 24) & 0x3F ]; \ + } while( 0 ) + +#define SWAP(a,b) \ + do \ + { \ + uint32_t t = (a); (a) = (b); (b) = t; t = 0; \ + } while( 0 ) + +void mbedtls_des_init( mbedtls_des_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_des_context ) ); +} + +void mbedtls_des_free( mbedtls_des_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des_context ) ); +} + +void mbedtls_des3_init( mbedtls_des3_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_des3_context ) ); +} + +void mbedtls_des3_free( mbedtls_des3_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des3_context ) ); +} + +static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, + 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, + 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, + 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, + 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, + 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, + 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, + 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, + 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, + 254 }; + +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + key[i] = odd_parity_table[key[i] / 2]; +} + +/* + * Check the given key's parity, returns 1 on failure, 0 on SUCCESS + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + if( key[i] != odd_parity_table[key[i] / 2] ) + return( 1 ); + + return( 0 ); +} + +/* + * Table of weak and semi-weak keys + * + * Source: http://en.wikipedia.org/wiki/Weak_key + * + * Weak: + * Alternating ones + zeros (0x0101010101010101) + * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) + * '0xE0E0E0E0F1F1F1F1' + * '0x1F1F1F1F0E0E0E0E' + * + * Semi-weak: + * 0x011F011F010E010E and 0x1F011F010E010E01 + * 0x01E001E001F101F1 and 0xE001E001F101F101 + * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 + * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E + * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E + * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 + * + */ + +#define WEAK_KEY_COUNT 16 + +static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = +{ + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, + { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, + { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, + + { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, + { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, + { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, + { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, + { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, + { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, + { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, + { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, + { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, + { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, + { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, + { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } +}; + +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < WEAK_KEY_COUNT; i++ ) + if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 ) + return( 1 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DES_SETKEY_ALT) +void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + uint32_t X, Y, T; + + GET_UINT32_BE( X, key, 0 ); + GET_UINT32_BE( Y, key, 4 ); + + /* + * Permuted Choice 1 + */ + T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); + T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); + + X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) + | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) + | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) + | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); + + Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) + | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) + | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) + | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); + + X &= 0x0FFFFFFF; + Y &= 0x0FFFFFFF; + + /* + * calculate subkeys + */ + for( i = 0; i < 16; i++ ) + { + if( i < 2 || i == 8 || i == 15 ) + { + X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; + Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; + } + else + { + X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; + Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; + } + + *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) + | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) + | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) + | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) + | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) + | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) + | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) + | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) + | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) + | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) + | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); + + *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) + | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) + | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) + | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) + | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) + | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) + | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) + | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) + | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) + | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) + | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); + } +} +#endif /* !MBEDTLS_DES_SETKEY_ALT */ + +/* + * DES key schedule (56-bit, encryption) + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + mbedtls_des_setkey( ctx->sk, key ); + + return( 0 ); +} + +/* + * DES key schedule (56-bit, decryption) + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + mbedtls_des_setkey( ctx->sk, key ); + + for( i = 0; i < 16; i += 2 ) + { + SWAP( ctx->sk[i ], ctx->sk[30 - i] ); + SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); + } + + return( 0 ); +} + +static void des3_set2key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] ) +{ + int i; + + mbedtls_des_setkey( esk, key ); + mbedtls_des_setkey( dsk + 32, key + 8 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[30 - i]; + dsk[i + 1] = esk[31 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + esk[i + 64] = esk[i ]; + esk[i + 65] = esk[i + 1]; + + dsk[i + 64] = dsk[i ]; + dsk[i + 65] = dsk[i + 1]; + } +} + +/* + * Triple-DES key schedule (112-bit, encryption) + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( ctx->sk, sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (112-bit, decryption) + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( sk, ctx->sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +static void des3_set3key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[24] ) +{ + int i; + + mbedtls_des_setkey( esk, key ); + mbedtls_des_setkey( dsk + 32, key + 8 ); + mbedtls_des_setkey( esk + 64, key + 16 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[94 - i]; + dsk[i + 1] = esk[95 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + dsk[i + 64] = esk[30 - i]; + dsk[i + 65] = esk[31 - i]; + } +} + +/* + * Triple-DES key schedule (168-bit, encryption) + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( ctx->sk, sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (168-bit, decryption) + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( sk, ctx->sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * DES-ECB block encryption/decryption + */ +#if !defined(MBEDTLS_DES_CRYPT_ECB_ALT) +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + GET_UINT32_BE( X, input, 0 ); + GET_UINT32_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_UINT32_BE( Y, output, 0 ); + PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} +#endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * DES-CBC buffer encryption/decryption + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_des_crypt_ecb( ctx, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* MBEDTLS_DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_des_crypt_ecb( ctx, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * 3DES-ECB block encryption/decryption + */ +#if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT) +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + GET_UINT32_BE( X, input, 0 ); + GET_UINT32_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( X, Y ); + DES_ROUND( Y, X ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_UINT32_BE( Y, output, 0 ); + PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} +#endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * 3DES-CBC buffer encryption/decryption + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_des3_crypt_ecb( ctx, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* MBEDTLS_DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_des3_crypt_ecb( ctx, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#endif /* !MBEDTLS_DES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * DES and 3DES test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip + */ +static const unsigned char des3_test_keys[24] = +{ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, + 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 +}; + +static const unsigned char des3_test_buf[8] = +{ + 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 +}; + +static const unsigned char des3_test_ecb_dec[3][8] = +{ + { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D }, + { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB }, + { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A } +}; + +static const unsigned char des3_test_ecb_enc[3][8] = +{ + { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B }, + { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 }, + { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char des3_test_iv[8] = +{ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, +}; + +static const unsigned char des3_test_cbc_dec[3][8] = +{ + { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 }, + { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 }, + { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C } +}; + +static const unsigned char des3_test_cbc_enc[3][8] = +{ + { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 }, + { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D }, + { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * Checkup routine + */ +int mbedtls_des_self_test( int verbose ) +{ + int i, j, u, v, ret = 0; + mbedtls_des_context ctx; + mbedtls_des3_context ctx3; + unsigned char buf[8]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[8]; + unsigned char iv[8]; +#endif + + mbedtls_des_init( &ctx ); + mbedtls_des3_init( &ctx3 ); + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " DES%c-ECB-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + mbedtls_des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + mbedtls_des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + + for( j = 0; j < 10000; j++ ) + { + if( u == 0 ) + mbedtls_des_crypt_ecb( &ctx, buf, buf ); + else + mbedtls_des3_crypt_ecb( &ctx3, buf, buf ); + } + + if( ( v == MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) || + ( v != MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " DES%c-CBC-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, des3_test_iv, 8 ); + memcpy( prv, des3_test_iv, 8 ); + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + mbedtls_des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + mbedtls_des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + + if( v == MBEDTLS_DES_DECRYPT ) + { + for( j = 0; j < 10000; j++ ) + { + if( u == 0 ) + mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + } + } + else + { + for( j = 0; j < 10000; j++ ) + { + unsigned char tmp[8]; + + if( u == 0 ) + mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + + memcpy( tmp, prv, 8 ); + memcpy( prv, buf, 8 ); + memcpy( buf, tmp, 8 ); + } + + memcpy( buf, prv, 8 ); + } + + if( ( v == MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) || + ( v != MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_des_free( &ctx ); + mbedtls_des3_free( &ctx3 ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_DES_C */ diff --git a/external/mbedtls/library/dhm.c b/external/mbedtls/library/dhm.c new file mode 100644 index 0000000..d652cf0 --- /dev/null +++ b/external/mbedtls/library/dhm.c @@ -0,0 +1,765 @@ +/* + * Diffie-Hellman-Merkle key exchange + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The following sources were referenced in the design of this implementation + * of the Diffie-Hellman-Merkle algorithm: + * + * [1] Handbook of Applied Cryptography - 1997, Chapter 12 + * Menezes, van Oorschot and Vanstone + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_DHM_C) + +#include "mbedtls/dhm.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if !defined(MBEDTLS_DHM_ALT) + +#define DHM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA ) +#define DHM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * helper to validate the mbedtls_mpi size and import it + */ +static int dhm_read_bignum( mbedtls_mpi *X, + unsigned char **p, + const unsigned char *end ) +{ + int ret, n; + + if( end - *p < 2 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + n = ( (*p)[0] << 8 ) | (*p)[1]; + (*p) += 2; + + if( (int)( end - *p ) < n ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 ) + return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret ); + + (*p) += n; + + return( 0 ); +} + +/* + * Verify sanity of parameter with regards to P + * + * Parameter should be: 2 <= public_param <= P - 2 + * + * This means that we need to return an error if + * public_param < 2 or public_param > P-2 + * + * For more information on the attack, see: + * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf + * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 + */ +static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P ) +{ + mbedtls_mpi L, U; + int ret = 0; + + mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) ); + + if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 || + mbedtls_mpi_cmp_mpi( param, &U ) > 0 ) + { + ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; + } + +cleanup: + mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U ); + return( ret ); +} + +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) +{ + DHM_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); +} + +/* + * Parse the ServerKeyExchange parameters + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ) +{ + int ret; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( p != NULL && *p != NULL ); + DHM_VALIDATE_RET( end != NULL ); + + if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) + return( ret ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + ctx->len = mbedtls_mpi_size( &ctx->P ); + + return( 0 ); +} + +/* + * Setup and write the ServerKeyExchange parameters + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count = 0; + size_t n1, n2, n3; + unsigned char *p; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( olen != NULL ); + DHM_VALIDATE_RET( f_rng != NULL ); + + if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + /* + * Generate X as large as possible ( < P ) + */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ); + } + while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); + + /* + * Calculate GX = G^X mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, + &ctx->P , &ctx->RP ) ); + + if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) + return( ret ); + + /* + * export P, G, GX + */ +#define DHM_MPI_EXPORT( X, n ) \ + do { \ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \ + p + 2, \ + ( n ) ) ); \ + *p++ = (unsigned char)( ( n ) >> 8 ); \ + *p++ = (unsigned char)( ( n ) ); \ + p += ( n ); \ + } while( 0 ) + + n1 = mbedtls_mpi_size( &ctx->P ); + n2 = mbedtls_mpi_size( &ctx->G ); + n3 = mbedtls_mpi_size( &ctx->GX ); + + p = output; + DHM_MPI_EXPORT( &ctx->P , n1 ); + DHM_MPI_EXPORT( &ctx->G , n2 ); + DHM_MPI_EXPORT( &ctx->GX, n3 ); + + *olen = p - output; + + ctx->len = n1; + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret ); + + return( 0 ); +} + +/* + * Set prime modulus and generator + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ) +{ + int ret; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( P != NULL ); + DHM_VALIDATE_RET( G != NULL ); + + if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 ) + { + return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret ); + } + + ctx->len = mbedtls_mpi_size( &ctx->P ); + return( 0 ); +} + +/* + * Import the peer's public value G^Y + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ) +{ + int ret; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( input != NULL ); + + if( ilen < 1 || ilen > ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) + return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Create own private value X and export G^X + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count = 0; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( f_rng != NULL ); + + if( olen < 1 || olen > ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + /* + * generate X and calculate GX = G^X mod P + */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); + } + while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, + &ctx->P , &ctx->RP ) ); + + if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) + return( ret ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) ); + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Pick a random R in the range [2, M) for blinding purposes + */ +static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count; + + count = 0; + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 ); + +cleanup: + return( ret ); +} + + +/* + * Use the blinding method and optimisation suggested in section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int dhm_update_blinding( mbedtls_dhm_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_mpi R; + + mbedtls_mpi_init( &R ); + + /* + * Don't use any blinding the first time a particular X is used, + * but remember it to use blinding next time. + */ + if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) ); + + return( 0 ); + } + + /* + * Ok, we need blinding. Can we re-use existing values? + * If yes, just update them by squaring them. + */ + if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + + return( 0 ); + } + + /* + * We need to generate blinding values from scratch + */ + + /* Vi = random( 2, P-1 ) */ + MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) ); + + /* Vf = Vi^-X mod P + * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod), + * then elevate to the Xth power. */ + MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); + +cleanup: + mbedtls_mpi_free( &R ); + + return( ret ); +} + +/* + * Derive and export the shared secret (G^Y)^X mod P + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi GYb; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( olen != NULL ); + + if( output_size < ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + mbedtls_mpi_init( &GYb ); + + /* Blind peer's value */ + if( f_rng != NULL ) + { + MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); + } + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) ); + + /* Do modular exponentiation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X, + &ctx->P, &ctx->RP ) ); + + /* Unblind secret value */ + if( f_rng != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); + } + + *olen = mbedtls_mpi_size( &ctx->K ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) ); + +cleanup: + mbedtls_mpi_free( &GYb ); + + if( ret != 0 ) + return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret ); + + return( 0 ); +} + +/* + * Free the components of a DHM key + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->pX ); + mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->K ); + mbedtls_mpi_free( &ctx->GY ); + mbedtls_mpi_free( &ctx->GX ); + mbedtls_mpi_free( &ctx->X ); + mbedtls_mpi_free( &ctx->G ); + mbedtls_mpi_free( &ctx->P ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); +} + +#if defined(MBEDTLS_ASN1_PARSE_C) +/* + * Parse DHM parameters + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ) +{ + int ret; + size_t len; + unsigned char *p, *end; +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_context pem; +#endif /* MBEDTLS_PEM_PARSE_C */ + + DHM_VALIDATE_RET( dhm != NULL ); + DHM_VALIDATE_RET( dhmin != NULL ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN DH PARAMETERS-----", + "-----END DH PARAMETERS-----", + dhmin, NULL, 0, &dhminlen ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + dhminlen = pem.buflen; + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + goto exit; + + p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; +#else + p = (unsigned char *) dhmin; +#endif /* MBEDTLS_PEM_PARSE_C */ + end = p + dhminlen; + + /* + * DHParams ::= SEQUENCE { + * prime INTEGER, -- P + * generator INTEGER, -- g + * privateValueLength INTEGER OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + + if( p != end ) + { + /* This might be the optional privateValueLength. + * If so, we can cleanly discard it */ + mbedtls_mpi rec; + mbedtls_mpi_init( &rec ); + ret = mbedtls_asn1_get_mpi( &p, end, &rec ); + mbedtls_mpi_free( &rec ); + if ( ret != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + if ( p != end ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + goto exit; + } + } + + ret = 0; + + dhm->len = mbedtls_mpi_size( &dhm->P ); + +exit: +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_free( &pem ); +#endif + if( ret != 0 ) + mbedtls_dhm_free( dhm ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +static int load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_DHM_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + + mbedtls_platform_zeroize( *buf, *n + 1 ); + mbedtls_free( *buf ); + + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); +} + +/* + * Load and parse DHM parameters + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + DHM_VALIDATE_RET( dhm != NULL ); + DHM_VALIDATE_RET( path != NULL ); + + if( ( ret = load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ +#endif /* MBEDTLS_DHM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(MBEDTLS_PEM_PARSE_C) +static const char mbedtls_test_dhm_params[] = +"-----BEGIN DH PARAMETERS-----\r\n" +"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" +"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" +"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" +"-----END DH PARAMETERS-----\r\n"; +#else /* MBEDTLS_PEM_PARSE_C */ +static const char mbedtls_test_dhm_params[] = { + 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44, + 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d, + 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3, + 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1, + 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18, + 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a, + 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1, + 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6, + 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64, + 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8, + 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f, + 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 }; +#endif /* MBEDTLS_PEM_PARSE_C */ + +static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params ); + +/* + * Checkup routine + */ +int mbedtls_dhm_self_test( int verbose ) +{ + int ret; + mbedtls_dhm_context dhm; + + mbedtls_dhm_init( &dhm ); + + if( verbose != 0 ) + mbedtls_printf( " DHM parameter load: " ); + + if( ( ret = mbedtls_dhm_parse_dhm( &dhm, + (const unsigned char *) mbedtls_test_dhm_params, + mbedtls_test_dhm_params_len ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n" ); + +exit: + mbedtls_dhm_free( &dhm ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_DHM_C */ diff --git a/external/mbedtls/library/ecdh.c b/external/mbedtls/library/ecdh.c new file mode 100644 index 0000000..8c27e4e --- /dev/null +++ b/external/mbedtls/library/ecdh.c @@ -0,0 +1,701 @@ +/* + * Elliptic curve Diffie-Hellman + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * RFC 4492 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECDH_C) + +#include "mbedtls/ecdh.h" +#include "mbedtls/platform_util.h" + +#include + +/* Parameter validation macros based on platform_util.h */ +#define ECDH_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECDH_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; +#endif + +static mbedtls_ecp_group_id mbedtls_ecdh_grp_id( + const mbedtls_ecdh_context *ctx ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ctx->grp.id ); +#else + return( ctx->grp_id ); +#endif +} + +#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) +/* + * Generate public key (restartable version) + * + * Note: this internal function relies on its caller preserving the value of + * the output parameter 'd' across continuation calls. This would not be + * acceptable for a public function but is OK here as we control call sites. + */ +static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + + /* If multiplication is in progress, we already generated a privkey */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx == NULL || rs_ctx->rsm == NULL ) +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G, + f_rng, p_rng, rs_ctx ) ); + +cleanup: + return( ret ); +} + +/* + * Generate public key + */ +int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDH_VALIDATE_RET( grp != NULL ); + ECDH_VALIDATE_RET( d != NULL ); + ECDH_VALIDATE_RET( Q != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */ + +#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) +/* + * Compute shared secret (SEC1 3.3.1) + */ +static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + mbedtls_ecp_point P; + + mbedtls_ecp_point_init( &P ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q, + f_rng, p_rng, rs_ctx ) ); + + if( mbedtls_ecp_is_zero( &P ) ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) ); + +cleanup: + mbedtls_ecp_point_free( &P ); + + return( ret ); +} + +/* + * Compute shared secret (SEC1 3.3.1) + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDH_VALIDATE_RET( grp != NULL ); + ECDH_VALIDATE_RET( Q != NULL ); + ECDH_VALIDATE_RET( d != NULL ); + ECDH_VALIDATE_RET( z != NULL ); + return( ecdh_compute_shared_restartable( grp, z, Q, d, + f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ + +static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx ) +{ + mbedtls_ecp_group_init( &ctx->grp ); + mbedtls_mpi_init( &ctx->d ); + mbedtls_ecp_point_init( &ctx->Q ); + mbedtls_ecp_point_init( &ctx->Qp ); + mbedtls_mpi_init( &ctx->z ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_init( &ctx->rs ); +#endif +} + +/* + * Initialize context + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) +{ + ECDH_VALIDATE( ctx != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + ecdh_init_internal( ctx ); + mbedtls_ecp_point_init( &ctx->Vi ); + mbedtls_ecp_point_init( &ctx->Vf ); + mbedtls_mpi_init( &ctx->_d ); +#else + memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); + + ctx->var = MBEDTLS_ECDH_VARIANT_NONE; +#endif + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; +#if defined(MBEDTLS_ECP_RESTARTABLE) + ctx->restart_enabled = 0; +#endif +} + +static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx, + mbedtls_ecp_group_id grp_id ) +{ + int ret; + + ret = mbedtls_ecp_group_load( &ctx->grp, grp_id ); + if( ret != 0 ) + { + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} + +/* + * Setup context + */ +int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_setup_internal( ctx, grp_id ) ); +#else + switch( grp_id ) + { + default: + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; + ctx->grp_id = grp_id; + ecdh_init_internal( &ctx->ctx.mbed_ecdh ); + return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) ); + } +#endif +} + +static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx ) +{ + mbedtls_ecp_group_free( &ctx->grp ); + mbedtls_mpi_free( &ctx->d ); + mbedtls_ecp_point_free( &ctx->Q ); + mbedtls_ecp_point_free( &ctx->Qp ); + mbedtls_mpi_free( &ctx->z ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_free( &ctx->rs ); +#endif +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Enable restartable operations for context + */ +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ) +{ + ECDH_VALIDATE( ctx != NULL ); + + ctx->restart_enabled = 1; +} +#endif + +/* + * Free context + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_ecp_point_free( &ctx->Vi ); + mbedtls_ecp_point_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->_d ); + ecdh_free_internal( ctx ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + ecdh_free_internal( &ctx->ctx.mbed_ecdh ); + break; + default: + break; + } + + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_NONE; + ctx->grp_id = MBEDTLS_ECP_DP_NONE; +#endif +} + +static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, int point_format, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret; + size_t grp_len, pt_len; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng, rs_ctx ) ) != 0 ) + return( ret ); +#else + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, + blen ) ) != 0 ) + return( ret ); + + buf += grp_len; + blen -= grp_len; + + if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, + &pt_len, buf, blen ) ) != 0 ) + return( ret ); + + *olen = grp_len + pt_len; + return( 0 ); +} + +/* + * Setup and write the ServerKeyExhange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen, + f_rng, p_rng, restart_enabled ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen, + ctx->point_format, buf, blen, + f_rng, p_rng, + restart_enabled ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx, + const unsigned char **buf, + const unsigned char *end ) +{ + return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, + end - *buf ) ); +} + +/* + * Read the ServerKeyExhange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, + const unsigned char *end ) +{ + int ret; + mbedtls_ecp_group_id grp_id; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( *buf != NULL ); + ECDH_VALIDATE_RET( end != NULL ); + + if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) ) + != 0 ) + return( ret ); + + if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_read_params_internal( ctx, buf, end ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh, + buf, end ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ) +{ + int ret; + + /* If it's not our key, just import the public part as Qp */ + if( side == MBEDTLS_ECDH_THEIRS ) + return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) ); + + /* Our key: import public (as Q) and private parts */ + if( side != MBEDTLS_ECDH_OURS ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Get parameters from a keypair + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ) +{ + int ret; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( key != NULL ); + ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS || + side == MBEDTLS_ECDH_THEIRS ); + + if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE ) + { + /* This is the first call to get_params(). Set up the context + * for use with the group. */ + if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 ) + return( ret ); + } + else + { + /* This is not the first call to get_params(). Check that the + * current key's group is the same as the context's, which was set + * from the first key's group. */ + if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_get_params_internal( ctx, key, side ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh, + key, side ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, int point_format, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng, rs_ctx ) ) != 0 ) + return( ret ); +#else + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen, + buf, blen ); +} + +/* + * Setup and export the client public value + */ +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen, + f_rng, p_rng, restart_enabled ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen, + ctx->point_format, buf, blen, + f_rng, p_rng, + restart_enabled ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx, + const unsigned char *buf, size_t blen ) +{ + int ret; + const unsigned char *p = buf; + + if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, + blen ) ) != 0 ) + return( ret ); + + if( (size_t)( p - buf ) != blen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Parse and import the client's public value + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_read_public_internal( ctx, buf, blen ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh, + buf, blen ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, unsigned char *buf, + size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx == NULL || ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp, + &ctx->d, f_rng, p_rng, + rs_ctx ) ) != 0 ) + { + return( ret ); + } +#else + if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, + &ctx->d, f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + if( mbedtls_mpi_size( &ctx->z ) > blen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); + return mbedtls_mpi_write_binary( &ctx->z, buf, *olen ); +} + +/* + * Derive and export the shared secret + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng, + restart_enabled ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf, + blen, f_rng, p_rng, + restart_enabled ) ); + default: + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } +#endif +} + +#endif /* MBEDTLS_ECDH_C */ diff --git a/external/mbedtls/library/ecdsa.c b/external/mbedtls/library/ecdsa.c new file mode 100644 index 0000000..2456238 --- /dev/null +++ b/external/mbedtls/library/ecdsa.c @@ -0,0 +1,1024 @@ +/* + * Elliptic curve DSA + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECDSA_C) + +#include "mbedtls/ecdsa.h" +#include "mbedtls/asn1write.h" + +#include + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#include "mbedtls/hmac_drbg.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/platform_util.h" + +/* Parameter validation macros based on platform_util.h */ +#define ECDSA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECDSA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/* + * Sub-context for ecdsa_verify() + */ +struct mbedtls_ecdsa_restart_ver +{ + mbedtls_mpi u1, u2; /* intermediate values */ + enum { /* what to do next? */ + ecdsa_ver_init = 0, /* getting started */ + ecdsa_ver_muladd, /* muladd step */ + } state; +}; + +/* + * Init verify restart sub-context + */ +static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx ) +{ + mbedtls_mpi_init( &ctx->u1 ); + mbedtls_mpi_init( &ctx->u2 ); + ctx->state = ecdsa_ver_init; +} + +/* + * Free the components of a verify restart sub-context + */ +static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->u1 ); + mbedtls_mpi_free( &ctx->u2 ); + + ecdsa_restart_ver_init( ctx ); +} + +/* + * Sub-context for ecdsa_sign() + */ +struct mbedtls_ecdsa_restart_sig +{ + int sign_tries; + int key_tries; + mbedtls_mpi k; /* per-signature random */ + mbedtls_mpi r; /* r value */ + enum { /* what to do next? */ + ecdsa_sig_init = 0, /* getting started */ + ecdsa_sig_mul, /* doing ecp_mul() */ + ecdsa_sig_modn, /* mod N computations */ + } state; +}; + +/* + * Init verify sign sub-context + */ +static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx ) +{ + ctx->sign_tries = 0; + ctx->key_tries = 0; + mbedtls_mpi_init( &ctx->k ); + mbedtls_mpi_init( &ctx->r ); + ctx->state = ecdsa_sig_init; +} + +/* + * Free the components of a sign restart sub-context + */ +static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->k ); + mbedtls_mpi_free( &ctx->r ); +} + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/* + * Sub-context for ecdsa_sign_det() + */ +struct mbedtls_ecdsa_restart_det +{ + mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */ + enum { /* what to do next? */ + ecdsa_det_init = 0, /* getting started */ + ecdsa_det_sign, /* make signature */ + } state; +}; + +/* + * Init verify sign_det sub-context + */ +static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx ) +{ + mbedtls_hmac_drbg_init( &ctx->rng_ctx ); + ctx->state = ecdsa_det_init; +} + +/* + * Free the components of a sign_det restart sub-context + */ +static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_hmac_drbg_free( &ctx->rng_ctx ); + + ecdsa_restart_det_init( ctx ); +} +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#define ECDSA_RS_ECP ( rs_ctx == NULL ? NULL : &rs_ctx->ecp ) + +/* Utility macro for checking and updating ops budget */ +#define ECDSA_BUDGET( ops ) \ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, ECDSA_RS_ECP, ops ) ); + +/* Call this when entering a function that needs its own sub-context */ +#define ECDSA_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) \ + rs_ctx->ecp.ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_is_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecdsa_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ +} while( 0 ) + +/* Call this when leaving a function that needs its own sub-context */ +#define ECDSA_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ + ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->ecp.depth--; \ +} while( 0 ) + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define ECDSA_RS_ECP NULL + +#define ECDSA_BUDGET( ops ) /* no-op; for compatibility */ + +#define ECDSA_RS_ENTER( SUB ) (void) rs_ctx +#define ECDSA_RS_LEAVE( SUB ) (void) rs_ctx + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \ + !defined(MBEDTLS_ECDSA_SIGN_ALT) || \ + !defined(MBEDTLS_ECDSA_VERIFY_ALT) +/* + * Derive a suitable integer for group grp from a buffer of length len + * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 + */ +static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x, + const unsigned char *buf, size_t blen ) +{ + int ret; + size_t n_size = ( grp->nbits + 7 ) / 8; + size_t use_size = blen > n_size ? n_size : blen; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) ); + if( use_size * 8 > grp->nbits ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) ); + + /* While at it, reduce modulo N */ + if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) ); + +cleanup: + return( ret ); +} +#endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */ + +#if !defined(MBEDTLS_ECDSA_SIGN_ALT) +/* + * Compute ECDSA signature of a hashed message (SEC1 4.1.3) + * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) + */ +static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret, key_tries, sign_tries; + int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries; + mbedtls_ecp_point R; + mbedtls_mpi k, e, t; + mbedtls_mpi *pk = &k, *pr = r; + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( grp->N.p == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* Make sure d is in range 1..n-1 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); + + ECDSA_RS_ENTER( sig ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + { + /* redirect to our context */ + p_sign_tries = &rs_ctx->sig->sign_tries; + p_key_tries = &rs_ctx->sig->key_tries; + pk = &rs_ctx->sig->k; + pr = &rs_ctx->sig->r; + + /* jump to current step */ + if( rs_ctx->sig->state == ecdsa_sig_mul ) + goto mul; + if( rs_ctx->sig->state == ecdsa_sig_modn ) + goto modn; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + *p_sign_tries = 0; + do + { + if( (*p_sign_tries)++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + + /* + * Steps 1-3: generate a suitable ephemeral keypair + * and set r = xR mod n + */ + *p_key_tries = 0; + do + { + if( (*p_key_tries)++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + rs_ctx->sig->state = ecdsa_sig_mul; + +mul: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G, + f_rng_blind, + p_rng_blind, + ECDSA_RS_ECP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) ); + } + while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + rs_ctx->sig->state = ecdsa_sig_modn; + +modn: +#endif + /* + * Accounting for everything up to the end of the loop + * (step 6, but checking now avoids saving e and t) + */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 ); + + /* + * Step 5: derive MPI from hashed message + */ + MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Generate a random value to blind inv_mod in next step, + * avoiding a potential timing leak. + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng_blind, + p_rng_blind ) ); + + /* + * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pk, pk, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); + } + while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + mbedtls_mpi_copy( r, pr ); +#endif + +cleanup: + mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); + + ECDSA_RS_LEAVE( sig ); + + return( ret ); +} + +/* + * Compute ECDSA signature of a hashed message + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( f_rng != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + /* Use the same RNG for both blinding and ephemeral key generation */ + return( ecdsa_sign_restartable( grp, r, s, d, buf, blen, + f_rng, p_rng, f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDSA_SIGN_ALT */ + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/* + * Deterministic signature wrapper + */ +static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret; + mbedtls_hmac_drbg_context rng_ctx; + mbedtls_hmac_drbg_context *p_rng = &rng_ctx; + unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; + size_t grp_len = ( grp->nbits + 7 ) / 8; + const mbedtls_md_info_t *md_info; + mbedtls_mpi h; + + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &h ); + mbedtls_hmac_drbg_init( &rng_ctx ); + + ECDSA_RS_ENTER( det ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->det != NULL ) + { + /* redirect to our context */ + p_rng = &rs_ctx->det->rng_ctx; + + /* jump to current step */ + if( rs_ctx->det->state == ecdsa_det_sign ) + goto sign; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); + MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); + mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->det != NULL ) + rs_ctx->det->state = ecdsa_det_sign; + +sign: +#endif +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng ); +#else + if( f_rng_blind != NULL ) + ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng, + f_rng_blind, p_rng_blind, rs_ctx ); + else + { + mbedtls_hmac_drbg_context *p_rng_blind_det; + +#if !defined(MBEDTLS_ECP_RESTARTABLE) + /* + * To avoid reusing rng_ctx and risking incorrect behavior we seed a + * second HMAC-DRBG with the same seed. We also apply a label to avoid + * reusing the bits of the ephemeral key for blinding and eliminate the + * risk that they leak this way. + */ + const char* blind_label = "BLINDING CONTEXT"; + mbedtls_hmac_drbg_context rng_ctx_blind; + + mbedtls_hmac_drbg_init( &rng_ctx_blind ); + p_rng_blind_det = &rng_ctx_blind; + + mbedtls_hmac_drbg_seed_buf( p_rng_blind_det, md_info, + data, 2 * grp_len ); + ret = mbedtls_hmac_drbg_update_ret( p_rng_blind_det, + (const unsigned char*) blind_label, + strlen( blind_label ) ); + if( ret != 0 ) + { + mbedtls_hmac_drbg_free( &rng_ctx_blind ); + goto cleanup; + } +#else + /* + * In the case of restartable computations we would either need to store + * the second RNG in the restart context too or set it up at every + * restart. The first option would penalize the correct application of + * the function and the second would defeat the purpose of the + * restartable feature. + * + * Therefore in this case we reuse the original RNG. This comes with the + * price that the resulting signature might not be a valid deterministic + * ECDSA signature with a very low probability (same magnitude as + * successfully guessing the private key). However even then it is still + * a valid ECDSA signature. + */ + p_rng_blind_det = p_rng; +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + /* + * Since the output of the RNGs is always the same for the same key and + * message, this limits the efficiency of blinding and leaks information + * through side channels. After mbedtls_ecdsa_sign_det() is removed NULL + * won't be a valid value for f_rng_blind anymore. Therefore it should + * be checked by the caller and this branch and check can be removed. + */ + ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng, + mbedtls_hmac_drbg_random, p_rng_blind_det, + rs_ctx ); + +#if !defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_hmac_drbg_free( &rng_ctx_blind ); +#endif + } +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ + +cleanup: + mbedtls_hmac_drbg_free( &rng_ctx ); + mbedtls_mpi_free( &h ); + + ECDSA_RS_LEAVE( det ); + + return( ret ); +} + +/* + * Deterministic signature wrappers + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, + NULL, NULL, NULL ) ); +} + +int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, + size_t), + void *p_rng_blind ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + ECDSA_VALIDATE_RET( f_rng_blind != NULL ); + + return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, + f_rng_blind, p_rng_blind, NULL ) ); +} +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#if !defined(MBEDTLS_ECDSA_VERIFY_ALT) +/* + * Verify ECDSA signature of hashed message (SEC1 4.1.4) + * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) + */ +static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, const mbedtls_mpi *s, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret; + mbedtls_mpi e, s_inv, u1, u2; + mbedtls_ecp_point R; + mbedtls_mpi *pu1 = &u1, *pu2 = &u2; + + mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); + mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( grp->N.p == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + ECDSA_RS_ENTER( ver ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ver != NULL ) + { + /* redirect to our context */ + pu1 = &rs_ctx->ver->u1; + pu2 = &rs_ctx->ver->u2; + + /* jump to current step */ + if( rs_ctx->ver->state == ecdsa_ver_muladd ) + goto muladd; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + /* + * Step 1: make sure r and s are in range 1..n-1 + */ + if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 || + mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Step 3: derive MPI from hashed message + */ + MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Step 4: u1 = e / s mod n, u2 = r / s mod n + */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ver != NULL ) + rs_ctx->ver->state = ecdsa_ver_muladd; + +muladd: +#endif + /* + * Step 5: R = u1 G + u2 Q + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp, + &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) ); + + if( mbedtls_ecp_is_zero( &R ) ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Step 6: convert xR to an integer (no-op) + * Step 7: reduce xR mod n (gives v) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) ); + + /* + * Step 8: check if v (that is, R.X) is equal to r + */ + if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); + mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); + + ECDSA_RS_LEAVE( ver ); + + return( ret ); +} + +/* + * Verify ECDSA signature of hashed message + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( Q != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) ); +} +#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ + +/* + * Convert a signature (given by context) to ASN.1 + */ +static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, + unsigned char *sig, size_t *slen ) +{ + int ret; + unsigned char buf[MBEDTLS_ECDSA_MAX_LEN]; + unsigned char *p = buf + sizeof( buf ); + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + memcpy( sig, p, len ); + *slen = len; + + return( 0 ); +} + +/* + * Compute and write signature + */ +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret; + mbedtls_mpi r, s; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); + + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, md_alg, f_rng, + p_rng, rs_ctx ) ); +#else + (void) md_alg; + +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + (void) rs_ctx; + + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng ) ); +#else + /* Use the same RNG for both blinding and ephemeral key generation */ + MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng, f_rng, + p_rng, rs_ctx ) ); +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + + MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + + return( ret ); +} + +/* + * Compute and write signature + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); + return( mbedtls_ecdsa_write_signature_restartable( + ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) && \ + defined(MBEDTLS_ECDSA_DETERMINISTIC) +int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + mbedtls_md_type_t md_alg ) +{ + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); + return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen, + NULL, NULL ) ); +} +#endif + +/* + * Read and check signature + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ) +{ + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + return( mbedtls_ecdsa_read_signature_restartable( + ctx, hash, hlen, sig, slen, NULL ) ); +} + +/* + * Restartable read and check signature + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret; + unsigned char *p = (unsigned char *) sig; + const unsigned char *end = sig + slen; + size_t len; + mbedtls_mpi r, s; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + if( p + len != end ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + goto cleanup; + } + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) + { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } +#if defined(MBEDTLS_ECDSA_VERIFY_ALT) + (void) rs_ctx; + + if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, + &ctx->Q, &r, &s ) ) != 0 ) + goto cleanup; +#else + if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen, + &ctx->Q, &r, &s, rs_ctx ) ) != 0 ) + goto cleanup; +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ + + /* At this point we know that the buffer starts with a valid signature. + * Return 0 if the buffer just contains the signature, and a specific + * error code if the valid signature is followed by more data. */ + if( p != end ) + ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + + return( ret ); +} + +#if !defined(MBEDTLS_ECDSA_GENKEY_ALT) +/* + * Generate key pair + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = 0; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( f_rng != NULL ); + + ret = mbedtls_ecp_group_load( &ctx->grp, gid ); + if( ret != 0 ) + return( ret ); + + return( mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, + &ctx->Q, f_rng, p_rng ) ); +} +#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */ + +/* + * Set context from an mbedtls_ecp_keypair + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) +{ + int ret; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( key != NULL ); + + if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 || + ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ) + { + mbedtls_ecdsa_free( ctx ); + } + + return( ret ); +} + +/* + * Initialize context + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) +{ + ECDSA_VALIDATE( ctx != NULL ); + + mbedtls_ecp_keypair_init( ctx ); +} + +/* + * Free context + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_keypair_free( ctx ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) +{ + ECDSA_VALIDATE( ctx != NULL ); + + mbedtls_ecp_restart_init( &ctx->ecp ); + + ctx->ver = NULL; + ctx->sig = NULL; +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + ctx->det = NULL; +#endif +} + +/* + * Free the components of a restart context + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_restart_free( &ctx->ecp ); + + ecdsa_restart_ver_free( ctx->ver ); + mbedtls_free( ctx->ver ); + ctx->ver = NULL; + + ecdsa_restart_sig_free( ctx->sig ); + mbedtls_free( ctx->sig ); + ctx->sig = NULL; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + ecdsa_restart_det_free( ctx->det ); + mbedtls_free( ctx->det ); + ctx->det = NULL; +#endif +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#endif /* MBEDTLS_ECDSA_C */ diff --git a/external/mbedtls/library/ecjpake.c b/external/mbedtls/library/ecjpake.c new file mode 100644 index 0000000..0532a29 --- /dev/null +++ b/external/mbedtls/library/ecjpake.c @@ -0,0 +1,1176 @@ +/* + * Elliptic curve J-PAKE + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * References in the code are to the Thread v1.0 Specification, + * available to members of the Thread Group http://threadgroup.org/ + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECJPAKE_C) + +#include "mbedtls/ecjpake.h" +#include "mbedtls/platform_util.h" + +#include + +#if !defined(MBEDTLS_ECJPAKE_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECJPAKE_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECJPAKE_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * Convert a mbedtls_ecjpake_role to identifier string + */ +static const char * const ecjpake_id[] = { + "client", + "server" +}; + +#define ID_MINE ( ecjpake_id[ ctx->role ] ) +#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] ) + +/* + * Initialize context + */ +void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ) +{ + ECJPAKE_VALIDATE( ctx != NULL ); + + ctx->md_info = NULL; + mbedtls_ecp_group_init( &ctx->grp ); + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + + mbedtls_ecp_point_init( &ctx->Xm1 ); + mbedtls_ecp_point_init( &ctx->Xm2 ); + mbedtls_ecp_point_init( &ctx->Xp1 ); + mbedtls_ecp_point_init( &ctx->Xp2 ); + mbedtls_ecp_point_init( &ctx->Xp ); + + mbedtls_mpi_init( &ctx->xm1 ); + mbedtls_mpi_init( &ctx->xm2 ); + mbedtls_mpi_init( &ctx->s ); +} + +/* + * Free context + */ +void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ) +{ + if( ctx == NULL ) + return; + + ctx->md_info = NULL; + mbedtls_ecp_group_free( &ctx->grp ); + + mbedtls_ecp_point_free( &ctx->Xm1 ); + mbedtls_ecp_point_free( &ctx->Xm2 ); + mbedtls_ecp_point_free( &ctx->Xp1 ); + mbedtls_ecp_point_free( &ctx->Xp2 ); + mbedtls_ecp_point_free( &ctx->Xp ); + + mbedtls_mpi_free( &ctx->xm1 ); + mbedtls_mpi_free( &ctx->xm2 ); + mbedtls_mpi_free( &ctx->s ); +} + +/* + * Setup context + */ +int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, + mbedtls_ecjpake_role role, + mbedtls_md_type_t hash, + mbedtls_ecp_group_id curve, + const unsigned char *secret, + size_t len ) +{ + int ret; + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT || + role == MBEDTLS_ECJPAKE_SERVER ); + ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 ); + + ctx->role = role; + + if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL ) + return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) ); + +cleanup: + if( ret != 0 ) + mbedtls_ecjpake_free( ctx ); + + return( ret ); +} + +/* + * Check if context is ready for use + */ +int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ) +{ + ECJPAKE_VALIDATE_RET( ctx != NULL ); + + if( ctx->md_info == NULL || + ctx->grp.id == MBEDTLS_ECP_DP_NONE || + ctx->s.p == NULL ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +/* + * Write a point plus its length to a buffer + */ +static int ecjpake_write_len_point( unsigned char **p, + const unsigned char *end, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *P ) +{ + int ret; + size_t len; + + /* Need at least 4 for length plus 1 for point */ + if( end < *p || end - *p < 5 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + ret = mbedtls_ecp_point_write_binary( grp, P, pf, + &len, *p + 4, end - ( *p + 4 ) ); + if( ret != 0 ) + return( ret ); + + (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF ); + (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF ); + (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF ); + (*p)[3] = (unsigned char)( ( len ) & 0xFF ); + + *p += 4 + len; + + return( 0 ); +} + +/* + * Size of the temporary buffer for ecjpake_hash: + * 3 EC points plus their length, plus ID and its length (4 + 6 bytes) + */ +#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 ) + +/* + * Compute hash for ZKP (7.4.2.2.2.1) + */ +static int ecjpake_hash( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_ecp_point *V, + const mbedtls_ecp_point *X, + const char *id, + mbedtls_mpi *h ) +{ + int ret; + unsigned char buf[ECJPAKE_HASH_BUF_LEN]; + unsigned char *p = buf; + const unsigned char *end = buf + sizeof( buf ); + const size_t id_len = strlen( id ); + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + + /* Write things to temporary buffer */ + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) ); + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) ); + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) ); + + if( end - p < 4 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( id_len ) & 0xFF ); + + if( end < p || (size_t)( end - p ) < id_len ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + memcpy( p, id, id_len ); + p += id_len; + + /* Compute hash */ + MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) ); + + /* Turn it into an integer mod n */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash, + mbedtls_md_get_size( md_info ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) ); + +cleanup: + return( ret ); +} + +/* + * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3) + */ +static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_ecp_point *X, + const char *id, + const unsigned char **p, + const unsigned char *end ) +{ + int ret; + mbedtls_ecp_point V, VV; + mbedtls_mpi r, h; + size_t r_len; + + mbedtls_ecp_point_init( &V ); + mbedtls_ecp_point_init( &VV ); + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &h ); + + /* + * struct { + * ECPoint V; + * opaque r<1..2^8-1>; + * } ECSchnorrZKP; + */ + if( end < *p ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) ); + + if( end < *p || (size_t)( end - *p ) < 1 ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + r_len = *(*p)++; + + if( end < *p || (size_t)( end - *p ) < r_len ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) ); + *p += r_len; + + /* + * Verification + */ + MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp, + &VV, &h, X, &r, G ) ); + + if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &V ); + mbedtls_ecp_point_free( &VV ); + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &h ); + + return( ret ); +} + +/* + * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2) + */ +static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_mpi *x, + const mbedtls_ecp_point *X, + const char *id, + unsigned char **p, + const unsigned char *end, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point V; + mbedtls_mpi v; + mbedtls_mpi h; /* later recycled to hold r */ + size_t len; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + mbedtls_ecp_point_init( &V ); + mbedtls_mpi_init( &v ); + mbedtls_mpi_init( &h ); + + /* Compute signature */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, + G, &v, &V, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */ + + /* Write it out */ + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V, + pf, &len, *p, end - *p ) ); + *p += len; + + len = mbedtls_mpi_size( &h ); /* actually r */ + if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + + *(*p)++ = (unsigned char)( len & 0xFF ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */ + *p += len; + +cleanup: + mbedtls_ecp_point_free( &V ); + mbedtls_mpi_free( &v ); + mbedtls_mpi_free( &h ); + + return( ret ); +} + +/* + * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof + * Output: verified public key X + */ +static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_ecp_point *X, + const char *id, + const unsigned char **p, + const unsigned char *end ) +{ + int ret; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * struct { + * ECPoint X; + * ECSchnorrZKP zkp; + * } ECJPAKEKeyKP; + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) ); + if( mbedtls_ecp_is_zero( X ) ) + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto cleanup; + } + + MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) ); + +cleanup: + return( ret ); +} + +/* + * Generate an ECJPAKEKeyKP + * Output: the serialized structure, plus private/public key pair + */ +static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_mpi *x, + mbedtls_ecp_point *X, + const char *id, + unsigned char **p, + const unsigned char *end, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t len; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + /* Generate key (7.4.2.3.1) and write it out */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X, + pf, &len, *p, end - *p ) ); + *p += len; + + /* Generate and write proof */ + MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id, + p, end, f_rng, p_rng ) ); + +cleanup: + return( ret ); +} + +/* + * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs + * Ouputs: verified peer public keys Xa, Xb + */ +static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_ecp_point *Xa, + mbedtls_ecp_point *Xb, + const char *id, + const unsigned char *buf, + size_t len ) +{ + int ret; + const unsigned char *p = buf; + const unsigned char *end = buf + len; + + /* + * struct { + * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2]; + * } ECJPAKEKeyKPPairList; + */ + MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) ); + MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) ); + + if( p != end ) + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + +cleanup: + return( ret ); +} + +/* + * Generate a ECJPAKEKeyKPPairList + * Outputs: the serialized structure, plus two private/public key pairs + */ +static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_mpi *xm1, + mbedtls_ecp_point *Xa, + mbedtls_mpi *xm2, + mbedtls_ecp_point *Xb, + const char *id, + unsigned char *buf, + size_t len, + size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char *p = buf; + const unsigned char *end = buf + len; + + MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id, + &p, end, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id, + &p, end, f_rng, p_rng ) ); + + *olen = p - buf; + +cleanup: + return( ret ); +} + +/* + * Read and process the first round message + */ +int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ) +{ + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + + return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format, + &ctx->grp.G, + &ctx->Xp1, &ctx->Xp2, ID_PEER, + buf, len ) ); +} + +/* + * Generate and write the first round message + */ +int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + + return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format, + &ctx->grp.G, + &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2, + ID_MINE, buf, len, olen, f_rng, p_rng ) ); +} + +/* + * Compute the sum of three points R = A + B + C + */ +static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *A, + const mbedtls_ecp_point *B, + const mbedtls_ecp_point *C ) +{ + int ret; + mbedtls_mpi one; + + mbedtls_mpi_init( &one ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) ); + +cleanup: + mbedtls_mpi_free( &one ); + + return( ret ); +} + +/* + * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6) + */ +int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ) +{ + int ret; + const unsigned char *p = buf; + const unsigned char *end = buf + len; + mbedtls_ecp_group grp; + mbedtls_ecp_point G; /* C: GB, S: GA */ + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &G ); + + /* + * Server: GA = X3 + X4 + X1 (7.4.2.6.1) + * Client: GB = X1 + X2 + X3 (7.4.2.5.1) + * Unified: G = Xm1 + Xm2 + Xp1 + * We need that before parsing in order to check Xp as we read it + */ + MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, + &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) ); + + /* + * struct { + * ECParameters curve_params; // only client reading server msg + * ECJPAKEKeyKP ecjpake_key_kp; + * } Client/ServerECJPAKEParams; + */ + if( ctx->role == MBEDTLS_ECJPAKE_CLIENT ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) ); + if( grp.id != ctx->grp.id ) + { + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + goto cleanup; + } + } + + MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp, + ctx->point_format, + &G, &ctx->Xp, ID_PEER, &p, end ) ); + + if( p != end ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &G ); + + return( ret ); +} + +/* + * Compute R = +/- X * S mod N, taking care not to leak S + */ +static int ecjpake_mul_secret( mbedtls_mpi *R, int sign, + const mbedtls_mpi *X, + const mbedtls_mpi *S, + const mbedtls_mpi *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi b; /* Blinding value, then s + N * blinding */ + + mbedtls_mpi_init( &b ); + + /* b = s + rnd-128-bit * N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) ); + + /* R = sign * X * b mod N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) ); + R->s *= sign; + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) ); + +cleanup: + mbedtls_mpi_free( &b ); + + return( ret ); +} + +/* + * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6) + */ +int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point G; /* C: GA, S: GB */ + mbedtls_ecp_point Xm; /* C: Xc, S: Xs */ + mbedtls_mpi xm; /* C: xc, S: xs */ + unsigned char *p = buf; + const unsigned char *end = buf + len; + size_t ec_len; + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + + mbedtls_ecp_point_init( &G ); + mbedtls_ecp_point_init( &Xm ); + mbedtls_mpi_init( &xm ); + + /* + * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1) + * + * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA + * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB + * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G + */ + MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, + &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) ); + MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s, + &ctx->grp.N, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) ); + + /* + * Now write things out + * + * struct { + * ECParameters curve_params; // only server writing its message + * ECJPAKEKeyKP ecjpake_key_kp; + * } Client/ServerECJPAKEParams; + */ + if( ctx->role == MBEDTLS_ECJPAKE_SERVER ) + { + if( end < p ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len, + p, end - p ) ); + p += ec_len; + } + + if( end < p ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm, + ctx->point_format, &ec_len, p, end - p ) ); + p += ec_len; + + MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp, + ctx->point_format, + &G, &xm, &Xm, ID_MINE, + &p, end, f_rng, p_rng ) ); + + *olen = p - buf; + +cleanup: + mbedtls_ecp_point_free( &G ); + mbedtls_ecp_point_free( &Xm ); + mbedtls_mpi_free( &xm ); + + return( ret ); +} + +/* + * Derive PMS (7.4.2.7 / 7.4.2.8) + */ +int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point K; + mbedtls_mpi m_xm2_s, one; + unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; + size_t x_bytes; + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + + *olen = mbedtls_md_get_size( ctx->md_info ); + if( len < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + mbedtls_ecp_point_init( &K ); + mbedtls_mpi_init( &m_xm2_s ); + mbedtls_mpi_init( &one ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); + + /* + * Client: K = ( Xs - X4 * x2 * s ) * x2 + * Server: K = ( Xc - X2 * x4 * s ) * x4 + * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2 + */ + MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s, + &ctx->grp.N, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K, + &one, &ctx->Xp, + &m_xm2_s, &ctx->Xp2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K, + f_rng, p_rng ) ); + + /* PMS = SHA-256( K.X ) */ + x_bytes = ( ctx->grp.pbits + 7 ) / 8; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) ); + +cleanup: + mbedtls_ecp_point_free( &K ); + mbedtls_mpi_free( &m_xm2_s ); + mbedtls_mpi_free( &one ); + + return( ret ); +} + +#undef ID_MINE +#undef ID_PEER + +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + !defined(MBEDTLS_SHA256_C) +int mbedtls_ecjpake_self_test( int verbose ) +{ + (void) verbose; + return( 0 ); +} +#else + +static const unsigned char ecjpake_test_password[] = { + 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74, + 0x65, 0x73, 0x74 +}; + +#if !defined(MBEDTLS_ECJPAKE_ALT) + +static const unsigned char ecjpake_test_x1[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21 +}; + +static const unsigned char ecjpake_test_x2[] = { + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 +}; + +static const unsigned char ecjpake_test_x3[] = { + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 +}; + +static const unsigned char ecjpake_test_x4[] = { + 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, + 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, + 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1 +}; + +static const unsigned char ecjpake_test_cli_one[] = { + 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19, + 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44, + 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad, + 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62, + 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9, + 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d, + 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e, + 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e, + 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73, + 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22, + 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce, + 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00, + 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b, + 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e, + 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62, + 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5, + 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb, + 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35, + 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0, + 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb, + 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47, + 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39, + 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97, + 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40, + 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d, + 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa, + 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d, + 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0 +}; + +static const unsigned char ecjpake_test_srv_one[] = { + 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, + 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, + 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, + 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, + 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, + 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d, + 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64, + 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36, + 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2, + 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec, + 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16, + 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96, + 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3, + 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19, + 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f, + 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8, + 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7, + 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea, + 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5, + 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6, + 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31, + 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d, + 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8, + 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee, + 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84, + 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f, + 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80, + 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12 +}; + +static const unsigned char ecjpake_test_srv_two[] = { + 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23, + 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c, + 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f, + 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca, + 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26, + 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55, + 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38, + 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6, + 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9, + 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4, + 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2, + 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8, + 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd, + 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c +}; + +static const unsigned char ecjpake_test_cli_two[] = { + 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46, + 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb, + 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72, + 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce, + 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98, + 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31, + 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15, + 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36, + 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8, + 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45, + 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d, + 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58, + 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82, + 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c +}; + +static const unsigned char ecjpake_test_pms[] = { + 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7, + 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9, + 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51 +}; + +/* Load my private keys and generate the corresponding public keys */ +static int ecjpake_test_load( mbedtls_ecjpake_context *ctx, + const unsigned char *xm1, size_t len1, + const unsigned char *xm2, size_t len2 ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1, + &ctx->grp.G, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2, + &ctx->grp.G, NULL, NULL ) ); + +cleanup: + return( ret ); +} + +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + +/* For tests we don't need a secure RNG; + * use the LGC from Numerical Recipes for simplicity */ +static int ecjpake_lgc( void *p, unsigned char *out, size_t len ) +{ + static uint32_t x = 42; + (void) p; + + while( len > 0 ) + { + size_t use_len = len > 4 ? 4 : len; + x = 1664525 * x + 1013904223; + memcpy( out, &x, use_len ); + out += use_len; + len -= use_len; + } + + return( 0 ); +} + +#define TEST_ASSERT( x ) \ + do { \ + if( x ) \ + ret = 0; \ + else \ + { \ + ret = 1; \ + goto cleanup; \ + } \ + } while( 0 ) + +/* + * Checkup routine + */ +int mbedtls_ecjpake_self_test( int verbose ) +{ + int ret; + mbedtls_ecjpake_context cli; + mbedtls_ecjpake_context srv; + unsigned char buf[512], pms[32]; + size_t len, pmslen; + + mbedtls_ecjpake_init( &cli ); + mbedtls_ecjpake_init( &srv ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #0 (setup): " ); + + TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT, + MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, + ecjpake_test_password, + sizeof( ecjpake_test_password ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER, + MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, + ecjpake_test_password, + sizeof( ecjpake_test_password ) ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #1 (random handshake): " ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, + pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == pmslen ); + TEST_ASSERT( memcmp( buf, pms, len ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +#if !defined(MBEDTLS_ECJPAKE_ALT) + /* 'reference handshake' tests can only be run against implementations + * for which we have 100% control over how the random ephemeral keys + * are generated. This is only the case for the internal mbed TLS + * implementation, so these tests are skipped in case the internal + * implementation is swapped out for an alternative one. */ + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #2 (reference handshake): " ); + + /* Simulate generation of round one */ + MBEDTLS_MPI_CHK( ecjpake_test_load( &cli, + ecjpake_test_x1, sizeof( ecjpake_test_x1 ), + ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) ); + + MBEDTLS_MPI_CHK( ecjpake_test_load( &srv, + ecjpake_test_x3, sizeof( ecjpake_test_x3 ), + ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) ); + + /* Read round one */ + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, + ecjpake_test_cli_one, + sizeof( ecjpake_test_cli_one ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, + ecjpake_test_srv_one, + sizeof( ecjpake_test_srv_one ) ) == 0 ); + + /* Skip generation of round two, read round two */ + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, + ecjpake_test_srv_two, + sizeof( ecjpake_test_srv_two ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, + ecjpake_test_cli_two, + sizeof( ecjpake_test_cli_two ) ) == 0 ); + + /* Server derives PMS */ + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); + TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); + + memset( buf, 0, len ); /* Avoid interferences with next step */ + + /* Client derives PMS */ + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); + TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + +cleanup: + mbedtls_ecjpake_free( &cli ); + mbedtls_ecjpake_free( &srv ); + + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#undef TEST_ASSERT + +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ECJPAKE_C */ diff --git a/external/mbedtls/library/ecp.c b/external/mbedtls/library/ecp.c new file mode 100644 index 0000000..fe41b41 --- /dev/null +++ b/external/mbedtls/library/ecp.c @@ -0,0 +1,3462 @@ +/* + * Elliptic curves over GF(p): generic functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone + * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf + * RFC 4492 for the related TLS structures and constants + * RFC 7748 for the Curve448 and Curve25519 curve definitions + * + * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/** + * \brief Function level alternative implementation. + * + * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to + * replace certain functions in this module. The alternative implementations are + * typically hardware accelerators and need to activate the hardware before the + * computation starts and deactivate it after it finishes. The + * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve + * this purpose. + * + * To preserve the correct functionality the following conditions must hold: + * + * - The alternative implementation must be activated by + * mbedtls_internal_ecp_init() before any of the replaceable functions is + * called. + * - mbedtls_internal_ecp_free() must \b only be called when the alternative + * implementation is activated. + * - mbedtls_internal_ecp_init() must \b not be called when the alternative + * implementation is activated. + * - Public functions must not return while the alternative implementation is + * activated. + * - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and + * before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) ) + * \endcode ensures that the alternative implementation supports the current + * group. + */ +#if defined(MBEDTLS_ECP_INTERNAL_ALT) +#endif + +#if defined(MBEDTLS_ECP_C) + +#include "mbedtls/ecp.h" +#include "mbedtls/threading.h" +#include "mbedtls/platform_util.h" + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECP_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECP_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ecp_internal.h" + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) +#if defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +#elif defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +#elif defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#elif defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#else +#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid." +#endif +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * Counts of point addition and doubling, and field multiplications. + * Used to test resistance of point multiplication to simple timing attacks. + */ +static unsigned long add_count, dbl_count, mul_count; +#endif + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) +/* + * Currently ecp_mul() takes a RNG function as an argument, used for + * side-channel protection, but it can be NULL. The initial reasoning was + * that people will pass non-NULL RNG when they care about side-channels, but + * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with + * no opportunity for the user to do anything about it. + * + * The obvious strategies for addressing that include: + * - change those APIs so that they take RNG arguments; + * - require a global RNG to be available to all crypto modules. + * + * Unfortunately those would break compatibility. So what we do instead is + * have our own internal DRBG instance, seeded from the secret scalar. + * + * The following is a light-weight abstraction layer for doing that with + * HMAC_DRBG (first choice) or CTR_DRBG. + */ + +#if defined(MBEDTLS_HMAC_DRBG_C) + +/* DRBG context type */ +typedef mbedtls_hmac_drbg_context ecp_drbg_context; + +/* DRBG context init */ +static inline void ecp_drbg_init( ecp_drbg_context *ctx ) +{ + mbedtls_hmac_drbg_init( ctx ); +} + +/* DRBG context free */ +static inline void ecp_drbg_free( ecp_drbg_context *ctx ) +{ + mbedtls_hmac_drbg_free( ctx ); +} + +/* DRBG function */ +static inline int ecp_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ) +{ + return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) ); +} + +/* DRBG context seeding */ +static int ecp_drbg_seed( ecp_drbg_context *ctx, + const mbedtls_mpi *secret, size_t secret_len ) +{ + int ret; + unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES]; + /* The list starts with strong hashes */ + const mbedtls_md_type_t md_type = mbedtls_md_list()[0]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret, + secret_bytes, secret_len ) ); + + ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len ); + +cleanup: + mbedtls_platform_zeroize( secret_bytes, secret_len ); + + return( ret ); +} + +#elif defined(MBEDTLS_CTR_DRBG_C) + +/* DRBG context type */ +typedef mbedtls_ctr_drbg_context ecp_drbg_context; + +/* DRBG context init */ +static inline void ecp_drbg_init( ecp_drbg_context *ctx ) +{ + mbedtls_ctr_drbg_init( ctx ); +} + +/* DRBG context free */ +static inline void ecp_drbg_free( ecp_drbg_context *ctx ) +{ + mbedtls_ctr_drbg_free( ctx ); +} + +/* DRBG function */ +static inline int ecp_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ) +{ + return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) ); +} + +/* + * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does, + * we need to pass an entropy function when seeding. So we use a dummy + * function for that, and pass the actual entropy as customisation string. + * (During seeding of CTR_DRBG the entropy input and customisation string are + * concatenated before being used to update the secret state.) + */ +static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len) +{ + (void) ctx; + memset( out, 0, len ); + return( 0 ); +} + +/* DRBG context seeding */ +static int ecp_drbg_seed( ecp_drbg_context *ctx, + const mbedtls_mpi *secret, size_t secret_len ) +{ + int ret; + unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES]; + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret, + secret_bytes, secret_len ) ); + + ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL, + secret_bytes, secret_len ); + +cleanup: + mbedtls_platform_zeroize( secret_bytes, secret_len ); + + return( ret ); +} + +#elif defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA256_C) + +/* This will be used in the self-test function */ +#define ECP_ONE_STEP_KDF + +/* + * We need to expand secret data (the scalar) into a longer stream of bytes. + * + * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash + * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for + * convenience, this is not a full-fledged DRBG, but we don't need one here.) + * + * We need a basic hash abstraction layer to use whatever SHA-2 is available. + */ +#if defined(MBEDTLS_SHA512_C) + +#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 ); +#define HASH_BLOCK_BYTES ( 512 / 8 ) + +#elif defined(MBEDTLS_SHA256_C) + +#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 ); +#define HASH_BLOCK_BYTES ( 256 / 8 ) + +#endif /* SHA512/SHA256 abstraction */ + +/* + * State consists of a 32-bit counter plus the secret value. + * + * We stored them concatenated in a single buffer as that's what will get + * passed to the hash function. + */ +typedef struct { + size_t total_len; + uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES]; +} ecp_drbg_context; + +static void ecp_drbg_init( ecp_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( ecp_drbg_context ) ); +} + +static void ecp_drbg_free( ecp_drbg_context *ctx ) +{ + mbedtls_platform_zeroize( ctx, sizeof( ecp_drbg_context ) ); +} + +static int ecp_drbg_seed( ecp_drbg_context *ctx, + const mbedtls_mpi *secret, size_t secret_len ) +{ + ctx->total_len = 4 + secret_len; + memset( ctx->buf, 0, 4); + return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) ); +} + +static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) +{ + ecp_drbg_context *ctx = p_rng; + int ret; + size_t len_done = 0; + uint8_t tmp[HASH_BLOCK_BYTES]; + + while( len_done < output_len ) + { + uint8_t use_len; + + /* This function is only called for coordinate randomisation, which + * happens only twice in a scalar multiplication. Each time needs a + * random value in the range [2, p-1], and gets it by drawing len(p) + * bytes from this function, and retrying up to 10 times if unlucky. + * + * So for the largest curve, each scalar multiplication draws at most + * 20 * 66 bytes. The minimum block size is 32 (SHA-256), so with + * rounding that means a most 20 * 3 blocks. + * + * Since we don't need to draw more that 255 blocks, don't bother + * with carry propagation and just return an error instead. We can + * change that it we even need to draw more blinding values. + */ + ctx->buf[3] += 1; + if( ctx->buf[3] == 0 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + + ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp ); + if( ret != 0 ) + return( ret ); + + if( output_len - len_done > HASH_BLOCK_BYTES ) + use_len = HASH_BLOCK_BYTES; + else + use_len = output_len - len_done; + + memcpy( output + len_done, tmp, use_len ); + len_done += use_len; + } + + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + + return( 0 ); +} + +#else /* DRBG/SHA modules */ +#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid." +#endif /* DRBG/SHA modules */ +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Maximum number of "basic operations" to be done in a row. + * + * Default value 0 means that ECC operations will not yield. + * Note that regardless of the value of ecp_max_ops, always at + * least one step is performed before yielding. + * + * Setting ecp_max_ops=1 can be suitable for testing purposes + * as it will interrupt computation at all possible points. + */ +static unsigned ecp_max_ops = 0; + +/* + * Set ecp_max_ops + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ) +{ + ecp_max_ops = max_ops; +} + +/* + * Check if restart is enabled + */ +int mbedtls_ecp_restart_is_enabled( void ) +{ + return( ecp_max_ops != 0 ); +} + +/* + * Restart sub-context for ecp_mul_comb() + */ +struct mbedtls_ecp_restart_mul +{ + mbedtls_ecp_point R; /* current intermediate result */ + size_t i; /* current index in various loops, 0 outside */ + mbedtls_ecp_point *T; /* table for precomputed points */ + unsigned char T_size; /* number of points in table T */ + enum { /* what were we doing last time we returned? */ + ecp_rsm_init = 0, /* nothing so far, dummy initial state */ + ecp_rsm_pre_dbl, /* precompute 2^n multiples */ + ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */ + ecp_rsm_pre_add, /* precompute remaining points by adding */ + ecp_rsm_pre_norm_add, /* normalize all precomputed points */ + ecp_rsm_comb_core, /* ecp_mul_comb_core() */ + ecp_rsm_final_norm, /* do the final normalization */ + } state; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_context drbg_ctx; + unsigned char drbg_seeded; +#endif +}; + +/* + * Init restart_mul sub-context + */ +static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx ) +{ + mbedtls_ecp_point_init( &ctx->R ); + ctx->i = 0; + ctx->T = NULL; + ctx->T_size = 0; + ctx->state = ecp_rsm_init; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_init( &ctx->drbg_ctx ); + ctx->drbg_seeded = 0; +#endif +} + +/* + * Free the components of a restart_mul sub-context + */ +static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx ) +{ + unsigned char i; + + if( ctx == NULL ) + return; + + mbedtls_ecp_point_free( &ctx->R ); + + if( ctx->T != NULL ) + { + for( i = 0; i < ctx->T_size; i++ ) + mbedtls_ecp_point_free( ctx->T + i ); + mbedtls_free( ctx->T ); + } + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_free( &ctx->drbg_ctx ); +#endif + + ecp_restart_rsm_init( ctx ); +} + +/* + * Restart context for ecp_muladd() + */ +struct mbedtls_ecp_restart_muladd +{ + mbedtls_ecp_point mP; /* mP value */ + mbedtls_ecp_point R; /* R intermediate result */ + enum { /* what should we do next? */ + ecp_rsma_mul1 = 0, /* first multiplication */ + ecp_rsma_mul2, /* second multiplication */ + ecp_rsma_add, /* addition */ + ecp_rsma_norm, /* normalization */ + } state; +}; + +/* + * Init restart_muladd sub-context + */ +static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx ) +{ + mbedtls_ecp_point_init( &ctx->mP ); + mbedtls_ecp_point_init( &ctx->R ); + ctx->state = ecp_rsma_mul1; +} + +/* + * Free the components of a restart_muladd sub-context + */ +static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_point_free( &ctx->mP ); + mbedtls_ecp_point_free( &ctx->R ); + + ecp_restart_ma_init( ctx ); +} + +/* + * Initialize a restart context + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ) +{ + ECP_VALIDATE( ctx != NULL ); + ctx->ops_done = 0; + ctx->depth = 0; + ctx->rsm = NULL; + ctx->ma = NULL; +} + +/* + * Free the components of a restart context + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + ecp_restart_rsm_free( ctx->rsm ); + mbedtls_free( ctx->rsm ); + + ecp_restart_ma_free( ctx->ma ); + mbedtls_free( ctx->ma ); + + mbedtls_ecp_restart_init( ctx ); +} + +/* + * Check if we can do the next step + */ +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ) +{ + ECP_VALIDATE_RET( grp != NULL ); + + if( rs_ctx != NULL && ecp_max_ops != 0 ) + { + /* scale depending on curve size: the chosen reference is 256-bit, + * and multiplication is quadratic. Round to the closest integer. */ + if( grp->pbits >= 512 ) + ops *= 4; + else if( grp->pbits >= 384 ) + ops *= 2; + + /* Avoid infinite loops: always allow first step. + * Because of that, however, it's not generally true + * that ops_done <= ecp_max_ops, so the check + * ops_done > ecp_max_ops below is mandatory. */ + if( ( rs_ctx->ops_done != 0 ) && + ( rs_ctx->ops_done > ecp_max_ops || + ops > ecp_max_ops - rs_ctx->ops_done ) ) + { + return( MBEDTLS_ERR_ECP_IN_PROGRESS ); + } + + /* update running count */ + rs_ctx->ops_done += ops; + } + + return( 0 ); +} + +/* Call this when entering a function that needs its own sub-context */ +#define ECP_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \ + rs_ctx->ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_is_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecp_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ +} while( 0 ) + +/* Call this when leaving a function that needs its own sub-context */ +#define ECP_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ + ecp_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->depth--; \ +} while( 0 ) + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define ECP_RS_ENTER( sub ) (void) rs_ctx; +#define ECP_RS_LEAVE( sub ) (void) rs_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define ECP_SHORTWEIERSTRASS +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ + defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define ECP_MONTGOMERY +#endif + +/* + * Curve types: internal for now, might be exposed later + */ +typedef enum +{ + ECP_TYPE_NONE = 0, + ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ + ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ +} ecp_curve_type; + +/* + * List of supported curves: + * - internal ID + * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2) + * - size in bits + * - readable name + * + * Curves are listed in order: largest curves first, and for a given size, + * fastest curves first. This provides the default order for the SSL module. + * + * Reminder: update profiles in x509_crt.c when adding a new curves! + */ +static const mbedtls_ecp_curve_info ecp_supported_curves[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, +#endif + { MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, +}; + +#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \ + sizeof( ecp_supported_curves[0] ) + +static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; + +/* + * List of supported curves and associated info + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ) +{ + return( ecp_supported_curves ); +} + +/* + * List of supported curves, group ID only + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ) +{ + static int init_done = 0; + + if( ! init_done ) + { + size_t i = 0; + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + ecp_supported_grp_id[i++] = curve_info->grp_id; + } + ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE; + + init_done = 1; + } + + return( ecp_supported_grp_id ); +} + +/* + * Get the curve info for the internal identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->grp_id == grp_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the TLS identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->tls_id == tls_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the name + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ) +{ + const mbedtls_ecp_curve_info *curve_info; + + if( name == NULL ) + return( NULL ); + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( strcmp( curve_info->name, name ) == 0 ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the type of a curve + */ +static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp ) +{ + if( grp->G.X.p == NULL ) + return( ECP_TYPE_NONE ); + + if( grp->G.Y.p == NULL ) + return( ECP_TYPE_MONTGOMERY ); + else + return( ECP_TYPE_SHORT_WEIERSTRASS ); +} + +/* + * Initialize (the components of) a point + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) +{ + ECP_VALIDATE( pt != NULL ); + + mbedtls_mpi_init( &pt->X ); + mbedtls_mpi_init( &pt->Y ); + mbedtls_mpi_init( &pt->Z ); +} + +/* + * Initialize (the components of) a group + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) +{ + ECP_VALIDATE( grp != NULL ); + + grp->id = MBEDTLS_ECP_DP_NONE; + mbedtls_mpi_init( &grp->P ); + mbedtls_mpi_init( &grp->A ); + mbedtls_mpi_init( &grp->B ); + mbedtls_ecp_point_init( &grp->G ); + mbedtls_mpi_init( &grp->N ); + grp->pbits = 0; + grp->nbits = 0; + grp->h = 0; + grp->modp = NULL; + grp->t_pre = NULL; + grp->t_post = NULL; + grp->t_data = NULL; + grp->T = NULL; + grp->T_size = 0; +} + +/* + * Initialize (the components of) a key pair + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) +{ + ECP_VALIDATE( key != NULL ); + + mbedtls_ecp_group_init( &key->grp ); + mbedtls_mpi_init( &key->d ); + mbedtls_ecp_point_init( &key->Q ); +} + +/* + * Unallocate (the components of) a point + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mbedtls_mpi_free( &( pt->X ) ); + mbedtls_mpi_free( &( pt->Y ) ); + mbedtls_mpi_free( &( pt->Z ) ); +} + +/* + * Unallocate (the components of) a group + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) +{ + size_t i; + + if( grp == NULL ) + return; + + if( grp->h != 1 ) + { + mbedtls_mpi_free( &grp->P ); + mbedtls_mpi_free( &grp->A ); + mbedtls_mpi_free( &grp->B ); + mbedtls_ecp_point_free( &grp->G ); + mbedtls_mpi_free( &grp->N ); + } + + if( grp->T != NULL ) + { + for( i = 0; i < grp->T_size; i++ ) + mbedtls_ecp_point_free( &grp->T[i] ); + mbedtls_free( grp->T ); + } + + mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) ); +} + +/* + * Unallocate (the components of) a key pair + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ) +{ + if( key == NULL ) + return; + + mbedtls_ecp_group_free( &key->grp ); + mbedtls_mpi_free( &key->d ); + mbedtls_ecp_point_free( &key->Q ); +} + +/* + * Copy the contents of a point + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ + int ret; + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) ); + +cleanup: + return( ret ); +} + +/* + * Copy the contents of a group object + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ) +{ + ECP_VALIDATE_RET( dst != NULL ); + ECP_VALIDATE_RET( src != NULL ); + + return( mbedtls_ecp_group_load( dst, src->id ) ); +} + +/* + * Set point to zero + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) +{ + int ret; + ECP_VALIDATE_RET( pt != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) ); + +cleanup: + return( ret ); +} + +/* + * Tell if a point is zero + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ) +{ + ECP_VALIDATE_RET( pt != NULL ); + + return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); +} + +/* + * Compare two points lazily + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ) +{ + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + + if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 ) + { + return( 0 ); + } + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Import a non-zero point from ASCII strings + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ) +{ + int ret; + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( x != NULL ); + ECP_VALIDATE_RET( y != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Export a point into unsigned binary data (SEC1 2.3.3) + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ) +{ + int ret = 0; + size_t plen; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED || + format == MBEDTLS_ECP_PF_COMPRESSED ); + + /* + * Common case: P == 0 + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + { + if( buflen < 1 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x00; + *olen = 1; + + return( 0 ); + } + + plen = mbedtls_mpi_size( &grp->P ); + + if( format == MBEDTLS_ECP_PF_UNCOMPRESSED ) + { + *olen = 2 * plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x04; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); + } + else if( format == MBEDTLS_ECP_PF_COMPRESSED ) + { + *olen = plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + } + +cleanup: + return( ret ); +} + +/* + * Import a point from unsigned binary data (SEC1 2.3.4) + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char *buf, size_t ilen ) +{ + int ret; + size_t plen; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + + if( ilen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( buf[0] == 0x00 ) + { + if( ilen == 1 ) + return( mbedtls_ecp_set_zero( pt ) ); + else + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + plen = mbedtls_mpi_size( &grp->P ); + + if( buf[0] != 0x04 ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + if( ilen != 2 * plen + 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Import a point from a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char **buf, size_t buf_len ) +{ + unsigned char data_len; + const unsigned char *buf_start; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); + + /* + * We must have at least two bytes (1 for length, at least one for data) + */ + if( buf_len < 2 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + data_len = *(*buf)++; + if( data_len < 1 || data_len > buf_len - 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Save buffer start for read_binary and update buf + */ + buf_start = *buf; + *buf += data_len; + + return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) ); +} + +/* + * Export a point as a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ) +{ + int ret; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED || + format == MBEDTLS_ECP_PF_COMPRESSED ); + + /* + * buffer length must be at least one, for our length byte + */ + if( blen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format, + olen, buf + 1, blen - 1) ) != 0 ) + return( ret ); + + /* + * write length to the first byte and update total length + */ + buf[0] = (unsigned char) *olen; + ++*olen; + + return( 0 ); +} + +/* + * Set a group from an ECParameters record (RFC 4492) + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, + const unsigned char **buf, size_t len ) +{ + int ret; + mbedtls_ecp_group_id grp_id; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); + + if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 ) + return( ret ); + + return( mbedtls_ecp_group_load( grp, grp_id ) ); +} + +/* + * Read a group id from an ECParameters record (RFC 4492) and convert it to + * mbedtls_ecp_group_id. + */ +int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp, + const unsigned char **buf, size_t len ) +{ + uint16_t tls_id; + const mbedtls_ecp_curve_info *curve_info; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); + + /* + * We expect at least three bytes (see below) + */ + if( len < 3 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * First byte is curve_type; only named_curve is handled + */ + if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Next two bytes are the namedcurve value + */ + tls_id = *(*buf)++; + tls_id <<= 8; + tls_id |= *(*buf)++; + + if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + *grp = curve_info->grp_id; + + return( 0 ); +} + +/* + * Write the ECParameters record corresponding to a group (RFC 4492) + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ) +{ + const mbedtls_ecp_curve_info *curve_info; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + + if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * We are going to write 3 bytes (see below) + */ + *olen = 3; + if( blen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + /* + * First byte is curve_type, always named_curve + */ + *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; + + /* + * Next two bytes are the namedcurve value + */ + buf[0] = curve_info->tls_id >> 8; + buf[1] = curve_info->tls_id & 0xFF; + + return( 0 ); +} + +/* + * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi. + * See the documentation of struct mbedtls_ecp_group. + * + * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf. + */ +static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp ) +{ + int ret; + + if( grp->modp == NULL ) + return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) || + mbedtls_mpi_bitlen( N ) > 2 * grp->pbits ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + MBEDTLS_MPI_CHK( grp->modp( N ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) ); + + while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 ) + /* we known P, N and the result are positive */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) ); + +cleanup: + return( ret ); +} + +/* + * Fast mod-p functions expect their argument to be in the 0..p^2 range. + * + * In order to guarantee that, we need to ensure that operands of + * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will + * bring the result back to this range. + * + * The following macros are shortcuts for doing that. + */ + +/* + * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi + */ +#if defined(MBEDTLS_SELF_TEST) +#define INC_MUL_COUNT mul_count++; +#else +#define INC_MUL_COUNT +#endif + +#define MOD_MUL( N ) \ + do \ + { \ + MBEDTLS_MPI_CHK( ecp_modp( &(N), grp ) ); \ + INC_MUL_COUNT \ + } while( 0 ) + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi + * N->s < 0 is a very fast test, which fails only if N is 0 + */ +#define MOD_SUB( N ) \ + while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) ) + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. + * We known P, N and the result are positive, so sub_abs is correct, and + * a bit faster. + */ +#define MOD_ADD( N ) \ + while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) ) + +#if defined(ECP_SHORTWEIERSTRASS) +/* + * For curves in short Weierstrass form, we do all the internal operations in + * Jacobian coordinates. + * + * For multiplication, we'll use a comb method with coutermeasueres against + * SPA, hence timing attacks. + */ + +/* + * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) + * Cost: 1N := 1I + 3M + 1S + */ +static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt ) +{ + int ret; + mbedtls_mpi Zi, ZZi; + + if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ) + return( 0 ); + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_jac( grp, pt ) ); +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ + + mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * X = X / Z^2 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X ); + + /* + * Y = Y / Z^3 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y ); + + /* + * Z = 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + +cleanup: + + mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + + return( ret ); +} + +/* + * Normalize jacobian coordinates of an array of (pointers to) points, + * using Montgomery's trick to perform only one inversion mod P. + * (See for example Cohen's "A Course in Computational Algebraic Number + * Theory", Algorithm 10.3.4.) + * + * Warning: fails (returning an error) if one of the points is zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * Cost: 1N(t) := 1I + (6t - 3)M + 1S + */ +static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t T_size ) +{ + int ret; + size_t i; + mbedtls_mpi *c, u, Zi, ZZi; + + if( T_size < 2 ) + return( ecp_normalize_jac( grp, *T ) ); + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) ); +#endif + + if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL ) + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + + for( i = 0; i < T_size; i++ ) + mbedtls_mpi_init( &c[i] ); + + mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * c[i] = Z_0 * ... * Z_i + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); + for( i = 1; i < T_size; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) ); + MOD_MUL( c[i] ); + } + + /* + * u = 1 / (Z_0 * ... * Z_n) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) ); + + for( i = T_size - 1; ; i-- ) + { + /* + * Zi = 1 / Z_i mod p + * u = 1 / (Z_0 * ... * Z_i) mod P + */ + if( i == 0 ) { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u ); + } + + /* + * proceed as in normalize() + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi ) ); MOD_MUL( T[i]->Y ); + + /* + * Post-precessing: reclaim some memory by shrinking coordinates + * - not storing Z (always 1) + * - shrinking other coordinates, but still keeping the same number of + * limbs as P, as otherwise it will too likely be regrown too fast. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) ); + mbedtls_mpi_free( &T[i]->Z ); + + if( i == 0 ) + break; + } + +cleanup: + + mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + for( i = 0; i < T_size; i++ ) + mbedtls_mpi_free( &c[i] ); + mbedtls_free( c ); + + return( ret ); +} + +/* + * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. + * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid + */ +static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *Q, + unsigned char inv ) +{ + int ret; + unsigned char nonzero; + mbedtls_mpi mQY; + + mbedtls_mpi_init( &mQY ); + + /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) ); + nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) ); + +cleanup: + mbedtls_mpi_free( &mQY ); + + return( ret ); +} + +/* + * Point doubling R = 2 P, Jacobian coordinates + * + * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 . + * + * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR + * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring. + * + * Standard optimizations are applied when curve parameter A is one of { 0, -3 }. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + */ +static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P ) +{ + int ret; + mbedtls_mpi M, S, T, U; + +#if defined(MBEDTLS_SELF_TEST) + dbl_count++; +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_double_jac( grp, R, P ) ); +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ + + mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + /* M = 3(X + Z^2)(X - Z^2) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + } + else + { + /* M = 3.X^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + + /* Optimize away for "koblitz" curves with A = 0 */ + if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 ) + { + /* M += A.Z^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M ); + } + } + + /* S = 4.X.Y^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S ); + + /* U = 8.Y^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); + + /* T = M^2 - 2.S */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); + + /* S = M(S - T) - U */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S ); + + /* U = 2.Y.Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) ); + +cleanup: + mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U ); + + return( ret ); +} + +/* + * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. + * None of these cases can happen as intermediate step in ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base point, the factor + * being less than its order, so none of them is zero; + * - Q is an odd multiple of the base point, P an even multiple, + * due to the choice of precomputed points in the modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as meaning 1. + * + * Cost: 1A := 8M + 3S + */ +static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ + int ret; + mbedtls_mpi T1, T2, T3, T4, X, Y, Z; + +#if defined(MBEDTLS_SELF_TEST) + add_count++; +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) ); +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ + + /* + * Trivial cases: P == 0 or Q == 0 (case 1) + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, Q ) ); + + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, P ) ); + + /* + * Make sure Q coordinates are normalized + */ + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 ); + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 ); + + /* Special cases (2) and (3) */ + if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 ) + { + if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 ) + { + ret = ecp_double_jac( grp, R, P ); + goto cleanup; + } + else + { + ret = mbedtls_ecp_set_zero( R ); + goto cleanup; + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) ); + +cleanup: + + mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 ); + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + + return( ret ); +} + +/* + * Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_jac(). + * + * This countermeasure was first suggested in [2]. + */ +static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_mpi l, ll; + size_t p_size; + int count = 0; + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) ); +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ + + p_size = ( grp->pbits + 7 ) / 8; + mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll ); + + /* Generate l such that 1 < l < p */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); + + /* Z = l * Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z ); + + /* X = l^2 * X */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X ); + + /* Y = l^3 * Y */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y ); + +cleanup: + mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll ); + + return( ret ); +} + +/* + * Check and define parameters used by the comb method (see below for details) + */ +#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7 +#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds" +#endif + +/* d = ceil( n / w ) */ +#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2 + +/* number of precomputed points */ +#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + +/* + * Compute the representation of m that will be used with our comb method. + * + * The basic comb method is described in GECC 3.44 for example. We use a + * modified version that provides resistance to SPA by avoiding zero + * digits in the representation as in [3]. We modify the method further by + * requiring that all K_i be odd, which has the small cost that our + * representation uses one more K_i, due to carries, but saves on the size of + * the precomputed table. + * + * Summary of the comb method and its modifications: + * + * - The goal is to compute m*P for some w*d-bit integer m. + * + * - The basic comb method splits m into the w-bit integers + * x[0] .. x[d-1] where x[i] consists of the bits in m whose + * index has residue i modulo d, and computes m * P as + * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where + * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P. + * + * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by + * .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] .., + * thereby successively converting it into a form where all summands + * are nonzero, at the cost of negative summands. This is the basic idea of [3]. + * + * - More generally, even if x[i+1] != 0, we can first transform the sum as + * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] .., + * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]]. + * Performing and iterating this procedure for those x[i] that are even + * (keeping track of carry), we can transform the original sum into one of the form + * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]] + * with all x'[i] odd. It is therefore only necessary to know S at odd indices, + * which is why we are only computing half of it in the first place in + * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb. + * + * - For the sake of compactness, only the seven low-order bits of x[i] + * are used to represent its absolute value (K_i in the paper), and the msb + * of x[i] encodes the sign (s_i in the paper): it is set if and only if + * if s_i == -1; + * + * Calling conventions: + * - x is an array of size d + 1 + * - w is the size, ie number of teeth, of the comb, and must be between + * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE) + * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d + * (the result will be incorrect if these assumptions are not satisfied) + */ +static void ecp_comb_recode_core( unsigned char x[], size_t d, + unsigned char w, const mbedtls_mpi *m ) +{ + size_t i, j; + unsigned char c, cc, adjust; + + memset( x, 0, d+1 ); + + /* First get the classical comb values (except for x_d = 0) */ + for( i = 0; i < d; i++ ) + for( j = 0; j < w; j++ ) + x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j; + + /* Now make sure x_1 .. x_d are odd */ + c = 0; + for( i = 1; i <= d; i++ ) + { + /* Add carry and update it */ + cc = x[i] & c; + x[i] = x[i] ^ c; + c = cc; + + /* Adjust if needed, avoiding branches */ + adjust = 1 - ( x[i] & 0x01 ); + c |= x[i] & ( x[i-1] * adjust ); + x[i] = x[i] ^ ( x[i-1] * adjust ); + x[i-1] |= adjust << 7; + } +} + +/* + * Precompute points for the adapted comb method + * + * Assumption: T must be able to hold 2^{w - 1} elements. + * + * Operation: If i = i_{w-1} ... i_1 is the binary representation of i, + * sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P. + * + * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) + * + * Note: Even comb values (those where P would be omitted from the + * sum defining T[i] above) are not needed in our adaption + * the comb method. See ecp_comb_recode_core(). + * + * This function currently works in four steps: + * (1) [dbl] Computation of intermediate T[i] for 2-power values of i + * (2) [norm_dbl] Normalization of coordinates of these T[i] + * (3) [add] Computation of all T[i] + * (4) [norm_add] Normalization of all T[i] + * + * Step 1 can be interrupted but not the others; together with the final + * coordinate normalization they are the largest steps done at once, depending + * on the window size. Here are operation counts for P-256: + * + * step (2) (3) (4) + * w = 5 142 165 208 + * w = 4 136 77 160 + * w = 3 130 33 136 + * w = 2 124 11 124 + * + * So if ECC operations are blocking for too long even with a low max_ops + * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order + * to minimize maximum blocking time. + */ +static int ecp_precompute_comb( const mbedtls_ecp_group *grp, + mbedtls_ecp_point T[], const mbedtls_ecp_point *P, + unsigned char w, size_t d, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + unsigned char i; + size_t j = 0; + const unsigned char T_size = 1U << ( w - 1 ); + mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) + goto dbl; + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl ) + goto norm_dbl; + if( rs_ctx->rsm->state == ecp_rsm_pre_add ) + goto add; + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add ) + goto norm_add; + } +#else + (void) rs_ctx; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + rs_ctx->rsm->state = ecp_rsm_pre_dbl; + + /* initial state for the loop */ + rs_ctx->rsm->i = 0; + } + +dbl: +#endif + /* + * Set T[0] = P and + * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) + j = rs_ctx->rsm->i; + else +#endif + j = 0; + + for( ; j < d * ( w - 1 ); j++ ) + { + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL ); + + i = 1U << ( j / d ); + cur = T + i; + + if( j % d == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); + + MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); + } + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl; + +norm_dbl: +#endif + /* + * Normalize current elements in T. As T has holes, + * use an auxiliary array of pointers to elements in T. + */ + j = 0; + for( i = 1; i < T_size; i <<= 1 ) + TT[j++] = T + i; + + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_add; + +add: +#endif + /* + * Compute the remaining ones using the minimal number of additions + * Be careful to update T[2^l] only after using it! + */ + MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD ); + + for( i = 1; i < T_size; i <<= 1 ) + { + j = i; + while( j-- ) + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); + } + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_norm_add; + +norm_add: +#endif + /* + * Normalize final elements in T. Even though there are no holes now, we + * still need the auxiliary array for homogeneity with the previous + * call. Also, skip T[0] which is already normalised, being a copy of P. + */ + for( j = 0; j + 1 < T_size; j++ ) + TT[j] = T + j + 1; + + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); + +cleanup: +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) + rs_ctx->rsm->i = j; + } +#endif + + return( ret ); +} + +/* + * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] + * + * See ecp_comb_recode_core() for background + */ +static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char T_size, + unsigned char i ) +{ + int ret; + unsigned char ii, j; + + /* Ignore the "sign" bit and scale down */ + ii = ( i & 0x7Fu ) >> 1; + + /* Read the whole table to thwart cache-based timing attacks */ + for( j = 0; j < T_size; j++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); + } + + /* Safely invert result if i is "negative" */ + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) ); + +cleanup: + return( ret ); +} + +/* + * Core multiplication algorithm for the (modified) comb method. + * This part is actually common with the basic comb method (GECC 3.44) + * + * Cost: d A + d D + 1 R + */ +static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char T_size, + const unsigned char x[], size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + mbedtls_ecp_point Txi; + size_t i; + + mbedtls_ecp_point_init( &Txi ); + +#if !defined(MBEDTLS_ECP_RESTARTABLE) + (void) rs_ctx; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + rs_ctx->rsm->state != ecp_rsm_comb_core ) + { + rs_ctx->rsm->i = 0; + rs_ctx->rsm->state = ecp_rsm_comb_core; + } + + /* new 'if' instead of nested for the sake of the 'else' branch */ + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) + { + /* restore current index (R already pointing to rs_ctx->rsm->R) */ + i = rs_ctx->rsm->i; + } + else +#endif + { + /* Start with a non-zero point and randomize its coordinates */ + i = d; + MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != 0 ) +#endif + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); + } + + while( i != 0 ) + { + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD ); + --i; + + MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); + MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); + } + +cleanup: + + mbedtls_ecp_point_free( &Txi ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + rs_ctx->rsm->i = i; + /* no need to save R, already pointing to rs_ctx->rsm->R */ + } +#endif + + return( ret ); +} + +/* + * Recode the scalar to get constant-time comb multiplication + * + * As the actual scalar recoding needs an odd scalar as a starting point, + * this wrapper ensures that by replacing m by N - m if necessary, and + * informs the caller that the result of multiplication will be negated. + * + * This works because we only support large prime order for Short Weierstrass + * curves, so N is always odd hence either m or N - m is. + * + * See ecp_comb_recode_core() for background. + */ +static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp, + const mbedtls_mpi *m, + unsigned char k[COMB_MAX_D + 1], + size_t d, + unsigned char w, + unsigned char *parity_trick ) +{ + int ret; + mbedtls_mpi M, mm; + + mbedtls_mpi_init( &M ); + mbedtls_mpi_init( &mm ); + + /* N is always odd (see above), just make extra sure */ + if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* do we need the parity trick? */ + *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 ); + + /* execute parity fix in constant time */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) ); + + /* actual scalar recoding */ + ecp_comb_recode_core( k, d, w, &M ); + +cleanup: + mbedtls_mpi_free( &mm ); + mbedtls_mpi_free( &M ); + + return( ret ); +} + +/* + * Perform comb multiplication (for short Weierstrass curves) + * once the auxiliary table has been pre-computed. + * + * Scalar recoding may use a parity trick that makes us compute -m * P, + * if that is the case we'll need to recover m * P at the end. + */ +static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *T, + unsigned char T_size, + unsigned char w, + size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + unsigned char parity_trick; + unsigned char k[COMB_MAX_D + 1]; + mbedtls_ecp_point *RR = R; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + RR = &rs_ctx->rsm->R; + + if( rs_ctx->rsm->state == ecp_rsm_final_norm ) + goto final_norm; + } +#endif + + MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, + &parity_trick ) ); + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d, + f_rng, p_rng, rs_ctx ) ); + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_final_norm; + +final_norm: + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); +#endif + /* + * Knowledge of the jacobian coordinates may leak the last few bits of the + * scalar [1], and since our MPI implementation isn't constant-flow, + * inversion (used for coordinate normalization) may leak the full value + * of its input via side-channels [2]. + * + * [1] https://eprint.iacr.org/2003/191 + * [2] https://eprint.iacr.org/2020/055 + * + * Avoid the leak by randomizing coordinates before we normalize them. + */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != 0 ) +#endif + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) ); +#endif + +cleanup: + return( ret ); +} + +/* + * Pick window size based on curve size and whether we optimize for base point + */ +static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp, + unsigned char p_eq_g ) +{ + unsigned char w; + + /* + * Minimize the number of multiplications, that is minimize + * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) + * (see costs of the various parts, with 1S = 1M) + */ + w = grp->nbits >= 384 ? 5 : 4; + + /* + * If P == G, pre-compute a bit more, since this may be re-used later. + * Just adding one avoids upping the cost of the first mul too much, + * and the memory cost too. + */ + if( p_eq_g ) + w++; + + /* + * Make sure w is within bounds. + * (The last test is useful only for very small curves in the test suite.) + */ + if( w > MBEDTLS_ECP_WINDOW_SIZE ) + w = MBEDTLS_ECP_WINDOW_SIZE; + if( w >= grp->nbits ) + w = 2; + + return( w ); +} + +/* + * Multiplication using the comb method - for curves in short Weierstrass form + * + * This function is mainly responsible for administrative work: + * - managing the restart context if enabled + * - managing the table of precomputed points (passed between the below two + * functions): allocation, computation, ownership tranfer, freeing. + * + * It delegates the actual arithmetic work to: + * ecp_precompute_comb() and ecp_mul_comb_with_precomp() + * + * See comments on ecp_comb_recode_core() regarding the computation strategy. + */ +static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + unsigned char w, p_eq_g, i; + size_t d; + unsigned char T_size = 0, T_ok = 0; + mbedtls_ecp_point *T = NULL; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_context drbg_ctx; + + ecp_drbg_init( &drbg_ctx ); +#endif + + ECP_RS_ENTER( rsm ); + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng == NULL ) + { + /* Adjust pointers */ + f_rng = &ecp_drbg_random; +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + p_rng = &rs_ctx->rsm->drbg_ctx; + else +#endif + p_rng = &drbg_ctx; + + /* Initialize internal DRBG if necessary */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx == NULL || rs_ctx->rsm == NULL || + rs_ctx->rsm->drbg_seeded == 0 ) +#endif + { + const size_t m_len = ( grp->nbits + 7 ) / 8; + MBEDTLS_MPI_CHK( ecp_drbg_seed( p_rng, m, m_len ) ); + } +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->drbg_seeded = 1; +#endif + } +#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */ + + /* Is P the base point ? */ +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); +#else + p_eq_g = 0; +#endif + + /* Pick window size and deduce related sizes */ + w = ecp_pick_window_size( grp, p_eq_g ); + T_size = 1U << ( w - 1 ); + d = ( grp->nbits + w - 1 ) / w; + + /* Pre-computed table: do we have it already for the base point? */ + if( p_eq_g && grp->T != NULL ) + { + /* second pointer to the same table, will be deleted on exit */ + T = grp->T; + T_ok = 1; + } + else +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* Pre-computed table: do we have one in progress? complete? */ + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL ) + { + /* transfer ownership of T from rsm to local function */ + T = rs_ctx->rsm->T; + rs_ctx->rsm->T = NULL; + rs_ctx->rsm->T_size = 0; + + /* This effectively jumps to the call to mul_comb_after_precomp() */ + T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core; + } + else +#endif + /* Allocate table if we didn't have any */ + { + T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) ); + if( T == NULL ) + { + ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; + goto cleanup; + } + + for( i = 0; i < T_size; i++ ) + mbedtls_ecp_point_init( &T[i] ); + + T_ok = 0; + } + + /* Compute table (or finish computing it) if not done already */ + if( !T_ok ) + { + MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) ); + + if( p_eq_g ) + { + /* almost transfer ownership of T to the group, but keep a copy of + * the pointer to use for calling the next function more easily */ + grp->T = T; + grp->T_size = T_size; + } + } + + /* Actual comb multiplication using precomputed points */ + MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m, + T, T_size, w, d, + f_rng, p_rng, rs_ctx ) ); + +cleanup: + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_free( &drbg_ctx ); +#endif + + /* does T belong to the group? */ + if( T == grp->T ) + T = NULL; + + /* does T belong to the restart context? */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL ) + { + /* transfer ownership of T from local function to rsm */ + rs_ctx->rsm->T_size = T_size; + rs_ctx->rsm->T = T; + T = NULL; + } +#endif + + /* did T belong to us? then let's destroy it! */ + if( T != NULL ) + { + for( i = 0; i < T_size; i++ ) + mbedtls_ecp_point_free( &T[i] ); + mbedtls_free( T ); + } + + /* don't free R while in progress in case R == P */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) +#endif + /* prevent caller from using invalid value */ + if( ret != 0 ) + mbedtls_ecp_point_free( R ); + + ECP_RS_LEAVE( rsm ); + + return( ret ); +} + +#endif /* ECP_SHORTWEIERSTRASS */ + +#if defined(ECP_MONTGOMERY) +/* + * For Montgomery curves, we do all the internal arithmetic in projective + * coordinates. Import/export of points uses only the x coordinates, which is + * internaly represented as X / Z. + * + * For scalar multiplication, we'll use a Montgomery ladder. + */ + +/* + * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1 + * Cost: 1M + 1I + */ +static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P ) +{ + int ret; + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_mxz( grp, P ) ); +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_mxz(). + * + * This countermeasure was first suggested in [2]. + * Cost: 2M + */ +static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_mpi l; + size_t p_size; + int count = 0; + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ); +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ + + p_size = ( grp->pbits + 7 ) / 8; + mbedtls_mpi_init( &l ); + + /* Generate l such that 1 < l < p */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z ); + +cleanup: + mbedtls_mpi_free( &l ); + + return( ret ); +} + +/* + * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), + * for Montgomery curves in x/z coordinates. + * + * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 + * with + * d = X1 + * P = (X2, Z2) + * Q = (X3, Z3) + * R = (X4, Z4) + * S = (X5, Z5) + * and eliminating temporary variables tO, ..., t4. + * + * Cost: 5M + 4S + */ +static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, + const mbedtls_mpi *d ) +{ + int ret; + mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) ); +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); + mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &E, &R->Z ) ); MOD_MUL( R->Z ); + +cleanup: + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B ); + mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB ); + + return( ret ); +} + +/* + * Multiplication with Montgomery ladder in x/z coordinates, + * for curves in Montgomery form + */ +static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t i; + unsigned char b; + mbedtls_ecp_point RP; + mbedtls_mpi PX; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_context drbg_ctx; + + ecp_drbg_init( &drbg_ctx ); +#endif + mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX ); + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng == NULL ) + { + const size_t m_len = ( grp->nbits + 7 ) / 8; + MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) ); + f_rng = &ecp_drbg_random; + p_rng = &drbg_ctx; + } +#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */ + + /* Save PX and read from P before writing to R, in case P == R */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) ); + + /* Set R to zero in modified x/z coordinates */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) ); + mbedtls_mpi_free( &R->Y ); + + /* RP.X might be sligtly larger than P, so reduce it */ + MOD_ADD( RP.X ); + + /* Randomize coordinates of the starting point */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != NULL ) +#endif + MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); + + /* Loop invariant: R = result so far, RP = R + P */ + i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */ + while( i-- > 0 ) + { + b = mbedtls_mpi_get_bit( m, i ); + /* + * if (b) R = 2R + P else R = 2R, + * which is: + * if (b) double_add( RP, R, RP, R ) + * else double_add( R, RP, R, RP ) + * but using safe conditional swaps to avoid leaks + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + } + + /* + * Knowledge of the projective coordinates may leak the last few bits of the + * scalar [1], and since our MPI implementation isn't constant-flow, + * inversion (used for coordinate normalization) may leak the full value + * of its input via side-channels [2]. + * + * [1] https://eprint.iacr.org/2003/191 + * [2] https://eprint.iacr.org/2020/055 + * + * Avoid the leak by randomizing coordinates before we normalize them. + */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != NULL ) +#endif + MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); + +cleanup: +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_free( &drbg_ctx ); +#endif + + mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); + + return( ret ); +} + +#endif /* ECP_MONTGOMERY */ + +/* + * Restartable multiplication R = m * P + */ +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* reset ops count for this call if top-level */ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) + rs_ctx->ops_done = 0; +#endif + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* skip argument check when restarting */ + if( rs_ctx == NULL || rs_ctx->rsm == NULL ) +#endif + { + /* check_privkey is free */ + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK ); + + /* Common sanity checks */ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) ); + } + + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) ); +#endif +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) ); +#endif + +cleanup: + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( is_grp_capable ) + mbedtls_internal_ecp_free( grp ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL ) + rs_ctx->depth--; +#endif + + return( ret ); +} + +/* + * Multiplication R = m * P + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) ); +} + +#if defined(ECP_SHORTWEIERSTRASS) +/* + * Check that an affine point is valid as a public key, + * short weierstrass curves (SEC1 3.2.3.1) + */ +static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + int ret; + mbedtls_mpi YY, RHS; + + /* pt coordinates must be normalized for our checks */ + if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 || + mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 || + mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || + mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS ); + + /* + * YY = Y^2 + * RHS = X (X^2 + A) + B = X^3 + A X + B + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS ); + + if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 ) + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + +cleanup: + + mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS ); + + return( ret ); +} +#endif /* ECP_SHORTWEIERSTRASS */ + +/* + * R = m * P with shortcuts for m == 1 and m == -1 + * NOT constant-time - ONLY for short Weierstrass! + */ +static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *P, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + + if( mbedtls_mpi_cmp_int( m, 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + } + else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P, + NULL, NULL, rs_ctx ) ); + } + +cleanup: + return( ret ); +} + +/* + * Restartable linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + mbedtls_ecp_point mP; + mbedtls_ecp_point *pmP = &mP; + mbedtls_ecp_point *pR = R; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( n != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + + if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + mbedtls_ecp_point_init( &mP ); + + ECP_RS_ENTER( ma ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + { + /* redirect intermediate results to restart context */ + pmP = &rs_ctx->ma->mP; + pR = &rs_ctx->ma->R; + + /* jump to next operation */ + if( rs_ctx->ma->state == ecp_rsma_mul2 ) + goto mul2; + if( rs_ctx->ma->state == ecp_rsma_add ) + goto add; + if( rs_ctx->ma->state == ecp_rsma_norm ) + goto norm; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_mul2; + +mul2: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) ); + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_add; + +add: +#endif + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_norm; + +norm: +#endif + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) ); +#endif + +cleanup: +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( is_grp_capable ) + mbedtls_internal_ecp_free( grp ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + + mbedtls_ecp_point_free( &mP ); + + ECP_RS_LEAVE( ma ); + + return( ret ); +} + +/* + * Linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( n != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) ); +} + +#if defined(ECP_MONTGOMERY) +/* + * Check validity of a public key for Montgomery curves with x-only schemes + */ +static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + /* [Curve25519 p. 5] Just check X is the correct number of bytes */ + /* Allow any public value, if it's too big then we'll just reduce it mod p + * (RFC 7748 sec. 5 para. 3). */ + if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( 0 ); +} +#endif /* ECP_MONTGOMERY */ + +/* + * Check that a point is valid as a public key + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + + /* Must use affine coordinates */ + if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + return( ecp_check_pubkey_mx( grp, pt ) ); +#endif +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + return( ecp_check_pubkey_sw( grp, pt ) ); +#endif + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Check that an mbedtls_mpi is valid as a private key + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, + const mbedtls_mpi *d ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + { + /* see RFC 7748 sec. 5 para. 5 */ + if( mbedtls_mpi_get_bit( d, 0 ) != 0 || + mbedtls_mpi_get_bit( d, 1 ) != 0 || + mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + /* see [Curve25519] page 5 */ + if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( 0 ); + } +#endif /* ECP_MONTGOMERY */ +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* see SEC1 3.2 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* ECP_SHORTWEIERSTRASS */ + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Generate a private key + */ +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + size_t n_size; + + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + n_size = ( grp->nbits + 7 ) / 8; + +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + { + /* [M225] page 5 */ + size_t b; + + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); + } while( mbedtls_mpi_bitlen( d ) == 0); + + /* Make sure the most significant bit is nbits */ + b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */ + if( b > grp->nbits ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) ); + + /* Make sure the last two bits are unset for Curve448, three bits for + Curve25519 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); + if( grp->nbits == 254 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); + } + } +#endif /* ECP_MONTGOMERY */ + +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* SEC1 3.2.1: Generate d such that 1 <= n < N */ + int count = 0; + unsigned cmp = 0; + + /* + * Match the procedure given in RFC 6979 (deterministic ECDSA): + * - use the same byte ordering; + * - keep the leftmost nbits bits of the generated octet string; + * - try until result is in the desired range. + * This also avoids any biais, which is especially important for ECDSA. + */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) ); + + /* + * Each try has at worst a probability 1/2 of failing (the msb has + * a probability 1/2 of being 0, and then the result will be < N), + * so after 30 tries failure probability is a most 2**(-30). + * + * For most curves, 1 try is enough with overwhelming probability, + * since N starts with a lot of 1s in binary, but some curves + * such as secp224k1 are actually very close to the worst case. + */ + if( ++count > 30 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + + ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp ); + if( ret != 0 ) + { + goto cleanup; + } + } + while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 ); + } +#endif /* ECP_SHORTWEIERSTRASS */ + +cleanup: + return( ret ); +} + +/* + * Generate a keypair with configurable base point + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( G != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); + +cleanup: + return( ret ); +} + +/* + * Generate key pair, wrapper for conventional base point + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) ); +} + +/* + * Generate a keypair, prettier wrapper + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + ECP_VALIDATE_RET( key != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) ); +} + +/* + * Check a public-private key pair + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ) +{ + int ret; + mbedtls_ecp_point Q; + mbedtls_ecp_group grp; + ECP_VALIDATE_RET( pub != NULL ); + ECP_VALIDATE_RET( prv != NULL ); + + if( pub->grp.id == MBEDTLS_ECP_DP_NONE || + pub->grp.id != prv->grp.id || + mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + mbedtls_ecp_point_init( &Q ); + mbedtls_ecp_group_init( &grp ); + + /* mbedtls_ecp_mul() needs a non-const group... */ + mbedtls_ecp_group_copy( &grp, &prv->grp ); + + /* Also checks d is valid */ + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) ); + + if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &Q ); + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(ECP_ONE_STEP_KDF) +/* + * There are no test vectors from NIST for the One-Step KDF in SP 800-56C, + * but unofficial ones can be found at: + * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors + * + * We only use the ones with empty fixedInfo, and for brevity's sake, only + * 40-bytes output (with SHA-256 that's more than one block, and with SHA-512 + * less than one block). + */ +#if defined(MBEDTLS_SHA512_C) + +static const uint8_t test_kdf_z[16] = { + 0x3b, 0xa9, 0x79, 0xe9, 0xbc, 0x5e, 0x3e, 0xc7, + 0x61, 0x30, 0x36, 0xb6, 0xf5, 0x1c, 0xd5, 0xaa, +}; +static const uint8_t test_kdf_out[40] = { + 0x3e, 0xf6, 0xda, 0xf9, 0x51, 0x60, 0x70, 0x5f, + 0xdf, 0x21, 0xcd, 0xab, 0xac, 0x25, 0x7b, 0x05, + 0xfe, 0xc1, 0xab, 0x7c, 0xc9, 0x68, 0x43, 0x25, + 0x8a, 0xfc, 0x40, 0x6e, 0x5b, 0xf7, 0x98, 0x27, + 0x10, 0xfa, 0x7b, 0x93, 0x52, 0xd4, 0x16, 0xaa, +}; + +#elif defined(MBEDTLS_SHA256_C) + +static const uint8_t test_kdf_z[16] = { + 0xc8, 0x3e, 0x35, 0x8e, 0x99, 0xa6, 0x89, 0xc6, + 0x7d, 0xb4, 0xfe, 0x39, 0xcf, 0x8f, 0x26, 0xe1, +}; +static const uint8_t test_kdf_out[40] = { + 0x7d, 0xf6, 0x41, 0xf8, 0x3c, 0x47, 0xdc, 0x28, + 0x5f, 0x7f, 0xaa, 0xde, 0x05, 0x64, 0xd6, 0x25, + 0x00, 0x6a, 0x47, 0xd9, 0x1e, 0xa4, 0xa0, 0x8c, + 0xd7, 0xf7, 0x0c, 0x99, 0xaa, 0xa0, 0x72, 0x66, + 0x69, 0x0e, 0x25, 0xaa, 0xa1, 0x63, 0x14, 0x79, +}; + +#endif + +static int ecp_kdf_self_test( void ) +{ + int ret; + ecp_drbg_context kdf_ctx; + mbedtls_mpi scalar; + uint8_t out[sizeof( test_kdf_out )]; + + ecp_drbg_init( &kdf_ctx ); + mbedtls_mpi_init( &scalar ); + memset( out, 0, sizeof( out ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar, + test_kdf_z, sizeof( test_kdf_z ) ) ); + + MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx, + &scalar, sizeof( test_kdf_z ) ) ); + + MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) ); + + if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 ) + ret = -1; + +cleanup: + ecp_drbg_free( &kdf_ctx ); + mbedtls_mpi_free( &scalar ); + + return( ret ); +} +#endif /* ECP_ONE_STEP_KDF */ + +/* + * Checkup routine + */ +int mbedtls_ecp_self_test( int verbose ) +{ + int ret; + size_t i; + mbedtls_ecp_group grp; + mbedtls_ecp_point R, P; + mbedtls_mpi m; + unsigned long add_c_prev, dbl_c_prev, mul_c_prev; + /* exponents especially adapted for secp192r1 */ + const char *exponents[] = + { + "000000000000000000000000000000000000000000000001", /* one */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */ + "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ + "400000000000000000000000000000000000000000000000", /* one and zeros */ + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ + "555555555555555555555555555555555555555555555555", /* 101010... */ + }; + + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &R ); + mbedtls_ecp_point_init( &P ); + mbedtls_mpi_init( &m ); + + /* Use secp192r1 if available, or any available curve */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) ); +#else + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) ); +#endif + + if( verbose != 0 ) + mbedtls_printf( " ECP test #1 (constant op_count, base point G): " ); + + /* Do a dummy multiplication first to trigger precomputation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) ); + + add_count = 0; + dbl_count = 0; + mul_count = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); + + for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (%u)\n", (unsigned int) i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " ECP test #2 (constant op_count, other point): " ); + /* We computed P = 2G last time, use it */ + + add_count = 0; + dbl_count = 0; + mul_count = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); + + for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (%u)\n", (unsigned int) i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +#if defined(ECP_ONE_STEP_KDF) + if( verbose != 0 ) + mbedtls_printf( " ECP test #3 (internal KDF): " ); + + ret = ecp_kdf_self_test(); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* ECP_ONE_STEP_KDF */ + +cleanup: + + if( ret < 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); + + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &R ); + mbedtls_ecp_point_free( &P ); + mbedtls_mpi_free( &m ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* !MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_C */ diff --git a/external/mbedtls/library/ecp_curves.c b/external/mbedtls/library/ecp_curves.c new file mode 100644 index 0000000..b04596b --- /dev/null +++ b/external/mbedtls/library/ecp_curves.c @@ -0,0 +1,1495 @@ +/* + * Elliptic curves over GF(p): curve-specific data and functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECP_C) + +#include "mbedtls/ecp.h" +#include "mbedtls/platform_util.h" + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECP_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECP_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* + * Conversion macros for embedded constants: + * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 + */ +#if defined(MBEDTLS_HAVE_INT32) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + ( (mbedtls_mpi_uint) (a) << 0 ) | \ + ( (mbedtls_mpi_uint) (b) << 8 ) | \ + ( (mbedtls_mpi_uint) (c) << 16 ) | \ + ( (mbedtls_mpi_uint) (d) << 24 ) + +#define BYTES_TO_T_UINT_2( a, b ) \ + BYTES_TO_T_UINT_4( a, b, 0, 0 ) + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + BYTES_TO_T_UINT_4( a, b, c, d ), \ + BYTES_TO_T_UINT_4( e, f, g, h ) + +#else /* 64-bits */ + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + ( (mbedtls_mpi_uint) (a) << 0 ) | \ + ( (mbedtls_mpi_uint) (b) << 8 ) | \ + ( (mbedtls_mpi_uint) (c) << 16 ) | \ + ( (mbedtls_mpi_uint) (d) << 24 ) | \ + ( (mbedtls_mpi_uint) (e) << 32 ) | \ + ( (mbedtls_mpi_uint) (f) << 40 ) | \ + ( (mbedtls_mpi_uint) (g) << 48 ) | \ + ( (mbedtls_mpi_uint) (h) << 56 ) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 ) + +#define BYTES_TO_T_UINT_2( a, b ) \ + BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 ) + +#endif /* bits in mbedtls_mpi_uint */ + +/* + * Note: the constants are in little-endian order + * to be directly usable in MPIs + */ + +/* + * Domain parameters for secp192r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static const mbedtls_mpi_uint secp192r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192r1_b[] = { + BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ), + BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ), + BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ), +}; +static const mbedtls_mpi_uint secp192r1_gx[] = { + BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ), + BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ), + BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ), +}; +static const mbedtls_mpi_uint secp192r1_gy[] = { + BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ), + BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ), + BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ), +}; +static const mbedtls_mpi_uint secp192r1_n[] = { + BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ), + BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +/* + * Domain parameters for secp224r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static const mbedtls_mpi_uint secp224r1_p[] = { + BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_b[] = { + BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ), + BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ), + BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ), + BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ), +}; +static const mbedtls_mpi_uint secp224r1_gx[] = { + BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ), + BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ), + BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ), + BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ), +}; +static const mbedtls_mpi_uint secp224r1_gy[] = { + BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ), + BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ), + BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ), + BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ), +}; +static const mbedtls_mpi_uint secp224r1_n[] = { + BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ), + BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +/* + * Domain parameters for secp256r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static const mbedtls_mpi_uint secp256r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256r1_b[] = { + BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ), + BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ), + BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ), + BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ), +}; +static const mbedtls_mpi_uint secp256r1_gx[] = { + BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), + BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ), + BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ), + BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ), +}; +static const mbedtls_mpi_uint secp256r1_gy[] = { + BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ), + BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ), + BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ), + BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ), +}; +static const mbedtls_mpi_uint secp256r1_n[] = { + BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ), + BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +/* + * Domain parameters for secp384r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static const mbedtls_mpi_uint secp384r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp384r1_b[] = { + BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ), + BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ), + BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ), + BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ), + BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ), + BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ), +}; +static const mbedtls_mpi_uint secp384r1_gx[] = { + BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ), + BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ), + BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ), + BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ), + BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ), + BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ), +}; +static const mbedtls_mpi_uint secp384r1_gy[] = { + BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ), + BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ), + BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ), + BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ), + BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ), + BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ), +}; +static const mbedtls_mpi_uint secp384r1_n[] = { + BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ), + BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ), + BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +/* + * Domain parameters for secp521r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static const mbedtls_mpi_uint secp521r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_b[] = { + BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ), + BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ), + BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ), + BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ), + BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ), + BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ), + BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ), + BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ), + BYTES_TO_T_UINT_2( 0x51, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gx[] = { + BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ), + BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ), + BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ), + BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ), + BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ), + BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ), + BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ), + BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ), + BYTES_TO_T_UINT_2( 0xC6, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gy[] = { + BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ), + BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ), + BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ), + BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ), + BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ), + BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ), + BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ), + BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ), + BYTES_TO_T_UINT_2( 0x18, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_n[] = { + BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ), + BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ), + BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ), + BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ), + BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static const mbedtls_mpi_uint secp192k1_p[] = { + BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_b[] = { + BYTES_TO_T_UINT_2( 0x03, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_gx[] = { + BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ), + BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ), + BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ), +}; +static const mbedtls_mpi_uint secp192k1_gy[] = { + BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ), + BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ), + BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ), +}; +static const mbedtls_mpi_uint secp192k1_n[] = { + BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ), + BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static const mbedtls_mpi_uint secp224k1_p[] = { + BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp224k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_b[] = { + BYTES_TO_T_UINT_2( 0x05, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_gx[] = { + BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ), + BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ), + BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ), + BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ), +}; +static const mbedtls_mpi_uint secp224k1_gy[] = { + BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ), + BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ), + BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ), + BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ), +}; +static const mbedtls_mpi_uint secp224k1_n[] = { + BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ), + BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), +}; +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static const mbedtls_mpi_uint secp256k1_p[] = { + BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_b[] = { + BYTES_TO_T_UINT_2( 0x07, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_gx[] = { + BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ), + BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ), + BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ), + BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ), +}; +static const mbedtls_mpi_uint secp256k1_gy[] = { + BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ), + BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ), + BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ), + BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ), +}; +static const mbedtls_mpi_uint secp256k1_n[] = { + BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ), + BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +/* + * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) + */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP256r1_p[] = { + BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ), + BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ), + BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_a[] = { + BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ), + BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ), + BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ), + BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_b[] = { + BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ), + BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ), + BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ), + BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { + BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ), + BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ), + BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ), + BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { + BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ), + BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ), + BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ), + BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_n[] = { + BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ), + BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ), + BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +/* + * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) + */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP384r1_p[] = { + BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ), + BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ), + BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ), + BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_a[] = { + BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), + BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ), + BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ), + BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ), + BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ), + BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_b[] = { + BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ), + BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ), + BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ), + BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ), + BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ), + BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { + BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ), + BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ), + BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ), + BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ), + BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ), + BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { + BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ), + BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ), + BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ), + BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ), + BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ), + BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_n[] = { + BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ), + BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ), + BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ), + BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +/* + * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) + */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP512r1_p[] = { + BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ), + BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ), + BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ), + BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ), + BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_a[] = { + BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ), + BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ), + BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ), + BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ), + BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ), + BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ), + BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ), + BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_b[] = { + BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ), + BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ), + BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ), + BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ), + BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ), + BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ), + BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ), + BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { + BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ), + BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ), + BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ), + BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ), + BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ), + BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ), + BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ), + BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { + BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ), + BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ), + BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ), + BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ), + BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ), + BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ), + BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ), + BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_n[] = { + BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ), + BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ), + BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ), + BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ), + BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +/* + * Create an MPI from embedded constants + * (assumes len is an exact multiple of sizeof mbedtls_mpi_uint) + */ +static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len ) +{ + X->s = 1; + X->n = len / sizeof( mbedtls_mpi_uint ); + X->p = (mbedtls_mpi_uint *) p; +} + +/* + * Set an MPI to static value 1 + */ +static inline void ecp_mpi_set1( mbedtls_mpi *X ) +{ + static mbedtls_mpi_uint one[] = { 1 }; + X->s = 1; + X->n = 1; + X->p = one; +} + +/* + * Make group available from embedded constants + */ +static int ecp_group_load( mbedtls_ecp_group *grp, + const mbedtls_mpi_uint *p, size_t plen, + const mbedtls_mpi_uint *a, size_t alen, + const mbedtls_mpi_uint *b, size_t blen, + const mbedtls_mpi_uint *gx, size_t gxlen, + const mbedtls_mpi_uint *gy, size_t gylen, + const mbedtls_mpi_uint *n, size_t nlen) +{ + ecp_mpi_load( &grp->P, p, plen ); + if( a != NULL ) + ecp_mpi_load( &grp->A, a, alen ); + ecp_mpi_load( &grp->B, b, blen ); + ecp_mpi_load( &grp->N, n, nlen ); + + ecp_mpi_load( &grp->G.X, gx, gxlen ); + ecp_mpi_load( &grp->G.Y, gy, gylen ); + ecp_mpi_set1( &grp->G.Z ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + grp->h = 1; + + return( 0 ); +} + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* Forward declarations */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static int ecp_mod_p192( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static int ecp_mod_p224( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static int ecp_mod_p256( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static int ecp_mod_p384( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static int ecp_mod_p521( mbedtls_mpi * ); +#endif + +#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P; +#else +#define NIST_MODP( P ) +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +/* Additional forward declarations */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +static int ecp_mod_p255( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +static int ecp_mod_p448( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static int ecp_mod_p192k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static int ecp_mod_p224k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static int ecp_mod_p256k1( mbedtls_mpi * ); +#endif + +#define LOAD_GROUP_A( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + G ## _a, sizeof( G ## _a ), \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) + +#define LOAD_GROUP( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + NULL, 0, \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +/* + * Specialized function for creating the Curve25519 group + */ +static int ecp_use_curve25519( mbedtls_ecp_group *grp ) +{ + int ret; + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "01DB42" ) ); + + /* P = 2^255 - 19 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 255 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 19 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* N = 2^252 + 27742317777372353535851937790883648493 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->N, 16, + "14DEF9DEA2F79CD65812631A5CF5D3ED" ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 252, 1 ) ); + + /* Y intentionally not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 9 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* Actually, the required msb for private keys */ + grp->nbits = 254; + +cleanup: + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +/* + * Specialized function for creating the Curve448 group + */ +static int ecp_use_curve448( mbedtls_ecp_group *grp ) +{ + mbedtls_mpi Ns; + int ret; + + mbedtls_mpi_init( &Ns ); + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "98AA" ) ); + + /* P = 2^448 - 2^224 - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* Y intentionally not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 5 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 446, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &Ns, 16, + "8335DC163BB124B65129C96FDE933D8D723A70AADC873D6D54A7BB0D" ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &grp->N, &grp->N, &Ns ) ); + + /* Actually, the required msb for private keys */ + grp->nbits = 447; + +cleanup: + mbedtls_mpi_free( &Ns ); + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +/* + * Set a group using well-known domain parameters + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) +{ + ECP_VALIDATE_RET( grp != NULL ); + mbedtls_ecp_group_free( grp ); + + grp->id = id; + + switch( id ) + { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case MBEDTLS_ECP_DP_SECP192R1: + NIST_MODP( p192 ); + return( LOAD_GROUP( secp192r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case MBEDTLS_ECP_DP_SECP224R1: + NIST_MODP( p224 ); + return( LOAD_GROUP( secp224r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case MBEDTLS_ECP_DP_SECP256R1: + NIST_MODP( p256 ); + return( LOAD_GROUP( secp256r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case MBEDTLS_ECP_DP_SECP384R1: + NIST_MODP( p384 ); + return( LOAD_GROUP( secp384r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case MBEDTLS_ECP_DP_SECP521R1: + NIST_MODP( p521 ); + return( LOAD_GROUP( secp521r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case MBEDTLS_ECP_DP_SECP192K1: + grp->modp = ecp_mod_p192k1; + return( LOAD_GROUP_A( secp192k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case MBEDTLS_ECP_DP_SECP224K1: + grp->modp = ecp_mod_p224k1; + return( LOAD_GROUP_A( secp224k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case MBEDTLS_ECP_DP_SECP256K1: + grp->modp = ecp_mod_p256k1; + return( LOAD_GROUP_A( secp256k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case MBEDTLS_ECP_DP_BP256R1: + return( LOAD_GROUP_A( brainpoolP256r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case MBEDTLS_ECP_DP_BP384R1: + return( LOAD_GROUP_A( brainpoolP384r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case MBEDTLS_ECP_DP_BP512R1: + return( LOAD_GROUP_A( brainpoolP512r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + case MBEDTLS_ECP_DP_CURVE25519: + grp->modp = ecp_mod_p255; + return( ecp_use_curve25519( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + case MBEDTLS_ECP_DP_CURVE448: + grp->modp = ecp_mod_p448; + return( ecp_use_curve448( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + + default: + mbedtls_ecp_group_free( grp ); + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } +} + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* + * Fast reduction modulo the primes used by the NIST curves. + * + * These functions are critical for speed, but not needed for correct + * operations. So, we make the choice to heavily rely on the internals of our + * bignum library, which creates a tight coupling between these functions and + * our MPI implementation. However, the coupling between the ECP module and + * MPI remains loose, since these functions can be deactivated at will. + */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +/* + * Compared to the way things are presented in FIPS 186-3 D.2, + * we proceed in columns, from right (least significant chunk) to left, + * adding chunks to N in place, and keeping a carry for the next chunk. + * This avoids moving things around in memory, and uselessly adding zeros, + * compared to the more straightforward, line-oriented approach. + * + * For this prime we need to handle data in chunks of 64 bits. + * Since this is always a multiple of our basic mbedtls_mpi_uint, we can + * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. + */ + +/* Add 64-bit chunks (dst += src) and update carry */ +static inline void add64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + mbedtls_mpi_uint c = 0; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++, src++ ) + { + *dst += c; c = ( *dst < c ); + *dst += *src; c += ( *dst < *src ); + } + *carry += c; +} + +/* Add carry to a 64-bit chunk and update carry */ +static inline void carry64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++ ) + { + *dst += *carry; + *carry = ( *dst < *carry ); + } +} + +#define WIDTH 8 / sizeof( mbedtls_mpi_uint ) +#define A( i ) N->p + (i) * WIDTH +#define ADD( i ) add64( p, A( i ), &c ) +#define NEXT p += WIDTH; carry64( p, &c ) +#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0 + +/* + * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + */ +static int ecp_mod_p192( mbedtls_mpi *N ) +{ + int ret; + mbedtls_mpi_uint c = 0; + mbedtls_mpi_uint *p, *end; + + /* Make sure we have enough blocks so that A(5) is legal */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, 6 * WIDTH ) ); + + p = N->p; + end = p + N->n; + + ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5 + ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5 + ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5 + +cleanup: + return( ret ); +} + +#undef WIDTH +#undef A +#undef ADD +#undef NEXT +#undef LAST +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * The reader is advised to first understand ecp_mod_p192() since the same + * general structure is used here, but with additional complications: + * (1) chunks of 32 bits, and (2) subtractions. + */ + +/* + * For these primes, we need to handle data in chunks of 32 bits. + * This makes it more complicated if we use 64 bits limbs in MPI, + * which prevents us from using a uniform access method as for p192. + * + * So, we define a mini abstraction layer to access 32 bit chunks, + * load them in 'cur' for work, and store them back from 'cur' when done. + * + * While at it, also define the size of N in terms of 32-bit chunks. + */ +#define LOAD32 cur = A( i ); + +#if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ + +#define MAX32 N->n +#define A( j ) N->p[j] +#define STORE32 N->p[i] = cur; + +#else /* 64-bit */ + +#define MAX32 N->n * 2 +#define A( j ) (j) % 2 ? (uint32_t)( N->p[(j)/2] >> 32 ) : \ + (uint32_t)( N->p[(j)/2] ) +#define STORE32 \ + if( i % 2 ) { \ + N->p[i/2] &= 0x00000000FFFFFFFF; \ + N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32; \ + } else { \ + N->p[i/2] &= 0xFFFFFFFF00000000; \ + N->p[i/2] |= (mbedtls_mpi_uint) cur; \ + } + +#endif /* sizeof( mbedtls_mpi_uint ) */ + +/* + * Helpers for addition and subtraction of chunks, with signed carry. + */ +static inline void add32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *dst += src; + *carry += ( *dst < src ); +} + +static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *carry -= ( *dst < src ); + *dst -= src; +} + +#define ADD( j ) add32( &cur, A( j ), &c ); +#define SUB( j ) sub32( &cur, A( j ), &c ); + +/* + * Helpers for the main 'loop' + * (see fix_negative for the motivation of C) + */ +#define INIT( b ) \ + int ret; \ + signed char c = 0, cc; \ + uint32_t cur; \ + size_t i = 0, bits = (b); \ + mbedtls_mpi C; \ + mbedtls_mpi_uint Cp[ (b) / 8 / sizeof( mbedtls_mpi_uint) + 1 ]; \ + \ + C.s = 1; \ + C.n = (b) / 8 / sizeof( mbedtls_mpi_uint) + 1; \ + C.p = Cp; \ + memset( Cp, 0, C.n * sizeof( mbedtls_mpi_uint ) ); \ + \ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, (b) * 2 / 8 / \ + sizeof( mbedtls_mpi_uint ) ) ); \ + LOAD32; + +#define NEXT \ + STORE32; i++; LOAD32; \ + cc = c; c = 0; \ + if( cc < 0 ) \ + sub32( &cur, -cc, &c ); \ + else \ + add32( &cur, cc, &c ); \ + +#define LAST \ + STORE32; i++; \ + cur = c > 0 ? c : 0; STORE32; \ + cur = 0; while( ++i < MAX32 ) { STORE32; } \ + if( c < 0 ) MBEDTLS_MPI_CHK( fix_negative( N, c, &C, bits ) ); + +/* + * If the result is negative, we get it in the form + * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits' + */ +static inline int fix_negative( mbedtls_mpi *N, signed char c, mbedtls_mpi *C, size_t bits ) +{ + int ret; + + /* C = - c * 2^(bits + 32) */ +#if !defined(MBEDTLS_HAVE_INT64) + ((void) bits); +#else + if( bits == 224 ) + C->p[ C->n - 1 ] = ((mbedtls_mpi_uint) -c) << 32; + else +#endif + C->p[ C->n - 1 ] = (mbedtls_mpi_uint) -c; + + /* N = - ( C - N ) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, C, N ) ); + N->s = -1; + +cleanup: + + return( ret ); +} + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +/* + * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) + */ +static int ecp_mod_p224( mbedtls_mpi *N ) +{ + INIT( 224 ); + + SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11 + SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12 + SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13 + SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11 + SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12 + SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13 + SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +/* + * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) + */ +static int ecp_mod_p256( mbedtls_mpi *N ) +{ + INIT( 256 ); + + ADD( 8 ); ADD( 9 ); + SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0 + + ADD( 9 ); ADD( 10 ); + SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1 + + ADD( 10 ); ADD( 11 ); + SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2 + + ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 ); + SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3 + + ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 ); + SUB( 9 ); SUB( 10 ); NEXT; // A4 + + ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 ); + SUB( 10 ); SUB( 11 ); NEXT; // A5 + + ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 ); + SUB( 8 ); SUB( 9 ); NEXT; // A6 + + ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 ); + SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) + */ +static int ecp_mod_p384( mbedtls_mpi *N ) +{ + INIT( 384 ); + + ADD( 12 ); ADD( 21 ); ADD( 20 ); + SUB( 23 ); NEXT; // A0 + + ADD( 13 ); ADD( 22 ); ADD( 23 ); + SUB( 12 ); SUB( 20 ); NEXT; // A2 + + ADD( 14 ); ADD( 23 ); + SUB( 13 ); SUB( 21 ); NEXT; // A2 + + ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 ); + SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3 + + ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 ); + SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4 + + ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 ); + SUB( 16 ); NEXT; // A5 + + ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 ); + SUB( 17 ); NEXT; // A6 + + ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 ); + SUB( 18 ); NEXT; // A7 + + ADD( 20 ); ADD( 17 ); ADD( 16 ); + SUB( 19 ); NEXT; // A8 + + ADD( 21 ); ADD( 18 ); ADD( 17 ); + SUB( 20 ); NEXT; // A9 + + ADD( 22 ); ADD( 19 ); ADD( 18 ); + SUB( 21 ); NEXT; // A10 + + ADD( 23 ); ADD( 20 ); ADD( 19 ); + SUB( 22 ); LAST; // A11 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#undef A +#undef LOAD32 +#undef STORE32 +#undef MAX32 +#undef INIT +#undef NEXT +#undef LAST + +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || + MBEDTLS_ECP_DP_SECP256R1_ENABLED || + MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +/* + * Here we have an actual Mersenne prime, so things are more straightforward. + * However, chunks are aligned on a 'weird' boundary (521 bits). + */ + +/* Size of p521 in terms of mbedtls_mpi_uint */ +#define P521_WIDTH ( 521 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* Bits to keep in the most significant mbedtls_mpi_uint */ +#define P521_MASK 0x01FF + +/* + * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) + * Write N as A1 + 2^521 A0, return A0 + A1 + */ +static int ecp_mod_p521( mbedtls_mpi *N ) +{ + int ret; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P521_WIDTH + 1]; + /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits: + * we need to hold bits 513 to 1056, which is 34 limbs, that is + * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ + + if( N->n < P521_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P521_WIDTH - 1 ); + if( M.n > P521_WIDTH + 1 ) + M.n = P521_WIDTH + 1; + M.p = Mp; + memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 521 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + + /* N = A0 */ + N->p[P521_WIDTH - 1] &= P521_MASK; + for( i = P521_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} + +#undef P521_WIDTH +#undef P521_MASK +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + +/* Size of p255 in terms of mbedtls_mpi_uint */ +#define P255_WIDTH ( 255 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* + * Fast quasi-reduction modulo p255 = 2^255 - 19 + * Write N as A0 + 2^255 A1, return A0 + 19 * A1 + */ +static int ecp_mod_p255( mbedtls_mpi *N ) +{ + int ret; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P255_WIDTH + 2]; + + if( N->n < P255_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P255_WIDTH - 1 ); + if( M.n > P255_WIDTH + 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + M.p = Mp; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 255 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + M.n++; /* Make room for multiplication by 19 */ + + /* N = A0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( N, 255, 0 ) ); + for( i = P255_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + 19 * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &M, 19 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + +/* Size of p448 in terms of mbedtls_mpi_uint */ +#define P448_WIDTH ( 448 / 8 / sizeof( mbedtls_mpi_uint ) ) + +/* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ +#define DIV_ROUND_UP( X, Y ) ( ( ( X ) + ( Y ) - 1 ) / ( Y ) ) +#define P224_WIDTH_MIN ( 28 / sizeof( mbedtls_mpi_uint ) ) +#define P224_WIDTH_MAX DIV_ROUND_UP( 28, sizeof( mbedtls_mpi_uint ) ) +#define P224_UNUSED_BITS ( ( P224_WIDTH_MAX * sizeof( mbedtls_mpi_uint ) * 8 ) - 224 ) + +/* + * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 + * Write N as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return + * A0 + A1 + B1 + (B0 + B1) * 2^224. This is different to the reference + * implementation of Curve448, which uses its own special 56-bit limbs rather + * than a generic bignum library. We could squeeze some extra speed out on + * 32-bit machines by splitting N up into 32-bit limbs and doing the + * arithmetic using the limbs directly as we do for the NIST primes above, + * but for 64-bit targets it should use half the number of operations if we do + * the reduction with 224-bit limbs, since mpi_add_mpi will then use 64-bit adds. + */ +static int ecp_mod_p448( mbedtls_mpi *N ) +{ + int ret; + size_t i; + mbedtls_mpi M, Q; + mbedtls_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH]; + + if( N->n <= P448_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P448_WIDTH ); + if( M.n > P448_WIDTH ) + /* Shouldn't be called with N larger than 2^896! */ + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + M.p = Mp; + memset( Mp, 0, sizeof( Mp ) ); + memcpy( Mp, N->p + P448_WIDTH, M.n * sizeof( mbedtls_mpi_uint ) ); + + /* N = A0 */ + for( i = P448_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N += A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); + + /* Q = B1, N += B1 */ + Q = M; + Q.p = Qp; + memcpy( Qp, Mp, sizeof( Qp ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Q, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &Q ) ); + + /* M = (B0 + B1) * 2^224, N += M */ + if( sizeof( mbedtls_mpi_uint ) > 4 ) + Mp[P224_WIDTH_MIN] &= ( (mbedtls_mpi_uint)-1 ) >> ( P224_UNUSED_BITS ); + for( i = P224_WIDTH_MAX; i < M.n; ++i ) + Mp[i] = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &Q ) ); + M.n = P448_WIDTH + 1; /* Make room for shifted carry bit from the addition */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &M, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo P = 2^s - R, + * with R about 33 bits, used by the Koblitz curves. + * + * Write N as A0 + 2^224 A1, return A0 + R * A1. + * Actually do two passes, since R is big. + */ +#define P_KOBLITZ_MAX ( 256 / 8 / sizeof( mbedtls_mpi_uint ) ) // Max limbs in P +#define P_KOBLITZ_R ( 8 / sizeof( mbedtls_mpi_uint ) ) // Limbs in R +static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs, + size_t adjust, size_t shift, mbedtls_mpi_uint mask ) +{ + int ret; + size_t i; + mbedtls_mpi M, R; + mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1]; + + if( N->n < p_limbs ) + return( 0 ); + + /* Init R */ + R.s = 1; + R.p = Rp; + R.n = P_KOBLITZ_R; + + /* Common setup for M */ + M.s = 1; + M.p = Mp; + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + + /* Second pass */ + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || + MBEDTLS_ECP_DP_SECP224K1_ENABLED) || + MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +/* + * Fast quasi-reduction modulo p192k1 = 2^192 - R, + * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 + */ +static int ecp_mod_p192k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + + return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +/* + * Fast quasi-reduction modulo p224k1 = 2^224 - R, + * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 + */ +static int ecp_mod_p224k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + +#if defined(MBEDTLS_HAVE_INT64) + return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) ); +#else + return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +#endif +} + +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo p256k1 = 2^256 - R, + * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 + */ +static int ecp_mod_p256k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#endif /* !MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_C */ diff --git a/external/mbedtls/library/entropy.c b/external/mbedtls/library/entropy.c new file mode 100644 index 0000000..c5f414a --- /dev/null +++ b/external/mbedtls/library/entropy.c @@ -0,0 +1,751 @@ +/* + * Entropy accumulator implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ENTROPY_C) + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +#warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! " +#warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES " +#warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE " +#endif + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif + +#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ + +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) +{ + ctx->source_count = 0; + memset( ctx->source, 0, sizeof( ctx->source ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + ctx->accumulator_started = 0; +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_init( &ctx->accumulator ); +#else + mbedtls_sha256_init( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_init( &ctx->havege_data ); +#endif + + /* Reminder: Update ENTROPY_HAVE_STRONG in the test files + * when adding more strong entropy sources here. */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, + 1, MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif + +#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, + MBEDTLS_ENTROPY_MIN_PLATFORM, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_TIMING_C) + mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDCLOCK, + MBEDTLS_ENTROPY_SOURCE_WEAK ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data, + MBEDTLS_ENTROPY_MIN_HAVEGE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDWARE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, + MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); + ctx->initial_entropy_run = 0; +#endif +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ +} + +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) +{ + /* If the context was already free, don't call free() again. + * This is important for mutexes which don't allow double-free. */ + if( ctx->accumulator_started == -1 ) + return; + +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_free( &ctx->havege_data ); +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_free( &ctx->accumulator ); +#else + mbedtls_sha256_free( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + ctx->initial_entropy_run = 0; +#endif + ctx->source_count = 0; + mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) ); + ctx->accumulator_started = -1; +} + +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ) +{ + int idx, ret = 0; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + idx = ctx->source_count; + if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES ) + { + ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; + goto exit; + } + + ctx->source[idx].f_source = f_source; + ctx->source[idx].p_source = p_source; + ctx->source[idx].threshold = threshold; + ctx->source[idx].strong = strong; + + ctx->source_count++; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Entropy accumulator update + */ +static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, + const unsigned char *data, size_t len ) +{ + unsigned char header[2]; + unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = len; + const unsigned char *p = data; + int ret = 0; + + if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + { +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; +#else + if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; +#endif + p = tmp; + use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + } + + header[0] = source_id; + header[1] = use_len & 0xFF; + + /* + * Start the accumulator if this has not already happened. Note that + * it is sufficient to start the accumulator here only because all calls to + * gather entropy eventually execute this code. + */ +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len ); +#else + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len ); +#endif + +cleanup: + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + + return( ret ); +} + +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ) +{ + int ret; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Run through the different sources to add entropy to our accumulator + */ +static int entropy_gather_internal( mbedtls_entropy_context *ctx ) +{ + int ret, i, have_one_strong = 0; + unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; + size_t olen; + + if( ctx->source_count == 0 ) + return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED ); + + /* + * Run through our entropy sources + */ + for( i = 0; i < ctx->source_count; i++ ) + { + if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) + have_one_strong = 1; + + olen = 0; + if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, + buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) + { + goto cleanup; + } + + /* + * Add if we actually gathered something + */ + if( olen > 0 ) + { + if( ( ret = entropy_update( ctx, (unsigned char) i, + buf, olen ) ) != 0 ) + return( ret ); + ctx->source[i].size += olen; + } + } + + if( have_one_strong == 0 ) + ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +/* + * Thread-safe wrapper for entropy_gather_internal() + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ) +{ + int ret; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_gather_internal( ctx ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) +{ + int ret, count = 0, i, done; + mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) + /* Update the NV entropy seed before generating any entropy for outside + * use. + */ + if( ctx->initial_entropy_run == 0 ) + { + ctx->initial_entropy_run = 1; + if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 ) + return( ret ); + } +#endif + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* + * Always gather extra entropy before a call + */ + do + { + if( count++ > ENTROPY_MAX_LOOP ) + { + ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + goto exit; + } + + if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) + goto exit; + + done = 1; + for( i = 0; i < ctx->source_count; i++ ) + if( ctx->source[i].size < ctx->source[i].threshold ) + done = 0; + } + while( ! done ); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + /* + * Note that at this stage it is assumed that the accumulator was started + * in a previous call to entropy_update(). If this is not guaranteed, the + * code below will fail. + */ + if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 ) + goto exit; + + /* + * Reset accumulator and counters and recycle existing entropy + */ + mbedtls_sha512_free( &ctx->accumulator ); + mbedtls_sha512_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + /* + * Perform second SHA-512 on entropy + */ + if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; +#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 ) + goto exit; + + /* + * Reset accumulator and counters and recycle existing entropy + */ + mbedtls_sha256_free( &ctx->accumulator ); + mbedtls_sha256_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + /* + * Perform second SHA-256 on entropy + */ + if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; +#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + + for( i = 0; i < ctx->source_count; i++ ) + ctx->source[i].size = 0; + + memcpy( output, buf, len ); + + ret = 0; + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) +{ + int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + /* Read new seed and write it to NV */ + if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + return( ret ); + + if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + /* Manually update the remaining stream with a separator value to diverge */ + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + return( ret ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + FILE *f; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE ) + { + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + fclose( f ); + return( ret ); +} + +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + int ret = 0; + FILE *f; + size_t n; + unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) + n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; + + if( fread( buf, 1, n, f ) != n ) + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + else + ret = mbedtls_entropy_update_manual( ctx, buf, n ); + + fclose( f ); + + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); + + return( mbedtls_entropy_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) +/* + * Dummy source function + */ +static int entropy_dummy_source( void *data, unsigned char *output, + size_t len, size_t *olen ) +{ + ((void) data); + + memset( output, 0x2a, len ); + *olen = len; + + return( 0 ); +} +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + +static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len ) +{ + int ret = 0; + size_t entropy_len = 0; + size_t olen = 0; + size_t attempts = buf_len; + + while( attempts > 0 && entropy_len < buf_len ) + { + if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len, + buf_len - entropy_len, &olen ) ) != 0 ) + return( ret ); + + entropy_len += olen; + attempts--; + } + + if( entropy_len < buf_len ) + { + ret = 1; + } + + return( ret ); +} + + +static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf, + size_t buf_len ) +{ + unsigned char set= 0xFF; + unsigned char unset = 0x00; + size_t i; + + for( i = 0; i < buf_len; i++ ) + { + set &= buf[i]; + unset |= buf[i]; + } + + return( set == 0xFF || unset == 0x00 ); +} + +/* + * A test to ensure hat the entropy sources are functioning correctly + * and there is no obvious failure. The test performs the following checks: + * - The entropy source is not providing only 0s (all bits unset) or 1s (all + * bits set). + * - The entropy source is not providing values in a pattern. Because the + * hardware could be providing data in an arbitrary length, this check polls + * the hardware entropy source twice and compares the result to ensure they + * are not equal. + * - The error code returned by the entropy source is not an error. + */ +int mbedtls_entropy_source_self_test( int verbose ) +{ + int ret = 0; + unsigned char buf0[2 * sizeof( unsigned long long int )]; + unsigned char buf1[2 * sizeof( unsigned long long int )]; + + if( verbose != 0 ) + mbedtls_printf( " ENTROPY_BIAS test: " ); + + memset( buf0, 0x00, sizeof( buf0 ) ); + memset( buf1, 0x00, sizeof( buf1 ) ); + + if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 ) + goto cleanup; + + /* Make sure that the returned values are not all 0 or 1 */ + if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 ) + goto cleanup; + + /* Make sure that the entropy source is not returning values in a + * pattern */ + ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0; + +cleanup: + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed\n" ); + else + mbedtls_printf( "passed\n" ); + + mbedtls_printf( "\n" ); + } + + return( ret != 0 ); +} + +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ + +/* + * The actual entropy quality is hard to test, but we can at least + * test that the functions don't cause errors and write the correct + * amount of data to buffers. + */ +int mbedtls_entropy_self_test( int verbose ) +{ + int ret = 1; +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_context ctx; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + size_t i, j; +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + + if( verbose != 0 ) + mbedtls_printf( " ENTROPY test: " ); + +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_init( &ctx ); + + /* First do a gather to make sure we have default sources */ + if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 ) + goto cleanup; + + ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16, + MBEDTLS_ENTROPY_SOURCE_WEAK ); + if( ret != 0 ) + goto cleanup; + + if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) + goto cleanup; + + /* + * To test that mbedtls_entropy_func writes correct number of bytes: + * - use the whole buffer and rely on ASan to detect overruns + * - collect entropy 8 times and OR the result in an accumulator: + * any byte should then be 0 with probably 2^(-64), so requiring + * each of the 32 or 64 bytes to be non-zero has a false failure rate + * of at most 2^(-58) which is acceptable. + */ + for( i = 0; i < 8; i++ ) + { + if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) + goto cleanup; + + for( j = 0; j < sizeof( buf ); j++ ) + acc[j] |= buf[j]; + } + + for( j = 0; j < sizeof( buf ); j++ ) + { + if( acc[j] == 0 ) + { + ret = 1; + goto cleanup; + } + } + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 ) + goto cleanup; +#endif + +cleanup: + mbedtls_entropy_free( &ctx ); +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed\n" ); + else + mbedtls_printf( "passed\n" ); + + mbedtls_printf( "\n" ); + } + + return( ret != 0 ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/external/mbedtls/library/entropy_poll.c b/external/mbedtls/library/entropy_poll.c new file mode 100644 index 0000000..d7062ea --- /dev/null +++ b/external/mbedtls/library/entropy_poll.c @@ -0,0 +1,261 @@ +/* + * Platform-specific and custom entropy polling functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if defined(__linux__) && !defined(_GNU_SOURCE) +/* Ensure that syscall() is available even when compiling with -std=c99 */ +#define _GNU_SOURCE +#endif + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_ENTROPY_C) + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" + +#if defined(MBEDTLS_TIMING_C) +#include "mbedtls/timing.h" +#endif +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) +#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0400 +#endif +#include +#include + +int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, + size_t *olen ) +{ + HCRYPTPROV provider; + ((void) data); + *olen = 0; + + if( CryptAcquireContext( &provider, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) + { + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) + { + CryptReleaseContext( provider, 0 ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + CryptReleaseContext( provider, 0 ); + *olen = len; + + return( 0 ); +} +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Test for Linux getrandom() support. + * Since there is no wrapper in the libc yet, use the generic syscall wrapper + * available in GNU libc and compatible libc's (eg uClibc). + */ +#if defined(__linux__) && defined(__GLIBC__) +#include +#include +#if defined(SYS_getrandom) +#define HAVE_GETRANDOM +#include + +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + /* MemSan cannot understand that the syscall writes to the buffer */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + memset( buf, 0, buflen ); +#endif +#endif + return( syscall( SYS_getrandom, buf, buflen, flags ) ); +} +#endif /* SYS_getrandom */ +#endif /* __linux__ */ + +#include + +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + FILE *file; + size_t read_len; + int ret; + ((void) data); + +#if defined(HAVE_GETRANDOM) + ret = getrandom_wrapper( output, len, 0 ); + if( ret >= 0 ) + { + *olen = ret; + return( 0 ); + } + else if( errno != ENOSYS ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + /* Fall through if the system call isn't known. */ +#else + ((void) ret); +#endif /* HAVE_GETRANDOM */ + + *olen = 0; + + file = fopen( "/dev/urandom", "rb" ); + if( file == NULL ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + read_len = fread( output, 1, len, file ); + if( read_len != len ) + { + fclose( file ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + fclose( file ); + *olen = len; + + return( 0 ); +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + ((void) data); + ((void) output); + *olen = 0; + + if( len < sizeof(unsigned char) ) + return( 0 ); + + *olen = sizeof(unsigned char); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_TIMING_C) +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned long timer = mbedtls_timing_hardclock(); + ((void) data); + *olen = 0; + + if( len < sizeof(unsigned long) ) + return( 0 ); + + memcpy( output, &timer, sizeof(unsigned long) ); + *olen = sizeof(unsigned long); + + return( 0 ); +} +#endif /* MBEDTLS_TIMING_C */ + +#if defined(MBEDTLS_HAVEGE_C) +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + mbedtls_havege_state *hs = (mbedtls_havege_state *) data; + *olen = 0; + + if( mbedtls_havege_random( hs, output, len ) != 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = len; + + return( 0 ); +} +#endif /* MBEDTLS_HAVEGE_C */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + ((void) data); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + if( len < use_len ) + use_len = len; + + memcpy( output, buf, use_len ); + *olen = use_len; + + return( 0 ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/external/mbedtls/library/error.c b/external/mbedtls/library/error.c new file mode 100644 index 0000000..b83b8d1 --- /dev/null +++ b/external/mbedtls/library/error.c @@ -0,0 +1,944 @@ +/* + * Error message information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) + +#include "mbedtls/error.h" + +#if defined(MBEDTLS_ERROR_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +#include +#include + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#endif + +#if defined(MBEDTLS_BASE64_C) +#include "mbedtls/base64.h" +#endif + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_CIPHER_C) +#include "mbedtls/cipher.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_DHM_C) +#include "mbedtls/dhm.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ENTROPY_C) +#include "mbedtls/entropy.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_HKDF_C) +#include "mbedtls/hkdf.h" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_MD2_C) +#include "mbedtls/md2.h" +#endif + +#if defined(MBEDTLS_MD4_C) +#include "mbedtls/md4.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_NET_C) +#include "mbedtls/net_sockets.h" +#endif + +#if defined(MBEDTLS_OID_C) +#include "mbedtls/oid.h" +#endif + +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#endif + +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#endif + +#if defined(MBEDTLS_POLY1305_C) +#include "mbedtls/poly1305.h" +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#include "mbedtls/ripemd160.h" +#endif + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) +#include "mbedtls/ssl.h" +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "mbedtls/x509.h" +#endif + +#if defined(MBEDTLS_XTEA_C) +#include "mbedtls/xtea.h" +#endif + + +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + size_t len; + int use_ret; + + if( buflen == 0 ) + return; + + memset( buf, 0x00, buflen ); + + if( ret < 0 ) + ret = -ret; + + if( ret & 0xFF80 ) + { + use_ret = ret & 0xFF80; + + // High level error codes + // + // BEGIN generated code +#if defined(MBEDTLS_CIPHER_C) + if( use_ret == -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "CIPHER - The selected feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Bad input parameters" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_PADDING) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT) ) + mbedtls_snprintf( buf, buflen, "CIPHER - The context is invalid. For example, because it was freed" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Cipher hardware accelerator failed" ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_DHM_C) + if( use_ret == -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "DHM - Bad input parameters" ); + if( use_ret == -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Reading of the public values failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Making of the public value failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "DHM - The ASN.1 data is not formatted correctly" ); + if( use_ret == -(MBEDTLS_ERR_DHM_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Allocation of memory failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "DHM - Read or write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - DHM hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Setting the modulus and generator failed" ); +#endif /* MBEDTLS_DHM_C */ + +#if defined(MBEDTLS_ECP_C) + if( use_ret == -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "ECP - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "ECP - The buffer is too small to write to" ); + if( use_ret == -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "ECP - The requested feature is not available, for example, the requested curve is not supported" ); + if( use_ret == -(MBEDTLS_ERR_ECP_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - The signature is not valid" ); + if( use_ret == -(MBEDTLS_ERR_ECP_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_ECP_RANDOM_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - Generation of random value, such as ephemeral key, failed" ); + if( use_ret == -(MBEDTLS_ERR_ECP_INVALID_KEY) ) + mbedtls_snprintf( buf, buflen, "ECP - Invalid private or public key" ); + if( use_ret == -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "ECP - The buffer contains a valid signature followed by more data" ); + if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - The ECP hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_ECP_IN_PROGRESS) ) + mbedtls_snprintf( buf, buflen, "ECP - Operation in progress, call again with the same parameters to continue" ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) + if( use_ret == -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "MD - The selected feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_MD_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "MD - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_MD_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_MD_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "MD - Opening or reading of file failed" ); + if( use_ret == -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD - MD hardware accelerator failed" ); +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + if( use_ret == -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) ) + mbedtls_snprintf( buf, buflen, "PEM - No PEM header or footer found" ); + if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_DATA) ) + mbedtls_snprintf( buf, buflen, "PEM - PEM string is not as expected" ); + if( use_ret == -(MBEDTLS_ERR_PEM_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "PEM - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_ENC_IV) ) + mbedtls_snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" ); + if( use_ret == -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG) ) + mbedtls_snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" ); + if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "PEM - Private key password can't be empty" ); + if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" ); + if( use_ret == -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" ); + if( use_ret == -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PEM - Bad input parameters to function" ); +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ + +#if defined(MBEDTLS_PK_C) + if( use_ret == -(MBEDTLS_ERR_PK_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "PK - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_PK_TYPE_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); + if( use_ret == -(MBEDTLS_ERR_PK_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PK - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PK_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "PK - Read/write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION) ) + mbedtls_snprintf( buf, buflen, "PK - Unsupported key version" ); + if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PK - Invalid key tag or value" ); + if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG) ) + mbedtls_snprintf( buf, buflen, "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "PK - Private key password can't be empty" ); + if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - Given private key password does not allow for correct decryption" ); + if( use_ret == -(MBEDTLS_ERR_PK_INVALID_PUBKEY) ) + mbedtls_snprintf( buf, buflen, "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_INVALID_ALG) ) + mbedtls_snprintf( buf, buflen, "PK - The algorithm tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE) ) + mbedtls_snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); + if( use_ret == -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - The buffer contains a valid signature followed by more data" ); + if( use_ret == -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "PK - PK hardware accelerator failed" ); +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_PKCS12_C) + if( use_ret == -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - PBE ASN.1 data not as expected" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS12_C */ + +#if defined(MBEDTLS_PKCS5_C) + if( use_ret == -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Unexpected ASN.1 data" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Requested encryption or digest alg not available" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS5_C */ + +#if defined(MBEDTLS_RSA_C) + if( use_ret == -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "RSA - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_RSA_INVALID_PADDING) ) + mbedtls_snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" ); + if( use_ret == -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - Something failed during generation of a key" ); + if( use_ret == -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - Key failed to pass the validity check of the library" ); + if( use_ret == -(MBEDTLS_ERR_RSA_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The public key operation failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_PRIVATE_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The private key operation failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) ) + mbedtls_snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" ); + if( use_ret == -(MBEDTLS_ERR_RSA_RNG_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" ); + if( use_ret == -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION) ) + mbedtls_snprintf( buf, buflen, "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality" ); + if( use_ret == -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - RSA hardware accelerator failed" ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_SSL_TLS_C) + if( use_ret == -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "SSL - The requested feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SSL - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_MAC) ) + mbedtls_snprintf( buf, buflen, "SSL - Verification of the message MAC failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_RECORD) ) + mbedtls_snprintf( buf, buflen, "SSL - An invalid SSL record was received" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CONN_EOF) ) + mbedtls_snprintf( buf, buflen, "SSL - The connection indicated an EOF" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER) ) + mbedtls_snprintf( buf, buflen, "SSL - An unknown cipher was received" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN) ) + mbedtls_snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_RNG) ) + mbedtls_snprintf( buf, buflen, "SSL - No RNG was provided to the SSL module" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE) ) + mbedtls_snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Our own certificate(s) is/are too large to send in an SSL message" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - The own private key or pre-shared key is not set, but needed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE) ) + mbedtls_snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" ); + if( use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE) ) + { + mbedtls_snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" ); + return; + } + if( use_ret == -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Verification of our peer failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) ) + mbedtls_snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function returned with error" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH) ) + mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function skipped / left alone data" ); + if( use_ret == -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION) ) + mbedtls_snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - Session ticket has expired" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) ) + mbedtls_snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INTERNAL_ERROR) ) + mbedtls_snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING) ) + mbedtls_snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO) ) + mbedtls_snprintf( buf, buflen, "SSL - Unexpected message at ServerHello in renegotiation" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - DTLS client must retry for hello verification" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "SSL - A buffer is too small to receive or write a message" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) ) + mbedtls_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WANT_READ) ) + mbedtls_snprintf( buf, buflen, "SSL - No data of requested type currently available on underlying transport" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WANT_WRITE) ) + mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" ); + if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) ) + mbedtls_snprintf( buf, buflen, "SSL - The operation timed out" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT) ) + mbedtls_snprintf( buf, buflen, "SSL - The client initiated a reconnect from the same port" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) ) + mbedtls_snprintf( buf, buflen, "SSL - Record header looks valid but is not expected" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NON_FATAL) ) + mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) ) + mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) ) + mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" ); + if( use_ret == -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) ) + mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" ); + if( use_ret == -(MBEDTLS_ERR_SSL_EARLY_MESSAGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that a message arrived early" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) ) + mbedtls_snprintf( buf, buflen, "SSL - A cryptographic operation is in progress. Try again later" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_CONFIG) ) + mbedtls_snprintf( buf, buflen, "SSL - Invalid value in SSL config" ); +#endif /* MBEDTLS_SSL_TLS_C */ + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + if( use_ret == -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_OID) ) + mbedtls_snprintf( buf, buflen, "X509 - Requested OID is unknown" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_VERSION) ) + mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR version element is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SERIAL) ) + mbedtls_snprintf( buf, buflen, "X509 - The serial tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_ALG) ) + mbedtls_snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_NAME) ) + mbedtls_snprintf( buf, buflen, "X509 - The name tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_DATE) ) + mbedtls_snprintf( buf, buflen, "X509 - The date tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SIGNATURE) ) + mbedtls_snprintf( buf, buflen, "X509 - The signature tag or value invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS) ) + mbedtls_snprintf( buf, buflen, "X509 - The extension tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_VERSION) ) + mbedtls_snprintf( buf, buflen, "X509 - CRT/CRL/CSR has an unsupported version number" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG) ) + mbedtls_snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" ); + if( use_ret == -(MBEDTLS_ERR_X509_SIG_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" ); + if( use_ret == -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT) ) + mbedtls_snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" ); + if( use_ret == -(MBEDTLS_ERR_X509_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "X509 - Input invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "X509 - Allocation of memory failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "X509 - Read/write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "X509 - Destination buffer is too small" ); + if( use_ret == -(MBEDTLS_ERR_X509_FATAL_ERROR) ) + mbedtls_snprintf( buf, buflen, "X509 - A fatal error occurred, eg the chain is too long or the vrfy callback failed" ); +#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ + // END generated code + + if( strlen( buf ) == 0 ) + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); + } + + use_ret = ret & ~0xFF80; + + if( use_ret == 0 ) + return; + + // If high level code is present, make a concatenation between both + // error strings. + // + len = strlen( buf ); + + if( len > 0 ) + { + if( buflen - len < 5 ) + return; + + mbedtls_snprintf( buf + len, buflen - len, " : " ); + + buf += len + 3; + buflen -= len + 3; + } + + // Low level error codes + // + // BEGIN generated code +#if defined(MBEDTLS_AES_C) + if( use_ret == -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH) ) + mbedtls_snprintf( buf, buflen, "AES - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_AES_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "AES - Invalid input data" ); + if( use_ret == -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "AES - Feature not available. For example, an unsupported AES key size" ); + if( use_ret == -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "AES - AES hardware accelerator failed" ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + if( use_ret == -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "ARC4 - ARC4 hardware accelerator failed" ); +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_ARIA_C) + if( use_ret == -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "ARIA - Bad input data" ); + if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "ARIA - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "ARIA - Feature not available. For example, an unsupported ARIA key size" ); + if( use_ret == -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "ARIA - ARIA hardware accelerator failed" ); +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_ASN1_PARSE_C) + if( use_ret == -(MBEDTLS_ERR_ASN1_OUT_OF_DATA) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) ) + mbedtls_snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_LENGTH) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_DATA) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Buffer too small when writing ASN.1 data structure" ); +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_BASE64_C) + if( use_ret == -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "BASE64 - Output buffer too small" ); + if( use_ret == -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER) ) + mbedtls_snprintf( buf, buflen, "BASE64 - Invalid character in input" ); +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_BIGNUM_C) + if( use_ret == -(MBEDTLS_ERR_MPI_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" ); + if( use_ret == -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_MPI_INVALID_CHARACTER) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" ); + if( use_ret == -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" ); + if( use_ret == -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" ); + if( use_ret == -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" ); + if( use_ret == -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" ); + if( use_ret == -(MBEDTLS_ERR_MPI_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - Memory allocation failed" ); +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Bad input data" ); + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Blowfish hardware accelerator failed" ); +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Bad input data" ); + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Camellia hardware accelerator failed" ); +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CCM_C) + if( use_ret == -(MBEDTLS_ERR_CCM_BAD_INPUT) ) + mbedtls_snprintf( buf, buflen, "CCM - Bad input parameters to the function" ); + if( use_ret == -(MBEDTLS_ERR_CCM_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); + if( use_ret == -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CCM - CCM hardware accelerator failed" ); +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_CHACHA20_C) + if( use_ret == -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Invalid input parameter(s)" ); + if( use_ret == -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Feature not available. For example, s part of the API is not implemented" ); + if( use_ret == -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Chacha20 hardware accelerator failed" ); +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE) ) + mbedtls_snprintf( buf, buflen, "CHACHAPOLY - The requested operation is not permitted in the current state" ); + if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CHACHAPOLY - Authenticated decryption failed: data was not authentic" ); +#endif /* MBEDTLS_CHACHAPOLY_C */ + +#if defined(MBEDTLS_CMAC_C) + if( use_ret == -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CMAC - CMAC hardware accelerator failed" ); +#endif /* MBEDTLS_CMAC_C */ + +#if defined(MBEDTLS_CTR_DRBG_C) + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" ); + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - The requested random buffer length is too big" ); + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - The input (entropy + additional data) is too large" ); + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - Read or write error in file" ); +#endif /* MBEDTLS_CTR_DRBG_C */ + +#if defined(MBEDTLS_DES_C) + if( use_ret == -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "DES - The data input has an invalid length" ); + if( use_ret == -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "DES - DES hardware accelerator failed" ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ENTROPY_C) + if( use_ret == -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - No more sources can be added" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - No strong sources have been added to poll" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - Read/write error in file" ); +#endif /* MBEDTLS_ENTROPY_C */ + +#if defined(MBEDTLS_GCM_C) + if( use_ret == -(MBEDTLS_ERR_GCM_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "GCM - Authenticated decryption failed" ); + if( use_ret == -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "GCM - GCM hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_GCM_BAD_INPUT) ) + mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" ); +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_HKDF_C) + if( use_ret == -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "HKDF - Bad input parameters to function" ); +#endif /* MBEDTLS_HKDF_C */ + +#if defined(MBEDTLS_HMAC_DRBG_C) + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" ); + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Input too large (Entropy + additional)" ); + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Read/write error in file" ); + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" ); +#endif /* MBEDTLS_HMAC_DRBG_C */ + +#if defined(MBEDTLS_MD2_C) + if( use_ret == -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD2 - MD2 hardware accelerator failed" ); +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + if( use_ret == -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD4 - MD4 hardware accelerator failed" ); +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + if( use_ret == -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD5 - MD5 hardware accelerator failed" ); +#endif /* MBEDTLS_MD5_C */ + +#if defined(MBEDTLS_NET_C) + if( use_ret == -(MBEDTLS_ERR_NET_SOCKET_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Failed to open a socket" ); + if( use_ret == -(MBEDTLS_ERR_NET_CONNECT_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - The connection to the given server / port failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_BIND_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Binding of the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_LISTEN_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Could not listen on the socket" ); + if( use_ret == -(MBEDTLS_ERR_NET_ACCEPT_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Could not accept the incoming connection" ); + if( use_ret == -(MBEDTLS_ERR_NET_RECV_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Reading information from the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_SEND_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Sending information through the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_CONN_RESET) ) + mbedtls_snprintf( buf, buflen, "NET - Connection was reset by peer" ); + if( use_ret == -(MBEDTLS_ERR_NET_UNKNOWN_HOST) ) + mbedtls_snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" ); + if( use_ret == -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "NET - Buffer is too small to hold the data" ); + if( use_ret == -(MBEDTLS_ERR_NET_INVALID_CONTEXT) ) + mbedtls_snprintf( buf, buflen, "NET - The context is invalid, eg because it was free()ed" ); + if( use_ret == -(MBEDTLS_ERR_NET_POLL_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Polling the net context failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "NET - Input invalid" ); +#endif /* MBEDTLS_NET_C */ + +#if defined(MBEDTLS_OID_C) + if( use_ret == -(MBEDTLS_ERR_OID_NOT_FOUND) ) + mbedtls_snprintf( buf, buflen, "OID - OID is not found" ); + if( use_ret == -(MBEDTLS_ERR_OID_BUF_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "OID - output buffer is too small" ); +#endif /* MBEDTLS_OID_C */ + +#if defined(MBEDTLS_PADLOCK_C) + if( use_ret == -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED) ) + mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); +#endif /* MBEDTLS_PADLOCK_C */ + +#if defined(MBEDTLS_PLATFORM_C) + if( use_ret == -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "PLATFORM - Hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED) ) + mbedtls_snprintf( buf, buflen, "PLATFORM - The requested feature is not supported by the platform" ); +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_POLY1305_C) + if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" ); + if( use_ret == -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Feature not available. For example, s part of the API is not implemented" ); + if( use_ret == -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Poly1305 hardware accelerator failed" ); +#endif /* MBEDTLS_POLY1305_C */ + +#if defined(MBEDTLS_RIPEMD160_C) + if( use_ret == -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "RIPEMD160 - RIPEMD160 hardware accelerator failed" ); +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_SHA1_C) + if( use_ret == -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA1 - SHA-1 hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SHA1 - SHA-1 input data was malformed" ); +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + if( use_ret == -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA256 - SHA-256 hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SHA256 - SHA-256 input data was malformed" ); +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + if( use_ret == -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA512 - SHA-512 hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SHA512 - SHA-512 input data was malformed" ); +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_THREADING_C) + if( use_ret == -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "THREADING - The selected feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "THREADING - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_THREADING_MUTEX_ERROR) ) + mbedtls_snprintf( buf, buflen, "THREADING - Locking / unlocking / free failed with error code" ); +#endif /* MBEDTLS_THREADING_C */ + +#if defined(MBEDTLS_XTEA_C) + if( use_ret == -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "XTEA - The data input has an invalid length" ); + if( use_ret == -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "XTEA - XTEA hardware accelerator failed" ); +#endif /* MBEDTLS_XTEA_C */ + // END generated code + + if( strlen( buf ) != 0 ) + return; + + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); +} + +#else /* MBEDTLS_ERROR_C */ + +/* + * Provide an non-function in case MBEDTLS_ERROR_C is not defined + */ +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + ((void) ret); + + if( buflen > 0 ) + buf[0] = '\0'; +} + +#endif /* MBEDTLS_ERROR_C */ + +#endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */ diff --git a/external/mbedtls/library/gcm.c b/external/mbedtls/library/gcm.c new file mode 100644 index 0000000..2afe502 --- /dev/null +++ b/external/mbedtls/library/gcm.c @@ -0,0 +1,1019 @@ +/* + * NIST SP800-38D compliant GCM implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf + * + * See also: + * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf + * + * We use the algorithm described as Shoup's method with 4-bit tables in + * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_GCM_C) + +#include "mbedtls/gcm.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_AESNI_C) +#include "mbedtls/aesni.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_GCM_ALT) + +/* Parameter validation macros */ +#define GCM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_GCM_BAD_INPUT ) +#define GCM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * Initialize a context + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ) +{ + GCM_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_gcm_context ) ); +} + +/* + * Precompute small multiples of H, that is set + * HH[i] || HL[i] = H times i, + * where i is seen as a field element as in [MGV], ie high-order bits + * correspond to low powers of P. The result is stored in the same way, that + * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL + * corresponds to P^127. + */ +static int gcm_gen_table( mbedtls_gcm_context *ctx ) +{ + int ret, i, j; + uint64_t hi, lo; + uint64_t vl, vh; + unsigned char h[16]; + size_t olen = 0; + + memset( h, 0, 16 ); + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 ) + return( ret ); + + /* pack h as two 64-bits ints, big-endian */ + GET_UINT32_BE( hi, h, 0 ); + GET_UINT32_BE( lo, h, 4 ); + vh = (uint64_t) hi << 32 | lo; + + GET_UINT32_BE( hi, h, 8 ); + GET_UINT32_BE( lo, h, 12 ); + vl = (uint64_t) hi << 32 | lo; + + /* 8 = 1000 corresponds to 1 in GF(2^128) */ + ctx->HL[8] = vl; + ctx->HH[8] = vh; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + /* With CLMUL support, we need only h, not the rest of the table */ + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) + return( 0 ); +#endif + + /* 0 corresponds to 0 in GF(2^128) */ + ctx->HH[0] = 0; + ctx->HL[0] = 0; + + for( i = 4; i > 0; i >>= 1 ) + { + uint32_t T = ( vl & 1 ) * 0xe1000000U; + vl = ( vh << 63 ) | ( vl >> 1 ); + vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); + + ctx->HL[i] = vl; + ctx->HH[i] = vh; + } + + for( i = 2; i <= 8; i *= 2 ) + { + uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; + vh = *HiH; + vl = *HiL; + for( j = 1; j < i; j++ ) + { + HiH[j] = vh ^ ctx->HH[j]; + HiL[j] = vl ^ ctx->HL[j]; + } + } + + return( 0 ); +} + +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( key != NULL ); + GCM_VALIDATE_RET( keybits == 128 || keybits == 192 || keybits == 256 ); + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = gcm_gen_table( ctx ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Shoup's method for multiplication use this table with + * last4[x] = x times P^128 + * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] + */ +static const uint64_t last4[16] = +{ + 0x0000, 0x1c20, 0x3840, 0x2460, + 0x7080, 0x6ca0, 0x48c0, 0x54e0, + 0xe100, 0xfd20, 0xd940, 0xc560, + 0x9180, 0x8da0, 0xa9c0, 0xb5e0 +}; + +/* + * Sets output to x times H using the precomputed tables. + * x and output are seen as elements of GF(2^128) as in [MGV]. + */ +static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16], + unsigned char output[16] ) +{ + int i = 0; + unsigned char lo, hi, rem; + uint64_t zh, zl; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) { + unsigned char h[16]; + + PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 ); + PUT_UINT32_BE( ctx->HH[8], h, 4 ); + PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 ); + PUT_UINT32_BE( ctx->HL[8], h, 12 ); + + mbedtls_aesni_gcm_mult( output, x, h ); + return; + } +#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */ + + lo = x[15] & 0xf; + + zh = ctx->HH[lo]; + zl = ctx->HL[lo]; + + for( i = 15; i >= 0; i-- ) + { + lo = x[i] & 0xf; + hi = x[i] >> 4; + + if( i != 15 ) + { + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[lo]; + zl ^= ctx->HL[lo]; + + } + + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[hi]; + zl ^= ctx->HL[hi]; + } + + PUT_UINT32_BE( zh >> 32, output, 0 ); + PUT_UINT32_BE( zh, output, 4 ); + PUT_UINT32_BE( zl >> 32, output, 8 ); + PUT_UINT32_BE( zl, output, 12 ); +} + +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ) +{ + int ret; + unsigned char work_buf[16]; + size_t i; + const unsigned char *p; + size_t use_len, olen = 0; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + + /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ + /* IV is not allowed to be zero length */ + if( iv_len == 0 || + ( (uint64_t) iv_len ) >> 61 != 0 || + ( (uint64_t) add_len ) >> 61 != 0 ) + { + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + memset( ctx->y, 0x00, sizeof(ctx->y) ); + memset( ctx->buf, 0x00, sizeof(ctx->buf) ); + + ctx->mode = mode; + ctx->len = 0; + ctx->add_len = 0; + + if( iv_len == 12 ) + { + memcpy( ctx->y, iv, iv_len ); + ctx->y[15] = 1; + } + else + { + memset( work_buf, 0x00, 16 ); + PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); + + p = iv; + while( iv_len > 0 ) + { + use_len = ( iv_len < 16 ) ? iv_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->y[i] ^= p[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + + iv_len -= use_len; + p += use_len; + } + + for( i = 0; i < 16; i++ ) + ctx->y[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + } + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, + &olen ) ) != 0 ) + { + return( ret ); + } + + ctx->add_len = add_len; + p = add; + while( add_len > 0 ) + { + use_len = ( add_len < 16 ) ? add_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->buf[i] ^= p[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + add_len -= use_len; + p += use_len; + } + + return( 0 ); +} + +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + unsigned char ectr[16]; + size_t i; + const unsigned char *p; + unsigned char *out_p = output; + size_t use_len, olen = 0; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + + if( output > input && (size_t) ( output - input ) < length ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes + * Also check for possible overflow */ + if( ctx->len + length < ctx->len || + (uint64_t) ctx->len + length > 0xFFFFFFFE0ull ) + { + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + ctx->len += length; + + p = input; + while( length > 0 ) + { + use_len = ( length < 16 ) ? length : 16; + + for( i = 16; i > 12; i-- ) + if( ++ctx->y[i - 1] != 0 ) + break; + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr, + &olen ) ) != 0 ) + { + return( ret ); + } + + for( i = 0; i < use_len; i++ ) + { + if( ctx->mode == MBEDTLS_GCM_DECRYPT ) + ctx->buf[i] ^= p[i]; + out_p[i] = ectr[i] ^ p[i]; + if( ctx->mode == MBEDTLS_GCM_ENCRYPT ) + ctx->buf[i] ^= out_p[i]; + } + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + length -= use_len; + p += use_len; + out_p += use_len; + } + + return( 0 ); +} + +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len ) +{ + unsigned char work_buf[16]; + size_t i; + uint64_t orig_len; + uint64_t orig_add_len; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + + orig_len = ctx->len * 8; + orig_add_len = ctx->add_len * 8; + + if( tag_len > 16 || tag_len < 4 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + memcpy( tag, ctx->base_ectr, tag_len ); + + if( orig_len || orig_add_len ) + { + memset( work_buf, 0x00, 16 ); + + PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 ); + PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 ); + PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 ); + PUT_UINT32_BE( ( orig_len ), work_buf, 12 ); + + for( i = 0; i < 16; i++ ) + ctx->buf[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + for( i = 0; i < tag_len; i++ ) + tag[i] ^= ctx->buf[i]; + } + + return( 0 ); +} + +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ) +{ + int ret; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + + if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + unsigned char check_tag[16]; + size_t i; + int diff; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + + if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, tag_len, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( MBEDTLS_ERR_GCM_AUTH_FAILED ); + } + + return( 0 ); +} + +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) +{ + if( ctx == NULL ) + return; + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); +} + +#endif /* !MBEDTLS_GCM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/* + * AES-GCM test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip + */ +#define MAX_TESTS 6 + +static const int key_index[MAX_TESTS] = + { 0, 0, 1, 1, 1, 1 }; + +static const unsigned char key[MAX_TESTS][32] = +{ + { 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 }, + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, +}; + +static const size_t iv_len[MAX_TESTS] = + { 12, 12, 12, 12, 8, 60 }; + +static const int iv_index[MAX_TESTS] = + { 0, 0, 1, 1, 1, 2 }; + +static const unsigned char iv[MAX_TESTS][64] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 }, + { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, + 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, + 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, + 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, + 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, + 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, + 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, + 0xa6, 0x37, 0xb3, 0x9b }, +}; + +static const size_t add_len[MAX_TESTS] = + { 0, 0, 0, 20, 20, 20 }; + +static const int add_index[MAX_TESTS] = + { 0, 0, 0, 1, 1, 1 }; + +static const unsigned char additional[MAX_TESTS][64] = +{ + { 0x00 }, + { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 }, +}; + +static const size_t pt_len[MAX_TESTS] = + { 0, 16, 64, 60, 60, 60 }; + +static const int pt_index[MAX_TESTS] = + { 0, 0, 1, 1, 1, 1 }; + +static const unsigned char pt[MAX_TESTS][64] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, +}; + +static const unsigned char ct[MAX_TESTS * 3][64] = +{ + { 0x00 }, + { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, + 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, + { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }, + { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91 }, + { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, + 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, + 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, + 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, + 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, + 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, + 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, + 0xc2, 0x3f, 0x45, 0x98 }, + { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, + 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, + 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, + 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, + 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, + 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, + 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, + 0x4c, 0x34, 0xae, 0xe5 }, + { 0x00 }, + { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, + 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, + { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, + { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10 }, + { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, + 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, + 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, + 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, + 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, + 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, + 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, + 0xa0, 0xf0, 0x62, 0xf7 }, + { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, + 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, + 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, + 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, + 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, + 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, + 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, + 0xe9, 0xb7, 0x37, 0x3b }, + { 0x00 }, + { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, + 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, + { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, + { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62 }, + { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, + 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, + 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, + 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, + 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, + 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, + 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, + 0xf4, 0x7c, 0x9b, 0x1f }, + { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, + 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, + 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, + 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, + 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, + 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, + 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, + 0x44, 0xae, 0x7e, 0x3f }, +}; + +static const unsigned char tag[MAX_TESTS * 3][16] = +{ + { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, + 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, + { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, + 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, + { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, + 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, + { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, + 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, + { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, + 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, + { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, + 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, + { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, + 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, + { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, + 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, + { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, + 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, + { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, + 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, + { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, + 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, + { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, + 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, + { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, + 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, + { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, + 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, + { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, + 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, + { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, + 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, + { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, + 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, + { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, + 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, +}; + +int mbedtls_gcm_self_test( int verbose ) +{ + mbedtls_gcm_context ctx; + unsigned char buf[64]; + unsigned char tag_buf[16]; + int i, j, ret; + mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + + for( j = 0; j < 3; j++ ) + { + int key_len = 128 + 64 * j; + + for( i = 0; i < MAX_TESTS; i++ ) + { + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "enc" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192 ) + { + mbedtls_printf( "skipped\n" ); + break; + } + else if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT, + pt_len[i], + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i], + pt[pt_index[i]], buf, 16, tag_buf ); + if( ret != 0 ) + goto exit; + + if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "dec" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT, + pt_len[i], + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i], + ct[j * 6 + i], buf, 16, tag_buf ); + + if( ret != 0 ) + goto exit; + + if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "enc" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT, + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i] ); + if( ret != 0 ) + goto exit; + + if( pt_len[i] > 32 ) + { + size_t rest_len = pt_len[i] - 32; + ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, + buf + 32 ); + if( ret != 0 ) + goto exit; + } + else + { + ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "dec" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT, + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i] ); + if( ret != 0 ) + goto exit; + + if( pt_len[i] > 32 ) + { + size_t rest_len = pt_len[i] - 32; + ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, + buf + 32 ); + if( ret != 0 ) + goto exit; + } + else + { + ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], + buf ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + ret = 0; + +exit: + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + mbedtls_gcm_free( &ctx ); + } + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_GCM_C */ diff --git a/external/mbedtls/library/havege.c b/external/mbedtls/library/havege.c new file mode 100644 index 0000000..5e91f40 --- /dev/null +++ b/external/mbedtls/library/havege.c @@ -0,0 +1,278 @@ +/** + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The HAVEGE RNG was designed by Andre Seznec in 2002. + * + * http://www.irisa.fr/caps/projects/hipsor/publi.php + * + * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HAVEGE_C) + +#include "mbedtls/havege.h" +#include "mbedtls/timing.h" +#include "mbedtls/platform_util.h" + +#include +#include + +/* If int isn't capable of storing 2^32 distinct values, the code of this + * module may cause a processor trap or a miscalculation. If int is more + * than 32 bits, the code may not calculate the intended values. */ +#if INT_MIN + 1 != -0x7fffffff +#error "The HAVEGE module requires int to be exactly 32 bits, with INT_MIN = -2^31." +#endif +#if UINT_MAX != 0xffffffff +#error "The HAVEGE module requires unsigned to be exactly 32 bits." +#endif + +/* ------------------------------------------------------------------------ + * On average, one iteration accesses two 8-word blocks in the havege WALK + * table, and generates 16 words in the RES array. + * + * The data read in the WALK table is updated and permuted after each use. + * The result of the hardware clock counter read is used for this update. + * + * 25 conditional tests are present. The conditional tests are grouped in + * two nested groups of 12 conditional tests and 1 test that controls the + * permutation; on average, there should be 6 tests executed and 3 of them + * should be mispredicted. + * ------------------------------------------------------------------------ + */ + +#define SWAP(X,Y) { unsigned *T = (X); (X) = (Y); (Y) = T; } + +#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; +#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; + +#define TST1_LEAVE U1++; } +#define TST2_LEAVE U2++; } + +#define ONE_ITERATION \ + \ + PTEST = PT1 >> 20; \ + \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + \ + PTX = (PT1 >> 18) & 7; \ + PT1 &= 0x1FFF; \ + PT2 &= 0x1FFF; \ + CLK = (unsigned) mbedtls_timing_hardclock(); \ + \ + i = 0; \ + A = &WALK[PT1 ]; RES[i++] ^= *A; \ + B = &WALK[PT2 ]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ + \ + IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ + *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ + *B = IN ^ U1; \ + *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ + *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ + B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ + \ + if( PTEST & 1 ) SWAP( A, C ); \ + \ + IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ + *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ + *B = IN; CLK = (unsigned) mbedtls_timing_hardclock(); \ + *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ + *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 4]; \ + B = &WALK[PT2 ^ 1]; \ + \ + PTEST = PT2 >> 1; \ + \ + PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ + PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ + PTY = (PT2 >> 10) & 7; \ + \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + \ + C = &WALK[PT1 ^ 5]; \ + D = &WALK[PT2 ^ 5]; \ + \ + RES[i++] ^= *A; \ + RES[i++] ^= *B; \ + RES[i++] ^= *C; \ + RES[i++] ^= *D; \ + \ + IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \ + *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ + *B = IN ^ U2; \ + *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ + *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ + B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ + \ + IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ + *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ + *B = IN; \ + *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ + *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ + \ + PT1 = ( RES[( i - 8 ) ^ PTX] ^ \ + WALK[PT1 ^ PTX ^ 7] ) & (~1); \ + PT1 ^= (PT2 ^ 0x10) & 0x10; \ + \ + for( n++, i = 0; i < 16; i++ ) \ + POOL[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i]; + +/* + * Entropy gathering function + */ +static void havege_fill( mbedtls_havege_state *hs ) +{ + unsigned i, n = 0; + unsigned U1, U2, *A, *B, *C, *D; + unsigned PT1, PT2, *WALK, *POOL, RES[16]; + unsigned PTX, PTY, CLK, PTEST, IN; + + WALK = (unsigned *) hs->WALK; + POOL = (unsigned *) hs->pool; + PT1 = hs->PT1; + PT2 = hs->PT2; + + PTX = U1 = 0; + PTY = U2 = 0; + + (void)PTX; + + memset( RES, 0, sizeof( RES ) ); + + while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 ) + { + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + } + + hs->PT1 = PT1; + hs->PT2 = PT2; + + hs->offset[0] = 0; + hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2; +} + +/* + * HAVEGE initialization + */ +void mbedtls_havege_init( mbedtls_havege_state *hs ) +{ + memset( hs, 0, sizeof( mbedtls_havege_state ) ); + + havege_fill( hs ); +} + +void mbedtls_havege_free( mbedtls_havege_state *hs ) +{ + if( hs == NULL ) + return; + + mbedtls_platform_zeroize( hs, sizeof( mbedtls_havege_state ) ); +} + +/* + * HAVEGE rand function + */ +int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len ) +{ + int val; + size_t use_len; + mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng; + unsigned char *p = buf; + + while( len > 0 ) + { + use_len = len; + if( use_len > sizeof(int) ) + use_len = sizeof(int); + + if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE ) + havege_fill( hs ); + + val = hs->pool[hs->offset[0]++]; + val ^= hs->pool[hs->offset[1]++]; + + memcpy( p, &val, use_len ); + + len -= use_len; + p += use_len; + } + + return( 0 ); +} + +#endif /* MBEDTLS_HAVEGE_C */ diff --git a/external/mbedtls/library/hkdf.c b/external/mbedtls/library/hkdf.c new file mode 100644 index 0000000..4a8bdfb --- /dev/null +++ b/external/mbedtls/library/hkdf.c @@ -0,0 +1,217 @@ +/* + * HKDF implementation -- RFC 5869 + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HKDF_C) + +#include +#include "mbedtls/hkdf.h" +#include "mbedtls/platform_util.h" + +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ) +{ + int ret; + unsigned char prk[MBEDTLS_MD_MAX_SIZE]; + + ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk ); + + if( ret == 0 ) + { + ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size( md ), + info, info_len, okm, okm_len ); + } + + mbedtls_platform_zeroize( prk, sizeof( prk ) ); + + return( ret ); +} + +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ) +{ + unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' }; + + if( salt == NULL ) + { + size_t hash_len; + + if( salt_len != 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + hash_len = mbedtls_md_get_size( md ); + + if( hash_len == 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + salt = null_salt; + salt_len = hash_len; + } + + return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) ); +} + +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ) +{ + size_t hash_len; + size_t where = 0; + size_t n; + size_t t_len = 0; + size_t i; + int ret = 0; + mbedtls_md_context_t ctx; + unsigned char t[MBEDTLS_MD_MAX_SIZE]; + + if( okm == NULL ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + hash_len = mbedtls_md_get_size( md ); + + if( prk_len < hash_len || hash_len == 0 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + if( info == NULL ) + { + info = (const unsigned char *) ""; + info_len = 0; + } + + n = okm_len / hash_len; + + if( (okm_len % hash_len) != 0 ) + { + n++; + } + + /* + * Per RFC 5869 Section 2.3, okm_len must not exceed + * 255 times the hash length + */ + if( n > 255 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + mbedtls_md_init( &ctx ); + + if( (ret = mbedtls_md_setup( &ctx, md, 1) ) != 0 ) + { + goto exit; + } + + /* + * Compute T = T(1) | T(2) | T(3) | ... | T(N) + * Where T(N) is defined in RFC 5869 Section 2.3 + */ + for( i = 1; i <= n; i++ ) + { + size_t num_to_copy; + unsigned char c = i & 0xff; + + ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_update( &ctx, t, t_len ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_update( &ctx, info, info_len ); + if( ret != 0 ) + { + goto exit; + } + + /* The constant concatenated to the end of each T(n) is a single octet. + * */ + ret = mbedtls_md_hmac_update( &ctx, &c, 1 ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_finish( &ctx, t ); + if( ret != 0 ) + { + goto exit; + } + + num_to_copy = i != n ? hash_len : okm_len - where; + memcpy( okm + where, t, num_to_copy ); + where += hash_len; + t_len = hash_len; + } + +exit: + mbedtls_md_free( &ctx ); + mbedtls_platform_zeroize( t, sizeof( t ) ); + + return( ret ); +} + +#endif /* MBEDTLS_HKDF_C */ diff --git a/external/mbedtls/library/hmac_drbg.c b/external/mbedtls/library/hmac_drbg.c new file mode 100644 index 0000000..b45d616 --- /dev/null +++ b/external/mbedtls/library/hmac_drbg.c @@ -0,0 +1,659 @@ +/* + * HMAC_DRBG implementation (NIST SP 800-90) + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * The NIST SP 800-90A DRBGs are described in the following publication. + * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf + * References below are based on rev. 1 (January 2012). + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) + +#include "mbedtls/hmac_drbg.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST */ +#endif /* MBEDTLS_PLATFORM_C */ + +/* + * HMAC_DRBG context initialization + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); + + ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; +} + +/* + * HMAC_DRBG update, using optional additional data (10.1.2.2) + */ +int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); + unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; + unsigned char sep[1]; + unsigned char K[MBEDTLS_MD_MAX_SIZE]; + int ret; + + for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) + { + /* Step 1 or 4 */ + if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + sep, 1 ) ) != 0 ) + goto exit; + if( rounds == 2 ) + { + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + additional, add_len ) ) != 0 ) + goto exit; + } + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 ) + goto exit; + + /* Step 2 or 5 */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) + goto exit; + } + +exit: + mbedtls_platform_zeroize( K, sizeof( K ) ); + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* + * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ) +{ + int ret; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, + mbedtls_md_get_size( md_info ) ) ) != 0 ) + return( ret ); + memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); + + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Internal function used both for seeding and reseeding the DRBG. + * Comments starting with arabic numbers refer to section 10.1.2.4 + * of SP800-90A, while roman numbers refer to section 9.2. + */ +static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len, + int use_nonce ) +{ + unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; + size_t seedlen = 0; + int ret; + + { + size_t total_entropy_len; + + if( use_nonce == 0 ) + total_entropy_len = ctx->entropy_len; + else + total_entropy_len = ctx->entropy_len * 3 / 2; + + /* III. Check input length */ + if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || + total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ) + { + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + } + } + + memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); + + /* IV. Gather entropy_len bytes of entropy for the seed */ + if( ( ret = ctx->f_entropy( ctx->p_entropy, + seed, ctx->entropy_len ) ) != 0 ) + { + return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); + } + seedlen += ctx->entropy_len; + + /* For initial seeding, allow adding of nonce generated + * from the entropy source. See Sect 8.6.7 in SP800-90A. */ + if( use_nonce ) + { + /* Note: We don't merge the two calls to f_entropy() in order + * to avoid requesting too much entropy from f_entropy() + * at once. Specifically, if the underlying digest is not + * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which + * is larger than the maximum of 32 Bytes that our own + * entropy source implementation can emit in a single + * call in configurations disabling SHA-512. */ + if( ( ret = ctx->f_entropy( ctx->p_entropy, + seed + seedlen, + ctx->entropy_len / 2 ) ) != 0 ) + { + return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); + } + + seedlen += ctx->entropy_len / 2; + } + + + /* 1. Concatenate entropy and additional data if any */ + if( additional != NULL && len != 0 ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* 2. Update state */ + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 ) + goto exit; + + /* 3. Reset reseed_counter */ + ctx->reseed_counter = 1; + +exit: + /* 4. Done */ + mbedtls_platform_zeroize( seed, seedlen ); + return( ret ); +} + +/* + * HMAC_DRBG reseeding: 10.1.2.4 + 9.2 + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + return( hmac_drbg_reseed_core( ctx, additional, len, 0 ) ); +} + +/* + * HMAC_DRBG initialisation (10.1.2.3 + 9.1) + * + * The nonce is not passed as a separate parameter but extracted + * from the entropy source as suggested in 8.6.7. + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + int ret; + size_t md_size; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + /* The mutex is initialized iff the md context is set up. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + md_size = mbedtls_md_get_size( md_info ); + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 ) + return( ret ); + memset( ctx->V, 0x01, md_size ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + if( ctx->entropy_len == 0 ) + { + /* + * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by + * each hash function, then according to SP800-90A rev1 10.1 table 2, + * min_entropy_len (in bits) is security_strength. + * + * (This also matches the sizes used in the NIST test vectors.) + */ + ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ + md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ + 32; /* better (256+) -> 256 bits */ + } + + if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, + 1 /* add nonce */ ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Set prediction resistance + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +/* + * Set entropy length grabbed for seeding + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +/* + * Set reseed interval + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval ) +{ + ctx->reseed_interval = interval; +} + +/* + * HMAC_DRBG random function with optional additional data: + * 10.1.2.5 (arabic) + 9.3 (Roman) + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t out_len, + const unsigned char *additional, size_t add_len ) +{ + int ret; + mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; + size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); + size_t left = out_len; + unsigned char *out = output; + + /* II. Check request length */ + if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST ) + return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); + + /* III. Check input length */ + if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT ) + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + + /* 1. (aka VII and IX) Check reseed counter and PR */ + if( ctx->f_entropy != NULL && /* For no-reseeding instances */ + ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON || + ctx->reseed_counter > ctx->reseed_interval ) ) + { + if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + return( ret ); + + add_len = 0; /* VII.4 */ + } + + /* 2. Use additional data if any */ + if( additional != NULL && add_len != 0 ) + { + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, + additional, add_len ) ) != 0 ) + goto exit; + } + + /* 3, 4, 5. Generate bytes */ + while( left != 0 ) + { + size_t use_len = left > md_len ? md_len : left; + + if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) + goto exit; + + memcpy( out, ctx->V, use_len ); + out += use_len; + left -= use_len; + } + + /* 6. Update */ + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, + additional, add_len ) ) != 0 ) + goto exit; + + /* 7. Update reseed counter */ + ctx->reseed_counter++; + +exit: + /* 8. Done */ + return( ret ); +} + +/* + * HMAC_DRBG random function + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) +{ + int ret; + mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * This function resets HMAC_DRBG context to the state immediately + * after initial call of mbedtls_hmac_drbg_init(). + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + /* The mutex is initialized iff the md context is set up. */ + if( ctx->md_ctx.md_info != NULL ) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_md_free( &ctx->md_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); + ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + int ret; + FILE *f; + unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + int ret = 0; + FILE *f = NULL; + size_t n; + unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + unsigned char c; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + n = fread( buf, 1, sizeof( buf ), f ); + if( fread( &c, 1, 1, f ) != 0 ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; + goto exit; + } + if( n == 0 || ferror( f ) ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; + goto exit; + } + fclose( f ); + f = NULL; + + ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n ); + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + if( f != NULL ) + fclose( f ); + if( ret != 0 ) + return( ret ); + return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_SHA1_C) +/* Dummy checkup routine */ +int mbedtls_hmac_drbg_self_test( int verbose ) +{ + (void) verbose; + return( 0 ); +} +#else + +#define OUTPUT_LEN 80 + +/* From a NIST PR=true test vector */ +static const unsigned char entropy_pr[] = { + 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, + 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, + 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, + 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, + 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; +static const unsigned char result_pr[OUTPUT_LEN] = { + 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, + 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, + 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, + 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, + 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, + 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, + 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; + +/* From a NIST PR=false test vector */ +static const unsigned char entropy_nopr[] = { + 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, + 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, + 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, + 0xe9, 0x9d, 0xfe, 0xdf }; +static const unsigned char result_nopr[OUTPUT_LEN] = { + 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, + 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, + 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, + 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, + 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, + 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, + 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; + +/* "Entropy" from buffer */ +static size_t test_offset; +static int hmac_drbg_self_test_entropy( void *data, + unsigned char *buf, size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine for HMAC_DRBG with SHA-1 + */ +int mbedtls_hmac_drbg_self_test( int verbose ) +{ + mbedtls_hmac_drbg_context ctx; + unsigned char buf[OUTPUT_LEN]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); + + mbedtls_hmac_drbg_init( &ctx ); + + /* + * PR = True + */ + if( verbose != 0 ) + mbedtls_printf( " HMAC_DRBG (PR = True) : " ); + + test_offset = 0; + CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_pr, + NULL, 0 ) ); + mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); + mbedtls_hmac_drbg_free( &ctx ); + + mbedtls_hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + /* + * PR = False + */ + if( verbose != 0 ) + mbedtls_printf( " HMAC_DRBG (PR = False) : " ); + + mbedtls_hmac_drbg_init( &ctx ); + + test_offset = 0; + CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_nopr, + NULL, 0 ) ); + CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); + mbedtls_hmac_drbg_free( &ctx ); + + mbedtls_hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_HMAC_DRBG_C */ diff --git a/external/mbedtls/library/md.c b/external/mbedtls/library/md.c new file mode 100644 index 0000000..867b914 --- /dev/null +++ b/external/mbedtls/library/md.c @@ -0,0 +1,500 @@ +/** + * \file mbedtls_md.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD_C) + +#include "mbedtls/md.h" +#include "mbedtls/md_internal.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +/* + * Reminder: update profiles in x509_crt.c when adding a new hash! + */ +static const int supported_digests[] = { + +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, + MBEDTLS_MD_SHA384, +#endif + +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif + +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_MD_SHA1, +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + MBEDTLS_MD_RIPEMD160, +#endif + +#if defined(MBEDTLS_MD5_C) + MBEDTLS_MD_MD5, +#endif + +#if defined(MBEDTLS_MD4_C) + MBEDTLS_MD_MD4, +#endif + +#if defined(MBEDTLS_MD2_C) + MBEDTLS_MD_MD2, +#endif + + MBEDTLS_MD_NONE +}; + +const int *mbedtls_md_list( void ) +{ + return( supported_digests ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) +{ + if( NULL == md_name ) + return( NULL ); + + /* Get the appropriate digest information */ +#if defined(MBEDTLS_MD2_C) + if( !strcmp( "MD2", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD2 ); +#endif +#if defined(MBEDTLS_MD4_C) + if( !strcmp( "MD4", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD4 ); +#endif +#if defined(MBEDTLS_MD5_C) + if( !strcmp( "MD5", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + if( !strcmp( "RIPEMD160", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 ); +#endif +#if defined(MBEDTLS_SHA1_C) + if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + if( !strcmp( "SHA224", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 ); + if( !strcmp( "SHA256", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + if( !strcmp( "SHA384", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); + if( !strcmp( "SHA512", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); +#endif + return( NULL ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) +{ + switch( md_type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( &mbedtls_md2_info ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( &mbedtls_md4_info ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( &mbedtls_md5_info ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( &mbedtls_ripemd160_info ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( &mbedtls_sha1_info ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( &mbedtls_sha224_info ); + case MBEDTLS_MD_SHA256: + return( &mbedtls_sha256_info ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + return( &mbedtls_sha384_info ); + case MBEDTLS_MD_SHA512: + return( &mbedtls_sha512_info ); +#endif + default: + return( NULL ); + } +} + +void mbedtls_md_init( mbedtls_md_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md_context_t ) ); +} + +void mbedtls_md_free( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return; + + if( ctx->md_ctx != NULL ) + ctx->md_info->ctx_free_func( ctx->md_ctx ); + + if( ctx->hmac_ctx != NULL ) + { + mbedtls_platform_zeroize( ctx->hmac_ctx, + 2 * ctx->md_info->block_size ); + mbedtls_free( ctx->hmac_ctx ); + } + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); +} + +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ) +{ + if( dst == NULL || dst->md_info == NULL || + src == NULL || src->md_info == NULL || + dst->md_info != src->md_info ) + { + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + dst->md_info->clone_func( dst->md_ctx, src->md_ctx ); + + return( 0 ); +} + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) +{ + return mbedtls_md_setup( ctx, md_info, 1 ); +} +#endif + +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ) +{ + if( md_info == NULL || ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + + if( hmac != 0 ) + { + ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size ); + if( ctx->hmac_ctx == NULL ) + { + md_info->ctx_free_func( ctx->md_ctx ); + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + } + } + + ctx->md_info = md_info; + + return( 0 ); +} + +int mbedtls_md_starts( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->starts_func( ctx->md_ctx ) ); +} + +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) ); +} + +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->finish_func( ctx->md_ctx, output ) ); +} + +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( md_info->digest_func( input, ilen, output ) ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ) +{ + int ret; + FILE *f; + size_t n; + mbedtls_md_context_t ctx; + unsigned char buf[1024]; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_MD_FILE_IO_ERROR ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + goto cleanup; + + if( ( ret = md_info->starts_func( ctx.md_ctx ) ) != 0 ) + goto cleanup; + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + if( ( ret = md_info->update_func( ctx.md_ctx, buf, n ) ) != 0 ) + goto cleanup; + + if( ferror( f ) != 0 ) + ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; + else + ret = md_info->finish_func( ctx.md_ctx, output ); + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + fclose( f ); + mbedtls_md_free( &ctx ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) +{ + int ret; + unsigned char sum[MBEDTLS_MD_MAX_SIZE]; + unsigned char *ipad, *opad; + size_t i; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( keylen > (size_t) ctx->md_info->block_size ) + { + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, sum ) ) != 0 ) + goto cleanup; + + keylen = ctx->md_info->size; + key = sum; + } + + ipad = (unsigned char *) ctx->hmac_ctx; + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + memset( ipad, 0x36, ctx->md_info->block_size ); + memset( opad, 0x5C, ctx->md_info->block_size ); + + for( i = 0; i < keylen; i++ ) + { + ipad[i] = (unsigned char)( ipad[i] ^ key[i] ); + opad[i] = (unsigned char)( opad[i] ^ key[i] ); + } + + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, ipad, + ctx->md_info->block_size ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_platform_zeroize( sum, sizeof( sum ) ); + + return( ret ); +} + +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) ); +} + +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + int ret; + unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; + unsigned char *opad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, tmp ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, opad, + ctx->md_info->block_size ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, tmp, + ctx->md_info->size ) ) != 0 ) + return( ret ); + return( ctx->md_info->finish_func( ctx->md_ctx, output ) ); +} + +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) +{ + int ret; + unsigned char *ipad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ipad = (unsigned char *) ctx->hmac_ctx; + + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + return( ret ); + return( ctx->md_info->update_func( ctx->md_ctx, ipad, + ctx->md_info->block_size ) ); +} + +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_md_context_t ctx; + int ret; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_starts( &ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_update( &ctx, input, ilen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_finish( &ctx, output ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_md_free( &ctx ); + + return( ret ); +} + +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->process_func( ctx->md_ctx, data ) ); +} + +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( 0 ); + + return md_info->size; +} + +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( MBEDTLS_MD_NONE ); + + return md_info->type; +} + +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( NULL ); + + return md_info->name; +} + +#endif /* MBEDTLS_MD_C */ diff --git a/external/mbedtls/library/md2.c b/external/mbedtls/library/md2.c new file mode 100644 index 0000000..fdcb630 --- /dev/null +++ b/external/mbedtls/library/md2.c @@ -0,0 +1,391 @@ +/* + * RFC 1115/1319 compliant MD2 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The MD2 algorithm was designed by Ron Rivest in 1989. + * + * http://www.ietf.org/rfc/rfc1115.txt + * http://www.ietf.org/rfc/rfc1319.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD2_C) + +#include "mbedtls/md2.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD2_ALT) + +static const unsigned char PI_SUBST[256] = +{ + 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, + 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, + 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, + 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, + 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, + 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, + 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, + 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, + 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, + 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, + 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, + 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, + 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, + 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, + 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, + 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, + 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, + 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, + 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, + 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, + 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, + 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, + 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, + 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, + 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, + 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 +}; + +void mbedtls_md2_init( mbedtls_md2_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md2_context ) ); +} + +void mbedtls_md2_free( mbedtls_md2_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md2_context ) ); +} + +void mbedtls_md2_clone( mbedtls_md2_context *dst, + const mbedtls_md2_context *src ) +{ + *dst = *src; +} + +/* + * MD2 context setup + */ +int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx ) +{ + memset( ctx->cksum, 0, 16 ); + memset( ctx->state, 0, 46 ); + memset( ctx->buffer, 0, 16 ); + ctx->left = 0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_starts( mbedtls_md2_context *ctx ) +{ + mbedtls_md2_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD2_PROCESS_ALT) +int mbedtls_internal_md2_process( mbedtls_md2_context *ctx ) +{ + int i, j; + unsigned char t = 0; + + for( i = 0; i < 16; i++ ) + { + ctx->state[i + 16] = ctx->buffer[i]; + ctx->state[i + 32] = + (unsigned char)( ctx->buffer[i] ^ ctx->state[i]); + } + + for( i = 0; i < 18; i++ ) + { + for( j = 0; j < 48; j++ ) + { + ctx->state[j] = (unsigned char) + ( ctx->state[j] ^ PI_SUBST[t] ); + t = ctx->state[j]; + } + + t = (unsigned char)( t + i ); + } + + t = ctx->cksum[15]; + + for( i = 0; i < 16; i++ ) + { + ctx->cksum[i] = (unsigned char) + ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] ); + t = ctx->cksum[i]; + } + + /* Zeroise variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &t, sizeof( t ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_process( mbedtls_md2_context *ctx ) +{ + mbedtls_internal_md2_process( ctx ); +} +#endif +#endif /* !MBEDTLS_MD2_PROCESS_ALT */ + +/* + * MD2 process buffer + */ +int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + + while( ilen > 0 ) + { + if( ilen > 16 - ctx->left ) + fill = 16 - ctx->left; + else + fill = ilen; + + memcpy( ctx->buffer + ctx->left, input, fill ); + + ctx->left += fill; + input += fill; + ilen -= fill; + + if( ctx->left == 16 ) + { + ctx->left = 0; + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + } + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_update( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md2_update_ret( ctx, input, ilen ); +} +#endif + +/* + * MD2 final digest + */ +int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, + unsigned char output[16] ) +{ + int ret; + size_t i; + unsigned char x; + + x = (unsigned char)( 16 - ctx->left ); + + for( i = ctx->left; i < 16; i++ ) + ctx->buffer[i] = x; + + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + + memcpy( ctx->buffer, ctx->cksum, 16 ); + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + + memcpy( output, ctx->state, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_finish( mbedtls_md2_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md2_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD2_ALT */ + +/* + * output = MD2( input buffer ) + */ +int mbedtls_md2_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret; + mbedtls_md2_context ctx; + + mbedtls_md2_init( &ctx ); + + if( ( ret = mbedtls_md2_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md2_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md2_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md2_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md2_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * RFC 1319 test vectors + */ +static const unsigned char md2_test_str[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890" } +}; + +static const size_t md2_test_strlen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md2_test_sum[7][16] = +{ + { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, + 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 }, + { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72, + 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 }, + { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B, + 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB }, + { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B, + 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 }, + { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB, + 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B }, + { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39, + 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD }, + { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D, + 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 } +}; + +/* + * Checkup routine + */ +int mbedtls_md2_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md2sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD2 test #%d: ", i + 1 ); + + ret = mbedtls_md2_ret( md2_test_str[i], md2_test_strlen[i], md2sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD2_C */ diff --git a/external/mbedtls/library/md4.c b/external/mbedtls/library/md4.c new file mode 100644 index 0000000..95e893e --- /dev/null +++ b/external/mbedtls/library/md4.c @@ -0,0 +1,515 @@ +/* + * RFC 1186/1320 compliant MD4 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The MD4 algorithm was designed by Ron Rivest in 1990. + * + * http://www.ietf.org/rfc/rfc1186.txt + * http://www.ietf.org/rfc/rfc1320.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD4_C) + +#include "mbedtls/md4.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD4_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void mbedtls_md4_init( mbedtls_md4_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md4_context ) ); +} + +void mbedtls_md4_free( mbedtls_md4_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) ); +} + +void mbedtls_md4_clone( mbedtls_md4_context *dst, + const mbedtls_md4_context *src ) +{ + *dst = *src; +} + +/* + * MD4 context setup + */ +int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_starts( mbedtls_md4_context *ctx ) +{ + mbedtls_md4_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD4_PROCESS_ALT) +int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t X[16], A, B, C, D; + } local; + + GET_UINT32_LE( local.X[ 0], data, 0 ); + GET_UINT32_LE( local.X[ 1], data, 4 ); + GET_UINT32_LE( local.X[ 2], data, 8 ); + GET_UINT32_LE( local.X[ 3], data, 12 ); + GET_UINT32_LE( local.X[ 4], data, 16 ); + GET_UINT32_LE( local.X[ 5], data, 20 ); + GET_UINT32_LE( local.X[ 6], data, 24 ); + GET_UINT32_LE( local.X[ 7], data, 28 ); + GET_UINT32_LE( local.X[ 8], data, 32 ); + GET_UINT32_LE( local.X[ 9], data, 36 ); + GET_UINT32_LE( local.X[10], data, 40 ); + GET_UINT32_LE( local.X[11], data, 44 ); + GET_UINT32_LE( local.X[12], data, 48 ); + GET_UINT32_LE( local.X[13], data, 52 ); + GET_UINT32_LE( local.X[14], data, 56 ); + GET_UINT32_LE( local.X[15], data, 60 ); + +#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) + + local.A = ctx->state[0]; + local.B = ctx->state[1]; + local.C = ctx->state[2]; + local.D = ctx->state[3]; + +#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z))) +#define P(a,b,c,d,x,s) \ + do \ + { \ + (a) += F((b),(c),(d)) + (x); \ + (a) = S((a),(s)); \ + } while( 0 ) + + + P( local.A, local.B, local.C, local.D, local.X[ 0], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 1], 7 ); + P( local.C, local.D, local.A, local.B, local.X[ 2], 11 ); + P( local.B, local.C, local.D, local.A, local.X[ 3], 19 ); + P( local.A, local.B, local.C, local.D, local.X[ 4], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 5], 7 ); + P( local.C, local.D, local.A, local.B, local.X[ 6], 11 ); + P( local.B, local.C, local.D, local.A, local.X[ 7], 19 ); + P( local.A, local.B, local.C, local.D, local.X[ 8], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 9], 7 ); + P( local.C, local.D, local.A, local.B, local.X[10], 11 ); + P( local.B, local.C, local.D, local.A, local.X[11], 19 ); + P( local.A, local.B, local.C, local.D, local.X[12], 3 ); + P( local.D, local.A, local.B, local.C, local.X[13], 7 ); + P( local.C, local.D, local.A, local.B, local.X[14], 11 ); + P( local.B, local.C, local.D, local.A, local.X[15], 19 ); + +#undef P +#undef F + +#define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define P(a,b,c,d,x,s) \ + do \ + { \ + (a) += F((b),(c),(d)) + (x) + 0x5A827999; \ + (a) = S((a),(s)); \ + } while( 0 ) + + P( local.A, local.B, local.C, local.D, local.X[ 0], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 4], 5 ); + P( local.C, local.D, local.A, local.B, local.X[ 8], 9 ); + P( local.B, local.C, local.D, local.A, local.X[12], 13 ); + P( local.A, local.B, local.C, local.D, local.X[ 1], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 5], 5 ); + P( local.C, local.D, local.A, local.B, local.X[ 9], 9 ); + P( local.B, local.C, local.D, local.A, local.X[13], 13 ); + P( local.A, local.B, local.C, local.D, local.X[ 2], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 6], 5 ); + P( local.C, local.D, local.A, local.B, local.X[10], 9 ); + P( local.B, local.C, local.D, local.A, local.X[14], 13 ); + P( local.A, local.B, local.C, local.D, local.X[ 3], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 7], 5 ); + P( local.C, local.D, local.A, local.B, local.X[11], 9 ); + P( local.B, local.C, local.D, local.A, local.X[15], 13 ); + +#undef P +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define P(a,b,c,d,x,s) \ + do \ + { \ + (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \ + (a) = S((a),(s)); \ + } while( 0 ) + + P( local.A, local.B, local.C, local.D, local.X[ 0], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 8], 9 ); + P( local.C, local.D, local.A, local.B, local.X[ 4], 11 ); + P( local.B, local.C, local.D, local.A, local.X[12], 15 ); + P( local.A, local.B, local.C, local.D, local.X[ 2], 3 ); + P( local.D, local.A, local.B, local.C, local.X[10], 9 ); + P( local.C, local.D, local.A, local.B, local.X[ 6], 11 ); + P( local.B, local.C, local.D, local.A, local.X[14], 15 ); + P( local.A, local.B, local.C, local.D, local.X[ 1], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 9], 9 ); + P( local.C, local.D, local.A, local.B, local.X[ 5], 11 ); + P( local.B, local.C, local.D, local.A, local.X[13], 15 ); + P( local.A, local.B, local.C, local.D, local.X[ 3], 3 ); + P( local.D, local.A, local.B, local.C, local.X[11], 9 ); + P( local.C, local.D, local.A, local.B, local.X[ 7], 11 ); + P( local.B, local.C, local.D, local.A, local.X[15], 15 ); + +#undef F +#undef P + + ctx->state[0] += local.A; + ctx->state[1] += local.B; + ctx->state[2] += local.C; + ctx->state[3] += local.D; + + /* Zeroise variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_md4_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_MD4_PROCESS_ALT */ + +/* + * MD4 process buffer + */ +int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, fill ); + + if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_update( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md4_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char md4_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD4 final digest + */ +int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, + unsigned char output[16] ) +{ + int ret; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn ); + if( ret != 0 ) + return( ret ); + + if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 ) + return( ret ); + + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_finish( mbedtls_md4_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md4_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD4_ALT */ + +/* + * output = MD4( input buffer ) + */ +int mbedtls_md4_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret; + mbedtls_md4_context ctx; + + mbedtls_md4_init( &ctx ); + + if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md4_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md4_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * RFC 1320 test vectors + */ +static const unsigned char md4_test_str[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890" } +}; + +static const size_t md4_test_strlen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md4_test_sum[7][16] = +{ + { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, + 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 }, + { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46, + 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 }, + { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52, + 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D }, + { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8, + 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B }, + { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD, + 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 }, + { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35, + 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 }, + { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19, + 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 } +}; + +/* + * Checkup routine + */ +int mbedtls_md4_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md4sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD4 test #%d: ", i + 1 ); + + ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD4_C */ diff --git a/external/mbedtls/library/md5.c b/external/mbedtls/library/md5.c new file mode 100644 index 0000000..d2b634f --- /dev/null +++ b/external/mbedtls/library/md5.c @@ -0,0 +1,529 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD5_C) + +#include "mbedtls/md5.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD5_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void mbedtls_md5_init( mbedtls_md5_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_free( mbedtls_md5_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ) +{ + *dst = *src; +} + +/* + * MD5 context setup + */ +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_starts( mbedtls_md5_context *ctx ) +{ + mbedtls_md5_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD5_PROCESS_ALT) +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t X[16], A, B, C, D; + } local; + + GET_UINT32_LE( local.X[ 0], data, 0 ); + GET_UINT32_LE( local.X[ 1], data, 4 ); + GET_UINT32_LE( local.X[ 2], data, 8 ); + GET_UINT32_LE( local.X[ 3], data, 12 ); + GET_UINT32_LE( local.X[ 4], data, 16 ); + GET_UINT32_LE( local.X[ 5], data, 20 ); + GET_UINT32_LE( local.X[ 6], data, 24 ); + GET_UINT32_LE( local.X[ 7], data, 28 ); + GET_UINT32_LE( local.X[ 8], data, 32 ); + GET_UINT32_LE( local.X[ 9], data, 36 ); + GET_UINT32_LE( local.X[10], data, 40 ); + GET_UINT32_LE( local.X[11], data, 44 ); + GET_UINT32_LE( local.X[12], data, 48 ); + GET_UINT32_LE( local.X[13], data, 52 ); + GET_UINT32_LE( local.X[14], data, 56 ); + GET_UINT32_LE( local.X[15], data, 60 ); + +#define S(x,n) \ + ( ( (x) << (n) ) | ( ( (x) & 0xFFFFFFFF) >> ( 32 - (n) ) ) ) + +#define P(a,b,c,d,k,s,t) \ + do \ + { \ + (a) += F((b),(c),(d)) + local.X[(k)] + (t); \ + (a) = S((a),(s)) + (b); \ + } while( 0 ) + + local.A = ctx->state[0]; + local.B = ctx->state[1]; + local.C = ctx->state[2]; + local.D = ctx->state[3]; + +#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + + P( local.A, local.B, local.C, local.D, 0, 7, 0xD76AA478 ); + P( local.D, local.A, local.B, local.C, 1, 12, 0xE8C7B756 ); + P( local.C, local.D, local.A, local.B, 2, 17, 0x242070DB ); + P( local.B, local.C, local.D, local.A, 3, 22, 0xC1BDCEEE ); + P( local.A, local.B, local.C, local.D, 4, 7, 0xF57C0FAF ); + P( local.D, local.A, local.B, local.C, 5, 12, 0x4787C62A ); + P( local.C, local.D, local.A, local.B, 6, 17, 0xA8304613 ); + P( local.B, local.C, local.D, local.A, 7, 22, 0xFD469501 ); + P( local.A, local.B, local.C, local.D, 8, 7, 0x698098D8 ); + P( local.D, local.A, local.B, local.C, 9, 12, 0x8B44F7AF ); + P( local.C, local.D, local.A, local.B, 10, 17, 0xFFFF5BB1 ); + P( local.B, local.C, local.D, local.A, 11, 22, 0x895CD7BE ); + P( local.A, local.B, local.C, local.D, 12, 7, 0x6B901122 ); + P( local.D, local.A, local.B, local.C, 13, 12, 0xFD987193 ); + P( local.C, local.D, local.A, local.B, 14, 17, 0xA679438E ); + P( local.B, local.C, local.D, local.A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) ((y) ^ ((z) & ((x) ^ (y)))) + + P( local.A, local.B, local.C, local.D, 1, 5, 0xF61E2562 ); + P( local.D, local.A, local.B, local.C, 6, 9, 0xC040B340 ); + P( local.C, local.D, local.A, local.B, 11, 14, 0x265E5A51 ); + P( local.B, local.C, local.D, local.A, 0, 20, 0xE9B6C7AA ); + P( local.A, local.B, local.C, local.D, 5, 5, 0xD62F105D ); + P( local.D, local.A, local.B, local.C, 10, 9, 0x02441453 ); + P( local.C, local.D, local.A, local.B, 15, 14, 0xD8A1E681 ); + P( local.B, local.C, local.D, local.A, 4, 20, 0xE7D3FBC8 ); + P( local.A, local.B, local.C, local.D, 9, 5, 0x21E1CDE6 ); + P( local.D, local.A, local.B, local.C, 14, 9, 0xC33707D6 ); + P( local.C, local.D, local.A, local.B, 3, 14, 0xF4D50D87 ); + P( local.B, local.C, local.D, local.A, 8, 20, 0x455A14ED ); + P( local.A, local.B, local.C, local.D, 13, 5, 0xA9E3E905 ); + P( local.D, local.A, local.B, local.C, 2, 9, 0xFCEFA3F8 ); + P( local.C, local.D, local.A, local.B, 7, 14, 0x676F02D9 ); + P( local.B, local.C, local.D, local.A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) + + P( local.A, local.B, local.C, local.D, 5, 4, 0xFFFA3942 ); + P( local.D, local.A, local.B, local.C, 8, 11, 0x8771F681 ); + P( local.C, local.D, local.A, local.B, 11, 16, 0x6D9D6122 ); + P( local.B, local.C, local.D, local.A, 14, 23, 0xFDE5380C ); + P( local.A, local.B, local.C, local.D, 1, 4, 0xA4BEEA44 ); + P( local.D, local.A, local.B, local.C, 4, 11, 0x4BDECFA9 ); + P( local.C, local.D, local.A, local.B, 7, 16, 0xF6BB4B60 ); + P( local.B, local.C, local.D, local.A, 10, 23, 0xBEBFBC70 ); + P( local.A, local.B, local.C, local.D, 13, 4, 0x289B7EC6 ); + P( local.D, local.A, local.B, local.C, 0, 11, 0xEAA127FA ); + P( local.C, local.D, local.A, local.B, 3, 16, 0xD4EF3085 ); + P( local.B, local.C, local.D, local.A, 6, 23, 0x04881D05 ); + P( local.A, local.B, local.C, local.D, 9, 4, 0xD9D4D039 ); + P( local.D, local.A, local.B, local.C, 12, 11, 0xE6DB99E5 ); + P( local.C, local.D, local.A, local.B, 15, 16, 0x1FA27CF8 ); + P( local.B, local.C, local.D, local.A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) ((y) ^ ((x) | ~(z))) + + P( local.A, local.B, local.C, local.D, 0, 6, 0xF4292244 ); + P( local.D, local.A, local.B, local.C, 7, 10, 0x432AFF97 ); + P( local.C, local.D, local.A, local.B, 14, 15, 0xAB9423A7 ); + P( local.B, local.C, local.D, local.A, 5, 21, 0xFC93A039 ); + P( local.A, local.B, local.C, local.D, 12, 6, 0x655B59C3 ); + P( local.D, local.A, local.B, local.C, 3, 10, 0x8F0CCC92 ); + P( local.C, local.D, local.A, local.B, 10, 15, 0xFFEFF47D ); + P( local.B, local.C, local.D, local.A, 1, 21, 0x85845DD1 ); + P( local.A, local.B, local.C, local.D, 8, 6, 0x6FA87E4F ); + P( local.D, local.A, local.B, local.C, 15, 10, 0xFE2CE6E0 ); + P( local.C, local.D, local.A, local.B, 6, 15, 0xA3014314 ); + P( local.B, local.C, local.D, local.A, 13, 21, 0x4E0811A1 ); + P( local.A, local.B, local.C, local.D, 4, 6, 0xF7537E82 ); + P( local.D, local.A, local.B, local.C, 11, 10, 0xBD3AF235 ); + P( local.C, local.D, local.A, local.B, 2, 15, 0x2AD7D2BB ); + P( local.B, local.C, local.D, local.A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += local.A; + ctx->state[1] += local.B; + ctx->state[2] += local.C; + ctx->state[3] += local.D; + + /* Zeroise variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_md5_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_MD5_PROCESS_ALT */ + +/* + * MD5 process buffer + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md5_update_ret( ctx, input, ilen ); +} +#endif + +/* + * MD5 final digest + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + int ret; + uint32_t used; + uint32_t high, low; + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, ctx->buffer, 56 ); + PUT_UINT32_LE( high, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md5_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD5_ALT */ + +/* + * output = MD5( input buffer ) + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret; + mbedtls_md5_context ctx; + + mbedtls_md5_init( &ctx ); + + if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md5_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md5_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * RFC 1321 test vectors + */ +static const unsigned char md5_test_buf[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890" } +}; + +static const size_t md5_test_buflen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md5_test_sum[7][16] = +{ + { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, + 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, + { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, + 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, + { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, + 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, + { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, + 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, + { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, + 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, + { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, + 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, + { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, + 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } +}; + +/* + * Checkup routine + */ +int mbedtls_md5_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md5sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD5 test #%d: ", i + 1 ); + + ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD5_C */ diff --git a/external/mbedtls/library/md_wrap.c b/external/mbedtls/library/md_wrap.c new file mode 100644 index 0000000..7459db2 --- /dev/null +++ b/external/mbedtls/library/md_wrap.c @@ -0,0 +1,611 @@ +/** + * \file md_wrap.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD_C) + +#include "mbedtls/md_internal.h" + +#if defined(MBEDTLS_MD2_C) +#include "mbedtls/md2.h" +#endif + +#if defined(MBEDTLS_MD4_C) +#include "mbedtls/md4.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#include "mbedtls/ripemd160.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_MD2_C) + +static int md2_starts_wrap( void *ctx ) +{ + return( mbedtls_md2_starts_ret( (mbedtls_md2_context *) ctx ) ); +} + +static int md2_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_md2_update_ret( (mbedtls_md2_context *) ctx, input, ilen ) ); +} + +static int md2_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_md2_finish_ret( (mbedtls_md2_context *) ctx, output ) ); +} + +static void *md2_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md2_context ) ); + + if( ctx != NULL ) + mbedtls_md2_init( (mbedtls_md2_context *) ctx ); + + return( ctx ); +} + +static void md2_ctx_free( void *ctx ) +{ + mbedtls_md2_free( (mbedtls_md2_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md2_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md2_clone( (mbedtls_md2_context *) dst, + (const mbedtls_md2_context *) src ); +} + +static int md2_process_wrap( void *ctx, const unsigned char *data ) +{ + ((void) data); + + return( mbedtls_internal_md2_process( (mbedtls_md2_context *) ctx ) ); +} + +const mbedtls_md_info_t mbedtls_md2_info = { + MBEDTLS_MD_MD2, + "MD2", + 16, + 16, + md2_starts_wrap, + md2_update_wrap, + md2_finish_wrap, + mbedtls_md2_ret, + md2_ctx_alloc, + md2_ctx_free, + md2_clone_wrap, + md2_process_wrap, +}; + +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + +static int md4_starts_wrap( void *ctx ) +{ + return( mbedtls_md4_starts_ret( (mbedtls_md4_context *) ctx ) ); +} + +static int md4_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_md4_update_ret( (mbedtls_md4_context *) ctx, input, ilen ) ); +} + +static int md4_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_md4_finish_ret( (mbedtls_md4_context *) ctx, output ) ); +} + +static void *md4_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md4_context ) ); + + if( ctx != NULL ) + mbedtls_md4_init( (mbedtls_md4_context *) ctx ); + + return( ctx ); +} + +static void md4_ctx_free( void *ctx ) +{ + mbedtls_md4_free( (mbedtls_md4_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md4_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md4_clone( (mbedtls_md4_context *) dst, + (const mbedtls_md4_context *) src ); +} + +static int md4_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_md4_process( (mbedtls_md4_context *) ctx, data ) ); +} + +const mbedtls_md_info_t mbedtls_md4_info = { + MBEDTLS_MD_MD4, + "MD4", + 16, + 64, + md4_starts_wrap, + md4_update_wrap, + md4_finish_wrap, + mbedtls_md4_ret, + md4_ctx_alloc, + md4_ctx_free, + md4_clone_wrap, + md4_process_wrap, +}; + +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + +static int md5_starts_wrap( void *ctx ) +{ + return( mbedtls_md5_starts_ret( (mbedtls_md5_context *) ctx ) ); +} + +static int md5_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_md5_update_ret( (mbedtls_md5_context *) ctx, input, ilen ) ); +} + +static int md5_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_md5_finish_ret( (mbedtls_md5_context *) ctx, output ) ); +} + +static void *md5_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) ); + + if( ctx != NULL ) + mbedtls_md5_init( (mbedtls_md5_context *) ctx ); + + return( ctx ); +} + +static void md5_ctx_free( void *ctx ) +{ + mbedtls_md5_free( (mbedtls_md5_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md5_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md5_clone( (mbedtls_md5_context *) dst, + (const mbedtls_md5_context *) src ); +} + +static int md5_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_md5_process( (mbedtls_md5_context *) ctx, data ) ); +} + +const mbedtls_md_info_t mbedtls_md5_info = { + MBEDTLS_MD_MD5, + "MD5", + 16, + 64, + md5_starts_wrap, + md5_update_wrap, + md5_finish_wrap, + mbedtls_md5_ret, + md5_ctx_alloc, + md5_ctx_free, + md5_clone_wrap, + md5_process_wrap, +}; + +#endif /* MBEDTLS_MD5_C */ + +#if defined(MBEDTLS_RIPEMD160_C) + +static int ripemd160_starts_wrap( void *ctx ) +{ + return( mbedtls_ripemd160_starts_ret( (mbedtls_ripemd160_context *) ctx ) ); +} + +static int ripemd160_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_ripemd160_update_ret( (mbedtls_ripemd160_context *) ctx, + input, ilen ) ); +} + +static int ripemd160_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_ripemd160_finish_ret( (mbedtls_ripemd160_context *) ctx, + output ) ); +} + +static void *ripemd160_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ripemd160_context ) ); + + if( ctx != NULL ) + mbedtls_ripemd160_init( (mbedtls_ripemd160_context *) ctx ); + + return( ctx ); +} + +static void ripemd160_ctx_free( void *ctx ) +{ + mbedtls_ripemd160_free( (mbedtls_ripemd160_context *) ctx ); + mbedtls_free( ctx ); +} + +static void ripemd160_clone_wrap( void *dst, const void *src ) +{ + mbedtls_ripemd160_clone( (mbedtls_ripemd160_context *) dst, + (const mbedtls_ripemd160_context *) src ); +} + +static int ripemd160_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_ripemd160_process( + (mbedtls_ripemd160_context *) ctx, data ) ); +} + +const mbedtls_md_info_t mbedtls_ripemd160_info = { + MBEDTLS_MD_RIPEMD160, + "RIPEMD160", + 20, + 64, + ripemd160_starts_wrap, + ripemd160_update_wrap, + ripemd160_finish_wrap, + mbedtls_ripemd160_ret, + ripemd160_ctx_alloc, + ripemd160_ctx_free, + ripemd160_clone_wrap, + ripemd160_process_wrap, +}; + +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_SHA1_C) + +static int sha1_starts_wrap( void *ctx ) +{ + return( mbedtls_sha1_starts_ret( (mbedtls_sha1_context *) ctx ) ); +} + +static int sha1_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_sha1_update_ret( (mbedtls_sha1_context *) ctx, + input, ilen ) ); +} + +static int sha1_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_sha1_finish_ret( (mbedtls_sha1_context *) ctx, output ) ); +} + +static void *sha1_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha1_context ) ); + + if( ctx != NULL ) + mbedtls_sha1_init( (mbedtls_sha1_context *) ctx ); + + return( ctx ); +} + +static void sha1_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha1_clone( (mbedtls_sha1_context *) dst, + (const mbedtls_sha1_context *) src ); +} + +static void sha1_ctx_free( void *ctx ) +{ + mbedtls_sha1_free( (mbedtls_sha1_context *) ctx ); + mbedtls_free( ctx ); +} + +static int sha1_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_sha1_process( (mbedtls_sha1_context *) ctx, + data ) ); +} + +const mbedtls_md_info_t mbedtls_sha1_info = { + MBEDTLS_MD_SHA1, + "SHA1", + 20, + 64, + sha1_starts_wrap, + sha1_update_wrap, + sha1_finish_wrap, + mbedtls_sha1_ret, + sha1_ctx_alloc, + sha1_ctx_free, + sha1_clone_wrap, + sha1_process_wrap, +}; + +#endif /* MBEDTLS_SHA1_C */ + +/* + * Wrappers for generic message digests + */ +#if defined(MBEDTLS_SHA256_C) + +static int sha224_starts_wrap( void *ctx ) +{ + return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 1 ) ); +} + +static int sha224_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_sha256_update_ret( (mbedtls_sha256_context *) ctx, + input, ilen ) ); +} + +static int sha224_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_sha256_finish_ret( (mbedtls_sha256_context *) ctx, + output ) ); +} + +static int sha224_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha256_ret( input, ilen, output, 1 ) ); +} + +static void *sha224_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) ); + + if( ctx != NULL ) + mbedtls_sha256_init( (mbedtls_sha256_context *) ctx ); + + return( ctx ); +} + +static void sha224_ctx_free( void *ctx ) +{ + mbedtls_sha256_free( (mbedtls_sha256_context *) ctx ); + mbedtls_free( ctx ); +} + +static void sha224_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha256_clone( (mbedtls_sha256_context *) dst, + (const mbedtls_sha256_context *) src ); +} + +static int sha224_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_sha256_process( (mbedtls_sha256_context *) ctx, + data ) ); +} + +const mbedtls_md_info_t mbedtls_sha224_info = { + MBEDTLS_MD_SHA224, + "SHA224", + 28, + 64, + sha224_starts_wrap, + sha224_update_wrap, + sha224_finish_wrap, + sha224_wrap, + sha224_ctx_alloc, + sha224_ctx_free, + sha224_clone_wrap, + sha224_process_wrap, +}; + +static int sha256_starts_wrap( void *ctx ) +{ + return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 0 ) ); +} + +static int sha256_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha256_ret( input, ilen, output, 0 ) ); +} + +const mbedtls_md_info_t mbedtls_sha256_info = { + MBEDTLS_MD_SHA256, + "SHA256", + 32, + 64, + sha256_starts_wrap, + sha224_update_wrap, + sha224_finish_wrap, + sha256_wrap, + sha224_ctx_alloc, + sha224_ctx_free, + sha224_clone_wrap, + sha224_process_wrap, +}; + +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + +static int sha384_starts_wrap( void *ctx ) +{ + return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 1 ) ); +} + +static int sha384_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_sha512_update_ret( (mbedtls_sha512_context *) ctx, + input, ilen ) ); +} + +static int sha384_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_sha512_finish_ret( (mbedtls_sha512_context *) ctx, + output ) ); +} + +static int sha384_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha512_ret( input, ilen, output, 1 ) ); +} + +static void *sha384_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha512_context ) ); + + if( ctx != NULL ) + mbedtls_sha512_init( (mbedtls_sha512_context *) ctx ); + + return( ctx ); +} + +static void sha384_ctx_free( void *ctx ) +{ + mbedtls_sha512_free( (mbedtls_sha512_context *) ctx ); + mbedtls_free( ctx ); +} + +static void sha384_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha512_clone( (mbedtls_sha512_context *) dst, + (const mbedtls_sha512_context *) src ); +} + +static int sha384_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_sha512_process( (mbedtls_sha512_context *) ctx, + data ) ); +} + +const mbedtls_md_info_t mbedtls_sha384_info = { + MBEDTLS_MD_SHA384, + "SHA384", + 48, + 128, + sha384_starts_wrap, + sha384_update_wrap, + sha384_finish_wrap, + sha384_wrap, + sha384_ctx_alloc, + sha384_ctx_free, + sha384_clone_wrap, + sha384_process_wrap, +}; + +static int sha512_starts_wrap( void *ctx ) +{ + return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 0 ) ); +} + +static int sha512_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha512_ret( input, ilen, output, 0 ) ); +} + +const mbedtls_md_info_t mbedtls_sha512_info = { + MBEDTLS_MD_SHA512, + "SHA512", + 64, + 128, + sha512_starts_wrap, + sha384_update_wrap, + sha384_finish_wrap, + sha512_wrap, + sha384_ctx_alloc, + sha384_ctx_free, + sha384_clone_wrap, + sha384_process_wrap, +}; + +#endif /* MBEDTLS_SHA512_C */ + +#endif /* MBEDTLS_MD_C */ diff --git a/external/mbedtls/library/memory_buffer_alloc.c b/external/mbedtls/library/memory_buffer_alloc.c new file mode 100644 index 0000000..915ec3a --- /dev/null +++ b/external/mbedtls/library/memory_buffer_alloc.c @@ -0,0 +1,775 @@ +/* + * Buffer-based memory allocator + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" + +/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C + is dependent upon MBEDTLS_PLATFORM_C */ +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_MEMORY_BACKTRACE) +#include +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#define MAGIC1 0xFF00AA55 +#define MAGIC2 0xEE119966 +#define MAX_BT 20 + +typedef struct _memory_header memory_header; +struct _memory_header +{ + size_t magic1; + size_t size; + size_t alloc; + memory_header *prev; + memory_header *next; + memory_header *prev_free; + memory_header *next_free; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + char **trace; + size_t trace_count; +#endif + size_t magic2; +}; + +typedef struct +{ + unsigned char *buf; + size_t len; + memory_header *first; + memory_header *first_free; + int verify; +#if defined(MBEDTLS_MEMORY_DEBUG) + size_t alloc_count; + size_t free_count; + size_t total_used; + size_t maximum_used; + size_t header_count; + size_t maximum_header_count; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +buffer_alloc_ctx; + +static buffer_alloc_ctx heap; + +#if defined(MBEDTLS_MEMORY_DEBUG) +static void debug_header( memory_header *hdr ) +{ +#if defined(MBEDTLS_MEMORY_BACKTRACE) + size_t i; +#endif + + mbedtls_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), " + "ALLOC(%zu), SIZE(%10zu)\n", + (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next, + hdr->alloc, hdr->size ); + mbedtls_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n", + (size_t) hdr->prev_free, (size_t) hdr->next_free ); + +#if defined(MBEDTLS_MEMORY_BACKTRACE) + mbedtls_fprintf( stderr, "TRACE: \n" ); + for( i = 0; i < hdr->trace_count; i++ ) + mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] ); + mbedtls_fprintf( stderr, "\n" ); +#endif +} + +static void debug_chain( void ) +{ + memory_header *cur = heap.first; + + mbedtls_fprintf( stderr, "\nBlock list\n" ); + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next; + } + + mbedtls_fprintf( stderr, "Free list\n" ); + cur = heap.first_free; + + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next_free; + } +} +#endif /* MBEDTLS_MEMORY_DEBUG */ + +static int verify_header( memory_header *hdr ) +{ + if( hdr->magic1 != MAGIC1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->magic2 != MAGIC2 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->alloc > 1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" ); +#endif + return( 1 ); + } + + if( hdr->prev != NULL && hdr->prev == hdr->next ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: prev == next\n" ); +#endif + return( 1 ); + } + + if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" ); +#endif + return( 1 ); + } + + return( 0 ); +} + +static int verify_chain( void ) +{ + memory_header *prv = heap.first, *cur; + + if( prv == NULL || verify_header( prv ) != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification of first header " + "failed\n" ); +#endif + return( 1 ); + } + + if( heap.first->prev != NULL ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification failed: " + "first->prev != NULL\n" ); +#endif + return( 1 ); + } + + cur = heap.first->next; + + while( cur != NULL ) + { + if( verify_header( cur ) != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification of header " + "failed\n" ); +#endif + return( 1 ); + } + + if( cur->prev != prv ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification failed: " + "cur->prev != prv\n" ); +#endif + return( 1 ); + } + + prv = cur; + cur = cur->next; + } + + return( 0 ); +} + +static void *buffer_alloc_calloc( size_t n, size_t size ) +{ + memory_header *new, *cur = heap.first_free; + unsigned char *p; + void *ret; + size_t original_len, len; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + void *trace_buffer[MAX_BT]; + size_t trace_cnt; +#endif + + if( heap.buf == NULL || heap.first == NULL ) + return( NULL ); + + original_len = len = n * size; + + if( n == 0 || size == 0 || len / n != size ) + return( NULL ); + else if( len > (size_t)-MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + return( NULL ); + + if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + len += MBEDTLS_MEMORY_ALIGN_MULTIPLE; + } + + // Find block that fits + // + while( cur != NULL ) + { + if( cur->size >= len ) + break; + + cur = cur->next_free; + } + + if( cur == NULL ) + return( NULL ); + + if( cur->alloc != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated " + "data\n" ); +#endif + mbedtls_exit( 1 ); + } + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.alloc_count++; +#endif + + // Found location, split block if > memory_header + 4 room left + // + if( cur->size - len < sizeof(memory_header) + + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + cur->alloc = 1; + + // Remove from free_list + // + if( cur->prev_free != NULL ) + cur->prev_free->next_free = cur->next_free; + else + heap.first_free = cur->next_free; + + if( cur->next_free != NULL ) + cur->next_free->prev_free = cur->prev_free; + + cur->prev_free = NULL; + cur->next_free = NULL; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(MBEDTLS_MEMORY_BACKTRACE) + trace_cnt = backtrace( trace_buffer, MAX_BT ); + cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); + cur->trace_count = trace_cnt; +#endif + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); + + ret = (unsigned char *) cur + sizeof( memory_header ); + memset( ret, 0, original_len ); + + return( ret ); + } + + p = ( (unsigned char *) cur ) + sizeof(memory_header) + len; + new = (memory_header *) p; + + new->size = cur->size - len - sizeof(memory_header); + new->alloc = 0; + new->prev = cur; + new->next = cur->next; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + new->trace = NULL; + new->trace_count = 0; +#endif + new->magic1 = MAGIC1; + new->magic2 = MAGIC2; + + if( new->next != NULL ) + new->next->prev = new; + + // Replace cur with new in free_list + // + new->prev_free = cur->prev_free; + new->next_free = cur->next_free; + if( new->prev_free != NULL ) + new->prev_free->next_free = new; + else + heap.first_free = new; + + if( new->next_free != NULL ) + new->next_free->prev_free = new; + + cur->alloc = 1; + cur->size = len; + cur->next = new; + cur->prev_free = NULL; + cur->next_free = NULL; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count++; + if( heap.header_count > heap.maximum_header_count ) + heap.maximum_header_count = heap.header_count; + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(MBEDTLS_MEMORY_BACKTRACE) + trace_cnt = backtrace( trace_buffer, MAX_BT ); + cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); + cur->trace_count = trace_cnt; +#endif + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); + + ret = (unsigned char *) cur + sizeof( memory_header ); + memset( ret, 0, original_len ); + + return( ret ); +} + +static void buffer_alloc_free( void *ptr ) +{ + memory_header *hdr, *old = NULL; + unsigned char *p = (unsigned char *) ptr; + + if( ptr == NULL || heap.buf == NULL || heap.first == NULL ) + return; + + if( p < heap.buf || p >= heap.buf + heap.len ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed " + "space\n" ); +#endif + mbedtls_exit( 1 ); + } + + p -= sizeof(memory_header); + hdr = (memory_header *) p; + + if( verify_header( hdr ) != 0 ) + mbedtls_exit( 1 ); + + if( hdr->alloc != 1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated " + "data\n" ); +#endif + mbedtls_exit( 1 ); + } + + hdr->alloc = 0; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.free_count++; + heap.total_used -= hdr->size; +#endif + +#if defined(MBEDTLS_MEMORY_BACKTRACE) + free( hdr->trace ); + hdr->trace = NULL; + hdr->trace_count = 0; +#endif + + // Regroup with block before + // + if( hdr->prev != NULL && hdr->prev->alloc == 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count--; +#endif + hdr->prev->size += sizeof(memory_header) + hdr->size; + hdr->prev->next = hdr->next; + old = hdr; + hdr = hdr->prev; + + if( hdr->next != NULL ) + hdr->next->prev = hdr; + + memset( old, 0, sizeof(memory_header) ); + } + + // Regroup with block after + // + if( hdr->next != NULL && hdr->next->alloc == 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count--; +#endif + hdr->size += sizeof(memory_header) + hdr->next->size; + old = hdr->next; + hdr->next = hdr->next->next; + + if( hdr->prev_free != NULL || hdr->next_free != NULL ) + { + if( hdr->prev_free != NULL ) + hdr->prev_free->next_free = hdr->next_free; + else + heap.first_free = hdr->next_free; + + if( hdr->next_free != NULL ) + hdr->next_free->prev_free = hdr->prev_free; + } + + hdr->prev_free = old->prev_free; + hdr->next_free = old->next_free; + + if( hdr->prev_free != NULL ) + hdr->prev_free->next_free = hdr; + else + heap.first_free = hdr; + + if( hdr->next_free != NULL ) + hdr->next_free->prev_free = hdr; + + if( hdr->next != NULL ) + hdr->next->prev = hdr; + + memset( old, 0, sizeof(memory_header) ); + } + + // Prepend to free_list if we have not merged + // (Does not have to stay in same order as prev / next list) + // + if( old == NULL ) + { + hdr->next_free = heap.first_free; + if( heap.first_free != NULL ) + heap.first_free->prev_free = hdr; + heap.first_free = hdr; + } + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); +} + +void mbedtls_memory_buffer_set_verify( int verify ) +{ + heap.verify = verify; +} + +int mbedtls_memory_buffer_alloc_verify( void ) +{ + return verify_chain(); +} + +#if defined(MBEDTLS_MEMORY_DEBUG) +void mbedtls_memory_buffer_alloc_status( void ) +{ + mbedtls_fprintf( stderr, + "Current use: %zu blocks / %zu bytes, max: %zu blocks / " + "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n", + heap.header_count, heap.total_used, + heap.maximum_header_count, heap.maximum_used, + heap.maximum_header_count * sizeof( memory_header ) + + heap.maximum_used, + heap.alloc_count, heap.free_count ); + + if( heap.first->next == NULL ) + { + mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); + } + else + { + mbedtls_fprintf( stderr, "Memory currently allocated:\n" ); + debug_chain(); + } +} + +void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ) +{ + *max_used = heap.maximum_used; + *max_blocks = heap.maximum_header_count; +} + +void mbedtls_memory_buffer_alloc_max_reset( void ) +{ + heap.maximum_used = 0; + heap.maximum_header_count = 0; +} + +void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ) +{ + *cur_used = heap.total_used; + *cur_blocks = heap.header_count; +} +#endif /* MBEDTLS_MEMORY_DEBUG */ + +#if defined(MBEDTLS_THREADING_C) +static void *buffer_alloc_calloc_mutexed( size_t n, size_t size ) +{ + void *buf; + if( mbedtls_mutex_lock( &heap.mutex ) != 0 ) + return( NULL ); + buf = buffer_alloc_calloc( n, size ); + if( mbedtls_mutex_unlock( &heap.mutex ) ) + return( NULL ); + return( buf ); +} + +static void buffer_alloc_free_mutexed( void *ptr ) +{ + /* We have to good option here, but corrupting the heap seems + * worse than loosing memory. */ + if( mbedtls_mutex_lock( &heap.mutex ) ) + return; + buffer_alloc_free( ptr ); + (void) mbedtls_mutex_unlock( &heap.mutex ); +} +#endif /* MBEDTLS_THREADING_C */ + +void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ) +{ + memset( &heap, 0, sizeof( buffer_alloc_ctx ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &heap.mutex ); + mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed, + buffer_alloc_free_mutexed ); +#else + mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free ); +#endif + + if( len < sizeof( memory_header ) + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + return; + else if( (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + /* Adjust len first since buf is used in the computation */ + len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE + - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE + - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + } + + memset( buf, 0, len ); + + heap.buf = buf; + heap.len = len; + + heap.first = (memory_header *)buf; + heap.first->size = len - sizeof( memory_header ); + heap.first->magic1 = MAGIC1; + heap.first->magic2 = MAGIC2; + heap.first_free = heap.first; +} + +void mbedtls_memory_buffer_alloc_free( void ) +{ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &heap.mutex ); +#endif + mbedtls_platform_zeroize( &heap, sizeof(buffer_alloc_ctx) ); +} + +#if defined(MBEDTLS_SELF_TEST) +static int check_pointer( void *p ) +{ + if( p == NULL ) + return( -1 ); + + if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 ) + return( -1 ); + + return( 0 ); +} + +static int check_all_free( void ) +{ + if( +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.total_used != 0 || +#endif + heap.first != heap.first_free || + (void *) heap.first != (void *) heap.buf ) + { + return( -1 ); + } + + return( 0 ); +} + +#define TEST_ASSERT( condition ) \ + if( ! (condition) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + \ + ret = 1; \ + goto cleanup; \ + } + +int mbedtls_memory_buffer_alloc_self_test( int verbose ) +{ + unsigned char buf[1024]; + unsigned char *p, *q, *r, *end; + int ret = 0; + + if( verbose != 0 ) + mbedtls_printf( " MBA test #1 (basic alloc-free cycle): " ); + + mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); + + p = mbedtls_calloc( 1, 1 ); + q = mbedtls_calloc( 1, 128 ); + r = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && + check_pointer( q ) == 0 && + check_pointer( r ) == 0 ); + + mbedtls_free( r ); + mbedtls_free( q ); + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + /* Memorize end to compare with the next test */ + end = heap.buf + heap.len; + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MBA test #2 (buf not aligned): " ); + + mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 ); + + TEST_ASSERT( heap.buf + heap.len == end ); + + p = mbedtls_calloc( 1, 1 ); + q = mbedtls_calloc( 1, 128 ); + r = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && + check_pointer( q ) == 0 && + check_pointer( r ) == 0 ); + + mbedtls_free( r ); + mbedtls_free( q ); + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MBA test #3 (full): " ); + + mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); + + p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) ); + + TEST_ASSERT( check_pointer( p ) == 0 ); + TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); + + mbedtls_free( p ); + + p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 ); + q = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 ); + TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); + + mbedtls_free( q ); + + TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL ); + + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + mbedtls_memory_buffer_alloc_free( ); + + return( ret ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ diff --git a/external/mbedtls/library/net_sockets.c b/external/mbedtls/library/net_sockets.c new file mode 100644 index 0000000..671115f --- /dev/null +++ b/external/mbedtls/library/net_sockets.c @@ -0,0 +1,712 @@ +/* + * TCP/IP or UDP/IP networking functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must + * be set before config.h, which pulls in glibc's features.h indirectly. + * Harmless on other platforms. */ +#define _POSIX_C_SOURCE 200112L + +#if defined(__NetBSD__) +#define _XOPEN_SOURCE 600 /* sockaddr_storage */ +#endif + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_NET_C) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) +#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#endif + +#include "mbedtls/net_sockets.h" + +#include + +#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ + !defined(EFI32) + +#define IS_EINTR( ret ) ( ( ret ) == WSAEINTR ) + +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501) +#undef _WIN32_WINNT +/* Enables getaddrinfo() & Co */ +#define _WIN32_WINNT 0x0501 +#endif + +#include + +#include +#include + +#if defined(_MSC_VER) +#if defined(_WIN32_WCE) +#pragma comment( lib, "ws2.lib" ) +#else +#pragma comment( lib, "ws2_32.lib" ) +#endif +#endif /* _MSC_VER */ + +#define read(fd,buf,len) recv( fd, (char*)( buf ), (int)( len ), 0 ) +#define write(fd,buf,len) send( fd, (char*)( buf ), (int)( len ), 0 ) +#define close(fd) closesocket(fd) + +static int wsa_init_done = 0; + +#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IS_EINTR( ret ) ( ( ret ) == EINTR ) + +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* Some MS functions want int and MSVC warns if we pass size_t, + * but the standard functions use socklen_t, so cast only for MSVC */ +#if defined(_MSC_VER) +#define MSVC_INT_CAST (int) +#else +#define MSVC_INT_CAST +#endif + +#include + +#include + +#include + +/* + * Prepare for using the sockets interface + */ +static int net_prepare( void ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + WSADATA wsaData; + + if( wsa_init_done == 0 ) + { + if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 ) + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + + wsa_init_done = 1; + } +#else +#if !defined(EFIX64) && !defined(EFI32) + signal( SIGPIPE, SIG_IGN ); +#endif +#endif + return( 0 ); +} + +/* + * Initialize a context + */ +void mbedtls_net_init( mbedtls_net_context *ctx ) +{ + ctx->fd = -1; +} + +/* + * Initiate a TCP connection with host:port and the given protocol + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, + const char *port, int proto ) +{ + int ret; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Do name resolution with both IPv6 and IPv4 */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + + if( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a connection succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 ) + { + ret = 0; + break; + } + + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_CONNECT_FAILED; + } + + freeaddrinfo( addr_list ); + + return( ret ); +} + +/* + * Create a listening socket on bind_ip:port + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) +{ + int n, ret; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + if( bind_ip == NULL ) + hints.ai_flags = AI_PASSIVE; + + if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a binding succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + n = 1; + if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_BIND_FAILED; + continue; + } + + /* Listen only makes sense for TCP */ + if( proto == MBEDTLS_NET_PROTO_TCP ) + { + if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_LISTEN_FAILED; + continue; + } + } + + /* Bind was successful */ + ret = 0; + break; + } + + freeaddrinfo( addr_list ); + + return( ret ); + +} + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + ((void) ctx); + return( WSAGetLastError() == WSAEWOULDBLOCK ); +} +#else +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + * + * Note: on a blocking socket this function always returns 0! + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + int err = errno; + + /* + * Never return 'WOULD BLOCK' on a blocking socket + */ + if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK ) + { + errno = err; + return( 0 ); + } + + switch( errno = err ) + { +#if defined EAGAIN + case EAGAIN: +#endif +#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + return( 1 ); + } + return( 0 ); +} +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* + * Accept a connection from a remote client + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ) +{ + int ret; + int type; + + struct sockaddr_storage client_addr; + +#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ + defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) || \ + ( defined(__NetBSD__) && defined(socklen_t) ) + socklen_t n = (socklen_t) sizeof( client_addr ); + socklen_t type_len = (socklen_t) sizeof( type ); +#else + int n = (int) sizeof( client_addr ); + int type_len = (int) sizeof( type ); +#endif + + /* Is this a TCP or UDP socket? */ + if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, + (void *) &type, &type_len ) != 0 || + ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) + { + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + if( type == SOCK_STREAM ) + { + /* TCP: actual accept() */ + ret = client_ctx->fd = (int) accept( bind_ctx->fd, + (struct sockaddr *) &client_addr, &n ); + } + else + { + /* UDP: wait for a message, but keep it in the queue */ + char buf[1] = { 0 }; + + ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, + (struct sockaddr *) &client_addr, &n ); + +#if defined(_WIN32) + if( ret == SOCKET_ERROR && + WSAGetLastError() == WSAEMSGSIZE ) + { + /* We know buf is too small, thanks, just peeking here */ + ret = 0; + } +#endif + } + + if( ret < 0 ) + { + if( net_would_block( bind_ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + /* UDP: hijack the listening socket to communicate with the client, + * then bind a new socket to accept new connections */ + if( type != SOCK_STREAM ) + { + struct sockaddr_storage local_addr; + int one = 1; + + if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + + client_ctx->fd = bind_ctx->fd; + bind_ctx->fd = -1; /* In case we exit early */ + + n = sizeof( struct sockaddr_storage ); + if( getsockname( client_ctx->fd, + (struct sockaddr *) &local_addr, &n ) != 0 || + ( bind_ctx->fd = (int) socket( local_addr.ss_family, + SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || + setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &one, sizeof( one ) ) != 0 ) + { + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + } + + if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) + { + return( MBEDTLS_ERR_NET_BIND_FAILED ); + } + } + + if( client_ip != NULL ) + { + if( client_addr.ss_family == AF_INET ) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; + *ip_len = sizeof( addr4->sin_addr.s_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); + } + else + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; + *ip_len = sizeof( addr6->sin6_addr.s6_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len); + } + } + + return( 0 ); +} + +/* + * Set the socket blocking or non-blocking + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 0; + return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); +#else + return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) ); +#endif +} + +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 1; + return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); +#else + return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) ); +#endif +} + +/* + * Check if data is available on the socket + */ + +int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ) +{ + int ret; + struct timeval tv; + + fd_set read_fds; + fd_set write_fds; + + int fd = ctx->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + /* A limitation of select() is that it only works with file descriptors + * that are strictly less than FD_SETSIZE. This is a limitation of the + * fd_set type. Error out early, because attempting to call FD_SET on a + * large file descriptor is a buffer overflow on typical platforms. */ + if( fd >= FD_SETSIZE ) + return( MBEDTLS_ERR_NET_POLL_FAILED ); + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + /* Ensure that memory sanitizers consider read_fds and write_fds as + * initialized even on platforms such as Glibc/x86_64 where FD_ZERO + * is implemented in assembly. */ + memset( &read_fds, 0, sizeof( read_fds ) ); + memset( &write_fds, 0, sizeof( write_fds ) ); +#endif +#endif + + FD_ZERO( &read_fds ); + if( rw & MBEDTLS_NET_POLL_READ ) + { + rw &= ~MBEDTLS_NET_POLL_READ; + FD_SET( fd, &read_fds ); + } + + FD_ZERO( &write_fds ); + if( rw & MBEDTLS_NET_POLL_WRITE ) + { + rw &= ~MBEDTLS_NET_POLL_WRITE; + FD_SET( fd, &write_fds ); + } + + if( rw != 0 ) + return( MBEDTLS_ERR_NET_BAD_INPUT_DATA ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + do + { + ret = select( fd + 1, &read_fds, &write_fds, NULL, + timeout == (uint32_t) -1 ? NULL : &tv ); + } + while( IS_EINTR( ret ) ); + + if( ret < 0 ) + return( MBEDTLS_ERR_NET_POLL_FAILED ); + + ret = 0; + if( FD_ISSET( fd, &read_fds ) ) + ret |= MBEDTLS_NET_POLL_READ; + if( FD_ISSET( fd, &write_fds ) ) + ret |= MBEDTLS_NET_POLL_WRITE; + + return( ret ); +} + +/* + * Portable usleep helper + */ +void mbedtls_net_usleep( unsigned long usec ) +{ +#if defined(_WIN32) + Sleep( ( usec + 999 ) / 1000 ); +#else + struct timeval tv; + tv.tv_sec = usec / 1000000; +#if defined(__unix__) || defined(__unix) || \ + ( defined(__APPLE__) && defined(__MACH__) ) + tv.tv_usec = (suseconds_t) usec % 1000000; +#else + tv.tv_usec = usec % 1000000; +#endif + select( 0, NULL, NULL, NULL, &tv ); +#endif +} + +/* + * Read at most 'len' characters + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) +{ + int ret; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + ret = (int) read( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + return( ret ); +} + +/* + * Read at most 'len' characters, blocking for at most 'timeout' ms + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, + size_t len, uint32_t timeout ) +{ + int ret; + struct timeval tv; + fd_set read_fds; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + /* A limitation of select() is that it only works with file descriptors + * that are strictly less than FD_SETSIZE. This is a limitation of the + * fd_set type. Error out early, because attempting to call FD_SET on a + * large file descriptor is a buffer overflow on typical platforms. */ + if( fd >= FD_SETSIZE ) + return( MBEDTLS_ERR_NET_POLL_FAILED ); + + FD_ZERO( &read_fds ); + FD_SET( fd, &read_fds ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); + + /* Zero fds ready means we timed out */ + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_TIMEOUT ); + + if( ret < 0 ) + { +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAEINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#else + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + /* This call will not block */ + return( mbedtls_net_recv( ctx, buf, len ) ); +} + +/* + * Write at most 'len' characters + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) +{ + int ret; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + ret = (int) write( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_WRITE ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_WRITE ); +#endif + + return( MBEDTLS_ERR_NET_SEND_FAILED ); + } + + return( ret ); +} + +/* + * Gracefully close the connection + */ +void mbedtls_net_free( mbedtls_net_context *ctx ) +{ + if( ctx->fd == -1 ) + return; + + shutdown( ctx->fd, 2 ); + close( ctx->fd ); + + ctx->fd = -1; +} + +#endif /* MBEDTLS_NET_C */ diff --git a/external/mbedtls/library/nist_kw.c b/external/mbedtls/library/nist_kw.c new file mode 100644 index 0000000..8341ff1 --- /dev/null +++ b/external/mbedtls/library/nist_kw.c @@ -0,0 +1,780 @@ +/* + * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes + * only + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * Definition of Key Wrapping: + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm" + * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm" + * + * Note: RFC 3394 defines different methodology for intermediate operations for + * the wrapping and unwrapping operation than the definition in NIST SP 800-38F. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_NIST_KW_C) + +#include "mbedtls/nist_kw.h" +#include "mbedtls/platform_util.h" + +#include +#include + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_NIST_KW_ALT) + +#define KW_SEMIBLOCK_LENGTH 8 +#define MIN_SEMIBLOCKS_COUNT 3 + +/* constant-time buffer comparison */ +static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } + + return( diff ); +} + +/*! The 64-bit default integrity check value (ICV) for KW mode. */ +static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}; +/*! The 32-bit default integrity check value (ICV) for KWP mode. */ +static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6}; + +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} while( 0 ) +#endif + +/* + * Initialize context + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) ); +} + +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, + keybits, + MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* + * SP 800-38F currently defines AES cipher as the only block cipher allowed: + * "For KW and KWP, the underlying block cipher shall be approved, and the + * block size shall be 128 bits. Currently, the AES block cipher, with key + * lengths of 128, 192, or 256 bits, is the only block cipher that fits + * this profile." + * Currently we don't support other 128 bit block ciphers for key wrapping, + * such as Camellia and Aria. + */ + if( cipher != MBEDTLS_CIPHER_ID_AES ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + is_wrap ? MBEDTLS_ENCRYPT : + MBEDTLS_DECRYPT ) + ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ) +{ + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) ); +} + +/* + * Helper function for Xoring the uint64_t "t" with the encrypted A. + * Defined in NIST SP 800-38F section 6.1 + */ +static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t ) +{ + size_t i = 0; + for( i = 0; i < sizeof( t ); i++ ) + { + A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff; + } +} + +/* + * KW-AE as defined in SP 800-38F section 6.2 + * KWP-AE as defined in SP 800-38F section 6.3 + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, + mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t *out_len, size_t out_size ) +{ + int ret = 0; + size_t semiblocks = 0; + size_t s; + size_t olen, padlen = 0; + uint64_t t = 0; + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; + unsigned char *A = output; + + *out_len = 0; + /* + * Generate the String to work on + */ + if( mode == MBEDTLS_KW_MODE_KW ) + { + if( out_size < in_len + KW_SEMIBLOCK_LENGTH ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* + * According to SP 800-38F Table 1, the plaintext length for KW + * must be between 2 to 2^54-1 semiblocks inclusive. + */ + if( in_len < 16 || +#if SIZE_MAX > 0x1FFFFFFFFFFFFF8 + in_len > 0x1FFFFFFFFFFFFF8 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH ); + memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len ); + } + else + { + if( in_len % 8 != 0 ) + { + padlen = ( 8 - ( in_len % 8 ) ); + } + + if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* + * According to SP 800-38F Table 1, the plaintext length for KWP + * must be between 1 and 2^32-1 octets inclusive. + */ + if( in_len < 1 +#if SIZE_MAX > 0xFFFFFFFF + || in_len > 0xFFFFFFFF +#endif + ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 ); + PUT_UINT32_BE( ( in_len & 0xffffffff ), output, + KW_SEMIBLOCK_LENGTH / 2 ); + + memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len ); + memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen ); + } + semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1; + + s = 6 * ( semiblocks - 1 ); + + if( mode == MBEDTLS_KW_MODE_KWP + && in_len <= KW_SEMIBLOCK_LENGTH ) + { + memcpy( inbuff, output, 16 ); + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, output, &olen ); + if( ret != 0 ) + goto cleanup; + } + else + { + /* + * Do the wrapping function W, as defined in RFC 3394 section 2.2.1 + */ + if( semiblocks < MIN_SEMIBLOCKS_COUNT ) + { + ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + goto cleanup; + } + + /* Calculate intermediate values */ + for( t = 1; t <= s; t++ ) + { + memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); + memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH ); + + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + calc_a_xor_t( A, t ); + + memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + R2 += KW_SEMIBLOCK_LENGTH; + if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) ) + R2 = output + KW_SEMIBLOCK_LENGTH; + } + } + + *out_len = semiblocks * KW_SEMIBLOCK_LENGTH; + +cleanup: + + if( ret != 0) + { + memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH ); + } + mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 ); + mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 ); + + return( ret ); +} + +/* + * W-1 function as defined in RFC 3394 section 2.2.2 + * This function assumes the following: + * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH. + * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH. + * 3. Minimal number of semiblocks is 3. + * 4. A is a buffer to hold the first semiblock of the input buffer. + */ +static int unwrap( mbedtls_nist_kw_context *ctx, + const unsigned char *input, size_t semiblocks, + unsigned char A[KW_SEMIBLOCK_LENGTH], + unsigned char *output, size_t* out_len ) +{ + int ret = 0; + const size_t s = 6 * ( semiblocks - 1 ); + size_t olen; + uint64_t t = 0; + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; + *out_len = 0; + + if( semiblocks < MIN_SEMIBLOCKS_COUNT ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( A, input, KW_SEMIBLOCK_LENGTH ); + memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); + + /* Calculate intermediate values */ + for( t = s; t >= 1; t-- ) + { + calc_a_xor_t( A, t ); + + memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); + memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH ); + + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + + /* Set R as LSB64 of outbuff */ + memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + + if( R == output ) + R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; + else + R -= KW_SEMIBLOCK_LENGTH; + } + + *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH; + +cleanup: + if( ret != 0) + memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); + mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) ); + mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); + + return( ret ); +} + +/* + * KW-AD as defined in SP 800-38F section 6.2 + * KWP-AD as defined in SP 800-38F section 6.3 + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, + mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t *out_len, size_t out_size ) +{ + int ret = 0; + size_t i, olen; + unsigned char A[KW_SEMIBLOCK_LENGTH]; + unsigned char diff, bad_padding = 0; + + *out_len = 0; + if( out_size < in_len - KW_SEMIBLOCK_LENGTH ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( mode == MBEDTLS_KW_MODE_KW ) + { + /* + * According to SP 800-38F Table 1, the ciphertext length for KW + * must be between 3 to 2^54 semiblocks inclusive. + */ + if( in_len < 24 || +#if SIZE_MAX > 0x200000000000000 + in_len > 0x200000000000000 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, + A, output, out_len ); + if( ret != 0 ) + goto cleanup; + + /* Check ICV in "constant-time" */ + diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH ); + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + goto cleanup; + } + + } + else if( mode == MBEDTLS_KW_MODE_KWP ) + { + size_t padlen = 0; + uint32_t Plen; + /* + * According to SP 800-38F Table 1, the ciphertext length for KWP + * must be between 2 to 2^29 semiblocks inclusive. + */ + if( in_len < KW_SEMIBLOCK_LENGTH * 2 || +#if SIZE_MAX > 0x100000000 + in_len > 0x100000000 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( in_len == KW_SEMIBLOCK_LENGTH * 2 ) + { + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + input, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); + *out_len = KW_SEMIBLOCK_LENGTH; + } + else + { + /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ + ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, + A, output, out_len ); + if( ret != 0 ) + goto cleanup; + } + + /* Check ICV in "constant-time" */ + diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 ); + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 ); + + /* + * Plen is the length of the plaintext, when the input is valid. + * If Plen is larger than the plaintext and padding, padlen will be + * larger than 8, because of the type wrap around. + */ + padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; + if ( padlen > 7 ) + { + padlen &= 7; + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + /* Check padding in "constant-time" */ + for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ ) + { + if( i >= KW_SEMIBLOCK_LENGTH - padlen ) + diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; + else + bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; + } + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + if( ret != 0 ) + { + goto cleanup; + } + memset( output + Plen, 0, padlen ); + *out_len = Plen; + } + else + { + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto cleanup; + } + +cleanup: + if( ret != 0 ) + { + memset( output, 0, *out_len ); + *out_len = 0; + } + + mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) ); + mbedtls_platform_zeroize( &diff, sizeof( diff ) ); + mbedtls_platform_zeroize( A, sizeof( A ) ); + + return( ret ); +} + +#endif /* !MBEDTLS_NIST_KW_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) + +#define KW_TESTS 3 + +/* + * Test vectors taken from NIST + * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW + */ +static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 }; + +static const unsigned char kw_key[KW_TESTS][32] = { + { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, + 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, + { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, + 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, + 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, + { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25, + 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, + 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, + 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } +}; + +static const unsigned char kw_msg[KW_TESTS][40] = { + { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, + 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, + { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, + 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, + 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, + 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d, + 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c }, + { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, + 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, + 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } +}; + +static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 }; +static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 }; +static const unsigned char kw_res[KW_TESTS][48] = { + { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, + 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, + 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, + { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, + 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, + 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, + 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8, + 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19, + 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d }, + { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d, + 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, + 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, + 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } +}; + +static const unsigned char kwp_key[KW_TESTS][32] = { + { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, + 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, + { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, + 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, + 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, + { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5, + 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, + 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, + 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } +}; + +static const unsigned char kwp_msg[KW_TESTS][31] = { + { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, + 0x96 }, + { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, + 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, + 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, + 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, + { 0xd1 } +}; +static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 }; + +static const unsigned char kwp_res[KW_TESTS][48] = { + { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, + 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, + 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, + { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, + 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, + 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, + 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90, + 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, + { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, + 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } +}; +static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 }; + +int mbedtls_nist_kw_self_test( int verbose ) +{ + mbedtls_nist_kw_context ctx; + unsigned char out[48]; + size_t olen; + int i; + int ret = 0; + mbedtls_nist_kw_init( &ctx ); + + for( i = 0; i < KW_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 ); + + ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 1 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KW: setup failed " ); + + goto end; + } + + ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], + kw_msg_len[i], out, &olen, sizeof( out ) ); + if( ret != 0 || kw_out_len[i] != olen || + memcmp( out, kw_res[i], kw_out_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 0 ) ) + != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KW: setup failed "); + + goto end; + } + + ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW, + out, olen, out, &olen, sizeof( out ) ); + + if( ret != 0 || olen != kw_msg_len[i] || + memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto end; + } + + if( verbose != 0 ) + mbedtls_printf( " passed\n" ); + } + + for( i = 0; i < KW_TESTS; i++ ) + { + olen = sizeof( out ); + if( verbose != 0 ) + mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 ); + + ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], + key_len[i] * 8, 1 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KWP: setup failed " ); + + goto end; + } + ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], + kwp_msg_len[i], out, &olen, sizeof( out ) ); + + if( ret != 0 || kwp_out_len[i] != olen || + memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kwp_key[i], key_len[i] * 8, 0 ) ) + != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KWP: setup failed "); + + goto end; + } + + ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out, + olen, out, &olen, sizeof( out ) ); + + if( ret != 0 || olen != kwp_msg_len[i] || + memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( verbose != 0 ) + mbedtls_printf( " passed\n" ); + } +end: + mbedtls_nist_kw_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_NIST_KW_C */ diff --git a/external/mbedtls/library/oid.c b/external/mbedtls/library/oid.c new file mode 100644 index 0000000..2414083 --- /dev/null +++ b/external/mbedtls/library/oid.c @@ -0,0 +1,783 @@ +/** + * \file oid.c + * + * \brief Object Identifier (OID) database + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_OID_C) + +#include "mbedtls/oid.h" +#include "mbedtls/rsa.h" + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "mbedtls/x509.h" +#endif + +/* + * Macro to automatically add the size of #define'd OIDs + */ +#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) + +/* + * Macro to generate an internal function for oid_XXX_from_asn1() (used by + * the other functions) + */ +#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ + static const TYPE_T * oid_ ## NAME ## _from_asn1( \ + const mbedtls_asn1_buf *oid ) \ + { \ + const TYPE_T *p = (LIST); \ + const mbedtls_oid_descriptor_t *cur = \ + (const mbedtls_oid_descriptor_t *) p; \ + if( p == NULL || oid == NULL ) return( NULL ); \ + while( cur->asn1 != NULL ) { \ + if( cur->asn1_len == oid->len && \ + memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ + return( p ); \ + } \ + p++; \ + cur = (const mbedtls_oid_descriptor_t *) p; \ + } \ + return( NULL ); \ + } + +/* + * Macro to generate a function for retrieving a single attribute from the + * descriptor of an mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->descriptor.ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving two attributes from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, \ + ATTR2_TYPE * ATTR2 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *(ATTR1) = data->ATTR1; \ + *(ATTR2) = data->ATTR2; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on a single + * attribute from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ +int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ +{ \ + const TYPE_T *cur = (LIST); \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == (ATTR1) ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on two + * attributes from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ + size_t *olen ) \ +{ \ + const TYPE_T *cur = (LIST); \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2) ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +/* + * For X520 attribute types + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + const char *short_name; +} oid_x520_attr_t; + +static const oid_x520_attr_t oid_x520_attr_type[] = +{ + { + { ADD_LEN( MBEDTLS_OID_AT_CN ), "id-at-commonName", "Common Name" }, + "CN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_COUNTRY ), "id-at-countryName", "Country" }, + "C", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_LOCALITY ), "id-at-locality", "Locality" }, + "L", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_STATE ), "id-at-state", "State" }, + "ST", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" }, + "O", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" }, + "OU", + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" }, + "emailAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" }, + "serialNumber", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" }, + "postalAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" }, + "postalCode", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SUR_NAME ), "id-at-surName", "Surname" }, + "SN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" }, + "GN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_INITIALS ), "id-at-initials", "Initials" }, + "initials", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" }, + "generationQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_TITLE ), "id-at-title", "Title" }, + "title", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" }, + "dnQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" }, + "pseudonym", + }, + { + { ADD_LEN( MBEDTLS_OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" }, + "DC", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier", "Unique Identifier" }, + "uniqueIdentifier", + }, + { + { NULL, 0, NULL, NULL }, + NULL, + } +}; + +FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) +FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) + +/* + * For X509 extensions + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + int ext_type; +} oid_x509_ext_t; + +static const oid_x509_ext_t oid_x509_ext[] = +{ + { + { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, + MBEDTLS_X509_EXT_BASIC_CONSTRAINTS, + }, + { + { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, + MBEDTLS_X509_EXT_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" }, + MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, + MBEDTLS_X509_EXT_SUBJECT_ALT_NAME, + }, + { + { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, + MBEDTLS_X509_EXT_NS_CERT_TYPE, + }, + { + { NULL, 0, NULL, NULL }, + 0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) +FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) + +static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = +{ + { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" }, + { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" }, + { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" }, + { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" }, + { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" }, + { ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" }, + { NULL, 0, NULL, NULL }, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) +FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) +#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ + +#if defined(MBEDTLS_MD_C) +/* + * For SignatureAlgorithmIdentifier + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; +} oid_sig_alg_t; + +static const oid_sig_alg_t oid_sig_alg[] = +{ +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" }, + MBEDTLS_MD_MD2, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" }, + MBEDTLS_MD_MD4, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" }, + MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_RSA_C) + { + { ADD_LEN( MBEDTLS_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" }, + MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, + }, +#endif /* MBEDTLS_RSA_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) +FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) +FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) +#endif /* MBEDTLS_MD_C */ + +/* + * For PublicKeyInfo (PKCS1, RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_pk_type_t pk_alg; +} oid_pk_alg_t; + +static const oid_pk_alg_t oid_pk_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS1_RSA ), "rsaEncryption", "RSA" }, + MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" }, + MBEDTLS_PK_ECKEY, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" }, + MBEDTLS_PK_ECKEY_DH, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) + +#if defined(MBEDTLS_ECP_C) +/* + * For namedCurve (RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_ecp_group_id grp_id; +} oid_ecp_grp_t; + +static const oid_ecp_grp_t oid_ecp_grp[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" }, + MBEDTLS_ECP_DP_SECP192R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" }, + MBEDTLS_ECP_DP_SECP224R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" }, + MBEDTLS_ECP_DP_SECP256R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" }, + MBEDTLS_ECP_DP_SECP384R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, + MBEDTLS_ECP_DP_SECP521R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, + MBEDTLS_ECP_DP_SECP192K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, + MBEDTLS_ECP_DP_SECP224K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, + MBEDTLS_ECP_DP_SECP256K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, + MBEDTLS_ECP_DP_BP256R1, + }, +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" }, + MBEDTLS_ECP_DP_BP384R1, + }, +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" }, + MBEDTLS_ECP_DP_BP512R1, + }, +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_ECP_DP_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) +FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_CIPHER_C) +/* + * For PKCS#5 PBES2 encryption algorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_cipher_type_t cipher_alg; +} oid_cipher_alg_t; + +static const oid_cipher_alg_t oid_cipher_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_DES_CBC ), "desCBC", "DES-CBC" }, + MBEDTLS_CIPHER_DES_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" }, + MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_MD_C) +/* + * For digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; +} oid_md_alg_t; + +static const oid_md_alg_t oid_md_alg[] = +{ +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" }, + MBEDTLS_MD_MD2, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" }, + MBEDTLS_MD_MD4, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" }, + MBEDTLS_MD_MD5, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) + +/* + * For HMAC digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_hmac; +} oid_md_hmac_t; + +static const oid_md_hmac_t oid_md_hmac[] = +{ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA1 ), "hmacSHA1", "HMAC-SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA224 ), "hmacSHA224", "HMAC-SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA256 ), "hmacSHA256", "HMAC-SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA384 ), "hmacSHA384", "HMAC-SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA512 ), "hmacSHA512", "HMAC-SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PKCS12_C) +/* + * For PKCS#12 PBEs + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_cipher_type_t cipher_alg; +} oid_pkcs12_pbe_alg_t; + +static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) +FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_PKCS12_C */ + +#define OID_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +/* Return the x.y.z.... style numeric string for the given OID */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, + const mbedtls_asn1_buf *oid ) +{ + int ret; + size_t i, n; + unsigned int value; + char *p; + + p = buf; + n = size; + + /* First byte contains first two dots */ + if( oid->len > 0 ) + { + ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 ); + OID_SAFE_SNPRINTF; + } + + value = 0; + for( i = 1; i < oid->len; i++ ) + { + /* Prevent overflow in value. */ + if( ( ( value << 7 ) >> 7 ) != value ) + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); + + value <<= 7; + value += oid->p[i] & 0x7F; + + if( !( oid->p[i] & 0x80 ) ) + { + /* Last byte */ + ret = mbedtls_snprintf( p, n, ".%d", value ); + OID_SAFE_SNPRINTF; + value = 0; + } + } + + return( (int) ( size - n ) ); +} + +#endif /* MBEDTLS_OID_C */ diff --git a/external/mbedtls/library/padlock.c b/external/mbedtls/library/padlock.c new file mode 100644 index 0000000..afb7e0a --- /dev/null +++ b/external/mbedtls/library/padlock.c @@ -0,0 +1,195 @@ +/* + * VIA PadLock support functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * This implementation is based on the VIA PadLock Programming Guide: + * + * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ + * programming_guide.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PADLOCK_C) + +#include "mbedtls/padlock.h" + +#include + +#ifndef asm +#define asm __asm +#endif + +#if defined(MBEDTLS_HAVE_X86) + +/* + * PadLock detection routine + */ +int mbedtls_padlock_has_support( int feature ) +{ + static int flags = -1; + int ebx = 0, edx = 0; + + if( flags == -1 ) + { + asm( "movl %%ebx, %0 \n\t" + "movl $0xC0000000, %%eax \n\t" + "cpuid \n\t" + "cmpl $0xC0000001, %%eax \n\t" + "movl $0, %%edx \n\t" + "jb unsupported \n\t" + "movl $0xC0000001, %%eax \n\t" + "cpuid \n\t" + "unsupported: \n\t" + "movl %%edx, %1 \n\t" + "movl %2, %%ebx \n\t" + : "=m" (ebx), "=m" (edx) + : "m" (ebx) + : "eax", "ecx", "edx" ); + + flags = edx; + } + + return( flags & feature ); +} + +/* + * PadLock AES-ECB block en(de)cryption + */ +int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int ebx = 0; + uint32_t *rk; + uint32_t *blk; + uint32_t *ctrl; + unsigned char buf[256]; + + rk = ctx->rk; + blk = MBEDTLS_PADLOCK_ALIGN16( buf ); + memcpy( blk, input, 16 ); + + ctrl = blk + 4; + *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 ); + + asm( "pushfl \n\t" + "popfl \n\t" + "movl %%ebx, %0 \n\t" + "movl $1, %%ecx \n\t" + "movl %2, %%edx \n\t" + "movl %3, %%ebx \n\t" + "movl %4, %%esi \n\t" + "movl %4, %%edi \n\t" + ".byte 0xf3,0x0f,0xa7,0xc8 \n\t" + "movl %1, %%ebx \n\t" + : "=m" (ebx) + : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk) + : "memory", "ecx", "edx", "esi", "edi" ); + + memcpy( output, blk, 16 ); + + return( 0 ); +} + +/* + * PadLock AES-CBC buffer en(de)cryption + */ +int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ebx = 0; + size_t count; + uint32_t *rk; + uint32_t *iw; + uint32_t *ctrl; + unsigned char buf[256]; + + if( ( (long) input & 15 ) != 0 || + ( (long) output & 15 ) != 0 ) + return( MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED ); + + rk = ctx->rk; + iw = MBEDTLS_PADLOCK_ALIGN16( buf ); + memcpy( iw, iv, 16 ); + + ctrl = iw + 4; + *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode ^ 1 ) - 10 ) << 9 ); + + count = ( length + 15 ) >> 4; + + asm( "pushfl \n\t" + "popfl \n\t" + "movl %%ebx, %0 \n\t" + "movl %2, %%ecx \n\t" + "movl %3, %%edx \n\t" + "movl %4, %%ebx \n\t" + "movl %5, %%esi \n\t" + "movl %6, %%edi \n\t" + "movl %7, %%eax \n\t" + ".byte 0xf3,0x0f,0xa7,0xd0 \n\t" + "movl %1, %%ebx \n\t" + : "=m" (ebx) + : "m" (ebx), "m" (count), "m" (ctrl), + "m" (rk), "m" (input), "m" (output), "m" (iw) + : "memory", "eax", "ecx", "edx", "esi", "edi" ); + + memcpy( iv, iw, 16 ); + + return( 0 ); +} + +#endif /* MBEDTLS_HAVE_X86 */ + +#endif /* MBEDTLS_PADLOCK_C */ diff --git a/external/mbedtls/library/pem.c b/external/mbedtls/library/pem.c new file mode 100644 index 0000000..50e663c --- /dev/null +++ b/external/mbedtls/library/pem.c @@ -0,0 +1,519 @@ +/* + * Privacy Enhanced Mail (PEM) decoding + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + +#include "mbedtls/pem.h" +#include "mbedtls/base64.h" +#include "mbedtls/des.h" +#include "mbedtls/aes.h" +#include "mbedtls/md5.h" +#include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +void mbedtls_pem_init( mbedtls_pem_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_pem_context ) ); +} + +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) +/* + * Read a 16-byte hex string and convert it to binary + */ +static int pem_get_iv( const unsigned char *s, unsigned char *iv, + size_t iv_len ) +{ + size_t i, j, k; + + memset( iv, 0, iv_len ); + + for( i = 0; i < iv_len * 2; i++, s++ ) + { + if( *s >= '0' && *s <= '9' ) j = *s - '0'; else + if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else + if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + k = ( ( i & 1 ) != 0 ) ? j : j << 4; + + iv[i >> 1] = (unsigned char)( iv[i >> 1] | k ); + } + + return( 0 ); +} + +static int pem_pbkdf1( unsigned char *key, size_t keylen, + unsigned char *iv, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_md5_context md5_ctx; + unsigned char md5sum[16]; + size_t use_len; + int ret; + + mbedtls_md5_init( &md5_ctx ); + + /* + * key[ 0..15] = MD5(pwd || IV) + */ + if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + if( keylen <= 16 ) + { + memcpy( key, md5sum, keylen ); + goto exit; + } + + memcpy( key, md5sum, 16 ); + + /* + * key[16..23] = MD5(key[ 0..15] || pwd || IV]) + */ + if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, md5sum, 16 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + use_len = 16; + if( keylen < 32 ) + use_len = keylen - 16; + + memcpy( key + 16, md5sum, use_len ); + +exit: + mbedtls_md5_free( &md5_ctx ); + mbedtls_platform_zeroize( md5sum, 16 ); + + return( ret ); +} + +#if defined(MBEDTLS_DES_C) +/* + * Decrypt with DES-CBC, using PBKDF1 for key derivation + */ +static int pem_des_decrypt( unsigned char des_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des_context des_ctx; + unsigned char des_key[8]; + int ret; + + mbedtls_des_init( &des_ctx ); + + if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 ) + goto exit; + ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, + des_iv, buf, buf ); + +exit: + mbedtls_des_free( &des_ctx ); + mbedtls_platform_zeroize( des_key, 8 ); + + return( ret ); +} + +/* + * Decrypt with 3DES-CBC, using PBKDF1 for key derivation + */ +static int pem_des3_decrypt( unsigned char des3_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des3_context des3_ctx; + unsigned char des3_key[24]; + int ret; + + mbedtls_des3_init( &des3_ctx ); + + if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 ) + goto exit; + ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, + des3_iv, buf, buf ); + +exit: + mbedtls_des3_free( &des3_ctx ); + mbedtls_platform_zeroize( des3_key, 24 ); + + return( ret ); +} +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* + * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation + */ +static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_aes_context aes_ctx; + unsigned char aes_key[32]; + int ret; + + mbedtls_aes_init( &aes_ctx ); + + if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 ) + goto exit; + ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, + aes_iv, buf, buf ); + +exit: + mbedtls_aes_free( &aes_ctx ); + mbedtls_platform_zeroize( aes_key, keylen ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, const unsigned char *pwd, + size_t pwdlen, size_t *use_len ) +{ + int ret, enc; + size_t len; + unsigned char *buf; + const unsigned char *s1, *s2, *end; +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + unsigned char pem_iv[16]; + mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + + if( ctx == NULL ) + return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ); + + s1 = (unsigned char *) strstr( (const char *) data, header ); + + if( s1 == NULL ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s2 = (unsigned char *) strstr( (const char *) data, footer ); + + if( s2 == NULL || s2 <= s1 ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s1 += strlen( header ); + if( *s1 == ' ' ) s1++; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + end = s2; + end += strlen( footer ); + if( *end == ' ' ) end++; + if( *end == '\r' ) end++; + if( *end == '\n' ) end++; + *use_len = end - data; + + enc = 0; + + if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + enc++; + + s1 += 22; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + +#if defined(MBEDTLS_DES_C) + if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; + + s1 += 23; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } + else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_CBC; + + s1 += 18; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) + { + if( s2 - s1 < 22 ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_128_CBC; + else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_192_CBC; + else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_256_CBC; + else + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + s1 += 22; + if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 32; + } +#endif /* MBEDTLS_AES_C */ + + if( enc_alg == MBEDTLS_CIPHER_NONE ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); +#else + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + if( s1 >= s2 ) + return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 ); + + if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) + return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); + + if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); + } + + if( enc != 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + if( pwd == NULL ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); + } + + ret = 0; + +#if defined(MBEDTLS_DES_C) + if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) + ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) + ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC ) + ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) + ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) + ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_AES_C */ + + if( ret != 0 ) + { + mbedtls_free( buf ); + return( ret ); + } + + /* + * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 + * length bytes (allow 4 to be sure) in all known use cases. + * + * Use that as a heuristic to try to detect password mismatches. + */ + if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); + } +#else + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + ctx->buf = buf; + ctx->buflen = len; + + return( 0 ); +} + +void mbedtls_pem_free( mbedtls_pem_context *ctx ) +{ + if ( ctx->buf != NULL ) + { + mbedtls_platform_zeroize( ctx->buf, ctx->buflen ); + mbedtls_free( ctx->buf ); + } + mbedtls_free( ctx->info ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) ); +} +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ) +{ + int ret; + unsigned char *encode_buf = NULL, *c, *p = buf; + size_t len = 0, use_len, add_len = 0; + + mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len ); + add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1; + + if( use_len + add_len > buf_len ) + { + *olen = use_len + add_len; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + if( use_len != 0 && + ( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data, + der_len ) ) != 0 ) + { + mbedtls_free( encode_buf ); + return( ret ); + } + + memcpy( p, header, strlen( header ) ); + p += strlen( header ); + c = encode_buf; + + while( use_len ) + { + len = ( use_len > 64 ) ? 64 : use_len; + memcpy( p, c, len ); + use_len -= len; + p += len; + c += len; + *p++ = '\n'; + } + + memcpy( p, footer, strlen( footer ) ); + p += strlen( footer ); + + *p++ = '\0'; + *olen = p - buf; + + /* Clean any remaining data previously written to the buffer */ + memset( buf + *olen, 0, buf_len - *olen ); + + mbedtls_free( encode_buf ); + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ + diff --git a/external/mbedtls/library/pk.c b/external/mbedtls/library/pk.c new file mode 100644 index 0000000..81cfdbf --- /dev/null +++ b/external/mbedtls/library/pk.c @@ -0,0 +1,571 @@ +/* + * Public Key abstraction layer + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#include "mbedtls/pk_internal.h" + +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#include +#include + +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * Initialise a mbedtls_pk_context + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ) +{ + PK_VALIDATE( ctx != NULL ); + + ctx->pk_info = NULL; + ctx->pk_ctx = NULL; +} + +/* + * Free (the components of) a mbedtls_pk_context + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ) +{ + if( ctx == NULL ) + return; + + if ( ctx->pk_info != NULL ) + ctx->pk_info->ctx_free_func( ctx->pk_ctx ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) ); +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ) +{ + PK_VALIDATE( ctx != NULL ); + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} + +/* + * Free the components of a restart context + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + ctx->pk_info->rs_free_func == NULL ) + { + return; + } + + ctx->pk_info->rs_free_func( ctx->rs_ctx ); + + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* + * Get pk_info structure from type + */ +const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) +{ + switch( pk_type ) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_PK_RSA: + return( &mbedtls_rsa_info ); +#endif +#if defined(MBEDTLS_ECP_C) + case MBEDTLS_PK_ECKEY: + return( &mbedtls_eckey_info ); + case MBEDTLS_PK_ECKEY_DH: + return( &mbedtls_eckeydh_info ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_PK_ECDSA: + return( &mbedtls_ecdsa_info ); +#endif + /* MBEDTLS_PK_RSA_ALT omitted on purpose */ + default: + return( NULL ); + } +} + +/* + * Initialise context + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) +{ + PK_VALIDATE_RET( ctx != NULL ); + if( info == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Initialize an RSA-alt context + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ) +{ + mbedtls_rsa_alt_context *rsa_alt; + const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; + + PK_VALIDATE_RET( ctx != NULL ); + if( ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; + + rsa_alt->key = key; + rsa_alt->decrypt_func = decrypt_func; + rsa_alt->sign_func = sign_func; + rsa_alt->key_len_func = key_len_func; + + return( 0 ); +} +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/* + * Tell if a PK can do the operations of the given type + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) +{ + /* A context with null pk_info is not set up yet and can't do anything. + * For backward compatibility, also accept NULL instead of a context + * pointer. */ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->can_do( type ) ); +} + +/* + * Helper for mbedtls_pk_sign and mbedtls_pk_verify + */ +static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len ) +{ + const mbedtls_md_info_t *md_info; + + if( *hash_len != 0 ) + return( 0 ); + + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( -1 ); + + *hash_len = mbedtls_md_get_size( md_info ); + return( 0 ); +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Helper to set up a restart context if needed + */ +static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx, + const mbedtls_pk_info_t *info ) +{ + /* Don't do anything if already set up or invalid */ + if( ctx == NULL || ctx->pk_info != NULL ) + return( 0 ); + + /* Should never happen when we're called */ + if( info->rs_alloc_func == NULL || info->rs_free_func == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* + * Verify a signature (restartable) + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->verify_rs_func != NULL ) + { + int ret; + + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); + + ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx, + md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx ); + + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); + + return( ret ); + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + if( ctx->pk_info->verify_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len ) ); +} + +/* + * Verify a signature + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len, + sig, sig_len, NULL ) ); +} + +/* + * Verify a signature with options + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ! mbedtls_pk_can_do( ctx, type ) ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + if( type == MBEDTLS_PK_RSASSA_PSS ) + { +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) + int ret; + const mbedtls_pk_rsassa_pss_options *pss_opts; + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( options == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; + + if( sig_len < mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ), + NULL, NULL, MBEDTLS_RSA_PUBLIC, + md_alg, (unsigned int) hash_len, hash, + pss_opts->mgf1_hash_id, + pss_opts->expected_salt_len, + sig ); + if( ret != 0 ) + return( ret ); + + if( sig_len > mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +#else + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ + } + + /* General case: no options */ + if( options != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); +} + +/* + * Make a signature (restartable) + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->sign_rs_func != NULL ) + { + int ret; + + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); + + ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg, + hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx ); + + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); + + return( ret ); + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + if( ctx->pk_info->sign_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng ) ); +} + +/* + * Make a signature + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng, NULL ) ); +} + +/* + * Decrypt message + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( input != NULL || ilen == 0 ); + PK_VALIDATE_RET( output != NULL || osize == 0 ); + PK_VALIDATE_RET( olen != NULL ); + + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->decrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Encrypt message + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( input != NULL || ilen == 0 ); + PK_VALIDATE_RET( output != NULL || osize == 0 ); + PK_VALIDATE_RET( olen != NULL ); + + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->encrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Check public-private key pair + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ) +{ + PK_VALIDATE_RET( pub != NULL ); + PK_VALIDATE_RET( prv != NULL ); + + if( pub->pk_info == NULL || + prv->pk_info == NULL || + prv->pk_info->check_pair_func == NULL ) + { + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + } + + if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) + { + if( pub->pk_info->type != MBEDTLS_PK_RSA ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + else + { + if( pub->pk_info != prv->pk_info ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + + return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) ); +} + +/* + * Get key size in bits + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) +{ + /* For backward compatibility, accept NULL or a context that + * isn't set up yet, and return a fake value that should be safe. */ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) ); +} + +/* + * Export debug information + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) +{ + PK_VALIDATE_RET( ctx != NULL ); + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->debug_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + ctx->pk_info->debug_func( ctx->pk_ctx, items ); + return( 0 ); +} + +/* + * Access the PK type name + */ +const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( "invalid PK" ); + + return( ctx->pk_info->name ); +} + +/* + * Access the PK type + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_PK_NONE ); + + return( ctx->pk_info->type ); +} + +#endif /* MBEDTLS_PK_C */ diff --git a/external/mbedtls/library/pk_wrap.c b/external/mbedtls/library/pk_wrap.c new file mode 100644 index 0000000..2c27552 --- /dev/null +++ b/external/mbedtls/library/pk_wrap.c @@ -0,0 +1,744 @@ +/* + * Public Key abstraction layer: wrapper functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk_internal.h" + +/* Even if RSA not activated, for the sake of RSA-alt */ +#include "mbedtls/rsa.h" + +#include + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +#include "mbedtls/platform_util.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include +#include + +#if defined(MBEDTLS_RSA_C) +static int rsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA || + type == MBEDTLS_PK_RSASSA_PSS ); +} + +static size_t rsa_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx; + return( 8 * mbedtls_rsa_get_len( rsa ) ); +} + +static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + size_t rsa_len = mbedtls_rsa_get_len( rsa ); + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( sig_len < rsa_len ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, NULL, NULL, + MBEDTLS_RSA_PUBLIC, md_alg, + (unsigned int) hash_len, hash, sig ) ) != 0 ) + return( ret ); + + /* The buffer contains a valid signature followed by extra data. + * We have a special error code for that so that so that callers can + * use mbedtls_pk_verify() to check "Does the buffer start with a + * valid signature?" and not just "Does the buffer contain a valid + * signature?". */ + if( sig_len > rsa_len ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +} + +static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = mbedtls_rsa_get_len( rsa ); + + return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + + if( ilen != mbedtls_rsa_get_len( rsa ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng, + MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); +} + +static int rsa_encrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + *olen = mbedtls_rsa_get_len( rsa ); + + if( *olen > osize ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC, + ilen, input, output ) ); +} + +static int rsa_check_pair_wrap( const void *pub, const void *prv ) +{ + return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub, + (const mbedtls_rsa_context *) prv ) ); +} + +static void *rsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) ); + + if( ctx != NULL ) + mbedtls_rsa_init( (mbedtls_rsa_context *) ctx, 0, 0 ); + + return( ctx ); +} + +static void rsa_free_wrap( void *ctx ) +{ + mbedtls_rsa_free( (mbedtls_rsa_context *) ctx ); + mbedtls_free( ctx ); +} + +static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.N"; + items->value = &( ((mbedtls_rsa_context *) ctx)->N ); + + items++; + + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.E"; + items->value = &( ((mbedtls_rsa_context *) ctx)->E ); +} + +const mbedtls_pk_info_t mbedtls_rsa_info = { + MBEDTLS_PK_RSA, + "RSA", + rsa_get_bitlen, + rsa_can_do, + rsa_verify_wrap, + rsa_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_decrypt_wrap, + rsa_encrypt_wrap, + rsa_check_pair_wrap, + rsa_alloc_wrap, + rsa_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_debug, +}; +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Generic EC key + */ +static int eckey_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH || + type == MBEDTLS_PK_ECDSA ); +} + +static size_t eckey_get_bitlen( const void *ctx ) +{ + return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits ); +} + +#if defined(MBEDTLS_ECDSA_C) +/* Forward declarations */ +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len, + f_rng, p_rng ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* Forward declarations */ +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ); + +/* + * Restart context for ECDSA operations with ECKEY context + * + * We need to store an actual ECDSA context, as we need to pass the same to + * the underlying ecdsa function, so we can't create it on the fly every time. + */ +typedef struct +{ + mbedtls_ecdsa_restart_ctx ecdsa_rs; + mbedtls_ecdsa_context ecdsa_ctx; +} eckey_restart_ctx; + +static void *eckey_rs_alloc( void ) +{ + eckey_restart_ctx *rs_ctx; + + void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) ); + + if( ctx != NULL ) + { + rs_ctx = ctx; + mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx ); + } + + return( ctx ); +} + +static void eckey_rs_free( void *ctx ) +{ + eckey_restart_ctx *rs_ctx; + + if( ctx == NULL) + return; + + rs_ctx = ctx; + mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx ); + + mbedtls_free( ctx ); +} + +static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) +{ + int ret; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx, + md_alg, hash, hash_len, + sig, sig_len, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); +} + +static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) +{ + int ret; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg, + hash, hash_len, sig, sig_len, + f_rng, p_rng, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDSA_C */ + +static int eckey_check_pair( const void *pub, const void *prv ) +{ + return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub, + (const mbedtls_ecp_keypair *) prv ) ); +} + +static void *eckey_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); + + if( ctx != NULL ) + mbedtls_ecp_keypair_init( ctx ); + + return( ctx ); +} + +static void eckey_free_wrap( void *ctx ) +{ + mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx ); + mbedtls_free( ctx ); +} + +static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_ECP; + items->name = "eckey.Q"; + items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); +} + +const mbedtls_pk_info_t mbedtls_eckey_info = { + MBEDTLS_PK_ECKEY, + "EC", + eckey_get_bitlen, + eckey_can_do, +#if defined(MBEDTLS_ECDSA_C) + eckey_verify_wrap, + eckey_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + eckey_verify_rs_wrap, + eckey_sign_rs_wrap, +#endif +#else /* MBEDTLS_ECDSA_C */ + NULL, + NULL, +#endif /* MBEDTLS_ECDSA_C */ + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, + eckey_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + eckey_rs_alloc, + eckey_rs_free, +#endif + eckey_debug, +}; + +/* + * EC key restricted to ECDH + */ +static int eckeydh_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH ); +} + +const mbedtls_pk_info_t mbedtls_eckeydh_info = { + MBEDTLS_PK_ECKEY_DH, + "EC_DH", + eckey_get_bitlen, /* Same underlying key structure */ + eckeydh_can_do, + NULL, + NULL, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, /* Same underlying key structure */ + eckey_free_wrap, /* Same underlying key structure */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + eckey_debug, /* Same underlying key structure */ +}; +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_ECDSA_C) +static int ecdsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECDSA ); +} + +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) +{ + int ret; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) +{ + return( mbedtls_ecdsa_write_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ) ); + +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +static void *ecdsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx ); + + return( ctx ); +} + +static void ecdsa_free_wrap( void *ctx ) +{ + mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx ); + mbedtls_free( ctx ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +static void *ecdsa_rs_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_restart_init( ctx ); + + return( ctx ); +} + +static void ecdsa_rs_free( void *ctx ) +{ + mbedtls_ecdsa_restart_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +const mbedtls_pk_info_t mbedtls_ecdsa_info = { + MBEDTLS_PK_ECDSA, + "ECDSA", + eckey_get_bitlen, /* Compatible key structures */ + ecdsa_can_do, + ecdsa_verify_wrap, + ecdsa_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_verify_rs_wrap, + ecdsa_sign_rs_wrap, +#endif + NULL, + NULL, + eckey_check_pair, /* Compatible key structures */ + ecdsa_alloc_wrap, + ecdsa_free_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_rs_alloc, + ecdsa_rs_free, +#endif + eckey_debug, /* Compatible key structures */ +}; +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Support for alternative RSA-private implementations + */ + +static int rsa_alt_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA ); +} + +static size_t rsa_alt_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; + + return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); +} + +static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = rsa_alt->key_len_func( rsa_alt->key ); + + return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_alt_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + + ((void) f_rng); + ((void) p_rng); + + if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( rsa_alt->decrypt_func( rsa_alt->key, + MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); +} + +#if defined(MBEDTLS_RSA_C) +static int rsa_alt_check_pair( const void *pub, const void *prv ) +{ + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char hash[32]; + size_t sig_len = 0; + int ret; + + if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + memset( hash, 0x2a, sizeof( hash ) ); + + if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE, + hash, sizeof( hash ), + sig, &sig_len, NULL, NULL ) ) != 0 ) + { + return( ret ); + } + + if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE, + hash, sizeof( hash ), sig, sig_len ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +static void *rsa_alt_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) ); + + if( ctx != NULL ) + memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) ); + + return( ctx ); +} + +static void rsa_alt_free_wrap( void *ctx ) +{ + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); + mbedtls_free( ctx ); +} + +const mbedtls_pk_info_t mbedtls_rsa_alt_info = { + MBEDTLS_PK_RSA_ALT, + "RSA-alt", + rsa_alt_get_bitlen, + rsa_alt_can_do, + NULL, + rsa_alt_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_alt_decrypt_wrap, + NULL, +#if defined(MBEDTLS_RSA_C) + rsa_alt_check_pair, +#else + NULL, +#endif + rsa_alt_alloc_wrap, + rsa_alt_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + NULL, +}; + +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +#endif /* MBEDTLS_PK_C */ diff --git a/external/mbedtls/library/pkcs11.c b/external/mbedtls/library/pkcs11.c new file mode 100644 index 0000000..cf484b8 --- /dev/null +++ b/external/mbedtls/library/pkcs11.c @@ -0,0 +1,265 @@ +/** + * \file pkcs11.c + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#include "mbedtls/pkcs11.h" + +#if defined(MBEDTLS_PKCS11_C) + +#include "mbedtls/md.h" +#include "mbedtls/oid.h" +#include "mbedtls/x509_crt.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_pkcs11_context ) ); +} + +int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + unsigned char *cert_blob = NULL; + size_t cert_blob_size = 0; + + if( cert == NULL ) + { + ret = 2; + goto cleanup; + } + + if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, + &cert_blob_size ) != CKR_OK ) + { + ret = 3; + goto cleanup; + } + + cert_blob = mbedtls_calloc( 1, cert_blob_size ); + if( NULL == cert_blob ) + { + ret = 4; + goto cleanup; + } + + if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, + &cert_blob_size ) != CKR_OK ) + { + ret = 5; + goto cleanup; + } + + if( 0 != mbedtls_x509_crt_parse( cert, cert_blob, cert_blob_size ) ) + { + ret = 6; + goto cleanup; + } + + ret = 0; + +cleanup: + if( NULL != cert_blob ) + mbedtls_free( cert_blob ); + + return( ret ); +} + + +int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + mbedtls_x509_crt cert; + + mbedtls_x509_crt_init( &cert ); + + if( priv_key == NULL ) + goto cleanup; + + if( 0 != mbedtls_pkcs11_x509_cert_bind( &cert, pkcs11_cert ) ) + goto cleanup; + + priv_key->len = mbedtls_pk_get_len( &cert.pk ); + priv_key->pkcs11h_cert = pkcs11_cert; + + ret = 0; + +cleanup: + mbedtls_x509_crt_free( &cert ); + + return( ret ); +} + +void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ) +{ + if( NULL != priv_key ) + pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert ); +} + +int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + size_t input_len, output_len; + + if( NULL == ctx ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( MBEDTLS_RSA_PRIVATE != mode ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + output_len = input_len = ctx->len; + + if( input_len < 16 || input_len > output_max_len ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Determine size of output buffer */ + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, NULL, &output_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + if( output_len > output_max_len ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, output, &output_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + *olen = output_len; + return( 0 ); +} + +int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t sig_len = 0, asn_len = 0, oid_size = 0; + unsigned char *p = sig; + const char *oid; + + if( NULL == ctx ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( MBEDTLS_RSA_PRIVATE != mode ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + asn_len = 10 + oid_size; + } + + sig_len = ctx->len; + if( hashlen > sig_len || asn_len > sig_len || + hashlen + asn_len > sig_len ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = oid_size & 0xFF; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = hashlen; + } + + memcpy( p, hash, hashlen ); + + if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, + asn_len + hashlen, sig, &sig_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +#endif /* defined(MBEDTLS_PKCS11_C) */ diff --git a/external/mbedtls/library/pkcs12.c b/external/mbedtls/library/pkcs12.c new file mode 100644 index 0000000..3d23d5e --- /dev/null +++ b/external/mbedtls/library/pkcs12.c @@ -0,0 +1,390 @@ +/* + * PKCS#12 Personal Information Exchange Syntax + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 + * + * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf + * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PKCS12_C) + +#include "mbedtls/pkcs12.h" +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations ) +{ + int ret; + unsigned char **p = ¶ms->p; + const unsigned char *end = params->p + params->len; + + /* + * pkcs-12PbeParams ::= SEQUENCE { + * salt OCTET STRING, + * iterations INTEGER + * } + * + */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); + + salt->p = *p; + *p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#define PKCS12_MAX_PWDLEN 128 + +static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + unsigned char *key, size_t keylen, + unsigned char *iv, size_t ivlen ) +{ + int ret, iterations = 0; + mbedtls_asn1_buf salt; + size_t i; + unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; + + if( pwdlen > PKCS12_MAX_PWDLEN ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + memset( &salt, 0, sizeof(mbedtls_asn1_buf) ); + memset( &unipwd, 0, sizeof(unipwd) ); + + if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, + &iterations ) ) != 0 ) + return( ret ); + + for( i = 0; i < pwdlen; i++ ) + unipwd[i * 2 + 1] = pwd[i]; + + if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 ) + { + return( ret ); + } + + if( iv == NULL || ivlen == 0 ) + return( 0 ); + + if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +#undef PKCS12_MAX_PWDLEN + +int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ +#if !defined(MBEDTLS_ARC4_C) + ((void) pbe_params); + ((void) mode); + ((void) pwd); + ((void) pwdlen); + ((void) data); + ((void) len); + ((void) output); + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); +#else + int ret; + unsigned char key[16]; + mbedtls_arc4_context ctx; + ((void) mode); + + mbedtls_arc4_init( &ctx ); + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDTLS_MD_SHA1, + pwd, pwdlen, + key, 16, NULL, 0 ) ) != 0 ) + { + return( ret ); + } + + mbedtls_arc4_setup( &ctx, key, 16 ); + if( ( ret = mbedtls_arc4_crypt( &ctx, len, data, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_arc4_free( &ctx ); + + return( ret ); +#endif /* MBEDTLS_ARC4_C */ +} + +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ + int ret, keylen = 0; + unsigned char key[32]; + unsigned char iv[16]; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_cipher_context_t cipher_ctx; + size_t olen = 0; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + keylen = cipher_info->key_bitlen / 8; + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, + key, keylen, + iv, cipher_info->iv_size ) ) != 0 ) + { + return( ret ); + } + + mbedtls_cipher_init( &cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len, + output, &olen ) ) != 0 ) + { + goto exit; + } + + if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) + ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; + +exit: + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( iv, sizeof( iv ) ); + mbedtls_cipher_free( &cipher_ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, + const unsigned char *filler, size_t fill_len ) +{ + unsigned char *p = data; + size_t use_len; + + while( data_len > 0 ) + { + use_len = ( data_len > fill_len ) ? fill_len : data_len; + memcpy( p, filler, use_len ); + p += use_len; + data_len -= use_len; + } +} + +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t md_type, int id, int iterations ) +{ + int ret; + unsigned int j; + + unsigned char diversifier[128]; + unsigned char salt_block[128], pwd_block[128], hash_block[128]; + unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; + unsigned char *p; + unsigned char c; + + size_t hlen, use_len, v, i; + + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + // This version only allows max of 64 bytes of password or salt + if( datalen > 128 || pwdlen > 64 || saltlen > 64 ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( md_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + mbedtls_md_init( &md_ctx ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + return( ret ); + hlen = mbedtls_md_get_size( md_info ); + + if( hlen <= 32 ) + v = 64; + else + v = 128; + + memset( diversifier, (unsigned char) id, v ); + + pkcs12_fill_buffer( salt_block, v, salt, saltlen ); + pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen ); + + p = data; + while( datalen > 0 ) + { + // Calculate hash( diversifier || salt_block || pwd_block ) + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 ) + goto exit; + + // Perform remaining ( iterations - 1 ) recursive hash calculations + for( i = 1; i < (size_t) iterations; i++ ) + { + if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 ) + goto exit; + } + + use_len = ( datalen > hlen ) ? hlen : datalen; + memcpy( p, hash_output, use_len ); + datalen -= use_len; + p += use_len; + + if( datalen == 0 ) + break; + + // Concatenating copies of hash_output into hash_block (B) + pkcs12_fill_buffer( hash_block, v, hash_output, hlen ); + + // B += 1 + for( i = v; i > 0; i-- ) + if( ++hash_block[i - 1] != 0 ) + break; + + // salt_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = salt_block[i - 1] + hash_block[i - 1] + c; + c = (unsigned char) (j >> 8); + salt_block[i - 1] = j & 0xFF; + } + + // pwd_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = pwd_block[i - 1] + hash_block[i - 1] + c; + c = (unsigned char) (j >> 8); + pwd_block[i - 1] = j & 0xFF; + } + } + + ret = 0; + +exit: + mbedtls_platform_zeroize( salt_block, sizeof( salt_block ) ); + mbedtls_platform_zeroize( pwd_block, sizeof( pwd_block ) ); + mbedtls_platform_zeroize( hash_block, sizeof( hash_block ) ); + mbedtls_platform_zeroize( hash_output, sizeof( hash_output ) ); + + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PKCS12_C */ diff --git a/external/mbedtls/library/pkcs5.c b/external/mbedtls/library/pkcs5.c new file mode 100644 index 0000000..c4447f1 --- /dev/null +++ b/external/mbedtls/library/pkcs5.c @@ -0,0 +1,441 @@ +/** + * \file pkcs5.c + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * PKCS#5 includes PBKDF2 and more + * + * http://tools.ietf.org/html/rfc2898 (Specification) + * http://tools.ietf.org/html/rfc6070 (Test vectors) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PKCS5_C) + +#include "mbedtls/pkcs5.h" + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" +#include "mbedtls/oid.h" +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations, + int *keylen, mbedtls_md_type_t *md_type ) +{ + int ret; + mbedtls_asn1_buf prf_alg_oid; + unsigned char *p = params->p; + const unsigned char *end = params->p + params->len; + + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + /* + * PBKDF2-params ::= SEQUENCE { + * salt OCTET STRING, + * iterationCount INTEGER, + * keyLength INTEGER OPTIONAL + * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 + * } + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + salt->p = p; + p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + } + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( p != end ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ) +{ + int ret, iterations = 0, keylen = 0; + unsigned char *p, *end; + mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; + mbedtls_asn1_buf salt; + mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; + unsigned char key[32], iv[32]; + size_t olen = 0; + const mbedtls_md_info_t *md_info; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_md_context_t md_ctx; + mbedtls_cipher_type_t cipher_alg; + mbedtls_cipher_context_t cipher_ctx; + + p = pbe_params->p; + end = p + pbe_params->len; + + /* + * PBES2-params ::= SEQUENCE { + * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, + * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} + * } + */ + if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + // Only PBKDF2 supported at the moment + // + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, + &salt, &iterations, &keylen, + &md_type ) ) != 0 ) + { + return( ret ); + } + + md_info = mbedtls_md_info_from_type( md_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid, + &enc_scheme_params ) ) != 0 ) + { + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + } + + if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + cipher_info = mbedtls_cipher_info_from_type( cipher_alg ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + /* + * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored + * since it is optional and we don't know if it was set or not + */ + keylen = cipher_info->key_bitlen / 8; + + if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || + enc_scheme_params.len != cipher_info->iv_size ) + { + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ); + } + + mbedtls_md_init( &md_ctx ); + mbedtls_cipher_init( &cipher_ctx ); + + memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, + iterations, keylen, key ) ) != 0 ) + { + goto exit; + } + + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, + data, datalen, output, &olen ) ) != 0 ) + ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; + +exit: + mbedtls_md_free( &md_ctx ); + mbedtls_cipher_free( &cipher_ctx ); + + return( ret ); +} +#endif /* MBEDTLS_ASN1_PARSE_C */ + +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ) +{ + int ret = 0, j; + unsigned int i; + unsigned char md1[MBEDTLS_MD_MAX_SIZE]; + unsigned char work[MBEDTLS_MD_MAX_SIZE]; + unsigned char md_size = mbedtls_md_get_size( ctx->md_info ); + size_t use_len; + unsigned char *out_p = output; + unsigned char counter[4]; + + memset( counter, 0, 4 ); + counter[3] = 1; + +#if UINT_MAX > 0xFFFFFFFF + if( iteration_count > 0xFFFFFFFF ) + return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); +#endif + + while( key_length ) + { + // U1 ends up in work + // + if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 ) + goto cleanup; + + memcpy( md1, work, md_size ); + + for( i = 1; i < iteration_count; i++ ) + { + // U2 ends up in md1 + // + if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 ) + goto cleanup; + + // U1 xor U2 + // + for( j = 0; j < md_size; j++ ) + work[j] ^= md1[j]; + } + + use_len = ( key_length < md_size ) ? key_length : md_size; + memcpy( out_p, work, use_len ); + + key_length -= (uint32_t) use_len; + out_p += use_len; + + for( i = 4; i > 0; i-- ) + if( ++counter[i - 1] != 0 ) + break; + } + +cleanup: + /* Zeroise buffers to clear sensitive data from memory. */ + mbedtls_platform_zeroize( work, MBEDTLS_MD_MAX_SIZE ); + mbedtls_platform_zeroize( md1, MBEDTLS_MD_MAX_SIZE ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_SHA1_C) +int mbedtls_pkcs5_self_test( int verbose ) +{ + if( verbose != 0 ) + mbedtls_printf( " PBKDF2 (SHA1): skipped\n\n" ); + + return( 0 ); +} +#else + +#define MAX_TESTS 6 + +static const size_t plen[MAX_TESTS] = + { 8, 8, 8, 24, 9 }; + +static const unsigned char password[MAX_TESTS][32] = +{ + "password", + "password", + "password", + "passwordPASSWORDpassword", + "pass\0word", +}; + +static const size_t slen[MAX_TESTS] = + { 4, 4, 4, 36, 5 }; + +static const unsigned char salt[MAX_TESTS][40] = +{ + "salt", + "salt", + "salt", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + "sa\0lt", +}; + +static const uint32_t it_cnt[MAX_TESTS] = + { 1, 2, 4096, 4096, 4096 }; + +static const uint32_t key_len[MAX_TESTS] = + { 20, 20, 20, 25, 16 }; + +static const unsigned char result_key[MAX_TESTS][32] = +{ + { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6 }, + { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57 }, + { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1 }, + { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, + 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, + 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, + 0x38 }, + { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, +}; + +int mbedtls_pkcs5_self_test( int verbose ) +{ + mbedtls_md_context_t sha1_ctx; + const mbedtls_md_info_t *info_sha1; + int ret, i; + unsigned char key[64]; + + mbedtls_md_init( &sha1_ctx ); + + info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); + if( info_sha1 == NULL ) + { + ret = 1; + goto exit; + } + + if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 ) + { + ret = 1; + goto exit; + } + + for( i = 0; i < MAX_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i ); + + ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i], + slen[i], it_cnt[i], key_len[i], key ); + if( ret != 0 || + memcmp( result_key[i], key, key_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_md_free( &sha1_ctx ); + + return( ret ); +} +#endif /* MBEDTLS_SHA1_C */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_PKCS5_C */ diff --git a/external/mbedtls/library/pkparse.c b/external/mbedtls/library/pkparse.c new file mode 100644 index 0000000..e410f3a --- /dev/null +++ b/external/mbedtls/library/pkparse.c @@ -0,0 +1,1563 @@ +/* + * Public Key layer for parsing key files and structures + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_PARSE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + PK_VALIDATE_RET( path != NULL ); + PK_VALIDATE_RET( buf != NULL ); + PK_VALIDATE_RET( n != NULL ); + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + + mbedtls_platform_zeroize( *buf, *n ); + mbedtls_free( *buf ); + + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); +} + +/* + * Load and parse a private key + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *pwd ) +{ + int ret; + size_t n; + unsigned char *buf; + + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( path != NULL ); + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + if( pwd == NULL ) + ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 ); + else + ret = mbedtls_pk_parse_key( ctx, buf, n, + (const unsigned char *) pwd, strlen( pwd ) ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +/* + * Load and parse a public key + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( path != NULL ); + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_pk_parse_public_key( ctx, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_ECP_C) +/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + * } + */ +static int pk_get_ecparams( unsigned char **p, const unsigned char *end, + mbedtls_asn1_buf *params ) +{ + int ret; + + if ( end - *p < 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* Tag may be either OID or SEQUENCE */ + params->tag = **p; + if( params->tag != MBEDTLS_ASN1_OID +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) +#endif + ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. + * WARNING: the resulting group should only be used with + * pk_group_id_from_specified(), since its base point may not be set correctly + * if it was encoded compressed. + * + * SpecifiedECDomain ::= SEQUENCE { + * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), + * fieldID FieldID {{FieldTypes}}, + * curve Curve, + * base ECPoint, + * order INTEGER, + * cofactor INTEGER OPTIONAL, + * hash HashAlgorithm OPTIONAL, + * ... + * } + * + * We only support prime-field as field type, and ignore hash and cofactor. + */ +static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret; + unsigned char *p = params->p; + const unsigned char * const end = params->p + params->len; + const unsigned char *end_field, *end_curve; + size_t len; + int ver; + + /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ + if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ver < 1 || ver > 3 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + /* + * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field + * fieldType FIELD-ID.&id({IOSet}), + * parameters FIELD-ID.&Type({IOSet}{@fieldType}) + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_field = p + len; + + /* + * FIELD-ID ::= TYPE-IDENTIFIER + * FieldTypes FIELD-ID ::= { + * { Prime-p IDENTIFIED BY prime-field } | + * { Characteristic-two IDENTIFIED BY characteristic-two-field } + * } + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) || + memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) + { + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + } + + p += len; + + /* Prime-p ::= INTEGER -- Field of size p. */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + if( p != end_field ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Curve ::= SEQUENCE { + * a FieldElement, + * b FieldElement, + * seed BIT STRING OPTIONAL + * -- Shall be present if used in SpecifiedECDomain + * -- with version equal to ecdpVer2 or ecdpVer3 + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_curve = p + len; + + /* + * FieldElement ::= OCTET STRING + * containing an integer in the case of a prime field + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + /* Ignore seed BIT STRING OPTIONAL */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 ) + p += len; + + if( p != end_curve ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * ECPoint ::= OCTET STRING + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G, + ( const unsigned char *) p, len ) ) != 0 ) + { + /* + * If we can't read the point because it's compressed, cheat by + * reading only the X coordinate and the parity bit of Y. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || + ( p[0] != 0x02 && p[0] != 0x03 ) || + len != mbedtls_mpi_size( &grp->P ) + 1 || + mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || + mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || + mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + + p += len; + + /* + * order INTEGER + */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + /* + * Allow optional elements by purposefully not enforcing p == end here. + */ + + return( 0 ); +} + +/* + * Find the group id associated with an (almost filled) group as generated by + * pk_group_from_specified(), or return an error if unknown. + */ +static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id ) +{ + int ret = 0; + mbedtls_ecp_group ref; + const mbedtls_ecp_group_id *id; + + mbedtls_ecp_group_init( &ref ); + + for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ ) + { + /* Load the group associated to that id */ + mbedtls_ecp_group_free( &ref ); + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) ); + + /* Compare to the group we were given, starting with easy tests */ + if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && + mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && + /* For Y we may only know the parity bit, so compare only that */ + mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) ) + { + break; + } + + } + +cleanup: + mbedtls_ecp_group_free( &ref ); + + *grp_id = *id; + + if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE ) + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + + return( ret ); +} + +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID + */ +static int pk_group_id_from_specified( const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *grp_id ) +{ + int ret; + mbedtls_ecp_group grp; + + mbedtls_ecp_group_init( &grp ); + + if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) + goto cleanup; + + ret = pk_group_id_from_group( &grp, grp_id ); + +cleanup: + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ + +/* + * Use EC parameters to initialise an EC group + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + */ +static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret; + mbedtls_ecp_group_id grp_id; + + if( params->tag == MBEDTLS_ASN1_OID ) + { + if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); + } + else + { +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) + return( ret ); +#else + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +#endif + } + + /* + * grp may already be initilialized; if so, make sure IDs match + */ + if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * EC public key is an EC point + * + * The caller is responsible for clearing the structure upon failure if + * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE + * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. + */ +static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, + mbedtls_ecp_keypair *key ) +{ + int ret; + + if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q, + (const unsigned char *) *p, end - *p ) ) == 0 ) + { + ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q ); + } + + /* + * We know mbedtls_ecp_point_read_binary consumed all bytes or failed + */ + *p = (unsigned char *) end; + + return( ret ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_get_rsapubkey( unsigned char **p, + const unsigned char *end, + mbedtls_rsa_context *rsa ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* Import N */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + /* Import E */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, *p, len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + if( mbedtls_rsa_complete( rsa ) != 0 || + mbedtls_rsa_check_pubkey( rsa ) != 0 ) + { + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + } + + if( *p != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +/* Get a PK algorithm identifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +static int pk_get_pk_alg( unsigned char **p, + const unsigned char *end, + mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) +{ + int ret; + mbedtls_asn1_buf alg_oid; + + memset( params, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_ALG + ret ); + + if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + /* + * No parameters with RSA (only for EC) + */ + if( *pk_alg == MBEDTLS_PK_RSA && + ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || + params->len != 0 ) ) + { + return( MBEDTLS_ERR_PK_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ) +{ + int ret; + size_t len; + mbedtls_asn1_buf alg_params; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + PK_VALIDATE_RET( p != NULL ); + PK_VALIDATE_RET( *p != NULL ); + PK_VALIDATE_RET( end != NULL ); + PK_VALIDATE_RET( pk != NULL ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = *p + len; + + if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) ); + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) + { + ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp ); + if( ret == 0 ) + ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) ); + } else +#endif /* MBEDTLS_ECP_C */ + ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + + if( ret == 0 && *p != end ) + ret = MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + + if( ret != 0 ) + mbedtls_pk_free( pk ); + + return( ret ); +} + +#if defined(MBEDTLS_RSA_C) +/* + * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. + * + * The value zero is: + * - never a valid value for an RSA parameter + * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). + * + * Since values can't be omitted in PKCS#1, passing a zero value to + * rsa_complete() would be incorrect, so reject zero values early. + */ +static int asn1_get_nonzero_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret; + + ret = mbedtls_asn1_get_mpi( p, end, X ); + if( ret != 0 ) + return( ret ); + + if( mbedtls_mpi_cmp_int( X, 0 ) == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + return( 0 ); +} + +/* + * Parse a PKCS#1 encoded private RSA key + */ +static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, + const unsigned char *key, + size_t keylen ) +{ + int ret, version; + size_t len; + unsigned char *p, *end; + + mbedtls_mpi T; + mbedtls_mpi_init( &T ); + + p = (unsigned char *) key; + end = p + keylen; + + /* + * This function parses the RSAPrivateKey (PKCS#1) + * + * 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 + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( version != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + } + + /* Import N */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, &T, NULL, NULL, + NULL, NULL ) ) != 0 ) + goto cleanup; + + /* Import E */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, + NULL, &T ) ) != 0 ) + goto cleanup; + + /* Import D */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, + &T, NULL ) ) != 0 ) + goto cleanup; + + /* Import P */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, &T, NULL, + NULL, NULL ) ) != 0 ) + goto cleanup; + + /* Import Q */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, &T, + NULL, NULL ) ) != 0 ) + goto cleanup; + +#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) + /* + * The RSA CRT parameters DP, DQ and QP are nominally redundant, in + * that they can be easily recomputed from D, P and Q. However by + * parsing them from the PKCS1 structure it is possible to avoid + * recalculating them which both reduces the overhead of loading + * RSA private keys into memory and also avoids side channels which + * can arise when computing those values, since all of D, P, and Q + * are secret. See https://eprint.iacr.org/2020/055 for a + * description of one such attack. + */ + + /* Import DP */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->DP, &T ) ) != 0 ) + goto cleanup; + + /* Import DQ */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->DQ, &T ) ) != 0 ) + goto cleanup; + + /* Import QP */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->QP, &T ) ) != 0 ) + goto cleanup; + +#else + /* Verify existance of the CRT params */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ) + goto cleanup; +#endif + + /* rsa_complete() doesn't complete anything with the default + * implementation but is still called: + * - for the benefit of alternative implementation that may want to + * pre-compute stuff beyond what's provided (eg Montgomery factors) + * - as is also sanity-checks the key + * + * Furthermore, we also check the public part for consistency with + * mbedtls_pk_parse_pubkey(), as it includes size minima for example. + */ + if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 || + ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) + { + goto cleanup; + } + + if( p != end ) + { + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ; + } + +cleanup: + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + { + /* Wrap error code if it's coming from a lower level */ + if( ( ret & 0xff80 ) == 0 ) + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret; + else + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + + mbedtls_rsa_free( rsa ); + } + + return( ret ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Parse a SEC1 encoded private EC key + */ +static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, + const unsigned char *key, + size_t keylen ) +{ + int ret; + int version, pubkey_done; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + unsigned char *end2; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + pubkey_done = 0; + if( p != end ) + { + /* + * Is 'parameters' present? + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || + ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + } + + if( p != end ) + { + /* + * Is 'publickey' present? If not, or if we can't read it (eg because it + * is compressed), create it from the private key. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( p + len != end2 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) + pubkey_done = 1; + else + { + /* + * The only acceptable failure mode of pk_get_ecpubkey() above + * is if the point format is not recognized. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + } + + if( ! pubkey_done && + ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, + NULL, NULL ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_ECP_C */ + +/* + * Parse an unencrypted PKCS#8 encoded private key + * + * Notes: + * + * - This function does not own the key buffer. It is the + * responsibility of the caller to take care of zeroizing + * and freeing it after use. + * + * - The function is responsible for freeing the provided + * PK context on failure. + * + */ +static int pk_parse_key_pkcs8_unencrypted_der( + mbedtls_pk_context *pk, + const unsigned char* key, + size_t keylen ) +{ + int ret, version; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + /* + * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey + */ + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret ); + + if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( len < 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + return( 0 ); +} + +/* + * Parse an encrypted PKCS#8 encoded private key + * + * To save space, the decryption happens in-place on the given key buffer. + * Also, while this function may modify the keybuffer, it doesn't own it, + * and instead it is the responsibility of the caller to zeroize and properly + * free it after use. + * + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) +static int pk_parse_key_pkcs8_encrypted_der( + mbedtls_pk_context *pk, + unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret, decrypted = 0; + size_t len; + unsigned char *buf; + unsigned char *p, *end; + mbedtls_asn1_buf pbe_alg_oid, pbe_params; +#if defined(MBEDTLS_PKCS12_C) + mbedtls_cipher_type_t cipher_alg; + mbedtls_md_type_t md_alg; +#endif + + p = key; + end = p + keylen; + + if( pwdlen == 0 ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + + /* + * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData + * } + * + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * EncryptedData ::= OCTET STRING + * + * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + buf = p; + + /* + * Decrypt EncryptedData with appropriate PBE + */ +#if defined(MBEDTLS_PKCS12_C) + if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, + cipher_alg, md_alg, + pwd, pwdlen, p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params, + MBEDTLS_PKCS12_PBE_DECRYPT, + pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + return( ret ); + } + + // Best guess for password mismatch when using RC4. If first tag is + // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE + // + if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PKCS5_C) + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS5_C */ + { + ((void) pwd); + } + + if( decrypted == 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); +} +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + +/* + * Parse a private key + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret; + const mbedtls_pk_info_t *pk_info; +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; +#endif + + PK_VALIDATE_RET( pk != NULL ); + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + PK_VALIDATE_RET( key != NULL ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); + +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + + if( ret == 0 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_ECP_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN ENCRYPTED PRIVATE KEY-----", + "-----END ENCRYPTED PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, + pem.buf, pem.buflen, + pwd, pwdlen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_PEM_PARSE_C */ + + /* + * At this point we only know it's not a PEM formatted key. Could be any + * of the known DER encoded private key formats + * + * We try the different DER format parsers to see if one passes without + * error + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + { + unsigned char *key_copy; + + if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + memcpy( key_copy, key, keylen ); + + ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen, + pwd, pwdlen ); + + mbedtls_platform_zeroize( key_copy, keylen ); + mbedtls_free( key_copy ); + } + + if( ret == 0 ) + return( 0 ); + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); + + if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) + { + return( ret ); + } +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 ) + return( 0 ); + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); + +#if defined(MBEDTLS_RSA_C) + + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + key, keylen ) == 0 ) + { + return( 0 ); + } + mbedtls_pk_free( pk ); +#endif /* MBEDTLS_ECP_C */ + + /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't, + * it is ok to leave the PK context initialized but not + * freed: It is the caller's responsibility to call pk_init() + * before calling this function, and to call pk_free() + * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C + * isn't, this leads to mbedtls_pk_free() being called + * twice, once here and once by the caller, but this is + * also ok and in line with the mbedtls_pk_free() calls + * on failed PEM parsing attempts. */ + + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +} + +/* + * Parse a public key + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ) +{ + int ret; + unsigned char *p; +#if defined(MBEDTLS_RSA_C) + const mbedtls_pk_info_t *pk_info; +#endif +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; +#endif + + PK_VALIDATE_RET( ctx != NULL ); + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + PK_VALIDATE_RET( key != NULL || keylen == 0 ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PUBLIC KEY-----", + "-----END RSA PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + p = pem.buf; + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 ) + mbedtls_pk_free( ctx ); + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + p = pem.buf; + + ret = mbedtls_pk_parse_subpubkey( &p, p + pem.buflen, ctx ); + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + mbedtls_pem_free( &pem ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_RSA_C) + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + p = (unsigned char *)key; + ret = pk_get_rsapubkey( &p, p + keylen, mbedtls_pk_rsa( *ctx ) ); + if( ret == 0 ) + { + return( ret ); + } + mbedtls_pk_free( ctx ); + if( ret != ( MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + { + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + p = (unsigned char *) key; + + ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PK_PARSE_C */ diff --git a/external/mbedtls/library/pkwrite.c b/external/mbedtls/library/pkwrite.c new file mode 100644 index 0000000..a770dfb --- /dev/null +++ b/external/mbedtls/library/pkwrite.c @@ -0,0 +1,591 @@ +/* + * Public Key layer for writing key files and structures + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_WRITE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/bignum.h" +#include "mbedtls/ecp.h" +#include "mbedtls/platform_util.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, + mbedtls_rsa_context *rsa ) +{ + int ret; + size_t len = 0; + mbedtls_mpi T; + + mbedtls_mpi_init( &T ); + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + +end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * EC public key is an EC point + */ +static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; + + if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &len, buf, sizeof( buf ) ) ) != 0 ) + { + return( ret ); + } + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *p -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +/* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * } + */ +static int pk_write_ec_param( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + const char *oid; + size_t oid_len; + + if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + return( (int) len ); +} + +/* + * privateKey OCTET STRING -- always of length ceil(log2(n)/8) + */ +static int pk_write_ec_private( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret; + size_t byte_length = ( ec->grp.pbits + 7 ) / 8; + unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; + + ret = mbedtls_mpi_write_binary( &ec->d, tmp, byte_length ); + if( ret != 0 ) + goto exit; + ret = mbedtls_asn1_write_octet_string( p, start, tmp, byte_length ); + +exit: + mbedtls_platform_zeroize( tmp, byte_length ); + return( ret ); +} +#endif /* MBEDTLS_ECP_C */ + +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ) +{ + int ret; + size_t len = 0; + + PK_VALIDATE_RET( p != NULL ); + PK_VALIDATE_RET( *p != NULL ); + PK_VALIDATE_RET( start != NULL ); + PK_VALIDATE_RET( key != NULL ); + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) ); + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) ); + else +#endif + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char *c; + size_t len = 0, par_len = 0, oid_len; + const char *oid; + + PK_VALIDATE_RET( key != NULL ); + if( size == 0 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + PK_VALIDATE_RET( buf != NULL ); + + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); + + if( c - buf < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ + *--c = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); + + if( ( ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ), + &oid, &oid_len ) ) != 0 ) + { + return( ret ); + } + +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) ); + } +#endif + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len, + par_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char *c; + size_t len = 0; + + PK_VALIDATE_RET( key != NULL ); + if( size == 0 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + PK_VALIDATE_RET( buf != NULL ); + + c = buf + size; + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + { + mbedtls_mpi T; /* Temporary holding the exported parameters */ + mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); + + /* + * Export the parameters one after another to avoid simultaneous copies. + */ + + mbedtls_mpi_init( &T ); + + /* Export QP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DQ */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export Q */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export P */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export D */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, + buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key ); + size_t pub_len = 0, par_len = 0; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + + /* publicKey */ + MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) ); + + if( c - buf < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + *--c = 0; + pub_len += 1; + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ); + len += pub_len; + + /* parameters */ + MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) ); + + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) ); + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + len += par_len; + + /* privateKey */ + MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_private( &c, buf, ec ) ); + + /* version */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +#if defined(MBEDTLS_PEM_WRITE_C) + +#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" +#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" + +#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" +#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" + +/* + * Max sizes of key per types. Shown as tag + len (+ content). + */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSA public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 9 (rsa oid) + * + 1 + 1 (params null) + * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) + * RSAPublicKey ::= SEQUENCE { 1 + 3 + * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 + * } + */ +#define RSA_PUB_DER_MAX_BYTES ( 38 + 2 * MBEDTLS_MPI_MAX_SIZE ) + +/* + * RSA private keys: + * RSAPrivateKey ::= SEQUENCE { 1 + 3 + * version Version, 1 + 1 + 1 + * modulus INTEGER, 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) + * } + */ +#define MPI_MAX_SIZE_2 ( MBEDTLS_MPI_MAX_SIZE / 2 + \ + MBEDTLS_MPI_MAX_SIZE % 2 ) +#define RSA_PRV_DER_MAX_BYTES ( 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ + + 5 * MPI_MAX_SIZE_2 ) + +#else /* MBEDTLS_RSA_C */ + +#define RSA_PUB_DER_MAX_BYTES 0 +#define RSA_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * EC public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 7 (ec oid) + * + 1 + 1 + 9 (namedCurve oid) + * subjectPublicKey BIT STRING 1 + 2 + 1 [1] + * + 1 (point format) [1] + * + 2 * ECP_MAX (coords) [1] + * } + */ +#define ECP_PUB_DER_MAX_BYTES ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES ) + +/* + * EC private keys: + * ECPrivateKey ::= SEQUENCE { 1 + 2 + * version INTEGER , 1 + 1 + 1 + * privateKey OCTET STRING, 1 + 1 + ECP_MAX + * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) + * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above + * } + */ +#define ECP_PRV_DER_MAX_BYTES ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES ) + +#else /* MBEDTLS_ECP_C */ + +#define ECP_PUB_DER_MAX_BYTES 0 +#define ECP_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_ECP_C */ + +#define PUB_DER_MAX_BYTES ( RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ + RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES ) +#define PRV_DER_MAX_BYTES ( RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ + RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES ) + +int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[PUB_DER_MAX_BYTES]; + size_t olen = 0; + + PK_VALIDATE_RET( key != NULL ); + PK_VALIDATE_RET( buf != NULL || size == 0 ); + + if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[PRV_DER_MAX_BYTES]; + const char *begin, *end; + size_t olen = 0; + + PK_VALIDATE_RET( key != NULL ); + PK_VALIDATE_RET( buf != NULL || size == 0 ); + + if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + { + begin = PEM_BEGIN_PRIVATE_KEY_RSA; + end = PEM_END_PRIVATE_KEY_RSA; + } + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + begin = PEM_BEGIN_PRIVATE_KEY_EC; + end = PEM_END_PRIVATE_KEY_EC; + } + else +#endif + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_pem_write_buffer( begin, end, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_PK_WRITE_C */ diff --git a/external/mbedtls/library/platform.c b/external/mbedtls/library/platform.c new file mode 100644 index 0000000..c4c3fd3 --- /dev/null +++ b/external/mbedtls/library/platform.c @@ -0,0 +1,373 @@ +/* + * Platform abstraction layer + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" + +/* The compile time configuration of memory allocation via the macros + * MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime + * configuration via mbedtls_platform_set_calloc_free(). So, omit everything + * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */ +#if defined(MBEDTLS_PLATFORM_MEMORY) && \ + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) + +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +static void *platform_calloc_uninit( size_t n, size_t size ) +{ + ((void) n); + ((void) size); + return( NULL ); +} + +#define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit +#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ + +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +static void platform_free_uninit( void *ptr ) +{ + ((void) ptr); +} + +#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FREE */ + +static void * (*mbedtls_calloc_func)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; +static void (*mbedtls_free_func)( void * ) = MBEDTLS_PLATFORM_STD_FREE; + +void * mbedtls_calloc( size_t nmemb, size_t size ) +{ + return (*mbedtls_calloc_func)( nmemb, size ); +} + +void mbedtls_free( void * ptr ) +{ + (*mbedtls_free_func)( ptr ); +} + +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ) +{ + mbedtls_calloc_func = calloc_func; + mbedtls_free_func = free_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_MEMORY && + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */ + +#if defined(_WIN32) +#include +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ) +{ + int ret; + va_list argp; + + /* Avoid calling the invalid parameter handler by checking ourselves */ + if( s == NULL || n == 0 || fmt == NULL ) + return( -1 ); + + va_start( argp, fmt ); +#if defined(_TRUNCATE) && !defined(__MINGW32__) + ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp ); +#else + ret = _vsnprintf( s, n, fmt, argp ); + if( ret < 0 || (size_t) ret == n ) + { + s[n-1] = '\0'; + ret = -1; + } +#endif + va_end( argp ); + + return( ret ); +} +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_snprintf_uninit( char * s, size_t n, + const char * format, ... ) +{ + ((void) s); + ((void) n); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ + +int (*mbedtls_snprintf)( char * s, size_t n, + const char * format, + ... ) = MBEDTLS_PLATFORM_STD_SNPRINTF; + +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, + ... ) ) +{ + mbedtls_snprintf = snprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_printf_uninit( const char *format, ... ) +{ + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ + +int (*mbedtls_printf)( const char *, ... ) = MBEDTLS_PLATFORM_STD_PRINTF; + +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ) +{ + mbedtls_printf = printf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_fprintf_uninit( FILE *stream, const char *format, ... ) +{ + ((void) stream); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ + +int (*mbedtls_fprintf)( FILE *, const char *, ... ) = + MBEDTLS_PLATFORM_STD_FPRINTF; + +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) ) +{ + mbedtls_fprintf = fprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static void platform_exit_uninit( int status ) +{ + ((void) status); +} + +#define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit +#endif /* !MBEDTLS_PLATFORM_STD_EXIT */ + +void (*mbedtls_exit)( int status ) = MBEDTLS_PLATFORM_STD_EXIT; + +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ) +{ + mbedtls_exit = exit_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +#if defined(MBEDTLS_HAVE_TIME) + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static mbedtls_time_t platform_time_uninit( mbedtls_time_t* timer ) +{ + ((void) timer); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit +#endif /* !MBEDTLS_PLATFORM_STD_TIME */ + +mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* timer ) = MBEDTLS_PLATFORM_STD_TIME; + +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* timer ) ) +{ + mbedtls_time = time_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Default implementations for the platform independent seed functions use + * standard libc file functions to read from and write to a pre-defined filename + */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) + return( -1 ); + + if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + mbedtls_platform_zeroize( buf, buf_len ); + return( -1 ); + } + + fclose( file ); + return( (int)n ); +} + +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL ) + return -1; + + if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + return -1; + } + + fclose( file ); + return( (int)n ); +} +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ + +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ + +int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_READ; +int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; + +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) ) +{ + mbedtls_nv_seed_read = nv_seed_read_func; + mbedtls_nv_seed_write = nv_seed_write_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) +/* + * Placeholder platform setup that does nothing by default + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ) +{ + (void)ctx; + + return( 0 ); +} + +/* + * Placeholder platform teardown that does nothing by default + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ) +{ + (void)ctx; +} +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +#endif /* MBEDTLS_PLATFORM_C */ diff --git a/external/mbedtls/library/platform_util.c b/external/mbedtls/library/platform_util.c new file mode 100644 index 0000000..c8cd52d --- /dev/null +++ b/external/mbedtls/library/platform_util.c @@ -0,0 +1,164 @@ +/* + * Common and shared functions used by multiple modules in the Mbed TLS + * library. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/platform_util.h" +#include "mbedtls/platform.h" +#include "mbedtls/threading.h" + +#include +#include + +#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) +/* + * This implementation should never be optimized out by the compiler + * + * This implementation for mbedtls_platform_zeroize() was inspired from Colin + * Percival's blog article at: + * + * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html + * + * It uses a volatile function pointer to the standard memset(). Because the + * pointer is volatile the compiler expects it to change at + * any time and will not optimize out the call that could potentially perform + * other operations on the input buffer instead of just setting it to 0. + * Nevertheless, as pointed out by davidtgoldblatt on Hacker News + * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for + * details), optimizations of the following form are still possible: + * + * if( memset_func != memset ) + * memset_func( buf, 0, len ); + * + * Note that it is extremely difficult to guarantee that + * mbedtls_platform_zeroize() will not be optimized out by aggressive compilers + * in a portable way. For this reason, Mbed TLS also provides the configuration + * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for their + * platform and needs. + */ +static void * (* const volatile memset_func)( void *, int, size_t ) = memset; + +void mbedtls_platform_zeroize( void *buf, size_t len ) +{ + MBEDTLS_INTERNAL_VALIDATE( len == 0 || buf != NULL ); + + if( len > 0 ) + memset_func( buf, 0, len ); +} +#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +#include +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define PLATFORM_UTIL_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */ + +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ) +{ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL ); +#elif !defined(PLATFORM_UTIL_USE_GMTIME) + return( gmtime_r( tt, tm_buf ) ); +#else + struct tm *lt; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + lt = gmtime( tt ); + + if( lt != NULL ) + { + memcpy( tm_buf, lt, sizeof( struct tm ) ); + } + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + return( ( lt == NULL ) ? NULL : tm_buf ); +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +} +#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */ diff --git a/external/mbedtls/library/poly1305.c b/external/mbedtls/library/poly1305.c new file mode 100644 index 0000000..5b023f0 --- /dev/null +++ b/external/mbedtls/library/poly1305.c @@ -0,0 +1,584 @@ +/** + * \file poly1305.c + * + * \brief Poly1305 authentication algorithm. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_POLY1305_C) + +#include "mbedtls/poly1305.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_POLY1305_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define POLY1305_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) +#define POLY1305_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define POLY1305_BLOCK_SIZE_BYTES ( 16U ) + +#define BYTES_TO_U32_LE( data, offset ) \ + ( (uint32_t) (data)[offset] \ + | (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 ) \ + | (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 ) \ + | (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 ) \ + ) + +/* + * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier. + * However we provided an alternative for platforms without such a multiplier. + */ +#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) +static uint64_t mul64( uint32_t a, uint32_t b ) +{ + /* a = al + 2**16 ah, b = bl + 2**16 bh */ + const uint16_t al = (uint16_t) a; + const uint16_t bl = (uint16_t) b; + const uint16_t ah = a >> 16; + const uint16_t bh = b >> 16; + + /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */ + const uint32_t lo = (uint32_t) al * bl; + const uint64_t me = (uint64_t)( (uint32_t) ah * bl ) + (uint32_t) al * bh; + const uint32_t hi = (uint32_t) ah * bh; + + return( lo + ( me << 16 ) + ( (uint64_t) hi << 32 ) ); +} +#else +static inline uint64_t mul64( uint32_t a, uint32_t b ) +{ + return( (uint64_t) a * b ); +} +#endif + + +/** + * \brief Process blocks with Poly1305. + * + * \param ctx The Poly1305 context. + * \param nblocks Number of blocks to process. Note that this + * function only processes full blocks. + * \param input Buffer containing the input block(s). + * \param needs_padding Set to 0 if the padding bit has already been + * applied to the input data before calling this + * function. Otherwise, set this parameter to 1. + */ +static void poly1305_process( mbedtls_poly1305_context *ctx, + size_t nblocks, + const unsigned char *input, + uint32_t needs_padding ) +{ + uint64_t d0, d1, d2, d3; + uint32_t acc0, acc1, acc2, acc3, acc4; + uint32_t r0, r1, r2, r3; + uint32_t rs1, rs2, rs3; + size_t offset = 0U; + size_t i; + + r0 = ctx->r[0]; + r1 = ctx->r[1]; + r2 = ctx->r[2]; + r3 = ctx->r[3]; + + rs1 = r1 + ( r1 >> 2U ); + rs2 = r2 + ( r2 >> 2U ); + rs3 = r3 + ( r3 >> 2U ); + + acc0 = ctx->acc[0]; + acc1 = ctx->acc[1]; + acc2 = ctx->acc[2]; + acc3 = ctx->acc[3]; + acc4 = ctx->acc[4]; + + /* Process full blocks */ + for( i = 0U; i < nblocks; i++ ) + { + /* The input block is treated as a 128-bit little-endian integer */ + d0 = BYTES_TO_U32_LE( input, offset + 0 ); + d1 = BYTES_TO_U32_LE( input, offset + 4 ); + d2 = BYTES_TO_U32_LE( input, offset + 8 ); + d3 = BYTES_TO_U32_LE( input, offset + 12 ); + + /* Compute: acc += (padded) block as a 130-bit integer */ + d0 += (uint64_t) acc0; + d1 += (uint64_t) acc1 + ( d0 >> 32U ); + d2 += (uint64_t) acc2 + ( d1 >> 32U ); + d3 += (uint64_t) acc3 + ( d2 >> 32U ); + acc0 = (uint32_t) d0; + acc1 = (uint32_t) d1; + acc2 = (uint32_t) d2; + acc3 = (uint32_t) d3; + acc4 += (uint32_t) ( d3 >> 32U ) + needs_padding; + + /* Compute: acc *= r */ + d0 = mul64( acc0, r0 ) + + mul64( acc1, rs3 ) + + mul64( acc2, rs2 ) + + mul64( acc3, rs1 ); + d1 = mul64( acc0, r1 ) + + mul64( acc1, r0 ) + + mul64( acc2, rs3 ) + + mul64( acc3, rs2 ) + + mul64( acc4, rs1 ); + d2 = mul64( acc0, r2 ) + + mul64( acc1, r1 ) + + mul64( acc2, r0 ) + + mul64( acc3, rs3 ) + + mul64( acc4, rs2 ); + d3 = mul64( acc0, r3 ) + + mul64( acc1, r2 ) + + mul64( acc2, r1 ) + + mul64( acc3, r0 ) + + mul64( acc4, rs3 ); + acc4 *= r0; + + /* Compute: acc %= (2^130 - 5) (partial remainder) */ + d1 += ( d0 >> 32 ); + d2 += ( d1 >> 32 ); + d3 += ( d2 >> 32 ); + acc0 = (uint32_t) d0; + acc1 = (uint32_t) d1; + acc2 = (uint32_t) d2; + acc3 = (uint32_t) d3; + acc4 = (uint32_t) ( d3 >> 32 ) + acc4; + + d0 = (uint64_t) acc0 + ( acc4 >> 2 ) + ( acc4 & 0xFFFFFFFCU ); + acc4 &= 3U; + acc0 = (uint32_t) d0; + d0 = (uint64_t) acc1 + ( d0 >> 32U ); + acc1 = (uint32_t) d0; + d0 = (uint64_t) acc2 + ( d0 >> 32U ); + acc2 = (uint32_t) d0; + d0 = (uint64_t) acc3 + ( d0 >> 32U ); + acc3 = (uint32_t) d0; + d0 = (uint64_t) acc4 + ( d0 >> 32U ); + acc4 = (uint32_t) d0; + + offset += POLY1305_BLOCK_SIZE_BYTES; + } + + ctx->acc[0] = acc0; + ctx->acc[1] = acc1; + ctx->acc[2] = acc2; + ctx->acc[3] = acc3; + ctx->acc[4] = acc4; +} + +/** + * \brief Compute the Poly1305 MAC + * + * \param ctx The Poly1305 context. + * \param mac The buffer to where the MAC is written. Must be + * big enough to contain the 16-byte MAC. + */ +static void poly1305_compute_mac( const mbedtls_poly1305_context *ctx, + unsigned char mac[16] ) +{ + uint64_t d; + uint32_t g0, g1, g2, g3, g4; + uint32_t acc0, acc1, acc2, acc3, acc4; + uint32_t mask; + uint32_t mask_inv; + + acc0 = ctx->acc[0]; + acc1 = ctx->acc[1]; + acc2 = ctx->acc[2]; + acc3 = ctx->acc[3]; + acc4 = ctx->acc[4]; + + /* Before adding 's' we ensure that the accumulator is mod 2^130 - 5. + * We do this by calculating acc - (2^130 - 5), then checking if + * the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5) + */ + + /* Calculate acc + -(2^130 - 5) */ + d = ( (uint64_t) acc0 + 5U ); + g0 = (uint32_t) d; + d = ( (uint64_t) acc1 + ( d >> 32 ) ); + g1 = (uint32_t) d; + d = ( (uint64_t) acc2 + ( d >> 32 ) ); + g2 = (uint32_t) d; + d = ( (uint64_t) acc3 + ( d >> 32 ) ); + g3 = (uint32_t) d; + g4 = acc4 + (uint32_t) ( d >> 32U ); + + /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */ + mask = (uint32_t) 0U - ( g4 >> 2U ); + mask_inv = ~mask; + + /* If 131st bit is set then acc=g, otherwise, acc is unmodified */ + acc0 = ( acc0 & mask_inv ) | ( g0 & mask ); + acc1 = ( acc1 & mask_inv ) | ( g1 & mask ); + acc2 = ( acc2 & mask_inv ) | ( g2 & mask ); + acc3 = ( acc3 & mask_inv ) | ( g3 & mask ); + + /* Add 's' */ + d = (uint64_t) acc0 + ctx->s[0]; + acc0 = (uint32_t) d; + d = (uint64_t) acc1 + ctx->s[1] + ( d >> 32U ); + acc1 = (uint32_t) d; + d = (uint64_t) acc2 + ctx->s[2] + ( d >> 32U ); + acc2 = (uint32_t) d; + acc3 += ctx->s[3] + (uint32_t) ( d >> 32U ); + + /* Compute MAC (128 least significant bits of the accumulator) */ + mac[ 0] = (unsigned char)( acc0 ); + mac[ 1] = (unsigned char)( acc0 >> 8 ); + mac[ 2] = (unsigned char)( acc0 >> 16 ); + mac[ 3] = (unsigned char)( acc0 >> 24 ); + mac[ 4] = (unsigned char)( acc1 ); + mac[ 5] = (unsigned char)( acc1 >> 8 ); + mac[ 6] = (unsigned char)( acc1 >> 16 ); + mac[ 7] = (unsigned char)( acc1 >> 24 ); + mac[ 8] = (unsigned char)( acc2 ); + mac[ 9] = (unsigned char)( acc2 >> 8 ); + mac[10] = (unsigned char)( acc2 >> 16 ); + mac[11] = (unsigned char)( acc2 >> 24 ); + mac[12] = (unsigned char)( acc3 ); + mac[13] = (unsigned char)( acc3 >> 8 ); + mac[14] = (unsigned char)( acc3 >> 16 ); + mac[15] = (unsigned char)( acc3 >> 24 ); +} + +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ) +{ + POLY1305_VALIDATE( ctx != NULL ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); +} + +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); +} + +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ) +{ + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( key != NULL ); + + /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ + ctx->r[0] = BYTES_TO_U32_LE( key, 0 ) & 0x0FFFFFFFU; + ctx->r[1] = BYTES_TO_U32_LE( key, 4 ) & 0x0FFFFFFCU; + ctx->r[2] = BYTES_TO_U32_LE( key, 8 ) & 0x0FFFFFFCU; + ctx->r[3] = BYTES_TO_U32_LE( key, 12 ) & 0x0FFFFFFCU; + + ctx->s[0] = BYTES_TO_U32_LE( key, 16 ); + ctx->s[1] = BYTES_TO_U32_LE( key, 20 ); + ctx->s[2] = BYTES_TO_U32_LE( key, 24 ); + ctx->s[3] = BYTES_TO_U32_LE( key, 28 ); + + /* Initial accumulator state */ + ctx->acc[0] = 0U; + ctx->acc[1] = 0U; + ctx->acc[2] = 0U; + ctx->acc[3] = 0U; + ctx->acc[4] = 0U; + + /* Queue initially empty */ + mbedtls_platform_zeroize( ctx->queue, sizeof( ctx->queue ) ); + ctx->queue_len = 0U; + + return( 0 ); +} + +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + size_t offset = 0U; + size_t remaining = ilen; + size_t queue_free_len; + size_t nblocks; + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ( remaining > 0U ) && ( ctx->queue_len > 0U ) ) + { + queue_free_len = ( POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); + + if( ilen < queue_free_len ) + { + /* Not enough data to complete the block. + * Store this data with the other leftovers. + */ + memcpy( &ctx->queue[ctx->queue_len], + input, + ilen ); + + ctx->queue_len += ilen; + + remaining = 0U; + } + else + { + /* Enough data to produce a complete block */ + memcpy( &ctx->queue[ctx->queue_len], + input, + queue_free_len ); + + ctx->queue_len = 0U; + + poly1305_process( ctx, 1U, ctx->queue, 1U ); /* add padding bit */ + + offset += queue_free_len; + remaining -= queue_free_len; + } + } + + if( remaining >= POLY1305_BLOCK_SIZE_BYTES ) + { + nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES; + + poly1305_process( ctx, nblocks, &input[offset], 1U ); + + offset += nblocks * POLY1305_BLOCK_SIZE_BYTES; + remaining %= POLY1305_BLOCK_SIZE_BYTES; + } + + if( remaining > 0U ) + { + /* Store partial block */ + ctx->queue_len = remaining; + memcpy( ctx->queue, &input[offset], remaining ); + } + + return( 0 ); +} + +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ) +{ + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( mac != NULL ); + + /* Process any leftover data */ + if( ctx->queue_len > 0U ) + { + /* Add padding bit */ + ctx->queue[ctx->queue_len] = 1U; + ctx->queue_len++; + + /* Pad with zeroes */ + memset( &ctx->queue[ctx->queue_len], + 0, + POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); + + poly1305_process( ctx, 1U, /* Process 1 block */ + ctx->queue, 0U ); /* Already padded above */ + } + + poly1305_compute_mac( ctx, mac ); + + return( 0 ); +} + +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ) +{ + mbedtls_poly1305_context ctx; + int ret; + POLY1305_VALIDATE_RET( key != NULL ); + POLY1305_VALIDATE_RET( mac != NULL ); + POLY1305_VALIDATE_RET( ilen == 0 || input != NULL ); + + mbedtls_poly1305_init( &ctx ); + + ret = mbedtls_poly1305_starts( &ctx, key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_update( &ctx, input, ilen ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_finish( &ctx, mac ); + +cleanup: + mbedtls_poly1305_free( &ctx ); + return( ret ); +} + +#endif /* MBEDTLS_POLY1305_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_keys[2][32] = +{ + { + 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, + 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, + 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, + 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b + }, + { + 0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, + 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0, + 0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, + 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0 + } +}; + +static const unsigned char test_data[2][127] = +{ + { + 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f, + 0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f, + 0x75, 0x70 + }, + { + 0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72, + 0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f, + 0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20, + 0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, + 0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c, + 0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77, + 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, + 0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20, + 0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75, + 0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e + } +}; + +static const size_t test_data_len[2] = +{ + 34U, + 127U +}; + +static const unsigned char test_mac[2][16] = +{ + { + 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, + 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9 + }, + { + 0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61, + 0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62 + } +}; + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_poly1305_self_test( int verbose ) +{ + unsigned char mac[16]; + unsigned i; + int ret; + + for( i = 0U; i < 2U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " Poly1305 test %u ", i ); + + ret = mbedtls_poly1305_mac( test_keys[i], + test_data[i], + test_data_len[i], + mac ); + ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), ( "failed (mac)\n" ) ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_POLY1305_C */ diff --git a/external/mbedtls/library/ripemd160.c b/external/mbedtls/library/ripemd160.c new file mode 100644 index 0000000..d6ee933 --- /dev/null +++ b/external/mbedtls/library/ripemd160.c @@ -0,0 +1,590 @@ +/* + * RIPE MD-160 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * The RIPEMD-160 algorithm was designed by RIPE in 1996 + * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html + * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + +#include "mbedtls/ripemd160.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_RIPEMD160_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) ); +} + +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) ); +} + +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ) +{ + *dst = *src; +} + +/* + * RIPEMD-160 context setup + */ +int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) +{ + mbedtls_ripemd160_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) +/* + * Process one block + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; + } local; + + GET_UINT32_LE( local.X[ 0], data, 0 ); + GET_UINT32_LE( local.X[ 1], data, 4 ); + GET_UINT32_LE( local.X[ 2], data, 8 ); + GET_UINT32_LE( local.X[ 3], data, 12 ); + GET_UINT32_LE( local.X[ 4], data, 16 ); + GET_UINT32_LE( local.X[ 5], data, 20 ); + GET_UINT32_LE( local.X[ 6], data, 24 ); + GET_UINT32_LE( local.X[ 7], data, 28 ); + GET_UINT32_LE( local.X[ 8], data, 32 ); + GET_UINT32_LE( local.X[ 9], data, 36 ); + GET_UINT32_LE( local.X[10], data, 40 ); + GET_UINT32_LE( local.X[11], data, 44 ); + GET_UINT32_LE( local.X[12], data, 48 ); + GET_UINT32_LE( local.X[13], data, 52 ); + GET_UINT32_LE( local.X[14], data, 56 ); + GET_UINT32_LE( local.X[15], data, 60 ); + + local.A = local.Ap = ctx->state[0]; + local.B = local.Bp = ctx->state[1]; + local.C = local.Cp = ctx->state[2]; + local.D = local.Dp = ctx->state[3]; + local.E = local.Ep = ctx->state[4]; + +#define F1( x, y, z ) ( (x) ^ (y) ^ (z) ) +#define F2( x, y, z ) ( ( (x) & (y) ) | ( ~(x) & (z) ) ) +#define F3( x, y, z ) ( ( (x) | ~(y) ) ^ (z) ) +#define F4( x, y, z ) ( ( (x) & (z) ) | ( (y) & ~(z) ) ) +#define F5( x, y, z ) ( (x) ^ ( (y) | ~(z) ) ) + +#define S( x, n ) ( ( (x) << (n) ) | ( (x) >> (32 - (n)) ) ) + +#define P( a, b, c, d, e, r, s, f, k ) \ + do \ + { \ + (a) += f( (b), (c), (d) ) + local.X[r] + (k); \ + (a) = S( (a), (s) ) + (e); \ + (c) = S( (c), 10 ); \ + } while( 0 ) + +#define P2( a, b, c, d, e, r, s, rp, sp ) \ + do \ + { \ + P( (a), (b), (c), (d), (e), (r), (s), F, K ); \ + P( a ## p, b ## p, c ## p, d ## p, e ## p, \ + (rp), (sp), Fp, Kp ); \ + } while( 0 ) + +#define F F1 +#define K 0x00000000 +#define Fp F5 +#define Kp 0x50A28BE6 + P2( local.A, local.B, local.C, local.D, local.E, 0, 11, 5, 8 ); + P2( local.E, local.A, local.B, local.C, local.D, 1, 14, 14, 9 ); + P2( local.D, local.E, local.A, local.B, local.C, 2, 15, 7, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 3, 12, 0, 11 ); + P2( local.B, local.C, local.D, local.E, local.A, 4, 5, 9, 13 ); + P2( local.A, local.B, local.C, local.D, local.E, 5, 8, 2, 15 ); + P2( local.E, local.A, local.B, local.C, local.D, 6, 7, 11, 15 ); + P2( local.D, local.E, local.A, local.B, local.C, 7, 9, 4, 5 ); + P2( local.C, local.D, local.E, local.A, local.B, 8, 11, 13, 7 ); + P2( local.B, local.C, local.D, local.E, local.A, 9, 13, 6, 7 ); + P2( local.A, local.B, local.C, local.D, local.E, 10, 14, 15, 8 ); + P2( local.E, local.A, local.B, local.C, local.D, 11, 15, 8, 11 ); + P2( local.D, local.E, local.A, local.B, local.C, 12, 6, 1, 14 ); + P2( local.C, local.D, local.E, local.A, local.B, 13, 7, 10, 14 ); + P2( local.B, local.C, local.D, local.E, local.A, 14, 9, 3, 12 ); + P2( local.A, local.B, local.C, local.D, local.E, 15, 8, 12, 6 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F2 +#define K 0x5A827999 +#define Fp F4 +#define Kp 0x5C4DD124 + P2( local.E, local.A, local.B, local.C, local.D, 7, 7, 6, 9 ); + P2( local.D, local.E, local.A, local.B, local.C, 4, 6, 11, 13 ); + P2( local.C, local.D, local.E, local.A, local.B, 13, 8, 3, 15 ); + P2( local.B, local.C, local.D, local.E, local.A, 1, 13, 7, 7 ); + P2( local.A, local.B, local.C, local.D, local.E, 10, 11, 0, 12 ); + P2( local.E, local.A, local.B, local.C, local.D, 6, 9, 13, 8 ); + P2( local.D, local.E, local.A, local.B, local.C, 15, 7, 5, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 3, 15, 10, 11 ); + P2( local.B, local.C, local.D, local.E, local.A, 12, 7, 14, 7 ); + P2( local.A, local.B, local.C, local.D, local.E, 0, 12, 15, 7 ); + P2( local.E, local.A, local.B, local.C, local.D, 9, 15, 8, 12 ); + P2( local.D, local.E, local.A, local.B, local.C, 5, 9, 12, 7 ); + P2( local.C, local.D, local.E, local.A, local.B, 2, 11, 4, 6 ); + P2( local.B, local.C, local.D, local.E, local.A, 14, 7, 9, 15 ); + P2( local.A, local.B, local.C, local.D, local.E, 11, 13, 1, 13 ); + P2( local.E, local.A, local.B, local.C, local.D, 8, 12, 2, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F3 +#define K 0x6ED9EBA1 +#define Fp F3 +#define Kp 0x6D703EF3 + P2( local.D, local.E, local.A, local.B, local.C, 3, 11, 15, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 10, 13, 5, 7 ); + P2( local.B, local.C, local.D, local.E, local.A, 14, 6, 1, 15 ); + P2( local.A, local.B, local.C, local.D, local.E, 4, 7, 3, 11 ); + P2( local.E, local.A, local.B, local.C, local.D, 9, 14, 7, 8 ); + P2( local.D, local.E, local.A, local.B, local.C, 15, 9, 14, 6 ); + P2( local.C, local.D, local.E, local.A, local.B, 8, 13, 6, 6 ); + P2( local.B, local.C, local.D, local.E, local.A, 1, 15, 9, 14 ); + P2( local.A, local.B, local.C, local.D, local.E, 2, 14, 11, 12 ); + P2( local.E, local.A, local.B, local.C, local.D, 7, 8, 8, 13 ); + P2( local.D, local.E, local.A, local.B, local.C, 0, 13, 12, 5 ); + P2( local.C, local.D, local.E, local.A, local.B, 6, 6, 2, 14 ); + P2( local.B, local.C, local.D, local.E, local.A, 13, 5, 10, 13 ); + P2( local.A, local.B, local.C, local.D, local.E, 11, 12, 0, 13 ); + P2( local.E, local.A, local.B, local.C, local.D, 5, 7, 4, 7 ); + P2( local.D, local.E, local.A, local.B, local.C, 12, 5, 13, 5 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F4 +#define K 0x8F1BBCDC +#define Fp F2 +#define Kp 0x7A6D76E9 + P2( local.C, local.D, local.E, local.A, local.B, 1, 11, 8, 15 ); + P2( local.B, local.C, local.D, local.E, local.A, 9, 12, 6, 5 ); + P2( local.A, local.B, local.C, local.D, local.E, 11, 14, 4, 8 ); + P2( local.E, local.A, local.B, local.C, local.D, 10, 15, 1, 11 ); + P2( local.D, local.E, local.A, local.B, local.C, 0, 14, 3, 14 ); + P2( local.C, local.D, local.E, local.A, local.B, 8, 15, 11, 14 ); + P2( local.B, local.C, local.D, local.E, local.A, 12, 9, 15, 6 ); + P2( local.A, local.B, local.C, local.D, local.E, 4, 8, 0, 14 ); + P2( local.E, local.A, local.B, local.C, local.D, 13, 9, 5, 6 ); + P2( local.D, local.E, local.A, local.B, local.C, 3, 14, 12, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 7, 5, 2, 12 ); + P2( local.B, local.C, local.D, local.E, local.A, 15, 6, 13, 9 ); + P2( local.A, local.B, local.C, local.D, local.E, 14, 8, 9, 12 ); + P2( local.E, local.A, local.B, local.C, local.D, 5, 6, 7, 5 ); + P2( local.D, local.E, local.A, local.B, local.C, 6, 5, 10, 15 ); + P2( local.C, local.D, local.E, local.A, local.B, 2, 12, 14, 8 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F5 +#define K 0xA953FD4E +#define Fp F1 +#define Kp 0x00000000 + P2( local.B, local.C, local.D, local.E, local.A, 4, 9, 12, 8 ); + P2( local.A, local.B, local.C, local.D, local.E, 0, 15, 15, 5 ); + P2( local.E, local.A, local.B, local.C, local.D, 5, 5, 10, 12 ); + P2( local.D, local.E, local.A, local.B, local.C, 9, 11, 4, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 7, 6, 1, 12 ); + P2( local.B, local.C, local.D, local.E, local.A, 12, 8, 5, 5 ); + P2( local.A, local.B, local.C, local.D, local.E, 2, 13, 8, 14 ); + P2( local.E, local.A, local.B, local.C, local.D, 10, 12, 7, 6 ); + P2( local.D, local.E, local.A, local.B, local.C, 14, 5, 6, 8 ); + P2( local.C, local.D, local.E, local.A, local.B, 1, 12, 2, 13 ); + P2( local.B, local.C, local.D, local.E, local.A, 3, 13, 13, 6 ); + P2( local.A, local.B, local.C, local.D, local.E, 8, 14, 14, 5 ); + P2( local.E, local.A, local.B, local.C, local.D, 11, 11, 0, 15 ); + P2( local.D, local.E, local.A, local.B, local.C, 6, 8, 3, 13 ); + P2( local.C, local.D, local.E, local.A, local.B, 15, 5, 9, 11 ); + P2( local.B, local.C, local.D, local.E, local.A, 13, 6, 11, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + + local.C = ctx->state[1] + local.C + local.Dp; + ctx->state[1] = ctx->state[2] + local.D + local.Ep; + ctx->state[2] = ctx->state[3] + local.E + local.Ap; + ctx->state[3] = ctx->state[4] + local.A + local.Bp; + ctx->state[4] = ctx->state[0] + local.B + local.Cp; + ctx->state[0] = local.C; + + /* Zeroise variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_ripemd160_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ + +/* + * RIPEMD-160 process buffer + */ +int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_ripemd160_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_ripemd160_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_ripemd160_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char ripemd160_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * RIPEMD-160 final digest + */ +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) +{ + int ret; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + ret = mbedtls_ripemd160_update_ret( ctx, ripemd160_padding, padn ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ripemd160_update_ret( ctx, msglen, 8 ); + if( ret != 0 ) + return( ret ); + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + PUT_UINT32_LE( ctx->state[4], output, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) +{ + mbedtls_ripemd160_finish_ret( ctx, output ); +} +#endif + +#endif /* ! MBEDTLS_RIPEMD160_ALT */ + +/* + * output = RIPEMD-160( input buffer ) + */ +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + int ret; + mbedtls_ripemd160_context ctx; + + mbedtls_ripemd160_init( &ctx ); + + if( ( ret = mbedtls_ripemd160_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_ripemd160_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + mbedtls_ripemd160_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * Test vectors from the RIPEMD-160 paper and + * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC + */ +#define TESTS 8 +static const unsigned char ripemd160_test_str[TESTS][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890" }, +}; + +static const size_t ripemd160_test_strlen[TESTS] = +{ + 0, 1, 3, 14, 26, 56, 62, 80 +}; + +static const unsigned char ripemd160_test_md[TESTS][20] = +{ + { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, + 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }, + { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, + 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }, + { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, + 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }, + { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, + 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }, + { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, + 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }, + { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, + 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }, + { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, + 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 }, + { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, + 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }, +}; + +/* + * Checkup routine + */ +int mbedtls_ripemd160_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char output[20]; + + memset( output, 0, sizeof output ); + + for( i = 0; i < TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " RIPEMD-160 test #%d: ", i + 1 ); + + ret = mbedtls_ripemd160_ret( ripemd160_test_str[i], + ripemd160_test_strlen[i], output ); + if( ret != 0 ) + goto fail; + + if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RIPEMD160_C */ diff --git a/external/mbedtls/library/rsa.c b/external/mbedtls/library/rsa.c new file mode 100644 index 0000000..c8c23db --- /dev/null +++ b/external/mbedtls/library/rsa.c @@ -0,0 +1,2791 @@ +/* + * The RSA public-key cryptosystem + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * The following sources were referenced in the design of this implementation + * of the RSA algorithm: + * + * [1] A method for obtaining digital signatures and public-key cryptosystems + * R Rivest, A Shamir, and L Adleman + * http://people.csail.mit.edu/rivest/pubs.html#RSA78 + * + * [2] Handbook of Applied Cryptography - 1997, Chapter 8 + * Menezes, van Oorschot and Vanstone + * + * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks + * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and + * Stefan Mangard + * https://arxiv.org/abs/1702.08719v2 + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/rsa_internal.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PKCS1_V21) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if !defined(MBEDTLS_RSA_ALT) + +/* Parameter validation macros */ +#define RSA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) +#define RSA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_PKCS1_V15) +/* constant-time buffer comparison */ +static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + const unsigned char *A = (const unsigned char *) a; + const unsigned char *B = (const unsigned char *) b; + unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + diff |= A[i] ^ B[i]; + + return( diff ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ) +{ + int ret; + RSA_VALIDATE_RET( ctx != NULL ); + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + + if( N != NULL ) + ctx->len = mbedtls_mpi_size( &ctx->N ); + + return( 0 ); +} + +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ) +{ + int ret = 0; + RSA_VALIDATE_RET( ctx != NULL ); + + if( N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) ); + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) ); + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + + return( 0 ); +} + +/* + * Checks whether the context fields are set in such a way + * that the RSA primitives will be able to execute without error. + * It does *not* make guarantees for consistency of the parameters. + */ +static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv, + int blinding_needed ) +{ +#if !defined(MBEDTLS_RSA_NO_CRT) + /* blinding_needed is only used for NO_CRT to decide whether + * P,Q need to be present or not. */ + ((void) blinding_needed); +#endif + + if( ctx->len != mbedtls_mpi_size( &ctx->N ) || + ctx->len > MBEDTLS_MPI_MAX_SIZE ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + /* + * 1. Modular exponentiation needs positive, odd moduli. + */ + + /* Modular exponentiation wrt. N is always used for + * RSA public key operations. */ + if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Modular exponentiation for P and Q is only + * used for private key operations and if CRT + * is used. */ + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* !MBEDTLS_RSA_NO_CRT */ + + /* + * 2. Exponents must be positive + */ + + /* Always need E for public key operations */ + if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* For private key operations, use D or DP & DQ + * as (unblinded) exponents. */ + if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); +#else + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Blinding shouldn't make exponents negative either, + * so check that P, Q >= 1 if that hasn't yet been + * done as part of 1. */ +#if defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && blinding_needed && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + /* It wouldn't lead to an error if it wasn't satisfied, + * but check for QP >= 1 nonetheless. */ +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && + mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + return( 0 ); +} + +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) +{ + int ret = 0; + int have_N, have_P, have_Q, have_D, have_E; +#if !defined(MBEDTLS_RSA_NO_CRT) + int have_DP, have_DQ, have_QP; +#endif + int n_missing, pq_missing, d_missing, is_pub, is_priv; + + RSA_VALIDATE_RET( ctx != NULL ); + + have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 ); + have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 ); + have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 ); + have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); + have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 ); + have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 ); + have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 ); +#endif + + /* + * Check whether provided parameters are enough + * to deduce all others. The following incomplete + * parameter sets for private keys are supported: + * + * (1) P, Q missing. + * (2) D and potentially N missing. + * + */ + + n_missing = have_P && have_Q && have_D && have_E; + pq_missing = have_N && !have_P && !have_Q && have_D && have_E; + d_missing = have_P && have_Q && !have_D && have_E; + is_pub = have_N && !have_P && !have_Q && !have_D && have_E; + + /* These three alternatives are mutually exclusive */ + is_priv = n_missing || pq_missing || d_missing; + + if( !is_priv && !is_pub ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Step 1: Deduce N if P, Q are provided. + */ + + if( !have_N && have_P && have_Q ) + { + if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, + &ctx->Q ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + /* + * Step 2: Deduce and verify all remaining core parameters. + */ + + if( pq_missing ) + { + ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D, + &ctx->P, &ctx->Q ); + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + + } + else if( d_missing ) + { + if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P, + &ctx->Q, + &ctx->E, + &ctx->D ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + } + + /* + * Step 3: Deduce all additional parameters specific + * to our current RSA implementation. + */ + +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && ! ( have_DP && have_DQ && have_QP ) ) + { + ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ); + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* + * Step 3: Basic sanity checks + */ + + return( rsa_check_context( ctx, is_priv, 1 ) ); +} + +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ) +{ + int ret = 0; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + if( N != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) ); + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) ); + +cleanup: + + return( ret ); +} + +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ) +{ + int ret; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + /* Export all requested core parameters. */ + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Export CRT parameters + * This must also be implemented if CRT is not used, for being able to + * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt + * can be used in this case. + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Export all requested blinding parameters. */ + if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) || + ( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) || + ( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#else + if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + DP, DQ, QP ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#endif + + return( 0 ); +} + +/* + * Initialize an RSA context + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id ) +{ + RSA_VALIDATE( ctx != NULL ); + RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 || + padding == MBEDTLS_RSA_PKCS_V21 ); + + memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); + + mbedtls_rsa_set_padding( ctx, padding, hash_id ); + +#if defined(MBEDTLS_THREADING_C) + /* Set ctx->ver to nonzero to indicate that the mutex has been + * initialized and will need to be freed. */ + ctx->ver = 1; + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Set padding for an existing RSA context + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id ) +{ + RSA_VALIDATE( ctx != NULL ); + RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 || + padding == MBEDTLS_RSA_PKCS_V21 ); + + ctx->padding = padding; + ctx->hash_id = hash_id; +} + +/* + * Get length in bytes of RSA modulus + */ + +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ) +{ + return( ctx->len ); +} + + +#if defined(MBEDTLS_GENPRIME) + +/* + * Generate an RSA keypair + * + * This generation method follows the RSA key pair generation procedure of + * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ) +{ + int ret; + mbedtls_mpi H, G, L; + int prime_quality = 0; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( f_rng != NULL ); + + /* + * If the modulus is 1024 bit long or shorter, then the security strength of + * the RSA algorithm is less than or equal to 80 bits and therefore an error + * rate of 2^-80 is sufficient. + */ + if( nbits > 1024 ) + prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR; + + mbedtls_mpi_init( &H ); + mbedtls_mpi_init( &G ); + mbedtls_mpi_init( &L ); + + if( nbits < 128 || exponent < 3 || nbits % 2 != 0 ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + /* + * find primes P and Q with Q < P so that: + * 1. |P-Q| > 2^( nbits / 2 - 100 ) + * 2. GCD( E, (P-1)*(Q-1) ) == 1 + * 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); + + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, + prime_quality, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, + prime_quality, f_rng, p_rng ) ); + + /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) ); + if( mbedtls_mpi_bitlen( &H ) <= ( ( nbits >= 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) ) + continue; + + /* not required by any standards, but some users rely on the fact that P > Q */ + if( H.s < 0 ) + mbedtls_mpi_swap( &ctx->P, &ctx->Q ); + + /* Temporarily replace P,Q by P-1, Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) ); + + /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + continue; + + /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->P, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L, NULL, &H, &G ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &L ) ); + + if( mbedtls_mpi_bitlen( &ctx->D ) <= ( ( nbits + 1 ) / 2 ) ) // (FIPS 186-4 §B.3.1 criterion 3(a)) + continue; + + break; + } + while( 1 ); + + /* Restore P,Q */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); + + ctx->len = mbedtls_mpi_size( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* + * DP = D mod (P - 1) + * DQ = D mod (Q - 1) + * QP = Q^-1 mod P + */ + MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Double-check */ + MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) ); + +cleanup: + + mbedtls_mpi_free( &H ); + mbedtls_mpi_free( &G ); + mbedtls_mpi_free( &L ); + + if( ret != 0 ) + { + mbedtls_rsa_free( ctx ); + if( ( -ret & ~0x7f ) == 0 ) + ret = MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret; + return( ret ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_GENPRIME */ + +/* + * Check a public RSA key + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + if( mbedtls_mpi_bitlen( &ctx->N ) < 128 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 || + mbedtls_mpi_bitlen( &ctx->E ) < 2 || + mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Check for the consistency of all fields in an RSA private key context + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + + if( mbedtls_rsa_check_pubkey( ctx ) != 0 || + rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q, + &ctx->D, &ctx->E, NULL, NULL ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } +#endif + + return( 0 ); +} + +/* + * Check if contexts holding a public and private key match + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ) +{ + RSA_VALIDATE_RET( pub != NULL ); + RSA_VALIDATE_RET( prv != NULL ); + + if( mbedtls_rsa_check_pubkey( pub ) != 0 || + mbedtls_rsa_check_privkey( prv ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || + mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Do an RSA public key operation + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + mbedtls_mpi T; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Generate or update blinding values, see section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count = 0; + mbedtls_mpi R; + + mbedtls_mpi_init( &R ); + + if( ctx->Vf.p != NULL ) + { + /* We already have blinding values, just update them by squaring */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); + + goto cleanup; + } + + /* Unblinding value: Vf = random number, invertible mod N */ + do { + if( count++ > 10 ) + { + ret = MBEDTLS_ERR_RSA_RNG_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); + + /* Compute Vf^-1 as R * (R Vf)^-1 to avoid leaks from inv_mod. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, ctx->len - 1, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* At this point, Vi is invertible mod N if and only if both Vf and R + * are invertible mod N. If one of them isn't, we don't need to know + * which one, we just loop and choose new values for both of them. + * (Each iteration succeeds with overwhelming probability.) */ + ret = mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vi, &ctx->N ); + if( ret != 0 && ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + } while( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + /* Finish the computation of Vf^-1 = R * (R Vf)^-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* Blinding value: Vi = Vf^(-e) mod N + * (Vi already contains Vf^-1 at this point) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); + + +cleanup: + mbedtls_mpi_free( &R ); + + return( ret ); +} + +/* + * Exponent blinding supposed to prevent side-channel attacks using multiple + * traces of measurements to recover the RSA key. The more collisions are there, + * the more bits of the key can be recovered. See [3]. + * + * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) + * observations on avarage. + * + * For example with 28 byte blinding to achieve 2 collisions the adversary has + * to make 2^112 observations on avarage. + * + * (With the currently (as of 2017 April) known best algorithms breaking 2048 + * bit RSA requires approximately as much time as trying out 2^112 random keys. + * Thus in this sense with 28 byte blinding the security is not reduced by + * side-channel attacks like the one in [3]) + * + * This countermeasure does not help if the key recovery is possible with a + * single trace. + */ +#define RSA_EXPONENT_BLINDING 28 + +/* + * Do an RSA private key operation + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + + /* Temporary holding the result */ + mbedtls_mpi T; + + /* Temporaries holding P-1, Q-1 and the + * exponent blinding factor, respectively. */ + mbedtls_mpi P1, Q1, R; + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Temporaries holding the results mod p resp. mod q. */ + mbedtls_mpi TP, TQ; + + /* Temporaries holding the blinded exponents for + * the mod p resp. mod q computation (if used). */ + mbedtls_mpi DP_blind, DQ_blind; + + /* Pointers to actual exponents to be used - either the unblinded + * or the blinded ones, depending on the presence of a PRNG. */ + mbedtls_mpi *DP = &ctx->DP; + mbedtls_mpi *DQ = &ctx->DQ; +#else + /* Temporary holding the blinded exponent (if used). */ + mbedtls_mpi D_blind; + + /* Pointer to actual exponent to be used - either the unblinded + * or the blinded one, depending on the presence of a PRNG. */ + mbedtls_mpi *D = &ctx->D; +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Temporaries holding the initial input and the double + * checked result; should be the same in the end. */ + mbedtls_mpi I, C; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); + + if( rsa_check_context( ctx, 1 /* private key checks */, + f_rng != NULL /* blinding y/n */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* MPI Initialization */ + mbedtls_mpi_init( &T ); + + mbedtls_mpi_init( &P1 ); + mbedtls_mpi_init( &Q1 ); + mbedtls_mpi_init( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &D_blind ); +#else + mbedtls_mpi_init( &DP_blind ); + mbedtls_mpi_init( &DQ_blind ); +#endif + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ ); +#endif + + mbedtls_mpi_init( &I ); + mbedtls_mpi_init( &C ); + + /* End of MPI initialization */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) ); + + if( f_rng != NULL ) + { + /* + * Blinding + * T = T * Vi mod N + */ + MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + + /* + * Exponent blinding + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* + * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); + + D = &D_blind; +#else + /* + * DP_blind = ( P - 1 ) * R + DP + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, + &ctx->DP ) ); + + DP = &DP_blind; + + /* + * DQ_blind = ( Q - 1 ) * R + DQ + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, + &ctx->DQ ) ); + + DQ = &DQ_blind; +#endif /* MBEDTLS_RSA_NO_CRT */ + } + +#if defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); +#else + /* + * Faster decryption using the CRT + * + * TP = input ^ dP mod P + * TQ = input ^ dQ mod Q + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) ); + + /* + * T = (TP - TQ) * (Q^-1 mod P) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) ); + + /* + * T = TQ + T * Q + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + if( f_rng != NULL ) + { + /* + * Unblind + * T = T * Vf mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + } + + /* Verify the result to prevent glitching attacks. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E, + &ctx->N, &ctx->RN ) ); + if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &P1 ); + mbedtls_mpi_free( &Q1 ); + mbedtls_mpi_free( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &D_blind ); +#else + mbedtls_mpi_free( &DP_blind ); + mbedtls_mpi_free( &DQ_blind ); +#endif + } + + mbedtls_mpi_free( &T ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ ); +#endif + + mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &I ); + + if( ret != 0 && ret >= -0x007f ) + return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); + + return( ret ); +} + +#if defined(MBEDTLS_PKCS1_V21) +/** + * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. + * + * \param dst buffer to mask + * \param dlen length of destination buffer + * \param src source of the mask generation + * \param slen length of the source buffer + * \param md_ctx message digest context to use + */ +static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, + size_t slen, mbedtls_md_context_t *md_ctx ) +{ + unsigned char mask[MBEDTLS_MD_MAX_SIZE]; + unsigned char counter[4]; + unsigned char *p; + unsigned int hlen; + size_t i, use_len; + int ret = 0; + + memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); + memset( counter, 0, 4 ); + + hlen = mbedtls_md_get_size( md_ctx->md_info ); + + /* Generate and apply dbMask */ + p = dst; + + while( dlen > 0 ) + { + use_len = hlen; + if( dlen < hlen ) + use_len = dlen; + + if( ( ret = mbedtls_md_starts( md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, src, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, counter, 4 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( md_ctx, mask ) ) != 0 ) + goto exit; + + for( i = 0; i < use_len; ++i ) + *p++ ^= mask[i]; + + counter[3]++; + + dlen -= use_len; + } + +exit: + mbedtls_platform_zeroize( mask, sizeof( mask ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t olen; + int ret; + unsigned char *p = output; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + hlen = mbedtls_md_get_size( md_info ); + + /* first comparison checks for overflow */ + if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + memset( output, 0, olen ); + + *p++ = 0; + + /* Generate a random octet string seed */ + if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + p += hlen; + + /* Construct DB */ + if( ( ret = mbedtls_md( md_info, label, label_len, p ) ) != 0 ) + return( ret ); + p += hlen; + p += olen - 2 * hlen - 2 - ilen; + *p++ = 1; + memcpy( p, input, ilen ); + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + /* maskedSeed: Apply seedMask to seed */ + if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, + &md_ctx ) ) != 0 ) + goto exit; + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t nb_pad, olen; + int ret; + unsigned char *p = output; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + /* first comparison checks for overflow */ + if( ilen + 11 < ilen || olen < ilen + 11 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad = olen - 3 - ilen; + + *p++ = 0; + if( mode == MBEDTLS_RSA_PUBLIC ) + { + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + *p++ = MBEDTLS_RSA_CRYPT; + + while( nb_pad-- > 0 ) + { + int rng_dl = 100; + + do { + ret = f_rng( p_rng, p, 1 ); + } while( *p == 0 && --rng_dl && ret == 0 ); + + /* Check if RNG failed to generate data */ + if( rng_dl == 0 || ret != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + p++; + } + } + else + { + *p++ = MBEDTLS_RSA_SIGN; + + while( nb_pad-- > 0 ) + *p++ = 0xFF; + } + + *p++ = 0; + memcpy( p, input, ilen ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Add the message padding, then do an RSA operation + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, + input, output ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, + ilen, input, output ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret; + size_t ilen, i, pad_len; + unsigned char *p, bad, pad_done; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + /* + * Parameters sanity checks + */ + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + // checking for integer underflow + if( 2 * hlen + 2 > ilen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * RSA operation + */ + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + /* + * Unmask data and generate lHash + */ + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + /* seed: Apply seedMask to maskedSeed */ + if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, + &md_ctx ) ) != 0 || + /* DB: Apply dbMask to maskedDB */ + ( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, + &md_ctx ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + mbedtls_md_free( &md_ctx ); + + /* Generate lHash */ + if( ( ret = mbedtls_md( md_info, label, label_len, lhash ) ) != 0 ) + goto cleanup; + + /* + * Check contents, in "constant-time" + */ + p = buf; + bad = 0; + + bad |= *p++; /* First byte must be 0 */ + + p += hlen; /* Skip seed */ + + /* Check lHash */ + for( i = 0; i < hlen; i++ ) + bad |= lhash[i] ^ *p++; + + /* Get zero-padding len, but always read till end of buffer + * (minus one, for the 01 byte) */ + pad_len = 0; + pad_done = 0; + for( i = 0; i < ilen - 2 * hlen - 2; i++ ) + { + pad_done |= p[i]; + pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + p += pad_len; + bad |= *p++ ^ 0x01; + + /* + * The only information "leaked" is whether the padding was correct or not + * (eg, no data is copied if it was not correct). This meets the + * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between + * the different error conditions. + */ + if( bad != 0 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } + + if( ilen - ( p - buf ) > output_max_len ) + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + ret = 0; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( lhash, sizeof( lhash ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/** Turn zero-or-nonzero into zero-or-all-bits-one, without branches. + * + * \param value The value to analyze. + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +static unsigned all_or_nothing_int( unsigned value ) +{ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} + +/** Check whether a size is out of bounds, without branches. + * + * This is equivalent to `size > max`, but is likely to be compiled to + * to code using bitwise operation rather than a branch. + * + * \param size Size to check. + * \param max Maximum desired value for \p size. + * \return \c 0 if `size <= max`. + * \return \c 1 if `size > max`. + */ +static unsigned size_greater_than( size_t size, size_t max ) +{ + /* Return the sign bit (1 for negative) of (max - size). */ + return( ( max - size ) >> ( sizeof( size_t ) * 8 - 1 ) ); +} + +/** Choose between two integer values, without branches. + * + * This is equivalent to `cond ? if1 : if0`, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param cond Condition to test. + * \param if1 Value to use if \p cond is nonzero. + * \param if0 Value to use if \p cond is zero. + * \return \c if1 if \p cond is nonzero, otherwise \c if0. + */ +static unsigned if_int( unsigned cond, unsigned if1, unsigned if0 ) +{ + unsigned mask = all_or_nothing_int( cond ); + return( ( mask & if1 ) | (~mask & if0 ) ); +} + +/** Shift some data towards the left inside a buffer without leaking + * the length of the data through side channels. + * + * `mem_move_to_left(start, total, offset)` is functionally equivalent to + * ``` + * memmove(start, start + offset, total - offset); + * memset(start + offset, 0, total - offset); + * ``` + * but it strives to use a memory access pattern (and thus total timing) + * that does not depend on \p offset. This timing independence comes at + * the expense of performance. + * + * \param start Pointer to the start of the buffer. + * \param total Total size of the buffer. + * \param offset Offset from which to copy \p total - \p offset bytes. + */ +static void mem_move_to_left( void *start, + size_t total, + size_t offset ) +{ + volatile unsigned char *buf = start; + size_t i, n; + if( total == 0 ) + return; + for( i = 0; i < total; i++ ) + { + unsigned no_op = size_greater_than( total - offset, i ); + /* The first `total - offset` passes are a no-op. The last + * `offset` passes shift the data one byte to the left and + * zero out the last byte. */ + for( n = 0; n < total - 1; n++ ) + { + unsigned char current = buf[n]; + unsigned char next = buf[n+1]; + buf[n] = if_int( no_op, current, next ); + } + buf[total-1] = if_int( no_op, buf[total-1], 0 ); + } +} + +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret; + size_t ilen, i, plaintext_max_size; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + /* The following variables take sensitive values: their value must + * not leak into the observable behavior of the function other than + * the designated outputs (output, olen, return value). Otherwise + * this would open the execution of the function to + * side-channel-based variants of the Bleichenbacher padding oracle + * attack. Potential side channels include overall timing, memory + * access patterns (especially visible to an adversary who has access + * to a shared memory cache), and branches (especially visible to + * an adversary who has access to a shared code cache or to a shared + * branch predictor). */ + size_t pad_count = 0; + unsigned bad = 0; + unsigned char pad_done = 0; + size_t plaintext_size = 0; + unsigned output_too_large; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + ilen = ctx->len; + plaintext_max_size = ( output_max_len > ilen - 11 ? + ilen - 11 : + output_max_len ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + /* Check and get padding length in constant time and constant + * memory trace. The first byte must be 0. */ + bad |= buf[0]; + + if( mode == MBEDTLS_RSA_PRIVATE ) + { + /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 + * where PS must be at least 8 nonzero bytes. */ + bad |= buf[1] ^ MBEDTLS_RSA_CRYPT; + + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. */ + for( i = 2; i < ilen; i++ ) + { + pad_done |= ((buf[i] | (unsigned char)-buf[i]) >> 7) ^ 1; + pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + } + else + { + /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00 + * where PS must be at least 8 bytes with the value 0xFF. */ + bad |= buf[1] ^ MBEDTLS_RSA_SIGN; + + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. + * If there's a non-0xff byte in the padding, the padding is bad. */ + for( i = 2; i < ilen; i++ ) + { + pad_done |= if_int( buf[i], 0, 1 ); + pad_count += if_int( pad_done, 0, 1 ); + bad |= if_int( pad_done, 0, buf[i] ^ 0xFF ); + } + } + + /* If pad_done is still zero, there's no data, only unfinished padding. */ + bad |= if_int( pad_done, 0, 1 ); + + /* There must be at least 8 bytes of padding. */ + bad |= size_greater_than( 8, pad_count ); + + /* If the padding is valid, set plaintext_size to the number of + * remaining bytes after stripping the padding. If the padding + * is invalid, avoid leaking this fact through the size of the + * output: use the maximum message size that fits in the output + * buffer. Do it without branches to avoid leaking the padding + * validity through timing. RSA keys are small enough that all the + * size_t values involved fit in unsigned int. */ + plaintext_size = if_int( bad, + (unsigned) plaintext_max_size, + (unsigned) ( ilen - pad_count - 3 ) ); + + /* Set output_too_large to 0 if the plaintext fits in the output + * buffer and to 1 otherwise. */ + output_too_large = size_greater_than( plaintext_size, + plaintext_max_size ); + + /* Set ret without branches to avoid timing attacks. Return: + * - INVALID_PADDING if the padding is bad (bad != 0). + * - OUTPUT_TOO_LARGE if the padding is good but the decrypted + * plaintext does not fit in the output buffer. + * - 0 if the padding is correct. */ + ret = - (int) if_int( bad, - MBEDTLS_ERR_RSA_INVALID_PADDING, + if_int( output_too_large, - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE, + 0 ) ); + + /* If the padding is bad or the plaintext is too large, zero the + * data that we're about to copy to the output buffer. + * We need to copy the same amount of data + * from the same buffer whether the padding is good or not to + * avoid leaking the padding validity through overall timing or + * through memory or cache access patterns. */ + bad = all_or_nothing_int( bad | output_too_large ); + for( i = 11; i < ilen; i++ ) + buf[i] &= ~bad; + + /* If the plaintext is too large, truncate it to the buffer size. + * Copy anyway to avoid revealing the length through timing, because + * revealing the length is as bad as revealing the padding validity + * for a Bleichenbacher attack. */ + plaintext_size = if_int( output_too_large, + (unsigned) plaintext_max_size, + (unsigned) plaintext_size ); + + /* Move the plaintext to the leftmost position where it can start in + * the working buffer, i.e. make it start plaintext_max_size from + * the end of the buffer. Do this with a memory access trace that + * does not depend on the plaintext size. After this move, the + * starting location of the plaintext is no longer sensitive + * information. */ + mem_move_to_left( buf + ilen - plaintext_max_size, + plaintext_max_size, + plaintext_max_size - plaintext_size ); + + /* Finally copy the decrypted plaintext plus trailing zeros + * into the output buffer. */ + memcpy( output, buf + ilen - plaintext_max_size, plaintext_max_size ); + + /* Report the amount of data we copied to the output buffer. In case + * of errors (bad padding or output too large), the value of *olen + * when this function returns is not specified. Making it equivalent + * to the good case limits the risks of leaking the padding validity. */ + *olen = plaintext_size; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation, then remove the message padding + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, + input, output, output_max_len ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, + olen, input, output, + output_max_len ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t olen; + unsigned char *p = sig; + unsigned char salt[MBEDTLS_MD_MAX_SIZE]; + size_t slen, min_slen, hlen, offset = 0; + int ret; + size_t msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + /* Calculate the largest possible salt length. Normally this is the hash + * length, which is the maximum length the salt can have. If there is not + * enough room, use the maximum salt length that fits. The constraint is + * that the hash length plus the salt length plus 2 bytes must be at most + * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017 + * (PKCS#1 v2.2) §9.1.1 step 3. */ + min_slen = hlen - 2; + if( olen < hlen + min_slen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + else if( olen >= hlen + hlen + 2 ) + slen = hlen; + else + slen = olen - hlen - 2; + + memset( sig, 0, olen ); + + /* Generate salt of length slen */ + if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + p += olen - hlen - slen - 2; + *p++ = 0x01; + memcpy( p, salt, slen ); + p += slen; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* Generate H = Hash( M' ) */ + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 ) + goto exit; + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + offset = 1; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + sig[0] &= 0xFF >> ( olen * 8 - msb ); + + p += hlen; + *p++ = 0xBC; + + mbedtls_platform_zeroize( salt, sizeof( salt ) ); + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, sig ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function + */ + +/* Construct a PKCS v1.5 encoding of a hashed message + * + * This is used both for signature generation and verification. + * + * Parameters: + * - md_alg: Identifies the hash algorithm used to generate the given hash; + * MBEDTLS_MD_NONE if raw data is signed. + * - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE. + * - hash: Buffer containing the hashed message or the raw data. + * - dst_len: Length of the encoded message. + * - dst: Buffer to hold the encoded message. + * + * Assumptions: + * - hash has size hashlen if md_alg == MBEDTLS_MD_NONE. + * - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE. + * - dst points to a buffer of size at least dst_len. + * + */ +static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + size_t dst_len, + unsigned char *dst ) +{ + size_t oid_size = 0; + size_t nb_pad = dst_len; + unsigned char *p = dst; + const char *oid = NULL; + + /* Are we signing hashed or raw data? */ + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + + /* Double-check that 8 + hashlen + oid_size can be used as a + * 1-byte ASN.1 length encoding and that there's no overflow. */ + if( 8 + hashlen + oid_size >= 0x80 || + 10 + hashlen < hashlen || + 10 + hashlen + oid_size < 10 + hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Static bounds check: + * - Need 10 bytes for five tag-length pairs. + * (Insist on 1-byte length encodings to protect against variants of + * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) + * - Need hashlen bytes for hash + * - Need oid_size bytes for hash alg OID. + */ + if( nb_pad < 10 + hashlen + oid_size ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 10 + hashlen + oid_size; + } + else + { + if( nb_pad < hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad -= hashlen; + } + + /* Need space for signature header and padding delimiter (3 bytes), + * and 8 bytes for the minimal padding */ + if( nb_pad < 3 + 8 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 3; + + /* Now nb_pad is the amount of memory to be filled + * with padding, and at least 8 bytes long. */ + + /* Write signature header and padding */ + *p++ = 0; + *p++ = MBEDTLS_RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + /* Are we signing raw data? */ + if( md_alg == MBEDTLS_MD_NONE ) + { + memcpy( p, hash, hashlen ); + return( 0 ); + } + + /* Signing hashed data, add corresponding ASN.1 structure + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * Digest ::= OCTET STRING + * + * Schematic: + * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] + * TAG-NULL + LEN [ NULL ] ] + * TAG-OCTET + LEN [ HASH ] ] + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = (unsigned char) oid_size; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = (unsigned char) hashlen; + memcpy( p, hash, hashlen ); + p += hashlen; + + /* Just a sanity-check, should be automatic + * after the initial bounds check. */ + if( p != dst + dst_len ) + { + mbedtls_platform_zeroize( dst, dst_len ); + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + int ret; + unsigned char *sig_try = NULL, *verif = NULL; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare PKCS1-v1.5 encoding (padding and hash identifier) + */ + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, + ctx->len, sig ) ) != 0 ) + return( ret ); + + /* + * Call respective RSA primitive + */ + + if( mode == MBEDTLS_RSA_PUBLIC ) + { + /* Skip verification on a public key operation */ + return( mbedtls_rsa_public( ctx, sig, sig ) ); + } + + /* Private key operation + * + * In order to prevent Lenstra's attack, make the signature in a + * temporary buffer and check it before returning it. + */ + + sig_try = mbedtls_calloc( 1, ctx->len ); + if( sig_try == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + verif = mbedtls_calloc( 1, ctx->len ); + if( verif == NULL ) + { + mbedtls_free( sig_try ); + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + } + + MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); + + if( mbedtls_safer_memcmp( verif, sig, ctx->len ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; + goto cleanup; + } + + memcpy( sig, sig_try, ctx->len ); + +cleanup: + mbedtls_free( sig_try ); + mbedtls_free( verif ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ) +{ + int ret; + size_t siglen; + unsigned char *p; + unsigned char *hash_start; + unsigned char result[MBEDTLS_MD_MAX_SIZE]; + unsigned char zeros[8]; + unsigned int hlen; + size_t observed_salt_len, msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( buf[siglen - 1] != 0xBC ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( mgf1_hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + memset( zeros, 0, 8 ); + + /* + * Note: EMSA-PSS verification is over the length of N - 1 bits + */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + + if( buf[0] >> ( 8 - siglen * 8 + msb ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + { + p++; + siglen -= 1; + } + + if( siglen < hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + hash_start = p + siglen - hlen - 1; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx ); + if( ret != 0 ) + goto exit; + + buf[0] &= 0xFF >> ( siglen * 8 - msb ); + + while( p < hash_start - 1 && *p == 0 ) + p++; + + if( *p++ != 0x01 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + observed_salt_len = hash_start - p; + + if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && + observed_salt_len != (size_t) expected_salt_len ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + /* + * Generate H = Hash( M' ) + */ + ret = mbedtls_md_starts( &md_ctx ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, zeros, 8 ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, hash, hashlen ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, p, observed_salt_len ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_finish( &md_ctx, result ); + if ( ret != 0 ) + goto exit; + + if( memcmp( hash_start, result, hlen ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto exit; + } + +exit: + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +/* + * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + mbedtls_md_type_t mgf1_hash_id; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) + ? (mbedtls_md_type_t) ctx->hash_id + : md_alg; + + return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode, + md_alg, hashlen, hash, + mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, + sig ) ); + +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + int ret = 0; + size_t sig_len; + unsigned char *encoded = NULL, *encoded_expected = NULL; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + sig_len = ctx->len; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare expected PKCS1 v1.5 encoding of hash. + */ + + if( ( encoded = mbedtls_calloc( 1, sig_len ) ) == NULL || + ( encoded_expected = mbedtls_calloc( 1, sig_len ) ) == NULL ) + { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto cleanup; + } + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len, + encoded_expected ) ) != 0 ) + goto cleanup; + + /* + * Apply RSA primitive to get what should be PKCS1 encoded hash. + */ + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, encoded ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, encoded ); + if( ret != 0 ) + goto cleanup; + + /* + * Compare + */ + + if( ( ret = mbedtls_safer_memcmp( encoded, encoded_expected, + sig_len ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + + if( encoded != NULL ) + { + mbedtls_platform_zeroize( encoded, sig_len ); + mbedtls_free( encoded ); + } + + if( encoded_expected != NULL ) + { + mbedtls_platform_zeroize( encoded_expected, sig_len ); + mbedtls_free( encoded_expected ); + } + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation and check the message digest + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +/* + * Copy the components of an RSA key + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) +{ + int ret; + RSA_VALIDATE_RET( dst != NULL ); + RSA_VALIDATE_RET( src != NULL ); + + dst->len = src->len; + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); + + dst->padding = src->padding; + dst->hash_id = src->hash_id; + +cleanup: + if( ret != 0 ) + mbedtls_rsa_free( dst ); + + return( ret ); +} + +/* + * Free the components of an RSA key + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->RN ); + mbedtls_mpi_free( &ctx->D ); + mbedtls_mpi_free( &ctx->Q ); + mbedtls_mpi_free( &ctx->P ); + mbedtls_mpi_free( &ctx->E ); + mbedtls_mpi_free( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &ctx->RQ ); + mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->QP ); + mbedtls_mpi_free( &ctx->DQ ); + mbedtls_mpi_free( &ctx->DP ); +#endif /* MBEDTLS_RSA_NO_CRT */ + +#if defined(MBEDTLS_THREADING_C) + /* Free the mutex, but only if it hasn't been freed already. */ + if( ctx->ver != 0 ) + { + mbedtls_mutex_free( &ctx->mutex ); + ctx->ver = 0; + } +#endif +} + +#endif /* !MBEDTLS_RSA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#include "mbedtls/sha1.h" + +/* + * Example RSA-1024 keypair, for test purposes + */ +#define KEY_LEN 128 + +#define RSA_N "9292758453063D803DD603D5E777D788" \ + "8ED1D5BF35786190FA2F23EBC0848AEA" \ + "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ + "7130B9CED7ACDF54CFC7555AC14EEBAB" \ + "93A89813FBF3C4F8066D2D800F7C38A8" \ + "1AE31942917403FF4946B0A83D3D3E05" \ + "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ + "5E94BB77B07507233A0BC7BAC8F90F79" + +#define RSA_E "10001" + +#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ + "66CA472BC44D253102F8B4A9D3BFA750" \ + "91386C0077937FE33FA3252D28855837" \ + "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ + "DF79C5CE07EE72C7F123142198164234" \ + "CABB724CF78B8173B9F880FC86322407" \ + "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ + "071513A1E85B5DFA031F21ECAE91A34D" + +#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ + "2C01CAD19EA484A87EA4377637E75500" \ + "FCB2005C5C7DD6EC4AC023CDA285D796" \ + "C3D9E75E1EFC42488BB4F1D13AC30A57" + +#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ + "E211C2B9E5DB1ED0BF61D0D9899620F4" \ + "910E4168387E3C30AA1E00C339A79508" \ + "8452DD96A9A5EA5D9DCA68DA636032AF" + +#define PT_LEN 24 +#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ + "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" + +#if defined(MBEDTLS_PKCS1_V15) +static int myrand( void *rng_state, unsigned char *output, size_t len ) +{ +#if !defined(__OpenBSD__) && !defined(__NetBSD__) + size_t i; + + if( rng_state != NULL ) + rng_state = NULL; + + for( i = 0; i < len; ++i ) + output[i] = rand(); +#else + if( rng_state != NULL ) + rng_state = NULL; + + arc4random_buf( output, len ); +#endif /* !OpenBSD && !NetBSD */ + + return( 0 ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Checkup routine + */ +int mbedtls_rsa_self_test( int verbose ) +{ + int ret = 0; +#if defined(MBEDTLS_PKCS1_V15) + size_t len; + mbedtls_rsa_context rsa; + unsigned char rsa_plaintext[PT_LEN]; + unsigned char rsa_decrypted[PT_LEN]; + unsigned char rsa_ciphertext[KEY_LEN]; +#if defined(MBEDTLS_SHA1_C) + unsigned char sha1sum[20]; +#endif + + mbedtls_mpi K; + + mbedtls_mpi_init( &K ); + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) ); + + MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) ); + + if( verbose != 0 ) + mbedtls_printf( " RSA key validation: " ); + + if( mbedtls_rsa_check_pubkey( &rsa ) != 0 || + mbedtls_rsa_check_privkey( &rsa ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 encryption : " ); + + memcpy( rsa_plaintext, RSA_PT, PT_LEN ); + + if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, + PT_LEN, rsa_plaintext, + rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 decryption : " ); + + if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, + &len, rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +#if defined(MBEDTLS_SHA1_C) + if( verbose != 0 ) + mbedtls_printf( " PKCS#1 data sign : " ); + + if( mbedtls_sha1_ret( rsa_plaintext, PT_LEN, sha1sum ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, + MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); + + if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, + MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* MBEDTLS_SHA1_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +cleanup: + mbedtls_mpi_free( &K ); + mbedtls_rsa_free( &rsa ); +#else /* MBEDTLS_PKCS1_V15 */ + ((void) verbose); +#endif /* MBEDTLS_PKCS1_V15 */ + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RSA_C */ diff --git a/external/mbedtls/library/rsa_internal.c b/external/mbedtls/library/rsa_internal.c new file mode 100644 index 0000000..4d94ca6 --- /dev/null +++ b/external/mbedtls/library/rsa_internal.c @@ -0,0 +1,517 @@ +/* + * Helper functions for the RSA module + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/bignum.h" +#include "mbedtls/rsa_internal.h" + +/* + * Compute RSA prime factors from public and private exponents + * + * Summary of algorithm: + * Setting F := lcm(P-1,Q-1), the idea is as follows: + * + * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2) + * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the + * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four + * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1) + * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime + * factors of N. + * + * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same + * construction still applies since (-)^K is the identity on the set of + * roots of 1 in Z/NZ. + * + * The public and private key primitives (-)^E and (-)^D are mutually inverse + * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e. + * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L. + * Splitting L = 2^t * K with K odd, we have + * + * DE - 1 = FL = (F/2) * (2^(t+1)) * K, + * + * so (F / 2) * K is among the numbers + * + * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord + * + * where ord is the order of 2 in (DE - 1). + * We can therefore iterate through these numbers apply the construction + * of (a) and (b) above to attempt to factor N. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, + mbedtls_mpi const *E, mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ) +{ + int ret = 0; + + uint16_t attempt; /* Number of current attempt */ + uint16_t iter; /* Number of squares computed in the current attempt */ + + uint16_t order; /* Order of 2 in DE - 1 */ + + mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */ + mbedtls_mpi K; /* Temporary holding the current candidate */ + + const unsigned char primes[] = { 2, + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251 + }; + + const size_t num_primes = sizeof( primes ) / sizeof( *primes ); + + if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || + mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + /* + * Initializations and temporary changes + */ + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &T ); + + /* T := DE - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &T, &T, 1 ) ); + + if( ( order = (uint16_t) mbedtls_mpi_lsb( &T ) ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + /* After this operation, T holds the largest odd divisor of DE - 1. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &T, order ) ); + + /* + * Actual work + */ + + /* Skip trying 2 if N == 1 mod 8 */ + attempt = 0; + if( N->p[0] % 8 == 1 ) + attempt = 1; + + for( ; attempt < num_primes; ++attempt ) + { + mbedtls_mpi_lset( &K, primes[attempt] ); + + /* Check if gcd(K,N) = 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + if( mbedtls_mpi_cmp_int( P, 1 ) != 0 ) + continue; + + /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ... + * and check whether they have nontrivial GCD with N. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &K, &K, &T, N, + Q /* temporarily use Q for storing Montgomery + * multiplication helper values */ ) ); + + for( iter = 1; iter <= order; ++iter ) + { + /* If we reach 1 prematurely, there's no point + * in continuing to square K */ + if( mbedtls_mpi_cmp_int( &K, 1 ) == 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + + if( mbedtls_mpi_cmp_int( P, 1 ) == 1 && + mbedtls_mpi_cmp_mpi( P, N ) == -1 ) + { + /* + * Have found a nontrivial divisor P of N. + * Set Q := N / P. + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( Q, NULL, N, P ) ); + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &K ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, N ) ); + } + + /* + * If we get here, then either we prematurely aborted the loop because + * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must + * be 1 if D,E,N were consistent. + * Check if that's the case and abort if not, to avoid very long, + * yet eventually failing, computations if N,D,E were not sane. + */ + if( mbedtls_mpi_cmp_int( &K, 1 ) != 0 ) + { + break; + } + } + + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &T ); + return( ret ); +} + +/* + * Given P, Q and the public exponent E, deduce D. + * This is essentially a modular inversion. + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ) +{ + int ret = 0; + mbedtls_mpi K, L; + + if( D == NULL || mbedtls_mpi_cmp_int( D, 0 ) != 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 0 ) == 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Temporarily put K := P-1 and L := Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + + /* Temporarily put D := gcd(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( D, &K, &L ) ); + + /* K := LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &L ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &K, NULL, &K, D ) ); + + /* Compute modular inverse of E in LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( D, E, &K ) ); + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that RSA CRT parameters are in accordance with core parameters. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ) +{ + int ret = 0; + + mbedtls_mpi K, L; + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Check that DP - D == 0 mod P - 1 */ + if( DP != NULL ) + { + if( P == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that DQ - D == 0 mod Q - 1 */ + if( DQ != NULL ) + { + if( Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that QP * Q - 1 == 0 mod P */ + if( QP != NULL ) + { + if( P == NULL || Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && + ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && + ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that core RSA parameters are sane. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = 0; + mbedtls_mpi K, L; + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* + * Step 1: If PRNG provided, check that P and Q are prime + */ + +#if defined(MBEDTLS_GENPRIME) + /* + * When generating keys, the strongest security we support aims for an error + * rate of at most 2^-100 and we are aiming for the same certainty here as + * well. + */ + if( f_rng != NULL && P != NULL && + ( ret = mbedtls_mpi_is_prime_ext( P, 50, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + if( f_rng != NULL && Q != NULL && + ( ret = mbedtls_mpi_is_prime_ext( Q, 50, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } +#else + ((void) f_rng); + ((void) p_rng); +#endif /* MBEDTLS_GENPRIME */ + + /* + * Step 2: Check that 1 < N = P * Q + */ + + if( P != NULL && Q != NULL && N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, P, Q ) ); + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( &K, N ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 3: Check and 1 < D, E < N if present. + */ + + if( N != NULL && D != NULL && E != NULL ) + { + if ( mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 4: Check that D, E are inverse modulo P-1 and Q-1 + */ + + if( P != NULL && Q != NULL && D != NULL && E != NULL ) + { + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod P-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + return( ret ); +} + +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = 0; + mbedtls_mpi K; + mbedtls_mpi_init( &K ); + + /* DP = D mod P-1 */ + if( DP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) ); + } + + /* DQ = D mod Q-1 */ + if( DQ != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) ); + } + + /* QP = Q^{-1} mod P */ + if( QP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) ); + } + +cleanup: + mbedtls_mpi_free( &K ); + + return( ret ); +} + +#endif /* MBEDTLS_RSA_C */ diff --git a/external/mbedtls/library/sha1.c b/external/mbedtls/library/sha1.c new file mode 100644 index 0000000..e99a5e8 --- /dev/null +++ b/external/mbedtls/library/sha1.c @@ -0,0 +1,606 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SHA1_C) + +#include "mbedtls/sha1.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA1_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA ) + +#define SHA1_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA1_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) +{ + SHA1_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ) +{ + SHA1_VALIDATE( dst != NULL ); + SHA1_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-1 context setup + */ +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ) +{ + SHA1_VALIDATE_RET( ctx != NULL ); + + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + mbedtls_sha1_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_SHA1_PROCESS_ALT) +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t temp, W[16], A, B, C, D, E; + } local; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (const unsigned char *)data != NULL ); + + GET_UINT32_BE( local.W[ 0], data, 0 ); + GET_UINT32_BE( local.W[ 1], data, 4 ); + GET_UINT32_BE( local.W[ 2], data, 8 ); + GET_UINT32_BE( local.W[ 3], data, 12 ); + GET_UINT32_BE( local.W[ 4], data, 16 ); + GET_UINT32_BE( local.W[ 5], data, 20 ); + GET_UINT32_BE( local.W[ 6], data, 24 ); + GET_UINT32_BE( local.W[ 7], data, 28 ); + GET_UINT32_BE( local.W[ 8], data, 32 ); + GET_UINT32_BE( local.W[ 9], data, 36 ); + GET_UINT32_BE( local.W[10], data, 40 ); + GET_UINT32_BE( local.W[11], data, 44 ); + GET_UINT32_BE( local.W[12], data, 48 ); + GET_UINT32_BE( local.W[13], data, 52 ); + GET_UINT32_BE( local.W[14], data, 56 ); + GET_UINT32_BE( local.W[15], data, 60 ); + +#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) + +#define R(t) \ + ( \ + local.temp = local.W[( (t) - 3 ) & 0x0F] ^ \ + local.W[( (t) - 8 ) & 0x0F] ^ \ + local.W[( (t) - 14 ) & 0x0F] ^ \ + local.W[ (t) & 0x0F], \ + ( local.W[(t) & 0x0F] = S(local.temp,1) ) \ + ) + +#define P(a,b,c,d,e,x) \ + do \ + { \ + (e) += S((a),5) + F((b),(c),(d)) + K + (x); \ + (b) = S((b),30); \ + } while( 0 ) + + local.A = ctx->state[0]; + local.B = ctx->state[1]; + local.C = ctx->state[2]; + local.D = ctx->state[3]; + local.E = ctx->state[4]; + +#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define K 0x5A827999 + + P( local.A, local.B, local.C, local.D, local.E, local.W[0] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[1] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[2] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[3] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[4] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[5] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[6] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[7] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[8] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[9] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[10] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[11] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[12] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[13] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[14] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[15] ); + P( local.E, local.A, local.B, local.C, local.D, R(16) ); + P( local.D, local.E, local.A, local.B, local.C, R(17) ); + P( local.C, local.D, local.E, local.A, local.B, R(18) ); + P( local.B, local.C, local.D, local.E, local.A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define K 0x6ED9EBA1 + + P( local.A, local.B, local.C, local.D, local.E, R(20) ); + P( local.E, local.A, local.B, local.C, local.D, R(21) ); + P( local.D, local.E, local.A, local.B, local.C, R(22) ); + P( local.C, local.D, local.E, local.A, local.B, R(23) ); + P( local.B, local.C, local.D, local.E, local.A, R(24) ); + P( local.A, local.B, local.C, local.D, local.E, R(25) ); + P( local.E, local.A, local.B, local.C, local.D, R(26) ); + P( local.D, local.E, local.A, local.B, local.C, R(27) ); + P( local.C, local.D, local.E, local.A, local.B, R(28) ); + P( local.B, local.C, local.D, local.E, local.A, R(29) ); + P( local.A, local.B, local.C, local.D, local.E, R(30) ); + P( local.E, local.A, local.B, local.C, local.D, R(31) ); + P( local.D, local.E, local.A, local.B, local.C, R(32) ); + P( local.C, local.D, local.E, local.A, local.B, R(33) ); + P( local.B, local.C, local.D, local.E, local.A, R(34) ); + P( local.A, local.B, local.C, local.D, local.E, R(35) ); + P( local.E, local.A, local.B, local.C, local.D, R(36) ); + P( local.D, local.E, local.A, local.B, local.C, R(37) ); + P( local.C, local.D, local.E, local.A, local.B, R(38) ); + P( local.B, local.C, local.D, local.E, local.A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define K 0x8F1BBCDC + + P( local.A, local.B, local.C, local.D, local.E, R(40) ); + P( local.E, local.A, local.B, local.C, local.D, R(41) ); + P( local.D, local.E, local.A, local.B, local.C, R(42) ); + P( local.C, local.D, local.E, local.A, local.B, R(43) ); + P( local.B, local.C, local.D, local.E, local.A, R(44) ); + P( local.A, local.B, local.C, local.D, local.E, R(45) ); + P( local.E, local.A, local.B, local.C, local.D, R(46) ); + P( local.D, local.E, local.A, local.B, local.C, R(47) ); + P( local.C, local.D, local.E, local.A, local.B, R(48) ); + P( local.B, local.C, local.D, local.E, local.A, R(49) ); + P( local.A, local.B, local.C, local.D, local.E, R(50) ); + P( local.E, local.A, local.B, local.C, local.D, R(51) ); + P( local.D, local.E, local.A, local.B, local.C, R(52) ); + P( local.C, local.D, local.E, local.A, local.B, R(53) ); + P( local.B, local.C, local.D, local.E, local.A, R(54) ); + P( local.A, local.B, local.C, local.D, local.E, R(55) ); + P( local.E, local.A, local.B, local.C, local.D, R(56) ); + P( local.D, local.E, local.A, local.B, local.C, R(57) ); + P( local.C, local.D, local.E, local.A, local.B, R(58) ); + P( local.B, local.C, local.D, local.E, local.A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define K 0xCA62C1D6 + + P( local.A, local.B, local.C, local.D, local.E, R(60) ); + P( local.E, local.A, local.B, local.C, local.D, R(61) ); + P( local.D, local.E, local.A, local.B, local.C, R(62) ); + P( local.C, local.D, local.E, local.A, local.B, R(63) ); + P( local.B, local.C, local.D, local.E, local.A, R(64) ); + P( local.A, local.B, local.C, local.D, local.E, R(65) ); + P( local.E, local.A, local.B, local.C, local.D, R(66) ); + P( local.D, local.E, local.A, local.B, local.C, R(67) ); + P( local.C, local.D, local.E, local.A, local.B, R(68) ); + P( local.B, local.C, local.D, local.E, local.A, R(69) ); + P( local.A, local.B, local.C, local.D, local.E, R(70) ); + P( local.E, local.A, local.B, local.C, local.D, R(71) ); + P( local.D, local.E, local.A, local.B, local.C, R(72) ); + P( local.C, local.D, local.E, local.A, local.B, R(73) ); + P( local.B, local.C, local.D, local.E, local.A, R(74) ); + P( local.A, local.B, local.C, local.D, local.E, R(75) ); + P( local.E, local.A, local.B, local.C, local.D, R(76) ); + P( local.D, local.E, local.A, local.B, local.C, R(77) ); + P( local.C, local.D, local.E, local.A, local.B, R(78) ); + P( local.B, local.C, local.D, local.E, local.A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += local.A; + ctx->state[1] += local.B; + ctx->state[2] += local.C; + ctx->state[3] += local.D; + ctx->state[4] += local.E; + + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha1_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ + +/* + * SHA-1 process buffer + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha1_update_ret( ctx, input, ilen ); +} +#endif + +/* + * SHA-1 final digest + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + int ret; + uint32_t used; + uint32_t high, low; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + mbedtls_sha1_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + int ret; + mbedtls_sha1_context ctx; + + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha1_init( &ctx ); + + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + mbedtls_sha1_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-1 test vectors + */ +static const unsigned char sha1_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha1_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha1_test_sum[3][20] = +{ + { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, + { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } +}; + +/* + * Checkup routine + */ +int mbedtls_sha1_self_test( int verbose ) +{ + int i, j, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + mbedtls_sha1_context ctx; + + mbedtls_sha1_init( &ctx ); + + /* + * SHA-1 + */ + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " SHA-1 test #%d: ", i + 1 ); + + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto fail; + + if( i == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha1_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha1_update_ret( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha1_finish_ret( &ctx, sha1sum ) ) != 0 ) + goto fail; + + if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA1_C */ diff --git a/external/mbedtls/library/sha256.c b/external/mbedtls/library/sha256.c new file mode 100644 index 0000000..75a8f8a --- /dev/null +++ b/external/mbedtls/library/sha256.c @@ -0,0 +1,638 @@ +/* + * FIPS-180-2 compliant SHA-256 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SHA256_C) + +#include "mbedtls/sha256.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA256_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA ) +#define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA256_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} while( 0 ) +#endif + +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) +{ + SHA256_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ) +{ + SHA256_VALIDATE( dst != NULL ); + SHA256_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-256 context setup + */ +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ) +{ + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); + + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is224 == 0 ) + { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } + else + { + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; + } + + ctx->is224 = is224; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ) +{ + mbedtls_sha256_starts_ret( ctx, is224 ); +} +#endif + +#if !defined(MBEDTLS_SHA256_PROCESS_ALT) +static const uint32_t K[] = +{ + 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, +}; + +#define SHR(x,n) (((x) & 0xFFFFFFFF) >> (n)) +#define ROTR(x,n) (SHR(x,n) | ((x) << (32 - (n)))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + +#define R(t) \ + ( \ + local.W[t] = S1(local.W[(t) - 2]) + local.W[(t) - 7] + \ + S0(local.W[(t) - 15]) + local.W[(t) - 16] \ + ) + +#define P(a,b,c,d,e,f,g,h,x,K) \ + do \ + { \ + local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ + local.temp2 = S2(a) + F0((a),(b),(c)); \ + (d) += local.temp1; (h) = local.temp1 + local.temp2; \ + } while( 0 ) + +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + } local; + + unsigned int i; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (const unsigned char *)data != NULL ); + + for( i = 0; i < 8; i++ ) + local.A[i] = ctx->state[i]; + +#if defined(MBEDTLS_SHA256_SMALLER) + for( i = 0; i < 64; i++ ) + { + if( i < 16 ) + GET_UINT32_BE( local.W[i], data, 4 * i ); + else + R( i ); + + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); + + local.temp1 = local.A[7]; local.A[7] = local.A[6]; + local.A[6] = local.A[5]; local.A[5] = local.A[4]; + local.A[4] = local.A[3]; local.A[3] = local.A[2]; + local.A[2] = local.A[1]; local.A[1] = local.A[0]; + local.A[0] = local.temp1; + } +#else /* MBEDTLS_SHA256_SMALLER */ + for( i = 0; i < 16; i++ ) + GET_UINT32_BE( local.W[i], data, 4 * i ); + + for( i = 0; i < 16; i += 8 ) + { + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i+0], K[i+0] ); + P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], + local.A[4], local.A[5], local.A[6], local.W[i+1], K[i+1] ); + P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], + local.A[3], local.A[4], local.A[5], local.W[i+2], K[i+2] ); + P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], + local.A[2], local.A[3], local.A[4], local.W[i+3], K[i+3] ); + P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], + local.A[1], local.A[2], local.A[3], local.W[i+4], K[i+4] ); + P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], + local.A[0], local.A[1], local.A[2], local.W[i+5], K[i+5] ); + P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], + local.A[7], local.A[0], local.A[1], local.W[i+6], K[i+6] ); + P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], + local.A[6], local.A[7], local.A[0], local.W[i+7], K[i+7] ); + } + + for( i = 16; i < 64; i += 8 ) + { + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], R(i+0), K[i+0] ); + P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], + local.A[4], local.A[5], local.A[6], R(i+1), K[i+1] ); + P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], + local.A[3], local.A[4], local.A[5], R(i+2), K[i+2] ); + P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], + local.A[2], local.A[3], local.A[4], R(i+3), K[i+3] ); + P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], + local.A[1], local.A[2], local.A[3], R(i+4), K[i+4] ); + P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], + local.A[0], local.A[1], local.A[2], R(i+5), K[i+5] ); + P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], + local.A[7], local.A[0], local.A[1], R(i+6), K[i+6] ); + P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], + local.A[6], local.A[7], local.A[0], R(i+7), K[i+7] ); + } +#endif /* MBEDTLS_SHA256_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += local.A[i]; + + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha256_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ + +/* + * SHA-256 process buffer + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha256_update_ret( ctx, input, ilen ); +} +#endif + +/* + * SHA-256 final digest + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + int ret; + uint32_t used; + uint32_t high, low; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + PUT_UINT32_BE( ctx->state[5], output, 20 ); + PUT_UINT32_BE( ctx->state[6], output, 24 ); + + if( ctx->is224 == 0 ) + PUT_UINT32_BE( ctx->state[7], output, 28 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + mbedtls_sha256_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA256_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) +{ + int ret; + mbedtls_sha256_context ctx; + + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha256_init( &ctx ); + + if( ( ret = mbedtls_sha256_starts_ret( &ctx, is224 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha256_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) +{ + mbedtls_sha256_ret( input, ilen, output, is224 ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha256_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha256_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha256_test_sum[6][32] = +{ + /* + * SHA-224 test vectors + */ + { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, + 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, + 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, + 0xE3, 0x6C, 0x9D, 0xA7 }, + { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, + 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, + 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, + 0x52, 0x52, 0x25, 0x25 }, + { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, + 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, + 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, + 0x4E, 0xE7, 0xAD, 0x67 }, + + /* + * SHA-256 test vectors + */ + { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, + { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, + { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } +}; + +/* + * Checkup routine + */ +int mbedtls_sha256_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha256sum[32]; + mbedtls_sha256_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha256_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); + + if( ( ret = mbedtls_sha256_starts_ret( &ctx, k ) ) != 0 ) + goto fail; + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha256_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + + } + else + { + ret = mbedtls_sha256_update_ret( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, sha256sum ) ) != 0 ) + goto fail; + + + if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha256_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA256_C */ diff --git a/external/mbedtls/library/sha512.c b/external/mbedtls/library/sha512.c new file mode 100644 index 0000000..986037a --- /dev/null +++ b/external/mbedtls/library/sha512.c @@ -0,0 +1,675 @@ +/* + * FIPS-180-2 compliant SHA-384/512 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The SHA-512 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SHA512_C) + +#include "mbedtls/sha512.h" +#include "mbedtls/platform_util.h" + +#if defined(_MSC_VER) || defined(__WATCOMC__) + #define UL64(x) x##ui64 +#else + #define UL64(x) x##ULL +#endif + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA512_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ) +#define SHA512_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA512_ALT) + +/* + * 64-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT64_BE +#define GET_UINT64_BE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) ] << 56 ) \ + | ( (uint64_t) (b)[(i) + 1] << 48 ) \ + | ( (uint64_t) (b)[(i) + 2] << 40 ) \ + | ( (uint64_t) (b)[(i) + 3] << 32 ) \ + | ( (uint64_t) (b)[(i) + 4] << 24 ) \ + | ( (uint64_t) (b)[(i) + 5] << 16 ) \ + | ( (uint64_t) (b)[(i) + 6] << 8 ) \ + | ( (uint64_t) (b)[(i) + 7] ); \ +} +#endif /* GET_UINT64_BE */ + +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 7] = (unsigned char) ( (n) ); \ +} +#endif /* PUT_UINT64_BE */ + +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) +{ + SHA512_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ) +{ + SHA512_VALIDATE( dst != NULL ); + SHA512_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-512 context setup + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ) +{ + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); + + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is384 == 0 ) + { + /* SHA-512 */ + ctx->state[0] = UL64(0x6A09E667F3BCC908); + ctx->state[1] = UL64(0xBB67AE8584CAA73B); + ctx->state[2] = UL64(0x3C6EF372FE94F82B); + ctx->state[3] = UL64(0xA54FF53A5F1D36F1); + ctx->state[4] = UL64(0x510E527FADE682D1); + ctx->state[5] = UL64(0x9B05688C2B3E6C1F); + ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); + ctx->state[7] = UL64(0x5BE0CD19137E2179); + } + else + { + /* SHA-384 */ + ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); + ctx->state[1] = UL64(0x629A292A367CD507); + ctx->state[2] = UL64(0x9159015A3070DD17); + ctx->state[3] = UL64(0x152FECD8F70E5939); + ctx->state[4] = UL64(0x67332667FFC00B31); + ctx->state[5] = UL64(0x8EB44A8768581511); + ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); + ctx->state[7] = UL64(0x47B5481DBEFA4FA4); + } + + ctx->is384 = is384; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ) +{ + mbedtls_sha512_starts_ret( ctx, is384 ); +} +#endif + +#if !defined(MBEDTLS_SHA512_PROCESS_ALT) + +/* + * Round constants + */ +static const uint64_t K[80] = +{ + UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), + UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), + UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), + UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), + UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), + UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), + UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), + UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), + UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), + UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), + UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), + UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), + UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), + UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), + UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), + UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), + UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), + UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), + UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), + UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), + UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), + UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), + UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), + UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), + UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), + UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), + UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), + UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), + UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), + UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), + UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), + UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), + UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), + UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), + UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), + UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), + UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), + UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), + UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), + UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) +}; + +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + int i; + struct + { + uint64_t temp1, temp2, W[80]; + uint64_t A, B, C, D, E, F, G, H; + } local; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (const unsigned char *)data != NULL ); + +#define SHR(x,n) ((x) >> (n)) +#define ROTR(x,n) (SHR((x),(n)) | ((x) << (64 - (n)))) + +#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) +#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) + +#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) + +#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + +#define P(a,b,c,d,e,f,g,h,x,K) \ + do \ + { \ + local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ + local.temp2 = S2(a) + F0((a),(b),(c)); \ + (d) += local.temp1; (h) = local.temp1 + local.temp2; \ + } while( 0 ) + + for( i = 0; i < 16; i++ ) + { + GET_UINT64_BE( local.W[i], data, i << 3 ); + } + + for( ; i < 80; i++ ) + { + local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] + + S0(local.W[i - 15]) + local.W[i - 16]; + } + + local.A = ctx->state[0]; + local.B = ctx->state[1]; + local.C = ctx->state[2]; + local.D = ctx->state[3]; + local.E = ctx->state[4]; + local.F = ctx->state[5]; + local.G = ctx->state[6]; + local.H = ctx->state[7]; + i = 0; + + do + { + P( local.A, local.B, local.C, local.D, local.E, + local.F, local.G, local.H, local.W[i], K[i] ); i++; + P( local.H, local.A, local.B, local.C, local.D, + local.E, local.F, local.G, local.W[i], K[i] ); i++; + P( local.G, local.H, local.A, local.B, local.C, + local.D, local.E, local.F, local.W[i], K[i] ); i++; + P( local.F, local.G, local.H, local.A, local.B, + local.C, local.D, local.E, local.W[i], K[i] ); i++; + P( local.E, local.F, local.G, local.H, local.A, + local.B, local.C, local.D, local.W[i], K[i] ); i++; + P( local.D, local.E, local.F, local.G, local.H, + local.A, local.B, local.C, local.W[i], K[i] ); i++; + P( local.C, local.D, local.E, local.F, local.G, + local.H, local.A, local.B, local.W[i], K[i] ); i++; + P( local.B, local.C, local.D, local.E, local.F, + local.G, local.H, local.A, local.W[i], K[i] ); i++; + } + while( i < 80 ); + + ctx->state[0] += local.A; + ctx->state[1] += local.B; + ctx->state[2] += local.C; + ctx->state[3] += local.D; + ctx->state[4] += local.E; + ctx->state[5] += local.F; + ctx->state[6] += local.G; + ctx->state[7] += local.H; + + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + mbedtls_internal_sha512_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ + +/* + * SHA-512 process buffer + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + unsigned int left; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = (unsigned int) (ctx->total[0] & 0x7F); + fill = 128 - left; + + ctx->total[0] += (uint64_t) ilen; + + if( ctx->total[0] < (uint64_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 128 ) + { + if( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 128; + ilen -= 128; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha512_update_ret( ctx, input, ilen ); +} +#endif + +/* + * SHA-512 final digest + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + int ret; + unsigned used; + uint64_t high, low; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 16 bytes remain for the length + */ + used = ctx->total[0] & 0x7F; + + ctx->buffer[used++] = 0x80; + + if( used <= 112 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 112 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 128 - used ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 112 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT64_BE( high, ctx->buffer, 112 ); + PUT_UINT64_BE( low, ctx->buffer, 120 ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + PUT_UINT64_BE( ctx->state[0], output, 0 ); + PUT_UINT64_BE( ctx->state[1], output, 8 ); + PUT_UINT64_BE( ctx->state[2], output, 16 ); + PUT_UINT64_BE( ctx->state[3], output, 24 ); + PUT_UINT64_BE( ctx->state[4], output, 32 ); + PUT_UINT64_BE( ctx->state[5], output, 40 ); + + if( ctx->is384 == 0 ) + { + PUT_UINT64_BE( ctx->state[6], output, 48 ); + PUT_UINT64_BE( ctx->state[7], output, 56 ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + mbedtls_sha512_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA512_ALT */ + +/* + * output = SHA-512( input buffer ) + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + int ret; + mbedtls_sha512_context ctx; + + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha512_init( &ctx ); + + if( ( ret = mbedtls_sha512_starts_ret( &ctx, is384 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha512_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + mbedtls_sha512_ret( input, ilen, output, is384 ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha512_test_buf[3][113] = +{ + { "abc" }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, + { "" } +}; + +static const size_t sha512_test_buflen[3] = +{ + 3, 112, 1000 +}; + +static const unsigned char sha512_test_sum[6][64] = +{ + /* + * SHA-384 test vectors + */ + { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, + 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, + 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, + 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, + 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, + 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 }, + { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, + 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, + 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, + 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, + 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, + 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 }, + { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, + 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, + 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, + 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, + 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, + 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, + + /* + * SHA-512 test vectors + */ + { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, + 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, + 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, + 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, + 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, + 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, + 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, + 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F }, + { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, + 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, + 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, + 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, + 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, + 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, + 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, + 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 }, + { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, + 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, + 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, + 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, + 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, + 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, + 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, + 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } +}; + +/* + * Checkup routine + */ +int mbedtls_sha512_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha512sum[64]; + mbedtls_sha512_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha512_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); + + if( ( ret = mbedtls_sha512_starts_ret( &ctx, k ) ) != 0 ) + goto fail; + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha512_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha512_update_ret( &ctx, sha512_test_buf[j], + sha512_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha512_finish_ret( &ctx, sha512sum ) ) != 0 ) + goto fail; + + if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha512_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA512_C */ diff --git a/external/mbedtls/library/ssl_cache.c b/external/mbedtls/library/ssl_cache.c new file mode 100644 index 0000000..1d2558a --- /dev/null +++ b/external/mbedtls/library/ssl_cache.c @@ -0,0 +1,352 @@ +/* + * SSL session cache implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_CACHE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_cache.h" + +#include + +void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ) +{ + memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) ); + + cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT; + cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &cache->mutex ); +#endif +} + +int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ) +{ + int ret = 1; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time( NULL ); +#endif + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur, *entry; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &cache->mutex ) != 0 ) + return( 1 ); +#endif + + cur = cache->chain; + entry = NULL; + + while( cur != NULL ) + { + entry = cur; + cur = cur->next; + +#if defined(MBEDTLS_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - entry->timestamp ) > cache->timeout ) + continue; +#endif + + if( session->ciphersuite != entry->session.ciphersuite || + session->compression != entry->session.compression || + session->id_len != entry->session.id_len ) + continue; + + if( memcmp( session->id, entry->session.id, + entry->session.id_len ) != 0 ) + continue; + + memcpy( session->master, entry->session.master, 48 ); + + session->verify_result = entry->session.verify_result; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * Restore peer certificate (without rest of the original chain) + */ + if( entry->peer_cert.p != NULL ) + { + if( ( session->peer_cert = mbedtls_calloc( 1, + sizeof(mbedtls_x509_crt) ) ) == NULL ) + { + ret = 1; + goto exit; + } + + mbedtls_x509_crt_init( session->peer_cert ); + if( mbedtls_x509_crt_parse( session->peer_cert, entry->peer_cert.p, + entry->peer_cert.len ) != 0 ) + { + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + ret = 1; + goto exit; + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + ret = 0; + goto exit; + } + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ) +{ + int ret = 1; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time( NULL ), oldest = 0; + mbedtls_ssl_cache_entry *old = NULL; +#endif + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur, *prv; + int count = 0; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &cache->mutex ) ) != 0 ) + return( ret ); +#endif + + cur = cache->chain; + prv = NULL; + + while( cur != NULL ) + { + count++; + +#if defined(MBEDTLS_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - cur->timestamp ) > cache->timeout ) + { + cur->timestamp = t; + break; /* expired, reuse this slot, update timestamp */ + } +#endif + + if( memcmp( session->id, cur->session.id, cur->session.id_len ) == 0 ) + break; /* client reconnected, keep timestamp for session id */ + +#if defined(MBEDTLS_HAVE_TIME) + if( oldest == 0 || cur->timestamp < oldest ) + { + oldest = cur->timestamp; + old = cur; + } +#endif + + prv = cur; + cur = cur->next; + } + + if( cur == NULL ) + { +#if defined(MBEDTLS_HAVE_TIME) + /* + * Reuse oldest entry if max_entries reached + */ + if( count >= cache->max_entries ) + { + if( old == NULL ) + { + ret = 1; + goto exit; + } + + cur = old; + } +#else /* MBEDTLS_HAVE_TIME */ + /* + * Reuse first entry in chain if max_entries reached, + * but move to last place + */ + if( count >= cache->max_entries ) + { + if( cache->chain == NULL ) + { + ret = 1; + goto exit; + } + + cur = cache->chain; + cache->chain = cur->next; + cur->next = NULL; + prv->next = cur; + } +#endif /* MBEDTLS_HAVE_TIME */ + else + { + /* + * max_entries not reached, create new entry + */ + cur = mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry) ); + if( cur == NULL ) + { + ret = 1; + goto exit; + } + + if( prv == NULL ) + cache->chain = cur; + else + prv->next = cur; + } + +#if defined(MBEDTLS_HAVE_TIME) + cur->timestamp = t; +#endif + } + + memcpy( &cur->session, session, sizeof( mbedtls_ssl_session ) ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * If we're reusing an entry, free its certificate first + */ + if( cur->peer_cert.p != NULL ) + { + mbedtls_free( cur->peer_cert.p ); + memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) ); + } + + /* + * Store peer certificate + */ + if( session->peer_cert != NULL ) + { + cur->peer_cert.p = mbedtls_calloc( 1, session->peer_cert->raw.len ); + if( cur->peer_cert.p == NULL ) + { + ret = 1; + goto exit; + } + + memcpy( cur->peer_cert.p, session->peer_cert->raw.p, + session->peer_cert->raw.len ); + cur->peer_cert.len = session->peer_cert->raw.len; + + cur->session.peer_cert = NULL; + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + ret = 0; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +#if defined(MBEDTLS_HAVE_TIME) +void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ) +{ + if( timeout < 0 ) timeout = 0; + + cache->timeout = timeout; +} +#endif /* MBEDTLS_HAVE_TIME */ + +void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ) +{ + if( max < 0 ) max = 0; + + cache->max_entries = max; +} + +void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ) +{ + mbedtls_ssl_cache_entry *cur, *prv; + + cur = cache->chain; + + while( cur != NULL ) + { + prv = cur; + cur = cur->next; + + mbedtls_ssl_session_free( &prv->session ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_free( prv->peer_cert.p ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + mbedtls_free( prv ); + } + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &cache->mutex ); +#endif + cache->chain = NULL; +} + +#endif /* MBEDTLS_SSL_CACHE_C */ diff --git a/external/mbedtls/library/ssl_ciphersuites.c b/external/mbedtls/library/ssl_ciphersuites.c new file mode 100644 index 0000000..090040e --- /dev/null +++ b/external/mbedtls/library/ssl_ciphersuites.c @@ -0,0 +1,2398 @@ +/** + * \file ssl_ciphersuites.c + * + * \brief SSL ciphersuites for mbed TLS + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#endif + +#include "mbedtls/ssl_ciphersuites.h" +#include "mbedtls/ssl.h" + +#include + +/* + * Ordered from most preferred to least preferred in terms of security. + * + * Current rule (except RC4 and 3DES, weak and null which come last): + * 1. By key exchange: + * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK + * 2. By key length and cipher: + * ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 + * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 + * 4. By hash function used when relevant + * 5. By key exchange/auth again: EC > non-EC + */ +static const int ciphersuite_preference[] = +{ +#if defined(MBEDTLS_SSL_CIPHERSUITES) + MBEDTLS_SSL_CIPHERSUITES, +#else + /* Chacha-Poly ephemeral suites */ + MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + + /* All AES-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + + /* All ARIA-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, + + /* All AES-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + + /* All ARIA-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, + + /* The PSK ephemeral suites */ + MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, + + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, + + /* The ECJPAKE suite */ + MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, + + /* All AES-256 suites */ + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 suites */ + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + + /* All ARIA-256 suites */ + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, + + /* All AES-128 suites */ + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 suites */ + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + + /* All ARIA-128 suites */ + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, + + /* The RSA PSK suites */ + MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, + + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, + + /* The PSK suites */ + MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, + MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, + + MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, + MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, + + /* 3DES suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, + + /* RC4 suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, + MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, + + /* Weak suites */ + MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, + + /* NULL suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, + + MBEDTLS_TLS_RSA_WITH_NULL_SHA256, + MBEDTLS_TLS_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_RSA_WITH_NULL_MD5, + MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, + MBEDTLS_TLS_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_PSK_WITH_NULL_SHA, + +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + 0 +}; + +static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = +{ +#if defined(MBEDTLS_CHACHAPOLY_C) && \ + defined(MBEDTLS_SHA256_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + { MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + { MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + { MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + { MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#endif /* MBEDTLS_CHACHAPOLY_C && + MBEDTLS_SHA256_C && + MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA", + MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA", + MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ +#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ + +#if defined(MBEDTLS_ARIA_C) + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384,MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#endif /* MBEDTLS_ARIA_C */ + + + { 0, "", + MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, + 0, 0, 0, 0, 0 } +}; + +#if defined(MBEDTLS_SSL_CIPHERSUITES) +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + return( ciphersuite_preference ); +} +#else +#define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ + sizeof( ciphersuite_definitions[0] ) +static int supported_ciphersuites[MAX_CIPHERSUITES]; +static int supported_init = 0; + +static int ciphersuite_is_removed( const mbedtls_ssl_ciphersuite_t *cs_info ) +{ + (void)cs_info; + +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + if( cs_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + return( 1 ); +#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ + +#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES) + if( cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_ECB || + cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_CBC ) + { + return( 1 ); + } +#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */ + + return( 0 ); +} + +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + /* + * On initial call filter out all ciphersuites not supported by current + * build based on presence in the ciphersuite_definitions. + */ + if( supported_init == 0 ) + { + const int *p; + int *q; + + for( p = ciphersuite_preference, q = supported_ciphersuites; + *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; + p++ ) + { + const mbedtls_ssl_ciphersuite_t *cs_info; + if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL && + !ciphersuite_is_removed( cs_info ) ) + { + *(q++) = *p; + } + } + *q = 0; + + supported_init = 1; + } + + return( supported_ciphersuites ); +} +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( + const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + if( NULL == ciphersuite_name ) + return( NULL ); + + while( cur->id != 0 ) + { + if( 0 == strcmp( cur->name, ciphersuite_name ) ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + while( cur->id != 0 ) + { + if( cur->id == ciphersuite ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); + + if( cur == NULL ) + return( "unknown" ); + + return( cur->name ); +} + +int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_string( ciphersuite_name ); + + if( cur == NULL ) + return( 0 ); + + return( cur->id ); +} + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( MBEDTLS_PK_ECKEY ); + + default: + return( MBEDTLS_PK_NONE ); + } +} + +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + default: + return( MBEDTLS_PK_NONE ); + } +} + +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/external/mbedtls/library/ssl_cli.c b/external/mbedtls/library/ssl_cli.c new file mode 100644 index 0000000..bd7f281 --- /dev/null +++ b/external/mbedtls/library/ssl_cli.c @@ -0,0 +1,3911 @@ +/* + * SSLv3/TLSv1 client-side functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_CLI_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" + +#include + +#include + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#include "mbedtls/platform_util.h" +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +static int ssl_write_hostname_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t hostname_len; + + *olen = 0; + + if( ssl->hostname == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding server name extension: %s", + ssl->hostname ) ); + + hostname_len = strlen( ssl->hostname ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, hostname_len + 9 ); + + /* + * Sect. 3, RFC 6066 (TLS Extensions Definitions) + * + * In order to provide any of the server names, clients MAY include an + * extension of type "server_name" in the (extended) client hello. The + * "extension_data" field of this extension SHALL contain + * "ServerNameList" where: + * + * struct { + * NameType name_type; + * select (name_type) { + * case host_name: HostName; + * } name; + * } ServerName; + * + * enum { + * host_name(0), (255) + * } NameType; + * + * opaque HostName<1..2^16-1>; + * + * struct { + * ServerName server_name_list<1..2^16-1> + * } ServerNameList; + * + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME ) & 0xFF ); + + *p++ = (unsigned char)( ( (hostname_len + 5) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( (hostname_len + 5) ) & 0xFF ); + + *p++ = (unsigned char)( ( (hostname_len + 3) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( (hostname_len + 3) ) & 0xFF ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF ); + *p++ = (unsigned char)( ( hostname_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( hostname_len ) & 0xFF ); + + memcpy( p, ssl->hostname, hostname_len ); + + *olen = hostname_len + 9; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + /* We're always including an TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the + * initial ClientHello, in which case also adding the renegotiation + * info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */ + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding renegotiation extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 + ssl->verify_data_len ); + + /* + * Secure renegotiation + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) + & 0xFF ); + + *p++ = 0x00; + *p++ = ( ssl->verify_data_len + 1 ) & 0xFF; + *p++ = ssl->verify_data_len & 0xFF; + + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + + *olen = 5 + ssl->verify_data_len; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Only if we handle at least one key exchange that needs signatures. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +static int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t sig_alg_len = 0; + const int *md; + +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) + unsigned char *sig_alg_list = buf + 6; +#endif + + *olen = 0; + + if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding signature_algorithms extension" ) ); + + if( ssl->conf->sig_hashes == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_len += 2; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_len += 2; +#endif + if( sig_alg_len > MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "length in bytes of sig-hash-alg extension too big" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + } + + /* Empty signature algorithms list, this is a configuration error. */ + if( sig_alg_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, sig_alg_len + 6 ); + + /* + * Prepare signature_algorithms extension (TLS 1.2) + */ + sig_alg_len = 0; + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA; +#endif + } + + /* + * enum { + * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), + * sha512(6), (255) + * } HashAlgorithm; + * + * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } + * SignatureAlgorithm; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2..2^16-2>; + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG ) & 0xFF ); + + *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF ); + + *olen = 6 + sig_alg_len; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + unsigned char *elliptic_curve_list = p + 6; + size_t elliptic_curve_len = 0; + const mbedtls_ecp_curve_info *info; + const mbedtls_ecp_group_id *grp_id; + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding supported_elliptic_curves extension" ) ); + + if( ssl->conf->curve_list == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + for( grp_id = ssl->conf->curve_list; + *grp_id != MBEDTLS_ECP_DP_NONE; + grp_id++ ) + { + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); + if( info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "invalid curve in ssl configuration" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + elliptic_curve_len += 2; + + if( elliptic_curve_len > MBEDTLS_SSL_MAX_CURVE_LIST_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "malformed supported_elliptic_curves extension in config" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + } + + /* Empty elliptic curve list, this is a configuration error. */ + if( elliptic_curve_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + elliptic_curve_len ); + + elliptic_curve_len = 0; + + for( grp_id = ssl->conf->curve_list; + *grp_id != MBEDTLS_ECP_DP_NONE; + grp_id++ ) + { + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); + elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8; + elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES ) + & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len ) ) & 0xFF ); + + *olen = 6 + elliptic_curve_len; + + return( 0 ); +} + +static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + (void) ssl; /* ssl used for debugging only */ + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding supported_point_formats extension" ) ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) + & 0xFF ); + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; + + *olen = 6; + + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + int ret; + unsigned char *p = buf; + size_t kkpp_len; + + *olen = 0; + + /* Skip costly extension if we can't use EC J-PAKE anyway */ + if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding ecjpake_kkpp extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); + + /* + * We may need to send ClientHello multiple times for Hello verification. + * We don't want to compute fresh values every time (both for performance + * and consistency reasons), so cache the extension content. + */ + if( ssl->handshake->ecjpake_cache == NULL || + ssl->handshake->ecjpake_cache_len == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "generating new ecjpake parameters" ) ); + + ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, + p + 2, end - p - 2, &kkpp_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1 , + "mbedtls_ecjpake_write_round_one", ret ); + return( ret ); + } + + ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len ); + if( ssl->handshake->ecjpake_cache == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "allocation failed" ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ssl->handshake->ecjpake_cache, p + 2, kkpp_len ); + ssl->handshake->ecjpake_cache_len = kkpp_len; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "re-using cached ecjpake parameters" ) ); + + kkpp_len = ssl->handshake->ecjpake_cache_len; + MBEDTLS_SSL_CHK_BUF_PTR( p + 2, end, kkpp_len ); + + memcpy( p + 2, ssl->handshake->ecjpake_cache, kkpp_len ); + } + + *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); + + *olen = kkpp_len + 4; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding max_fragment_length extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) + & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->conf->mfl_code; + + *olen = 5; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static int ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding truncated_hmac extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding encrypt_then_mac extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding extended_master_secret extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) + & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t tlen = ssl->session_negotiate->ticket_len; + + *olen = 0; + + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding session ticket extension" ) ); + + /* The addition is safe here since the ticket length is 16 bit. */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 + tlen ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); + + *p++ = (unsigned char)( ( tlen >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( tlen ) & 0xFF ); + + *olen = 4; + + if( ssl->session_negotiate->ticket == NULL || tlen == 0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "sending session ticket of length %d", tlen ) ); + + memcpy( p, ssl->session_negotiate->ticket, tlen ); + + *olen += tlen; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) +static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t alpnlen = 0; + const char **cur; + + *olen = 0; + + if( ssl->conf->alpn_list == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); + + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + alpnlen += strlen( *cur ) + 1; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + alpnlen ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Skip writing extension and list length for now */ + p += 4; + + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + { + /* + * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of + * protocol names is less than 255. + */ + *p = (unsigned char)strlen( *cur ); + memcpy( p + 1, *cur, *p ); + p += 1 + *p; + } + + *olen = p - buf; + + /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ + buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); + buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); + + /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */ + buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); + buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +/* + * Generate random bytes for ClientHello + */ +static int ssl_generate_random( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *p = ssl->handshake->randbytes; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t; +#endif + + /* + * When responding to a verify request, MUST reuse random (RFC 6347 4.2.1) + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->verify_cookie != NULL ) + { + return( 0 ); + } +#endif + +#if defined(MBEDTLS_HAVE_TIME) + t = mbedtls_time( NULL ); + *p++ = (unsigned char)( t >> 24 ); + *p++ = (unsigned char)( t >> 16 ); + *p++ = (unsigned char)( t >> 8 ); + *p++ = (unsigned char)( t ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) ); +#else + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* MBEDTLS_HAVE_TIME */ + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/** + * \brief Validate cipher suite against config in SSL context. + * + * \param suite_info cipher suite to validate + * \param ssl SSL context + * \param min_minor_ver Minimal minor version to accept a cipher suite + * \param max_minor_ver Maximal minor version to accept a cipher suite + * + * \return 0 if valid, else 1 + */ +static int ssl_validate_ciphersuite( + const mbedtls_ssl_ciphersuite_t * suite_info, + const mbedtls_ssl_context * ssl, + int min_minor_ver, int max_minor_ver ) +{ + (void) ssl; + if( suite_info == NULL ) + return( 1 ); + + if( suite_info->min_minor_ver > max_minor_ver || + suite_info->max_minor_ver < min_minor_ver ) + return( 1 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 1 ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + return( 1 ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + return( 1 ); +#endif + + return( 0 ); +} + +static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t i, n, olen, ext_len = 0; + + unsigned char *buf; + unsigned char *p, *q; + const unsigned char *end; + + unsigned char offer_compress; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + int uses_ec = 0; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + ssl->major_ver = ssl->conf->min_major_ver; + ssl->minor_ver = ssl->conf->min_minor_ver; + } + + if( ssl->conf->max_major_ver == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "configured max major version is invalid, consider using mbedtls_ssl_config_defaults()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + buf = ssl->out_msg; + end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN; + + /* + * Check if there's enough space for the first part of the ClientHello + * consisting of the 38 bytes described below, the session identifier (at + * most 32 bytes) and its length (1 byte). + * + * Use static upper bounds instead of the actual values + * to allow the compiler to optimize this away. + */ + MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 ); + + /* + * The 38 first bytes of the ClientHello: + * 0 . 0 handshake type (written later) + * 1 . 3 handshake length (written later) + * 4 . 5 highest version supported + * 6 . 9 current UNIX time + * 10 . 37 random bytes + * + * The current UNIX time (4 bytes) and following 28 random bytes are written + * by ssl_generate_random() into ssl->handshake->randbytes buffer and then + * copied from there into the output buffer. + */ + + p = buf + 4; + mbedtls_ssl_write_version( ssl->conf->max_major_ver, + ssl->conf->max_minor_ver, + ssl->conf->transport, p ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]", + buf[4], buf[5] ) ); + + if( ( ret = ssl_generate_random( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_generate_random", ret ); + return( ret ); + } + + memcpy( p, ssl->handshake->randbytes, 32 ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", p, 32 ); + p += 32; + + /* + * 38 . 38 session id length + * 39 . 39+n session id + * 39+n . 39+n DTLS only: cookie length (1 byte) + * 40+n . .. DTLS only: cookie + * .. . .. ciphersuitelist length (2 bytes) + * .. . .. ciphersuitelist + * .. . .. compression methods length (1 byte) + * .. . .. compression methods + * .. . .. extensions length (2 bytes) + * .. . .. extensions + */ + n = ssl->session_negotiate->id_len; + + if( n < 16 || n > 32 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->handshake->resume == 0 ) + { + n = 0; + } + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + /* + * RFC 5077 section 3.4: "When presenting a ticket, the client MAY + * generate and include a Session ID in the TLS ClientHello." + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ssl->session_negotiate->ticket != NULL && + ssl->session_negotiate->ticket_len != 0 ) + { + ret = ssl->conf->f_rng( ssl->conf->p_rng, + ssl->session_negotiate->id, 32 ); + + if( ret != 0 ) + return( ret ); + + ssl->session_negotiate->id_len = n = 32; + } + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + /* + * The first check of the output buffer size above ( + * MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 );) + * has checked that there is enough space in the output buffer for the + * session identifier length byte and the session identifier (n <= 32). + */ + *p++ = (unsigned char) n; + + for( i = 0; i < n; i++ ) + *p++ = ssl->session_negotiate->id[i]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); + + /* + * With 'n' being the length of the session identifier + * + * 39+n . 39+n DTLS only: cookie length (1 byte) + * 40+n . .. DTLS only: cookie + * .. . .. ciphersuitelist length (2 bytes) + * .. . .. ciphersuitelist + * .. . .. compression methods length (1 byte) + * .. . .. compression methods + * .. . .. extensions length (2 bytes) + * .. . .. extensions + */ + + /* + * DTLS cookie + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 1 ); + + if( ssl->handshake->verify_cookie == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) ); + *p++ = 0; + } + else + { + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", + ssl->handshake->verify_cookie, + ssl->handshake->verify_cookie_len ); + + *p++ = ssl->handshake->verify_cookie_len; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, + ssl->handshake->verify_cookie_len ); + memcpy( p, ssl->handshake->verify_cookie, + ssl->handshake->verify_cookie_len ); + p += ssl->handshake->verify_cookie_len; + } + } +#endif + + /* + * Ciphersuite list + */ + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + + /* Skip writing ciphersuite length for now */ + n = 0; + q = p; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + p += 2; + + for( i = 0; ciphersuites[i] != 0; i++ ) + { + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] ); + + if( ssl_validate_ciphersuite( ciphersuite_info, ssl, + ssl->conf->min_minor_ver, + ssl->conf->max_minor_ver ) != 0 ) + continue; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x", + ciphersuites[i] ) ); + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info ); +#endif + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + + n++; + *p++ = (unsigned char)( ciphersuites[i] >> 8 ); + *p++ = (unsigned char)( ciphersuites[i] ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, got %d ciphersuites (excluding SCSVs)", n ) ); + + /* + * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 ); + *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ); + n++; + } + + /* Some versions of OpenSSL don't handle it correctly if not at end */ +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + if( ssl->conf->fallback == MBEDTLS_SSL_IS_FALLBACK ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ); + *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ); + n++; + } +#endif + + *q++ = (unsigned char)( n >> 7 ); + *q++ = (unsigned char)( n << 1 ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + offer_compress = 1; +#else + offer_compress = 0; +#endif + + /* + * We don't support compression with DTLS right now: if many records come + * in the same datagram, uncompressing one could overwrite the next one. + * We don't want to add complexity for handling that case unless there is + * an actual need for it. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + offer_compress = 0; +#endif + + if( offer_compress ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d", + MBEDTLS_SSL_COMPRESS_DEFLATE, + MBEDTLS_SSL_COMPRESS_NULL ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 3 ); + *p++ = 2; + *p++ = MBEDTLS_SSL_COMPRESS_DEFLATE; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", + MBEDTLS_SSL_COMPRESS_NULL ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + *p++ = 1; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + } + + /* First write extensions, then the total length */ + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ( ret = ssl_write_hostname_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_hostname_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + + /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added + * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ( ret = ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_renegotiation_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + if( ( ret = ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_signature_algorithms_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( uses_ec ) + { + if( ( ret = ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_elliptic_curves_ext", ret ); + return( ret ); + } + ext_len += olen; + + if( ( ret = ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_point_formats_ext", ret ); + return( ret ); + } + ext_len += olen; + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ( ret = ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_ecjpake_kkpp_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( ( ret = ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_max_fragment_length_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + if( ( ret = ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_truncated_hmac_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( ( ret = ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_encrypt_then_mac_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( ( ret = ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_extended_ms_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + if( ( ret = ssl_write_alpn_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_alpn_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ( ret = ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_session_ticket_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + + /* olen unused if all extensions are disabled */ + ((void) olen); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d", + ext_len ) ); + + if( ext_len > 0 ) + { + /* No need to check for space here, because the extension + * writing functions already took care of that. */ + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + p += ext_len; + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_HELLO; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); + + return( 0 ); +} + +static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len * 2 || + buf[0] != ssl->verify_data_len * 2 || + mbedtls_ssl_safer_memcmp( buf + 1, + ssl->own_verify_data, ssl->verify_data_len ) != 0 || + mbedtls_ssl_safer_memcmp( buf + 1 + ssl->verify_data_len, + ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x00 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-zero length renegotiation info" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + /* + * server should use the extension only if we did, + * and if so the server's value should match ours (and len is always 1) + */ + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE || + len != 1 || + buf[0] != ssl->conf->mfl_code ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching max fragment length extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching truncated HMAC extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching encrypt-then-MAC extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching extended master secret extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching session ticket extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->new_session_ticket = 1; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + if( len == 0 || (size_t)( buf[0] + 1 ) != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + list_size = buf[0]; + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || + p[0] == MBEDTLS_ECP_PF_COMPRESSED ) + { +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl->handshake->ecjpake_ctx.point_format = p[0]; +#endif + MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + + if( ssl->transform_negotiate->ciphersuite_info->key_exchange != + MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); + return( 0 ); + } + + /* If we got here, we no longer need our cached extension */ + mbedtls_free( ssl->handshake->ecjpake_cache ); + ssl->handshake->ecjpake_cache = NULL; + ssl->handshake->ecjpake_cache_len = 0; + + if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, + buf, len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, name_len; + const char **p; + + /* If we didn't send it, the server shouldn't send it */ + if( ssl->conf->alpn_list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching ALPN extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + * + * the "ProtocolNameList" MUST contain exactly one "ProtocolName" + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + name_len = buf[2]; + if( name_len != list_len - 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* Check that the server chosen protocol was in our list and save it */ + for( p = ssl->conf->alpn_list; *p != NULL; p++ ) + { + if( name_len == strlen( *p ) && + memcmp( buf + 3, *p, name_len ) == 0 ) + { + ssl->alpn_chosen = *p; + return( 0 ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ALPN extension: no matching protocol" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +/* + * Parse HelloVerifyRequest. Only called after verifying the HS type. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) +{ + const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + int major_ver, minor_ver; + unsigned char cookie_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) ); + + /* Check that there is enough room for: + * - 2 bytes of version + * - 1 byte of cookie_len + */ + if( mbedtls_ssl_hs_hdr_len( ssl ) + 3 > ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "incoming HelloVerifyRequest message is too short" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); + mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, p ); + p += 2; + + /* + * Since the RFC is not clear on this point, accept DTLS 1.0 (TLS 1.1) + * even is lower than our min version. + */ + if( major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || + minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 || + major_ver > ssl->conf->max_major_ver || + minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server version" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + cookie_len = *p++; + if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "cookie length does not match incoming message size" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len ); + + mbedtls_free( ssl->handshake->verify_cookie ); + + ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len ); + if( ssl->handshake->verify_cookie == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", cookie_len ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ssl->handshake->verify_cookie, p, cookie_len ); + ssl->handshake->verify_cookie_len = cookie_len; + + /* Start over at ClientHello */ + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + mbedtls_ssl_reset_checksum( ssl ); + + mbedtls_ssl_recv_flight_completed( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse hello verify request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) +{ + int ret, i; + size_t n; + size_t ext_len; + unsigned char *buf, *ext; + unsigned char comp; +#if defined(MBEDTLS_ZLIB_SUPPORT) + int accept_comp; +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const mbedtls_ssl_ciphersuite_t *suite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); + + buf = ssl->in_msg; + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + /* No alert on a read error. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + ssl->renego_records_seen++; + + if( ssl->conf->renego_max_records >= 0 && + ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation requested, but not honored by server" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-handshake message during renegotiation" ) ); + + ssl->keep_current_message = 1; + return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received hello verify request" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + return( ssl_parse_hello_verify_request( ssl ) ); + } + else + { + /* We made it through the verification process */ + mbedtls_free( ssl->handshake->verify_cookie ); + ssl->handshake->verify_cookie = NULL; + ssl->handshake->verify_cookie_len = 0; + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len( ssl ) || + buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * 0 . 1 server_version + * 2 . 33 random (maybe including 4 bytes of Unix time) + * 34 . 34 session_id length = n + * 35 . 34+n session_id + * 35+n . 36+n cipher_suite + * 37+n . 37+n compression_method + * + * 38+n . 39+n extensions length (optional) + * 40+n . .. extensions + */ + buf += mbedtls_ssl_hs_hdr_len( ssl ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", buf + 0, 2 ); + mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, + ssl->conf->transport, buf + 0 ); + + if( ssl->major_ver < ssl->conf->min_major_ver || + ssl->minor_ver < ssl->conf->min_minor_ver || + ssl->major_ver > ssl->conf->max_major_ver || + ssl->minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server version out of bounds - min: [%d:%d], server: [%d:%d], max: [%d:%d]", + ssl->conf->min_major_ver, + ssl->conf->min_minor_ver, + ssl->major_ver, ssl->minor_ver, + ssl->conf->max_major_ver, + ssl->conf->max_minor_ver ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", + ( (uint32_t) buf[2] << 24 ) | + ( (uint32_t) buf[3] << 16 ) | + ( (uint32_t) buf[4] << 8 ) | + ( (uint32_t) buf[5] ) ) ); + + memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 ); + + n = buf[34]; + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 2, 32 ); + + if( n > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( ssl->in_hslen > mbedtls_ssl_hs_hdr_len( ssl ) + 39 + n ) + { + ext_len = ( ( buf[38 + n] << 8 ) + | ( buf[39 + n] ) ); + + if( ( ext_len > 0 && ext_len < 4 ) || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + else if( ssl->in_hslen == mbedtls_ssl_hs_hdr_len( ssl ) + 38 + n ) + { + ext_len = 0; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* ciphersuite (used later) */ + i = ( buf[35 + n] << 8 ) | buf[36 + n]; + + /* + * Read and check compression + */ + comp = buf[37 + n]; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + /* See comments in ssl_write_client_hello() */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + accept_comp = 0; + else +#endif + accept_comp = 1; + + if( comp != MBEDTLS_SSL_COMPRESS_NULL && + ( comp != MBEDTLS_SSL_COMPRESS_DEFLATE || accept_comp == 0 ) ) +#else /* MBEDTLS_ZLIB_SUPPORT */ + if( comp != MBEDTLS_SSL_COMPRESS_NULL ) +#endif/* MBEDTLS_ZLIB_SUPPORT */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server hello, bad compression: %d", comp ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* + * Initialize update checksum functions + */ + ssl->transform_negotiate->ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id( i ); + + if( ssl->transform_negotiate->ciphersuite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "ciphersuite info for %04x not found", i ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + mbedtls_ssl_optimize_checksum( ssl, + ssl->transform_negotiate->ciphersuite_info ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n ); + + /* + * Check if the session can be resumed + */ + if( ssl->handshake->resume == 0 || n == 0 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->session_negotiate->ciphersuite != i || + ssl->session_negotiate->compression != comp || + ssl->session_negotiate->id_len != n || + memcmp( ssl->session_negotiate->id, buf + 35, n ) != 0 ) + { + ssl->state++; + ssl->handshake->resume = 0; +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time( NULL ); +#endif + ssl->session_negotiate->ciphersuite = i; + ssl->session_negotiate->compression = comp; + ssl->session_negotiate->id_len = n; + memcpy( ssl->session_negotiate->id, buf + 35, n ); + } + else + { + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", + buf[37 + n] ) ); + + /* + * Perform cipher suite validation in same way as in ssl_write_client_hello. + */ + i = 0; + while( 1 ) + { + if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( ssl->conf->ciphersuite_list[ssl->minor_ver][i++] == + ssl->session_negotiate->ciphersuite ) + { + break; + } + } + + suite_info = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite ); + if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver, + ssl->minor_ver ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + ssl->handshake->ecrs_enabled = 1; + } +#endif + + if( comp != MBEDTLS_SSL_COMPRESS_NULL +#if defined(MBEDTLS_ZLIB_SUPPORT) + && comp != MBEDTLS_SSL_COMPRESS_DEFLATE +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + ssl->session_negotiate->compression = comp; + + ext = buf + 40 + n; + + MBEDTLS_SSL_DEBUG_MSG( 2, + ( "server hello, total extension length: %d", ext_len ) ); + + while( ext_len ) + { + unsigned int ext_id = ( ( ext[0] << 8 ) + | ( ext[1] ) ); + unsigned int ext_size = ( ( ext[2] << 8 ) + | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + switch( ext_id ) + { + case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, + ext_size ) ) != 0 ) + return( ret ); + + break; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found max_fragment_length extension" ) ); + + if( ( ret = ssl_parse_max_fragment_length_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated_hmac extension" ) ); + + if( ( ret = ssl_parse_truncated_hmac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) ); + + if( ( ret = ssl_parse_encrypt_then_mac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found extended_master_secret extension" ) ); + + if( ( ret = ssl_parse_extended_ms_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_TLS_EXT_SESSION_TICKET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) ); + + if( ( ret = ssl_parse_session_ticket_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found supported_point_formats extension" ) ); + + if( ( ret = ssl_parse_supported_point_formats_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake_kkpp extension" ) ); + + if( ( ret = ssl_parse_ecjpake_kkpp( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + if( ( ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 ) + return( ret ); + + break; +#endif /* MBEDTLS_SSL_ALPN */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "unknown extension found: %d (ignoring)", ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx, + p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 2, ( "mbedtls_dhm_read_params" ), ret ); + return( ret ); + } + + if( ssl->handshake->dhm_ctx.len * 8 < ssl->conf->dhm_min_bitlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %d < %d", + ssl->handshake->dhm_ctx.len * 8, + ssl->conf->dhm_min_bitlen ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) +{ + const mbedtls_ecp_curve_info *curve_info; + mbedtls_ecp_group_id grp_id; +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + grp_id = ssl->handshake->ecdh_ctx.grp.id; +#else + grp_id = ssl->handshake->ecdh_ctx.grp_id; +#endif + + curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id ); + if( curve_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); + +#if defined(MBEDTLS_ECP_C) + if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 ) +#else + if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || + ssl->handshake->ecdh_ctx.grp.nbits > 521 ) +#endif + return( -1 ); + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + if( ( ret = mbedtls_ecdh_read_params( &ssl->handshake->ecdh_ctx, + (const unsigned char **) p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (ECDHE curve)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t len; + ((void) ssl); + + /* + * PSK parameters: + * + * opaque psk_identity_hint<0..2^16-1>; + */ + if( end - (*p) < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (psk_identity_hint length)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + len = (*p)[0] << 8 | (*p)[1]; + *p += 2; + + if( end - (*p) < (int) len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (psk_identity_hint length)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Note: we currently ignore the PKS identity hint, as we only allow one + * PSK to be provisionned on the client. This could be changed later if + * someone needs that feature. + */ + *p += len; + ret = 0; + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +/* + * Generate a pre-master secret and encrypt it with the server's RSA key + */ +static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, + size_t offset, size_t *olen, + size_t pms_offset ) +{ + int ret; + size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2; + unsigned char *p = ssl->handshake->premaster + pms_offset; + + if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Generate (part of) the pre-master as + * struct { + * ProtocolVersion client_version; + * opaque random[46]; + * } PreMasterSecret; + */ + mbedtls_ssl_write_version( ssl->conf->max_major_ver, + ssl->conf->max_minor_ver, + ssl->conf->transport, p ); + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p + 2, 46 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret ); + return( ret ); + } + + ssl->handshake->pmslen = 48; + + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * Now write it out, encrypted + */ + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, + MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk, + p, ssl->handshake->pmslen, + ssl->out_msg + offset + len_bytes, olen, + MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( len_bytes == 2 ) + { + ssl->out_msg[offset+0] = (unsigned char)( *olen >> 8 ); + ssl->out_msg[offset+1] = (unsigned char)( *olen ); + *olen += 2; + } +#endif + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end, + mbedtls_md_type_t *md_alg, + mbedtls_pk_type_t *pk_alg ) +{ + ((void) ssl); + *md_alg = MBEDTLS_MD_NONE; + *pk_alg = MBEDTLS_PK_NONE; + + /* Only in TLS 1.2 */ + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + return( 0 ); + } + + if( (*p) + 2 > end ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + /* + * Get hash algorithm + */ + if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) ) + == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "Server used unsupported HashAlgorithm %d", *(p)[0] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Get signature algorithm + */ + if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) ) + == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server used unsupported SignatureAlgorithm %d", (*p)[1] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Check if the hash is acceptable + */ + if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server used HashAlgorithm %d that was not offered", *(p)[0] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", + (*p)[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", + (*p)[0] ) ); + *p += 2; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) +{ + int ret; + const mbedtls_ecp_keypair *peer_key; + + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, + MBEDTLS_PK_ECKEY ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + peer_key = mbedtls_pk_ec( ssl->session_negotiate->peer_cert->pk ); + + if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key, + MBEDTLS_ECDH_THEIRS ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + unsigned char *p = NULL, *end = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing ) + { + goto start_processing; + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server + * doesn't use a psk_identity_hint + */ + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE ) + { + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + /* Current message is probably either + * CertificateRequest or ServerHelloDone */ + ssl->keep_current_message = 1; + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server key exchange message must not be skipped" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing; + +start_processing: +#endif + p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + end = ssl->in_msg + ssl->in_hslen; + MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } /* FALLTROUGH */ +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + ; /* nothing more to do */ + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) + { + size_t sig_len, hashlen; + unsigned char hash[64]; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + size_t params_len = p - params; + void *rs_ctx = NULL; + + /* + * Handle the digitally-signed structure + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + if( ssl_parse_signature_algorithm( ssl, &p, end, + &md_alg, &pk_alg ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + if( pk_alg != + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + { + pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + + /* Default hash for ECDSA is SHA-1 */ + if( pk_alg == MBEDTLS_PK_ECDSA && md_alg == MBEDTLS_MD_NONE ) + md_alg = MBEDTLS_MD_SHA1; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Read signature + */ + + if( p > end - 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + sig_len = ( p[0] << 8 ) | p[1]; + p += 2; + + if( p != end - sig_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "signature", p, sig_len ); + + /* + * Compute the hash that has been signed + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( md_alg == MBEDTLS_MD_NONE ) + { + hashlen = 36; + ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, params, + params_len ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( md_alg != MBEDTLS_MD_NONE ) + { + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, + params, params_len, + md_alg ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); + + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * Verify signature + */ + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, + pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + rs_ctx = &ssl->handshake->ecrs_ctx.pk; +#endif + + if( ( ret = mbedtls_pk_verify_restartable( + &ssl->session_negotiate->peer_cert->pk, + md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 ) + { +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) +#endif + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + } +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + +exit: + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); + + return( 0 ); +} + +#if ! defined(MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED) +static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ +static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *buf; + size_t n = 0; + size_t cert_type_len = 0, dn_len = 0; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->state++; + ssl->client_auth = ( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request", + ssl->client_auth ? "a" : "no" ) ); + + if( ssl->client_auth == 0 ) + { + /* Current message is probably the ServerHelloDone */ + ssl->keep_current_message = 1; + goto exit; + } + + /* + * struct { + * ClientCertificateType certificate_types<1..2^8-1>; + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2^16-1>; -- TLS 1.2 only + * DistinguishedName certificate_authorities<0..2^16-1>; + * } CertificateRequest; + * + * Since we only support a single certificate on clients, let's just + * ignore all the information that's supposed to help us pick a + * certificate. + * + * We could check that our certificate matches the request, and bail out + * if it doesn't, but it's simpler to just send the certificate anyway, + * and give the server the opportunity to decide if it should terminate + * the connection when it doesn't like our certificate. + * + * Same goes for the hash in TLS 1.2's signature_algorithms: at this + * point we only have one hash available (see comments in + * write_certificate_verify), so let's just use what we have. + * + * However, we still minimally parse the message to check it is at least + * superficially sane. + */ + buf = ssl->in_msg; + + /* certificate_types */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; + n = cert_type_len; + + /* + * In the subsequent code there are two paths that read from buf: + * * the length of the signature algorithms field (if minor version of + * SSL is 3), + * * distinguished name length otherwise. + * Both reach at most the index: + * ...hdr_len + 2 + n, + * therefore the buffer length at this point must be greater than that + * regardless of the actual code path. + */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + + /* supported_signature_algorithms */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + size_t sig_alg_len = + ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); +#if defined(MBEDTLS_DEBUG_C) + unsigned char* sig_alg; + size_t i; +#endif + + /* + * The furthest access in buf is in the loop few lines below: + * sig_alg[i + 1], + * where: + * sig_alg = buf + ...hdr_len + 3 + n, + * max(i) = sig_alg_len - 1. + * Therefore the furthest access is: + * buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1], + * which reduces to: + * buf[...hdr_len + 3 + n + sig_alg_len], + * which is one less than we need the buf to be. + */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + + 3 + n + sig_alg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + +#if defined(MBEDTLS_DEBUG_C) + sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; + for( i = 0; i < sig_alg_len; i += 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "Supported Signature Algorithm found: %d,%d", + sig_alg[i], sig_alg[i + 1] ) ); + } +#endif + + n += 2 + sig_alg_len; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* certificate_authorities */ + dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); + + n += dn_len; + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + +exit: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ + +static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) || + ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ); + } + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) ); + + return( 0 ); +} + +static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t i, n; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) + { + /* + * DHM key exchange -- send G^X mod P + */ + n = ssl->handshake->dhm_ctx.len; + + ssl->out_msg[4] = (unsigned char)( n >> 8 ); + ssl->out_msg[5] = (unsigned char)( n ); + i = 6; + + ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[i], n, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + /* + * ECDH key exchange -- send client public value + */ + i = 4; + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + { + if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret ) + goto ecdh_calc_secret; + + mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx ); + } +#endif + + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, + &n, + &ssl->out_msg[i], 1000, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + { + ssl->handshake->ecrs_n = n; + ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret; + } + +ecdh_calc_secret: + if( ssl->handshake->ecrs_enabled ) + n = ssl->handshake->ecrs_n; +#endif + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_psk( ciphersuite_info ) ) + { + /* + * opaque psk_identity<0..2^16-1>; + */ + if( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for PSK" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + i = 4; + n = ssl->conf->psk_identity_len; + + if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "psk identity too long or SSL buffer too short" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[i++] = (unsigned char)( n >> 8 ); + ssl->out_msg[i++] = (unsigned char)( n ); + + memcpy( ssl->out_msg + i, + ssl->conf->psk_identity, + ssl->conf->psk_identity_len ); + i += ssl->conf->psk_identity_len; + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) + { + n = 0; + } + else +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 ) + return( ret ); + } + else +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + /* + * ClientDiffieHellmanPublic public (DHM send G^X mod P) + */ + n = ssl->handshake->dhm_ctx.len; + + if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "psk identity or DHM size too long or SSL buffer too short" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[i++] = (unsigned char)( n >> 8 ); + ssl->out_msg[i++] = (unsigned char)( n ); + + ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[i], n, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + /* + * ClientECDiffieHellmanPublic public; + */ + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, + &ssl->out_msg[i], MBEDTLS_SSL_OUT_CONTENT_LEN - i, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, + "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + i = 4; + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + i = 4; + + ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, + ssl->out_msg + i, MBEDTLS_SSL_OUT_CONTENT_LEN - i, &n, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); + return( ret ); + } + + ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, + ssl->handshake->premaster, 32, &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + { + ((void) ciphersuite_info); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msglen = i + n; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + size_t n = 0, offset = 0; + unsigned char hash[48]; + unsigned char *hash_start = hash; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + unsigned int hashlen; + void *rs_ctx = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign ) + { + goto sign; + } +#endif + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->client_auth == 0 || mbedtls_ssl_own_cert( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for certificate" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Make a signature of the handshake digests + */ +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign; + +sign: +#endif + + ssl->handshake->calc_verify( ssl, hash ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(handshake_messages); + * + * sha_hash + * SHA(handshake_messages); + */ + hashlen = 36; + md_alg = MBEDTLS_MD_NONE; + + /* + * For ECDSA, default hash is SHA-1 only + */ + if( mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = MBEDTLS_MD_SHA1; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque handshake_messages[handshake_messages_length]; + * }; + * + * Taking shortcut here. We assume that the server always allows the + * PRF Hash function and has sent it in the allowed signature + * algorithms list received in the Certificate Request message. + * + * Until we encounter a server that does not, we will take this + * shortcut. + * + * Reason: Otherwise we should have running hashes for SHA512 and + * SHA224 in order to satisfy 'weird' needs from the server + * side. + */ + if( ssl->transform_negotiate->ciphersuite_info->mac == + MBEDTLS_MD_SHA384 ) + { + md_alg = MBEDTLS_MD_SHA384; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384; + } + else + { + md_alg = MBEDTLS_MD_SHA256; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256; + } + ssl->out_msg[5] = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + offset = 2; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + rs_ctx = &ssl->handshake->ecrs_ctx.pk; +#endif + + if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ), + md_alg, hash_start, hashlen, + ssl->out_msg + 6 + offset, &n, + ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 ); + ssl->out_msg[5 + offset] = (unsigned char)( n ); + + ssl->out_msglen = 6 + n + offset; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) +{ + int ret; + uint32_t lifetime; + size_t ticket_len; + unsigned char *ticket; + const unsigned char *msg; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 0 . 3 ticket_lifetime_hint + * 4 . 5 ticket_len (n) + * 6 . 5+n ticket content + */ + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET || + ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + + lifetime = ( ((uint32_t) msg[0]) << 24 ) | ( msg[1] << 16 ) | + ( msg[2] << 8 ) | ( msg[3] ); + + ticket_len = ( msg[4] << 8 ) | ( msg[5] ); + + if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) ); + + /* We're not waiting for a NewSessionTicket message any more */ + ssl->handshake->new_session_ticket = 0; + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + /* + * Zero-length ticket means the server changed his mind and doesn't want + * to send a ticket after all, so just forget it + */ + if( ticket_len == 0 ) + return( 0 ); + + mbedtls_platform_zeroize( ssl->session_negotiate->ticket, + ssl->session_negotiate->ticket_len ); + mbedtls_free( ssl->session_negotiate->ticket ); + ssl->session_negotiate->ticket = NULL; + ssl->session_negotiate->ticket_len = 0; + + if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ticket, msg + 6, ticket_len ); + + ssl->session_negotiate->ticket = ticket; + ssl->session_negotiate->ticket_len = ticket_len; + ssl->session_negotiate->ticket_lifetime = lifetime; + + /* + * RFC 5077 section 3.4: + * "If the client receives a session ticket from the server, then it + * discards any Session ID that was sent in the ServerHello." + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) ); + ssl->session_negotiate->id_len = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- client side -- single step + */ +int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Change state now, so that it is right in mbedtls_ssl_read_record(), used + * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && + ssl->handshake->new_session_ticket != 0 ) + { + ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET; + } +#endif + + switch( ssl->state ) + { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + break; + + /* + * ==> ClientHello + */ + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_write_client_hello( ssl ); + break; + + /* + * <== ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_parse_server_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = mbedtls_ssl_parse_certificate( ssl ); + break; + + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + ret = ssl_parse_server_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_parse_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO_DONE: + ret = ssl_parse_server_hello_done( ssl ); + break; + + /* + * ==> ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_write_certificate( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_write_client_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_write_certificate_verify( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_write_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = mbedtls_ssl_write_finished( ssl ); + break; + + /* + * <== ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: + ret = ssl_parse_new_session_ticket( ssl ); + break; +#endif + + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = mbedtls_ssl_parse_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + mbedtls_ssl_handshake_wrapup( ssl ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_CLI_C */ diff --git a/external/mbedtls/library/ssl_cookie.c b/external/mbedtls/library/ssl_cookie.c new file mode 100644 index 0000000..04565e0 --- /dev/null +++ b/external/mbedtls/library/ssl_cookie.c @@ -0,0 +1,279 @@ +/* + * DTLS cookie callbacks implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_COOKIE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_cookie.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/platform_util.h" + +#include + +/* + * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is + * available. Try SHA-256 first, 512 wastes resources since we need to stay + * with max 32 bytes of cookie for DTLS 1.0 + */ +#if defined(MBEDTLS_SHA256_C) +#define COOKIE_MD MBEDTLS_MD_SHA224 +#define COOKIE_MD_OUTLEN 32 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA512_C) +#define COOKIE_MD MBEDTLS_MD_SHA384 +#define COOKIE_MD_OUTLEN 48 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA1_C) +#define COOKIE_MD MBEDTLS_MD_SHA1 +#define COOKIE_MD_OUTLEN 20 +#define COOKIE_HMAC_LEN 20 +#else +#error "DTLS hello verify needs SHA-1 or SHA-2" +#endif + +/* + * Cookies are formed of a 4-bytes timestamp (or serial number) and + * an HMAC of timestemp and client ID. + */ +#define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN ) + +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_init( &ctx->hmac_ctx ); +#if !defined(MBEDTLS_HAVE_TIME) + ctx->serial = 0; +#endif + ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ) +{ + ctx->timeout = delay; +} + +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_free( &ctx->hmac_ctx ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); +} + +int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char key[COOKIE_MD_OUTLEN]; + + if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 ) + return( ret ); + + ret = mbedtls_md_setup( &ctx->hmac_ctx, mbedtls_md_info_from_type( COOKIE_MD ), 1 ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_md_hmac_starts( &ctx->hmac_ctx, key, sizeof( key ) ); + if( ret != 0 ) + return( ret ); + + mbedtls_platform_zeroize( key, sizeof( key ) ); + + return( 0 ); +} + +/* + * Generate the HMAC part of a cookie + */ +static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx, + const unsigned char time[4], + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + unsigned char hmac_out[COOKIE_MD_OUTLEN]; + + MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_HMAC_LEN ); + + if( mbedtls_md_hmac_reset( hmac_ctx ) != 0 || + mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 || + mbedtls_md_hmac_update( hmac_ctx, cli_id, cli_id_len ) != 0 || + mbedtls_md_hmac_finish( hmac_ctx, hmac_out ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( *p, hmac_out, COOKIE_HMAC_LEN ); + *p += COOKIE_HMAC_LEN; + + return( 0 ); +} + +/* + * Generate cookie for DTLS ClientHello verification + */ +int mbedtls_ssl_cookie_write( void *p_ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + int ret; + mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; + unsigned long t; + + if( ctx == NULL || cli_id == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_LEN ); + +#if defined(MBEDTLS_HAVE_TIME) + t = (unsigned long) mbedtls_time( NULL ); +#else + t = ctx->serial++; +#endif + + (*p)[0] = (unsigned char)( t >> 24 ); + (*p)[1] = (unsigned char)( t >> 16 ); + (*p)[2] = (unsigned char)( t >> 8 ); + (*p)[3] = (unsigned char)( t ); + *p += 4; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); +#endif + + ret = ssl_cookie_hmac( &ctx->hmac_ctx, *p - 4, + p, end, cli_id, cli_id_len ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + + MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Check a cookie + */ +int mbedtls_ssl_cookie_check( void *p_ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + unsigned char ref_hmac[COOKIE_HMAC_LEN]; + int ret = 0; + unsigned char *p = ref_hmac; + mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; + unsigned long cur_time, cookie_time; + + if( ctx == NULL || cli_id == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( cookie_len != COOKIE_LEN ) + return( -1 ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); +#endif + + if( ssl_cookie_hmac( &ctx->hmac_ctx, cookie, + &p, p + sizeof( ref_hmac ), + cli_id, cli_id_len ) != 0 ) + ret = -1; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + + MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + if( ret != 0 ) + return( ret ); + + if( mbedtls_ssl_safer_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 ) + return( -1 ); + +#if defined(MBEDTLS_HAVE_TIME) + cur_time = (unsigned long) mbedtls_time( NULL ); +#else + cur_time = ctx->serial; +#endif + + cookie_time = ( (unsigned long) cookie[0] << 24 ) | + ( (unsigned long) cookie[1] << 16 ) | + ( (unsigned long) cookie[2] << 8 ) | + ( (unsigned long) cookie[3] ); + + if( ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout ) + return( -1 ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_COOKIE_C */ diff --git a/external/mbedtls/library/ssl_srv.c b/external/mbedtls/library/ssl_srv.c new file mode 100644 index 0000000..cbf6142 --- /dev/null +++ b/external/mbedtls/library/ssl_srv.c @@ -0,0 +1,4405 @@ +/* + * SSLv3/TLSv1 server-side functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen ) +{ + if( ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + mbedtls_free( ssl->cli_id ); + + if( ( ssl->cli_id = mbedtls_calloc( 1, ilen ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( ssl->cli_id, info, ilen ); + ssl->cli_id_len = ilen; + + return( 0 ); +} + +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ) +{ + conf->f_cookie_write = f_cookie_write; + conf->f_cookie_check = f_cookie_check; + conf->p_cookie = p_cookie; +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + size_t servername_list_size, hostname_len; + const unsigned char *p; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); + + if( len < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( servername_list_size + 2 != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + p = buf + 2; + while( servername_list_size > 2 ) + { + hostname_len = ( ( p[1] << 8 ) | p[2] ); + if( hostname_len + 3 > servername_list_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) + { + ret = ssl->conf->f_sni( ssl->conf->p_sni, + ssl, p + 3, hostname_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + return( 0 ); + } + + servername_list_size -= hostname_len + 3; + p += hostname_len + 3; + } + + if( servername_list_size != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len || + buf[0] != ssl->verify_data_len || + mbedtls_ssl_safer_memcmp( buf + 1, ssl->peer_verify_data, + ssl->verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + +/* + * Status of the implementation of signature-algorithms extension: + * + * Currently, we are only considering the signature-algorithm extension + * to pick a ciphersuite which allows us to send the ServerKeyExchange + * message with a signature-hash combination that the user allows. + * + * We do *not* check whether all certificates in our certificate + * chain are signed with an allowed signature-hash pair. + * This needs to be done at a later stage. + * + */ +static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t sig_alg_list_size; + + const unsigned char *p; + const unsigned char *end = buf + len; + + mbedtls_md_type_t md_cur; + mbedtls_pk_type_t sig_cur; + + if ( len < 2 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( sig_alg_list_size + 2 != len || + sig_alg_list_size % 2 != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Currently we only guarantee signing the ServerKeyExchange message according + * to the constraints specified in this extension (see above), so it suffices + * to remember only one suitable hash for each possible signature algorithm. + * + * This will change when we also consider certificate signatures, + * in which case we will need to remember the whole signature-hash + * pair list from the extension. + */ + + for( p = buf + 2; p < end; p += 2 ) + { + /* Silently ignore unknown signature or hash algorithms. */ + + if( ( sig_cur = mbedtls_ssl_pk_alg_from_sig( p[1] ) ) == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext" + " unknown sig alg encoding %d", p[1] ) ); + continue; + } + + /* Check if we support the hash the user proposes */ + md_cur = mbedtls_ssl_md_alg_from_hash( p[0] ); + if( md_cur == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" + " unknown hash alg encoding %d", p[0] ) ); + continue; + } + + if( mbedtls_ssl_check_sig_hash( ssl, md_cur ) == 0 ) + { + mbedtls_ssl_sig_hash_set_add( &ssl->handshake->hash_algs, sig_cur, md_cur ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" + " match sig %d and hash %d", + sig_cur, md_cur ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: " + "hash alg %d not supported", md_cur ) ); + } + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size, our_size; + const unsigned char *p; + const mbedtls_ecp_curve_info *curve_info, **curves; + + if ( len < 2 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( list_size + 2 != len || + list_size % 2 != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Should never happen unless client duplicates the extension */ + if( ssl->handshake->curves != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Don't allow our peer to make us allocate too much memory, + * and leave room for a final 0 */ + our_size = list_size / 2 + 1; + if( our_size > MBEDTLS_ECP_DP_MAX ) + our_size = MBEDTLS_ECP_DP_MAX; + + if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + ssl->handshake->curves = curves; + + p = buf + 2; + while( list_size > 0 && our_size > 1 ) + { + curve_info = mbedtls_ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] ); + + if( curve_info != NULL ) + { + *curves++ = curve_info; + our_size--; + } + + list_size -= 2; + p += 2; + } + + return( 0 ); +} + +static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + if( len == 0 || (size_t)( buf[0] + 1 ) != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + list_size = buf[0]; + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || + p[0] == MBEDTLS_ECP_PF_COMPRESSED ) + { +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl->handshake->ecjpake_ctx.point_format = p[0]; +#endif + MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + + if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); + return( 0 ); + } + + if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, + buf, len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( ret ); + } + + /* Only mark the extension as OK when we're sure it is */ + ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->session_negotiate->mfl_code = buf[0]; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) + ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t len ) +{ + int ret; + mbedtls_ssl_session session; + + mbedtls_ssl_session_init( &session ); + + if( ssl->conf->f_ticket_parse == NULL || + ssl->conf->f_ticket_write == NULL ) + { + return( 0 ); + } + + /* Remember the client asked us to send a new ticket */ + ssl->handshake->new_session_ticket = 1; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", len ) ); + + if( len == 0 ) + return( 0 ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* + * Failures are ok: just ignore the ticket and proceed. + */ + if( ( ret = ssl->conf->f_ticket_parse( ssl->conf->p_ticket, &session, + buf, len ) ) != 0 ) + { + mbedtls_ssl_session_free( &session ); + + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is not authentic" ) ); + else if( ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED ) + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is expired" ) ); + else + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_parse", ret ); + + return( 0 ); + } + + /* + * Keep the session ID sent by the client, since we MUST send it back to + * inform them we're accepting the ticket (RFC 5077 section 3.4) + */ + session.id_len = ssl->session_negotiate->id_len; + memcpy( &session.id, ssl->session_negotiate->id, session.id_len ); + + mbedtls_ssl_session_free( ssl->session_negotiate ); + memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) ); + + /* Zeroize instead of free as we copied the content */ + mbedtls_platform_zeroize( &session, sizeof( mbedtls_ssl_session ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) ); + + ssl->handshake->resume = 1; + + /* Don't send a new ticket after all, this one is OK */ + ssl->handshake->new_session_ticket = 0; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) +static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, cur_len, ours_len; + const unsigned char *theirs, *start, *end; + const char **ours; + + /* If ALPN not configured, just ignore the extension */ + if( ssl->conf->alpn_list == NULL ) + return( 0 ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Validate peer's list (lengths) + */ + start = buf + 2; + end = buf + len; + for( theirs = start; theirs != end; theirs += cur_len ) + { + cur_len = *theirs++; + + /* Current identifier must fit in list */ + if( cur_len > (size_t)( end - theirs ) ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Empty strings MUST NOT be included */ + if( cur_len == 0 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + + /* + * Use our order of preference + */ + for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ ) + { + ours_len = strlen( *ours ); + for( theirs = start; theirs != end; theirs += cur_len ) + { + cur_len = *theirs++; + + if( cur_len == ours_len && + memcmp( theirs, *ours, cur_len ) == 0 ) + { + ssl->alpn_chosen = *ours; + return( 0 ); + } + } + } + + /* If we get there, no match was found */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +/* + * Auxiliary functions for ServerHello parsing and related actions + */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * Return 0 if the given key uses one of the acceptable curves, -1 otherwise + */ +#if defined(MBEDTLS_ECDSA_C) +static int ssl_check_key_curve( mbedtls_pk_context *pk, + const mbedtls_ecp_curve_info **curves ) +{ + const mbedtls_ecp_curve_info **crv = curves; + mbedtls_ecp_group_id grp_id = mbedtls_pk_ec( *pk )->grp.id; + + while( *crv != NULL ) + { + if( (*crv)->grp_id == grp_id ) + return( 0 ); + crv++; + } + + return( -1 ); +} +#endif /* MBEDTLS_ECDSA_C */ + +/* + * Try picking a certificate for this ciphersuite, + * return 0 on success and -1 on failure. + */ +static int ssl_pick_cert( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t * ciphersuite_info ) +{ + mbedtls_ssl_key_cert *cur, *list, *fallback = NULL; + mbedtls_pk_type_t pk_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + uint32_t flags; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_key_cert != NULL ) + list = ssl->handshake->sni_key_cert; + else +#endif + list = ssl->conf->key_cert; + + if( pk_alg == MBEDTLS_PK_NONE ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) ); + + if( list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server has no certificate" ) ); + return( -1 ); + } + + for( cur = list; cur != NULL; cur = cur->next ) + { + MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", + cur->cert ); + + if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) ); + continue; + } + + /* + * This avoids sending the client a cert it'll reject based on + * keyUsage or other extensions. + * + * It also allows the user to provision different certificates for + * different uses based on keyUsage, eg if they want to avoid signing + * and decrypting with the same RSA key. + */ + if( mbedtls_ssl_check_cert_usage( cur->cert, ciphersuite_info, + MBEDTLS_SSL_IS_SERVER, &flags ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: " + "(extended) key usage extension" ) ); + continue; + } + +#if defined(MBEDTLS_ECDSA_C) + if( pk_alg == MBEDTLS_PK_ECDSA && + ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) ); + continue; + } +#endif + + /* + * Try to select a SHA-1 certificate for pre-1.2 clients, but still + * present them a SHA-higher cert rather than failing if it's the only + * one we got that satisfies the other conditions. + */ + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 && + cur->cert->sig_md != MBEDTLS_MD_SHA1 ) + { + if( fallback == NULL ) + fallback = cur; + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate not preferred: " + "sha-2 with pre-TLS 1.2 client" ) ); + continue; + } + } + + /* If we get there, we got a winner */ + break; + } + + if( cur == NULL ) + cur = fallback; + + /* Do not update ssl->handshake->key_cert unless there is a match */ + if( cur != NULL ) + { + ssl->handshake->key_cert = cur; + MBEDTLS_SSL_DEBUG_CRT( 3, "selected certificate chain, certificate", + ssl->handshake->key_cert->cert ); + return( 0 ); + } + + return( -1 ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Check if a given ciphersuite is suitable for use with our config/keys/etc + * Sets ciphersuite_info only if the suite matches. + */ +static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, + const mbedtls_ssl_ciphersuite_t **ciphersuite_info ) +{ + const mbedtls_ssl_ciphersuite_t *suite_info; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + mbedtls_pk_type_t sig_type; +#endif + + suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id ); + if( suite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %s", suite_info->name ) ); + + if( suite_info->min_minor_ver > ssl->minor_ver || + suite_info->max_minor_ver < ssl->minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) ); + return( 0 ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 0 ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: rc4" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + ( ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: ecjpake " + "not configured or ext missing" ) ); + return( 0 ); + } +#endif + + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + if( mbedtls_ssl_ciphersuite_uses_ec( suite_info ) && + ( ssl->handshake->curves == NULL || + ssl->handshake->curves[0] == NULL ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no common elliptic curve" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + /* If the ciphersuite requires a pre-shared key and we don't + * have one, skip it now rather than failing later */ + if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && + ssl->conf->f_psk == NULL && + ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || + ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + /* If the ciphersuite requires signing, check whether + * a suitable hash algorithm is present. */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + sig_type = mbedtls_ssl_get_ciphersuite_sig_alg( suite_info ); + if( sig_type != MBEDTLS_PK_NONE && + mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, sig_type ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no suitable hash algorithm " + "for signature algorithm %d", sig_type ) ); + return( 0 ); + } + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * Final check: if ciphersuite requires us to have a + * certificate/key of a particular type: + * - select the appropriate certificate if we have one, or + * - try the next ciphersuite if we don't + * This must be done last since we modify the key_cert list. + */ + if( ssl_pick_cert( ssl, suite_info ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no suitable certificate" ) ); + return( 0 ); + } +#endif + + *ciphersuite_info = suite_info; + return( 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) +{ + int ret, got_common_suite; + unsigned int i, j; + size_t n; + unsigned int ciph_len, sess_len, chal_len; + unsigned char *buf, *p; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + buf = ssl->in_hdr; + + MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, 5 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d", + buf[2] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d", + ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]", + buf[3], buf[4] ) ); + + /* + * SSLv2 Client Hello + * + * Record layer: + * 0 . 1 message length + * + * SSL layer: + * 2 . 2 message type + * 3 . 4 protocol version + */ + if( buf[2] != MBEDTLS_SSL_HS_CLIENT_HELLO || + buf[3] != MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF; + + if( n < 17 || n > 512 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + ssl->minor_ver = ( buf[4] <= ssl->conf->max_minor_ver ) + ? buf[4] : ssl->conf->max_minor_ver; + + if( ssl->minor_ver < ssl->conf->min_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + ssl->handshake->max_major_ver = buf[3]; + ssl->handshake->max_minor_ver = buf[4]; + + if( ( ret = mbedtls_ssl_fetch_input( ssl, 2 + n ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + ssl->handshake->update_checksum( ssl, buf + 2, n ); + + buf = ssl->in_msg; + n = ssl->in_left - 5; + + /* + * 0 . 1 ciphersuitelist length + * 2 . 3 session id length + * 4 . 5 challenge length + * 6 . .. ciphersuitelist + * .. . .. session id + * .. . .. challenge + */ + MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, n ); + + ciph_len = ( buf[0] << 8 ) | buf[1]; + sess_len = ( buf[2] << 8 ) | buf[3]; + chal_len = ( buf[4] << 8 ) | buf[5]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d", + ciph_len, sess_len, chal_len ) ); + + /* + * Make sure each parameter length is valid + */ + if( ciph_len < 3 || ( ciph_len % 3 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( sess_len > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( chal_len < 8 || chal_len > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( n != 6 + ciph_len + sess_len + chal_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + 6, ciph_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", + buf + 6 + ciph_len, sess_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, challenge", + buf + 6 + ciph_len + sess_len, chal_len ); + + p = buf + 6 + ciph_len; + ssl->session_negotiate->id_len = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->id_len ); + + p += sess_len; + memset( ssl->handshake->randbytes, 0, 64 ); + memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len ); + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) + { + if( p[0] == 0 && p[1] == 0 && p[2] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " + "during renegotiation" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + break; + } + } + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) + { + if( p[0] == 0 && + p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && + p[2] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) ); + + if( ssl->minor_ver < ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + break; + } + } +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ + + got_common_suite = 0; + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) + for( i = 0; ciphersuites[i] != 0; i++ ) +#else + for( i = 0; ciphersuites[i] != 0; i++ ) + for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) +#endif + { + if( p[0] != 0 || + p[1] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || + p[2] != ( ( ciphersuites[i] ) & 0xFF ) ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite_v2; + } + + if( got_common_suite ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + +have_ciphersuite_v2: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; + + /* + * SSLv2 Client Hello relevant renegotiation security checks + */ + if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->in_left = 0; + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ + +/* This function doesn't alert on errors that happen early during + ClientHello parsing because they might indicate that the client is + not talking SSL/TLS at all and would not understand our alert. */ +static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret, got_common_suite; + size_t i, j; + size_t ciph_offset, comp_offset, ext_offset; + size_t msg_len, ciph_len, sess_len, comp_len, ext_len; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + size_t cookie_offset, cookie_len; +#endif + unsigned char *buf, *p, *ext; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + int major, minor; + + /* If there is no signature-algorithm extension present, + * we need to fall back to the default values for allowed + * signature-hash pairs. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + int sig_hash_alg_ext_present = 0; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +read_record_header: +#endif + /* + * If renegotiating, then the input was read with mbedtls_ssl_read_record(), + * otherwise read it ourselves manually in order to support SSLv2 + * ClientHello, which doesn't use the same record layer format. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 ) + { + /* No alert on a read error. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + } + + buf = ssl->in_hdr; + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) +#endif + if( ( buf[0] & 0x80 ) != 0 ) + return( ssl_parse_client_hello_v2( ssl ) ); +#endif + + MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_hdr_len( ssl ) ); + + /* + * SSLv3/TLS Client Hello + * + * Record layer: + * 0 . 0 message type + * 1 . 2 protocol version + * 3 . 11 DTLS: epoch + record sequence number + * 3 . 4 message length + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d", + buf[0] ) ); + + if( buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d", + ( ssl->in_len[0] << 8 ) | ssl->in_len[1] ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, protocol version: [%d:%d]", + buf[1], buf[2] ) ); + + mbedtls_ssl_read_version( &major, &minor, ssl->conf->transport, buf + 1 ); + + /* According to RFC 5246 Appendix E.1, the version here is typically + * "{03,00}, the lowest version number supported by the client, [or] the + * value of ClientHello.client_version", so the only meaningful check here + * is the major version shouldn't be less than 3 */ + if( major < MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* For DTLS if this is the initial handshake, remember the client sequence + * number to use it in our next message (RFC 6347 4.2.1) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) + { + /* Epoch should be 0 for initial handshakes */ + if( ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + memcpy( ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6 ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record, discarding" ) ); + ssl->next_record_offset = 0; + ssl->in_left = 0; + goto read_record_header; + } + + /* No MAC to check yet, so we can update right now */ + mbedtls_ssl_dtls_replay_update( ssl ); +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + msg_len = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Set by mbedtls_ssl_read_record() */ + msg_len = ssl->in_hslen; + } + else +#endif + { + if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( ( ret = mbedtls_ssl_fetch_input( ssl, + mbedtls_ssl_hdr_len( ssl ) + msg_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + /* Done reading this record, get ready for the next one */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->next_record_offset = msg_len + mbedtls_ssl_hdr_len( ssl ); + else +#endif + ssl->in_left = 0; + } + + buf = ssl->in_msg; + + MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, msg_len ); + + ssl->handshake->update_checksum( ssl, buf, msg_len ); + + /* + * Handshake layer: + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 DTLS only: message seqence number + * 6 . 8 DTLS only: fragment offset + * 9 . 11 DTLS only: fragment length + */ + if( msg_len < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", buf[0] ) ); + + if( buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d", + ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) ); + + /* We don't support fragmentation of ClientHello (yet?) */ + if( buf[1] != 0 || + msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* + * Copy the client's handshake message_seq on initial handshakes, + * check sequence number on renego. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + /* This couldn't be done in ssl_prepare_handshake_record() */ + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + + if( cli_msg_seq != ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: " + "%d (expected %d)", cli_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->handshake->in_msg_seq++; + } + else +#endif + { + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + ssl->handshake->out_msg_seq = cli_msg_seq; + ssl->handshake->in_msg_seq = cli_msg_seq + 1; + } + + /* + * For now we don't support fragmentation, so make sure + * fragment_offset == 0 and fragment_length == length + */ + if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 || + memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ClientHello fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + buf += mbedtls_ssl_hs_hdr_len( ssl ); + msg_len -= mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * ClientHello layer: + * 0 . 1 protocol version + * 2 . 33 random bytes (starting with 4 bytes of Unix time) + * 34 . 35 session id length (1 byte) + * 35 . 34+x session id + * 35+x . 35+x DTLS only: cookie length (1 byte) + * 36+x . .. DTLS only: cookie + * .. . .. ciphersuite list length (2 bytes) + * .. . .. ciphersuite list + * .. . .. compression alg. list length (1 byte) + * .. . .. compression alg. list + * .. . .. extensions length (2 bytes, optional) + * .. . .. extensions (optional) + */ + + /* + * Minimal length (with everything empty and extensions omitted) is + * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can + * read at least up to session id length without worrying. + */ + if( msg_len < 38 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Check and save the protocol version + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, version", buf, 2 ); + + mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, + ssl->conf->transport, buf ); + + ssl->handshake->max_major_ver = ssl->major_ver; + ssl->handshake->max_minor_ver = ssl->minor_ver; + + if( ssl->major_ver < ssl->conf->min_major_ver || + ssl->minor_ver < ssl->conf->min_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + if( ssl->major_ver > ssl->conf->max_major_ver ) + { + ssl->major_ver = ssl->conf->max_major_ver; + ssl->minor_ver = ssl->conf->max_minor_ver; + } + else if( ssl->minor_ver > ssl->conf->max_minor_ver ) + ssl->minor_ver = ssl->conf->max_minor_ver; + + /* + * Save client random (inc. Unix time) + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 2, 32 ); + + memcpy( ssl->handshake->randbytes, buf + 2, 32 ); + + /* + * Check the session ID length and save session ID + */ + sess_len = buf[34]; + + if( sess_len > sizeof( ssl->session_negotiate->id ) || + sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 35, sess_len ); + + ssl->session_negotiate->id_len = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, buf + 35, + ssl->session_negotiate->id_len ); + + /* + * Check the cookie length and content + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + cookie_offset = 35 + sess_len; + cookie_len = buf[cookie_offset]; + + if( cookie_offset + 1 + cookie_len + 2 > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", + buf + cookie_offset + 1, cookie_len ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( ssl->conf->f_cookie_check != NULL +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) + { + if( ssl->conf->f_cookie_check( ssl->conf->p_cookie, + buf + cookie_offset + 1, cookie_len, + ssl->cli_id, ssl->cli_id_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) ); + ssl->handshake->verify_cookie_len = 1; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) ); + ssl->handshake->verify_cookie_len = 0; + } + } + else +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + { + /* We know we didn't send a cookie, so it should be empty */ + if( cookie_len != 0 ) + { + /* This may be an attacker's probe, so don't send an alert */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification skipped" ) ); + } + + /* + * Check the ciphersuitelist length (will be parsed later) + */ + ciph_offset = cookie_offset + 1 + cookie_len; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + ciph_offset = 35 + sess_len; + + ciph_len = ( buf[ciph_offset + 0] << 8 ) + | ( buf[ciph_offset + 1] ); + + if( ciph_len < 2 || + ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */ + ( ciph_len % 2 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + ciph_offset + 2, ciph_len ); + + /* + * Check the compression algorithms length and pick one + */ + comp_offset = ciph_offset + 2 + ciph_len; + + comp_len = buf[comp_offset]; + + if( comp_len < 1 || + comp_len > 16 || + comp_len + comp_offset + 1 > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, compression", + buf + comp_offset + 1, comp_len ); + + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; +#if defined(MBEDTLS_ZLIB_SUPPORT) + for( i = 0; i < comp_len; ++i ) + { + if( buf[comp_offset + 1 + i] == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_DEFLATE; + break; + } + } +#endif + + /* See comments in ssl_write_client_hello() */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; +#endif + + /* Do not parse the extensions if the protocol is SSLv3 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) + { +#endif + /* + * Check the extension length + */ + ext_offset = comp_offset + 1 + comp_len; + if( msg_len > ext_offset ) + { + if( msg_len < ext_offset + 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ext_len = ( buf[ext_offset + 0] << 8 ) + | ( buf[ext_offset + 1] ); + + if( ( ext_len > 0 && ext_len < 4 ) || + msg_len != ext_offset + 2 + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + else + ext_len = 0; + + ext = buf + ext_offset + 2; + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", ext, ext_len ); + + while( ext_len != 0 ) + { + unsigned int ext_id; + unsigned int ext_size; + if ( ext_len < 4 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + ext_id = ( ( ext[0] << 8 ) | ( ext[1] ) ); + ext_size = ( ( ext[2] << 8 ) | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + switch( ext_id ) + { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + case MBEDTLS_TLS_EXT_SERVERNAME: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) ); + if( ssl->conf->f_sni == NULL ) + break; + + ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + + case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + case MBEDTLS_TLS_EXT_SIG_ALG: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); + + ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + + sig_hash_alg_ext_present = 1; + break; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) ); + + ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) ); + ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; + + ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake kkpp extension" ) ); + + ret = ssl_parse_ecjpake_kkpp( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) ); + + ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) ); + + ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) ); + + ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) ); + + ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_TLS_EXT_SESSION_TICKET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) ); + + ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", + ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } +#if defined(MBEDTLS_SSL_PROTO_SSL3) + } +#endif + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && + p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received FALLBACK_SCSV" ) ); + + if( ssl->minor_ver < ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + break; + } + } +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + + /* + * Try to fall back to default hash SHA1 if the client + * hasn't provided any preferred signature-hash combinations. + */ + if( sig_hash_alg_ext_present == 0 ) + { + mbedtls_md_type_t md_default = MBEDTLS_MD_SHA1; + + if( mbedtls_ssl_check_sig_hash( ssl, md_default ) != 0 ) + md_default = MBEDTLS_MD_NONE; + + mbedtls_ssl_sig_hash_set_const_hash( &ssl->handshake->hash_algs, md_default ); + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " + "during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + break; + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Search for a matching ciphersuite + * (At the end because we need information from the EC-based extensions + * and certificate from the SNI callback triggered by the SNI extension.) + */ + got_common_suite = 0; + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) + for( i = 0; ciphersuites[i] != 0; i++ ) +#else + for( i = 0; ciphersuites[i] != 0; i++ ) + for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) +#endif + { + if( p[0] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || + p[1] != ( ( ciphersuites[i] ) & 0xFF ) ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite; + } + + if( got_common_suite ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + +have_ciphersuite: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + /* Debugging-only output for testsuite */ +#if defined(MBEDTLS_DEBUG_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg( ciphersuite_info ); + if( sig_alg != MBEDTLS_PK_NONE ) + { + mbedtls_md_type_t md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, + sig_alg ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", + mbedtls_ssl_hash_from_md_alg( md_alg ) ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no hash algorithm for signature algorithm " + "%d - should not happen", sig_alg ) ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const mbedtls_ssl_ciphersuite_t *suite = NULL; + const mbedtls_cipher_info_t *cipher = NULL; + + if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + *olen = 0; + return; + } + + /* + * RFC 7366: "If a server receives an encrypt-then-MAC request extension + * from a client and then selects a stream or Authenticated Encryption + * with Associated Data (AEAD) ciphersuite, it MUST NOT send an + * encrypt-then-MAC response extension back to the client." + */ + if( ( suite = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite ) ) == NULL || + ( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL || + cipher->mode != MBEDTLS_MODE_CBC ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret " + "extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->new_session_ticket == 0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + *p++ = 0x00; + *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF; + *p++ = ssl->verify_data_len * 2 & 0xFF; + + memcpy( p, ssl->peer_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + *p++ = 0x00; + *p++ = 0x01; + *p++ = 0x00; + } + + *olen = p - buf; +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->session_negotiate->mfl_code; + + *olen = 5; +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + ((void) ssl); + + if( ( ssl->handshake->cli_exts & + MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; + + *olen = 6; +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + int ret; + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + size_t kkpp_len; + + *olen = 0; + + /* Skip costly computation if not needed */ + if( ssl->transform_negotiate->ciphersuite_info->key_exchange != + MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, ecjpake kkpp extension" ) ); + + if( end - p < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); + + ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, + p + 2, end - p - 2, &kkpp_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); + return; + } + + *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); + + *olen = kkpp_len + 4; +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN ) +static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + if( ssl->alpn_chosen == NULL ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) ); + + /* + * 0 . 1 ext identifier + * 2 . 3 ext length + * 4 . 5 protocol list length + * 6 . 6 protocol name length + * 7 . 7+n protocol name + */ + buf[0] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); + buf[1] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); + + *olen = 7 + strlen( ssl->alpn_chosen ); + + buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); + buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); + + buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); + buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); + + buf[6] = (unsigned char)( ( ( *olen - 7 ) ) & 0xFF ); + + memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *p = ssl->out_msg + 4; + unsigned char *cookie_len_byte; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello verify request" ) ); + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + + /* The RFC is not clear on this point, but sending the actual negotiated + * version looks like the most interoperable thing to do. */ + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, p ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); + p += 2; + + /* If we get here, f_cookie_check is not null */ + if( ssl->conf->f_cookie_write == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inconsistent cookie callbacks" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Skip length byte until we know the length */ + cookie_len_byte = p++; + + if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie, + &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN, + ssl->cli_id, ssl->cli_id_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret ); + return( ret ); + } + + *cookie_len_byte = (unsigned char)( p - ( cookie_len_byte + 1 ) ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte ); + + ssl->out_msglen = p - ssl->out_msg; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + + ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t; +#endif + int ret; + size_t olen, ext_len = 0, n; + unsigned char *buf, *p; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->verify_cookie_len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ssl_write_hello_verify_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 protocol version + * 6 . 9 UNIX time() + * 10 . 37 random bytes + */ + buf = ssl->out_msg; + p = buf + 4; + + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, p ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", + buf[4], buf[5] ) ); + +#if defined(MBEDTLS_HAVE_TIME) + t = mbedtls_time( NULL ); + *p++ = (unsigned char)( t >> 24 ); + *p++ = (unsigned char)( t >> 16 ); + *p++ = (unsigned char)( t >> 8 ); + *p++ = (unsigned char)( t ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); +#else + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* MBEDTLS_HAVE_TIME */ + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + p += 28; + + memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); + + /* + * Resume is 0 by default, see ssl_handshake_init(). + * It may be already set to 1 by ssl_parse_session_ticket_ext(). + * If not, try looking up session ID in our cache. + */ + if( ssl->handshake->resume == 0 && +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE && +#endif + ssl->session_negotiate->id_len != 0 && + ssl->conf->f_get_cache != NULL && + ssl->conf->f_get_cache( ssl->conf->p_cache, ssl->session_negotiate ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) ); + ssl->handshake->resume = 1; + } + + if( ssl->handshake->resume == 0 ) + { + /* + * New session, create a new session id, + * unless we're about to issue a session ticket + */ + ssl->state++; + +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time( NULL ); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + { + ssl->session_negotiate->id_len = n = 0; + memset( ssl->session_negotiate->id, 0, 32 ); + } + else +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + { + ssl->session_negotiate->id_len = n = 32; + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, + n ) ) != 0 ) + return( ret ); + } + } + else + { + /* + * Resuming a session + */ + n = ssl->session_negotiate->id_len; + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + } + + /* + * 38 . 38 session id length + * 39 . 38+n session id + * 39+n . 40+n chosen ciphersuite + * 41+n . 41+n chosen compression alg. + * 42+n . 43+n extensions length + * 44+n . 43+n+m extensions + */ + *p++ = (unsigned char) ssl->session_negotiate->id_len; + memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + p += ssl->session_negotiate->id_len; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 ); + *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite ); + *p++ = (unsigned char)( ssl->session_negotiate->compression ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", + mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X", + ssl->session_negotiate->compression ) ); + + /* Do not write the extensions if the protocol is SSLv3 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) + { +#endif + + /* + * First write extensions, then the total length + */ + ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if ( mbedtls_ssl_ciphersuite_uses_ec( + mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) ) + { + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) ); + + if( ext_len > 0 ) + { + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + p += ext_len; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + } +#endif + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; + + ret = mbedtls_ssl_write_handshake_msg( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ret ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + size_t dn_size, total_dn_size; /* excluding length bytes */ + size_t ct_len, sa_len; /* including length bytes */ + unsigned char *buf, *p; + const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + const mbedtls_x509_crt *crt; + int authmode; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + ssl->state++; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) + authmode = ssl->handshake->sni_authmode; + else +#endif + authmode = ssl->conf->authmode; + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE || + authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + return( 0 ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 4 cert type count + * 5 .. m-1 cert types + * m .. m+1 sig alg length (TLS 1.2 only) + * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only) + * n .. n+1 length of all DNs + * n+2 .. n+3 length of DN 1 + * n+4 .. ... Distinguished Name #1 + * ... .. ... length of DN 2, etc. + */ + buf = ssl->out_msg; + p = buf + 4; + + /* + * Supported certificate types + * + * ClientCertificateType certificate_types<1..2^8-1>; + * enum { (255) } ClientCertificateType; + */ + ct_len = 0; + +#if defined(MBEDTLS_RSA_C) + p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN; +#endif +#if defined(MBEDTLS_ECDSA_C) + p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN; +#endif + + p[0] = (unsigned char) ct_len++; + p += ct_len; + + sa_len = 0; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Add signature_algorithms for verify (TLS 1.2) + * + * SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * enum { (255) } HashAlgorithm; + * enum { (255) } SignatureAlgorithm; + */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + const int *cur; + + /* + * Supported signature algorithms + */ + for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) + { + unsigned char hash = mbedtls_ssl_hash_from_md_alg( *cur ); + + if( MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md( ssl, hash ) ) + continue; + +#if defined(MBEDTLS_RSA_C) + p[2 + sa_len++] = hash; + p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA; +#endif +#if defined(MBEDTLS_ECDSA_C) + p[2 + sa_len++] = hash; + p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif + } + + p[0] = (unsigned char)( sa_len >> 8 ); + p[1] = (unsigned char)( sa_len ); + sa_len += 2; + p += sa_len; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* + * DistinguishedName certificate_authorities<0..2^16-1>; + * opaque DistinguishedName<1..2^16-1>; + */ + p += 2; + + total_dn_size = 0; + + if( ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED ) + { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + crt = ssl->handshake->sni_ca_chain; + else +#endif + crt = ssl->conf->ca_chain; + + while( crt != NULL && crt->version != 0 ) + { + dn_size = crt->subject_raw.len; + + if( end < p || + (size_t)( end - p ) < dn_size || + (size_t)( end - p ) < 2 + dn_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); + break; + } + + *p++ = (unsigned char)( dn_size >> 8 ); + *p++ = (unsigned char)( dn_size ); + memcpy( p, crt->subject_raw.p, dn_size ); + p += dn_size; + + MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); + + total_dn_size += 2 + dn_size; + crt = crt->next; + } + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST; + ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 ); + ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size ); + + ret = mbedtls_ssl_write_handshake_msg( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, + mbedtls_pk_ec( *mbedtls_ssl_own_key( ssl ) ), + MBEDTLS_ECDH_OURS ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \ + defined(MBEDTLS_SSL_ASYNC_PRIVATE) +static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl, + size_t *signature_len ) +{ + /* Append the signature to ssl->out_msg, leaving 2 bytes for the + * signature length which will be added in ssl_write_server_key_exchange + * after the call to ssl_prepare_server_key_exchange. + * ssl_write_server_key_exchange also takes care of incrementing + * ssl->out_msglen. */ + unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2; + size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN + - sig_start ); + int ret = ssl->conf->f_async_resume( ssl, + sig_start, signature_len, sig_max_len ); + if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + { + ssl->handshake->async_in_progress = 0; + mbedtls_ssl_set_async_operation_data( ssl, NULL ); + } + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_resume_server_key_exchange", ret ); + return( ret ); +} +#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && + defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ + +/* Prepare the ServerKeyExchange message, up to and including + * calculating the signature if any, but excluding formatting the + * signature and sending the message. */ +static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, + size_t *signature_len ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + unsigned char *dig_signed = NULL; +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ + + (void) ciphersuite_info; /* unused in some configurations */ +#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + (void) signature_len; +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + + ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */ + + /* + * + * Part 1: Provide key exchange parameters for chosen ciphersuite. + * + */ + + /* + * - ECJPAKE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + int ret; + size_t len = 0; + + ret = mbedtls_ecjpake_write_round_two( + &ssl->handshake->ecjpake_ctx, + ssl->out_msg + ssl->out_msglen, + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); + return( ret ); + } + + ssl->out_msglen += len; + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + + /* + * For (EC)DHE key exchanges with PSK, parameters are prefixed by support + * identity hint (RFC 4279, Sec. 3). Until someone needs this feature, + * we use empty support identity hints here. + **/ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + ssl->out_msg[ssl->out_msglen++] = 0x00; + ssl->out_msg[ssl->out_msglen++] = 0x00; + } +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + + /* + * - DHE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) ) + { + int ret; + size_t len = 0; + + if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mbedtls_dhm_set_group( &ssl->handshake->dhm_ctx, + &ssl->conf->dhm_P, + &ssl->conf->dhm_G ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_set_group", ret ); + return( ret ); + } + + if( ( ret = mbedtls_dhm_make_params( + &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + ssl->out_msg + ssl->out_msglen, &len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret ); + return( ret ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + dig_signed = ssl->out_msg + ssl->out_msglen; +#endif + + ssl->out_msglen += len; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED */ + + /* + * - ECDHE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdhe( ciphersuite_info ) ) + { + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + const mbedtls_ecp_curve_info **curve = NULL; + const mbedtls_ecp_group_id *gid; + int ret; + size_t len = 0; + + /* Match our preference list against the offered curves */ + for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) + for( curve = ssl->handshake->curves; *curve != NULL; curve++ ) + if( (*curve)->grp_id == *gid ) + goto curve_matching_done; + +curve_matching_done: + if( curve == NULL || *curve == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); + + if( ( ret = mbedtls_ecdh_setup( &ssl->handshake->ecdh_ctx, + (*curve)->grp_id ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret ); + return( ret ); + } + + if( ( ret = mbedtls_ecdh_make_params( + &ssl->handshake->ecdh_ctx, &len, + ssl->out_msg + ssl->out_msglen, + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret ); + return( ret ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + dig_signed = ssl->out_msg + ssl->out_msglen; +#endif + + ssl->out_msglen += len; + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ + + /* + * + * Part 2: For key exchanges involving the server signing the + * exchange parameters, compute and add the signature here. + * + */ +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) + { + size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed; + size_t hashlen = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + int ret; + + /* + * 2.1: Choose hash algorithm: + * A: For TLS 1.2, obey signature-hash-algorithm extension + * to choose appropriate hash. + * B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1 + * (RFC 4492, Sec. 5.4) + * C: Otherwise, use MD5 + SHA1 (RFC 4346, Sec. 7.4.3) + */ + + mbedtls_md_type_t md_alg; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_pk_type_t sig_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* A: For TLS 1.2, obey signature-hash-algorithm extension + * (RFC 5246, Sec. 7.4.1.4.1). */ + if( sig_alg == MBEDTLS_PK_NONE || + ( md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, + sig_alg ) ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + /* (... because we choose a cipher suite + * only if there is a matching hash.) */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + /* B: Default hash SHA1 */ + md_alg = MBEDTLS_MD_SHA1; + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + { + /* C: MD5 + SHA1 */ + md_alg = MBEDTLS_MD_NONE; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) ); + + /* + * 2.2: Compute the hash to be signed + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( md_alg == MBEDTLS_MD_NONE ) + { + hashlen = 36; + ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, + dig_signed, + dig_signed_len ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( md_alg != MBEDTLS_MD_NONE ) + { + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, + dig_signed, + dig_signed_len, + md_alg ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); + + /* + * 2.3: Compute and add the signature + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * For TLS 1.2, we need to specify signature and hash algorithm + * explicitly through a prefix to the signature. + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * struct { + * SignatureAndHashAlgorithm algorithm; + * opaque signature<0..2^16-1>; + * } DigitallySigned; + * + */ + + ssl->out_msg[ssl->out_msglen++] = + mbedtls_ssl_hash_from_md_alg( md_alg ); + ssl->out_msg[ssl->out_msglen++] = + mbedtls_ssl_sig_from_pk_alg( sig_alg ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_sign_start != NULL ) + { + ret = ssl->conf->f_async_sign_start( ssl, + mbedtls_ssl_own_cert( ssl ), + md_alg, hash, hashlen ); + switch( ret ) + { + case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: + /* act as if f_async_sign was null */ + break; + case 0: + ssl->handshake->async_in_progress = 1; + return( ssl_resume_server_key_exchange( ssl, signature_len ) ); + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + ssl->handshake->async_in_progress = 1; + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + default: + MBEDTLS_SSL_DEBUG_RET( 1, "f_async_sign_start", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* Append the signature to ssl->out_msg, leaving 2 bytes for the + * signature length which will be added in ssl_write_server_key_exchange + * after the call to ssl_prepare_server_key_exchange. + * ssl_write_server_key_exchange also takes care of incrementing + * ssl->out_msglen. */ + if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), + md_alg, hash, hashlen, + ssl->out_msg + ssl->out_msglen + 2, + signature_len, + ssl->conf->f_rng, + ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + + return( 0 ); +} + +/* Prepare the ServerKeyExchange message and send it. For ciphersuites + * that do not include a ServerKeyExchange message, do nothing. Either + * way, if successful, move on to the next step in the SSL state + * machine. */ +static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t signature_len = 0; +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) + /* Extract static ECDH parameters and abort if ServerKeyExchange + * is not needed. */ + if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) ) + { + /* For suites involving ECDH, extract DH parameters + * from certificate at this point. */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) + { + ssl_get_ecdh_params_from_cert( ssl ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ + + /* Key exchanges not involving ephemeral keys don't use + * ServerKeyExchange, so end here. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \ + defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /* If we have already prepared the message and there is an ongoing + * signature operation, resume signing. */ + if( ssl->handshake->async_in_progress != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming signature operation" ) ); + ret = ssl_resume_server_key_exchange( ssl, &signature_len ); + } + else +#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && + defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ + { + /* ServerKeyExchange is needed. Prepare the message. */ + ret = ssl_prepare_server_key_exchange( ssl, &signature_len ); + } + + if( ret != 0 ) + { + /* If we're starting to write a new message, set ssl->out_msglen + * to 0. But if we're resuming after an asynchronous message, + * out_msglen is the amount of data written so far and mst be + * preserved. */ + if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange (pending)" ) ); + else + ssl->out_msglen = 0; + return( ret ); + } + + /* If there is a signature, write its length. + * ssl_prepare_server_key_exchange already wrote the signature + * itself at its proper place in the output buffer. */ +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + if( signature_len != 0 ) + { + ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len >> 8 ); + ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", + ssl->out_msg + ssl->out_msglen, + signature_len ); + + /* Skip over the already-written signature */ + ssl->out_msglen += signature_len; + } +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + + /* Add header and send. */ + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); + return( 0 ); +} + +static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO_DONE; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t n; + + /* + * Receive G^Y mod P, premaster = (G^Y)^X mod P + */ + if( *p + 2 > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( *p + n > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + *p += n; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl, + unsigned char *peer_pms, + size_t *peer_pmslen, + size_t peer_pmssize ) +{ + int ret = ssl->conf->f_async_resume( ssl, + peer_pms, peer_pmslen, peer_pmssize ); + if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + { + ssl->handshake->async_in_progress = 0; + mbedtls_ssl_set_async_operation_data( ssl, NULL ); + } + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_decrypt_encrypted_pms", ret ); + return( ret ); +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + unsigned char *peer_pms, + size_t *peer_pmslen, + size_t peer_pmssize ) +{ + int ret; + mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl ); + mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk; + size_t len = mbedtls_pk_get_len( public_key ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /* If we have already started decoding the message and there is an ongoing + * decryption operation, resume signing. */ + if( ssl->handshake->async_in_progress != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming decryption operation" ) ); + return( ssl_resume_decrypt_pms( ssl, + peer_pms, peer_pmslen, peer_pmssize ) ); + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + /* + * Prepare to decrypt the premaster using own private RSA key + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if ( p + 2 > end ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + if( *p++ != ( ( len >> 8 ) & 0xFF ) || + *p++ != ( ( len ) & 0xFF ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + } +#endif + + if( p + len != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + /* + * Decrypt the premaster secret + */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_decrypt_start != NULL ) + { + ret = ssl->conf->f_async_decrypt_start( ssl, + mbedtls_ssl_own_cert( ssl ), + p, len ); + switch( ret ) + { + case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: + /* act as if f_async_decrypt_start was null */ + break; + case 0: + ssl->handshake->async_in_progress = 1; + return( ssl_resume_decrypt_pms( ssl, + peer_pms, + peer_pmslen, + peer_pmssize ) ); + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + ssl->handshake->async_in_progress = 1; + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + default: + MBEDTLS_SSL_DEBUG_RET( 1, "f_async_decrypt_start", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + ret = mbedtls_pk_decrypt( private_key, p, len, + peer_pms, peer_pmslen, peer_pmssize, + ssl->conf->f_rng, ssl->conf->p_rng ); + return( ret ); +} + +static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + size_t pms_offset ) +{ + int ret; + unsigned char *pms = ssl->handshake->premaster + pms_offset; + unsigned char ver[2]; + unsigned char fake_pms[48], peer_pms[48]; + unsigned char mask; + size_t i, peer_pmslen; + unsigned int diff; + + /* In case of a failure in decryption, the decryption may write less than + * 2 bytes of output, but we always read the first two bytes. It doesn't + * matter in the end because diff will be nonzero in that case due to + * ret being nonzero, and we only care whether diff is 0. + * But do initialize peer_pms and peer_pmslen for robustness anyway. This + * also makes memory analyzers happy (don't access uninitialized memory, + * even if it's an unsigned char). */ + peer_pms[0] = peer_pms[1] = ~0; + peer_pmslen = 0; + + ret = ssl_decrypt_encrypted_pms( ssl, p, end, + peer_pms, + &peer_pmslen, + sizeof( peer_pms ) ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if ( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + return( ret ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + mbedtls_ssl_write_version( ssl->handshake->max_major_ver, + ssl->handshake->max_minor_ver, + ssl->conf->transport, ver ); + + /* Avoid data-dependent branches while checking for invalid + * padding, to protect against timing-based Bleichenbacher-type + * attacks. */ + diff = (unsigned int) ret; + diff |= peer_pmslen ^ 48; + diff |= peer_pms[0] ^ ver[0]; + diff |= peer_pms[1] ^ ver[1]; + + /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + /* + * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding + * must not cause the connection to end immediately; instead, send a + * bad_record_mac later in the handshake. + * To protect against timing-based variants of the attack, we must + * not have any branch that depends on whether the decryption was + * successful. In particular, always generate the fake premaster secret, + * regardless of whether it will ultimately influence the output or not. + */ + ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) ); + if( ret != 0 ) + { + /* It's ok to abort on an RNG failure, since this does not reveal + * anything about the RSA decryption. */ + return( ret ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( diff != 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); +#endif + + if( sizeof( ssl->handshake->premaster ) < pms_offset || + sizeof( ssl->handshake->premaster ) - pms_offset < 48 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + ssl->handshake->pmslen = 48; + + /* Set pms to either the true or the fake PMS, without + * data-dependent branches. */ + for( i = 0; i < ssl->handshake->pmslen; i++ ) + pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = 0; + size_t n; + + if( ssl->conf->f_psk == NULL && + ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || + ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Receive client pre-shared key identity name + */ + if( end - *p < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( n < 1 || n > 65535 || n > (size_t) ( end - *p ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->conf->f_psk != NULL ) + { + if( ssl->conf->f_psk( ssl->conf->p_psk, ssl, *p, n ) != 0 ) + ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + else + { + /* Identity is not a big secret since clients send it in the clear, + * but treat it carefully anyway, just in case */ + if( n != ssl->conf->psk_identity_len || + mbedtls_ssl_safer_memcmp( ssl->conf->psk_identity, *p, n ) != 0 ) + { + ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + } + + if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ); + return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ); + } + + *p += n; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + unsigned char *p, *end; + + ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) ) + if( ( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) && + ( ssl->handshake->async_in_progress != 0 ) ) + { + /* We've already read a record and there is an asynchronous + * operation in progress to decrypt it. So skip reading the + * record. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "will resume decryption of previously-read record" ) ); + } + else +#endif + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + end = ssl->in_msg + ssl->in_hslen; + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) + { + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if ( ssl->handshake->async_in_progress != 0 ) + { + /* There is an asynchronous operation in progress to + * decrypt the encrypted premaster secret, so skip + * directly to resuming this operation. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "PSK identity already parsed" ) ); + /* Update p to skip the PSK identity. ssl_parse_encrypted_pms + * won't actually use it, but maintain p anyway for robustness. */ + p += ssl->conf->psk_identity_len + 2; + } + else +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); + return( ret ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, + ssl->handshake->premaster, 32, &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, sig_len; + unsigned char hash[48]; + unsigned char *hash_start = hash; + size_t hashlen; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_pk_type_t pk_alg; +#endif + mbedtls_md_type_t md_alg; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE || + ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + /* Read the message without adding it to the checksum */ + ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ ); + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record" ), ret ); + return( ret ); + } + + ssl->state++; + + /* Process the message contents */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || + ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * struct { + * SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only + * opaque signature<0..2^16-1>; + * } DigitallySigned; + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + md_alg = MBEDTLS_MD_NONE; + hashlen = 36; + + /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */ + if( mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, + MBEDTLS_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = MBEDTLS_MD_SHA1; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + if( i + 2 > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * Hash + */ + md_alg = mbedtls_ssl_md_alg_from_hash( ssl->in_msg[i] ); + + if( md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md( ssl, ssl->in_msg[i] ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + +#if !defined(MBEDTLS_MD_SHA1) + if( MBEDTLS_MD_SHA1 == md_alg ) + hash_start += 16; +#endif + + /* Info from md_alg will be used instead */ + hashlen = 0; + + i++; + + /* + * Signature + */ + if( ( pk_alg = mbedtls_ssl_pk_alg_from_sig( ssl->in_msg[i] ) ) + == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * Check the certificate's key type matches the signature alg + */ + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + i++; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( i + 2 > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + sig_len = ( ssl->in_msg[i] << 8 ) | ssl->in_msg[i+1]; + i += 2; + + if( i + sig_len != ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* Calculate hash and verify signature */ + ssl->handshake->calc_verify( ssl, hash ); + + if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, + md_alg, hash_start, hashlen, + ssl->in_msg + i, sig_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); + return( ret ); + } + + mbedtls_ssl_update_handshake_status( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t tlen; + uint32_t lifetime; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_NEW_SESSION_TICKET; + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 4 . 7 ticket_lifetime_hint (0 = unspecified) + * 8 . 9 ticket_len (n) + * 10 . 9+n ticket content + */ + + if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket, + ssl->session_negotiate, + ssl->out_msg + 10, + ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, + &tlen, &lifetime ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret ); + tlen = 0; + } + + ssl->out_msg[4] = ( lifetime >> 24 ) & 0xFF; + ssl->out_msg[5] = ( lifetime >> 16 ) & 0xFF; + ssl->out_msg[6] = ( lifetime >> 8 ) & 0xFF; + ssl->out_msg[7] = ( lifetime ) & 0xFF; + + ssl->out_msg[8] = (unsigned char)( ( tlen >> 8 ) & 0xFF ); + ssl->out_msg[9] = (unsigned char)( ( tlen ) & 0xFF ); + + ssl->out_msglen = 10 + tlen; + + /* + * Morally equivalent to updating ssl->state, but NewSessionTicket and + * ChangeCipherSpec share the same state. + */ + ssl->handshake->new_session_ticket = 0; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- server side -- single step + */ +int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) ); + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + switch( ssl->state ) + { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + break; + + /* + * <== ClientHello + */ + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_parse_client_hello( ssl ); + break; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +#endif + + /* + * ==> ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_write_server_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = mbedtls_ssl_write_certificate( ssl ); + break; + + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + ret = ssl_write_server_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_write_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO_DONE: + ret = ssl_write_server_hello_done( ssl ); + break; + + /* + * <== ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_parse_certificate( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_parse_client_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_parse_certificate_verify( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = mbedtls_ssl_parse_finished( ssl ); + break; + + /* + * ==> ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + ret = ssl_write_new_session_ticket( ssl ); + else +#endif + ret = mbedtls_ssl_write_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = mbedtls_ssl_write_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + mbedtls_ssl_handshake_wrapup( ssl ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_SRV_C */ diff --git a/external/mbedtls/library/ssl_ticket.c b/external/mbedtls/library/ssl_ticket.c new file mode 100644 index 0000000..bbde8e4 --- /dev/null +++ b/external/mbedtls/library/ssl_ticket.c @@ -0,0 +1,530 @@ +/* + * TLS server tickets callbacks implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_internal.h" +#include "mbedtls/ssl_ticket.h" +#include "mbedtls/platform_util.h" + +#include + +/* + * Initialze context + */ +void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ssl_ticket_context ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +#define MAX_KEY_BYTES 32 /* 256 bits */ + +#define TICKET_KEY_NAME_BYTES 4 +#define TICKET_IV_BYTES 12 +#define TICKET_CRYPT_LEN_BYTES 2 +#define TICKET_AUTH_TAG_BYTES 16 + +#define TICKET_MIN_LEN ( TICKET_KEY_NAME_BYTES + \ + TICKET_IV_BYTES + \ + TICKET_CRYPT_LEN_BYTES + \ + TICKET_AUTH_TAG_BYTES ) +#define TICKET_ADD_DATA_LEN ( TICKET_KEY_NAME_BYTES + \ + TICKET_IV_BYTES + \ + TICKET_CRYPT_LEN_BYTES ) + +/* + * Generate/update a key + */ +static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, + unsigned char index ) +{ + int ret; + unsigned char buf[MAX_KEY_BYTES]; + mbedtls_ssl_ticket_key *key = ctx->keys + index; + +#if defined(MBEDTLS_HAVE_TIME) + key->generation_time = (uint32_t) mbedtls_time( NULL ); +#endif + + if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 ) + return( ret ); + + if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 ) + return( ret ); + + /* With GCM and CCM, same context can encrypt & decrypt */ + ret = mbedtls_cipher_setkey( &key->ctx, buf, + mbedtls_cipher_get_key_bitlen( &key->ctx ), + MBEDTLS_ENCRYPT ); + + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +/* + * Rotate/generate keys if necessary + */ +static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) +{ +#if !defined(MBEDTLS_HAVE_TIME) + ((void) ctx); +#else + if( ctx->ticket_lifetime != 0 ) + { + uint32_t current_time = (uint32_t) mbedtls_time( NULL ); + uint32_t key_time = ctx->keys[ctx->active].generation_time; + + if( current_time >= key_time && + current_time - key_time < ctx->ticket_lifetime ) + { + return( 0 ); + } + + ctx->active = 1 - ctx->active; + + return( ssl_ticket_gen_key( ctx, ctx->active ) ); + } + else +#endif /* MBEDTLS_HAVE_TIME */ + return( 0 ); +} + +/* + * Setup context for actual use + */ +int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_cipher_type_t cipher, + uint32_t lifetime ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + ctx->f_rng = f_rng; + ctx->p_rng = p_rng; + + ctx->ticket_lifetime = lifetime; + + cipher_info = mbedtls_cipher_info_from_type( cipher); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( cipher_info->mode != MBEDTLS_MODE_GCM && + cipher_info->mode != MBEDTLS_MODE_CCM ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 || + ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 || + ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Serialize a session in the following format: + * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session) + * n . n+2 peer_cert length = m (0 if no certificate) + * n+3 . n+2+m peer cert ASN.1 + */ +static int ssl_save_session( const mbedtls_ssl_session *session, + unsigned char *buf, size_t buf_len, + size_t *olen ) +{ + unsigned char *p = buf; + size_t left = buf_len; +#if defined(MBEDTLS_X509_CRT_PARSE_C) + size_t cert_len; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( left < sizeof( mbedtls_ssl_session ) ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + memcpy( p, session, sizeof( mbedtls_ssl_session ) ); + p += sizeof( mbedtls_ssl_session ); + left -= sizeof( mbedtls_ssl_session ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( session->peer_cert == NULL ) + cert_len = 0; + else + cert_len = session->peer_cert->raw.len; + + if( left < 3 + cert_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( cert_len ) & 0xFF ); + + if( session->peer_cert != NULL ) + memcpy( p, session->peer_cert->raw.p, cert_len ); + + p += cert_len; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + *olen = p - buf; + + return( 0 ); +} + +/* + * Unserialise session, see ssl_save_session() + */ +static int ssl_load_session( mbedtls_ssl_session *session, + const unsigned char *buf, size_t len ) +{ + const unsigned char *p = buf; + const unsigned char * const end = buf + len; +#if defined(MBEDTLS_X509_CRT_PARSE_C) + size_t cert_len; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( session, p, sizeof( mbedtls_ssl_session ) ); + p += sizeof( mbedtls_ssl_session ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( 3 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; + + if( cert_len == 0 ) + { + session->peer_cert = NULL; + } + else + { + int ret; + + if( cert_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( session->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + mbedtls_x509_crt_init( session->peer_cert ); + + if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, + p, cert_len ) ) != 0 ) + { + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + return( ret ); + } + + p += cert_len; + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( p != end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Create session ticket, with the following structure: + * + * struct { + * opaque key_name[4]; + * opaque iv[12]; + * opaque encrypted_state<0..2^16-1>; + * opaque tag[16]; + * } ticket; + * + * The key_name, iv, and length of encrypted_state are the additional + * authenticated data. + */ + +int mbedtls_ssl_ticket_write( void *p_ticket, + const mbedtls_ssl_session *session, + unsigned char *start, + const unsigned char *end, + size_t *tlen, + uint32_t *ticket_lifetime ) +{ + int ret; + mbedtls_ssl_ticket_context *ctx = p_ticket; + mbedtls_ssl_ticket_key *key; + unsigned char *key_name = start; + unsigned char *iv = start + TICKET_KEY_NAME_BYTES; + unsigned char *state_len_bytes = iv + TICKET_IV_BYTES; + unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES; + unsigned char *tag; + size_t clear_len, ciph_len; + + *tlen = 0; + + if( ctx == NULL || ctx->f_rng == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, + * in addition to session itself, that will be checked when writing it. */ + MBEDTLS_SSL_CHK_BUF_PTR( start, end, TICKET_MIN_LEN ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) + goto cleanup; + + key = &ctx->keys[ctx->active]; + + *ticket_lifetime = ctx->ticket_lifetime; + + memcpy( key_name, key->name, TICKET_KEY_NAME_BYTES ); + + if( ( ret = ctx->f_rng( ctx->p_rng, iv, TICKET_IV_BYTES ) ) != 0 ) + goto cleanup; + + /* Dump session state */ + if( ( ret = ssl_save_session( session, + state, end - state, &clear_len ) ) != 0 || + (unsigned long) clear_len > 65535 ) + { + goto cleanup; + } + state_len_bytes[0] = ( clear_len >> 8 ) & 0xff; + state_len_bytes[1] = ( clear_len ) & 0xff; + + /* Encrypt and authenticate */ + tag = state + clear_len; + if( ( ret = mbedtls_cipher_auth_encrypt( &key->ctx, + iv, TICKET_IV_BYTES, + /* Additional data: key name, IV and length */ + key_name, TICKET_ADD_DATA_LEN, + state, clear_len, state, &ciph_len, + tag, TICKET_AUTH_TAG_BYTES ) ) != 0 ) + { + goto cleanup; + } + if( ciph_len != clear_len ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + *tlen = TICKET_MIN_LEN + ciph_len; + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Select key based on name + */ +static mbedtls_ssl_ticket_key *ssl_ticket_select_key( + mbedtls_ssl_ticket_context *ctx, + const unsigned char name[4] ) +{ + unsigned char i; + + for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ ) + if( memcmp( name, ctx->keys[i].name, 4 ) == 0 ) + return( &ctx->keys[i] ); + + return( NULL ); +} + +/* + * Load session ticket (see mbedtls_ssl_ticket_write for structure) + */ +int mbedtls_ssl_ticket_parse( void *p_ticket, + mbedtls_ssl_session *session, + unsigned char *buf, + size_t len ) +{ + int ret; + mbedtls_ssl_ticket_context *ctx = p_ticket; + mbedtls_ssl_ticket_key *key; + unsigned char *key_name = buf; + unsigned char *iv = buf + TICKET_KEY_NAME_BYTES; + unsigned char *enc_len_p = iv + TICKET_IV_BYTES; + unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES; + unsigned char *tag; + size_t enc_len, clear_len; + + if( ctx == NULL || ctx->f_rng == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( len < TICKET_MIN_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) + goto cleanup; + + enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; + tag = ticket + enc_len; + + if( len != TICKET_MIN_LEN + enc_len ) + { + ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + goto cleanup; + } + + /* Select key */ + if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL ) + { + /* We can't know for sure but this is a likely option unless we're + * under attack - this is only informative anyway */ + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; + goto cleanup; + } + + /* Decrypt and authenticate */ + if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx, + iv, TICKET_IV_BYTES, + /* Additional data: key name, IV and length */ + key_name, TICKET_ADD_DATA_LEN, + ticket, enc_len, + ticket, &clear_len, + tag, TICKET_AUTH_TAG_BYTES ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) + ret = MBEDTLS_ERR_SSL_INVALID_MAC; + + goto cleanup; + } + if( clear_len != enc_len ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + /* Actually load session */ + if( ( ret = ssl_load_session( session, ticket, clear_len ) ) != 0 ) + goto cleanup; + +#if defined(MBEDTLS_HAVE_TIME) + { + /* Check for expiration */ + mbedtls_time_t current_time = mbedtls_time( NULL ); + + if( current_time < session->start || + (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime ) + { + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; + goto cleanup; + } + } +#endif + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Free context + */ +void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ) +{ + mbedtls_cipher_free( &ctx->keys[0].ctx ); + mbedtls_cipher_free( &ctx->keys[1].ctx ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); +} + +#endif /* MBEDTLS_SSL_TICKET_C */ diff --git a/external/mbedtls/library/ssl_tls.c b/external/mbedtls/library/ssl_tls.c new file mode 100644 index 0000000..c749a86 --- /dev/null +++ b/external/mbedtls/library/ssl_tls.c @@ -0,0 +1,9914 @@ +/* + * SSLv3/TLSv1 shared functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The SSL 3.0 specification was drafted by Netscape in 1996, + * and became an IETF standard in 1999. + * + * http://wp.netscape.com/eng/ssl3/ + * http://www.ietf.org/rfc/rfc2246.txt + * http://www.ietf.org/rfc/rfc4346.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/oid.h" +#endif + +static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ); +static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ); + +/* Length of the "epoch" field in the record header */ +static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 2 ); +#else + ((void) ssl); +#endif + return( 0 ); +} + +/* + * Start a timer. + * Passing millisecs = 0 cancels a running timer. + */ +static void ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ) +{ + if( ssl->f_set_timer == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) ); + ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs ); +} + +/* + * Return -1 is timer is expired, 0 if it isn't. + */ +static int ssl_check_timer( mbedtls_ssl_context *ssl ) +{ + if( ssl->f_get_timer == NULL ) + return( 0 ); + + if( ssl->f_get_timer( ssl->p_timer ) == 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) ); + return( -1 ); + } + + return( 0 ); +} + +static void ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ); +static void ssl_update_in_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ); + +#define SSL_DONT_FORCE_FLUSH 0 +#define SSL_FORCE_FLUSH 1 + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +/* Forward declarations for functions related to message buffering. */ +static void ssl_buffering_free( mbedtls_ssl_context *ssl ); +static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, + uint8_t slot ); +static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ); +static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ); +static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ); +static int ssl_buffer_message( mbedtls_ssl_context *ssl ); +static int ssl_buffer_future_record( mbedtls_ssl_context *ssl ); +static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ); + +static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl ); +static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl ) +{ + size_t mtu = ssl_get_current_mtu( ssl ); + + if( mtu != 0 && mtu < MBEDTLS_SSL_OUT_BUFFER_LEN ) + return( mtu ); + + return( MBEDTLS_SSL_OUT_BUFFER_LEN ); +} + +static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl ) +{ + size_t const bytes_written = ssl->out_left; + size_t const mtu = ssl_get_maximum_datagram_size( ssl ); + + /* Double-check that the write-index hasn't gone + * past what we can transmit in a single datagram. */ + if( bytes_written > mtu ) + { + /* Should never happen... */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( (int) ( mtu - bytes_written ) ); +} + +static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl ) +{ + int ret; + size_t remaining, expansion; + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; + + /* By the standard (RFC 6066 Sect. 4), the MFL extension + * only limits the maximum record payload size, so in theory + * we would be allowed to pack multiple records of payload size + * MFL into a single datagram. However, this would mean that there's + * no way to explicitly communicate MTU restrictions to the peer. + * + * The following reduction of max_len makes sure that we never + * write datagrams larger than MFL + Record Expansion Overhead. + */ + if( max_len <= ssl->out_left ) + return( 0 ); + + max_len -= ssl->out_left; +#endif + + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + remaining = (size_t) ret; + + ret = mbedtls_ssl_get_record_expansion( ssl ); + if( ret < 0 ) + return( ret ); + expansion = (size_t) ret; + + if( remaining <= expansion ) + return( 0 ); + + remaining -= expansion; + if( remaining >= max_len ) + remaining = max_len; + + return( (int) remaining ); +} + +/* + * Double the retransmit timeout value, within the allowed range, + * returning -1 if the maximum value has already been reached. + */ +static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + uint32_t new_timeout; + + if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) + return( -1 ); + + /* Implement the final paragraph of RFC 6347 section 4.1.1.1 + * in the following way: after the initial transmission and a first + * retransmission, back off to a temporary estimated MTU of 508 bytes. + * This value is guaranteed to be deliverable (if not guaranteed to be + * delivered) of any compliant IPv4 (and IPv6) network, and should work + * on most non-IP stacks too. */ + if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min ) + { + ssl->handshake->mtu = 508; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) ); + } + + new_timeout = 2 * ssl->handshake->retransmit_timeout; + + /* Avoid arithmetic overflow and range overflow */ + if( new_timeout < ssl->handshake->retransmit_timeout || + new_timeout > ssl->conf->hs_timeout_max ) + { + new_timeout = ssl->conf->hs_timeout_max; + } + + ssl->handshake->retransmit_timeout = new_timeout; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", + ssl->handshake->retransmit_timeout ) ); + + return( 0 ); +} + +static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", + ssl->handshake->retransmit_timeout ) ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/* + * Convert max_fragment_length codes to length. + * RFC 6066 says: + * enum{ + * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) + * } MaxFragmentLength; + * and we add 0 -> extension unused + */ +static unsigned int ssl_mfl_code_to_length( int mfl ) +{ + switch( mfl ) + { + case MBEDTLS_SSL_MAX_FRAG_LEN_NONE: + return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); + case MBEDTLS_SSL_MAX_FRAG_LEN_512: + return 512; + case MBEDTLS_SSL_MAX_FRAG_LEN_1024: + return 1024; + case MBEDTLS_SSL_MAX_FRAG_LEN_2048: + return 2048; + case MBEDTLS_SSL_MAX_FRAG_LEN_4096: + return 4096; + default: + return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); + } +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_CLI_C) +static int ssl_session_copy( mbedtls_ssl_session *dst, const mbedtls_ssl_session *src ) +{ + mbedtls_ssl_session_free( dst ); + memcpy( dst, src, sizeof( mbedtls_ssl_session ) ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( src->peer_cert != NULL ) + { + int ret; + + dst->peer_cert = mbedtls_calloc( 1, sizeof(mbedtls_x509_crt) ); + if( dst->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + mbedtls_x509_crt_init( dst->peer_cert ); + + if( ( ret = mbedtls_x509_crt_parse_der( dst->peer_cert, src->peer_cert->raw.p, + src->peer_cert->raw.len ) ) != 0 ) + { + mbedtls_free( dst->peer_cert ); + dst->peer_cert = NULL; + return( ret ); + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( src->ticket != NULL ) + { + dst->ticket = mbedtls_calloc( 1, src->ticket_len ); + if( dst->ticket == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( dst->ticket, src->ticket, src->ticket_len ); + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + return( 0 ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) +int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl, + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen ) = NULL; +int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL; +int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL; +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +/* + * Key material generation + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static int ssl3_prf( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + int ret = 0; + size_t i; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char padding[16]; + unsigned char sha1sum[20]; + ((void)label); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + /* + * SSLv3: + * block = + * MD5( secret + SHA1( 'A' + secret + random ) ) + + * MD5( secret + SHA1( 'BB' + secret + random ) ) + + * MD5( secret + SHA1( 'CCC' + secret + random ) ) + + * ... + */ + for( i = 0; i < dlen / 16; i++ ) + { + memset( padding, (unsigned char) ('A' + i), 1 + i ); + + if( ( ret = mbedtls_sha1_starts_ret( &sha1 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, padding, 1 + i ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, secret, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, random, rlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_finish_ret( &sha1, sha1sum ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_starts_ret( &md5 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5, secret, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5, sha1sum, 20 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5, dstbuf + i * 16 ) ) != 0 ) + goto exit; + } + +exit: + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_platform_zeroize( padding, sizeof( padding ) ); + mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) ); + + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static int tls1_prf( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb, hs; + size_t i, j, k; + const unsigned char *S1, *S2; + unsigned char tmp[128]; + unsigned char h_i[20]; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret; + + mbedtls_md_init( &md_ctx ); + + if( sizeof( tmp ) < 20 + strlen( label ) + rlen ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + hs = ( slen + 1 ) / 2; + S1 = secret; + S2 = secret + slen - hs; + + nb = strlen( label ); + memcpy( tmp + 20, label, nb ); + memcpy( tmp + 20 + nb, random, rlen ); + nb += rlen; + + /* + * First compute P_md5(secret,label+random)[0..dlen] + */ + if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + mbedtls_md_hmac_starts( &md_ctx, S1, hs ); + mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); + mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); + + for( i = 0; i < dlen; i += 16 ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 ); + mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); + + k = ( i + 16 > dlen ) ? dlen % 16 : 16; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + mbedtls_md_free( &md_ctx ); + + /* + * XOR out with P_sha1(secret,label+random)[0..dlen] + */ + if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + mbedtls_md_hmac_starts( &md_ctx, S2, hs ); + mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + for( i = 0; i < dlen; i += 20 ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, 20 + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, 20 ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + k = ( i + 20 > dlen ) ? dlen % 20 : 20; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] ); + } + + mbedtls_md_free( &md_ctx ); + + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( h_i, sizeof( h_i ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1) || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +static int tls_prf_generic( mbedtls_md_type_t md_type, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb; + size_t i, j, k, md_len; + unsigned char tmp[128]; + unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret; + + mbedtls_md_init( &md_ctx ); + + if( ( md_info = mbedtls_md_info_from_type( md_type ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + md_len = mbedtls_md_get_size( md_info ); + + if( sizeof( tmp ) < md_len + strlen( label ) + rlen ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + nb = strlen( label ); + memcpy( tmp + md_len, label, nb ); + memcpy( tmp + md_len + nb, random, rlen ); + nb += rlen; + + /* + * Compute P_(secret, label + random)[0..dlen] + */ + if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + mbedtls_md_hmac_starts( &md_ctx, secret, slen ); + mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + for( i = 0; i < dlen; i += md_len ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, md_len + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, md_len ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + k = ( i + md_len > dlen ) ? dlen % md_len : md_len; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + mbedtls_md_free( &md_ctx ); + + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( h_i, sizeof( h_i ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SHA256_C) +static int tls_prf_sha256( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + return( tls_prf_generic( MBEDTLS_MD_SHA256, secret, slen, + label, random, rlen, dstbuf, dlen ) ); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) +static int tls_prf_sha384( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + return( tls_prf_generic( MBEDTLS_MD_SHA384, secret, slen, + label, random, rlen, dstbuf, dlen ) ); +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static void ssl_update_checksum_start( mbedtls_ssl_context *, const unsigned char *, size_t ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *, const unsigned char *, size_t ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static void ssl_calc_verify_ssl( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_finished_ssl( mbedtls_ssl_context *, unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_calc_verify_tls( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_finished_tls( mbedtls_ssl_context *, unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_update_checksum_sha256( mbedtls_ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SHA512_C) +static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + unsigned char tmp[64]; + unsigned char keyblk[256]; + unsigned char *key1; + unsigned char *key2; + unsigned char *mac_enc; + unsigned char *mac_dec; + size_t mac_key_len; + size_t iv_copy_len; + const mbedtls_cipher_info_t *cipher_info; + const mbedtls_md_info_t *md_info; + + mbedtls_ssl_session *session = ssl->session_negotiate; + mbedtls_ssl_transform *transform = ssl->transform_negotiate; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); + + cipher_info = mbedtls_cipher_info_from_type( transform->ciphersuite_info->cipher ); + if( cipher_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %d not found", + transform->ciphersuite_info->cipher ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + md_info = mbedtls_md_info_from_type( transform->ciphersuite_info->mac ); + if( md_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %d not found", + transform->ciphersuite_info->mac ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + handshake->tls_prf = ssl3_prf; + handshake->calc_verify = ssl_calc_verify_ssl; + handshake->calc_finished = ssl_calc_finished_ssl; + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls1_prf; + handshake->calc_verify = ssl_calc_verify_tls; + handshake->calc_finished = ssl_calc_finished_tls; + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + transform->ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + { + handshake->tls_prf = tls_prf_sha384; + handshake->calc_verify = ssl_calc_verify_tls_sha384; + handshake->calc_finished = ssl_calc_finished_tls_sha384; + } + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls_prf_sha256; + handshake->calc_verify = ssl_calc_verify_tls_sha256; + handshake->calc_finished = ssl_calc_finished_tls_sha256; + } + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * SSLv3: + * master = + * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) + + * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) + + * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) + * + * TLSv1+: + * master = PRF( premaster, "master secret", randbytes )[0..47] + */ + if( handshake->resume == 0 ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster, + handshake->pmslen ); + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) + { + unsigned char session_hash[48]; + size_t hash_len; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); + + ssl->handshake->calc_verify( ssl, session_hash ); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { +#if defined(MBEDTLS_SHA512_C) + if( ssl->transform_negotiate->ciphersuite_info->mac == + MBEDTLS_MD_SHA384 ) + { + hash_len = 48; + } + else +#endif + hash_len = 32; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + hash_len = 36; + + MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, hash_len ); + + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, + "extended master secret", + session_hash, hash_len, + session->master, 48 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + } + else +#endif + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, + "master secret", + handshake->randbytes, 64, + session->master, 48 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + mbedtls_platform_zeroize( handshake->premaster, + sizeof(handshake->premaster) ); + } + else + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); + + /* + * Swap the client and server random values. + */ + memcpy( tmp, handshake->randbytes, 64 ); + memcpy( handshake->randbytes, tmp + 32, 32 ); + memcpy( handshake->randbytes + 32, tmp, 32 ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + + /* + * SSLv3: + * key block = + * MD5( master + SHA1( 'A' + master + randbytes ) ) + + * MD5( master + SHA1( 'BB' + master + randbytes ) ) + + * MD5( master + SHA1( 'CCC' + master + randbytes ) ) + + * MD5( master + SHA1( 'DDDD' + master + randbytes ) ) + + * ... + * + * TLSv1: + * key block = PRF( master, "key expansion", randbytes ) + */ + ret = handshake->tls_prf( session->master, 48, "key expansion", + handshake->randbytes, 64, keyblk, 256 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", + mbedtls_ssl_get_ciphersuite_name( session->ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", session->master, 48 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); + + mbedtls_platform_zeroize( handshake->randbytes, + sizeof( handshake->randbytes ) ); + + /* + * Determine the appropriate key, IV and MAC length. + */ + + transform->keylen = cipher_info->key_bitlen / 8; + + if( cipher_info->mode == MBEDTLS_MODE_GCM || + cipher_info->mode == MBEDTLS_MODE_CCM || + cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) + { + size_t taglen, explicit_ivlen; + + transform->maclen = 0; + mac_key_len = 0; + + /* All modes haves 96-bit IVs; + * GCM and CCM has 4 implicit and 8 explicit bytes + * ChachaPoly has all 12 bytes implicit + */ + transform->ivlen = 12; + if( cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) + transform->fixed_ivlen = 12; + else + transform->fixed_ivlen = 4; + + /* All modes have 128-bit tags, except CCM_8 (ciphersuite flag) */ + taglen = transform->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + + + /* Minimum length of encrypted record */ + explicit_ivlen = transform->ivlen - transform->fixed_ivlen; + transform->minlen = explicit_ivlen + taglen; + } + else + { + /* Initialize HMAC contexts */ + if( ( ret = mbedtls_md_setup( &transform->md_ctx_enc, md_info, 1 ) ) != 0 || + ( ret = mbedtls_md_setup( &transform->md_ctx_dec, md_info, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + return( ret ); + } + + /* Get MAC length */ + mac_key_len = mbedtls_md_get_size( md_info ); + transform->maclen = mac_key_len; + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + /* + * If HMAC is to be truncated, we shall keep the leftmost bytes, + * (rfc 6066 page 13 or rfc 2104 section 4), + * so we only need to adjust the length here. + */ + if( session->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) + { + transform->maclen = MBEDTLS_SSL_TRUNCATED_HMAC_LEN; + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) + /* Fall back to old, non-compliant version of the truncated + * HMAC implementation which also truncates the key + * (Mbed TLS versions from 1.3 to 2.6.0) */ + mac_key_len = transform->maclen; +#endif + } +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + + /* IV length */ + transform->ivlen = cipher_info->iv_size; + + /* Minimum length */ + if( cipher_info->mode == MBEDTLS_MODE_STREAM ) + transform->minlen = transform->maclen; + else + { + /* + * GenericBlockCipher: + * 1. if EtM is in use: one block plus MAC + * otherwise: * first multiple of blocklen greater than maclen + * 2. IV except for SSL3 and TLS 1.0 + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( session->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + transform->minlen = transform->maclen + + cipher_info->block_size; + } + else +#endif + { + transform->minlen = transform->maclen + + cipher_info->block_size + - transform->maclen % cipher_info->block_size; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_1 ) + ; /* No need to adjust minlen */ + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + transform->minlen += transform->ivlen; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d", + transform->keylen, transform->minlen, transform->ivlen, + transform->maclen ) ); + + /* + * Finally setup the cipher contexts, IVs and MAC secrets. + */ +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + key1 = keyblk + mac_key_len * 2; + key2 = keyblk + mac_key_len * 2 + transform->keylen; + + mac_enc = keyblk; + mac_dec = keyblk + mac_key_len; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_enc, key2 + transform->keylen, iv_copy_len ); + memcpy( transform->iv_dec, key2 + transform->keylen + iv_copy_len, + iv_copy_len ); + } + else +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + key1 = keyblk + mac_key_len * 2 + transform->keylen; + key2 = keyblk + mac_key_len * 2; + + mac_enc = keyblk + mac_key_len; + mac_dec = keyblk; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_dec, key1 + transform->keylen, iv_copy_len ); + memcpy( transform->iv_enc, key1 + transform->keylen + iv_copy_len, + iv_copy_len ); + } + else +#endif /* MBEDTLS_SSL_SRV_C */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( mac_key_len > sizeof transform->mac_enc ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( transform->mac_enc, mac_enc, mac_key_len ); + memcpy( transform->mac_dec, mac_dec, mac_key_len ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + /* For HMAC-based ciphersuites, initialize the HMAC transforms. + For AEAD-based ciphersuites, there is nothing to do here. */ + if( mac_key_len != 0 ) + { + mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, mac_key_len ); + mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, mac_key_len ); + } + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_init != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_init()" ) ); + + if( ( ret = mbedtls_ssl_hw_record_init( ssl, key1, key2, transform->keylen, + transform->iv_enc, transform->iv_dec, + iv_copy_len, + mac_enc, mac_dec, + mac_key_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_init", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + if( ssl->conf->f_export_keys != NULL ) + { + ssl->conf->f_export_keys( ssl->conf->p_export_keys, + session->master, keyblk, + mac_key_len, transform->keylen, + iv_copy_len ); + } +#endif + + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, key1, + cipher_info->key_bitlen, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, key2, + cipher_info->key_bitlen, + MBEDTLS_DECRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + return( ret ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( cipher_info->mode == MBEDTLS_MODE_CBC ) + { + if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_enc, + MBEDTLS_PADDING_NONE ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_dec, + MBEDTLS_PADDING_NONE ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + mbedtls_platform_zeroize( keyblk, sizeof( keyblk ) ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + // Initialize compression + // + if( session->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ssl->compress_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); + ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); + if( ssl->compress_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) ); + + memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) ); + memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) ); + + if( deflateInit( &transform->ctx_deflate, + Z_DEFAULT_COMPRESSION ) != Z_OK || + inflateInit( &transform->ctx_inflate ) != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + } +#endif /* MBEDTLS_ZLIB_SUPPORT */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +void ssl_calc_verify_ssl( mbedtls_ssl_context *ssl, unsigned char *hash ) +{ + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char pad_1[48]; + unsigned char pad_2[48]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + memset( pad_1, 0x36, 48 ); + memset( pad_2, 0x5C, 48 ); + + mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update_ret( &md5, pad_1, 48 ); + mbedtls_md5_finish_ret( &md5, hash ); + + mbedtls_md5_starts_ret( &md5 ); + mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update_ret( &md5, pad_2, 48 ); + mbedtls_md5_update_ret( &md5, hash, 16 ); + mbedtls_md5_finish_ret( &md5, hash ); + + mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update_ret( &sha1, pad_1, 40 ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); + + mbedtls_sha1_starts_ret( &sha1 ); + mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update_ret( &sha1, pad_2, 40 ); + mbedtls_sha1_update_ret( &sha1, hash + 16, 20 ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + return; +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +void ssl_calc_verify_tls( mbedtls_ssl_context *ssl, unsigned char *hash ) +{ + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + mbedtls_md5_finish_ret( &md5, hash ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + return; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *ssl, unsigned char *hash ) +{ + mbedtls_sha256_context sha256; + + mbedtls_sha256_init( &sha256 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); + + mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); + mbedtls_sha256_finish_ret( &sha256, hash ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_sha256_free( &sha256 ); + + return; +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) +void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *ssl, unsigned char *hash ) +{ + mbedtls_sha512_context sha512; + + mbedtls_sha512_init( &sha512 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); + + mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); + mbedtls_sha512_finish_ret( &sha512, hash ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_sha512_free( &sha512 ); + + return; +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ) +{ + unsigned char *p = ssl->handshake->premaster; + unsigned char *end = p + sizeof( ssl->handshake->premaster ); + const unsigned char *psk = ssl->conf->psk; + size_t psk_len = ssl->conf->psk_len; + + /* If the psk callback was called, use its result */ + if( ssl->handshake->psk != NULL ) + { + psk = ssl->handshake->psk; + psk_len = ssl->handshake->psk_len; + } + + /* + * PMS = struct { + * opaque other_secret<0..2^16-1>; + * opaque psk<0..2^16-1>; + * }; + * with "other_secret" depending on the particular key exchange + */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_PSK ) + { + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *(p++) = (unsigned char)( psk_len >> 8 ); + *(p++) = (unsigned char)( psk_len ); + + if( end < p || (size_t)( end - p ) < psk_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memset( p, 0, psk_len ); + p += psk_len; + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + /* + * other_secret already set by the ClientKeyExchange message, + * and is 48 bytes long + */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *p++ = 0; + *p++ = 48; + p += 48; + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + int ret; + size_t len; + + /* Write length only when we know the actual value */ + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + p + 2, end - ( p + 2 ), &len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( ret ); + } + *(p++) = (unsigned char)( len >> 8 ); + *(p++) = (unsigned char)( len ); + p += len; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + int ret; + size_t zlen; + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen, + p + 2, end - ( p + 2 ), + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( ret ); + } + + *(p++) = (unsigned char)( zlen >> 8 ); + *(p++) = (unsigned char)( zlen ); + p += zlen; + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* opaque psk<0..2^16-1>; */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *(p++) = (unsigned char)( psk_len >> 8 ); + *(p++) = (unsigned char)( psk_len ); + + if( end < p || (size_t)( end - p ) < psk_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( p, psk, psk_len ); + p += psk_len; + + ssl->handshake->pmslen = p - ssl->handshake->premaster; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +/* + * SSLv3.0 MAC functions + */ +#define SSL_MAC_MAX_BYTES 20 /* MD-5 or SHA-1 */ +static void ssl_mac( mbedtls_md_context_t *md_ctx, + const unsigned char *secret, + const unsigned char *buf, size_t len, + const unsigned char *ctr, int type, + unsigned char out[SSL_MAC_MAX_BYTES] ) +{ + unsigned char header[11]; + unsigned char padding[48]; + int padlen; + int md_size = mbedtls_md_get_size( md_ctx->md_info ); + int md_type = mbedtls_md_get_type( md_ctx->md_info ); + + /* Only MD5 and SHA-1 supported */ + if( md_type == MBEDTLS_MD_MD5 ) + padlen = 48; + else + padlen = 40; + + memcpy( header, ctr, 8 ); + header[ 8] = (unsigned char) type; + header[ 9] = (unsigned char)( len >> 8 ); + header[10] = (unsigned char)( len ); + + memset( padding, 0x36, padlen ); + mbedtls_md_starts( md_ctx ); + mbedtls_md_update( md_ctx, secret, md_size ); + mbedtls_md_update( md_ctx, padding, padlen ); + mbedtls_md_update( md_ctx, header, 11 ); + mbedtls_md_update( md_ctx, buf, len ); + mbedtls_md_finish( md_ctx, out ); + + memset( padding, 0x5C, padlen ); + mbedtls_md_starts( md_ctx ); + mbedtls_md_update( md_ctx, secret, md_size ); + mbedtls_md_update( md_ctx, padding, padlen ); + mbedtls_md_update( md_ctx, out, md_size ); + mbedtls_md_finish( md_ctx, out ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) +#define SSL_SOME_MODES_USE_MAC +#endif + +/* + * Encryption/decryption functions + */ +static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) +{ + mbedtls_cipher_mode_t mode; + int auth_done = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); + + if( ssl->session_out == NULL || ssl->transform_out == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", + ssl->out_msg, ssl->out_msglen ); + + /* + * Add MAC before if needed + */ +#if defined(SSL_SOME_MODES_USE_MAC) + if( mode == MBEDTLS_MODE_STREAM || + ( mode == MBEDTLS_MODE_CBC +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + && ssl->session_out->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED +#endif + ) ) + { +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + unsigned char mac[SSL_MAC_MAX_BYTES]; + + ssl_mac( &ssl->transform_out->md_ctx_enc, + ssl->transform_out->mac_enc, + ssl->out_msg, ssl->out_msglen, + ssl->out_ctr, ssl->out_msgtype, + mac ); + + memcpy( ssl->out_msg + ssl->out_msglen, mac, ssl->transform_out->maclen ); + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 8 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_hdr, 3 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_len, 2 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, + ssl->out_msg, ssl->out_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, mac ); + mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + + memcpy( ssl->out_msg + ssl->out_msglen, mac, ssl->transform_out->maclen ); + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", + ssl->out_msg + ssl->out_msglen, + ssl->transform_out->maclen ); + + ssl->out_msglen += ssl->transform_out->maclen; + auth_done++; + } +#endif /* AEAD not the only option */ + + /* + * Encrypt + */ +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( mode == MBEDTLS_MODE_STREAM ) + { + int ret; + size_t olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of padding", + ssl->out_msglen, 0 ) ); + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, + ssl->out_msg, ssl->out_msglen, + ssl->out_msg, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( ssl->out_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) + { + int ret; + size_t enc_msglen, olen; + unsigned char *enc_msg; + unsigned char add_data[13]; + unsigned char iv[12]; + mbedtls_ssl_transform *transform = ssl->transform_out; + unsigned char taglen = transform->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + size_t explicit_ivlen = transform->ivlen - transform->fixed_ivlen; + + /* + * Prepare additional authenticated data + */ + memcpy( add_data, ssl->out_ctr, 8 ); + add_data[8] = ssl->out_msgtype; + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, add_data + 9 ); + add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF; + add_data[12] = ssl->out_msglen & 0xFF; + + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 ); + + /* + * Generate IV + */ + if( transform->ivlen == 12 && transform->fixed_ivlen == 4 ) + { + /* GCM and CCM: fixed || explicit (=seqnum) */ + memcpy( iv, transform->iv_enc, transform->fixed_ivlen ); + memcpy( iv + transform->fixed_ivlen, ssl->out_ctr, 8 ); + memcpy( ssl->out_iv, ssl->out_ctr, 8 ); + + } + else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 ) + { + /* ChachaPoly: fixed XOR sequence number */ + unsigned char i; + + memcpy( iv, transform->iv_enc, transform->fixed_ivlen ); + + for( i = 0; i < 8; i++ ) + iv[i+4] ^= ssl->out_ctr[i]; + } + else + { + /* Reminder if we ever add an AEAD mode with a different size */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)", + iv, transform->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)", + ssl->out_iv, explicit_ivlen ); + + /* + * Fix message length with added IV + */ + enc_msg = ssl->out_msg; + enc_msglen = ssl->out_msglen; + ssl->out_msglen += explicit_ivlen; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including 0 bytes of padding", + ssl->out_msglen ) ); + + /* + * Encrypt and authenticate + */ + if( ( ret = mbedtls_cipher_auth_encrypt( &transform->cipher_ctx_enc, + iv, transform->ivlen, + add_data, 13, + enc_msg, enc_msglen, + enc_msg, &olen, + enc_msg + enc_msglen, taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret ); + return( ret ); + } + + if( olen != enc_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msglen += taglen; + auth_done++; + + MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, taglen ); + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) + if( mode == MBEDTLS_MODE_CBC ) + { + int ret; + unsigned char *enc_msg; + size_t enc_msglen, padlen, olen = 0, i; + + padlen = ssl->transform_out->ivlen - ( ssl->out_msglen + 1 ) % + ssl->transform_out->ivlen; + if( padlen == ssl->transform_out->ivlen ) + padlen = 0; + + for( i = 0; i <= padlen; i++ ) + ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen; + + ssl->out_msglen += padlen + 1; + + enc_msglen = ssl->out_msglen; + enc_msg = ssl->out_msg; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Prepend per-record IV for block cipher in TLS v1.1 and up as per + * Method 1 (6.2.3.2. in RFC4346 and RFC5246) + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Generate IV + */ + ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ); + if( ret != 0 ) + return( ret ); + + memcpy( ssl->out_iv, ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ); + + /* + * Fix pointer positions and message length with added IV + */ + enc_msg = ssl->out_msg; + enc_msglen = ssl->out_msglen; + ssl->out_msglen += ssl->transform_out->ivlen; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of IV and %d bytes of padding", + ssl->out_msglen, ssl->transform_out->ivlen, + padlen + 1 ) ); + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, + enc_msg, enc_msglen, + enc_msg, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( enc_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( ssl->transform_out->iv_enc, + ssl->transform_out->cipher_ctx_enc.iv, + ssl->transform_out->ivlen ); + } +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( auth_done == 0 ) + { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + + /* + * MAC(MAC_write_key, seq_num + + * TLSCipherText.type + + * TLSCipherText.version + + * length_of( (IV +) ENC(...) ) + + * IV + // except for TLS 1.0 + * ENC(content + padding + padding_length)); + */ + unsigned char pseudo_hdr[13]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + + memcpy( pseudo_hdr + 0, ssl->out_ctr, 8 ); + memcpy( pseudo_hdr + 8, ssl->out_hdr, 3 ); + pseudo_hdr[11] = (unsigned char)( ( ssl->out_msglen >> 8 ) & 0xFF ); + pseudo_hdr[12] = (unsigned char)( ( ssl->out_msglen ) & 0xFF ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); + + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, + ssl->out_iv, ssl->out_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, mac ); + mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + + memcpy( ssl->out_iv + ssl->out_msglen, mac, + ssl->transform_out->maclen ); + + ssl->out_msglen += ssl->transform_out->maclen; + auth_done++; + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + } + else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) +/* + * Constant-flow conditional memcpy: + * - if c1 == c2, equivalent to memcpy(dst, src, len), + * - otherwise, a no-op, + * but with execution flow independent of the values of c1 and c2. + * + * Use only bit operations to avoid branches that could be used by some + * compilers on some platforms to translate comparison operators. + */ +static void mbedtls_ssl_cf_memcpy_if_eq( unsigned char *dst, + const unsigned char *src, + size_t len, + size_t c1, size_t c2 ) +{ + /* diff = 0 if c1 == c2, non-zero otherwise */ + const size_t diff = c1 ^ c2; + + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + /* diff_msb's most significant bit is equal to c1 != c2 */ + const size_t diff_msb = ( diff | -diff ); + + /* diff1 = c1 != c2 */ + const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 ); + + /* mask = c1 != c2 ? 0xff : 0x00 */ + const unsigned char mask = (unsigned char) -diff1; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + /* dst[i] = c1 != c2 ? dst[i] : src[i] */ + size_t i; + for( i = 0; i < len; i++ ) + dst[i] = ( dst[i] & mask ) | ( src[i] & ~mask ); +} + +/* + * Compute HMAC of variable-length data with constant flow. + * + * Only works with MD-5, SHA-1, SHA-256 and SHA-384. + * (Otherwise, computation of block_size needs to be adapted.) + */ +int mbedtls_ssl_cf_hmac( + mbedtls_md_context_t *ctx, + const unsigned char *add_data, size_t add_data_len, + const unsigned char *data, size_t data_len_secret, + size_t min_data_len, size_t max_data_len, + unsigned char *output ) +{ + /* + * This function breaks the HMAC abstraction and uses the md_clone() + * extension to the MD API in order to get constant-flow behaviour. + * + * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means + * concatenation, and okey/ikey are the XOR of the key with some fixed bit + * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx. + * + * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to + * minlen, then cloning the context, and for each byte up to maxlen + * finishing up the hash computation, keeping only the correct result. + * + * Then we only need to compute HASH(okey + inner_hash) and we're done. + */ + const mbedtls_md_type_t md_alg = mbedtls_md_get_type( ctx->md_info ); + /* TLS 1.0-1.2 only support SHA-384, SHA-256, SHA-1, MD-5, + * all of which have the same block size except SHA-384. */ + const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64; + const unsigned char * const ikey = ctx->hmac_ctx; + const unsigned char * const okey = ikey + block_size; + const size_t hash_size = mbedtls_md_get_size( ctx->md_info ); + + unsigned char aux_out[MBEDTLS_MD_MAX_SIZE]; + mbedtls_md_context_t aux; + size_t offset; + int ret; + + mbedtls_md_init( &aux ); + +#define MD_CHK( func_call ) \ + do { \ + ret = (func_call); \ + if( ret != 0 ) \ + goto cleanup; \ + } while( 0 ) + + MD_CHK( mbedtls_md_setup( &aux, ctx->md_info, 0 ) ); + + /* After hmac_start() of hmac_reset(), ikey has already been hashed, + * so we can start directly with the message */ + MD_CHK( mbedtls_md_update( ctx, add_data, add_data_len ) ); + MD_CHK( mbedtls_md_update( ctx, data, min_data_len ) ); + + /* For each possible length, compute the hash up to that point */ + for( offset = min_data_len; offset <= max_data_len; offset++ ) + { + MD_CHK( mbedtls_md_clone( &aux, ctx ) ); + MD_CHK( mbedtls_md_finish( &aux, aux_out ) ); + /* Keep only the correct inner_hash in the output buffer */ + mbedtls_ssl_cf_memcpy_if_eq( output, aux_out, hash_size, + offset, data_len_secret ); + + if( offset < max_data_len ) + MD_CHK( mbedtls_md_update( ctx, data + offset, 1 ) ); + } + + /* Now compute HASH(okey + inner_hash) */ + MD_CHK( mbedtls_md_starts( ctx ) ); + MD_CHK( mbedtls_md_update( ctx, okey, block_size ) ); + MD_CHK( mbedtls_md_update( ctx, output, hash_size ) ); + MD_CHK( mbedtls_md_finish( ctx, output ) ); + + /* Done, get ready for next time */ + MD_CHK( mbedtls_md_hmac_reset( ctx ) ); + +#undef MD_CHK + +cleanup: + mbedtls_md_free( &aux ); + return( ret ); +} + +/* + * Constant-flow memcpy from variable position in buffer. + * - functionally equivalent to memcpy(dst, src + offset_secret, len) + * - but with execution flow independent from the value of offset_secret. + */ +void mbedtls_ssl_cf_memcpy_offset( unsigned char *dst, + const unsigned char *src_base, + size_t offset_secret, + size_t offset_min, size_t offset_max, + size_t len ) +{ + size_t offset; + + for( offset = offset_min; offset <= offset_max; offset++ ) + { + mbedtls_ssl_cf_memcpy_if_eq( dst, src_base + offset, len, + offset, offset_secret ); + } +} +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) +{ + mbedtls_cipher_mode_t mode; + int auth_done = 0; +#if defined(SSL_SOME_MODES_USE_MAC) + size_t padlen = 0, correct = 1; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); + + if( ssl->session_in == NULL || ssl->transform_in == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_in->cipher_ctx_dec ); + + if( ssl->in_msglen < ssl->transform_in->minlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)", + ssl->in_msglen, ssl->transform_in->minlen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( mode == MBEDTLS_MODE_STREAM ) + { + int ret; + size_t olen = 0; + + padlen = 0; + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, + ssl->in_msg, ssl->in_msglen, + ssl->in_msg, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( ssl->in_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) + { + int ret; + size_t dec_msglen, olen; + unsigned char *dec_msg; + unsigned char *dec_msg_result; + unsigned char add_data[13]; + unsigned char iv[12]; + mbedtls_ssl_transform *transform = ssl->transform_in; + unsigned char taglen = transform->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen; + + /* + * Compute and update sizes + */ + if( ssl->in_msglen < explicit_iv_len + taglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) " + "+ taglen (%d)", ssl->in_msglen, + explicit_iv_len, taglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + dec_msglen = ssl->in_msglen - explicit_iv_len - taglen; + + dec_msg = ssl->in_msg; + dec_msg_result = ssl->in_msg; + ssl->in_msglen = dec_msglen; + + /* + * Prepare additional authenticated data + */ + memcpy( add_data, ssl->in_ctr, 8 ); + add_data[8] = ssl->in_msgtype; + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, add_data + 9 ); + add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF; + add_data[12] = ssl->in_msglen & 0xFF; + + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 ); + + /* + * Prepare IV + */ + if( transform->ivlen == 12 && transform->fixed_ivlen == 4 ) + { + /* GCM and CCM: fixed || explicit (transmitted) */ + memcpy( iv, transform->iv_dec, transform->fixed_ivlen ); + memcpy( iv + transform->fixed_ivlen, ssl->in_iv, 8 ); + + } + else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 ) + { + /* ChachaPoly: fixed XOR sequence number */ + unsigned char i; + + memcpy( iv, transform->iv_dec, transform->fixed_ivlen ); + + for( i = 0; i < 8; i++ ) + iv[i+4] ^= ssl->in_ctr[i]; + } + else + { + /* Reminder if we ever add an AEAD mode with a different size */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen ); + + /* + * Decrypt and authenticate + */ + if( ( ret = mbedtls_cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec, + iv, transform->ivlen, + add_data, 13, + dec_msg, dec_msglen, + dec_msg_result, &olen, + dec_msg + dec_msglen, taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret ); + + if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + + return( ret ); + } + auth_done++; + + if( olen != dec_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) + if( mode == MBEDTLS_MODE_CBC ) + { + /* + * Decrypt and check the padding + */ + int ret; + unsigned char *dec_msg; + unsigned char *dec_msg_result; + size_t dec_msglen; + size_t minlen = 0; + size_t olen = 0; + + /* + * Check immediate ciphertext sanity + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + minlen += ssl->transform_in->ivlen; +#endif + + if( ssl->in_msglen < minlen + ssl->transform_in->ivlen || + ssl->in_msglen < minlen + ssl->transform_in->maclen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) " + "+ 1 ) ( + expl IV )", ssl->in_msglen, + ssl->transform_in->ivlen, + ssl->transform_in->maclen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + + dec_msglen = ssl->in_msglen; + dec_msg = ssl->in_msg; + dec_msg_result = ssl->in_msg; + + /* + * Authenticate before decrypt if enabled + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( ssl->session_in->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; + unsigned char pseudo_hdr[13]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + + dec_msglen -= ssl->transform_in->maclen; + ssl->in_msglen -= ssl->transform_in->maclen; + + memcpy( pseudo_hdr + 0, ssl->in_ctr, 8 ); + memcpy( pseudo_hdr + 8, ssl->in_hdr, 3 ); + pseudo_hdr[11] = (unsigned char)( ( ssl->in_msglen >> 8 ) & 0xFF ); + pseudo_hdr[12] = (unsigned char)( ( ssl->in_msglen ) & 0xFF ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); + + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, pseudo_hdr, 13 ); + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, + ssl->in_iv, ssl->in_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect ); + mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_iv + ssl->in_msglen, + ssl->transform_in->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, + ssl->transform_in->maclen ); + + if( mbedtls_ssl_safer_memcmp( ssl->in_iv + ssl->in_msglen, mac_expect, + ssl->transform_in->maclen ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); + + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + auth_done++; + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + + /* + * Check length sanity + */ + if( ssl->in_msglen % ssl->transform_in->ivlen != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0", + ssl->in_msglen, ssl->transform_in->ivlen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Initialize for prepended IV for block cipher in TLS v1.1 and up + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + unsigned char i; + dec_msglen -= ssl->transform_in->ivlen; + ssl->in_msglen -= ssl->transform_in->ivlen; + + for( i = 0; i < ssl->transform_in->ivlen; i++ ) + ssl->transform_in->iv_dec[i] = ssl->in_iv[i]; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, + dec_msg, dec_msglen, + dec_msg_result, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( dec_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( ssl->transform_in->iv_dec, + ssl->transform_in->cipher_ctx_dec.iv, + ssl->transform_in->ivlen ); + } +#endif + + padlen = 1 + ssl->in_msg[ssl->in_msglen - 1]; + + if( ssl->in_msglen < ssl->transform_in->maclen + padlen && + auth_done == 0 ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)", + ssl->in_msglen, ssl->transform_in->maclen, padlen ) ); +#endif + padlen = 0; + correct = 0; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( padlen > ssl->transform_in->ivlen ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, " + "should be no more than %d", + padlen, ssl->transform_in->ivlen ) ); +#endif + correct = 0; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* + * TLSv1+: always check the padding up to the first failure + * and fake check up to 256 bytes of padding + */ + size_t pad_count = 0, real_count = 1; + size_t padding_idx = ssl->in_msglen - padlen; + size_t i; + + /* + * Padding is guaranteed to be incorrect if: + * 1. padlen > ssl->in_msglen + * + * 2. padding_idx > MBEDTLS_SSL_IN_CONTENT_LEN + + * ssl->transform_in->maclen + * + * In both cases we reset padding_idx to a safe value (0) to + * prevent out-of-buffer reads. + */ + correct &= ( padlen <= ssl->in_msglen ); + correct &= ( padding_idx <= MBEDTLS_SSL_IN_CONTENT_LEN + + ssl->transform_in->maclen ); + + padding_idx *= correct; + + for( i = 0; i < 256; i++ ) + { + real_count &= ( i < padlen ); + pad_count += real_count * + ( ssl->in_msg[padding_idx + i] == padlen - 1 ); + } + + correct &= ( pad_count == padlen ); /* Only 1 on correct padding */ + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( padlen > 0 && correct == 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) ); +#endif + padlen &= correct * 0x1FF; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_msglen -= padlen; + } + else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC) */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", + ssl->in_msg, ssl->in_msglen ); +#endif + + /* + * Authenticate if not done yet. + * Compute the MAC regardless of the padding result (RFC4346, CBCTIME). + */ +#if defined(SSL_SOME_MODES_USE_MAC) + if( auth_done == 0 ) + { + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; + unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD]; + + ssl->in_msglen -= ssl->transform_in->maclen; + + ssl->in_len[0] = (unsigned char)( ssl->in_msglen >> 8 ); + ssl->in_len[1] = (unsigned char)( ssl->in_msglen ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl_mac( &ssl->transform_in->md_ctx_dec, + ssl->transform_in->mac_dec, + ssl->in_msg, ssl->in_msglen, + ssl->in_ctr, ssl->in_msgtype, + mac_expect ); + memcpy( mac_peer, ssl->in_msg + ssl->in_msglen, + ssl->transform_in->maclen ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) + { + int ret; + unsigned char add_data[13]; + + /* + * The next two sizes are the minimum and maximum values of + * in_msglen over all padlen values. + * + * They're independent of padlen, since we previously did + * in_msglen -= padlen. + * + * Note that max_len + maclen is never more than the buffer + * length, as we previously did in_msglen -= maclen too. + */ + const size_t max_len = ssl->in_msglen + padlen; + const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0; + + memcpy( add_data + 0, ssl->in_ctr, 8 ); + memcpy( add_data + 8, ssl->in_hdr, 3 ); + memcpy( add_data + 11, ssl->in_len, 2 ); + + ret = mbedtls_ssl_cf_hmac( &ssl->transform_in->md_ctx_dec, + add_data, sizeof( add_data ), + ssl->in_msg, ssl->in_msglen, + min_len, max_len, + mac_expect ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_cf_hmac", ret ); + return( ret ); + } + + mbedtls_ssl_cf_memcpy_offset( mac_peer, ssl->in_msg, + ssl->in_msglen, + min_len, max_len, + ssl->transform_in->maclen ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, ssl->transform_in->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", mac_peer, ssl->transform_in->maclen ); +#endif + + if( mbedtls_ssl_safer_memcmp( mac_peer, mac_expect, + ssl->transform_in->maclen ) != 0 ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); +#endif + correct = 0; + } + auth_done++; + } + + /* + * Finally check the correct flag + */ + if( correct == 0 ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); +#endif /* SSL_SOME_MODES_USE_MAC */ + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ssl->in_msglen == 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 + && ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* TLS v1.2 explicitly disallows zero-length messages which are not application data */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + ssl->nb_zero++; + + /* + * Three or more empty messages may be a DoS attack + * (excessive CPU consumption). + */ + if( ssl->nb_zero > 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty " + "messages, possible DoS attack" ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + } + else + ssl->nb_zero = 0; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ; /* in_ctr read from peer, not maintained internally */ + } + else +#endif + { + unsigned char i; + for( i = 8; i > ssl_ep_len( ssl ); i-- ) + if( ++ssl->in_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); + + return( 0 ); +} + +#undef MAC_NONE +#undef MAC_PLAINTEXT +#undef MAC_CIPHERTEXT + +#if defined(MBEDTLS_ZLIB_SUPPORT) +/* + * Compression/decompression functions + */ +static int ssl_compress_buf( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *msg_post = ssl->out_msg; + ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf; + size_t len_pre = ssl->out_msglen; + unsigned char *msg_pre = ssl->compress_buf; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->out_msg, len_pre ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ", + ssl->out_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + ssl->transform_out->ctx_deflate.next_in = msg_pre; + ssl->transform_out->ctx_deflate.avail_in = len_pre; + ssl->transform_out->ctx_deflate.next_out = msg_post; + ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_OUT_BUFFER_LEN - bytes_written; + + ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->out_msglen = MBEDTLS_SSL_OUT_BUFFER_LEN - + ssl->transform_out->ctx_deflate.avail_out - bytes_written; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", + ssl->out_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) ); + + return( 0 ); +} + +static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *msg_post = ssl->in_msg; + ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf; + size_t len_pre = ssl->in_msglen; + unsigned char *msg_pre = ssl->compress_buf; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->in_msg, len_pre ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ", + ssl->in_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + ssl->transform_in->ctx_inflate.next_in = msg_pre; + ssl->transform_in->ctx_inflate.avail_in = len_pre; + ssl->transform_in->ctx_inflate.next_out = msg_post; + ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_IN_BUFFER_LEN - + header_bytes; + + ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->in_msglen = MBEDTLS_SSL_IN_BUFFER_LEN - + ssl->transform_in->ctx_inflate.avail_out - header_bytes; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", + ssl->in_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_resend_hello_request( mbedtls_ssl_context *ssl ) +{ + /* If renegotiation is not enforced, retransmit until we would reach max + * timeout if we were using the usual handshake doubling scheme */ + if( ssl->conf->renego_max_records < 0 ) + { + uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; + unsigned char doublings = 1; + + while( ratio != 0 ) + { + ++doublings; + ratio >>= 1; + } + + if( ++ssl->renego_records_seen > doublings ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "no longer retransmitting hello request" ) ); + return( 0 ); + } + } + + return( ssl_write_hello_request( ssl ) ); +} +#endif +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Fill the input message buffer by appending data to it. + * The amount of data already fetched is in ssl->in_left. + * + * If we return 0, is it guaranteed that (at least) nb_want bytes are + * available (from this read and/or a previous one). Otherwise, an error code + * is returned (possibly EOF or WANT_READ). + * + * With stream transport (TLS) on success ssl->in_left == nb_want, but + * with datagram transport (DTLS) on success ssl->in_left >= nb_want, + * since we always read a whole datagram at once. + * + * For DTLS, it is up to the caller to set ssl->next_record_offset when + * they're done reading a record. + */ +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) +{ + int ret; + size_t len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); + + if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( nb_want > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + uint32_t timeout; + + /* Just to be sure */ + if( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use " + "mbedtls_ssl_set_timer_cb() for DTLS" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * The point is, we need to always read a full datagram at once, so we + * sometimes read more then requested, and handle the additional data. + * It could be the rest of the current record (while fetching the + * header) and/or some other records in the same datagram. + */ + + /* + * Move to the next record in the already read datagram if applicable + */ + if( ssl->next_record_offset != 0 ) + { + if( ssl->in_left < ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_left -= ssl->next_record_offset; + + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %d", + ssl->next_record_offset ) ); + memmove( ssl->in_hdr, + ssl->in_hdr + ssl->next_record_offset, + ssl->in_left ); + } + + ssl->next_record_offset = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + + /* + * Done if we already have enough data. + */ + if( nb_want <= ssl->in_left) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + return( 0 ); + } + + /* + * A record can't be split across datagrams. If we need to read but + * are not at the beginning of a new record, the caller did something + * wrong. + */ + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Don't even try to read if time's out already. + * This avoids by-passing the timer when repeatedly receiving messages + * that will end up being dropped. + */ + if( ssl_check_timer( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) ); + ret = MBEDTLS_ERR_SSL_TIMEOUT; + } + else + { + len = MBEDTLS_SSL_IN_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + timeout = ssl->handshake->retransmit_timeout; + else + timeout = ssl->conf->read_timeout; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) ); + + if( ssl->f_recv_timeout != NULL ) + ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len, + timeout ); + else + ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + } + + if( ret == MBEDTLS_ERR_SSL_TIMEOUT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) ); + ssl_set_timer( ssl, 0 ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ssl_double_retransmit_timeout( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) ); + return( MBEDTLS_ERR_SSL_TIMEOUT ); + } + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + } + + if( ret < 0 ) + return( ret ); + + ssl->in_left = ret; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + + while( ssl->in_left < nb_want ) + { + len = nb_want - ssl->in_left; + + if( ssl_check_timer( ssl ) != 0 ) + ret = MBEDTLS_ERR_SSL_TIMEOUT; + else + { + if( ssl->f_recv_timeout != NULL ) + { + ret = ssl->f_recv_timeout( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len, + ssl->conf->read_timeout ); + } + else + { + ret = ssl->f_recv( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + + if( ret < 0 ) + return( ret ); + + if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_recv returned %d bytes but only %lu were requested", + ret, (unsigned long)len ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_left += ret; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + + return( 0 ); +} + +/* + * Flush any data not yet written + */ +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *buf; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); + + if( ssl->f_send == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Avoid incrementing counter if data is flushed */ + if( ssl->out_left == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + return( 0 ); + } + + while( ssl->out_left > 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", + mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); + + buf = ssl->out_hdr - ssl->out_left; + ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); + + if( ret <= 0 ) + return( ret ); + + if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_send returned %d bytes but only %lu bytes were sent", + ret, (unsigned long)ssl->out_left ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_left -= ret; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + } + else +#endif + { + ssl->out_hdr = ssl->out_buf + 8; + } + ssl_update_out_pointers( ssl, ssl->transform_out ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + + return( 0 ); +} + +/* + * Functions to handle the DTLS retransmission state machine + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Append current handshake message to current outgoing flight + */ +static int ssl_flight_append( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_flight_item *msg; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight", + ssl->out_msg, ssl->out_msglen ); + + /* Allocate space for current message */ + if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", + sizeof( mbedtls_ssl_flight_item ) ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", ssl->out_msglen ) ); + mbedtls_free( msg ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Copy current handshake message with headers */ + memcpy( msg->p, ssl->out_msg, ssl->out_msglen ); + msg->len = ssl->out_msglen; + msg->type = ssl->out_msgtype; + msg->next = NULL; + + /* Append to the current flight */ + if( ssl->handshake->flight == NULL ) + ssl->handshake->flight = msg; + else + { + mbedtls_ssl_flight_item *cur = ssl->handshake->flight; + while( cur->next != NULL ) + cur = cur->next; + cur->next = msg; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) ); + return( 0 ); +} + +/* + * Free the current flight of handshake messages + */ +static void ssl_flight_free( mbedtls_ssl_flight_item *flight ) +{ + mbedtls_ssl_flight_item *cur = flight; + mbedtls_ssl_flight_item *next; + + while( cur != NULL ) + { + next = cur->next; + + mbedtls_free( cur->p ); + mbedtls_free( cur ); + + cur = next; + } +} + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ); +#endif + +/* + * Swap transform_out and out_ctr with the alternative ones + */ +static int ssl_swap_epochs( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_transform *tmp_transform; + unsigned char tmp_out_ctr[8]; +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + int ret; +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + + if( ssl->transform_out == ssl->handshake->alt_transform_out ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) ); + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) ); + + /* Swap transforms */ + tmp_transform = ssl->transform_out; + ssl->transform_out = ssl->handshake->alt_transform_out; + ssl->handshake->alt_transform_out = tmp_transform; + + /* Swap epoch + sequence_number */ + memcpy( tmp_out_ctr, ssl->cur_out_ctr, 8 ); + memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, 8 ); + memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); + + /* Adjust to the newly activated transform */ + ssl_update_out_pointers( ssl, ssl->transform_out ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + + return( 0 ); +} + +/* + * Retransmit the current flight of messages. + */ +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); + + ret = mbedtls_ssl_flight_transmit( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); + + return( ret ); +} + +/* + * Transmit or retransmit the current flight of messages. + * + * Need to remember the current message in case flush_output returns + * WANT_WRITE, causing us to exit this function and come back later. + * This function must be called until state is no longer SENDING. + */ +int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) +{ + int ret; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) ); + + if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) ); + + ssl->handshake->cur_msg = ssl->handshake->flight; + ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12; + if( ( ret = ssl_swap_epochs( ssl ) ) != 0 ) + return( ret ); + + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; + } + + while( ssl->handshake->cur_msg != NULL ) + { + size_t max_frag_len; + const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg; + + int const is_finished = + ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && + cur->p[0] == MBEDTLS_SSL_HS_FINISHED ); + + uint8_t const force_flush = ssl->disable_datagram_packing == 1 ? + SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; + + /* Swap epochs before sending Finished: we can't do it after + * sending ChangeCipherSpec, in case write returns WANT_READ. + * Must be done before copying, may change out_msg pointer */ + if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) ); + if( ( ret = ssl_swap_epochs( ssl ) ) != 0 ) + return( ret ); + } + + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + max_frag_len = (size_t) ret; + + /* CCS is copied as is, while HS messages may need fragmentation */ + if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + if( max_frag_len == 0 ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + + memcpy( ssl->out_msg, cur->p, cur->len ); + ssl->out_msglen = cur->len; + ssl->out_msgtype = cur->type; + + /* Update position inside current message */ + ssl->handshake->cur_msg_p += cur->len; + } + else + { + const unsigned char * const p = ssl->handshake->cur_msg_p; + const size_t hs_len = cur->len - 12; + const size_t frag_off = p - ( cur->p + 12 ); + const size_t rem_len = hs_len - frag_off; + size_t cur_hs_frag_len, max_hs_frag_len; + + if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) ) + { + if( is_finished ) + { + if( ( ret = ssl_swap_epochs( ssl ) ) != 0 ) + return( ret ); + } + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + max_hs_frag_len = max_frag_len - 12; + + cur_hs_frag_len = rem_len > max_hs_frag_len ? + max_hs_frag_len : rem_len; + + if( frag_off == 0 && cur_hs_frag_len != hs_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)", + (unsigned) cur_hs_frag_len, + (unsigned) max_hs_frag_len ) ); + } + + /* Messages are stored with handshake headers as if not fragmented, + * copy beginning of headers then fill fragmentation fields. + * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */ + memcpy( ssl->out_msg, cur->p, 6 ); + + ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff ); + ssl->out_msg[7] = ( ( frag_off >> 8 ) & 0xff ); + ssl->out_msg[8] = ( ( frag_off ) & 0xff ); + + ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff ); + ssl->out_msg[10] = ( ( cur_hs_frag_len >> 8 ) & 0xff ); + ssl->out_msg[11] = ( ( cur_hs_frag_len ) & 0xff ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 ); + + /* Copy the handshake message content and set records fields */ + memcpy( ssl->out_msg + 12, p, cur_hs_frag_len ); + ssl->out_msglen = cur_hs_frag_len + 12; + ssl->out_msgtype = cur->type; + + /* Update position inside current message */ + ssl->handshake->cur_msg_p += cur_hs_frag_len; + } + + /* If done with the current message move to the next one if any */ + if( ssl->handshake->cur_msg_p >= cur->p + cur->len ) + { + if( cur->next != NULL ) + { + ssl->handshake->cur_msg = cur->next; + ssl->handshake->cur_msg_p = cur->next->p + 12; + } + else + { + ssl->handshake->cur_msg = NULL; + ssl->handshake->cur_msg_p = NULL; + } + } + + /* Actually send the message out */ + if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + /* Update state and set timer */ + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + else + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) ); + + return( 0 ); +} + +/* + * To be called when the last message of an incoming flight is received. + */ +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ) +{ + /* We won't need to resend that one any more */ + ssl_flight_free( ssl->handshake->flight ); + ssl->handshake->flight = NULL; + ssl->handshake->cur_msg = NULL; + + /* The next incoming flight will start with this msg_seq */ + ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; + + /* We don't want to remember CCS's across flight boundaries. */ + ssl->handshake->buffering.seen_ccs = 0; + + /* Clear future message buffering structure. */ + ssl_buffering_free( ssl ); + + /* Cancel timer */ + ssl_set_timer( ssl, 0 ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; +} + +/* + * To be called when the last message of an outgoing flight is send. + */ +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) +{ + ssl_reset_retransmit_timeout( ssl ); + ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/* + * Handshake layer functions + */ + +/* + * Write (DTLS: or queue) current handshake (including CCS) message. + * + * - fill in handshake headers + * - update handshake checksum + * - DTLS: save message for resending + * - then pass to the record layer + * + * DTLS: except for HelloRequest, messages are only queued, and will only be + * actually sent when calling flight_transmit() or resend(). + * + * Inputs: + * - ssl->out_msglen: 4 + actual handshake message len + * (4 is the size of handshake headers for TLS) + * - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc) + * - ssl->out_msg + 4: the handshake message body + * + * Outputs, ie state before passing to flight_append() or write_record(): + * - ssl->out_msglen: the length of the record contents + * (including handshake headers but excluding record headers) + * - ssl->out_msg: the record contents (handshake headers + content) + */ +int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ) +{ + int ret; + const size_t hs_len = ssl->out_msglen - 4; + const unsigned char hs_type = ssl->out_msg[0]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) ); + + /* + * Sanity checks + */ + if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + /* In SSLv3, the client might send a NoCertificate alert. */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) + if( ! ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->out_msgtype == MBEDTLS_SSL_MSG_ALERT && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) ) +#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + + /* Whenever we send anything different from a + * HelloRequest we should be in a handshake - double check. */ + if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) && + ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } +#endif + + /* Double-check that we did not exceed the bounds + * of the outgoing record buffer. + * This should never fail as the various message + * writing functions must obey the bounds of the + * outgoing record buffer, but better be safe. + * + * Note: We deliberately do not check for the MTU or MFL here. + */ + if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: " + "size %u, maximum %u", + (unsigned) ssl->out_msglen, + (unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Fill handshake headers + */ + if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + ssl->out_msg[1] = (unsigned char)( hs_len >> 16 ); + ssl->out_msg[2] = (unsigned char)( hs_len >> 8 ); + ssl->out_msg[3] = (unsigned char)( hs_len ); + + /* + * DTLS has additional fields in the Handshake layer, + * between the length field and the actual payload: + * uint16 message_seq; + * uint24 fragment_offset; + * uint24 fragment_length; + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Make room for the additional DTLS fields */ + if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: " + "size %u, maximum %u", + (unsigned) ( hs_len ), + (unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len ); + ssl->out_msglen += 8; + + /* Write message_seq and update it, except for HelloRequest */ + if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + { + ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF; + ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF; + ++( ssl->handshake->out_msg_seq ); + } + else + { + ssl->out_msg[4] = 0; + ssl->out_msg[5] = 0; + } + + /* Handshake hashes are computed without fragmentation, + * so set frag_offset = 0 and frag_len = hs_len for now */ + memset( ssl->out_msg + 6, 0x00, 3 ); + memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Update running hashes of handshake messages seen */ + if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen ); + } + + /* Either send now, or just save to be sent (and resent) later */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) ) + { + if( ( ret = ssl_flight_append( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret ); + return( ret ); + } + } + else +#endif + { + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) ); + + return( 0 ); +} + +/* + * Record layer functions + */ + +/* + * Write current record. + * + * Uses: + * - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS) + * - ssl->out_msglen: length of the record content (excl headers) + * - ssl->out_msg: record content + */ +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ) +{ + int ret, done = 0; + size_t len = ssl->out_msglen; + uint8_t flush = force_flush; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_out != NULL && + ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + } +#endif /*MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_write != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) ); + + ret = mbedtls_ssl_hw_record_write( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done ) + { + unsigned i; + size_t protected_record_size; + + ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, ssl->out_hdr + 1 ); + + memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 ); + ssl->out_len[0] = (unsigned char)( len >> 8 ); + ssl->out_len[1] = (unsigned char)( len ); + + if( ssl->transform_out != NULL ) + { + if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + ssl->out_len[0] = (unsigned char)( len >> 8 ); + ssl->out_len[1] = (unsigned char)( len ); + } + + protected_record_size = len + mbedtls_ssl_hdr_len( ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* In case of DTLS, double-check that we don't exceed + * the remaining space in the datagram. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + + if( protected_record_size > (size_t) ret ) + { + /* Should never happen */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + ssl->out_hdr[0], ssl->out_hdr[1], + ssl->out_hdr[2], len ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_hdr, protected_record_size ); + + ssl->out_left += protected_record_size; + ssl->out_hdr += protected_record_size; + ssl_update_out_pointers( ssl, ssl->transform_out ); + + for( i = 8; i > ssl_ep_len( ssl ); i-- ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + flush == SSL_DONT_FORCE_FLUSH ) + { + size_t remaining; + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram", + ret ); + return( ret ); + } + + remaining = (size_t) ret; + if( remaining == 0 ) + { + flush = SSL_FORCE_FLUSH; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ( flush == SSL_FORCE_FLUSH ) && + ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < ssl->in_hslen || + memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || + memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 ) + { + return( 1 ); + } + return( 0 ); +} + +static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[9] << 16 ) | + ( ssl->in_msg[10] << 8 ) | + ssl->in_msg[11] ); +} + +static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[6] << 16 ) | + ( ssl->in_msg[7] << 8 ) | + ssl->in_msg[8] ); +} + +static int ssl_check_hs_header( mbedtls_ssl_context const *ssl ) +{ + uint32_t msg_len, frag_off, frag_len; + + msg_len = ssl_get_hs_total_len( ssl ); + frag_off = ssl_get_hs_frag_off( ssl ); + frag_len = ssl_get_hs_frag_len( ssl ); + + if( frag_off > msg_len ) + return( -1 ); + + if( frag_len > msg_len - frag_off ) + return( -1 ); + + if( frag_len + 12 > ssl->in_msglen ) + return( -1 ); + + return( 0 ); +} + +/* + * Mark bits in bitmask (used for DTLS HS reassembly) + */ +static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len ) +{ + unsigned int start_bits, end_bits; + + start_bits = 8 - ( offset % 8 ); + if( start_bits != 8 ) + { + size_t first_byte_idx = offset / 8; + + /* Special case */ + if( len <= start_bits ) + { + for( ; len != 0; len-- ) + mask[first_byte_idx] |= 1 << ( start_bits - len ); + + /* Avoid potential issues with offset or len becoming invalid */ + return; + } + + offset += start_bits; /* Now offset % 8 == 0 */ + len -= start_bits; + + for( ; start_bits != 0; start_bits-- ) + mask[first_byte_idx] |= 1 << ( start_bits - 1 ); + } + + end_bits = len % 8; + if( end_bits != 0 ) + { + size_t last_byte_idx = ( offset + len ) / 8; + + len -= end_bits; /* Now len % 8 == 0 */ + + for( ; end_bits != 0; end_bits-- ) + mask[last_byte_idx] |= 1 << ( 8 - end_bits ); + } + + memset( mask + offset / 8, 0xFF, len / 8 ); +} + +/* + * Check that bitmask is full + */ +static int ssl_bitmask_check( unsigned char *mask, size_t len ) +{ + size_t i; + + for( i = 0; i < len / 8; i++ ) + if( mask[i] != 0xFF ) + return( -1 ); + + for( i = 0; i < len % 8; i++ ) + if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 ) + return( -1 ); + + return( 0 ); +} + +/* msg_len does not include the handshake header */ +static size_t ssl_get_reassembly_buffer_size( size_t msg_len, + unsigned add_bitmap ) +{ + size_t alloc_len; + + alloc_len = 12; /* Handshake header */ + alloc_len += msg_len; /* Content buffer */ + + if( add_bitmap ) + alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap */ + + return( alloc_len ); +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[1] << 16 ) | + ( ssl->in_msg[2] << 8 ) | + ssl->in_msg[3] ); +} + +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" + " %d, type = %d, hslen = %d", + ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + int ret; + unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + + if( ssl_check_hs_header( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->handshake != NULL && + ( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && + recv_msg_seq != ssl->handshake->in_msg_seq ) || + ( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) ) + { + if( recv_msg_seq > ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + + /* Retransmit only on last message from previous flight, to avoid + * too many retransmissions. + * Besides, No sane server ever retransmits HelloVerifyRequest */ + if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && + ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, " + "message_seq = %d, start_of_flight = %d", + recv_msg_seq, + ssl->handshake->in_flight_start_seq ) ); + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: " + "message_seq = %d, expected = %d", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + } + + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } + /* Wait until message completion to increment in_msg_seq */ + + /* Message reassembly is handled alongside buffering of future + * messages; the commonality is that both handshake fragments and + * future messages cannot be forwarded immediately to the + * handshake logic layer. */ + if( ssl_hs_is_proper_fragment( ssl ) == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + /* With TLS we don't handle fragmentation (for now) */ + if( ssl->in_msglen < ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} + +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL ) + { + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + } + + /* Handshake message is complete, increment counter */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL ) + { + unsigned offset; + mbedtls_ssl_hs_buffer *hs_buf; + + /* Increment handshake sequence number */ + hs->in_msg_seq++; + + /* + * Clear up handshake buffering and reassembly structure. + */ + + /* Free first entry */ + ssl_buffering_free_slot( ssl, 0 ); + + /* Shift all other entries */ + for( offset = 0, hs_buf = &hs->buffering.hs[0]; + offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS; + offset++, hs_buf++ ) + { + *hs_buf = *(hs_buf + 1); + } + + /* Create a fresh last entry */ + memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); + } +#endif +} + +/* + * DTLS anti-replay: RFC 6347 4.1.2.6 + * + * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). + * Bit n is set iff record number in_window_top - n has been seen. + * + * Usually, in_window_top is the last record number seen and the lsb of + * in_window is set. The only exception is the initial state (record number 0 + * not seen yet). + */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ) +{ + ssl->in_window_top = 0; + ssl->in_window = 0; +} + +static inline uint64_t ssl_load_six_bytes( unsigned char *buf ) +{ + return( ( (uint64_t) buf[0] << 40 ) | + ( (uint64_t) buf[1] << 32 ) | + ( (uint64_t) buf[2] << 24 ) | + ( (uint64_t) buf[3] << 16 ) | + ( (uint64_t) buf[4] << 8 ) | + ( (uint64_t) buf[5] ) ); +} + +/* + * Return 0 if sequence number is acceptable, -1 otherwise + */ +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + uint64_t bit; + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return( 0 ); + + if( rec_seqnum > ssl->in_window_top ) + return( 0 ); + + bit = ssl->in_window_top - rec_seqnum; + + if( bit >= 64 ) + return( -1 ); + + if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 ) + return( -1 ); + + return( 0 ); +} + +/* + * Update replay window on new validated record + */ +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return; + + if( rec_seqnum > ssl->in_window_top ) + { + /* Update window_top and the contents of the window */ + uint64_t shift = rec_seqnum - ssl->in_window_top; + + if( shift >= 64 ) + ssl->in_window = 1; + else + { + ssl->in_window <<= shift; + ssl->in_window |= 1; + } + + ssl->in_window_top = rec_seqnum; + } + else + { + /* Mark that number as seen in the current window */ + uint64_t bit = ssl->in_window_top - rec_seqnum; + + if( bit < 64 ) /* Always true, but be extra sure */ + ssl->in_window |= (uint64_t) 1 << bit; + } +} +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +/* Forward declaration */ +static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); + +/* + * Without any SSL context, check if a datagram looks like a ClientHello with + * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message. + * Both input and output include full DTLS headers. + * + * - if cookie is valid, return 0 + * - if ClientHello looks superficially valid but cookie is not, + * fill obuf and set olen, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - otherwise return a specific error code + */ +static int ssl_check_dtls_clihlo_cookie( + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie, + const unsigned char *cli_id, size_t cli_id_len, + const unsigned char *in, size_t in_len, + unsigned char *obuf, size_t buf_len, size_t *olen ) +{ + size_t sid_len, cookie_len; + unsigned char *p; + + if( f_cookie_write == NULL || f_cookie_check == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* + * Structure of ClientHello with record and handshake headers, + * and expected values. We don't need to check a lot, more checks will be + * done when actually parsing the ClientHello - skipping those checks + * avoids code duplication and does not make cookie forging any easier. + * + * 0-0 ContentType type; copied, must be handshake + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied, must be 0 + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; (ignored) + * + * 13-13 HandshakeType msg_type; (ignored) + * 14-16 uint24 length; (ignored) + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied, must be 0 + * 22-24 uint24 fragment_length; (ignored) + * + * 25-26 ProtocolVersion client_version; (ignored) + * 27-58 Random random; (ignored) + * 59-xx SessionID session_id; 1 byte len + sid_len content + * 60+ opaque cookie<0..2^8-1>; 1 byte len + content + * ... + * + * Minimum length is 61 bytes. + */ + if( in_len < 61 || + in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || + in[3] != 0 || in[4] != 0 || + in[19] != 0 || in[20] != 0 || in[21] != 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + sid_len = in[59]; + if( sid_len > in_len - 61 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + cookie_len = in[60 + sid_len]; + if( cookie_len > in_len - 60 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len, + cli_id, cli_id_len ) == 0 ) + { + /* Valid cookie */ + return( 0 ); + } + + /* + * If we get here, we've got an invalid cookie, let's prepare HVR. + * + * 0-0 ContentType type; copied + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; olen - 13 + * + * 13-13 HandshakeType msg_type; hello_verify_request + * 14-16 uint24 length; olen - 25 + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied + * 22-24 uint24 fragment_length; olen - 25 + * + * 25-26 ProtocolVersion server_version; 0xfe 0xff + * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie + * + * Minimum length is 28. + */ + if( buf_len < 28 ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + /* Copy most fields and adapt others */ + memcpy( obuf, in, 25 ); + obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + obuf[25] = 0xfe; + obuf[26] = 0xff; + + /* Generate and write actual cookie */ + p = obuf + 28; + if( f_cookie_write( p_cookie, + &p, obuf + buf_len, cli_id, cli_id_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + *olen = p - obuf; + + /* Go back and fill length fields */ + obuf[27] = (unsigned char)( *olen - 28 ); + + obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 ); + obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 ); + obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) ); + + obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 ); + obuf[12] = (unsigned char)( ( *olen - 13 ) ); + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +} + +/* + * Handle possible client reconnect with the same UDP quadruplet + * (RFC 6347 Section 4.2.8). + * + * Called by ssl_parse_record_header() in case we receive an epoch 0 record + * that looks like a ClientHello. + * + * - if the input looks like a ClientHello without cookies, + * send back HelloVerifyRequest, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - if the input looks like a ClientHello with a valid cookie, + * reset the session of the current context, and + * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * - if anything goes wrong, return a specific error code + * + * mbedtls_ssl_read_record() will ignore the record if anything else than + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT or 0 is returned, although this function + * cannot not return 0. + */ +static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t len; + + ret = ssl_check_dtls_clihlo_cookie( + ssl->conf->f_cookie_write, + ssl->conf->f_cookie_check, + ssl->conf->p_cookie, + ssl->cli_id, ssl->cli_id_len, + ssl->in_buf, ssl->in_left, + ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); + + if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) + { + int send_ret; + MBEDTLS_SSL_DEBUG_MSG( 1, ( "sending HelloVerifyRequest" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_buf, len ); + /* Don't check write errors as we can't do anything here. + * If the error is permanent we'll catch it later, + * if it's not, then hopefully it'll work next time. */ + send_ret = ssl->f_send( ssl->p_bio, ssl->out_buf, len ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", send_ret ); + (void) send_ret; + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); + } + + if( ret == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cookie is valid, resetting context" ) ); + if( ( ret = ssl_session_reset_int( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + +/* + * ContentType type; + * ProtocolVersion version; + * uint16 epoch; // DTLS only + * uint48 sequence_number; // DTLS only + * uint16 length; + * + * Return 0 if header looks sane (and, for DTLS, the record is expected) + * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad, + * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected. + * + * With DTLS, mbedtls_ssl_read_record() will: + * 1. proceed with the record if this function returns 0 + * 2. drop only the current record if this function returns UNEXPECTED_RECORD + * 3. return CLIENT_RECONNECT if this function return that value + * 4. drop the whole datagram if this function returns anything else. + * Point 2 is needed when the peer is resending, and we have already received + * the first record from a datagram but are still waiting for the others. + */ +static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) +{ + int major_ver, minor_ver; + + MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) ); + + ssl->in_msgtype = ssl->in_hdr[0]; + ssl->in_msglen = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; + mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, ssl->in_hdr + 1 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + ssl->in_msgtype, + major_ver, minor_ver, ssl->in_msglen ) ); + + /* Check record type */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msgtype != MBEDTLS_SSL_MSG_ALERT && + ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && + ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* Silently ignore invalid DTLS records as recommended by RFC 6347 + * Section 4.1.2.7 */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Check version */ + if( major_ver != ssl->major_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Check length against the size of our buffer */ + if( ssl->in_msglen > MBEDTLS_SSL_IN_BUFFER_LEN + - (size_t)( ssl->in_msg - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* + * DTLS-related tests. + * Check epoch before checking length constraint because + * the latter varies with the epoch. E.g., if a ChangeCipherSpec + * message gets duplicated before the corresponding Finished message, + * the second ChangeCipherSpec should be discarded because it belongs + * to an old epoch, but not because its length is shorter than + * the minimum record length for packets using the new record transform. + * Note that these two kinds of failures are handled differently, + * as an unexpected record is silently skipped but an invalid + * record leads to the entire datagram being dropped. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; + + /* Check epoch (and sequence number) with DTLS */ + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: " + "expected %d, received %d", + ssl->in_epoch, rec_epoch ) ); + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) + /* + * Check for an epoch 0 ClientHello. We can't use in_msg here to + * access the first byte of record content (handshake type), as we + * have an active transform (possibly iv_len != 0), so use the + * fact that the record header len is 13 instead. + */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + rec_epoch == 0 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_left > 13 && + ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect " + "from the same port" ) ); + return( ssl_handle_possible_reconnect( ssl ) ); + } + else +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + { + /* Consider buffering the record. */ + if( rec_epoch == (unsigned int) ssl->in_epoch + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + } + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + /* Replay detection only works for the current epoch */ + if( rec_epoch == ssl->in_epoch && + mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } +#endif + + /* Drop unexpected ApplicationData records, + * except at the beginning of renegotiations */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && + ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + + /* Check length against bounds of the current transform and version */ + if( ssl->transform_in == NULL ) + { + if( ssl->in_msglen < 1 || + ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + else + { + if( ssl->in_msglen < ssl->transform_in->minlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * TLS encrypted messages can have up to 256 bytes of padding + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 && + ssl->in_msglen > ssl->transform_in->minlen + + MBEDTLS_SSL_IN_CONTENT_LEN + 256 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif + } + + return( 0 ); +} + +/* + * If applicable, decrypt (and decompress) record content + */ +static int ssl_prepare_record_content( mbedtls_ssl_context *ssl ) +{ + int ret, done = 0; + + MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network", + ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_read != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) ); + + ret = mbedtls_ssl_hw_record_read( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done && ssl->transform_in != NULL ) + { + if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", + ssl->in_msg, ssl->in_msglen ); + + if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_in != NULL && + ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_decompress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + mbedtls_ssl_dtls_replay_update( ssl ); + } +#endif + + return( 0 ); +} + +static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); + +/* + * Read a record. + * + * Silently ignore non-fatal alert (and for DTLS, invalid records as well, + * RFC 6347 4.1.2.7) and continue reading until a valid record is found. + * + */ + +/* Helper functions for mbedtls_ssl_read_record(). */ +static int ssl_consume_current_message( mbedtls_ssl_context *ssl ); +static int ssl_get_next_record( mbedtls_ssl_context *ssl ); +static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, + unsigned update_hs_digest ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); + + if( ssl->keep_current_message == 0 ) + { + do { + + ret = ssl_consume_current_message( ssl ); + if( ret != 0 ) + return( ret ); + + if( ssl_record_is_in_progress( ssl ) == 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + int have_buffered = 0; + + /* We only check for buffered messages if the + * current datagram is fully consumed. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl_next_record_is_in_datagram( ssl ) == 0 ) + { + if( ssl_load_buffered_message( ssl ) == 0 ) + have_buffered = 1; + } + + if( have_buffered == 0 ) +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ret = ssl_get_next_record( ssl ); + if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ) + continue; + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret ); + return( ret ); + } + } + } + + ret = mbedtls_ssl_handle_message_type( ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + /* Buffer future message */ + ret = ssl_buffer_message( ssl ); + if( ret != 0 ) + return( ret ); + + ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret || + MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret ); + + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); + return( ret ); + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + update_hs_digest == 1 ) + { + mbedtls_ssl_update_handshake_status( ssl ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) ); + ssl->keep_current_message = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_left > ssl->next_record_offset ) + return( 1 ); + + return( 0 ); +} + +static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + mbedtls_ssl_hs_buffer * hs_buf; + int ret = 0; + + if( hs == NULL ) + return( -1 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) ); + + if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC || + ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + /* Check if we have seen a ChangeCipherSpec before. + * If yes, synthesize a CCS record. */ + if( !hs->buffering.seen_ccs ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) ); + ret = -1; + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) ); + ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->in_msglen = 1; + ssl->in_msg[0] = 1; + + /* As long as they are equal, the exact value doesn't matter. */ + ssl->in_left = 0; + ssl->next_record_offset = 0; + + hs->buffering.seen_ccs = 0; + goto exit; + } + +#if defined(MBEDTLS_DEBUG_C) + /* Debug only */ + { + unsigned offset; + for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) + { + hs_buf = &hs->buffering.hs[offset]; + if( hs_buf->is_valid == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.", + hs->in_msg_seq + offset, + hs_buf->is_complete ? "fully" : "partially" ) ); + } + } + } +#endif /* MBEDTLS_DEBUG_C */ + + /* Check if we have buffered and/or fully reassembled the + * next handshake message. */ + hs_buf = &hs->buffering.hs[0]; + if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) ) + { + /* Synthesize a record containing the buffered HS message. */ + size_t msg_len = ( hs_buf->data[1] << 16 ) | + ( hs_buf->data[2] << 8 ) | + hs_buf->data[3]; + + /* Double-check that we haven't accidentally buffered + * a message that doesn't fit into the input buffer. */ + if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)", + hs_buf->data, msg_len + 12 ); + + ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->in_hslen = msg_len + 12; + ssl->in_msglen = msg_len + 12; + memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen ); + + ret = 0; + goto exit; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered", + hs->in_msg_seq ) ); + } + + ret = -1; + +exit: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) ); + return( ret ); +} + +static int ssl_buffer_make_space( mbedtls_ssl_context *ssl, + size_t desired ) +{ + int offset; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available", + (unsigned) desired ) ); + + /* Get rid of future records epoch first, if such exist. */ + ssl_free_buffered_record( ssl ); + + /* Check if we have enough space available now. */ + if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) ); + return( 0 ); + } + + /* We don't have enough space to buffer the next expected handshake + * message. Remove buffers used for future messages to gain space, + * starting with the most distant one. */ + for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1; + offset >= 0; offset-- ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message", + offset ) ); + + ssl_buffering_free_slot( ssl, (uint8_t) offset ); + + /* Check if we have enough space available now. */ + if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) ); + return( 0 ); + } + } + + return( -1 ); +} + +static int ssl_buffer_message( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( hs == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) ); + + switch( ssl->in_msgtype ) + { + case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) ); + + hs->buffering.seen_ccs = 1; + break; + + case MBEDTLS_SSL_MSG_HANDSHAKE: + { + unsigned recv_msg_seq_offset; + unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + mbedtls_ssl_hs_buffer *hs_buf; + size_t msg_len = ssl->in_hslen - 12; + + /* We should never receive an old handshake + * message - double-check nonetheless. */ + if( recv_msg_seq < ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq; + if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS ) + { + /* Silently ignore -- message too far in the future */ + MBEDTLS_SSL_DEBUG_MSG( 2, + ( "Ignore future HS message with sequence number %u, " + "buffering window %u - %u", + recv_msg_seq, ssl->handshake->in_msg_seq, + ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) ); + + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ", + recv_msg_seq, recv_msg_seq_offset ) ); + + hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ]; + + /* Check if the buffering for this seq nr has already commenced. */ + if( !hs_buf->is_valid ) + { + size_t reassembly_buf_sz; + + hs_buf->is_fragmented = + ( ssl_hs_is_proper_fragment( ssl ) == 1 ); + + /* We copy the message back into the input buffer + * after reassembly, so check that it's not too large. + * This is an implementation-specific limitation + * and not one from the standard, hence it is not + * checked in ssl_check_hs_header(). */ + if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + /* Ignore message */ + goto exit; + } + + /* Check if we have enough space to buffer the message. */ + if( hs->buffering.total_bytes_buffered > + MBEDTLS_SSL_DTLS_MAX_BUFFERING ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len, + hs_buf->is_fragmented ); + + if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + if( recv_msg_seq_offset > 0 ) + { + /* If we can't buffer a future message because + * of space limitations -- ignore. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n", + (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + goto exit; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- attempt to make space by freeing buffered future messages\n", + (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + } + + if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %u (%u with bitmap) would exceed the compile-time limit %u (already %u bytes buffered) -- fail\n", + (unsigned) msg_len, + (unsigned) reassembly_buf_sz, + MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + goto exit; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", + msg_len ) ); + + hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz ); + if( hs_buf->data == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + hs_buf->data_len = reassembly_buf_sz; + + /* Prepare final header: copy msg_type, length and message_seq, + * then add standardised fragment_offset and fragment_length */ + memcpy( hs_buf->data, ssl->in_msg, 6 ); + memset( hs_buf->data + 6, 0, 3 ); + memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 ); + + hs_buf->is_valid = 1; + + hs->buffering.total_bytes_buffered += reassembly_buf_sz; + } + else + { + /* Make sure msg_type and length are consistent */ + if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) ); + /* Ignore */ + goto exit; + } + } + + if( !hs_buf->is_complete ) + { + size_t frag_len, frag_off; + unsigned char * const msg = hs_buf->data + 12; + + /* + * Check and copy current fragment + */ + + /* Validation of header fields already done in + * mbedtls_ssl_prepare_handshake_record(). */ + frag_off = ssl_get_hs_frag_off( ssl ); + frag_len = ssl_get_hs_frag_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", + frag_off, frag_len ) ); + memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); + + if( hs_buf->is_fragmented ) + { + unsigned char * const bitmask = msg + msg_len; + ssl_bitmask_set( bitmask, frag_off, frag_len ); + hs_buf->is_complete = ( ssl_bitmask_check( bitmask, + msg_len ) == 0 ); + } + else + { + hs_buf->is_complete = 1; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete", + hs_buf->is_complete ? "" : "not yet " ) ); + } + + break; + } + + default: + /* We don't buffer other types of messages. */ + break; + } + +exit: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) ); + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_consume_current_message( mbedtls_ssl_context *ssl ) +{ + /* + * Consume last content-layer message and potentially + * update in_msglen which keeps track of the contents' + * consumption state. + * + * (1) Handshake messages: + * Remove last handshake message, move content + * and adapt in_msglen. + * + * (2) Alert messages: + * Consume whole record content, in_msglen = 0. + * + * (3) Change cipher spec: + * Consume whole record content, in_msglen = 0. + * + * (4) Application data: + * Don't do anything - the record layer provides + * the application data as a stream transport + * and consumes through mbedtls_ssl_read only. + * + */ + + /* Case (1): Handshake messages */ + if( ssl->in_hslen != 0 ) + { + /* Hard assertion to be sure that no application data + * is in flight, as corrupting ssl->in_msglen during + * ssl->in_offt != NULL is fatal. */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Get next Handshake message in the current record + */ + + /* Notes: + * (1) in_hslen is not necessarily the size of the + * current handshake content: If DTLS handshake + * fragmentation is used, that's the fragment + * size instead. Using the total handshake message + * size here is faulty and should be changed at + * some point. + * (2) While it doesn't seem to cause problems, one + * has to be very careful not to assume that in_hslen + * is always <= in_msglen in a sensible communication. + * Again, it's wrong for DTLS handshake fragmentation. + * The following check is therefore mandatory, and + * should not be treated as a silently corrected assertion. + * Additionally, ssl->in_hslen might be arbitrarily out of + * bounds after handling a DTLS message with an unexpected + * sequence number, see mbedtls_ssl_prepare_handshake_record. + */ + if( ssl->in_hslen < ssl->in_msglen ) + { + ssl->in_msglen -= ssl->in_hslen; + memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, + ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", + ssl->in_msg, ssl->in_msglen ); + } + else + { + ssl->in_msglen = 0; + } + + ssl->in_hslen = 0; + } + /* Case (4): Application data */ + else if( ssl->in_offt != NULL ) + { + return( 0 ); + } + /* Everything else (CCS & Alerts) */ + else + { + ssl->in_msglen = 0; + } + + return( 0 ); +} + +static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen > 0 ) + return( 1 ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + if( hs == NULL ) + return; + + if( hs->buffering.future_record.data != NULL ) + { + hs->buffering.total_bytes_buffered -= + hs->buffering.future_record.len; + + mbedtls_free( hs->buffering.future_record.data ); + hs->buffering.future_record.data = NULL; + } +} + +static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + unsigned char * rec; + size_t rec_len; + unsigned rec_epoch; + + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 0 ); + + if( hs == NULL ) + return( 0 ); + + rec = hs->buffering.future_record.data; + rec_len = hs->buffering.future_record.len; + rec_epoch = hs->buffering.future_record.epoch; + + if( rec == NULL ) + return( 0 ); + + /* Only consider loading future records if the + * input buffer is empty. */ + if( ssl_next_record_is_in_datagram( ssl ) == 1 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) ); + + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) ); + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) ); + + /* Double-check that the record is not too large */ + if( rec_len > MBEDTLS_SSL_IN_BUFFER_LEN - + (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( ssl->in_hdr, rec, rec_len ); + ssl->in_left = rec_len; + ssl->next_record_offset = 0; + + ssl_free_buffered_record( ssl ); + +exit: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) ); + return( 0 ); +} + +static int ssl_buffer_future_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + size_t const rec_hdr_len = 13; + size_t const total_buf_sz = rec_hdr_len + ssl->in_msglen; + + /* Don't buffer future records outside handshakes. */ + if( hs == NULL ) + return( 0 ); + + /* Only buffer handshake records (we are only interested + * in Finished messages). */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + return( 0 ); + + /* Don't buffer more than one future epoch record. */ + if( hs->buffering.future_record.data != NULL ) + return( 0 ); + + /* Don't buffer record if there's not enough buffering space remaining. */ + if( total_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n", + (unsigned) total_buf_sz, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + return( 0 ); + } + + /* Buffer record */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u", + ssl->in_epoch + 1 ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", ssl->in_hdr, + rec_hdr_len + ssl->in_msglen ); + + /* ssl_parse_record_header() only considers records + * of the next epoch as candidates for buffering. */ + hs->buffering.future_record.epoch = ssl->in_epoch + 1; + hs->buffering.future_record.len = total_buf_sz; + + hs->buffering.future_record.data = + mbedtls_calloc( 1, hs->buffering.future_record.len ); + if( hs->buffering.future_record.data == NULL ) + { + /* If we run out of RAM trying to buffer a + * record from the next epoch, just ignore. */ + return( 0 ); + } + + memcpy( hs->buffering.future_record.data, ssl->in_hdr, total_buf_sz ); + + hs->buffering.total_bytes_buffered += total_buf_sz; + return( 0 ); +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_get_next_record( mbedtls_ssl_context *ssl ) +{ + int ret; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* We might have buffered a future record; if so, + * and if the epoch matches now, load it. + * On success, this call will set ssl->in_left to + * the length of the buffered record, so that + * the calls to ssl_fetch_input() below will + * essentially be no-ops. */ + ret = ssl_load_buffered_record( ssl ); + if( ret != 0 ) + return( ret ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + if( ( ret = ssl_parse_record_header( ssl ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT ) + { + if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + ret = ssl_buffer_future_record( ssl ); + if( ret != 0 ) + return( ret ); + + /* Fall through to handling of unexpected records */ + ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; + } + + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ) + { + /* Skip unexpected record (but not whole datagram) */ + ssl->next_record_offset = ssl->in_msglen + + mbedtls_ssl_hdr_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record " + "(header)" ) ); + } + else + { + /* Skip invalid record and the rest of the datagram */ + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record " + "(header)" ) ); + } + + /* Get next record */ + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } +#endif + return( ret ); + } + + /* + * Read and optionally decrypt the message contents + */ + if( ( ret = mbedtls_ssl_fetch_input( ssl, + mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + /* Done reading this record, get ready for the next one */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->next_record_offset = ssl->in_msglen + mbedtls_ssl_hdr_len( ssl ); + if( ssl->next_record_offset < ssl->in_left ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) ); + } + } + else +#endif + ssl->in_left = 0; + + if( ( ret = ssl_prepare_record_content( ssl ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Silently discard invalid records */ + if( ret == MBEDTLS_ERR_SSL_INVALID_RECORD || + ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + /* Except when waiting for Finished as a bad mac here + * probably means something went wrong in the handshake + * (eg wrong psk used, mitm downgrade attempt, etc.) */ + if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED || + ssl->state == MBEDTLS_SSL_SERVER_FINISHED ) + { +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + if( ssl->conf->badmac_limit != 0 && + ++ssl->badmac_seen >= ssl->conf->badmac_limit ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } +#endif + + /* As above, invalid records cause + * dismissal of the whole datagram. */ + + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } + + return( ret ); + } + else +#endif + { + /* Error out (and send alert) on invalid records */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + } + + return( 0 ); +} + +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) +{ + int ret; + + /* + * Handle particular types of records + */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 ) + { + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + if( ssl->in_msglen != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_msg[0] != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x", + ssl->in_msg[0] ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + if( ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } +#endif + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + if( ssl->in_msglen != 2 ) + { + /* Note: Standard allows for more than one 2 byte alert + to be packed in a single message, but Mbed TLS doesn't + currently support this. */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", + ssl->in_msg[0], ssl->in_msg[1] ) ); + + /* + * Ignore non-fatal alerts, except close_notify and no_renegotiation + */ + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)", + ssl->in_msg[1] ) ); + return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ); + } + + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); + return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) ); + /* Will be handled when trying to parse ServerHello */ + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); + /* Will be handled in mbedtls_ssl_parse_certificate() */ + return( 0 ); + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ + + /* Silently ignore: fetch new message */ + return MBEDTLS_ERR_SSL_NON_FATAL; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ssl_handshake_wrapup_free_hs_transform( ssl ); + } +#endif + + return( 0 ); +} + +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ) +{ + int ret; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message )); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msglen = 2; + ssl->out_msg[0] = level; + ssl->out_msg[1] = message; + + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); + + return( 0 ); +} + +/* + * Handshake functions + */ +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +/* No certificate support -> dummy functions */ +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} + +#else +/* Some certificate support -> implement write and parse */ + +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const mbedtls_x509_crt *crt; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + if( ssl->client_auth == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* + * If using SSLv3 and got no cert, send an Alert message + * (otherwise an empty Certificate message will be sent). + */ + if( mbedtls_ssl_own_cert( ssl ) == NULL && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->out_msglen = 2; + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msg[0] = MBEDTLS_SSL_ALERT_LEVEL_WARNING; + ssl->out_msg[1] = MBEDTLS_SSL_ALERT_MSG_NO_CERT; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) ); + goto write_msg; + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + } +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( mbedtls_ssl_own_cert( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) ); + return( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_CRT( 3, "own certificate", mbedtls_ssl_own_cert( ssl ) ); + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 6 length of all certs + * 7 . 9 length of cert. 1 + * 10 . n-1 peer certificate + * n . n+2 length of cert. 2 + * n+3 . ... upper level cert, etc. + */ + i = 7; + crt = mbedtls_ssl_own_cert( ssl ); + + while( crt != NULL ) + { + n = crt->raw.len; + if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", + i + 3 + n, MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ); + } + + ssl->out_msg[i ] = (unsigned char)( n >> 16 ); + ssl->out_msg[i + 1] = (unsigned char)( n >> 8 ); + ssl->out_msg[i + 2] = (unsigned char)( n ); + + i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n ); + i += n; crt = crt->next; + } + + ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 ); + ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 ); + ssl->out_msg[6] = (unsigned char)( ( i - 7 ) ); + + ssl->out_msglen = i; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) +write_msg: +#endif + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); + + return( ret ); +} + +/* + * Once the certificate message is read, parse it into a cert chain and + * perform basic checks, but leave actual verification to the caller + */ +static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t i, n; + uint8_t alert; + +#if defined(MBEDTLS_SSL_SRV_C) +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* + * Check if the client sent an empty certificate + */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( ssl->in_msglen == 2 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT && + ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); + + /* The client was asked for a certificate but didn't send + one. The client should know what's going on, so we + don't send an alert. */ + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && + memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); + + /* The client was asked for a certificate but didn't send + one. The client should know what's going on, so we + don't send an alert. */ + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_SRV_C */ + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE || + ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * Same message structure as in mbedtls_ssl_write_certificate() + */ + n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; + + if( ssl->in_msg[i] != 0 || + ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* In case we tried to reuse a session but it failed */ + if( ssl->session_negotiate->peer_cert != NULL ) + { + mbedtls_x509_crt_free( ssl->session_negotiate->peer_cert ); + mbedtls_free( ssl->session_negotiate->peer_cert ); + } + + if( ( ssl->session_negotiate->peer_cert = mbedtls_calloc( 1, + sizeof( mbedtls_x509_crt ) ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + sizeof( mbedtls_x509_crt ) ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert ); + + i += 3; + + while( i < ssl->in_hslen ) + { + if ( i + 3 > ssl->in_hslen ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + if( ssl->in_msg[i] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + n = ( (unsigned int) ssl->in_msg[i + 1] << 8 ) + | (unsigned int) ssl->in_msg[i + 2]; + i += 3; + + if( n < 128 || i + n > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert, + ssl->in_msg + i, n ); + switch( ret ) + { + case 0: /*ok*/ + case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: + /* Ignore certificate with an unknown algorithm: maybe a + prior certificate was already trusted. */ + break; + + case MBEDTLS_ERR_X509_ALLOC_FAILED: + alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR; + goto crt_parse_der_failed; + + case MBEDTLS_ERR_X509_UNKNOWN_VERSION: + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + goto crt_parse_der_failed; + + default: + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + crt_parse_der_failed: + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert ); + MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); + return( ret ); + } + + i += n; + } + + MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert ); + + /* + * On client, make sure the server cert doesn't change during renego to + * avoid "triple handshake" attack: https://secure-resumption.com/ + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + if( ssl->session->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + if( ssl->session->peer_cert->raw.len != + ssl->session_negotiate->peer_cert->raw.len || + memcmp( ssl->session->peer_cert->raw.p, + ssl->session_negotiate->peer_cert->raw.p, + ssl->session->peer_cert->raw.len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + + return( 0 ); +} + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + int ret; + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET + ? ssl->handshake->sni_authmode + : ssl->conf->authmode; +#else + const int authmode = ssl->conf->authmode; +#endif + void *rs_ctx = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + + ssl->state++; + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_crt_verify ) + { + goto crt_verify; + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + /* mbedtls_ssl_read_record may have sent an alert already. We + let it decide whether to alert. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ( ret = ssl_parse_certificate_chain( ssl ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_SRV_C) + if( ret == MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE && + authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) + { + ret = 0; + } +#endif + + ssl->state++; + return( ret ); + } + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled) + ssl->handshake->ecrs_state = ssl_ecrs_crt_verify; + +crt_verify: + if( ssl->handshake->ecrs_enabled) + rs_ctx = &ssl->handshake->ecrs_ctx; +#endif + + if( authmode != MBEDTLS_SSL_VERIFY_NONE ) + { + mbedtls_x509_crt *ca_chain; + mbedtls_x509_crl *ca_crl; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + { + ca_chain = ssl->handshake->sni_ca_chain; + ca_crl = ssl->handshake->sni_ca_crl; + } + else +#endif + { + ca_chain = ssl->conf->ca_chain; + ca_crl = ssl->conf->ca_crl; + } + + /* + * Main check: verify certificate + */ + ret = mbedtls_x509_crt_verify_restartable( + ssl->session_negotiate->peer_cert, + ca_chain, ca_crl, + ssl->conf->cert_profile, + ssl->hostname, + &ssl->session_negotiate->verify_result, + ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx ); + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); + } + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ); +#endif + + /* + * Secondary checks: always done, but change 'ret' only if it was 0 + */ + +#if defined(MBEDTLS_ECP_C) + { + const mbedtls_pk_context *pk = &ssl->session_negotiate->peer_cert->pk; + + /* If certificate uses an EC key, make sure the curve is OK */ + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) && + mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 ) + { + ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + } + } +#endif /* MBEDTLS_ECP_C */ + + if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert, + ciphersuite_info, + ! ssl->conf->endpoint, + &ssl->session_negotiate->verify_result ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + } + + /* mbedtls_x509_crt_verify_with_profile is supposed to report a + * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED, + * with details encoded in the verification flags. All other kinds + * of error codes, including those from the user provided f_vrfy + * functions, are treated as fatal and lead to a failure of + * ssl_parse_certificate even if verification was optional. */ + if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && + ( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || + ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) ) + { + ret = 0; + } + + if( ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); + ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; + } + + if( ret != 0 ) + { + uint8_t alert; + + /* The certificate may have been rejected for several reasons. + Pick one and send the corresponding alert. Which alert to send + may be a subject of debate in some cases. */ + if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER ) + alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH ) + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED ) + alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED ) + alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED ) + alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA; + else + alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN; + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + alert ); + } + +#if defined(MBEDTLS_DEBUG_C) + if( ssl->session_negotiate->verify_result != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %x", + ssl->session_negotiate->verify_result ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) ); + } +#endif /* MBEDTLS_DEBUG_C */ + } + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->out_msglen = 1; + ssl->out_msg[0] = 1; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); + + return( 0 ); +} + +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* CCS records are only accepted if they have length 1 and content '1', + * so we don't need to check this here. */ + + /* + * Switch to our negotiated transform and session parameters for inbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); + ssl->transform_in = ssl->transform_negotiate; + ssl->session_in = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + ssl_dtls_replay_reset( ssl ); +#endif + + /* Increment epoch */ + if( ++ssl->in_epoch == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + /* This is highly unlikely to happen for legitimate reasons, so + treat it as an attack and don't send an alert. */ + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->in_ctr, 0, 8 ); + + ssl_update_in_pointers( ssl, ssl->transform_negotiate ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); + + return( 0 ); +} + +void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info ) +{ + ((void) ciphersuite_info); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + ssl->handshake->update_checksum = ssl_update_checksum_md5sha1; + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha384; + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( ciphersuite_info->mac != MBEDTLS_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha256; + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return; + } +} + +void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_starts_ret( &ssl->handshake->fin_md5 ); + mbedtls_sha1_starts_ret( &ssl->handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_starts_ret( &ssl->handshake->fin_sha256, 0 ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_starts_ret( &ssl->handshake->fin_sha512, 1 ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +static void ssl_update_checksum_start( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_update_ret( &ssl->handshake->fin_md5 , buf, len ); + mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + mbedtls_md5_update_ret( &ssl->handshake->fin_md5 , buf, len ); + mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len ); +} +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_update_checksum_sha256( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len ); +} +#endif + +#if defined(MBEDTLS_SHA512_C) +static void ssl_update_checksum_sha384( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len ); +} +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static void ssl_calc_finished_ssl( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + const char *sender; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + + unsigned char padbuf[48]; + unsigned char md5sum[16]; + unsigned char sha1sum[20]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + /* + * SSLv3: + * hash = + * MD5( master + pad2 + + * MD5( handshake + sender + master + pad1 ) ) + * + SHA1( master + pad2 + + * SHA1( handshake + sender + master + pad1 ) ) + */ + +#if !defined(MBEDTLS_MD5_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); +#endif + +#if !defined(MBEDTLS_SHA1_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) ? "CLNT" + : "SRVR"; + + memset( padbuf, 0x36, 48 ); + + mbedtls_md5_update_ret( &md5, (const unsigned char *) sender, 4 ); + mbedtls_md5_update_ret( &md5, session->master, 48 ); + mbedtls_md5_update_ret( &md5, padbuf, 48 ); + mbedtls_md5_finish_ret( &md5, md5sum ); + + mbedtls_sha1_update_ret( &sha1, (const unsigned char *) sender, 4 ); + mbedtls_sha1_update_ret( &sha1, session->master, 48 ); + mbedtls_sha1_update_ret( &sha1, padbuf, 40 ); + mbedtls_sha1_finish_ret( &sha1, sha1sum ); + + memset( padbuf, 0x5C, 48 ); + + mbedtls_md5_starts_ret( &md5 ); + mbedtls_md5_update_ret( &md5, session->master, 48 ); + mbedtls_md5_update_ret( &md5, padbuf, 48 ); + mbedtls_md5_update_ret( &md5, md5sum, 16 ); + mbedtls_md5_finish_ret( &md5, buf ); + + mbedtls_sha1_starts_ret( &sha1 ); + mbedtls_sha1_update_ret( &sha1, session->master, 48 ); + mbedtls_sha1_update_ret( &sha1, padbuf , 40 ); + mbedtls_sha1_update_ret( &sha1, sha1sum, 20 ); + mbedtls_sha1_finish_ret( &sha1, buf + 16 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + mbedtls_platform_zeroize( md5sum, sizeof( md5sum ) ); + mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_calc_finished_tls( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char padbuf[36]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + /* + * TLSv1: + * hash = PRF( master, finished_label, + * MD5( handshake ) + SHA1( handshake ) )[0..11] + */ + +#if !defined(MBEDTLS_MD5_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); +#endif + +#if !defined(MBEDTLS_SHA1_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + mbedtls_md5_finish_ret( &md5, padbuf ); + mbedtls_sha1_finish_ret( &sha1, padbuf + 16 ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 36, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_calc_finished_tls_sha256( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + mbedtls_sha256_context sha256; + unsigned char padbuf[32]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + mbedtls_sha256_init( &sha256 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) ); + + mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(MBEDTLS_SHA256_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) + sha256.state, sizeof( sha256.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + mbedtls_sha256_finish_ret( &sha256, padbuf ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 32, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_sha256_free( &sha256 ); + + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + +typedef int (*finish_sha384_t)(mbedtls_sha512_context*, unsigned char*); + +static void ssl_calc_finished_tls_sha384( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + mbedtls_sha512_context sha512; + unsigned char padbuf[48]; + /* + * For SHA-384, we can save 16 bytes by keeping padbuf 48 bytes long. + * However, to avoid stringop-overflow warning in gcc, we have to cast + * mbedtls_sha512_finish_ret(). + */ + finish_sha384_t finish_sha384 = (finish_sha384_t)mbedtls_sha512_finish_ret; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + mbedtls_sha512_init( &sha512 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) ); + + mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(MBEDTLS_SHA512_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha512 state", (unsigned char *) + sha512.state, sizeof( sha512.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + finish_sha384( &sha512, padbuf ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 48, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_sha512_free( &sha512 ); + + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) +{ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup: final free" ) ); + + /* + * Free our handshake params + */ + mbedtls_ssl_handshake_free( ssl ); + mbedtls_free( ssl->handshake ); + ssl->handshake = NULL; + + /* + * Free the previous transform and swith in the current one + */ + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + } + ssl->transform = ssl->transform_negotiate; + ssl->transform_negotiate = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup: final free" ) ); +} + +void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) +{ + int resume = ssl->handshake->resume; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_DONE; + ssl->renego_records_seen = 0; + } +#endif + + /* + * Free the previous session and switch in the current one + */ + if( ssl->session ) + { +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + /* RFC 7366 3.1: keep the EtM state */ + ssl->session_negotiate->encrypt_then_mac = + ssl->session->encrypt_then_mac; +#endif + + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + ssl->session = ssl->session_negotiate; + ssl->session_negotiate = NULL; + + /* + * Add cache entry + */ + if( ssl->conf->f_set_cache != NULL && + ssl->session->id_len != 0 && + resume == 0 ) + { + if( ssl->conf->f_set_cache( ssl->conf->p_cache, ssl->session ) != 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cache did not store session" ) ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->flight != NULL ) + { + /* Cancel handshake timer */ + ssl_set_timer( ssl, 0 ); + + /* Keep last flight around in case we need to resend it: + * we need the handshake and transform structures for that */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip freeing handshake and transform" ) ); + } + else +#endif + ssl_handshake_wrapup_free_hs_transform( ssl ); + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); +} + +int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) +{ + int ret, hash_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); + + ssl_update_out_pointers( ssl, ssl->transform_negotiate ); + + ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); + + /* + * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites + * may define some other value. Currently (early 2016), no defined + * ciphersuite does this (and this is unlikely to change as activity has + * moved to TLS 1.3 now) so we can keep the hardcoded 12 here. + */ + hash_len = ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) ? 36 : 12; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len ); +#endif + + ssl->out_msglen = 4 + hash_len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED; + + /* + * In case of session resuming, invert the client and server + * ChangeCipherSpec messages order. + */ + if( ssl->handshake->resume != 0 ) + { +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif + } + else + ssl->state++; + + /* + * Switch to our negotiated transform and session parameters for outbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + unsigned char i; + + /* Remember current epoch settings for resending */ + ssl->handshake->alt_transform_out = ssl->transform_out; + memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8 ); + + /* Set sequence_number to zero */ + memset( ssl->cur_out_ctr + 2, 0, 6 ); + + /* Increment epoch */ + for( i = 2; i > 0; i-- ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->cur_out_ctr, 0, 8 ); + + ssl->transform_out = ssl->transform_negotiate; + ssl->session_out = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define SSL_MAX_HASH_LEN 36 +#else +#define SSL_MAX_HASH_LEN 12 +#endif + +int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned int hash_len; + unsigned char buf[SSL_MAX_HASH_LEN]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished" ) ); + + ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* There is currently no ciphersuite using another length with TLS 1.2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + hash_len = 36; + else +#endif + hash_len = 12; + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); + } + + if( mbedtls_ssl_safer_memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), + buf, hash_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->peer_verify_data, buf, hash_len ); +#endif + + if( ssl->handshake->resume != 0 ) + { +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; +#endif + } + else + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse finished" ) ); + + return( 0 ); +} + +static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) +{ + memset( handshake, 0, sizeof( mbedtls_ssl_handshake_params ) ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_init( &handshake->fin_md5 ); + mbedtls_sha1_init( &handshake->fin_sha1 ); + mbedtls_md5_starts_ret( &handshake->fin_md5 ); + mbedtls_sha1_starts_ret( &handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_init( &handshake->fin_sha256 ); + mbedtls_sha256_starts_ret( &handshake->fin_sha256, 0 ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_init( &handshake->fin_sha512 ); + mbedtls_sha512_starts_ret( &handshake->fin_sha512, 1 ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + handshake->update_checksum = ssl_update_checksum_start; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + mbedtls_ssl_sig_hash_set_init( &handshake->hash_algs ); +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_init( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_init( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_init( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx ); +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; +#endif +} + +static void ssl_transform_init( mbedtls_ssl_transform *transform ) +{ + memset( transform, 0, sizeof(mbedtls_ssl_transform) ); + + mbedtls_cipher_init( &transform->cipher_ctx_enc ); + mbedtls_cipher_init( &transform->cipher_ctx_dec ); + + mbedtls_md_init( &transform->md_ctx_enc ); + mbedtls_md_init( &transform->md_ctx_dec ); +} + +void mbedtls_ssl_session_init( mbedtls_ssl_session *session ) +{ + memset( session, 0, sizeof(mbedtls_ssl_session) ); +} + +static int ssl_handshake_init( mbedtls_ssl_context *ssl ) +{ + /* Clear old handshake information if present */ + if( ssl->transform_negotiate ) + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + if( ssl->session_negotiate ) + mbedtls_ssl_session_free( ssl->session_negotiate ); + if( ssl->handshake ) + mbedtls_ssl_handshake_free( ssl ); + + /* + * Either the pointers are now NULL or cleared properly and can be freed. + * Now allocate missing structures. + */ + if( ssl->transform_negotiate == NULL ) + { + ssl->transform_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_transform) ); + } + + if( ssl->session_negotiate == NULL ) + { + ssl->session_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_session) ); + } + + if( ssl->handshake == NULL ) + { + ssl->handshake = mbedtls_calloc( 1, sizeof(mbedtls_ssl_handshake_params) ); + } + + /* All pointers should exist and can be directly freed without issue */ + if( ssl->handshake == NULL || + ssl->transform_negotiate == NULL || + ssl->session_negotiate == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc() of ssl sub-contexts failed" ) ); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + + ssl->handshake = NULL; + ssl->transform_negotiate = NULL; + ssl->session_negotiate = NULL; + + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Initialize structures */ + mbedtls_ssl_session_init( ssl->session_negotiate ); + ssl_transform_init( ssl->transform_negotiate ); + ssl_handshake_params_init( ssl->handshake ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->handshake->alt_transform_out = ssl->transform_out; + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + + ssl_set_timer( ssl, 0 ); + } +#endif + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/* Dummy cookie callbacks for defaults */ +static int ssl_cookie_write_dummy( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) p); + ((void) end); + ((void) cli_id); + ((void) cli_id_len); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} + +static int ssl_cookie_check_dummy( void *ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) cookie); + ((void) cookie_len); + ((void) cli_id); + ((void) cli_id_len); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +/* Once ssl->out_hdr as the address of the beginning of the + * next outgoing record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->out_hdr, + * and the caller has to make sure there's space for this. + */ + +static void ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_ctr = ssl->out_hdr + 3; + ssl->out_len = ssl->out_hdr + 11; + ssl->out_iv = ssl->out_hdr + 13; + } + else +#endif + { + ssl->out_ctr = ssl->out_hdr - 8; + ssl->out_len = ssl->out_hdr + 3; + ssl->out_iv = ssl->out_hdr + 5; + } + + /* Adjust out_msg to make space for explicit IV, if used. */ + if( transform != NULL && + ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->out_msg = ssl->out_iv + transform->ivlen - transform->fixed_ivlen; + } + else + ssl->out_msg = ssl->out_iv; +} + +/* Once ssl->in_hdr as the address of the beginning of the + * next incoming record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->in_hdr, + * and the caller has to make sure there's space for this. + */ + +static void ssl_update_in_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->in_ctr = ssl->in_hdr + 3; + ssl->in_len = ssl->in_hdr + 11; + ssl->in_iv = ssl->in_hdr + 13; + } + else +#endif + { + ssl->in_ctr = ssl->in_hdr - 8; + ssl->in_len = ssl->in_hdr + 3; + ssl->in_iv = ssl->in_hdr + 5; + } + + /* Offset in_msg from in_iv to allow space for explicit IV, if used. */ + if( transform != NULL && + ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->in_msg = ssl->in_iv + transform->ivlen - transform->fixed_ivlen; + } + else + ssl->in_msg = ssl->in_iv; +} + +/* + * Initialize an SSL context + */ +void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) +{ + memset( ssl, 0, sizeof( mbedtls_ssl_context ) ); +} + +/* + * Setup an SSL context + */ + +static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ) +{ + /* Set the incoming and outgoing record pointers. */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + ssl->in_hdr = ssl->in_buf; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ssl->out_hdr = ssl->out_buf + 8; + ssl->in_hdr = ssl->in_buf + 8; + } + + /* Derive other internal pointers. */ + ssl_update_out_pointers( ssl, NULL /* no transform enabled */ ); + ssl_update_in_pointers ( ssl, NULL /* no transform enabled */ ); +} + +int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf ) +{ + int ret; + + ssl->conf = conf; + + /* + * Prepare base structures + */ + + /* Set to NULL in case of an error condition */ + ssl->out_buf = NULL; + + ssl->in_buf = mbedtls_calloc( 1, MBEDTLS_SSL_IN_BUFFER_LEN ); + if( ssl->in_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_IN_BUFFER_LEN) ); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; + } + + ssl->out_buf = mbedtls_calloc( 1, MBEDTLS_SSL_OUT_BUFFER_LEN ); + if( ssl->out_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_OUT_BUFFER_LEN) ); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; + } + + ssl_reset_in_out_pointers( ssl ); + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + goto error; + + return( 0 ); + +error: + mbedtls_free( ssl->in_buf ); + mbedtls_free( ssl->out_buf ); + + ssl->conf = NULL; + + ssl->in_buf = NULL; + ssl->out_buf = NULL; + + ssl->in_hdr = NULL; + ssl->in_ctr = NULL; + ssl->in_len = NULL; + ssl->in_iv = NULL; + ssl->in_msg = NULL; + + ssl->out_hdr = NULL; + ssl->out_ctr = NULL; + ssl->out_len = NULL; + ssl->out_iv = NULL; + ssl->out_msg = NULL; + + return( ret ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + * + * If partial is non-zero, keep data in the input buffer and client ID. + * (Use when a DTLS client reconnects from the same port.) + */ +static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) +{ + int ret; + +#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || \ + !defined(MBEDTLS_SSL_SRV_C) + ((void) partial); +#endif + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + + /* Cancel any possibly running timer */ + ssl_set_timer( ssl, 0 ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; + ssl->renego_records_seen = 0; + + ssl->verify_data_len = 0; + memset( ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); + memset( ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; + + ssl->in_offt = NULL; + ssl_reset_in_out_pointers( ssl ); + + ssl->in_msgtype = 0; + ssl->in_msglen = 0; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + ssl->next_record_offset = 0; + ssl->in_epoch = 0; +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + ssl_dtls_replay_reset( ssl ); +#endif + + ssl->in_hslen = 0; + ssl->nb_zero = 0; + + ssl->keep_current_message = 0; + + ssl->out_msgtype = 0; + ssl->out_msglen = 0; + ssl->out_left = 0; +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + if( ssl->split_done != MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ) + ssl->split_done = 0; +#endif + + memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) ); + + ssl->transform_in = NULL; + ssl->transform_out = NULL; + + ssl->session_in = NULL; + ssl->session_out = NULL; + + memset( ssl->out_buf, 0, MBEDTLS_SSL_OUT_BUFFER_LEN ); + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) + if( partial == 0 ) +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + { + ssl->in_left = 0; + memset( ssl->in_buf, 0, MBEDTLS_SSL_IN_BUFFER_LEN ); + } + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_reset != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_reset()" ) ); + if( ( ret = mbedtls_ssl_hw_record_reset( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_reset", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + ssl->transform = NULL; + } + + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + ssl->session = NULL; + } + +#if defined(MBEDTLS_SSL_ALPN) + ssl->alpn_chosen = NULL; +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) + if( partial == 0 ) +#endif + { + mbedtls_free( ssl->cli_id ); + ssl->cli_id = NULL; + ssl->cli_id_len = 0; + } +#endif + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) +{ + return( ssl_session_reset_int( ssl, 0 ) ); +} + +/* + * SSL set accessors + */ +void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ) +{ + conf->endpoint = endpoint; +} + +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ) +{ + conf->transport = transport; +} + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ) +{ + conf->anti_replay = mode; +} +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ) +{ + conf->badmac_limit = limit; +} +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ) +{ + ssl->disable_datagram_packing = !allow_packing; +} + +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, + uint32_t min, uint32_t max ) +{ + conf->hs_timeout_min = min; + conf->hs_timeout_max = max; +} +#endif + +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ) +{ + conf->authmode = authmode; +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + conf->f_vrfy = f_vrfy; + conf->p_vrfy = p_vrfy; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + conf->f_rng = f_rng; + conf->p_rng = p_rng; +} + +void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg ) +{ + conf->f_dbg = f_dbg; + conf->p_dbg = p_dbg; +} + +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout ) +{ + ssl->p_bio = p_bio; + ssl->f_send = f_send; + ssl->f_recv = f_recv; + ssl->f_recv_timeout = f_recv_timeout; +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu ) +{ + ssl->mtu = mtu; +} +#endif + +void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) +{ + conf->read_timeout = timeout; +} + +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer ) +{ + ssl->p_timer = p_timer; + ssl->f_set_timer = f_set_timer; + ssl->f_get_timer = f_get_timer; + + /* Make sure we start with no timer running */ + ssl_set_timer( ssl, 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, + void *p_cache, + int (*f_get_cache)(void *, mbedtls_ssl_session *), + int (*f_set_cache)(void *, const mbedtls_ssl_session *) ) +{ + conf->p_cache = p_cache; + conf->f_get_cache = f_get_cache; + conf->f_set_cache = f_set_cache; +} +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ) +{ + int ret; + + if( ssl == NULL || + session == NULL || + ssl->session_negotiate == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( ( ret = ssl_session_copy( ssl->session_negotiate, session ) ) != 0 ) + return( ret ); + + ssl->handshake->resume = 1; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, + const int *ciphersuites ) +{ + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = ciphersuites; +} + +void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, + const int *ciphersuites, + int major, int minor ) +{ + if( major != MBEDTLS_SSL_MAJOR_VERSION_3 ) + return; + + if( minor < MBEDTLS_SSL_MINOR_VERSION_0 || minor > MBEDTLS_SSL_MINOR_VERSION_3 ) + return; + + conf->ciphersuite_list[minor] = ciphersuites; +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile ) +{ + conf->cert_profile = profile; +} + +/* Append a new keycert entry to a (possibly empty) list */ +static int ssl_append_key_cert( mbedtls_ssl_key_cert **head, + mbedtls_x509_crt *cert, + mbedtls_pk_context *key ) +{ + mbedtls_ssl_key_cert *new_cert; + + new_cert = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); + if( new_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + new_cert->cert = cert; + new_cert->key = key; + new_cert->next = NULL; + + /* Update head is the list was null, else add to the end */ + if( *head == NULL ) + { + *head = new_cert; + } + else + { + mbedtls_ssl_key_cert *cur = *head; + while( cur->next != NULL ) + cur = cur->next; + cur->next = new_cert; + } + + return( 0 ); +} + +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ) +{ + return( ssl_append_key_cert( &conf->key_cert, own_cert, pk_key ) ); +} + +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ) +{ + conf->ca_chain = ca_chain; + conf->ca_crl = ca_crl; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ) +{ + return( ssl_append_key_cert( &ssl->handshake->sni_key_cert, + own_cert, pk_key ) ); +} + +void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ) +{ + ssl->handshake->sni_ca_chain = ca_chain; + ssl->handshake->sni_ca_crl = ca_crl; +} + +void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, + int authmode ) +{ + ssl->handshake->sni_authmode = authmode; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/* + * Set EC J-PAKE password for current handshake + */ +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ) +{ + mbedtls_ecjpake_role role; + + if( ssl->handshake == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + role = MBEDTLS_ECJPAKE_SERVER; + else + role = MBEDTLS_ECJPAKE_CLIENT; + + return( mbedtls_ecjpake_setup( &ssl->handshake->ecjpake_ctx, + role, + MBEDTLS_MD_SHA256, + MBEDTLS_ECP_DP_SECP256R1, + pw, pw_len ) ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ) +{ + if( psk == NULL || psk_identity == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( psk_len > MBEDTLS_PSK_MAX_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* Identity len will be encoded on two bytes */ + if( ( psk_identity_len >> 16 ) != 0 || + psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( conf->psk != NULL ) + { + mbedtls_platform_zeroize( conf->psk, conf->psk_len ); + + mbedtls_free( conf->psk ); + conf->psk = NULL; + conf->psk_len = 0; + } + if( conf->psk_identity != NULL ) + { + mbedtls_free( conf->psk_identity ); + conf->psk_identity = NULL; + conf->psk_identity_len = 0; + } + + if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL || + ( conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ) ) == NULL ) + { + mbedtls_free( conf->psk ); + mbedtls_free( conf->psk_identity ); + conf->psk = NULL; + conf->psk_identity = NULL; + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + conf->psk_len = psk_len; + conf->psk_identity_len = psk_identity_len; + + memcpy( conf->psk, psk, conf->psk_len ); + memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len ); + + return( 0 ); +} + +int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len ) +{ + if( psk == NULL || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( psk_len > MBEDTLS_PSK_MAX_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ssl->handshake->psk != NULL ) + { + mbedtls_platform_zeroize( ssl->handshake->psk, + ssl->handshake->psk_len ); + mbedtls_free( ssl->handshake->psk ); + ssl->handshake->psk_len = 0; + } + + if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + ssl->handshake->psk_len = psk_len; + memcpy( ssl->handshake->psk, psk, ssl->handshake->psk_len ); + + return( 0 ); +} + +void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_psk ) +{ + conf->f_psk = f_psk; + conf->p_psk = p_psk; +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G ) +{ + int ret; + + if( ( ret = mbedtls_mpi_read_string( &conf->dhm_P, 16, dhm_P ) ) != 0 || + ( ret = mbedtls_mpi_read_string( &conf->dhm_G, 16, dhm_G ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ) +{ + int ret; + + if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} + +int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ) +{ + int ret; + + if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 || + ( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) +/* + * Set the minimum length for Diffie-Hellman parameters + */ +void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, + unsigned int bitlen ) +{ + conf->dhm_min_bitlen = bitlen; +} +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/* + * Set allowed/preferred hashes for handshake signatures + */ +void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, + const int *hashes ) +{ + conf->sig_hashes = hashes; +} +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECP_C) +/* + * Set the allowed elliptic curves + */ +void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curve_list ) +{ + conf->curve_list = curve_list; +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) +{ + /* Initialize to suppress unnecessary compiler warning */ + size_t hostname_len = 0; + + /* Check if new hostname is valid before + * making any change to current one */ + if( hostname != NULL ) + { + hostname_len = strlen( hostname ); + + if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Now it's clear that we will overwrite the old hostname, + * so we can free it safely */ + + if( ssl->hostname != NULL ) + { + mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_free( ssl->hostname ); + } + + /* Passing NULL as hostname shall clear the old one */ + + if( hostname == NULL ) + { + ssl->hostname = NULL; + } + else + { + ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 ); + if( ssl->hostname == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( ssl->hostname, hostname, hostname_len ); + + ssl->hostname[hostname_len] = '\0'; + } + + return( 0 ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, + const unsigned char *, size_t), + void *p_sni ) +{ + conf->f_sni = f_sni; + conf->p_sni = p_sni; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ALPN) +int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ) +{ + size_t cur_len, tot_len; + const char **p; + + /* + * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings + * MUST NOT be truncated." + * We check lengths now rather than later. + */ + tot_len = 0; + for( p = protos; *p != NULL; p++ ) + { + cur_len = strlen( *p ); + tot_len += cur_len; + + if( ( cur_len == 0 ) || + ( cur_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN ) || + ( tot_len > MBEDTLS_SSL_MAX_ALPN_LIST_LEN ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->alpn_list = protos; + + return( 0 ); +} + +const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ) +{ + return( ssl->alpn_chosen ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ) +{ + conf->max_major_ver = major; + conf->max_minor_ver = minor; +} + +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ) +{ + conf->min_major_ver = major; + conf->min_minor_ver = minor; +} + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) +void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ) +{ + conf->fallback = fallback; +} +#endif + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ) +{ + conf->cert_req_ca_list = cert_req_ca_list; +} +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ) +{ + conf->encrypt_then_mac = etm; +} +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ) +{ + conf->extended_ms = ems; +} +#endif + +#if defined(MBEDTLS_ARC4_C) +void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ) +{ + conf->arc4_disabled = arc4; +} +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ) +{ + if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || + ssl_mfl_code_to_length( mfl_code ) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->mfl_code = mfl_code; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ) +{ + conf->trunc_hmac = truncate; +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ) +{ + conf->cbc_record_splitting = split; +} +#endif + +void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ) +{ + conf->allow_legacy_renegotiation = allow_legacy; +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ) +{ + conf->disable_renegotiation = renegotiation; +} + +void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ) +{ + conf->renego_max_records = max_records; +} + +void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ) +{ + memcpy( conf->renego_period, period, 8 ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#if defined(MBEDTLS_SSL_CLI_C) +void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ) +{ + conf->session_tickets = use_tickets; +} +#endif + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket ) +{ + conf->f_ticket_write = f_ticket_write; + conf->f_ticket_parse = f_ticket_parse; + conf->p_ticket = p_ticket; +} +#endif +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ) +{ + conf->f_export_keys = f_export_keys; + conf->p_export_keys = p_export_keys; +} +#endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +void mbedtls_ssl_conf_async_private_cb( + mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *async_config_data ) +{ + conf->f_async_sign_start = f_async_sign; + conf->f_async_decrypt_start = f_async_decrypt; + conf->f_async_resume = f_async_resume; + conf->f_async_cancel = f_async_cancel; + conf->p_async_config_data = async_config_data; +} + +void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ) +{ + return( conf->p_async_config_data ); +} + +void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ) +{ + if( ssl->handshake == NULL ) + return( NULL ); + else + return( ssl->handshake->user_async_ctx ); +} + +void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, + void *ctx ) +{ + if( ssl->handshake != NULL ) + ssl->handshake->user_async_ctx = ctx; +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +/* + * SSL get accessors + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) +{ + return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); +} + +int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ) +{ + /* + * Case A: We're currently holding back + * a message for further processing. + */ + + if( ssl->keep_current_message == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) ); + return( 1 ); + } + + /* + * Case B: Further records are pending in the current datagram. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->in_left > ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) ); + return( 1 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Case C: A handshake message is being processed. + */ + + if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) ); + return( 1 ); + } + + /* + * Case D: An application data message is being processed + */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) ); + return( 1 ); + } + + /* + * In all other cases, the rest of the message can be dropped. + * As in ssl_get_next_record, this needs to be adapted if + * we implement support for multiple alerts in single records. + */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) ); + return( 0 ); +} + +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ) +{ + if( ssl->session != NULL ) + return( ssl->session->verify_result ); + + if( ssl->session_negotiate != NULL ) + return( ssl->session_negotiate->verify_result ); + + return( 0xFFFFFFFF ); +} + +const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return mbedtls_ssl_get_ciphersuite_name( ssl->session->ciphersuite ); +} + +const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + switch( ssl->minor_ver ) + { + case MBEDTLS_SSL_MINOR_VERSION_2: + return( "DTLSv1.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_3: + return( "DTLSv1.2" ); + + default: + return( "unknown (DTLS)" ); + } + } +#endif + + switch( ssl->minor_ver ) + { + case MBEDTLS_SSL_MINOR_VERSION_0: + return( "SSLv3.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_1: + return( "TLSv1.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_2: + return( "TLSv1.1" ); + + case MBEDTLS_SSL_MINOR_VERSION_3: + return( "TLSv1.2" ); + + default: + return( "unknown" ); + } +} + +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) +{ + size_t transform_expansion = 0; + const mbedtls_ssl_transform *transform = ssl->transform_out; + unsigned block_size; + + if( transform == NULL ) + return( (int) mbedtls_ssl_hdr_len( ssl ) ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + + switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) + { + case MBEDTLS_MODE_GCM: + case MBEDTLS_MODE_CCM: + case MBEDTLS_MODE_CHACHAPOLY: + case MBEDTLS_MODE_STREAM: + transform_expansion = transform->minlen; + break; + + case MBEDTLS_MODE_CBC: + + block_size = mbedtls_cipher_get_block_size( + &transform->cipher_ctx_enc ); + + /* Expansion due to the addition of the MAC. */ + transform_expansion += transform->maclen; + + /* Expansion due to the addition of CBC padding; + * Theoretically up to 256 bytes, but we never use + * more than the block size of the underlying cipher. */ + transform_expansion += block_size; + + /* For TLS 1.1 or higher, an explicit IV is added + * after the record header. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + transform_expansion += block_size; +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( (int)( mbedtls_ssl_hdr_len( ssl ) + transform_expansion ) ); +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) +{ + size_t max_len; + + /* + * Assume mfl_code is correct since it was checked when set + */ + max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code ); + + /* Check if a smaller max length was negotiated */ + if( ssl->session_out != NULL && + ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len ) + { + max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code ); + } + + /* During a handshake, use the value being negotiated */ + if( ssl->session_negotiate != NULL && + ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ) < max_len ) + { + max_len = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ); + } + + return( max_len ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl ) +{ + /* Return unlimited mtu for client hello messages to avoid fragmentation. */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ( ssl->state == MBEDTLS_SSL_CLIENT_HELLO || + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) ) + return ( 0 ); + + if( ssl->handshake == NULL || ssl->handshake->mtu == 0 ) + return( ssl->mtu ); + + if( ssl->mtu == 0 ) + return( ssl->handshake->mtu ); + + return( ssl->mtu < ssl->handshake->mtu ? + ssl->mtu : ssl->handshake->mtu ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ) +{ + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) + (void) ssl; +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl_get_current_mtu( ssl ) != 0 ) + { + const size_t mtu = ssl_get_current_mtu( ssl ); + const int ret = mbedtls_ssl_get_record_expansion( ssl ); + const size_t overhead = (size_t) ret; + + if( ret < 0 ) + return( ret ); + + if( mtu <= overhead ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "MTU too low for record expansion" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + if( max_len > mtu - overhead ) + max_len = mtu - overhead; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) + ((void) ssl); +#endif + + return( (int) max_len ); +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return( ssl->session->peer_cert ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *dst ) +{ + if( ssl == NULL || + dst == NULL || + ssl->session == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ssl_session_copy( dst, ssl->session ) ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +/* + * Perform a single step of the SSL handshake + */ +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ret = mbedtls_ssl_handshake_client_step( ssl ); +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ret = mbedtls_ssl_handshake_server_step( ssl ); +#endif + + return( ret ); +} + +/* + * Perform the SSL handshake + */ +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); + + while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake_step( ssl ); + + if( ret != 0 ) + break; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); + + return( ret ); +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +#if defined(MBEDTLS_SSL_SRV_C) +/* + * Write HelloRequest to request renegotiation on server + */ +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SRV_C */ + +/* + * Actually renegotiate current connection, triggered by either: + * - any side: calling mbedtls_ssl_renegotiate(), + * - client: receiving a HelloRequest during mbedtls_ssl_read(), + * - server: receiving any handshake message on server during mbedtls_ssl_read() after + * the initial handshake is completed. + * If the handshake doesn't complete due to waiting for I/O, it will continue + * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. + */ +static int ssl_start_renegotiation( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and + * the ServerHello will have message_seq = 1" */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->handshake->out_msg_seq = 1; + else + ssl->handshake->in_msg_seq = 1; + } +#endif + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; + + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); + + return( 0 ); +} + +/* + * Renegotiate current connection on client, + * or request renegotiation on server + */ +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_SRV_C) + /* On server, just send the request */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + + /* Did we already try/start sending HelloRequest? */ + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + return( ssl_write_hello_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) + /* + * On client, either start the renegotiation process or, + * if already in progress, continue the handshake + */ + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); + return( ret ); + } + } + else + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_CLI_C */ + + return( ret ); +} + +/* + * Check record counters and renegotiate if they're above the limit. + */ +static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) +{ + size_t ep_len = ssl_ep_len( ssl ); + int in_ctr_cmp; + int out_ctr_cmp; + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || + ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) + { + return( 0 ); + } + + in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + + if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) + { + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) ); + return( mbedtls_ssl_renegotiate( ssl ) ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Receive application data decrypted from the SSL layer + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) +{ + int ret; + size_t n; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + if( ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + return( ret ); + } + } +#endif + + /* + * Check if renegotiation is necessary and/or handshake is + * in process. If yes, perform/continue, and fall through + * if an unexpected packet is received while the client + * is waiting for the ServerHello. + * + * (There is no equivalent to the last condition on + * the server-side as it is not treated as within + * a handshake while waiting for the ClientHello + * after a renegotiation request.) + */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ret = ssl_check_ctr_renegotiate( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + + /* Loop as long as no application data record is available */ + while( ssl->in_offt == NULL ) + { + /* Start timer if not already running */ + if( ssl->f_get_timer != NULL && + ssl->f_get_timer( ssl->p_timer ) == -1 ) + { + ssl_set_timer( ssl, ssl->conf->read_timeout ); + } + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msglen == 0 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* + * OpenSSL sends empty messages to randomize the IV + */ + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); + + /* + * - For client-side, expect SERVER_HELLO_REQUEST. + * - For server-side, expect CLIENT_HELLO. + * - Fail (TLS) or silently drop record (DTLS) in other cases. + */ + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + continue; + } +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif /* MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + continue; + } +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + /* Determine whether renegotiation attempt should be accepted */ + if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || + ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) ) + { + /* + * Accept renegotiation request + */ + + /* DTLS clients need to know renego is server-initiated */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + } +#endif + ret = ssl_start_renegotiation( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + /* + * Refuse renegotiation + */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* SSLv3 does not have a "no_renegotiation" warning, so + we send a fatal alert and abort the connection. */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) + { + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + + /* At this point, we don't know whether the renegotiation has been + * completed or not. The cases to consider are the following: + * 1) The renegotiation is complete. In this case, no new record + * has been read yet. + * 2) The renegotiation is incomplete because the client received + * an application data record while awaiting the ServerHello. + * 3) The renegotiation is incomplete because the client received + * a non-handshake, non-application data message while awaiting + * the ServerHello. + * In each of these case, looping will be the proper action: + * - For 1), the next iteration will read a new record and check + * if it's application data. + * - For 2), the loop condition isn't satisfied as application data + * is present, hence continue is the same as break + * - For 3), the loop condition is satisfied and read_record + * will re-deliver the message that was held back by the client + * when expecting the ServerHello. + */ + continue; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ssl->conf->renego_max_records >= 0 ) + { + if( ++ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " + "but not honored by client" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + } + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) ); + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->in_offt = ssl->in_msg; + + /* We're going to return something now, cancel timer, + * except if handshake (renegotiation) is in progress */ + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + ssl_set_timer( ssl, 0 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* If we requested renego but received AppData, resend HelloRequest. + * Do it now, after setting in_offt, to avoid taking this branch + * again if ssl_write_hello_request() returns WANT_WRITE */ +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + } + + n = ( len < ssl->in_msglen ) + ? len : ssl->in_msglen; + + memcpy( buf, ssl->in_offt, n ); + ssl->in_msglen -= n; + + /* Zeroising the plaintext buffer to erase unused application data + from the memory. */ + mbedtls_platform_zeroize( ssl->in_offt, n ); + + if( ssl->in_msglen == 0 ) + { + /* all bytes consumed */ + ssl->in_offt = NULL; + ssl->keep_current_message = 0; + } + else + { + /* more data available */ + ssl->in_offt += n; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); + + return( (int) n ); +} + +/* + * Send application data to be encrypted by the SSL layer, taking care of max + * fragment length and buffer size. + * + * According to RFC 5246 Section 6.2.1: + * + * Zero-length fragments of Application data MAY be sent as they are + * potentially useful as a traffic analysis countermeasure. + * + * Therefore, it is possible that the input message length is 0 and the + * corresponding return code is 0 on success. + */ +static int ssl_write_real( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret = mbedtls_ssl_get_max_out_record_payload( ssl ); + const size_t max_len = (size_t) ret; + + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret ); + return( ret ); + } + + if( len > max_len ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) " + "maximum fragment length: %d > %d", + len, max_len ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + else +#endif + len = max_len; + } + + if( ssl->out_left != 0 ) + { + /* + * The user has previously tried to send the data and + * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially + * written. In this case, we expect the high-level write function + * (e.g. mbedtls_ssl_write()) to be called with the same parameters + */ + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + } + else + { + /* + * The user is trying to send a message the first time, so we need to + * copy the data into the internal buffers and setup the data structure + * to keep track of partial writes + */ + ssl->out_msglen = len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; + memcpy( ssl->out_msg, buf, len ); + + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + return( (int) len ); +} + +/* + * Write application data, doing 1/n-1 splitting if necessary. + * + * With non-blocking I/O, ssl_write_real() may return WANT_WRITE, + * then the caller will call us again with the same arguments, so + * remember whether we already did the split or not. + */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +static int ssl_write_split( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret; + + if( ssl->conf->cbc_record_splitting == + MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED || + len <= 1 || + ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 || + mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ) + != MBEDTLS_MODE_CBC ) + { + return( ssl_write_real( ssl, buf, len ) ); + } + + if( ssl->split_done == 0 ) + { + if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 ) + return( ret ); + ssl->split_done = 1; + } + + if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 ) + return( ret ); + ssl->split_done = 0; + + return( ret + 1 ); +} +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +/* + * Write application data (public-facing wrapper) + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + ret = ssl_write_split( ssl, buf, len ); +#else + ret = ssl_write_real( ssl, buf, len ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) ); + + return( ret ); +} + +/* + * Notify the peer that the connection is being closed + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); + + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); + + return( 0 ); +} + +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ) +{ + if( transform == NULL ) + return; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + deflateEnd( &transform->ctx_deflate ); + inflateEnd( &transform->ctx_inflate ); +#endif + + mbedtls_cipher_free( &transform->cipher_ctx_enc ); + mbedtls_cipher_free( &transform->cipher_ctx_dec ); + + mbedtls_md_free( &transform->md_ctx_enc ); + mbedtls_md_free( &transform->md_ctx_dec ); + + mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) +{ + mbedtls_ssl_key_cert *cur = key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + mbedtls_free( cur ); + cur = next; + } +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +static void ssl_buffering_free( mbedtls_ssl_context *ssl ) +{ + unsigned offset; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( hs == NULL ) + return; + + ssl_free_buffered_record( ssl ); + + for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) + ssl_buffering_free_slot( ssl, offset ); +} + +static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, + uint8_t slot ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot]; + + if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS ) + return; + + if( hs_buf->is_valid == 1 ) + { + hs->buffering.total_bytes_buffered -= hs_buf->data_len; + mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len ); + mbedtls_free( hs_buf->data ); + memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); + } +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + if( handshake == NULL ) + return; + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0 ) + { + ssl->conf->f_async_cancel( ssl ); + handshake->async_in_progress = 0; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_free( &handshake->fin_md5 ); + mbedtls_sha1_free( &handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_free( &handshake->fin_sha256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_free( &handshake->fin_sha512 ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_free( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_free( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_free( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + mbedtls_free( handshake->ecjpake_cache ); + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + /* explicit void pointer cast for buggy MS compiler */ + mbedtls_free( (void *) handshake->curves ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( handshake->psk != NULL ) + { + mbedtls_platform_zeroize( handshake->psk, handshake->psk_len ); + mbedtls_free( handshake->psk ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /* + * Free only the linked list wrapper, not the keys themselves + * since the belong to the SNI callback + */ + if( handshake->sni_key_cert != NULL ) + { + mbedtls_ssl_key_cert *cur = handshake->sni_key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + mbedtls_free( cur ); + cur = next; + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + mbedtls_free( handshake->verify_cookie ); + ssl_flight_free( handshake->flight ); + ssl_buffering_free( ssl ); +#endif + + mbedtls_platform_zeroize( handshake, + sizeof( mbedtls_ssl_handshake_params ) ); +} + +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) +{ + if( session == NULL ) + return; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( session->peer_cert != NULL ) + { + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + } +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + mbedtls_free( session->ticket ); +#endif + + mbedtls_platform_zeroize( session, sizeof( mbedtls_ssl_session ) ); +} + +/* + * Free an SSL context + */ +void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> free" ) ); + + if( ssl->out_buf != NULL ) + { + mbedtls_platform_zeroize( ssl->out_buf, MBEDTLS_SSL_OUT_BUFFER_LEN ); + mbedtls_free( ssl->out_buf ); + } + + if( ssl->in_buf != NULL ) + { + mbedtls_platform_zeroize( ssl->in_buf, MBEDTLS_SSL_IN_BUFFER_LEN ); + mbedtls_free( ssl->in_buf ); + } + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->compress_buf != NULL ) + { + mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); + mbedtls_free( ssl->compress_buf ); + } +#endif + + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + } + + if( ssl->handshake ) + { + mbedtls_ssl_handshake_free( ssl ); + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + mbedtls_ssl_session_free( ssl->session_negotiate ); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + } + + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( ssl->hostname != NULL ) + { + mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_free( ssl->hostname ); + } +#endif + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_finish != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_finish()" ) ); + mbedtls_ssl_hw_record_finish( ssl ); + } +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + mbedtls_free( ssl->cli_id ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) ); + + /* Actually clear after last debug message */ + mbedtls_platform_zeroize( ssl, sizeof( mbedtls_ssl_context ) ); +} + +/* + * Initialze mbedtls_ssl_config + */ +void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ) +{ + memset( conf, 0, sizeof( mbedtls_ssl_config ) ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +static int ssl_preset_default_hashes[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, + MBEDTLS_MD_SHA384, +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif +#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE) + MBEDTLS_MD_SHA1, +#endif + MBEDTLS_MD_NONE +}; +#endif + +static int ssl_preset_suiteb_ciphersuites[] = { + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + 0 +}; + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +static int ssl_preset_suiteb_hashes[] = { + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA384, + MBEDTLS_MD_NONE +}; +#endif + +#if defined(MBEDTLS_ECP_C) +static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = { +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + MBEDTLS_ECP_DP_SECP256R1, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + MBEDTLS_ECP_DP_SECP384R1, +#endif + MBEDTLS_ECP_DP_NONE +}; +#endif + +/* + * Load default in mbedtls_ssl_config + */ +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, + int endpoint, int transport, int preset ) +{ +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + int ret; +#endif + + /* Use the functions here so that they are covered in tests, + * but otherwise access member directly for efficiency */ + mbedtls_ssl_conf_endpoint( conf, endpoint ); + mbedtls_ssl_conf_transport( conf, transport ); + + /* + * Things that are common to all presets + */ +#if defined(MBEDTLS_SSL_CLI_C) + if( endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED; +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED; +#endif + } +#endif + +#if defined(MBEDTLS_ARC4_C) + conf->arc4_disabled = MBEDTLS_SSL_ARC4_DISABLED; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + conf->cbc_record_splitting = MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + conf->f_cookie_write = ssl_cookie_write_dummy; + conf->f_cookie_check = ssl_cookie_check_dummy; +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; + conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; + memset( conf->renego_period, 0x00, 2 ); + memset( conf->renego_period + 2, 0xFF, 6 ); +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + if( endpoint == MBEDTLS_SSL_IS_SERVER ) + { + const unsigned char dhm_p[] = + MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN; + const unsigned char dhm_g[] = + MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN; + + if ( ( ret = mbedtls_ssl_conf_dh_param_bin( conf, + dhm_p, sizeof( dhm_p ), + dhm_g, sizeof( dhm_g ) ) ) != 0 ) + { + return( ret ); + } + } +#endif + + /* + * Preset-specific defaults + */ + switch( preset ) + { + /* + * NSA Suite B + */ + case MBEDTLS_SSL_PRESET_SUITEB: + conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */ + conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; + conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; + + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = + ssl_preset_suiteb_ciphersuites; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + conf->sig_hashes = ssl_preset_suiteb_hashes; +#endif + +#if defined(MBEDTLS_ECP_C) + conf->curve_list = ssl_preset_suiteb_curves; +#endif + break; + + /* + * Default + */ + default: + conf->min_major_ver = ( MBEDTLS_SSL_MIN_MAJOR_VERSION > + MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION ) ? + MBEDTLS_SSL_MIN_MAJOR_VERSION : + MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION; + conf->min_minor_ver = ( MBEDTLS_SSL_MIN_MINOR_VERSION > + MBEDTLS_SSL_MIN_VALID_MINOR_VERSION ) ? + MBEDTLS_SSL_MIN_MINOR_VERSION : + MBEDTLS_SSL_MIN_VALID_MINOR_VERSION; + conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; + conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_2; +#endif + + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = + mbedtls_ssl_list_ciphersuites(); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_default; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + conf->sig_hashes = ssl_preset_default_hashes; +#endif + +#if defined(MBEDTLS_ECP_C) + conf->curve_list = mbedtls_ecp_grp_id_list(); +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + conf->dhm_min_bitlen = 1024; +#endif + } + + return( 0 ); +} + +/* + * Free mbedtls_ssl_config + */ +void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) +{ +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( conf->psk != NULL ) + { + mbedtls_platform_zeroize( conf->psk, conf->psk_len ); + mbedtls_free( conf->psk ); + conf->psk = NULL; + conf->psk_len = 0; + } + + if( conf->psk_identity != NULL ) + { + mbedtls_platform_zeroize( conf->psk_identity, conf->psk_identity_len ); + mbedtls_free( conf->psk_identity ); + conf->psk_identity = NULL; + conf->psk_identity_len = 0; + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + ssl_key_cert_free( conf->key_cert ); +#endif + + mbedtls_platform_zeroize( conf, sizeof( mbedtls_ssl_config ) ); +} + +#if defined(MBEDTLS_PK_C) && \ + ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) ) +/* + * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX + */ +unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ) +{ +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_RSA ) ) + return( MBEDTLS_SSL_SIG_RSA ); +#endif +#if defined(MBEDTLS_ECDSA_C) + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECDSA ) ) + return( MBEDTLS_SSL_SIG_ECDSA ); +#endif + return( MBEDTLS_SSL_SIG_ANON ); +} + +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ) +{ + switch( type ) { + case MBEDTLS_PK_RSA: + return( MBEDTLS_SSL_SIG_RSA ); + case MBEDTLS_PK_ECDSA: + case MBEDTLS_PK_ECKEY: + return( MBEDTLS_SSL_SIG_ECDSA ); + default: + return( MBEDTLS_SSL_SIG_ANON ); + } +} + +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) +{ + switch( sig ) + { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_SSL_SIG_RSA: + return( MBEDTLS_PK_RSA ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_SSL_SIG_ECDSA: + return( MBEDTLS_PK_ECDSA ); +#endif + default: + return( MBEDTLS_PK_NONE ); + } +} +#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ) +{ + switch( sig_alg ) + { + case MBEDTLS_PK_RSA: + return( set->rsa ); + case MBEDTLS_PK_ECDSA: + return( set->ecdsa ); + default: + return( MBEDTLS_MD_NONE ); + } +} + +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ) +{ + switch( sig_alg ) + { + case MBEDTLS_PK_RSA: + if( set->rsa == MBEDTLS_MD_NONE ) + set->rsa = md_alg; + break; + + case MBEDTLS_PK_ECDSA: + if( set->ecdsa == MBEDTLS_MD_NONE ) + set->ecdsa = md_alg; + break; + + default: + break; + } +} + +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ) +{ + set->rsa = md_alg; + set->ecdsa = md_alg; +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +/* + * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX + */ +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ) +{ + switch( hash ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_SSL_HASH_MD5: + return( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_SSL_HASH_SHA1: + return( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_HASH_SHA224: + return( MBEDTLS_MD_SHA224 ); + case MBEDTLS_SSL_HASH_SHA256: + return( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_SSL_HASH_SHA384: + return( MBEDTLS_MD_SHA384 ); + case MBEDTLS_SSL_HASH_SHA512: + return( MBEDTLS_MD_SHA512 ); +#endif + default: + return( MBEDTLS_MD_NONE ); + } +} + +/* + * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX + */ +unsigned char mbedtls_ssl_hash_from_md_alg( int md ) +{ + switch( md ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( MBEDTLS_SSL_HASH_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( MBEDTLS_SSL_HASH_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( MBEDTLS_SSL_HASH_SHA224 ); + case MBEDTLS_MD_SHA256: + return( MBEDTLS_SSL_HASH_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + return( MBEDTLS_SSL_HASH_SHA384 ); + case MBEDTLS_MD_SHA512: + return( MBEDTLS_SSL_HASH_SHA512 ); +#endif + default: + return( MBEDTLS_SSL_HASH_NONE ); + } +} + +#if defined(MBEDTLS_ECP_C) +/* + * Check if a curve proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ) +{ + const mbedtls_ecp_group_id *gid; + + if( ssl->conf->curve_list == NULL ) + return( -1 ); + + for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) + if( *gid == grp_id ) + return( 0 ); + + return( -1 ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/* + * Check if a hash proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md ) +{ + const int *cur; + + if( ssl->conf->sig_hashes == NULL ) + return( -1 ); + + for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) + if( *cur == (int) md ) + return( 0 ); + + return( -1 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags ) +{ + int ret = 0; +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + int usage = 0; +#endif +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + const char *ext_oid; + size_t ext_len; +#endif + +#if !defined(MBEDTLS_X509_CHECK_KEY_USAGE) && \ + !defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + ((void) cert); + ((void) cert_endpoint); + ((void) flags); +#endif + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) + { + /* Server part of the key exchange */ + switch( ciphersuite->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT; + break; + + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + break; + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + usage = MBEDTLS_X509_KU_KEY_AGREEMENT; + break; + + /* Don't use default: we want warnings when adding new values */ + case MBEDTLS_KEY_EXCHANGE_NONE: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + usage = 0; + } + } + else + { + /* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */ + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + } + + if( mbedtls_x509_crt_check_key_usage( cert, usage ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE; + ret = -1; + } +#else + ((void) ciphersuite); +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) + { + ext_oid = MBEDTLS_OID_SERVER_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_SERVER_AUTH ); + } + else + { + ext_oid = MBEDTLS_OID_CLIENT_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_CLIENT_AUTH ); + } + + if( mbedtls_x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; + ret = -1; + } +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + + return( ret ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Convert version numbers to/from wire format + * and, for DTLS, to/from TLS equivalent. + * + * For TLS this is the identity. + * For DTLS, use 1's complement (v -> 255 - v, and then map as follows: + * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1) + * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) + */ +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( minor == MBEDTLS_SSL_MINOR_VERSION_2 ) + --minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + + ver[0] = (unsigned char)( 255 - ( major - 2 ) ); + ver[1] = (unsigned char)( 255 - ( minor - 1 ) ); + } + else +#else + ((void) transport); +#endif + { + ver[0] = (unsigned char) major; + ver[1] = (unsigned char) minor; + } +} + +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + *major = 255 - ver[0] + 2; + *minor = 255 - ver[1] + 1; + + if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 ) + ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + } + else +#else + ((void) transport); +#endif + { + *major = ver[0]; + *minor = ver[1]; + } +} + +int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; + + switch( md ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_SSL_HASH_MD5: + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_SSL_HASH_SHA1: + ssl->handshake->calc_verify = ssl_calc_verify_tls; + break; +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_SSL_HASH_SHA384: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_HASH_SHA256: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; + break; +#endif + default: + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; + } + + return 0; +#else /* !MBEDTLS_SSL_PROTO_TLS1_2 */ + (void) ssl; + (void) md; + + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len ) +{ + int ret = 0; + mbedtls_md5_context mbedtls_md5; + mbedtls_sha1_context mbedtls_sha1; + + mbedtls_md5_init( &mbedtls_md5 ); + mbedtls_sha1_init( &mbedtls_sha1 ); + + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(ClientHello.random + ServerHello.random + * + ServerParams); + * sha_hash + * SHA(ClientHello.random + ServerHello.random + * + ServerParams); + */ + if( ( ret = mbedtls_md5_starts_ret( &mbedtls_md5 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_starts_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, + ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, data, data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_finish_ret( &mbedtls_md5, output ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_finish_ret", ret ); + goto exit; + } + + if( ( ret = mbedtls_sha1_starts_ret( &mbedtls_sha1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_starts_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, + ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, data, + data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_finish_ret( &mbedtls_sha1, + output + 16 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_finish_ret", ret ); + goto exit; + } + +exit: + mbedtls_md5_free( &mbedtls_md5 ); + mbedtls_sha1_free( &mbedtls_sha1 ); + + if( ret != 0 ) + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( ret ); + +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ) +{ + int ret = 0; + mbedtls_md_context_t ctx; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + *hashlen = mbedtls_md_get_size( md_info ); + + mbedtls_md_init( &ctx ); + + /* + * digitally-signed struct { + * opaque client_random[32]; + * opaque server_random[32]; + * ServerDHParams params; + * }; + */ + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + goto exit; + } + if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_starts", ret ); + goto exit; + } + if( ( ret = mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); + goto exit; + } + if( ( ret = mbedtls_md_update( &ctx, data, data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); + goto exit; + } + if( ( ret = mbedtls_md_finish( &ctx, hash ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret ); + goto exit; + } + +exit: + mbedtls_md_free( &ctx ); + + if( ret != 0 ) + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/external/mbedtls/library/threading.c b/external/mbedtls/library/threading.c new file mode 100644 index 0000000..0dc5488 --- /dev/null +++ b/external/mbedtls/library/threading.c @@ -0,0 +1,218 @@ +/* + * Threading abstraction layer + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_THREADING_C) + +#include "mbedtls/threading.h" + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) + +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ + +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define THREADING_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */ + +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + +#if defined(MBEDTLS_THREADING_PTHREAD) +static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return; + + /* A nonzero value of is_valid indicates a successfully initialized + * mutex. This is a workaround for not being able to return an error + * code for this function. The lock/unlock functions return an error + * if is_valid is nonzero. The Mbed TLS unit test code uses this field + * to distinguish more states of the mutex; see helpers.function for + * details. */ + mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0; +} + +static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || !mutex->is_valid ) + return; + + (void) pthread_mutex_destroy( &mutex->mutex ); + mutex->is_valid = 0; +} + +static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_lock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +static int threading_mutex_unlock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_unlock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_init_pthread; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_free_pthread; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_pthread; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread; + +/* + * With phtreads we can statically initialize mutexes + */ +#define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 } + +#endif /* MBEDTLS_THREADING_PTHREAD */ + +#if defined(MBEDTLS_THREADING_ALT) +static int threading_mutex_fail( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); +} +static void threading_mutex_dummy( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return; +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; + +/* + * Set functions pointers and initialize global mutexes + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ) +{ + mbedtls_mutex_init = mutex_init; + mbedtls_mutex_free = mutex_free; + mbedtls_mutex_lock = mutex_lock; + mbedtls_mutex_unlock = mutex_unlock; + +#if defined(MBEDTLS_FS_IO) + mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); +#endif +#if defined(THREADING_USE_GMTIME) + mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); +#endif +} + +/* + * Free global mutexes + */ +void mbedtls_threading_free_alt( void ) +{ +#if defined(MBEDTLS_FS_IO) + mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); +#endif +#if defined(THREADING_USE_GMTIME) + mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); +#endif +} +#endif /* MBEDTLS_THREADING_ALT */ + +/* + * Define global mutexes + */ +#ifndef MUTEX_INIT +#define MUTEX_INIT +#endif +#if defined(MBEDTLS_FS_IO) +mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; +#endif +#if defined(THREADING_USE_GMTIME) +mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; +#endif + +#endif /* MBEDTLS_THREADING_C */ diff --git a/external/mbedtls/library/timing.c b/external/mbedtls/library/timing.c new file mode 100644 index 0000000..50a2216 --- /dev/null +++ b/external/mbedtls/library/timing.c @@ -0,0 +1,561 @@ +/* + * Portable interface to the CPU cycle counter + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if defined(MBEDTLS_TIMING_C) + +#include "mbedtls/timing.h" + +#if !defined(MBEDTLS_TIMING_ALT) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) +#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h" +#endif + +#ifndef asm +#define asm __asm +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#include +#include + +struct _hr_time +{ + LARGE_INTEGER start; +}; + +#else + +#include +#include +#include +#include +#include + +struct _hr_time +{ + struct timeval start; +}; + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tsc; + __asm rdtsc + __asm mov [tsc], eax + return( tsc ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */ + +/* some versions of mingw-64 have 32-bit longs even on x84_64 */ +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__i386__) || ( \ + ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __i386__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo | ( hi << 32 ) ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && ( __amd64__ || __x86_64__ ) */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tbl, tbu0, tbu1; + + do + { + asm volatile( "mftbu %0" : "=r" (tbu0) ); + asm volatile( "mftb %0" : "=r" (tbl ) ); + asm volatile( "mftbu %0" : "=r" (tbu1) ); + } + while( tbu0 != tbu1 ); + + return( tbl ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && ( __powerpc__ || __ppc__ ) */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc64__) + +#if defined(__OpenBSD__) +#warning OpenBSD does not allow access to tick register using software version instead +#else +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tick; + asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) ); + return( tick ); +} +#endif /* __OpenBSD__ */ +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __sparc64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tick; + asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" ); + asm volatile( "mov %%g1, %0" : "=r" (tick) ); + return( tick ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __sparc__ && !__sparc64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__alpha__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long cc; + asm volatile( "rpcc %0" : "=r" (cc) ); + return( cc & 0xFFFFFFFF ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __alpha__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__ia64__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long itc; + asm volatile( "mov %0 = ar.itc" : "=r" (itc) ); + return( itc ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __ia64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \ + !defined(EFIX64) && !defined(EFI32) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + LARGE_INTEGER offset; + + QueryPerformanceCounter( &offset ); + + return( (unsigned long)( offset.QuadPart ) ); +} +#endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */ + +#if !defined(HAVE_HARDCLOCK) + +#define HAVE_HARDCLOCK + +static int hardclock_init = 0; +static struct timeval tv_init; + +unsigned long mbedtls_timing_hardclock( void ) +{ + struct timeval tv_cur; + + if( hardclock_init == 0 ) + { + gettimeofday( &tv_init, NULL ); + hardclock_init = 1; + } + + gettimeofday( &tv_cur, NULL ); + return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 + + ( tv_cur.tv_usec - tv_init.tv_usec ) ); +} +#endif /* !HAVE_HARDCLOCK */ + +volatile int mbedtls_timing_alarmed = 0; + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + QueryPerformanceCounter( &t->start ); + return( 0 ); + } + else + { + unsigned long delta; + LARGE_INTEGER now, hfreq; + QueryPerformanceCounter( &now ); + QueryPerformanceFrequency( &hfreq ); + delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul + / hfreq.QuadPart ); + return( delta ); + } +} + +/* It's OK to use a global because alarm() is supposed to be global anyway */ +static DWORD alarmMs; + +static void TimerProc( void *TimerContext ) +{ + (void) TimerContext; + Sleep( alarmMs ); + mbedtls_timing_alarmed = 1; + /* _endthread will be called implicitly on return + * That ensures execution of thread funcition's epilogue */ +} + +void mbedtls_set_alarm( int seconds ) +{ + if( seconds == 0 ) + { + /* No need to create a thread for this simple case. + * Also, this shorcut is more reliable at least on MinGW32 */ + mbedtls_timing_alarmed = 1; + return; + } + + mbedtls_timing_alarmed = 0; + alarmMs = seconds * 1000; + (void) _beginthread( TimerProc, 0, NULL ); +} + +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + gettimeofday( &t->start, NULL ); + return( 0 ); + } + else + { + unsigned long delta; + struct timeval now; + gettimeofday( &now, NULL ); + delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul + + ( now.tv_usec - t->start.tv_usec ) / 1000; + return( delta ); + } +} + +static void sighandler( int signum ) +{ + mbedtls_timing_alarmed = 1; + signal( signum, sighandler ); +} + +void mbedtls_set_alarm( int seconds ) +{ + mbedtls_timing_alarmed = 0; + signal( SIGALRM, sighandler ); + alarm( seconds ); + if( seconds == 0 ) + { + /* alarm(0) cancelled any previous pending alarm, but the + handler won't fire, so raise the flag straight away. */ + mbedtls_timing_alarmed = 1; + } +} + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Set delays to watch + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + + ctx->int_ms = int_ms; + ctx->fin_ms = fin_ms; + + if( fin_ms != 0 ) + (void) mbedtls_timing_get_timer( &ctx->timer, 1 ); +} + +/* + * Get number of delays expired + */ +int mbedtls_timing_get_delay( void *data ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + unsigned long elapsed_ms; + + if( ctx->fin_ms == 0 ) + return( -1 ); + + elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 ); + + if( elapsed_ms >= ctx->fin_ms ) + return( 2 ); + + if( elapsed_ms >= ctx->int_ms ) + return( 1 ); + + return( 0 ); +} + +#endif /* !MBEDTLS_TIMING_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Busy-waits for the given number of milliseconds. + * Used for testing mbedtls_timing_hardclock. + */ +static void busy_msleep( unsigned long msec ) +{ + struct mbedtls_timing_hr_time hires; + unsigned long i = 0; /* for busy-waiting */ + volatile unsigned long j; /* to prevent optimisation */ + + (void) mbedtls_timing_get_timer( &hires, 1 ); + + while( mbedtls_timing_get_timer( &hires, 0 ) < msec ) + i++; + + j = i; + (void) j; +} + +#define FAIL do \ + { \ + if( verbose != 0 ) \ + { \ + mbedtls_printf( "failed at line %d\n", __LINE__ ); \ + mbedtls_printf( " cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \ + cycles, ratio, millisecs, secs, hardfail, \ + (unsigned long) a, (unsigned long) b ); \ + mbedtls_printf( " elapsed(hires)=%lu elapsed(ctx)=%lu status(ctx)=%d\n", \ + mbedtls_timing_get_timer( &hires, 0 ), \ + mbedtls_timing_get_timer( &ctx.timer, 0 ), \ + mbedtls_timing_get_delay( &ctx ) ); \ + } \ + return( 1 ); \ + } while( 0 ) + +/* + * Checkup routine + * + * Warning: this is work in progress, some tests may not be reliable enough + * yet! False positives may happen. + */ +int mbedtls_timing_self_test( int verbose ) +{ + unsigned long cycles = 0, ratio = 0; + unsigned long millisecs = 0, secs = 0; + int hardfail = 0; + struct mbedtls_timing_hr_time hires; + uint32_t a = 0, b = 0; + mbedtls_timing_delay_context ctx; + + if( verbose != 0 ) + mbedtls_printf( " TIMING tests note: will take some time!\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " ); + + { + secs = 1; + + (void) mbedtls_timing_get_timer( &hires, 1 ); + + mbedtls_set_alarm( (int) secs ); + while( !mbedtls_timing_alarmed ) + ; + + millisecs = mbedtls_timing_get_timer( &hires, 0 ); + + /* For some reason on Windows it looks like alarm has an extra delay + * (maybe related to creating a new thread). Allow some room here. */ + if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 ) + FAIL; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #2 (set/get_delay ): " ); + + { + a = 800; + b = 400; + mbedtls_timing_set_delay( &ctx, a, a + b ); /* T = 0 */ + + busy_msleep( a - a / 4 ); /* T = a - a/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 0 ) + FAIL; + + busy_msleep( a / 4 + b / 4 ); /* T = a + b/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 1 ) + FAIL; + + busy_msleep( b ); /* T = a + b + b/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 2 ) + FAIL; + } + + mbedtls_timing_set_delay( &ctx, 0, 0 ); + busy_msleep( 200 ); + if( mbedtls_timing_get_delay( &ctx ) != -1 ) + FAIL; + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #3 (hardclock / get_timer): " ); + + /* + * Allow one failure for possible counter wrapping. + * On a 4Ghz 32-bit machine the cycle counter wraps about once per second; + * since the whole test is about 10ms, it shouldn't happen twice in a row. + */ + +hard_test: + if( hardfail > 1 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (ignored)\n" ); + + goto hard_test_done; + } + + /* Get a reference ratio cycles/ms */ + millisecs = 1; + cycles = mbedtls_timing_hardclock(); + busy_msleep( millisecs ); + cycles = mbedtls_timing_hardclock() - cycles; + ratio = cycles / millisecs; + + /* Check that the ratio is mostly constant */ + for( millisecs = 2; millisecs <= 4; millisecs++ ) + { + cycles = mbedtls_timing_hardclock(); + busy_msleep( millisecs ); + cycles = mbedtls_timing_hardclock() - cycles; + + /* Allow variation up to 20% */ + if( cycles / millisecs < ratio - ratio / 5 || + cycles / millisecs > ratio + ratio / 5 ) + { + hardfail++; + goto hard_test; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +hard_test_done: + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_TIMING_C */ diff --git a/external/mbedtls/library/version.c b/external/mbedtls/library/version.c new file mode 100644 index 0000000..5733288 --- /dev/null +++ b/external/mbedtls/library/version.c @@ -0,0 +1,75 @@ +/* + * Version information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_VERSION_C) + +#include "mbedtls/version.h" +#include + +unsigned int mbedtls_version_get_number( void ) +{ + return( MBEDTLS_VERSION_NUMBER ); +} + +void mbedtls_version_get_string( char *string ) +{ + memcpy( string, MBEDTLS_VERSION_STRING, + sizeof( MBEDTLS_VERSION_STRING ) ); +} + +void mbedtls_version_get_string_full( char *string ) +{ + memcpy( string, MBEDTLS_VERSION_STRING_FULL, + sizeof( MBEDTLS_VERSION_STRING_FULL ) ); +} + +#endif /* MBEDTLS_VERSION_C */ diff --git a/external/mbedtls/library/version_features.c b/external/mbedtls/library/version_features.c new file mode 100644 index 0000000..8c8e815 --- /dev/null +++ b/external/mbedtls/library/version_features.c @@ -0,0 +1,822 @@ +/* + * Version feature information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_VERSION_C) + +#include "mbedtls/version.h" + +#include + +static const char *features[] = { +#if defined(MBEDTLS_VERSION_FEATURES) +#if defined(MBEDTLS_HAVE_ASM) + "MBEDTLS_HAVE_ASM", +#endif /* MBEDTLS_HAVE_ASM */ +#if defined(MBEDTLS_NO_UDBL_DIVISION) + "MBEDTLS_NO_UDBL_DIVISION", +#endif /* MBEDTLS_NO_UDBL_DIVISION */ +#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) + "MBEDTLS_NO_64BIT_MULTIPLICATION", +#endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */ +#if defined(MBEDTLS_HAVE_SSE2) + "MBEDTLS_HAVE_SSE2", +#endif /* MBEDTLS_HAVE_SSE2 */ +#if defined(MBEDTLS_HAVE_TIME) + "MBEDTLS_HAVE_TIME", +#endif /* MBEDTLS_HAVE_TIME */ +#if defined(MBEDTLS_HAVE_TIME_DATE) + "MBEDTLS_HAVE_TIME_DATE", +#endif /* MBEDTLS_HAVE_TIME_DATE */ +#if defined(MBEDTLS_PLATFORM_MEMORY) + "MBEDTLS_PLATFORM_MEMORY", +#endif /* MBEDTLS_PLATFORM_MEMORY */ +#if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) + "MBEDTLS_PLATFORM_NO_STD_FUNCTIONS", +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) + "MBEDTLS_PLATFORM_EXIT_ALT", +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) + "MBEDTLS_PLATFORM_TIME_ALT", +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) + "MBEDTLS_PLATFORM_FPRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) + "MBEDTLS_PLATFORM_PRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) + "MBEDTLS_PLATFORM_SNPRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) + "MBEDTLS_PLATFORM_NV_SEED_ALT", +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + "MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT", +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ +#if defined(MBEDTLS_DEPRECATED_WARNING) + "MBEDTLS_DEPRECATED_WARNING", +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#if defined(MBEDTLS_DEPRECATED_REMOVED) + "MBEDTLS_DEPRECATED_REMOVED", +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#if defined(MBEDTLS_CHECK_PARAMS) + "MBEDTLS_CHECK_PARAMS", +#endif /* MBEDTLS_CHECK_PARAMS */ +#if defined(MBEDTLS_CHECK_PARAMS_ASSERT) + "MBEDTLS_CHECK_PARAMS_ASSERT", +#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */ +#if defined(MBEDTLS_TIMING_ALT) + "MBEDTLS_TIMING_ALT", +#endif /* MBEDTLS_TIMING_ALT */ +#if defined(MBEDTLS_AES_ALT) + "MBEDTLS_AES_ALT", +#endif /* MBEDTLS_AES_ALT */ +#if defined(MBEDTLS_ARC4_ALT) + "MBEDTLS_ARC4_ALT", +#endif /* MBEDTLS_ARC4_ALT */ +#if defined(MBEDTLS_ARIA_ALT) + "MBEDTLS_ARIA_ALT", +#endif /* MBEDTLS_ARIA_ALT */ +#if defined(MBEDTLS_BLOWFISH_ALT) + "MBEDTLS_BLOWFISH_ALT", +#endif /* MBEDTLS_BLOWFISH_ALT */ +#if defined(MBEDTLS_CAMELLIA_ALT) + "MBEDTLS_CAMELLIA_ALT", +#endif /* MBEDTLS_CAMELLIA_ALT */ +#if defined(MBEDTLS_CCM_ALT) + "MBEDTLS_CCM_ALT", +#endif /* MBEDTLS_CCM_ALT */ +#if defined(MBEDTLS_CHACHA20_ALT) + "MBEDTLS_CHACHA20_ALT", +#endif /* MBEDTLS_CHACHA20_ALT */ +#if defined(MBEDTLS_CHACHAPOLY_ALT) + "MBEDTLS_CHACHAPOLY_ALT", +#endif /* MBEDTLS_CHACHAPOLY_ALT */ +#if defined(MBEDTLS_CMAC_ALT) + "MBEDTLS_CMAC_ALT", +#endif /* MBEDTLS_CMAC_ALT */ +#if defined(MBEDTLS_DES_ALT) + "MBEDTLS_DES_ALT", +#endif /* MBEDTLS_DES_ALT */ +#if defined(MBEDTLS_DHM_ALT) + "MBEDTLS_DHM_ALT", +#endif /* MBEDTLS_DHM_ALT */ +#if defined(MBEDTLS_ECJPAKE_ALT) + "MBEDTLS_ECJPAKE_ALT", +#endif /* MBEDTLS_ECJPAKE_ALT */ +#if defined(MBEDTLS_GCM_ALT) + "MBEDTLS_GCM_ALT", +#endif /* MBEDTLS_GCM_ALT */ +#if defined(MBEDTLS_NIST_KW_ALT) + "MBEDTLS_NIST_KW_ALT", +#endif /* MBEDTLS_NIST_KW_ALT */ +#if defined(MBEDTLS_MD2_ALT) + "MBEDTLS_MD2_ALT", +#endif /* MBEDTLS_MD2_ALT */ +#if defined(MBEDTLS_MD4_ALT) + "MBEDTLS_MD4_ALT", +#endif /* MBEDTLS_MD4_ALT */ +#if defined(MBEDTLS_MD5_ALT) + "MBEDTLS_MD5_ALT", +#endif /* MBEDTLS_MD5_ALT */ +#if defined(MBEDTLS_POLY1305_ALT) + "MBEDTLS_POLY1305_ALT", +#endif /* MBEDTLS_POLY1305_ALT */ +#if defined(MBEDTLS_RIPEMD160_ALT) + "MBEDTLS_RIPEMD160_ALT", +#endif /* MBEDTLS_RIPEMD160_ALT */ +#if defined(MBEDTLS_RSA_ALT) + "MBEDTLS_RSA_ALT", +#endif /* MBEDTLS_RSA_ALT */ +#if defined(MBEDTLS_SHA1_ALT) + "MBEDTLS_SHA1_ALT", +#endif /* MBEDTLS_SHA1_ALT */ +#if defined(MBEDTLS_SHA256_ALT) + "MBEDTLS_SHA256_ALT", +#endif /* MBEDTLS_SHA256_ALT */ +#if defined(MBEDTLS_SHA512_ALT) + "MBEDTLS_SHA512_ALT", +#endif /* MBEDTLS_SHA512_ALT */ +#if defined(MBEDTLS_XTEA_ALT) + "MBEDTLS_XTEA_ALT", +#endif /* MBEDTLS_XTEA_ALT */ +#if defined(MBEDTLS_ECP_ALT) + "MBEDTLS_ECP_ALT", +#endif /* MBEDTLS_ECP_ALT */ +#if defined(MBEDTLS_MD2_PROCESS_ALT) + "MBEDTLS_MD2_PROCESS_ALT", +#endif /* MBEDTLS_MD2_PROCESS_ALT */ +#if defined(MBEDTLS_MD4_PROCESS_ALT) + "MBEDTLS_MD4_PROCESS_ALT", +#endif /* MBEDTLS_MD4_PROCESS_ALT */ +#if defined(MBEDTLS_MD5_PROCESS_ALT) + "MBEDTLS_MD5_PROCESS_ALT", +#endif /* MBEDTLS_MD5_PROCESS_ALT */ +#if defined(MBEDTLS_RIPEMD160_PROCESS_ALT) + "MBEDTLS_RIPEMD160_PROCESS_ALT", +#endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */ +#if defined(MBEDTLS_SHA1_PROCESS_ALT) + "MBEDTLS_SHA1_PROCESS_ALT", +#endif /* MBEDTLS_SHA1_PROCESS_ALT */ +#if defined(MBEDTLS_SHA256_PROCESS_ALT) + "MBEDTLS_SHA256_PROCESS_ALT", +#endif /* MBEDTLS_SHA256_PROCESS_ALT */ +#if defined(MBEDTLS_SHA512_PROCESS_ALT) + "MBEDTLS_SHA512_PROCESS_ALT", +#endif /* MBEDTLS_SHA512_PROCESS_ALT */ +#if defined(MBEDTLS_DES_SETKEY_ALT) + "MBEDTLS_DES_SETKEY_ALT", +#endif /* MBEDTLS_DES_SETKEY_ALT */ +#if defined(MBEDTLS_DES_CRYPT_ECB_ALT) + "MBEDTLS_DES_CRYPT_ECB_ALT", +#endif /* MBEDTLS_DES_CRYPT_ECB_ALT */ +#if defined(MBEDTLS_DES3_CRYPT_ECB_ALT) + "MBEDTLS_DES3_CRYPT_ECB_ALT", +#endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */ +#if defined(MBEDTLS_AES_SETKEY_ENC_ALT) + "MBEDTLS_AES_SETKEY_ENC_ALT", +#endif /* MBEDTLS_AES_SETKEY_ENC_ALT */ +#if defined(MBEDTLS_AES_SETKEY_DEC_ALT) + "MBEDTLS_AES_SETKEY_DEC_ALT", +#endif /* MBEDTLS_AES_SETKEY_DEC_ALT */ +#if defined(MBEDTLS_AES_ENCRYPT_ALT) + "MBEDTLS_AES_ENCRYPT_ALT", +#endif /* MBEDTLS_AES_ENCRYPT_ALT */ +#if defined(MBEDTLS_AES_DECRYPT_ALT) + "MBEDTLS_AES_DECRYPT_ALT", +#endif /* MBEDTLS_AES_DECRYPT_ALT */ +#if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) + "MBEDTLS_ECDH_GEN_PUBLIC_ALT", +#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ +#if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) + "MBEDTLS_ECDH_COMPUTE_SHARED_ALT", +#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ +#if defined(MBEDTLS_ECDSA_VERIFY_ALT) + "MBEDTLS_ECDSA_VERIFY_ALT", +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + "MBEDTLS_ECDSA_SIGN_ALT", +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ +#if defined(MBEDTLS_ECDSA_GENKEY_ALT) + "MBEDTLS_ECDSA_GENKEY_ALT", +#endif /* MBEDTLS_ECDSA_GENKEY_ALT */ +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + "MBEDTLS_ECP_INTERNAL_ALT", +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + "MBEDTLS_ECP_RANDOMIZE_JAC_ALT", +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + "MBEDTLS_ECP_ADD_MIXED_ALT", +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + "MBEDTLS_ECP_DOUBLE_JAC_ALT", +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + "MBEDTLS_ECP_NORMALIZE_JAC_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT", +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT", +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + "MBEDTLS_ECP_NORMALIZE_MXZ_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) + "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN", +#endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */ +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND) + "MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND", +#endif /* MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + "MBEDTLS_TEST_NULL_ENTROPY", +#endif /* MBEDTLS_TEST_NULL_ENTROPY */ +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + "MBEDTLS_ENTROPY_HARDWARE_ALT", +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#if defined(MBEDTLS_AES_ROM_TABLES) + "MBEDTLS_AES_ROM_TABLES", +#endif /* MBEDTLS_AES_ROM_TABLES */ +#if defined(MBEDTLS_AES_FEWER_TABLES) + "MBEDTLS_AES_FEWER_TABLES", +#endif /* MBEDTLS_AES_FEWER_TABLES */ +#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) + "MBEDTLS_CAMELLIA_SMALL_MEMORY", +#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) + "MBEDTLS_CIPHER_MODE_CBC", +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CIPHER_MODE_CFB) + "MBEDTLS_CIPHER_MODE_CFB", +#endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_CTR) + "MBEDTLS_CIPHER_MODE_CTR", +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) + "MBEDTLS_CIPHER_MODE_OFB", +#endif /* MBEDTLS_CIPHER_MODE_OFB */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + "MBEDTLS_CIPHER_MODE_XTS", +#endif /* MBEDTLS_CIPHER_MODE_XTS */ +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + "MBEDTLS_CIPHER_NULL_CIPHER", +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + "MBEDTLS_CIPHER_PADDING_PKCS7", +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + "MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS", +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + "MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN", +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + "MBEDTLS_CIPHER_PADDING_ZEROS", +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) + "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY", +#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ +#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) + "MBEDTLS_ENABLE_WEAK_CIPHERSUITES", +#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + "MBEDTLS_REMOVE_ARC4_CIPHERSUITES", +#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ +#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES) + "MBEDTLS_REMOVE_3DES_CIPHERSUITES", +#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + "MBEDTLS_ECP_DP_SECP192R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + "MBEDTLS_ECP_DP_SECP224R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + "MBEDTLS_ECP_DP_SECP256R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + "MBEDTLS_ECP_DP_SECP384R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + "MBEDTLS_ECP_DP_SECP521R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + "MBEDTLS_ECP_DP_SECP192K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + "MBEDTLS_ECP_DP_SECP224K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + "MBEDTLS_ECP_DP_SECP256K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + "MBEDTLS_ECP_DP_BP256R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + "MBEDTLS_ECP_DP_BP384R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + "MBEDTLS_ECP_DP_BP512R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + "MBEDTLS_ECP_DP_CURVE25519_ENABLED", +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + "MBEDTLS_ECP_DP_CURVE448_ENABLED", +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ +#if defined(MBEDTLS_ECP_NIST_OPTIM) + "MBEDTLS_ECP_NIST_OPTIM", +#endif /* MBEDTLS_ECP_NIST_OPTIM */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + "MBEDTLS_ECP_NO_INTERNAL_RNG", +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + "MBEDTLS_ECP_RESTARTABLE", +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + "MBEDTLS_ECDSA_DETERMINISTIC", +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + "MBEDTLS_PK_PARSE_EC_EXTENDED", +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ +#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) + "MBEDTLS_ERROR_STRERROR_DUMMY", +#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ +#if defined(MBEDTLS_GENPRIME) + "MBEDTLS_GENPRIME", +#endif /* MBEDTLS_GENPRIME */ +#if defined(MBEDTLS_FS_IO) + "MBEDTLS_FS_IO", +#endif /* MBEDTLS_FS_IO */ +#if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) + "MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES", +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ +#if defined(MBEDTLS_NO_PLATFORM_ENTROPY) + "MBEDTLS_NO_PLATFORM_ENTROPY", +#endif /* MBEDTLS_NO_PLATFORM_ENTROPY */ +#if defined(MBEDTLS_ENTROPY_FORCE_SHA256) + "MBEDTLS_ENTROPY_FORCE_SHA256", +#endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) + "MBEDTLS_ENTROPY_NV_SEED", +#endif /* MBEDTLS_ENTROPY_NV_SEED */ +#if defined(MBEDTLS_MEMORY_DEBUG) + "MBEDTLS_MEMORY_DEBUG", +#endif /* MBEDTLS_MEMORY_DEBUG */ +#if defined(MBEDTLS_MEMORY_BACKTRACE) + "MBEDTLS_MEMORY_BACKTRACE", +#endif /* MBEDTLS_MEMORY_BACKTRACE */ +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) + "MBEDTLS_PK_RSA_ALT_SUPPORT", +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ +#if defined(MBEDTLS_PKCS1_V15) + "MBEDTLS_PKCS1_V15", +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + "MBEDTLS_PKCS1_V21", +#endif /* MBEDTLS_PKCS1_V21 */ +#if defined(MBEDTLS_RSA_NO_CRT) + "MBEDTLS_RSA_NO_CRT", +#endif /* MBEDTLS_RSA_NO_CRT */ +#if defined(MBEDTLS_SELF_TEST) + "MBEDTLS_SELF_TEST", +#endif /* MBEDTLS_SELF_TEST */ +#if defined(MBEDTLS_SHA256_SMALLER) + "MBEDTLS_SHA256_SMALLER", +#endif /* MBEDTLS_SHA256_SMALLER */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + "MBEDTLS_SSL_ALL_ALERT_MESSAGES", +#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + "MBEDTLS_SSL_ASYNC_PRIVATE", +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#if defined(MBEDTLS_SSL_DEBUG_ALL) + "MBEDTLS_SSL_DEBUG_ALL", +#endif /* MBEDTLS_SSL_DEBUG_ALL */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + "MBEDTLS_SSL_ENCRYPT_THEN_MAC", +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + "MBEDTLS_SSL_EXTENDED_MASTER_SECRET", +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + "MBEDTLS_SSL_FALLBACK_SCSV", +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + "MBEDTLS_SSL_HW_RECORD_ACCEL", +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + "MBEDTLS_SSL_CBC_RECORD_SPLITTING", +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + "MBEDTLS_SSL_RENEGOTIATION", +#endif /* MBEDTLS_SSL_RENEGOTIATION */ +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) + "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO", +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + "MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE", +#endif /* MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + "MBEDTLS_SSL_PROTO_SSL3", +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) + "MBEDTLS_SSL_PROTO_TLS1", +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) + "MBEDTLS_SSL_PROTO_TLS1_1", +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + "MBEDTLS_SSL_PROTO_TLS1_2", +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + "MBEDTLS_SSL_PROTO_DTLS", +#endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_ALPN) + "MBEDTLS_SSL_ALPN", +#endif /* MBEDTLS_SSL_ALPN */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + "MBEDTLS_SSL_DTLS_ANTI_REPLAY", +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + "MBEDTLS_SSL_DTLS_HELLO_VERIFY", +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) + "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE", +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */ +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + "MBEDTLS_SSL_SESSION_TICKETS", +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + "MBEDTLS_SSL_EXPORT_KEYS", +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + "MBEDTLS_SSL_SERVER_NAME_INDICATION", +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + "MBEDTLS_SSL_TRUNCATED_HMAC", +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) + "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT", +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */ +#if defined(MBEDTLS_TEST_HOOKS) + "MBEDTLS_TEST_HOOKS", +#endif /* MBEDTLS_TEST_HOOKS */ +#if defined(MBEDTLS_THREADING_ALT) + "MBEDTLS_THREADING_ALT", +#endif /* MBEDTLS_THREADING_ALT */ +#if defined(MBEDTLS_THREADING_PTHREAD) + "MBEDTLS_THREADING_PTHREAD", +#endif /* MBEDTLS_THREADING_PTHREAD */ +#if defined(MBEDTLS_VERSION_FEATURES) + "MBEDTLS_VERSION_FEATURES", +#endif /* MBEDTLS_VERSION_FEATURES */ +#if defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) + "MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3", +#endif /* MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 */ +#if defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + "MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION", +#endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */ +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + "MBEDTLS_X509_CHECK_KEY_USAGE", +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + "MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE", +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + "MBEDTLS_X509_RSASSA_PSS_SUPPORT", +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + "MBEDTLS_ZLIB_SUPPORT", +#endif /* MBEDTLS_ZLIB_SUPPORT */ +#if defined(MBEDTLS_AESNI_C) + "MBEDTLS_AESNI_C", +#endif /* MBEDTLS_AESNI_C */ +#if defined(MBEDTLS_AES_C) + "MBEDTLS_AES_C", +#endif /* MBEDTLS_AES_C */ +#if defined(MBEDTLS_ARC4_C) + "MBEDTLS_ARC4_C", +#endif /* MBEDTLS_ARC4_C */ +#if defined(MBEDTLS_ASN1_PARSE_C) + "MBEDTLS_ASN1_PARSE_C", +#endif /* MBEDTLS_ASN1_PARSE_C */ +#if defined(MBEDTLS_ASN1_WRITE_C) + "MBEDTLS_ASN1_WRITE_C", +#endif /* MBEDTLS_ASN1_WRITE_C */ +#if defined(MBEDTLS_BASE64_C) + "MBEDTLS_BASE64_C", +#endif /* MBEDTLS_BASE64_C */ +#if defined(MBEDTLS_BIGNUM_C) + "MBEDTLS_BIGNUM_C", +#endif /* MBEDTLS_BIGNUM_C */ +#if defined(MBEDTLS_BLOWFISH_C) + "MBEDTLS_BLOWFISH_C", +#endif /* MBEDTLS_BLOWFISH_C */ +#if defined(MBEDTLS_CAMELLIA_C) + "MBEDTLS_CAMELLIA_C", +#endif /* MBEDTLS_CAMELLIA_C */ +#if defined(MBEDTLS_ARIA_C) + "MBEDTLS_ARIA_C", +#endif /* MBEDTLS_ARIA_C */ +#if defined(MBEDTLS_CCM_C) + "MBEDTLS_CCM_C", +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CERTS_C) + "MBEDTLS_CERTS_C", +#endif /* MBEDTLS_CERTS_C */ +#if defined(MBEDTLS_CHACHA20_C) + "MBEDTLS_CHACHA20_C", +#endif /* MBEDTLS_CHACHA20_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + "MBEDTLS_CHACHAPOLY_C", +#endif /* MBEDTLS_CHACHAPOLY_C */ +#if defined(MBEDTLS_CIPHER_C) + "MBEDTLS_CIPHER_C", +#endif /* MBEDTLS_CIPHER_C */ +#if defined(MBEDTLS_CMAC_C) + "MBEDTLS_CMAC_C", +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_CTR_DRBG_C) + "MBEDTLS_CTR_DRBG_C", +#endif /* MBEDTLS_CTR_DRBG_C */ +#if defined(MBEDTLS_DEBUG_C) + "MBEDTLS_DEBUG_C", +#endif /* MBEDTLS_DEBUG_C */ +#if defined(MBEDTLS_DES_C) + "MBEDTLS_DES_C", +#endif /* MBEDTLS_DES_C */ +#if defined(MBEDTLS_DHM_C) + "MBEDTLS_DHM_C", +#endif /* MBEDTLS_DHM_C */ +#if defined(MBEDTLS_ECDH_C) + "MBEDTLS_ECDH_C", +#endif /* MBEDTLS_ECDH_C */ +#if defined(MBEDTLS_ECDSA_C) + "MBEDTLS_ECDSA_C", +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_ECJPAKE_C) + "MBEDTLS_ECJPAKE_C", +#endif /* MBEDTLS_ECJPAKE_C */ +#if defined(MBEDTLS_ECP_C) + "MBEDTLS_ECP_C", +#endif /* MBEDTLS_ECP_C */ +#if defined(MBEDTLS_ENTROPY_C) + "MBEDTLS_ENTROPY_C", +#endif /* MBEDTLS_ENTROPY_C */ +#if defined(MBEDTLS_ERROR_C) + "MBEDTLS_ERROR_C", +#endif /* MBEDTLS_ERROR_C */ +#if defined(MBEDTLS_GCM_C) + "MBEDTLS_GCM_C", +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_HAVEGE_C) + "MBEDTLS_HAVEGE_C", +#endif /* MBEDTLS_HAVEGE_C */ +#if defined(MBEDTLS_HKDF_C) + "MBEDTLS_HKDF_C", +#endif /* MBEDTLS_HKDF_C */ +#if defined(MBEDTLS_HMAC_DRBG_C) + "MBEDTLS_HMAC_DRBG_C", +#endif /* MBEDTLS_HMAC_DRBG_C */ +#if defined(MBEDTLS_NIST_KW_C) + "MBEDTLS_NIST_KW_C", +#endif /* MBEDTLS_NIST_KW_C */ +#if defined(MBEDTLS_MD_C) + "MBEDTLS_MD_C", +#endif /* MBEDTLS_MD_C */ +#if defined(MBEDTLS_MD2_C) + "MBEDTLS_MD2_C", +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + "MBEDTLS_MD4_C", +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + "MBEDTLS_MD5_C", +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + "MBEDTLS_MEMORY_BUFFER_ALLOC_C", +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ +#if defined(MBEDTLS_NET_C) + "MBEDTLS_NET_C", +#endif /* MBEDTLS_NET_C */ +#if defined(MBEDTLS_OID_C) + "MBEDTLS_OID_C", +#endif /* MBEDTLS_OID_C */ +#if defined(MBEDTLS_PADLOCK_C) + "MBEDTLS_PADLOCK_C", +#endif /* MBEDTLS_PADLOCK_C */ +#if defined(MBEDTLS_PEM_PARSE_C) + "MBEDTLS_PEM_PARSE_C", +#endif /* MBEDTLS_PEM_PARSE_C */ +#if defined(MBEDTLS_PEM_WRITE_C) + "MBEDTLS_PEM_WRITE_C", +#endif /* MBEDTLS_PEM_WRITE_C */ +#if defined(MBEDTLS_PK_C) + "MBEDTLS_PK_C", +#endif /* MBEDTLS_PK_C */ +#if defined(MBEDTLS_PK_PARSE_C) + "MBEDTLS_PK_PARSE_C", +#endif /* MBEDTLS_PK_PARSE_C */ +#if defined(MBEDTLS_PK_WRITE_C) + "MBEDTLS_PK_WRITE_C", +#endif /* MBEDTLS_PK_WRITE_C */ +#if defined(MBEDTLS_PKCS5_C) + "MBEDTLS_PKCS5_C", +#endif /* MBEDTLS_PKCS5_C */ +#if defined(MBEDTLS_PKCS11_C) + "MBEDTLS_PKCS11_C", +#endif /* MBEDTLS_PKCS11_C */ +#if defined(MBEDTLS_PKCS12_C) + "MBEDTLS_PKCS12_C", +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PLATFORM_C) + "MBEDTLS_PLATFORM_C", +#endif /* MBEDTLS_PLATFORM_C */ +#if defined(MBEDTLS_POLY1305_C) + "MBEDTLS_POLY1305_C", +#endif /* MBEDTLS_POLY1305_C */ +#if defined(MBEDTLS_RIPEMD160_C) + "MBEDTLS_RIPEMD160_C", +#endif /* MBEDTLS_RIPEMD160_C */ +#if defined(MBEDTLS_RSA_C) + "MBEDTLS_RSA_C", +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_SHA1_C) + "MBEDTLS_SHA1_C", +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + "MBEDTLS_SHA256_C", +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + "MBEDTLS_SHA512_C", +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SSL_CACHE_C) + "MBEDTLS_SSL_CACHE_C", +#endif /* MBEDTLS_SSL_CACHE_C */ +#if defined(MBEDTLS_SSL_COOKIE_C) + "MBEDTLS_SSL_COOKIE_C", +#endif /* MBEDTLS_SSL_COOKIE_C */ +#if defined(MBEDTLS_SSL_TICKET_C) + "MBEDTLS_SSL_TICKET_C", +#endif /* MBEDTLS_SSL_TICKET_C */ +#if defined(MBEDTLS_SSL_CLI_C) + "MBEDTLS_SSL_CLI_C", +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + "MBEDTLS_SSL_SRV_C", +#endif /* MBEDTLS_SSL_SRV_C */ +#if defined(MBEDTLS_SSL_TLS_C) + "MBEDTLS_SSL_TLS_C", +#endif /* MBEDTLS_SSL_TLS_C */ +#if defined(MBEDTLS_THREADING_C) + "MBEDTLS_THREADING_C", +#endif /* MBEDTLS_THREADING_C */ +#if defined(MBEDTLS_TIMING_C) + "MBEDTLS_TIMING_C", +#endif /* MBEDTLS_TIMING_C */ +#if defined(MBEDTLS_VERSION_C) + "MBEDTLS_VERSION_C", +#endif /* MBEDTLS_VERSION_C */ +#if defined(MBEDTLS_X509_USE_C) + "MBEDTLS_X509_USE_C", +#endif /* MBEDTLS_X509_USE_C */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + "MBEDTLS_X509_CRT_PARSE_C", +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_X509_CRL_PARSE_C) + "MBEDTLS_X509_CRL_PARSE_C", +#endif /* MBEDTLS_X509_CRL_PARSE_C */ +#if defined(MBEDTLS_X509_CSR_PARSE_C) + "MBEDTLS_X509_CSR_PARSE_C", +#endif /* MBEDTLS_X509_CSR_PARSE_C */ +#if defined(MBEDTLS_X509_CREATE_C) + "MBEDTLS_X509_CREATE_C", +#endif /* MBEDTLS_X509_CREATE_C */ +#if defined(MBEDTLS_X509_CRT_WRITE_C) + "MBEDTLS_X509_CRT_WRITE_C", +#endif /* MBEDTLS_X509_CRT_WRITE_C */ +#if defined(MBEDTLS_X509_CSR_WRITE_C) + "MBEDTLS_X509_CSR_WRITE_C", +#endif /* MBEDTLS_X509_CSR_WRITE_C */ +#if defined(MBEDTLS_XTEA_C) + "MBEDTLS_XTEA_C", +#endif /* MBEDTLS_XTEA_C */ +#endif /* MBEDTLS_VERSION_FEATURES */ + NULL +}; + +int mbedtls_version_check_feature( const char *feature ) +{ + const char **idx = features; + + if( *idx == NULL ) + return( -2 ); + + if( feature == NULL ) + return( -1 ); + + while( *idx != NULL ) + { + if( !strcmp( *idx, feature ) ) + return( 0 ); + idx++; + } + return( -1 ); +} + +#endif /* MBEDTLS_VERSION_C */ diff --git a/external/mbedtls/library/x509.c b/external/mbedtls/library/x509.c new file mode 100644 index 0000000..0c820ec --- /dev/null +++ b/external/mbedtls/library/x509.c @@ -0,0 +1,1097 @@ +/* + * X.509 common functions for parsing and verification + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_USE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/asn1.h" +#include "mbedtls/oid.h" + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_printf printf +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_util.h" +#include +#endif + +#define CHECK(code) if( ( ret = ( code ) ) != 0 ){ return( ret ); } +#define CHECK_RANGE(min, max, val) \ + do \ + { \ + if( ( val ) < ( min ) || ( val ) > ( max ) ) \ + { \ + return( ret ); \ + } \ + } while( 0 ) + +/* + * CertificateSerialNumber ::= INTEGER + */ +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ) +{ + int ret; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) && + **p != MBEDTLS_ASN1_INTEGER ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + serial->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret ); + + serial->p = *p; + *p += serial->len; + + return( 0 ); +} + +/* Get an algorithm identifier without parameters (eg for signatures) + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +/* + * Parse an algorithm identifier with (optional) parameters + */ +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +/* + * HashAlgorithm ::= AlgorithmIdentifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * For HashAlgorithm, parameters MUST be NULL or absent. + */ +static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg ) +{ + int ret; + unsigned char *p; + const unsigned char *end; + mbedtls_x509_buf md_oid; + size_t len; + + /* Make sure we got a SEQUENCE and setup bounds */ + if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) alg->p; + end = p + alg->len; + + if( p >= end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* Parse md_oid */ + md_oid.tag = *p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + md_oid.p = p; + p += md_oid.len; + + /* Get md_alg from md_oid */ + if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + /* Make sure params is absent of NULL */ + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, + * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, + * saltLength [2] INTEGER DEFAULT 20, + * trailerField [3] INTEGER DEFAULT 1 } + * -- Note that the tags in this Sequence are explicit. + * + * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value + * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other + * option. Enfore this at parsing time. + */ +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ) +{ + int ret; + unsigned char *p; + const unsigned char *end, *end2; + size_t len; + mbedtls_x509_buf alg_id, alg_params; + + /* First set everything to defaults */ + *md_alg = MBEDTLS_MD_SHA1; + *mgf_md = MBEDTLS_MD_SHA1; + *salt_len = 20; + + /* Make sure params is a SEQUENCE and setup bounds */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) params->p; + end = p + params->len; + + if( p == end ) + return( 0 ); + + /* + * HashAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + end2 = p + len; + + /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ + if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * MaskGenAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ + if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) + return( ret ); + + /* Only MFG1 is recognised for now */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE + + MBEDTLS_ERR_OID_NOT_FOUND ); + + /* Parse HashAlgorithm */ + if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) + return( ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * salt_len + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * trailer_field (if present, must be 1) + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 ) + { + int trailer_field; + + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( trailer_field != 1 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + +/* + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_get_attr_type_value( unsigned char **p, + const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret; + size_t len; + mbedtls_x509_buf *oid; + mbedtls_x509_buf *val; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + end = *p + len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + oid = &cur->oid; + oid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + oid->p = *p; + *p += oid->len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && + **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && + **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && + **p != MBEDTLS_ASN1_BIT_STRING ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + val = &cur->val; + val->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + val->p = *p; + *p += val->len; + + if( *p != end ) + { + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + cur->next = NULL; + + return( 0 ); +} + +/* + * Name ::= CHOICE { -- only one possibility for now -- + * rdnSequence RDNSequence } + * + * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + * + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + * + * The data structure is optimized for the common case where each RDN has only + * one element, which is represented as a list of AttributeTypeAndValue. + * For the general case we still use a flat list, but we mark elements of the + * same set so that they are "merged" together in the functions that consume + * this list, eg mbedtls_x509_dn_gets(). + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret; + size_t set_len; + const unsigned char *end_set; + + /* don't use recursion, we'd risk stack overflow if not optimized */ + while( 1 ) + { + /* + * parse SET + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + end_set = *p + set_len; + + while( 1 ) + { + if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) + return( ret ); + + if( *p == end_set ) + break; + + /* Mark this item as being no the only one in a set */ + cur->next_merged = 1; + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } + + /* + * continue until end of SEQUENCE is reached + */ + if( *p == end ) + return( 0 ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } +} + +static int x509_parse_int( unsigned char **p, size_t n, int *res ) +{ + *res = 0; + + for( ; n > 0; --n ) + { + if( ( **p < '0') || ( **p > '9' ) ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + *res *= 10; + *res += ( *(*p)++ - '0' ); + } + + return( 0 ); +} + +static int x509_date_is_valid(const mbedtls_x509_time *t ) +{ + int ret = MBEDTLS_ERR_X509_INVALID_DATE; + int month_len; + + CHECK_RANGE( 0, 9999, t->year ); + CHECK_RANGE( 0, 23, t->hour ); + CHECK_RANGE( 0, 59, t->min ); + CHECK_RANGE( 0, 59, t->sec ); + + switch( t->mon ) + { + case 1: case 3: case 5: case 7: case 8: case 10: case 12: + month_len = 31; + break; + case 4: case 6: case 9: case 11: + month_len = 30; + break; + case 2: + if( ( !( t->year % 4 ) && t->year % 100 ) || + !( t->year % 400 ) ) + month_len = 29; + else + month_len = 28; + break; + default: + return( ret ); + } + CHECK_RANGE( 1, month_len, t->day ); + + return( 0 ); +} + +/* + * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) + * field. + */ +static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, + mbedtls_x509_time *tm ) +{ + int ret; + + /* + * Minimum length is 10 or 12 depending on yearlen + */ + if ( len < yearlen + 8 ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + len -= yearlen + 8; + + /* + * Parse year, month, day, hour, minute + */ + CHECK( x509_parse_int( p, yearlen, &tm->year ) ); + if ( 2 == yearlen ) + { + if ( tm->year < 50 ) + tm->year += 100; + + tm->year += 1900; + } + + CHECK( x509_parse_int( p, 2, &tm->mon ) ); + CHECK( x509_parse_int( p, 2, &tm->day ) ); + CHECK( x509_parse_int( p, 2, &tm->hour ) ); + CHECK( x509_parse_int( p, 2, &tm->min ) ); + + /* + * Parse seconds if present + */ + if ( len >= 2 ) + { + CHECK( x509_parse_int( p, 2, &tm->sec ) ); + len -= 2; + } + else + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + /* + * Parse trailing 'Z' if present + */ + if ( 1 == len && 'Z' == **p ) + { + (*p)++; + len--; + } + + /* + * We should have parsed all characters at this point + */ + if ( 0 != len ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + CHECK( x509_date_is_valid( tm ) ); + + return ( 0 ); +} + +/* + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + */ +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *tm ) +{ + int ret; + size_t len, year_len; + unsigned char tag; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + + if( tag == MBEDTLS_ASN1_UTC_TIME ) + year_len = 2; + else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) + year_len = 4; + else + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + ret = mbedtls_asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); + + return x509_parse_time( p, len, year_len, tm ); +} + +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) +{ + int ret; + size_t len; + int tag_type; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag_type = **p; + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret ); + + sig->tag = tag_type; + sig->len = len; + sig->p = *p; + + *p += len; + + return( 0 ); +} + +/* + * Get signature algorithm from alg OID and optional parameters + */ +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ) +{ + int ret; + + if( *sig_opts != NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( *pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + mbedtls_pk_rsassa_pss_options *pss_opts; + + pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) ); + if( pss_opts == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + ret = mbedtls_x509_get_rsassa_pss_params( sig_params, + md_alg, + &pss_opts->mgf1_hash_id, + &pss_opts->expected_salt_len ); + if( ret != 0 ) + { + mbedtls_free( pss_opts ); + return( ret ); + } + + *sig_opts = (void *) pss_opts; + } + else +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + { + /* Make sure parameters are absent or NULL */ + if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) || + sig_params->len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * X.509 Extensions (No parsing of extensions, pointer should + * be either manually updated or extensions should be parsed!) + */ +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ) +{ + int ret; + size_t len; + + /* Extension structure use EXPLICIT tagging. That is, the actual + * `Extensions` structure is wrapped by a tag-length pair using + * the respective context-specific tag. */ + ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ); + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag; + ext->p = *p; + end = *p + ext->len; + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( end != *p + len ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Store the name in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) +{ + int ret; + size_t i, n; + unsigned char c, merge = 0; + const mbedtls_x509_name *name; + const char *short_name = NULL; + char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; + + memset( s, 0, sizeof( s ) ); + + name = dn; + p = buf; + n = size; + + while( name != NULL ) + { + if( !name->oid.p ) + { + name = name->next; + continue; + } + + if( name != dn ) + { + ret = mbedtls_snprintf( p, n, merge ? " + " : ", " ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name ); + + if( ret == 0 ) + ret = mbedtls_snprintf( p, n, "%s=", short_name ); + else + ret = mbedtls_snprintf( p, n, "\?\?=" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + for( i = 0; i < name->val.len; i++ ) + { + if( i >= sizeof( s ) - 1 ) + break; + + c = name->val.p[i]; + if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) + s[i] = '?'; + else s[i] = c; + } + s[i] = '\0'; + ret = mbedtls_snprintf( p, n, "%s", s ); + MBEDTLS_X509_SAFE_SNPRINTF; + + merge = name->next_merged; + name = name->next; + } + + return( (int) ( size - n ) ); +} + +/* + * Store the serial in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ) +{ + int ret; + size_t i, n, nr; + char *p; + + p = buf; + n = size; + + nr = ( serial->len <= 32 ) + ? serial->len : 28; + + for( i = 0; i < nr; i++ ) + { + if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%02X%s", + serial->p[i], ( i < nr - 1 ) ? ":" : "" ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + if( nr != serial->len ) + { + ret = mbedtls_snprintf( p, n, "...." ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +/* + * Helper for writing signature algorithms + */ +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ) +{ + int ret; + char *p = buf; + size_t n = size; + const char *desc = NULL; + + ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc ); + if( ret != 0 ) + ret = mbedtls_snprintf( p, n, "???" ); + else + ret = mbedtls_snprintf( p, n, "%s", desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + const mbedtls_pk_rsassa_pss_options *pss_opts; + const mbedtls_md_info_t *md_info, *mgf_md_info; + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; + + md_info = mbedtls_md_info_from_type( md_alg ); + mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id ); + + ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", + md_info ? mbedtls_md_get_name( md_info ) : "???", + mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???", + pss_opts->expected_salt_len ); + MBEDTLS_X509_SAFE_SNPRINTF; + } +#else + ((void) pk_alg); + ((void) md_alg); + ((void) sig_opts); +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + + return( (int)( size - n ) ); +} + +/* + * Helper for writing "RSA key size", "EC key size", etc + */ +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) +{ + char *p = buf; + size_t n = buf_size; + int ret; + + ret = mbedtls_snprintf( p, n, "%s key size", name ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( 0 ); +} + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/* + * Set the time structure to the current time. + * Return 0 on success, non-zero on failure. + */ +static int x509_get_current_time( mbedtls_x509_time *now ) +{ + struct tm *lt, tm_buf; + mbedtls_time_t tt; + int ret = 0; + + tt = mbedtls_time( NULL ); + lt = mbedtls_platform_gmtime_r( &tt, &tm_buf ); + + if( lt == NULL ) + ret = -1; + else + { + now->year = lt->tm_year + 1900; + now->mon = lt->tm_mon + 1; + now->day = lt->tm_mday; + now->hour = lt->tm_hour; + now->min = lt->tm_min; + now->sec = lt->tm_sec; + } + + return( ret ); +} + +/* + * Return 0 if before <= after, 1 otherwise + */ +static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after ) +{ + if( before->year > after->year ) + return( 1 ); + + if( before->year == after->year && + before->mon > after->mon ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day > after->day ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour > after->hour ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min > after->min ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min == after->min && + before->sec > after->sec ) + return( 1 ); + + return( 0 ); +} + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( &now, to ) ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( from, &now ) ); +} + +#else /* MBEDTLS_HAVE_TIME_DATE */ + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + ((void) to); + return( 0 ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + ((void) from); + return( 0 ); +} +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#if defined(MBEDTLS_SELF_TEST) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/certs.h" + +/* + * Checkup routine + */ +int mbedtls_x509_self_test( int verbose ) +{ + int ret = 0; +#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C) + uint32_t flags; + mbedtls_x509_crt cacert; + mbedtls_x509_crt clicert; + + if( verbose != 0 ) + mbedtls_printf( " X.509 certificate load: " ); + + mbedtls_x509_crt_init( &cacert ); + mbedtls_x509_crt_init( &clicert ); + + ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, + mbedtls_test_cli_crt_len ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt, + mbedtls_test_ca_crt_len ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n X.509 signature verify: "); + + ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n"); + +cleanup: + mbedtls_x509_crt_free( &cacert ); + mbedtls_x509_crt_free( &clicert ); +#else + ((void) verbose); +#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA256_C */ + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_X509_USE_C */ diff --git a/external/mbedtls/library/x509_create.c b/external/mbedtls/library/x509_create.c new file mode 100644 index 0000000..0dbd679 --- /dev/null +++ b/external/mbedtls/library/x509_create.c @@ -0,0 +1,404 @@ +/* + * X.509 base functions for creating certificates / CSRs + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CREATE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/oid.h" + +#include + +/* Structure linking OIDs for X.509 DN AttributeTypes to their + * string representations and default string encodings used by Mbed TLS. */ +typedef struct { + const char *name; /* String representation of AttributeType, e.g. + * "CN" or "emailAddress". */ + size_t name_len; /* Length of 'name', without trailing 0 byte. */ + const char *oid; /* String representation of OID of AttributeType, + * as per RFC 5280, Appendix A.1. */ + int default_tag; /* The default character encoding used for the + * given attribute type, e.g. + * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */ +} x509_attr_descriptor_t; + +#define ADD_STRLEN( s ) s, sizeof( s ) - 1 + +/* X.509 DN attributes from RFC 5280, Appendix A.1. */ +static const x509_attr_descriptor_t x509_attrs[] = +{ + { ADD_STRLEN( "CN" ), + MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "commonName" ), + MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "C" ), + MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "countryName" ), + MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "O" ), + MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "organizationName" ), + MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "L" ), + MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "locality" ), + MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "R" ), + MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "OU" ), + MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "organizationalUnitName" ), + MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "ST" ), + MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "stateOrProvinceName" ), + MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "emailAddress" ), + MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "serialNumber" ), + MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "postalAddress" ), + MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "postalCode" ), + MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "dnQualifier" ), + MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "title" ), + MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "surName" ), + MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "SN" ), + MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "givenName" ), + MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "GN" ), + MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "initials" ), + MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "pseudonym" ), + MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "generationQualifier" ), + MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "domainComponent" ), + MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "DC" ), + MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, + { NULL, 0, NULL, MBEDTLS_ASN1_NULL } +}; + +static const x509_attr_descriptor_t *x509_attr_descr_from_name( const char *name, size_t name_len ) +{ + const x509_attr_descriptor_t *cur; + + for( cur = x509_attrs; cur->name != NULL; cur++ ) + if( cur->name_len == name_len && + strncmp( cur->name, name, name_len ) == 0 ) + break; + + if ( cur->name == NULL ) + return( NULL ); + + return( cur ); +} + +int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ) +{ + int ret = 0; + const char *s = name, *c = s; + const char *end = s + strlen( s ); + const char *oid = NULL; + const x509_attr_descriptor_t* attr_descr = NULL; + int in_tag = 1; + char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; + char *d = data; + + /* Clear existing chain if present */ + mbedtls_asn1_free_named_data_list( head ); + + while( c <= end ) + { + if( in_tag && *c == '=' ) + { + if( ( attr_descr = x509_attr_descr_from_name( s, c - s ) ) == NULL ) + { + ret = MBEDTLS_ERR_X509_UNKNOWN_OID; + goto exit; + } + + oid = attr_descr->oid; + s = c + 1; + in_tag = 0; + d = data; + } + + if( !in_tag && *c == '\\' && c != end ) + { + c++; + + /* Check for valid escaped characters */ + if( c == end || *c != ',' ) + { + ret = MBEDTLS_ERR_X509_INVALID_NAME; + goto exit; + } + } + else if( !in_tag && ( *c == ',' || c == end ) ) + { + mbedtls_asn1_named_data* cur = + mbedtls_asn1_store_named_data( head, oid, strlen( oid ), + (unsigned char *) data, + d - data ); + + if(cur == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + // set tagType + cur->val.tag = attr_descr->default_tag; + + while( c < end && *(c + 1) == ' ' ) + c++; + + s = c + 1; + in_tag = 1; + } + + if( !in_tag && s != c + 1 ) + { + *(d++) = *c; + + if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE ) + { + ret = MBEDTLS_ERR_X509_INVALID_NAME; + goto exit; + } + } + + c++; + } + +exit: + + return( ret ); +} + +/* The first byte of the value in the mbedtls_asn1_named_data structure is reserved + * to store the critical boolean for us + */ +int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, size_t val_len ) +{ + mbedtls_asn1_named_data *cur; + + if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len, + NULL, val_len + 1 ) ) == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + cur->val.p[0] = critical; + memcpy( cur->val.p + 1, val, val_len ); + + return( 0 ); +} + +/* + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name) +{ + int ret; + size_t len = 0; + const char *oid = (const char*)cur_name->oid.p; + size_t oid_len = cur_name->oid.len; + const unsigned char *name = cur_name->val.p; + size_t name_len = cur_name->val.len; + + // Write correct string tag and value + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tagged_string( p, start, + cur_name->val.tag, + (const char *) name, + name_len ) ); + // Write OID + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, + oid_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SET ) ); + + return( (int) len ); +} + +int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ) +{ + int ret; + size_t len = 0; + mbedtls_asn1_named_data *cur = first; + + while( cur != NULL ) + { + MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, cur ) ); + cur = cur->next; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ) +{ + int ret; + size_t len = 0; + + if( *p < start || (size_t)( *p - start ) < size ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, sig, len ); + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); + + // Write OID + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid, + oid_len, 0 ) ); + + return( (int) len ); +} + +static int x509_write_extension( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *ext ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1, + ext->val.len - 1 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); + + if( ext->val.p[0] != 0 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p, + ext->oid.len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +/* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING + * -- contains the DER encoding of an ASN.1 value + * -- corresponding to the extension type identified + * -- by extnID + * } + */ +int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ) +{ + int ret; + size_t len = 0; + mbedtls_asn1_named_data *cur_ext = first; + + while( cur_ext != NULL ) + { + MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) ); + cur_ext = cur_ext->next; + } + + return( (int) len ); +} + +#endif /* MBEDTLS_X509_CREATE_C */ diff --git a/external/mbedtls/library/x509_crl.c b/external/mbedtls/library/x509_crl.c new file mode 100644 index 0000000..dba71fa --- /dev/null +++ b/external/mbedtls/library/x509_crl.c @@ -0,0 +1,798 @@ +/* + * X.509 Certidicate Revocation List (CRL) parsing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + +#include "mbedtls/x509_crl.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* + * Version ::= INTEGER { v1(0), v2(1) } + */ +static int x509_crl_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + } + + return( 0 ); +} + +/* + * X.509 CRL v2 extensions + * + * We currently don't parse any extension's content, but we do check that the + * list of extensions is well-formed and abort on critical extensions (that + * are unsupported as we don't support any extension so far) + */ +static int x509_get_crl_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret; + + if( *p == end ) + return( 0 ); + + /* + * crlExtensions [0] EXPLICIT Extensions OPTIONAL + * -- if present, version MUST be v2 + */ + if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0 ) ) != 0 ) + return( ret ); + + end = ext->p + ext->len; + + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + int is_critical = 0; + const unsigned char *end_ext_data; + size_t len; + + /* Get enclosing sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_data = *p + len; + + /* Get OID (currently ignored) */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OID ) ) != 0 ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + *p += len; + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, + &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Ignore data so far and just check its length */ + *p += len; + if( *p != end_ext_data ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* Abort on (unsupported) critical extensions */ + if( is_critical ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 CRL v2 entry extensions (no extensions parsed yet.) + */ +static int x509_get_crl_entry_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret; + size_t len = 0; + + /* OPTIONAL */ + if( end <= *p ) + return( 0 ); + + ext->tag = **p; + ext->p = *p; + + /* + * Get CRL-entry extension sequence header + * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + ext->p = NULL; + return( 0 ); + } + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + + end = *p + ext->len; + + if( end != *p + ext->len ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + *p += len; + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 CRL Entries + */ +static int x509_get_entries( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crl_entry *entry ) +{ + int ret; + size_t entry_len; + mbedtls_x509_crl_entry *cur_entry = entry; + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &entry_len, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + end = *p + entry_len; + + while( *p < end ) + { + size_t len2; + const unsigned char *end2; + + cur_entry->raw.tag = **p; + if( ( ret = mbedtls_asn1_get_tag( p, end, &len2, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + return( ret ); + } + + cur_entry->raw.p = *p; + cur_entry->raw.len = len2; + end2 = *p + len2; + + if( ( ret = mbedtls_x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_x509_get_time( p, end2, + &cur_entry->revocation_date ) ) != 0 ) + return( ret ); + + if( ( ret = x509_get_crl_entry_ext( p, end2, + &cur_entry->entry_ext ) ) != 0 ) + return( ret ); + + if( *p < end ) + { + cur_entry->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry ) ); + + if( cur_entry->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur_entry = cur_entry->next; + } + } + + return( 0 ); +} + +/* + * Parse one CRLs in DER format and append it to the chained list + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p = NULL, *end = NULL; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + mbedtls_x509_crl *crl = chain; + + /* + * Check for valid input + */ + if( crl == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Add new CRL on the end of the chain if needed. + */ + while( crl->version != 0 && crl->next != NULL ) + crl = crl->next; + + if( crl->version != 0 && crl->next == NULL ) + { + crl->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) ); + + if( crl->next == NULL ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + mbedtls_x509_crl_init( crl->next ); + crl = crl->next; + } + + /* + * Copy raw DER-encoded CRL + */ + if( buflen == 0 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + p = mbedtls_calloc( 1, buflen ); + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + crl->raw.p = p; + crl->raw.len = buflen; + + end = p + buflen; + + /* + * CertificateList ::= SEQUENCE { + * tbsCertList TBSCertList, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * TBSCertList ::= SEQUENCE { + */ + crl->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + crl->tbs.len = end - crl->tbs.p; + + /* + * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } + * -- if present, MUST be v2 + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->version < 0 || crl->version > 1 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + crl->version++; + + if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, + &crl->sig_md, &crl->sig_pk, + &crl->sig_opts ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + /* + * issuer Name + */ + crl->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + crl->issuer_raw.len = p - crl->issuer_raw.p; + + /* + * thisUpdate Time + * nextUpdate Time OPTIONAL + */ + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 ) + { + if( ret != ( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) && + ret != ( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + /* + * revokedCertificates SEQUENCE OF SEQUENCE { + * userCertificate CertificateSerialNumber, + * revocationDate Time, + * crlEntryExtensions Extensions OPTIONAL + * -- if present, MUST be v2 + * } OPTIONAL + */ + if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + /* + * crlExtensions EXPLICIT Extensions OPTIONAL + * -- if present, MUST be v2 + */ + if( crl->version == 2 ) + { + ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); + + if( ret != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crl->raw.p + crl->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->sig_oid.len != sig_oid2.len || + memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int ret; + size_t use_len; + mbedtls_pem_context pem; + int is_pem = 0; + + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + do + { + mbedtls_pem_init( &pem ); + + // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated + // string + if( buflen == 0 || buf[buflen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN X509 CRL-----", + "-----END X509 CRL-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + is_pem = 1; + + buflen -= use_len; + buf += use_len; + + if( ( ret = mbedtls_x509_crl_parse_der( chain, + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + } + else if( is_pem ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + + mbedtls_pem_free( &pem ); + } + /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. + * And a valid CRL cannot be less than 1 byte anyway. */ + while( is_pem && buflen > 1 ); + + if( is_pem ) + return( 0 ); + else +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crl_parse( chain, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CRL. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ) +{ + int ret; + size_t n; + char *p; + const mbedtls_x509_crl_entry *entry; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCRL version : %d", + prefix, crl->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crl->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sthis update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->this_update.year, crl->this_update.mon, + crl->this_update.day, crl->this_update.hour, + crl->this_update.min, crl->this_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%snext update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->next_update.year, crl->next_update.mon, + crl->next_update.day, crl->next_update.hour, + crl->next_update.min, crl->next_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = &crl->entry; + + ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + while( entry != NULL && entry->raw.len != 0 ) + { + ret = mbedtls_snprintf( p, n, "\n%sserial number: ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &entry->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, " revocation date: " \ + "%04d-%02d-%02d %02d:%02d:%02d", + entry->revocation_date.year, entry->revocation_date.mon, + entry->revocation_date.day, entry->revocation_date.hour, + entry->revocation_date.min, entry->revocation_date.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = entry->next; + } + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, + crl->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CRL chain + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ) +{ + memset( crl, 0, sizeof(mbedtls_x509_crl) ); +} + +/* + * Unallocate all CRL data + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) +{ + mbedtls_x509_crl *crl_cur = crl; + mbedtls_x509_crl *crl_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_crl_entry *entry_cur; + mbedtls_x509_crl_entry *entry_prv; + + if( crl == NULL ) + return; + + do + { +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( crl_cur->sig_opts ); +#endif + + name_cur = crl_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + entry_cur = crl_cur->entry.next; + while( entry_cur != NULL ) + { + entry_prv = entry_cur; + entry_cur = entry_cur->next; + mbedtls_platform_zeroize( entry_prv, + sizeof( mbedtls_x509_crl_entry ) ); + mbedtls_free( entry_prv ); + } + + if( crl_cur->raw.p != NULL ) + { + mbedtls_platform_zeroize( crl_cur->raw.p, crl_cur->raw.len ); + mbedtls_free( crl_cur->raw.p ); + } + + crl_cur = crl_cur->next; + } + while( crl_cur != NULL ); + + crl_cur = crl; + do + { + crl_prv = crl_cur; + crl_cur = crl_cur->next; + + mbedtls_platform_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); + if( crl_prv != crl ) + mbedtls_free( crl_prv ); + } + while( crl_cur != NULL ); +} + +#endif /* MBEDTLS_X509_CRL_PARSE_C */ diff --git a/external/mbedtls/library/x509_crt.c b/external/mbedtls/library/x509_crt.c new file mode 100644 index 0000000..4b53d1a --- /dev/null +++ b/external/mbedtls/library/x509_crt.c @@ -0,0 +1,2761 @@ +/* + * X.509 certificate parsing and verification + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + * + * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) +#include +#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) +#include +#include +#include +#endif /* !_WIN32 || EFIX64 || EFI32 */ +#endif + +/* + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *crt; + uint32_t flags; +} x509_crt_verify_chain_item; + +/* + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) + +/* + * Default profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = +{ +#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) + /* Allow SHA-1 (weak, but still safe in controlled environments) */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | +#endif + /* Only SHA-2 hashes */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 2048, +}; + +/* + * Next-default profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = +{ + /* Hashes from SHA-256 and above */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ +#if defined(MBEDTLS_ECP_C) + /* Curves at or above 128-bit security level */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ), +#else + 0, +#endif + 2048, +}; + +/* + * NSA Suite B Profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = +{ + /* Only SHA-256 and 384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), + /* Only ECDSA */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ), +#if defined(MBEDTLS_ECP_C) + /* Only NIST P-256 and P-384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), +#else + 0, +#endif + 0, +}; + +/* + * Check md_alg against profile + * Return 0 if md_alg is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, + mbedtls_md_type_t md_alg ) +{ + if( md_alg == MBEDTLS_MD_NONE ) + return( -1 ); + + if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 ) + return( 0 ); + + return( -1 ); +} + +/* + * Check pk_alg against profile + * Return 0 if pk_alg is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, + mbedtls_pk_type_t pk_alg ) +{ + if( pk_alg == MBEDTLS_PK_NONE ) + return( -1 ); + + if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 ) + return( 0 ); + + return( -1 ); +} + +/* + * Check key against profile + * Return 0 if pk is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, + const mbedtls_pk_context *pk ) +{ + const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen ) + return( 0 ); + + return( -1 ); + } +#endif + +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECDSA || + pk_alg == MBEDTLS_PK_ECKEY || + pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; + + if( gid == MBEDTLS_ECP_DP_NONE ) + return( -1 ); + + if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 ) + return( 0 ); + + return( -1 ); + } +#endif + + return( -1 ); +} + +/* + * Like memcmp, but case-insensitive and always returns -1 if different + */ +static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) +{ + size_t i; + unsigned char diff; + const unsigned char *n1 = s1, *n2 = s2; + + for( i = 0; i < len; i++ ) + { + diff = n1[i] ^ n2[i]; + + if( diff == 0 ) + continue; + + if( diff == 32 && + ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || + ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) + { + continue; + } + + return( -1 ); + } + + return( 0 ); +} + +/* + * Return 0 if name matches wildcard, -1 otherwise + */ +static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name ) +{ + size_t i; + size_t cn_idx = 0, cn_len = strlen( cn ); + + /* We can't have a match if there is no wildcard to match */ + if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) + return( -1 ); + + for( i = 0; i < cn_len; ++i ) + { + if( cn[i] == '.' ) + { + cn_idx = i; + break; + } + } + + if( cn_idx == 0 ) + return( -1 ); + + if( cn_len - cn_idx == name->len - 1 && + x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 strings, case-insensitive, and allowing for some encoding + * variations (but not all). + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) +{ + if( a->tag == b->tag && + a->len == b->len && + memcmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + a->len == b->len && + x509_memcasecmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 Names (aka rdnSequence). + * + * See RFC 5280 section 7.1, though we don't implement the whole algorithm: + * we sometimes return unequal when the full algorithm would return equal, + * but never the other way. (In particular, we don't do Unicode normalisation + * or space folding.) + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) +{ + /* Avoid recursion, it might not be optimised by the compiler */ + while( a != NULL || b != NULL ) + { + if( a == NULL || b == NULL ) + return( -1 ); + + /* type */ + if( a->oid.tag != b->oid.tag || + a->oid.len != b->oid.len || + memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) + { + return( -1 ); + } + + /* value */ + if( x509_string_cmp( &a->val, &b->val ) != 0 ) + return( -1 ); + + /* structure of the list of sets */ + if( a->next_merged != b->next_merged ) + return( -1 ); + + a = a->next; + b = b->next; + } + + /* a == NULL == b */ + return( 0 ); +} + +/* + * Reset (init or clear) a verify_chain + */ +static void x509_crt_verify_chain_reset( + mbedtls_x509_crt_verify_chain *ver_chain ) +{ + size_t i; + + for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ ) + { + ver_chain->items[i].crt = NULL; + ver_chain->items[i].flags = (uint32_t) -1; + } + + ver_chain->len = 0; +} + +/* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ +static int x509_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = *p + len; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_VERSION + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ +static int x509_get_dates( unsigned char **p, + const unsigned char *end, + mbedtls_x509_time *from, + mbedtls_x509_time *to ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); + + end = *p + len; + + if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 ) + return( ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 v2/v3 unique identifier (not parsed) + */ +static int x509_get_uid( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *uid, int n ) +{ + int ret; + + if( *p == end ) + return( 0 ); + + uid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + uid->p = *p; + *p += uid->len; + + return( 0 ); +} + +static int x509_get_basic_constraints( unsigned char **p, + const unsigned char *end, + int *ca_istrue, + int *max_pathlen ) +{ + int ret; + size_t len; + + /* + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + */ + *ca_istrue = 0; /* DEFAULT FALSE */ + *max_pathlen = 0; /* endless */ + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + ret = mbedtls_asn1_get_int( p, end, ca_istrue ); + + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *ca_istrue != 0 ) + *ca_istrue = 1; + } + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer + * overflow, which is an undefined behavior. */ + if( *max_pathlen == INT_MAX ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + (*max_pathlen)++; + + return( 0 ); +} + +static int x509_get_ns_cert_type( unsigned char **p, + const unsigned char *end, + unsigned char *ns_cert_type) +{ + int ret; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( bs.len != 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + /* Get actual bitstring */ + *ns_cert_type = *bs.p; + return( 0 ); +} + +static int x509_get_key_usage( unsigned char **p, + const unsigned char *end, + unsigned int *key_usage) +{ + int ret; + size_t i; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( bs.len < 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + /* Get actual bitstring */ + *key_usage = 0; + for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ ) + { + *key_usage |= (unsigned int) bs.p[i] << (8*i); + } + + return( 0 ); +} + +/* + * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + * + * KeyPurposeId ::= OBJECT IDENTIFIER + */ +static int x509_get_ext_key_usage( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *ext_key_usage) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Sequence length must be >= 1 */ + if( ext_key_usage->buf.p == NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + return( 0 ); +} + +/* + * SubjectAltName ::= GeneralNames + * + * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + * + * GeneralName ::= CHOICE { + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER } + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * EDIPartyName ::= SEQUENCE { + * nameAssigner [0] DirectoryString OPTIONAL, + * partyName [1] DirectoryString } + * + * NOTE: we only parse and use dNSName at this point. + */ +static int x509_get_subject_alt_name( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *subject_alt_name ) +{ + int ret; + size_t len, tag_len; + mbedtls_asn1_buf *buf; + unsigned char tag; + mbedtls_asn1_sequence *cur = subject_alt_name; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + (*p)++; + if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( ( tag & MBEDTLS_ASN1_TAG_CLASS_MASK ) != + MBEDTLS_ASN1_CONTEXT_SPECIFIC ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + /* Skip everything but DNS name */ + if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) ) + { + *p += tag_len; + continue; + } + + /* Allocate and assign next pointer */ + if( cur->buf.p != NULL ) + { + if( cur->next != NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + + buf = &(cur->buf); + buf->tag = tag; + buf->p = *p; + buf->len = tag_len; + *p += buf->len; + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 v3 extensions + * + */ +static int x509_get_crt_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crt *crt ) +{ + int ret; + size_t len; + unsigned char *end_ext_data, *end_ext_octet; + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) + return( ret ); + + end = crt->v3_ext.p + crt->v3_ext.len; + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + mbedtls_x509_buf extn_oid = {0, 0, NULL}; + int is_critical = 0; /* DEFAULT FALSE */ + int ext_type = 0; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_data = *p + len; + + /* Get extension ID */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len, + MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + extn_oid.tag = MBEDTLS_ASN1_OID; + extn_oid.p = *p; + *p += extn_oid.len; + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_octet = *p + len; + + if( end_ext_octet != end_ext_data ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Detect supported extensions + */ + ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type ); + + if( ret != 0 ) + { + /* No parser found, skip extension */ + *p = end_ext_octet; + +#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( is_critical ) + { + /* Data is marked as critical: fail */ + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } +#endif + continue; + } + + /* Forbid repeated extensions */ + if( ( crt->ext_types & ext_type ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + crt->ext_types |= ext_type; + + switch( ext_type ) + { + case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: + /* Parse basic constraints */ + if( ( ret = x509_get_basic_constraints( p, end_ext_octet, + &crt->ca_istrue, &crt->max_pathlen ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_KEY_USAGE: + /* Parse key usage */ + if( ( ret = x509_get_key_usage( p, end_ext_octet, + &crt->key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: + /* Parse extended key usage */ + if( ( ret = x509_get_ext_key_usage( p, end_ext_octet, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: + /* Parse subject alt name */ + if( ( ret = x509_get_subject_alt_name( p, end_ext_octet, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_NS_CERT_TYPE: + /* Parse netscape certificate type */ + if( ( ret = x509_get_ns_cert_type( p, end_ext_octet, + &crt->ns_cert_type ) ) != 0 ) + return( ret ); + break; + + default: + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + } + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Parse and fill a single X.509 certificate in DER format + */ +static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *buf, + size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end, *crt_end; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + // Use the original buffer until we figure out actual length + p = (unsigned char*) buf; + len = buflen; + end = p + len; + + /* + * Certificate ::= SEQUENCE { + * tbsCertificate TBSCertificate, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len > (size_t) ( end - p ) ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + crt_end = p + len; + + // Create and populate a new buffer for the raw field + crt->raw.len = crt_end - buf; + crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len ); + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, crt->raw.len ); + + // Direct pointers to the new buffer + p += crt->raw.len - len; + end = crt_end = p + len; + + /* + * TBSCertificate ::= SEQUENCE { + */ + crt->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + crt->tbs.len = end - crt->tbs.p; + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + * + * CertificateSerialNumber ::= INTEGER + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || + ( ret = mbedtls_x509_get_serial( &p, end, &crt->serial ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crt->sig_oid, + &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->version < 0 || crt->version > 2 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + crt->version++; + + if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1, + &crt->sig_md, &crt->sig_pk, + &crt->sig_opts ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * issuer Name + */ + crt->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->issuer_raw.len = p - crt->issuer_raw.p; + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + */ + if( ( ret = x509_get_dates( &p, end, &crt->valid_from, + &crt->valid_to ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * subject Name + */ + crt->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->subject_raw.len = p - crt->subject_raw.p; + + /* + * SubjectPublicKeyInfo + */ + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * extensions [3] EXPLICIT Extensions OPTIONAL + * -- If present, version shall be v3 + */ + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + +#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) + if( crt->version == 3 ) +#endif + { + ret = x509_get_crt_ext( &p, end, crt ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crt_end; + + /* + * } + * -- end of TBSCertificate + * + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->sig_oid.len != sig_oid2.len || + memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 || + sig_params1.tag != sig_params2.tag || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse one X.509 certificate in DER format from a buffer and add them to a + * chained list + */ +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, + size_t buflen ) +{ + int ret; + mbedtls_x509_crt *crt = chain, *prev = NULL; + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + while( crt->version != 0 && crt->next != NULL ) + { + prev = crt; + crt = crt->next; + } + + /* + * Add new certificate on the end of the chain if needed. + */ + if( crt->version != 0 && crt->next == NULL ) + { + crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( crt->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + prev = crt; + mbedtls_x509_crt_init( crt->next ); + crt = crt->next; + } + + if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 ) + { + if( prev ) + prev->next = NULL; + + if( crt != chain ) + mbedtls_free( crt ); + + return( ret ); + } + + return( 0 ); +} + +/* + * Parse one or more PEM certificates from a buffer and add them to the chained + * list + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int success = 0, first_error = 0, total_failed = 0; + int buf_format = MBEDTLS_X509_FORMAT_DER; +#endif + + /* + * Check for valid input + */ + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + /* + * Determine buffer content. Buffer contains either one DER certificate or + * one or more PEM certificates. + */ +#if defined(MBEDTLS_PEM_PARSE_C) + if( buflen != 0 && buf[buflen - 1] == '\0' && + strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL ) + { + buf_format = MBEDTLS_X509_FORMAT_PEM; + } + + if( buf_format == MBEDTLS_X509_FORMAT_DER ) + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#else + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) + if( buf_format == MBEDTLS_X509_FORMAT_PEM ) + { + int ret; + mbedtls_pem_context pem; + + /* 1 rather than 0 since the terminating NULL byte is counted in */ + while( buflen > 1 ) + { + size_t use_len; + mbedtls_pem_init( &pem ); + + /* If we get there, we know the string is null-terminated */ + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE-----", + "-----END CERTIFICATE-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + buflen -= use_len; + buf += use_len; + } + else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA ) + { + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + + /* + * PEM header and footer were found + */ + buflen -= use_len; + buf += use_len; + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + else + break; + + ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen ); + + mbedtls_pem_free( &pem ); + + if( ret != 0 ) + { + /* + * Quit parsing on a memory error + */ + if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED ) + return( ret ); + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + + success = 1; + } + } + + if( success ) + return( total_failed ); + else if( first_error ) + return( first_error ); + else + return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ); +#endif /* MBEDTLS_PEM_PARSE_C */ +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more certificates and add them to the chained list + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crt_parse( chain, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) +{ + int ret = 0; +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + int w_ret; + WCHAR szDir[MAX_PATH]; + char filename[MAX_PATH]; + char *p; + size_t len = strlen( path ); + + WIN32_FIND_DATAW file_data; + HANDLE hFind; + + if( len > MAX_PATH - 3 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( szDir, 0, sizeof(szDir) ); + memset( filename, 0, MAX_PATH ); + memcpy( filename, path, len ); + filename[len++] = '\\'; + p = filename + len; + filename[len++] = '*'; + + w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, + MAX_PATH - 3 ); + if( w_ret == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + hFind = FindFirstFileW( szDir, &file_data ); + if( hFind == INVALID_HANDLE_VALUE ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + + len = MAX_PATH - len; + do + { + memset( p, 0, len ); + + if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + continue; + + w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, + lstrlenW( file_data.cFileName ), + p, (int) len - 1, + NULL, NULL ); + if( w_ret == 0 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + w_ret = mbedtls_x509_crt_parse_file( chain, filename ); + if( w_ret < 0 ) + ret++; + else + ret += w_ret; + } + while( FindNextFileW( hFind, &file_data ) != 0 ); + + if( GetLastError() != ERROR_NO_MORE_FILES ) + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + +cleanup: + FindClose( hFind ); +#else /* _WIN32 */ + int t_ret; + int snp_ret; + struct stat sb; + struct dirent *entry; + char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; + DIR *dir = opendir( path ); + + if( dir == NULL ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 ) + { + closedir( dir ); + return( ret ); + } +#endif /* MBEDTLS_THREADING_C */ + + while( ( entry = readdir( dir ) ) != NULL ) + { + snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name, + "%s/%s", path, entry->d_name ); + + if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name ) + { + ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + goto cleanup; + } + else if( stat( entry_name, &sb ) == -1 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + if( !S_ISREG( sb.st_mode ) ) + continue; + + // Ignore parse errors + // + t_ret = mbedtls_x509_crt_parse_file( chain, entry_name ); + if( t_ret < 0 ) + ret++; + else + ret += t_ret; + } + +cleanup: + closedir( dir ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 ) + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; +#endif /* MBEDTLS_THREADING_C */ + +#endif /* _WIN32 */ + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +static int x509_info_subject_alt_name( char **buf, size_t *size, + const mbedtls_x509_sequence *subject_alt_name ) +{ + size_t i; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = subject_alt_name; + const char *sep = ""; + size_t sep_len = 0; + + while( cur != NULL ) + { + if( cur->buf.len + sep_len >= n ) + { + *p = '\0'; + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); + } + + n -= cur->buf.len + sep_len; + for( i = 0; i < sep_len; i++ ) + *p++ = sep[i]; + for( i = 0; i < cur->buf.len; i++ ) + *p++ = cur->buf.p[i]; + + sep = ", "; + sep_len = 2; + + cur = cur->next; + } + + *p = '\0'; + + *size = n; + *buf = p; + + return( 0 ); +} + +#define PRINT_ITEM(i) \ + { \ + ret = mbedtls_snprintf( p, n, "%s" i, sep ); \ + MBEDTLS_X509_SAFE_SNPRINTF; \ + sep = ", "; \ + } + +#define CERT_TYPE(type,name) \ + if( ns_cert_type & (type) ) \ + PRINT_ITEM( name ); + +static int x509_info_cert_type( char **buf, size_t *size, + unsigned char ns_cert_type ) +{ + int ret; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +#define KEY_USAGE(code,name) \ + if( key_usage & (code) ) \ + PRINT_ITEM( name ); + +static int x509_info_key_usage( char **buf, size_t *size, + unsigned int key_usage ) +{ + int ret; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" ); + KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" ); + KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +static int x509_info_ext_key_usage( char **buf, size_t *size, + const mbedtls_x509_sequence *extended_key_usage ) +{ + int ret; + const char *desc; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = extended_key_usage; + const char *sep = ""; + + while( cur != NULL ) + { + if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 ) + desc = "???"; + + ret = mbedtls_snprintf( p, n, "%s%s", sep, desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + + sep = ", "; + + cur = cur->next; + } + + *size = n; + *buf = p; + + return( 0 ); +} + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 18 +#define BC "18" +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ) +{ + int ret; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + if( NULL == crt ) + { + ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); + } + + ret = mbedtls_snprintf( p, n, "%scert. version : %d\n", + prefix, crt->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_snprintf( p, n, "%sserial number : ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &crt->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissued on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_from.year, crt->valid_from.mon, + crt->valid_from.day, crt->valid_from.hour, + crt->valid_from.min, crt->valid_from.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_to.year, crt->valid_to.mon, + crt->valid_to.day, crt->valid_to.hour, + crt->valid_to.min, crt->valid_to.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk, + crt->sig_md, crt->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* Key size */ + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &crt->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &crt->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* + * Optional extensions + */ + + if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS ) + { + ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix, + crt->ca_istrue ? "true" : "false" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( crt->max_pathlen > 0 ) + { + ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + } + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_subject_alt_name( &p, &n, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE ) + { + ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_ext_key_usage( &p, &n, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +struct x509_crt_verify_string { + int code; + const char *string; +}; + +static const struct x509_crt_verify_string x509_crt_verify_strings[] = { + { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" }, + { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, + { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" }, + { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" }, + { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" }, + { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" }, + { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" }, + { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" }, + { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" }, + { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, + { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, + { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, + { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { 0, NULL } +}; + +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ) +{ + int ret; + const struct x509_crt_verify_string *cur; + char *p = buf; + size_t n = size; + + for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ ) + { + if( ( flags & cur->code ) == 0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string ); + MBEDTLS_X509_SAFE_SNPRINTF; + flags ^= cur->code; + } + + if( flags != 0 ) + { + ret = mbedtls_snprintf( p, n, "%sUnknown reason " + "(this should not happen)\n", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ) +{ + unsigned int usage_must, usage_may; + unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY + | MBEDTLS_X509_KU_DECIPHER_ONLY; + + if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 ) + return( 0 ); + + usage_must = usage & ~may_mask; + + if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + usage_may = usage & may_mask; + + if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ) +{ + const mbedtls_x509_sequence *cur; + + /* Extension is not mandatory, absent means no restriction */ + if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 ) + return( 0 ); + + /* + * Look for the requested usage (or wildcard ANY) in our list + */ + for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next ) + { + const mbedtls_x509_buf *cur_oid = &cur->buf; + + if( cur_oid->len == usage_len && + memcmp( cur_oid->p, usage_oid, usage_len ) == 0 ) + { + return( 0 ); + } + + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 ) + return( 0 ); + } + + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); +} +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/* + * Return 1 if the certificate is revoked, or 0 otherwise. + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ) +{ + const mbedtls_x509_crl_entry *cur = &crl->entry; + + while( cur != NULL && cur->serial.len != 0 ) + { + if( crt->serial.len == cur->serial.len && + memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 ) + { + return( 1 ); + } + + cur = cur->next; + } + + return( 0 ); +} + +/* + * Check that the given certificate is not revoked according to the CRL. + * Skip validation if no CRL for the given CA is present. + */ +static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, + mbedtls_x509_crl *crl_list, + const mbedtls_x509_crt_profile *profile ) +{ + int flags = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + + if( ca == NULL ) + return( flags ); + + while( crl_list != NULL ) + { + if( crl_list->version == 0 || + x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 ) + { + crl_list = crl_list->next; + continue; + } + + /* + * Check if the CA is configured to sign CRLs + */ +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( mbedtls_x509_crt_check_key_usage( ca, + MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } +#endif + + /* + * Check if CRL is correctly signed by the trusted CA + */ + if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_MD; + + if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_PK; + + md_info = mbedtls_md_info_from_type( crl_list->sig_md ); + if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 ) + { + /* Note: this can't happen except after an internal error */ + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + if( x509_profile_check_key( profile, &ca->pk ) != 0 ) + flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, + crl_list->sig_md, hash, mbedtls_md_get_size( md_info ), + crl_list->sig.p, crl_list->sig.len ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + /* + * Check for validity of CRL (Do not drop out) + */ + if( mbedtls_x509_time_is_past( &crl_list->next_update ) ) + flags |= MBEDTLS_X509_BADCRL_EXPIRED; + + if( mbedtls_x509_time_is_future( &crl_list->this_update ) ) + flags |= MBEDTLS_X509_BADCRL_FUTURE; + + /* + * Check if certificate is revoked + */ + if( mbedtls_x509_crt_is_revoked( crt, crl_list ) ) + { + flags |= MBEDTLS_X509_BADCERT_REVOKED; + break; + } + + crl_list = crl_list->next; + } + + return( flags ); +} +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/* + * Check the signature of a certificate by its parent + */ +static int x509_crt_check_signature( const mbedtls_x509_crt *child, + mbedtls_x509_crt *parent, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + const mbedtls_md_info_t *md_info; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + + md_info = mbedtls_md_info_from_type( child->sig_md ); + if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 ) + { + /* Note: this can't happen except after an internal error */ + return( -1 ); + } + + /* Skip expensive computation on obvious mismatch */ + if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) ) + return( -1 ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA ) + { + return( mbedtls_pk_verify_restartable( &parent->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len, &rs_ctx->pk ) ); + } +#else + (void) rs_ctx; +#endif + + return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len ) ); +} + +/* + * Check if 'parent' is a suitable parent (signing CA) for 'child'. + * Return 0 if yes, -1 if not. + * + * top means parent is a locally-trusted certificate + */ +static int x509_crt_check_parent( const mbedtls_x509_crt *child, + const mbedtls_x509_crt *parent, + int top ) +{ + int need_ca_bit; + + /* Parent must be the issuer */ + if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 ) + return( -1 ); + + /* Parent must have the basicConstraints CA bit set as a general rule */ + need_ca_bit = 1; + + /* Exception: v1/v2 certificates that are locally trusted. */ + if( top && parent->version < 3 ) + need_ca_bit = 0; + + if( need_ca_bit && ! parent->ca_istrue ) + return( -1 ); + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( need_ca_bit && + mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 ) + { + return( -1 ); + } +#endif + + return( 0 ); +} + +/* + * Find a suitable parent for child in candidates, or return NULL. + * + * Here suitable is defined as: + * 1. subject name matches child's issuer + * 2. if necessary, the CA bit is set and key usage allows signing certs + * 3. for trusted roots, the signature is correct + * (for intermediates, the signature is checked and the result reported) + * 4. pathlen constraints are satisfied + * + * If there's a suitable candidate which is also time-valid, return the first + * such. Otherwise, return the first suitable candidate (or NULL if there is + * none). + * + * The rationale for this rule is that someone could have a list of trusted + * roots with two versions on the same root with different validity periods. + * (At least one user reported having such a list and wanted it to just work.) + * The reason we don't just require time-validity is that generally there is + * only one version, and if it's expired we want the flags to state that + * rather than NOT_TRUSTED, as would be the case if we required it here. + * + * The rationale for rule 3 (signature for trusted roots) is that users might + * have two versions of the same CA with different keys in their list, and the + * way we select the correct one is by checking the signature (as we don't + * rely on key identifier extensions). (This is one way users might choose to + * handle key rollover, another relies on self-issued certs, see [SIRO].) + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent + * - [in] candidates: chained list of potential parents + * - [out] r_parent: parent found (or NULL) + * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0 + * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top + * of the chain, 0 otherwise + * - [in] path_cnt: number of intermediates seen so far + * - [in] self_cnt: number of self-signed intermediates seen so far + * (will never be greater than path_cnt) + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - 0 on success + * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise + */ +static int x509_crt_find_parent_in( + mbedtls_x509_crt *child, + mbedtls_x509_crt *candidates, + mbedtls_x509_crt **r_parent, + int *r_signature_is_good, + int top, + unsigned path_cnt, + unsigned self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + int ret; + mbedtls_x509_crt *parent, *fallback_parent; + int signature_is_good, fallback_signature_is_good; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* did we have something in progress? */ + if( rs_ctx != NULL && rs_ctx->parent != NULL ) + { + /* restore saved state */ + parent = rs_ctx->parent; + fallback_parent = rs_ctx->fallback_parent; + fallback_signature_is_good = rs_ctx->fallback_signature_is_good; + + /* clear saved state */ + rs_ctx->parent = NULL; + rs_ctx->fallback_parent = NULL; + rs_ctx->fallback_signature_is_good = 0; + + /* resume where we left */ + goto check_signature; + } +#endif + + fallback_parent = NULL; + fallback_signature_is_good = 0; + + for( parent = candidates; parent != NULL; parent = parent->next ) + { + /* basic parenting skills (name, CA bit, key usage) */ + if( x509_crt_check_parent( child, parent, top ) != 0 ) + continue; + + /* +1 because stored max_pathlen is 1 higher that the actual value */ + if( parent->max_pathlen > 0 && + (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt ) + { + continue; + } + + /* Signature */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +check_signature: +#endif + ret = x509_crt_check_signature( child, parent, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->parent = parent; + rs_ctx->fallback_parent = fallback_parent; + rs_ctx->fallback_signature_is_good = fallback_signature_is_good; + + return( ret ); + } +#else + (void) ret; +#endif + + signature_is_good = ret == 0; + if( top && ! signature_is_good ) + continue; + + /* optional time check */ + if( mbedtls_x509_time_is_past( &parent->valid_to ) || + mbedtls_x509_time_is_future( &parent->valid_from ) ) + { + if( fallback_parent == NULL ) + { + fallback_parent = parent; + fallback_signature_is_good = signature_is_good; + } + + continue; + } + + *r_parent = parent; + *r_signature_is_good = signature_is_good; + + break; + } + + if( parent == NULL ) + { + *r_parent = fallback_parent; + *r_signature_is_good = fallback_signature_is_good; + } + + return( 0 ); +} + +/* + * Find a parent in trusted CAs or the provided chain, or return NULL. + * + * Searches in trusted CAs first, and return the first suitable parent found + * (see find_parent_in() for definition of suitable). + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent, followed + * by a chain of possible intermediates + * - [in] trust_ca: list of locally trusted certificates + * - [out] parent: parent found (or NULL) + * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0 + * - [out] signature_is_good: 1 if child signature by parent is valid, or 0 + * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child) + * - [in] self_cnt: number of self-signed certs in the chain so far + * (will always be no greater than path_cnt) + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - 0 on success + * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise + */ +static int x509_crt_find_parent( + mbedtls_x509_crt *child, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crt **parent, + int *parent_is_trusted, + int *signature_is_good, + unsigned path_cnt, + unsigned self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + int ret; + mbedtls_x509_crt *search_list; + + *parent_is_trusted = 1; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* restore then clear saved state if we have some stored */ + if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 ) + { + *parent_is_trusted = rs_ctx->parent_is_trusted; + rs_ctx->parent_is_trusted = -1; + } +#endif + + while( 1 ) { + search_list = *parent_is_trusted ? trust_ca : child->next; + + ret = x509_crt_find_parent_in( child, search_list, + parent, signature_is_good, + *parent_is_trusted, + path_cnt, self_cnt, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->parent_is_trusted = *parent_is_trusted; + return( ret ); + } +#else + (void) ret; +#endif + + /* stop here if found or already in second iteration */ + if( *parent != NULL || *parent_is_trusted == 0 ) + break; + + /* prepare second iteration */ + *parent_is_trusted = 0; + } + + /* extra precaution against mistakes in the caller */ + if( *parent == NULL ) + { + *parent_is_trusted = 0; + *signature_is_good = 0; + } + + return( 0 ); +} + +/* + * Check if an end-entity certificate is locally trusted + * + * Currently we require such certificates to be self-signed (actually only + * check for self-issued as self-signatures are not checked) + */ +static int x509_crt_check_ee_locally_trusted( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca ) +{ + mbedtls_x509_crt *cur; + + /* must be self-issued */ + if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 ) + return( -1 ); + + /* look for an exact match with trusted cert */ + for( cur = trust_ca; cur != NULL; cur = cur->next ) + { + if( crt->raw.len == cur->raw.len && + memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 ) + { + return( 0 ); + } + } + + /* too bad */ + return( -1 ); +} + +/* + * Build and verify a certificate chain + * + * Given a peer-provided list of certificates EE, C1, ..., Cn and + * a list of trusted certs R1, ... Rp, try to build and verify a chain + * EE, Ci1, ... Ciq [, Rj] + * such that every cert in the chain is a child of the next one, + * jumping to a trusted root as early as possible. + * + * Verify that chain and return it with flags for all issues found. + * + * Special cases: + * - EE == Rj -> return a one-element list containing it + * - EE, Ci1, ..., Ciq cannot be continued with a trusted root + * -> return that chain with NOT_TRUSTED set on Ciq + * + * Tests for (aspects of) this function should include at least: + * - trusted EE + * - EE -> trusted root + * - EE -> intermediate CA -> trusted root + * - if relevant: EE untrusted + * - if relevant: EE -> intermediate, untrusted + * with the aspect under test checked at each relevant level (EE, int, root). + * For some aspects longer chains are required, but usually length 2 is + * enough (but length 1 is not in general). + * + * Arguments: + * - [in] crt: the cert list EE, C1, ..., Cn + * - [in] trust_ca: the trusted list R1, ..., Rp + * - [in] ca_crl, profile: as in verify_with_profile() + * - [out] ver_chain: the built and verified chain + * Only valid when return value is 0, may contain garbage otherwise! + * Restart note: need not be the same when calling again to resume. + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - non-zero if the chain could not be fully built and examined + * - 0 is the chain was successfully built and examined, + * even if it was found to be invalid + */ +static int x509_crt_verify_chain( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + mbedtls_x509_crt_verify_chain *ver_chain, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + /* Don't initialize any of those variables here, so that the compiler can + * catch potential issues with jumping ahead when restarting */ + int ret; + uint32_t *flags; + mbedtls_x509_crt_verify_chain_item *cur; + mbedtls_x509_crt *child; + mbedtls_x509_crt *parent; + int parent_is_trusted; + int child_is_trusted; + int signature_is_good; + unsigned self_cnt; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* resume if we had an operation in progress */ + if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent ) + { + /* restore saved state */ + *ver_chain = rs_ctx->ver_chain; /* struct copy */ + self_cnt = rs_ctx->self_cnt; + + /* restore derived state */ + cur = &ver_chain->items[ver_chain->len - 1]; + child = cur->crt; + flags = &cur->flags; + + goto find_parent; + } +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + child = crt; + self_cnt = 0; + parent_is_trusted = 0; + child_is_trusted = 0; + + while( 1 ) { + /* Add certificate to the verification chain */ + cur = &ver_chain->items[ver_chain->len]; + cur->crt = child; + cur->flags = 0; + ver_chain->len++; + flags = &cur->flags; + + /* Check time-validity (all certificates) */ + if( mbedtls_x509_time_is_past( &child->valid_to ) ) + *flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &child->valid_from ) ) + *flags |= MBEDTLS_X509_BADCERT_FUTURE; + + /* Stop here for trusted roots (but not for trusted EE certs) */ + if( child_is_trusted ) + return( 0 ); + + /* Check signature algorithm: MD & PK algs */ + if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_MD; + + if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + /* Special case: EE certs that are locally trusted */ + if( ver_chain->len == 1 && + x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 ) + { + return( 0 ); + } + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +find_parent: +#endif + /* Look for a parent in trusted CAs or up the chain */ + ret = x509_crt_find_parent( child, trust_ca, &parent, + &parent_is_trusted, &signature_is_good, + ver_chain->len - 1, self_cnt, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->in_progress = x509_crt_rs_find_parent; + rs_ctx->self_cnt = self_cnt; + rs_ctx->ver_chain = *ver_chain; /* struct copy */ + + return( ret ); + } +#else + (void) ret; +#endif + + /* No parent? We're done here */ + if( parent == NULL ) + { + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + return( 0 ); + } + + /* Count intermediate self-issued (not necessarily self-signed) certs. + * These can occur with some strategies for key rollover, see [SIRO], + * and should be excluded from max_pathlen checks. */ + if( ver_chain->len != 1 && + x509_name_cmp( &child->issuer, &child->subject ) == 0 ) + { + self_cnt++; + } + + /* path_cnt is 0 for the first intermediate CA, + * and if parent is trusted it's not an intermediate CA */ + if( ! parent_is_trusted && + ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) + { + /* return immediately to avoid overflow the chain array */ + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + } + + /* signature was checked while searching parent */ + if( ! signature_is_good ) + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + + /* check size of signing key */ + if( x509_profile_check_key( profile, &parent->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the given crt */ + *flags |= x509_crt_verifycrl( child, parent, ca_crl, profile ); +#else + (void) ca_crl; +#endif + + /* prepare for next iteration */ + child = parent; + parent = NULL; + child_is_trusted = parent_is_trusted; + signature_is_good = 0; + } +} + +/* + * Check for CN match + */ +static int x509_crt_check_cn( const mbedtls_x509_buf *name, + const char *cn, size_t cn_len ) +{ + /* try exact match */ + if( name->len == cn_len && + x509_memcasecmp( cn, name->p, cn_len ) == 0 ) + { + return( 0 ); + } + + /* try wildcard match */ + if( x509_check_wildcard( cn, name ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Verify the requested CN - only call this if cn is not NULL! + */ +static void x509_crt_verify_name( const mbedtls_x509_crt *crt, + const char *cn, + uint32_t *flags ) +{ + const mbedtls_x509_name *name; + const mbedtls_x509_sequence *cur; + size_t cn_len = strlen( cn ); + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + for( cur = &crt->subject_alt_names; cur != NULL; cur = cur->next ) + { + if( x509_crt_check_cn( &cur->buf, cn, cn_len ) == 0 ) + break; + } + + if( cur == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + else + { + for( name = &crt->subject; name != NULL; name = name->next ) + { + if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 && + x509_crt_check_cn( &name->val, cn, cn_len ) == 0 ) + { + break; + } + } + + if( name == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } +} + +/* + * Merge the flags for all certs in the chain, after calling callback + */ +static int x509_crt_merge_flags_with_cb( + uint32_t *flags, + const mbedtls_x509_crt_verify_chain *ver_chain, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + int ret; + unsigned i; + uint32_t cur_flags; + const mbedtls_x509_crt_verify_chain_item *cur; + + for( i = ver_chain->len; i != 0; --i ) + { + cur = &ver_chain->items[i-1]; + cur_flags = cur->flags; + + if( NULL != f_vrfy ) + if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 ) + return( ret ); + + *flags |= cur_flags; + } + + return( 0 ); +} + +/* + * Verify the certificate validity (default profile, not restartable) + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl, + &mbedtls_x509_crt_profile_default, cn, flags, + f_vrfy, p_vrfy, NULL ) ); +} + +/* + * Verify the certificate validity (user-chosen profile, not restartable) + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl, + profile, cn, flags, f_vrfy, p_vrfy, NULL ) ); +} + +/* + * Verify the certificate validity, with profile, restartable version + * + * This function: + * - checks the requested CN (if any) + * - checks the type and size of the EE cert's key, + * as that isn't done as part of chain building/verification currently + * - builds and verifies the chain + * - then calls the callback and merges the flags + */ +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + int ret; + mbedtls_pk_type_t pk_type; + mbedtls_x509_crt_verify_chain ver_chain; + uint32_t ee_flags; + + *flags = 0; + ee_flags = 0; + x509_crt_verify_chain_reset( &ver_chain ); + + if( profile == NULL ) + { + ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; + goto exit; + } + + /* check name if requested */ + if( cn != NULL ) + x509_crt_verify_name( crt, cn, &ee_flags ); + + /* Check the type and size of the key */ + pk_type = mbedtls_pk_get_type( &crt->pk ); + + if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) + ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + if( x509_profile_check_key( profile, &crt->pk ) != 0 ) + ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + /* Check the chain */ + ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile, + &ver_chain, rs_ctx ); + + if( ret != 0 ) + goto exit; + + /* Merge end-entity flags */ + ver_chain.items[0].flags |= ee_flags; + + /* Build final flags, calling callback on the way if any */ + ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy ); + +exit: +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_x509_crt_restart_free( rs_ctx ); +#endif + + /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by + * the SSL module for authmode optional, but non-zero return from the + * callback means a fatal error so it shouldn't be ignored */ + if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) + ret = MBEDTLS_ERR_X509_FATAL_ERROR; + + if( ret != 0 ) + { + *flags = (uint32_t) -1; + return( ret ); + } + + if( *flags != 0 ) + return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); + + return( 0 ); +} + +/* + * Initialize a certificate chain + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ) +{ + memset( crt, 0, sizeof(mbedtls_x509_crt) ); +} + +/* + * Unallocate all certificate data + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) +{ + mbedtls_x509_crt *cert_cur = crt; + mbedtls_x509_crt *cert_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_sequence *seq_cur; + mbedtls_x509_sequence *seq_prv; + + if( crt == NULL ) + return; + + do + { + mbedtls_pk_free( &cert_cur->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( cert_cur->sig_opts ); +#endif + + name_cur = cert_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + name_cur = cert_cur->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + seq_cur = cert_cur->ext_key_usage.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + seq_cur = cert_cur->subject_alt_names.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + if( cert_cur->raw.p != NULL ) + { + mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len ); + mbedtls_free( cert_cur->raw.p ); + } + + cert_cur = cert_cur->next; + } + while( cert_cur != NULL ); + + cert_cur = crt; + do + { + cert_prv = cert_cur; + cert_cur = cert_cur->next; + + mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); + if( cert_prv != crt ) + mbedtls_free( cert_prv ); + } + while( cert_cur != NULL ); +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ) +{ + mbedtls_pk_restart_init( &ctx->pk ); + + ctx->parent = NULL; + ctx->fallback_parent = NULL; + ctx->fallback_signature_is_good = 0; + + ctx->parent_is_trusted = -1; + + ctx->in_progress = x509_crt_rs_none; + ctx->self_cnt = 0; + x509_crt_verify_chain_reset( &ctx->ver_chain ); +} + +/* + * Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_pk_restart_free( &ctx->pk ); + mbedtls_x509_crt_restart_init( ctx ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/external/mbedtls/library/x509_csr.c b/external/mbedtls/library/x509_csr.c new file mode 100644 index 0000000..663047d --- /dev/null +++ b/external/mbedtls/library/x509_csr.c @@ -0,0 +1,444 @@ +/* + * X.509 Certificate Signing Request (CSR) parsing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) + +#include "mbedtls/x509_csr.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* + * Version ::= INTEGER { v1(0) } + */ +static int x509_csr_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + } + + return( 0 ); +} + +/* + * Parse a CSR in DER format + */ +int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end; + mbedtls_x509_buf sig_params; + + memset( &sig_params, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL || buflen == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + mbedtls_x509_csr_init( csr ); + + /* + * first copy the raw DER data + */ + p = mbedtls_calloc( 1, len = buflen ); + + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + csr->raw.p = p; + csr->raw.len = len; + end = p + len; + + /* + * CertificationRequest ::= SEQUENCE { + * certificationRequestInfo CertificationRequestInfo, + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * CertificationRequestInfo ::= SEQUENCE { + */ + csr->cri.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + csr->cri.len = end - csr->cri.p; + + /* + * Version ::= INTEGER { v1(0) } + */ + if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( csr->version != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + csr->version++; + + /* + * subject Name + */ + csr->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + csr->subject_raw.len = p - csr->subject_raw.p; + + /* + * subjectPKInfo SubjectPublicKeyInfo + */ + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + /* + * attributes [0] Attributes + * + * The list of possible attributes is open-ended, though RFC 2985 + * (PKCS#9) defines a few in section 5.4. We currently don't support any, + * so we just ignore them. This is a safe thing to do as the worst thing + * that could happen is that we issue a certificate that does not match + * the requester's expectations - this cannot cause a violation of our + * signature policies. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + p += len; + + end = csr->raw.p + csr->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params, + &csr->sig_md, &csr->sig_pk, + &csr->sig_opts ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse a CSR, allowing for PEM or raw DER encoding + */ +int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int ret; + size_t use_len; + mbedtls_pem_context pem; +#endif + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL || buflen == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_PEM_PARSE_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( buf[buflen - 1] == '\0' ) + { + mbedtls_pem_init( &pem ); + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE REQUEST-----", + "-----END CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + if( ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN NEW CERTIFICATE REQUEST-----", + "-----END NEW CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + } + + if( ret == 0 ) + { + /* + * Was PEM encoded, parse the result + */ + ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ); + } + + mbedtls_pem_free( &pem ); + if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + } +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load a CSR into the structure + */ +int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_csr_parse( csr, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CSR. + */ +int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_csr *csr ) +{ + int ret; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCSR version : %d", + prefix, csr->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &csr->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md, + csr->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &csr->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &csr->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CSR + */ +void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ) +{ + memset( csr, 0, sizeof(mbedtls_x509_csr) ); +} + +/* + * Unallocate all CSR data + */ +void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ) +{ + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + + if( csr == NULL ) + return; + + mbedtls_pk_free( &csr->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( csr->sig_opts ); +#endif + + name_cur = csr->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + if( csr->raw.p != NULL ) + { + mbedtls_platform_zeroize( csr->raw.p, csr->raw.len ); + mbedtls_free( csr->raw.p ); + } + + mbedtls_platform_zeroize( csr, sizeof( mbedtls_x509_csr ) ); +} + +#endif /* MBEDTLS_X509_CSR_PARSE_C */ diff --git a/external/mbedtls/library/x509write_crt.c b/external/mbedtls/library/x509write_crt.c new file mode 100644 index 0000000..5462e83 --- /dev/null +++ b/external/mbedtls/library/x509write_crt.c @@ -0,0 +1,601 @@ +/* + * X.509 certificate writing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * References: + * - certificates: RFC 5280, updated by RFC 6818 + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/oid.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/sha1.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif /* MBEDTLS_PEM_WRITE_C */ + +/* + * For the currently used signature algorithms the buffer to store any signature + * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE) + */ +#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE +#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN +#else +#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif + +void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_x509write_cert ) ); + + mbedtls_mpi_init( &ctx->serial ); + ctx->version = MBEDTLS_X509_CRT_VERSION_3; +} + +void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) +{ + mbedtls_mpi_free( &ctx->serial ); + + mbedtls_asn1_free_named_data_list( &ctx->subject ); + mbedtls_asn1_free_named_data_list( &ctx->issuer ); + mbedtls_asn1_free_named_data_list( &ctx->extensions ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) ); +} + +void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, + int version ) +{ + ctx->version = version; +} + +void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, + mbedtls_md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, + mbedtls_pk_context *key ) +{ + ctx->subject_key = key; +} + +void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, + mbedtls_pk_context *key ) +{ + ctx->issuer_key = key; +} + +int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, + const char *subject_name ) +{ + return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); +} + +int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, + const char *issuer_name ) +{ + return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name ); +} + +int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, + const mbedtls_mpi *serial ) +{ + int ret; + + if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, + const char *not_before, + const char *not_after ) +{ + if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || + strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ) + { + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + } + strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); + strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); + ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + + return( 0 ); +} + +int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ) +{ + return( mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, + critical, val, val_len ) ); +} + +int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, + int is_ca, int max_pathlen ) +{ + int ret; + unsigned char buf[9]; + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + + if( is_ca && max_pathlen > 127 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + if( is_ca ) + { + if( max_pathlen >= 0 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, + max_pathlen ) ); + } + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( + mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, + MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ), + 0, buf + sizeof(buf) - len, len ) ); +} + +#if defined(MBEDTLS_SHA1_C) +int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ) +{ + int ret; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) ); + + ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, + buf + sizeof( buf ) - 20 ); + if( ret != 0 ) + return( ret ); + c = buf + sizeof( buf ) - 20; + len = 20; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); + + return mbedtls_x509write_crt_set_extension( ctx, + MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), + 0, buf + sizeof(buf) - len, len ); +} + +int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ) +{ + int ret; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof( buf ); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); + + ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, + buf + sizeof( buf ) - 20 ); + if( ret != 0 ) + return( ret ); + c = buf + sizeof( buf ) - 20; + len = 20; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return mbedtls_x509write_crt_set_extension( + ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), + 0, buf + sizeof( buf ) - len, len ); +} +#endif /* MBEDTLS_SHA1_C */ + +static size_t crt_get_unused_bits_for_named_bitstring( unsigned char bitstring, + size_t bit_offset ) +{ + size_t unused_bits; + + /* Count the unused bits removing trailing 0s */ + for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ ) + if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 ) + break; + + return( unused_bits ); +} + +int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, + unsigned int key_usage ) +{ + unsigned char buf[4], ku; + unsigned char *c; + int ret; + size_t unused_bits; + const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE | + MBEDTLS_X509_KU_NON_REPUDIATION | + MBEDTLS_X509_KU_KEY_ENCIPHERMENT | + MBEDTLS_X509_KU_DATA_ENCIPHERMENT | + MBEDTLS_X509_KU_KEY_AGREEMENT | + MBEDTLS_X509_KU_KEY_CERT_SIGN | + MBEDTLS_X509_KU_CRL_SIGN; + + /* Check that nothing other than the allowed flags is set */ + if( ( key_usage & ~allowed_bits ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + + c = buf + 4; + ku = (unsigned char)key_usage; + unused_bits = crt_get_unused_bits_for_named_bitstring( ku, 1 ); + ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 8 - unused_bits ); + + if( ret < 0 ) + return( ret ); + else if( ret < 3 || ret > 4 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + 1, c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + size_t unused_bits; + int ret; + + c = buf + 4; + + unused_bits = crt_get_unused_bits_for_named_bitstring( ns_cert_type, 0 ); + ret = mbedtls_asn1_write_bitstring( &c, + buf, + &ns_cert_type, + 8 - unused_bits ); + if( ret < 3 || ret > 4 ) + return( ret ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + 0, c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +static int x509_write_time( unsigned char **p, unsigned char *start, + const char *t, size_t size ) +{ + int ret; + size_t len = 0; + + /* + * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) + */ + if( t[0] == '2' && t[1] == '0' && t[2] < '5' ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) t + 2, + size - 2 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_UTC_TIME ) ); + } + else + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) t, + size ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_GENERALIZED_TIME ) ); + } + + return( (int) len ); +} + +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, + unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + unsigned char sig[SIGNATURE_MAX_SIZE]; + size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + mbedtls_pk_type_t pk_alg; + + /* + * Prepare data to be signed at the end of the target buffer + */ + c = buf + size; + + /* Signature algorithm needed in TBS, and later for actual signature */ + + /* There's no direct way of extracting a signature algorithm + * (represented as an element of mbedtls_pk_type_t) from a PK instance. */ + if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) ) + pk_alg = MBEDTLS_PK_RSA; + else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) ) + pk_alg = MBEDTLS_PK_ECDSA; + else + return( MBEDTLS_ERR_X509_INVALID_ALG ); + + if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + + /* Only for v3 */ + if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 ) + { + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_x509_write_extensions( &c, + buf, ctx->extensions ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); + } + + /* + * SubjectPublicKeyInfo + */ + MBEDTLS_ASN1_CHK_ADD( pub_len, + mbedtls_pk_write_pubkey_der( ctx->subject_key, + buf, c - buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_x509_write_names( &c, buf, + ctx->subject ) ); + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ + sub_len = 0; + + MBEDTLS_ASN1_CHK_ADD( sub_len, + x509_write_time( &c, buf, ctx->not_after, + MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); + + MBEDTLS_ASN1_CHK_ADD( sub_len, + x509_write_time( &c, buf, ctx->not_before, + MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); + + len += sub_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Issuer ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf, + ctx->issuer ) ); + + /* + * Signature ::= AlgorithmIdentifier + */ + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_algorithm_identifier( &c, buf, + sig_oid, strlen( sig_oid ), 0 ) ); + + /* + * Serial ::= INTEGER + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, + &ctx->serial ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + + /* Can be omitted for v1 */ + if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 ) + { + sub_len = 0; + MBEDTLS_ASN1_CHK_ADD( sub_len, + mbedtls_asn1_write_int( &c, buf, ctx->version ) ); + len += sub_len; + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_len( &c, buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Make signature + */ + + /* Compute hash of CRT. */ + if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, + len, hash ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, + hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + /* Move CRT to the front of the buffer to have space + * for the signature. */ + memmove( buf, c, len ); + c = buf + len; + + /* Add signature at the end of the buffer, + * making sure that it doesn't underflow + * into the CRT buffer. */ + c2 = buf + size; + MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, c, + sig_oid, sig_oid_len, sig, sig_len ) ); + + /* + * Memory layout after this step: + * + * buf c=buf+len c2 buf+size + * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm] + */ + + /* Move raw CRT to just before the signature. */ + c = c2 - len; + memmove( c, buf, len ); + + len += sig_and_oid_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" +#define PEM_END_CRT "-----END CERTIFICATE-----\n" + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, + unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t olen; + + if( ( ret = mbedtls_x509write_crt_der( crt, buf, size, + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, + buf + size - ret, ret, + buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_X509_CRT_WRITE_C */ diff --git a/external/mbedtls/library/x509write_csr.c b/external/mbedtls/library/x509write_csr.c new file mode 100644 index 0000000..60cf123 --- /dev/null +++ b/external/mbedtls/library/x509write_csr.c @@ -0,0 +1,385 @@ +/* + * X.509 Certificate Signing Request writing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * References: + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) + +#include "mbedtls/x509_csr.h" +#include "mbedtls/oid.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/platform_util.h" + +#include +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +/* + * For the currently used signature algorithms the buffer to store any signature + * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE) + */ +#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE +#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN +#else +#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_x509write_csr ) ); +} + +void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ) +{ + mbedtls_asn1_free_named_data_list( &ctx->subject ); + mbedtls_asn1_free_named_data_list( &ctx->extensions ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_csr ) ); +} + +void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ) +{ + ctx->key = key; +} + +int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, + const char *subject_name ) +{ + return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); +} + +int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ) +{ + return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, + 0, val, val_len ); +} + +static size_t csr_get_unused_bits_for_named_bitstring( unsigned char bitstring, + size_t bit_offset ) +{ + size_t unused_bits; + + /* Count the unused bits removing trailing 0s */ + for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ ) + if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 ) + break; + + return( unused_bits ); +} + +int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) +{ + unsigned char buf[4]; + unsigned char *c; + size_t unused_bits; + int ret; + + c = buf + 4; + + unused_bits = csr_get_unused_bits_for_named_bitstring( key_usage, 0 ); + ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 8 - unused_bits ); + + if( ret < 0 ) + return( ret ); + else if( ret < 3 || ret > 4 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + size_t unused_bits; + int ret; + + c = buf + 4; + + unused_bits = csr_get_unused_bits_for_named_bitstring( ns_cert_type, 0 ); + ret = mbedtls_asn1_write_bitstring( &c, + buf, + &ns_cert_type, + 8 - unused_bits ); + + if( ret < 0 ) + return( ret ); + else if( ret < 3 || ret > 4 ) + return( ret ); + + ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +static int x509write_csr_der_internal( mbedtls_x509write_csr *ctx, + unsigned char *buf, + size_t size, + unsigned char *sig, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + size_t pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + mbedtls_pk_type_t pk_alg; + + /* Write the CSR backwards starting from the end of buf */ + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, buf, + ctx->extensions ) ); + + if( len ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ); + + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_oid( + &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, + MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ); + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key, + buf, c - buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf, + ctx->subject ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Sign the written CSR data into the sig buffer + * Note: hash errors can happen only after an internal error + */ + ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); + if( ret != 0 ) + return( ret ); + + if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) ) + pk_alg = MBEDTLS_PK_RSA; + else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) ) + pk_alg = MBEDTLS_PK_ECDSA; + else + return( MBEDTLS_ERR_X509_INVALID_ALG ); + + if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } + + /* + * Move the written CSR data to the start of buf to create space for + * writing the signature into buf. + */ + memmove( buf, c, len ); + + /* + * Write sig and its OID into buf backwards from the end of buf. + * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len + * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed. + */ + c2 = buf + size; + MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, + mbedtls_x509_write_sig( &c2, buf + len, sig_oid, sig_oid_len, + sig, sig_len ) ); + + /* + * Compact the space between the CSR data and signature by moving the + * CSR data to the start of the signature. + */ + c2 -= len; + memmove( c2, buf, len ); + + /* ASN encode the total size and tag the CSR data with it. */ + len += sig_and_oid_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c2, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + /* Zero the unused bytes at the start of buf */ + memset( buf, 0, c2 - buf); + + return( (int) len ); +} + +int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, + size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char *sig; + + if( ( sig = mbedtls_calloc( 1, SIGNATURE_MAX_SIZE ) ) == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + ret = x509write_csr_der_internal( ctx, buf, size, sig, f_rng, p_rng ); + + mbedtls_free( sig ); + + return( ret ); +} + +#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" +#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char output_buf[4096]; + size_t olen = 0; + + if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf), + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_X509_CSR_WRITE_C */ diff --git a/external/mbedtls/library/xtea.c b/external/mbedtls/library/xtea.c new file mode 100644 index 0000000..4e62817 --- /dev/null +++ b/external/mbedtls/library/xtea.c @@ -0,0 +1,302 @@ +/* + * An 32-bit implementation of the XTEA algorithm + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_XTEA_C) + +#include "mbedtls/xtea.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_XTEA_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void mbedtls_xtea_init( mbedtls_xtea_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_xtea_context ) ); +} + +void mbedtls_xtea_free( mbedtls_xtea_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_xtea_context ) ); +} + +/* + * XTEA key schedule + */ +void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ) +{ + int i; + + memset( ctx, 0, sizeof(mbedtls_xtea_context) ); + + for( i = 0; i < 4; i++ ) + { + GET_UINT32_BE( ctx->k[i], key, i << 2 ); + } +} + +/* + * XTEA encrypt function + */ +int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, int mode, + const unsigned char input[8], unsigned char output[8]) +{ + uint32_t *k, v0, v1, i; + + k = ctx->k; + + GET_UINT32_BE( v0, input, 0 ); + GET_UINT32_BE( v1, input, 4 ); + + if( mode == MBEDTLS_XTEA_ENCRYPT ) + { + uint32_t sum = 0, delta = 0x9E3779B9; + + for( i = 0; i < 32; i++ ) + { + v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + sum += delta; + v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); + } + } + else /* MBEDTLS_XTEA_DECRYPT */ + { + uint32_t delta = 0x9E3779B9, sum = delta * 32; + + for( i = 0; i < 32; i++ ) + { + v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); + sum -= delta; + v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + } + } + + PUT_UINT32_BE( v0, output, 0 ); + PUT_UINT32_BE( v1, output, 4 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * XTEA-CBC buffer encryption/decryption + */ +int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, int mode, size_t length, + unsigned char iv[8], const unsigned char *input, + unsigned char *output) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_XTEA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_xtea_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_xtea_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* !MBEDTLS_XTEA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * XTEA tests vectors (non-official) + */ + +static const unsigned char xtea_test_key[6][16] = +{ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, + { 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 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char xtea_test_pt[6][8] = +{ + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 } +}; + +static const unsigned char xtea_test_ct[6][8] = +{ + { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }, + { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }, + { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } +}; + +/* + * Checkup routine + */ +int mbedtls_xtea_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char buf[8]; + mbedtls_xtea_context ctx; + + mbedtls_xtea_init( &ctx ); + for( i = 0; i < 6; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " XTEA test #%d: ", i + 1 ); + + memcpy( buf, xtea_test_pt[i], 8 ); + + mbedtls_xtea_setup( &ctx, xtea_test_key[i] ); + mbedtls_xtea_crypt_ecb( &ctx, MBEDTLS_XTEA_ENCRYPT, buf, buf ); + + if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_xtea_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_XTEA_C */ diff --git a/external/mbedtls/programs/CMakeLists.txt b/external/mbedtls/programs/CMakeLists.txt new file mode 100644 index 0000000..4cdae78 --- /dev/null +++ b/external/mbedtls/programs/CMakeLists.txt @@ -0,0 +1,8 @@ +add_subdirectory(aes) +add_subdirectory(hash) +add_subdirectory(pkey) +add_subdirectory(random) +add_subdirectory(ssl) +add_subdirectory(test) +add_subdirectory(x509) +add_subdirectory(util) diff --git a/external/mbedtls/programs/Makefile b/external/mbedtls/programs/Makefile new file mode 100644 index 0000000..d09949b --- /dev/null +++ b/external/mbedtls/programs/Makefile @@ -0,0 +1,306 @@ + +# To compile on SunOS: add "-lsocket -lnsl" to LDFLAGS +# To compile with PKCS11: add "-lpkcs11-helper" to LDFLAGS + +CFLAGS ?= -O2 +WARNING_CFLAGS ?= -Wall -W -Wdeclaration-after-statement +WARNING_CXXFLAGS ?= -Wall -W +LDFLAGS ?= + +LOCAL_CFLAGS = $(WARNING_CFLAGS) -I../include -D_FILE_OFFSET_BITS=64 +LOCAL_CXXFLAGS = $(WARNING_CXXFLAGS) -I../include -D_FILE_OFFSET_BITS=64 +LOCAL_LDFLAGS = -L../library \ + -lmbedtls$(SHARED_SUFFIX) \ + -lmbedx509$(SHARED_SUFFIX) \ + -lmbedcrypto$(SHARED_SUFFIX) + +ifndef SHARED +DEP=../library/libmbedcrypto.a ../library/libmbedx509.a ../library/libmbedtls.a +else +DEP=../library/libmbedcrypto.$(DLEXT) ../library/libmbedx509.$(DLEXT) ../library/libmbedtls.$(DLEXT) +endif + +ifdef DEBUG +LOCAL_CFLAGS += -g3 +endif + +# if we're running on Windows, build for Windows +ifdef WINDOWS +WINDOWS_BUILD=1 +endif + +ifdef WINDOWS_BUILD +DLEXT=dll +EXEXT=.exe +LOCAL_LDFLAGS += -lws2_32 +ifdef SHARED +SHARED_SUFFIX=.$(DLEXT) +endif +else +DLEXT ?= so +EXEXT= +SHARED_SUFFIX= +endif + +# Zlib shared library extensions: +ifdef ZLIB +LOCAL_LDFLAGS += -lz +endif + +APPS = aes/aescrypt2$(EXEXT) aes/crypt_and_hash$(EXEXT) \ + hash/hello$(EXEXT) hash/generic_sum$(EXEXT) \ + pkey/dh_client$(EXEXT) \ + pkey/dh_genprime$(EXEXT) pkey/dh_server$(EXEXT) \ + pkey/ecdh_curve25519$(EXEXT) \ + pkey/ecdsa$(EXEXT) pkey/gen_key$(EXEXT) \ + pkey/key_app$(EXEXT) pkey/key_app_writer$(EXEXT) \ + pkey/mpi_demo$(EXEXT) pkey/pk_decrypt$(EXEXT) \ + pkey/pk_encrypt$(EXEXT) pkey/pk_sign$(EXEXT) \ + pkey/pk_verify$(EXEXT) pkey/rsa_genkey$(EXEXT) \ + pkey/rsa_decrypt$(EXEXT) pkey/rsa_encrypt$(EXEXT) \ + pkey/rsa_sign$(EXEXT) pkey/rsa_verify$(EXEXT) \ + pkey/rsa_sign_pss$(EXEXT) pkey/rsa_verify_pss$(EXEXT) \ + ssl/dtls_client$(EXEXT) ssl/dtls_server$(EXEXT) \ + ssl/ssl_client1$(EXEXT) ssl/ssl_client2$(EXEXT) \ + ssl/ssl_server$(EXEXT) ssl/ssl_server2$(EXEXT) \ + ssl/ssl_fork_server$(EXEXT) ssl/mini_client$(EXEXT) \ + ssl/ssl_mail_client$(EXEXT) random/gen_entropy$(EXEXT) \ + random/gen_random_havege$(EXEXT) \ + random/gen_random_ctr_drbg$(EXEXT) \ + test/benchmark$(EXEXT) \ + test/selftest$(EXEXT) test/udp_proxy$(EXEXT) \ + test/zeroize$(EXEXT) \ + test/query_compile_time_config$(EXEXT) \ + util/pem2der$(EXEXT) util/strerror$(EXEXT) \ + x509/cert_app$(EXEXT) x509/crl_app$(EXEXT) \ + x509/cert_req$(EXEXT) x509/cert_write$(EXEXT) \ + x509/req_app$(EXEXT) + +ifdef PTHREAD +APPS += ssl/ssl_pthread_server$(EXEXT) +endif + +ifdef TEST_CPP +APPS += test/cpp_dummy_build$(EXEXT) +endif + +.SILENT: + +.PHONY: all clean list + +all: $(APPS) + +$(DEP): + $(MAKE) -C ../library + +aes/aescrypt2$(EXEXT): aes/aescrypt2.c $(DEP) + echo " CC aes/aescrypt2.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) aes/aescrypt2.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +aes/crypt_and_hash$(EXEXT): aes/crypt_and_hash.c $(DEP) + echo " CC aes/crypt_and_hash.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) aes/crypt_and_hash.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +hash/hello$(EXEXT): hash/hello.c $(DEP) + echo " CC hash/hello.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) hash/hello.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +hash/generic_sum$(EXEXT): hash/generic_sum.c $(DEP) + echo " CC hash/generic_sum.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) hash/generic_sum.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/dh_client$(EXEXT): pkey/dh_client.c $(DEP) + echo " CC pkey/dh_client.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/dh_client.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/dh_genprime$(EXEXT): pkey/dh_genprime.c $(DEP) + echo " CC pkey/dh_genprime.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/dh_genprime.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/dh_server$(EXEXT): pkey/dh_server.c $(DEP) + echo " CC pkey/dh_server.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/dh_server.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/ecdh_curve25519$(EXEXT): pkey/ecdh_curve25519.c $(DEP) + echo " CC pkey/ecdh_curve25519.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/ecdh_curve25519.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/ecdsa$(EXEXT): pkey/ecdsa.c $(DEP) + echo " CC pkey/ecdsa.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/ecdsa.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/gen_key$(EXEXT): pkey/gen_key.c $(DEP) + echo " CC pkey/gen_key.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/gen_key.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/key_app$(EXEXT): pkey/key_app.c $(DEP) + echo " CC pkey/key_app.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/key_app.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/key_app_writer$(EXEXT): pkey/key_app_writer.c $(DEP) + echo " CC pkey/key_app_writer.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/key_app_writer.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/mpi_demo$(EXEXT): pkey/mpi_demo.c $(DEP) + echo " CC pkey/mpi_demo.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/mpi_demo.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/pk_decrypt$(EXEXT): pkey/pk_decrypt.c $(DEP) + echo " CC pkey/pk_decrypt.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/pk_decrypt.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/pk_encrypt$(EXEXT): pkey/pk_encrypt.c $(DEP) + echo " CC pkey/pk_encrypt.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/pk_encrypt.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/pk_sign$(EXEXT): pkey/pk_sign.c $(DEP) + echo " CC pkey/pk_sign.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/pk_sign.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/pk_verify$(EXEXT): pkey/pk_verify.c $(DEP) + echo " CC pkey/pk_verify.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/pk_verify.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/rsa_genkey$(EXEXT): pkey/rsa_genkey.c $(DEP) + echo " CC pkey/rsa_genkey.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/rsa_genkey.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/rsa_sign$(EXEXT): pkey/rsa_sign.c $(DEP) + echo " CC pkey/rsa_sign.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/rsa_sign.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/rsa_verify$(EXEXT): pkey/rsa_verify.c $(DEP) + echo " CC pkey/rsa_verify.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/rsa_verify.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/rsa_sign_pss$(EXEXT): pkey/rsa_sign_pss.c $(DEP) + echo " CC pkey/rsa_sign_pss.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/rsa_sign_pss.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/rsa_verify_pss$(EXEXT): pkey/rsa_verify_pss.c $(DEP) + echo " CC pkey/rsa_verify_pss.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/rsa_verify_pss.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/rsa_decrypt$(EXEXT): pkey/rsa_decrypt.c $(DEP) + echo " CC pkey/rsa_decrypt.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/rsa_decrypt.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +pkey/rsa_encrypt$(EXEXT): pkey/rsa_encrypt.c $(DEP) + echo " CC pkey/rsa_encrypt.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) pkey/rsa_encrypt.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +random/gen_entropy$(EXEXT): random/gen_entropy.c $(DEP) + echo " CC random/gen_entropy.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) random/gen_entropy.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +random/gen_random_havege$(EXEXT): random/gen_random_havege.c $(DEP) + echo " CC random/gen_random_havege.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) random/gen_random_havege.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +random/gen_random_ctr_drbg$(EXEXT): random/gen_random_ctr_drbg.c $(DEP) + echo " CC random/gen_random_ctr_drbg.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) random/gen_random_ctr_drbg.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/dtls_client$(EXEXT): ssl/dtls_client.c $(DEP) + echo " CC ssl/dtls_client.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/dtls_client.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/dtls_server$(EXEXT): ssl/dtls_server.c $(DEP) + echo " CC ssl/dtls_server.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/dtls_server.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/ssl_client1$(EXEXT): ssl/ssl_client1.c $(DEP) + echo " CC ssl/ssl_client1.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_client1.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/ssl_client2$(EXEXT): ssl/ssl_client2.c ssl/query_config.c $(DEP) + echo " CC ssl/ssl_client2.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_client2.c ssl/query_config.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/ssl_server$(EXEXT): ssl/ssl_server.c $(DEP) + echo " CC ssl/ssl_server.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_server.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/ssl_server2$(EXEXT): ssl/ssl_server2.c ssl/query_config.c $(DEP) + echo " CC ssl/ssl_server2.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_server2.c ssl/query_config.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/ssl_fork_server$(EXEXT): ssl/ssl_fork_server.c $(DEP) + echo " CC ssl/ssl_fork_server.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_fork_server.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/ssl_pthread_server$(EXEXT): ssl/ssl_pthread_server.c $(DEP) + echo " CC ssl/ssl_pthread_server.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_pthread_server.c $(LOCAL_LDFLAGS) -lpthread $(LDFLAGS) -o $@ + +ssl/ssl_mail_client$(EXEXT): ssl/ssl_mail_client.c $(DEP) + echo " CC ssl/ssl_mail_client.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_mail_client.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/mini_client$(EXEXT): ssl/mini_client.c $(DEP) + echo " CC ssl/mini_client.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/mini_client.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +test/benchmark$(EXEXT): test/benchmark.c $(DEP) + echo " CC test/benchmark.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/benchmark.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +test/cpp_dummy_build$(EXEXT): test/cpp_dummy_build.cpp $(DEP) + echo " CXX test/cpp_dummy_build.cpp" + $(CXX) $(LOCAL_CXXFLAGS) $(CXXFLAGS) test/cpp_dummy_build.cpp $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +test/selftest$(EXEXT): test/selftest.c $(DEP) + echo " CC test/selftest.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/selftest.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +test/udp_proxy$(EXEXT): test/udp_proxy.c $(DEP) + echo " CC test/udp_proxy.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/udp_proxy.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +test/zeroize$(EXEXT): test/zeroize.c $(DEP) + echo " CC test/zeroize.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/zeroize.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +test/query_compile_time_config$(EXEXT): test/query_compile_time_config.c ssl/query_config.c $(DEP) + echo " CC test/query_compile_time_config.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/query_compile_time_config.c ssl/query_config.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +util/pem2der$(EXEXT): util/pem2der.c $(DEP) + echo " CC util/pem2der.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) util/pem2der.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +util/strerror$(EXEXT): util/strerror.c $(DEP) + echo " CC util/strerror.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) util/strerror.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +x509/cert_app$(EXEXT): x509/cert_app.c $(DEP) + echo " CC x509/cert_app.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/cert_app.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +x509/cert_write$(EXEXT): x509/cert_write.c $(DEP) + echo " CC x509/cert_write.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/cert_write.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +x509/crl_app$(EXEXT): x509/crl_app.c $(DEP) + echo " CC x509/crl_app.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/crl_app.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +x509/cert_req$(EXEXT): x509/cert_req.c $(DEP) + echo " CC x509/cert_req.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/cert_req.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +x509/req_app$(EXEXT): x509/req_app.c $(DEP) + echo " CC x509/req_app.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/req_app.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +clean: +ifndef WINDOWS + rm -f $(APPS) + -rm -f ssl/ssl_pthread_server$(EXEXT) + -rm -f test/cpp_dummy_build$(EXEXT) +else + del /S /Q /F *.o *.exe +endif + +list: + echo $(APPS) diff --git a/external/mbedtls/programs/README.md b/external/mbedtls/programs/README.md new file mode 100644 index 0000000..d26349d --- /dev/null +++ b/external/mbedtls/programs/README.md @@ -0,0 +1,123 @@ +Mbed TLS sample programs +======================== + +This subdirectory mostly contains sample programs that illustrate specific features of the library, as well as a few test and support programs. + +## Symmetric cryptography (AES) examples + +* [`aes/aescrypt2.c`](aes/aescrypt2.c): file encryption and authentication with a key derived from a low-entropy secret, demonstrating the low-level AES interface, the digest interface and HMAC. + Warning: this program illustrates how to use low-level functions in the library. It should not be taken as an example of how to build a secure encryption mechanism. To derive a key from a low-entropy secret such as a password, use a standard key stretching mechanism such as PBKDF2 (provided by the `pkcs5` module). To encrypt and authenticate data, use a standard mode such as GCM or CCM (both available as library module). + +* [`aes/crypt_and_hash.c`](aes/crypt_and_hash.c): file encryption and authentication, demonstrating the generic cipher interface and the generic hash interface. + +## Hash (digest) examples + +* [`hash/generic_sum.c`](hash/generic_sum.c): file hash calculator and verifier, demonstrating the message digest (`md`) interface. + +* [`hash/hello.c`](hash/hello.c): hello-world program for MD5. + +## Public-key cryptography examples + +### Generic public-key cryptography (`pk`) examples + +* [`pkey/gen_key.c`](pkey/gen_key.c): generates a key for any of the supported public-key algorithms (RSA or ECC) and writes it to a file that can be used by the other pk sample programs. + +* [`pkey/key_app.c`](pkey/key_app.c): loads a PEM or DER public key or private key file and dumps its content. + +* [`pkey/key_app_writer.c`](pkey/key_app_writer.c): loads a PEM or DER public key or private key file and writes it to a new PEM or DER file. + +* [`pkey/pk_encrypt.c`](pkey/pk_encrypt.c), [`pkey/pk_decrypt.c`](pkey/pk_decrypt.c): loads a PEM or DER public/private key file and uses the key to encrypt/decrypt a short string through the generic public-key interface. + +* [`pkey/pk_sign.c`](pkey/pk_sign.c), [`pkey/pk_verify.c`](pkey/pk_verify.c): loads a PEM or DER private/public key file and uses the key to sign/verify a short string. + +### ECDSA and RSA signature examples + +* [`pkey/ecdsa.c`](pkey/ecdsa.c): generates an ECDSA key, signs a fixed message and verifies the signature. + +* [`pkey/rsa_encrypt.c`](pkey/rsa_encrypt.c), [`pkey/rsa_decrypt.c`](pkey/rsa_decrypt.c): loads an RSA public/private key and uses it to encrypt/decrypt a short string through the low-level RSA interface. + +* [`pkey/rsa_genkey.c`](pkey/rsa_genkey.c): generates an RSA key and writes it to a file that can be used with the other RSA sample programs. + +* [`pkey/rsa_sign.c`](pkey/rsa_sign.c), [`pkey/rsa_verify.c`](pkey/rsa_verify.c): loads an RSA private/public key and uses it to sign/verify a short string with the RSA PKCS#1 v1.5 algorithm. + +* [`pkey/rsa_sign_pss.c`](pkey/rsa_sign_pss.c), [`pkey/rsa_verify_pss.c`](pkey/rsa_verify_pss.c): loads an RSA private/public key and uses it to sign/verify a short string with the RSASSA-PSS algorithm. + +### Diffie-Hellman key exchange examples + +* [`pkey/dh_client.c`](pkey/dh_client.c), [`pkey/dh_server.c`](pkey/dh_server.c): secure channel demonstrators (client, server). This pair of programs illustrates how to set up a secure channel using RSA for authentication and Diffie-Hellman to generate a shared AES session key. + +* [`pkey/ecdh_curve25519.c`](pkey/ecdh_curve25519.c): demonstration of a elliptic curve Diffie-Hellman (ECDH) key agreement. + +### Bignum (`mpi`) usage examples + +* [`pkey/dh_genprime.c`](pkey/dh_genprime.c): shows how to use the bignum (`mpi`) interface to generate Diffie-Hellman parameters. + +* [`pkey/mpi_demo.c`](pkey/mpi_demo.c): demonstrates operations on big integers. + +## Random number generator (RNG) examples + +* [`random/gen_entropy.c`](random/gen_entropy.c): shows how to use the default entropy sources to generate random data. + Note: most applications should only use the entropy generator to seed a cryptographic pseudorandom generator, as illustrated by `random/gen_random_ctr_drbg.c`. + +* [`random/gen_random_ctr_drbg.c`](random/gen_random_ctr_drbg.c): shows how to use the default entropy sources to seed a pseudorandom generator, and how to use the resulting random generator to generate random data. + +* [`random/gen_random_havege.c`](random/gen_random_havege.c): demonstrates the HAVEGE entropy collector. + +## SSL/TLS examples + +### SSL/TLS sample applications + +* [`ssl/dtls_client.c`](ssl/dtls_client.c): a simple DTLS client program, which sends one datagram to the server and reads one datagram in response. + +* [`ssl/dtls_server.c`](ssl/dtls_server.c): a simple DTLS server program, which expects one datagram from the client and writes one datagram in response. This program supports DTLS cookies for hello verification. + +* [`ssl/mini_client.c`](ssl/mini_client.c): a minimalistic SSL client, which sends a short string and disconnects. This is primarily intended as a benchmark; for a better example of a typical TLS client, see `ssl/ssl_client1.c`. + +* [`ssl/ssl_client1.c`](ssl/ssl_client1.c): a simple HTTPS client that sends a fixed request and displays the response. + +* [`ssl/ssl_fork_server.c`](ssl/ssl_fork_server.c): a simple HTTPS server using one process per client to send a fixed response. This program requires a Unix/POSIX environment implementing the `fork` system call. + +* [`ssl/ssl_mail_client.c`](ssl/ssl_mail_client.c): a simple SMTP-over-TLS or SMTP-STARTTLS client. This client sends an email with fixed content. + +* [`ssl/ssl_pthread_server.c`](ssl/ssl_pthread_server.c): a simple HTTPS server using one thread per client to send a fixed response. This program requires the pthread library. + +* [`ssl/ssl_server.c`](ssl/ssl_server.c): a simple HTTPS server that sends a fixed response. It serves a single client at a time. + +### SSL/TLS feature demonstrators + +Note: unlike most of the other programs under the `programs/` directory, these two programs are not intended as a basis for writing an application. They combine most of the features supported by the library, and most applications require only a few features. To write a new application, we recommended that you start with `ssl_client1.c` or `ssl_server.c`, and then look inside `ssl/ssl_client2.c` or `ssl/ssl_server2.c` to see how to use the specific features that your application needs. + +* [`ssl/ssl_client2.c`](ssl/ssl_client2.c): an HTTPS client that sends a fixed request and displays the response, with options to select TLS protocol features and Mbed TLS library features. + +* [`ssl/ssl_server2.c`](ssl/ssl_server2.c): an HTTPS server that sends a fixed response, with options to select TLS protocol features and Mbed TLS library features. + +In addition to providing options for testing client-side features, the `ssl_client2` program has options that allow you to trigger certain behaviors in the server. For example, there are options to select ciphersuites, or to force a renegotiation. These options are useful for testing the corresponding features in a TLS server. Likewise, `ssl_server2` has options to activate certain behaviors that are useful for testing a TLS client. + +## Test utilities + +* [`test/benchmark.c`](test/benchmark.c): benchmark for cryptographic algorithms. + +* [`test/selftest.c`](test/selftest.c): runs the self-test function in each library module. + +* [`test/udp_proxy.c`](test/udp_proxy.c): a UDP proxy that can inject certain failures (delay, duplicate, drop). Useful for testing DTLS. + +* [`test/zeroize.c`](test/zeroize.c): a test program for `mbedtls_platform_zeroize`, used by [`tests/scripts/test_zeroize.gdb`](tests/scripts/test_zeroize.gdb). + +## Development utilities + +* [`util/pem2der.c`](util/pem2der.c): a PEM to DER converter. Mbed TLS can read PEM files directly, but this utility can be useful for interacting with other tools or with minimal Mbed TLS builds that lack PEM support. + +* [`util/strerror.c`](util/strerror.c): prints the error description corresponding to an integer status returned by an Mbed TLS function. + +## X.509 certificate examples + +* [`x509/cert_app.c`](x509/cert_app.c): connects to a TLS server and verifies its certificate chain. + +* [`x509/cert_req.c`](x509/cert_req.c): generates a certificate signing request (CSR) for a private key. + +* [`x509/cert_write.c`](x509/cert_write.c): signs a certificate signing request, or self-signs a certificate. + +* [`x509/crl_app.c`](x509/crl_app.c): loads and dumps a certificate revocation list (CRL). + +* [`x509/req_app.c`](x509/req_app.c): loads and dumps a certificate signing request (CSR). + diff --git a/external/mbedtls/programs/aes/CMakeLists.txt b/external/mbedtls/programs/aes/CMakeLists.txt new file mode 100644 index 0000000..f5a0caa --- /dev/null +++ b/external/mbedtls/programs/aes/CMakeLists.txt @@ -0,0 +1,9 @@ +add_executable(aescrypt2 aescrypt2.c) +target_link_libraries(aescrypt2 mbedtls) + +add_executable(crypt_and_hash crypt_and_hash.c) +target_link_libraries(crypt_and_hash mbedtls) + +install(TARGETS aescrypt2 crypt_and_hash + DESTINATION "bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/external/mbedtls/programs/aes/aescrypt2.c b/external/mbedtls/programs/aes/aescrypt2.c new file mode 100644 index 0000000..8b44aad --- /dev/null +++ b/external/mbedtls/programs/aes/aescrypt2.c @@ -0,0 +1,495 @@ +/* + * AES-256 file encryption program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* Enable definition of fileno() even when compiling with -std=c99. Must be + * set before config.h, which pulls in glibc's features.h indirectly. + * Harmless on other platforms. */ +#define _POSIX_C_SOURCE 1 + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#include "mbedtls/aes.h" +#include "mbedtls/md.h" +#include "mbedtls/platform_util.h" + +#include +#include +#include + +#if defined(_WIN32) +#include +#if !defined(_WIN32_WCE) +#include +#endif +#else +#include +#include +#endif + +#define MODE_ENCRYPT 0 +#define MODE_DECRYPT 1 + +#define USAGE \ + "\n aescrypt2 \n" \ + "\n : 0 = encrypt, 1 = decrypt\n" \ + "\n example: aescrypt2 0 file file.aes hex:E76B2413958B00E193\n" \ + "\n" + +#if !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_MD_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_AES_C and/or MBEDTLS_SHA256_C " + "and/or MBEDTLS_FS_IO and/or MBEDTLS_MD_C " + "not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +int main( int argc, char *argv[] ) +{ + int ret = 0; + int exit_code = MBEDTLS_EXIT_FAILURE; + + unsigned int i, n; + int mode, lastn; + size_t keylen; + FILE *fkey, *fin = NULL, *fout = NULL; + + char *p; + + unsigned char IV[16]; + unsigned char tmp[16]; + unsigned char key[512]; + unsigned char digest[32]; + unsigned char buffer[1024]; + unsigned char diff; + + mbedtls_aes_context aes_ctx; + mbedtls_md_context_t sha_ctx; + +#if defined(_WIN32_WCE) + long filesize, offset; +#elif defined(_WIN32) + LARGE_INTEGER li_size; + __int64 filesize, offset; +#else + off_t filesize, offset; +#endif + + mbedtls_aes_init( &aes_ctx ); + mbedtls_md_init( &sha_ctx ); + + ret = mbedtls_md_setup( &sha_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 1 ); + if( ret != 0 ) + { + mbedtls_printf( " ! mbedtls_md_setup() returned -0x%04x\n", -ret ); + goto exit; + } + + /* + * Parse the command-line arguments. + */ + if( argc != 5 ) + { + mbedtls_printf( USAGE ); + +#if defined(_WIN32) + mbedtls_printf( "\n Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + goto exit; + } + + mode = atoi( argv[1] ); + memset( IV, 0, sizeof( IV ) ); + memset( key, 0, sizeof( key ) ); + memset( digest, 0, sizeof( digest ) ); + memset( buffer, 0, sizeof( buffer ) ); + + if( mode != MODE_ENCRYPT && mode != MODE_DECRYPT ) + { + mbedtls_fprintf( stderr, "invalide operation mode\n" ); + goto exit; + } + + if( strcmp( argv[2], argv[3] ) == 0 ) + { + mbedtls_fprintf( stderr, "input and output filenames must differ\n" ); + goto exit; + } + + if( ( fin = fopen( argv[2], "rb" ) ) == NULL ) + { + mbedtls_fprintf( stderr, "fopen(%s,rb) failed\n", argv[2] ); + goto exit; + } + + if( ( fout = fopen( argv[3], "wb+" ) ) == NULL ) + { + mbedtls_fprintf( stderr, "fopen(%s,wb+) failed\n", argv[3] ); + goto exit; + } + + /* + * Read the secret key from file or command line + */ + if( ( fkey = fopen( argv[4], "rb" ) ) != NULL ) + { + keylen = fread( key, 1, sizeof( key ), fkey ); + fclose( fkey ); + } + else + { + if( memcmp( argv[4], "hex:", 4 ) == 0 ) + { + p = &argv[4][4]; + keylen = 0; + + while( sscanf( p, "%02X", &n ) > 0 && + keylen < (int) sizeof( key ) ) + { + key[keylen++] = (unsigned char) n; + p += 2; + } + } + else + { + keylen = strlen( argv[4] ); + + if( keylen > (int) sizeof( key ) ) + keylen = (int) sizeof( key ); + + memcpy( key, argv[4], keylen ); + } + } + +#if defined(_WIN32_WCE) + filesize = fseek( fin, 0L, SEEK_END ); +#else +#if defined(_WIN32) + /* + * Support large files (> 2Gb) on Win32 + */ + li_size.QuadPart = 0; + li_size.LowPart = + SetFilePointer( (HANDLE) _get_osfhandle( _fileno( fin ) ), + li_size.LowPart, &li_size.HighPart, FILE_END ); + + if( li_size.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR ) + { + mbedtls_fprintf( stderr, "SetFilePointer(0,FILE_END) failed\n" ); + goto exit; + } + + filesize = li_size.QuadPart; +#else + if( ( filesize = lseek( fileno( fin ), 0, SEEK_END ) ) < 0 ) + { + perror( "lseek" ); + goto exit; + } +#endif +#endif + + if( fseek( fin, 0, SEEK_SET ) < 0 ) + { + mbedtls_fprintf( stderr, "fseek(0,SEEK_SET) failed\n" ); + goto exit; + } + + if( mode == MODE_ENCRYPT ) + { + /* + * Generate the initialization vector as: + * IV = SHA-256( filesize || filename )[0..15] + */ + for( i = 0; i < 8; i++ ) + buffer[i] = (unsigned char)( filesize >> ( i << 3 ) ); + + p = argv[2]; + + mbedtls_md_starts( &sha_ctx ); + mbedtls_md_update( &sha_ctx, buffer, 8 ); + mbedtls_md_update( &sha_ctx, (unsigned char *) p, strlen( p ) ); + mbedtls_md_finish( &sha_ctx, digest ); + + memcpy( IV, digest, 16 ); + + /* + * The last four bits in the IV are actually used + * to store the file size modulo the AES block size. + */ + lastn = (int)( filesize & 0x0F ); + + IV[15] = (unsigned char) + ( ( IV[15] & 0xF0 ) | lastn ); + + /* + * Append the IV at the beginning of the output. + */ + if( fwrite( IV, 1, 16, fout ) != 16 ) + { + mbedtls_fprintf( stderr, "fwrite(%d bytes) failed\n", 16 ); + goto exit; + } + + /* + * Hash the IV and the secret key together 8192 times + * using the result to setup the AES context and HMAC. + */ + memset( digest, 0, 32 ); + memcpy( digest, IV, 16 ); + + for( i = 0; i < 8192; i++ ) + { + mbedtls_md_starts( &sha_ctx ); + mbedtls_md_update( &sha_ctx, digest, 32 ); + mbedtls_md_update( &sha_ctx, key, keylen ); + mbedtls_md_finish( &sha_ctx, digest ); + } + + mbedtls_aes_setkey_enc( &aes_ctx, digest, 256 ); + mbedtls_md_hmac_starts( &sha_ctx, digest, 32 ); + + /* + * Encrypt and write the ciphertext. + */ + for( offset = 0; offset < filesize; offset += 16 ) + { + n = ( filesize - offset > 16 ) ? 16 : (int) + ( filesize - offset ); + + if( fread( buffer, 1, n, fin ) != (size_t) n ) + { + mbedtls_fprintf( stderr, "fread(%d bytes) failed\n", n ); + goto exit; + } + + for( i = 0; i < 16; i++ ) + buffer[i] = (unsigned char)( buffer[i] ^ IV[i] ); + + mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, buffer, buffer ); + mbedtls_md_hmac_update( &sha_ctx, buffer, 16 ); + + if( fwrite( buffer, 1, 16, fout ) != 16 ) + { + mbedtls_fprintf( stderr, "fwrite(%d bytes) failed\n", 16 ); + goto exit; + } + + memcpy( IV, buffer, 16 ); + } + + /* + * Finally write the HMAC. + */ + mbedtls_md_hmac_finish( &sha_ctx, digest ); + + if( fwrite( digest, 1, 32, fout ) != 32 ) + { + mbedtls_fprintf( stderr, "fwrite(%d bytes) failed\n", 16 ); + goto exit; + } + } + + if( mode == MODE_DECRYPT ) + { + /* + * The encrypted file must be structured as follows: + * + * 00 .. 15 Initialization Vector + * 16 .. 31 AES Encrypted Block #1 + * .. + * N*16 .. (N+1)*16 - 1 AES Encrypted Block #N + * (N+1)*16 .. (N+1)*16 + 32 HMAC-SHA-256(ciphertext) + */ + if( filesize < 48 ) + { + mbedtls_fprintf( stderr, "File too short to be encrypted.\n" ); + goto exit; + } + + if( ( filesize & 0x0F ) != 0 ) + { + mbedtls_fprintf( stderr, "File size not a multiple of 16.\n" ); + goto exit; + } + + /* + * Subtract the IV + HMAC length. + */ + filesize -= ( 16 + 32 ); + + /* + * Read the IV and original filesize modulo 16. + */ + if( fread( buffer, 1, 16, fin ) != 16 ) + { + mbedtls_fprintf( stderr, "fread(%d bytes) failed\n", 16 ); + goto exit; + } + + memcpy( IV, buffer, 16 ); + lastn = IV[15] & 0x0F; + + /* + * Hash the IV and the secret key together 8192 times + * using the result to setup the AES context and HMAC. + */ + memset( digest, 0, 32 ); + memcpy( digest, IV, 16 ); + + for( i = 0; i < 8192; i++ ) + { + mbedtls_md_starts( &sha_ctx ); + mbedtls_md_update( &sha_ctx, digest, 32 ); + mbedtls_md_update( &sha_ctx, key, keylen ); + mbedtls_md_finish( &sha_ctx, digest ); + } + + mbedtls_aes_setkey_dec( &aes_ctx, digest, 256 ); + mbedtls_md_hmac_starts( &sha_ctx, digest, 32 ); + + /* + * Decrypt and write the plaintext. + */ + for( offset = 0; offset < filesize; offset += 16 ) + { + if( fread( buffer, 1, 16, fin ) != 16 ) + { + mbedtls_fprintf( stderr, "fread(%d bytes) failed\n", 16 ); + goto exit; + } + + memcpy( tmp, buffer, 16 ); + + mbedtls_md_hmac_update( &sha_ctx, buffer, 16 ); + mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_DECRYPT, buffer, buffer ); + + for( i = 0; i < 16; i++ ) + buffer[i] = (unsigned char)( buffer[i] ^ IV[i] ); + + memcpy( IV, tmp, 16 ); + + n = ( lastn > 0 && offset == filesize - 16 ) + ? lastn : 16; + + if( fwrite( buffer, 1, n, fout ) != (size_t) n ) + { + mbedtls_fprintf( stderr, "fwrite(%d bytes) failed\n", n ); + goto exit; + } + } + + /* + * Verify the message authentication code. + */ + mbedtls_md_hmac_finish( &sha_ctx, digest ); + + if( fread( buffer, 1, 32, fin ) != 32 ) + { + mbedtls_fprintf( stderr, "fread(%d bytes) failed\n", 32 ); + goto exit; + } + + /* Use constant-time buffer comparison */ + diff = 0; + for( i = 0; i < 32; i++ ) + diff |= digest[i] ^ buffer[i]; + + if( diff != 0 ) + { + mbedtls_fprintf( stderr, "HMAC check failed: wrong key, " + "or file corrupted.\n" ); + goto exit; + } + } + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + if( fin ) + fclose( fin ); + if( fout ) + fclose( fout ); + + /* Zeroize all command line arguments to also cover + the case when the user has missed or reordered some, + in which case the key might not be in argv[4]. */ + for( i = 0; i < (unsigned int) argc; i++ ) + mbedtls_platform_zeroize( argv[i], strlen( argv[i] ) ); + + mbedtls_platform_zeroize( IV, sizeof( IV ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( buffer, sizeof( buffer ) ); + mbedtls_platform_zeroize( digest, sizeof( digest ) ); + + mbedtls_aes_free( &aes_ctx ); + mbedtls_md_free( &sha_ctx ); + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_AES_C && MBEDTLS_SHA256_C && MBEDTLS_FS_IO */ diff --git a/external/mbedtls/programs/aes/crypt_and_hash.c b/external/mbedtls/programs/aes/crypt_and_hash.c new file mode 100644 index 0000000..9c566e7 --- /dev/null +++ b/external/mbedtls/programs/aes/crypt_and_hash.c @@ -0,0 +1,593 @@ +/* + * \brief Generic file encryption program using generic wrappers for configured + * security. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* Enable definition of fileno() even when compiling with -std=c99. Must be + * set before config.h, which pulls in glibc's features.h indirectly. + * Harmless on other platforms. */ +#define _POSIX_C_SOURCE 1 + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_MD_C) && \ + defined(MBEDTLS_FS_IO) +#include "mbedtls/cipher.h" +#include "mbedtls/md.h" +#include "mbedtls/platform_util.h" + +#include +#include +#include +#endif + +#if defined(_WIN32) +#include +#if !defined(_WIN32_WCE) +#include +#endif +#else +#include +#include +#endif + +#define MODE_ENCRYPT 0 +#define MODE_DECRYPT 1 + +#define USAGE \ + "\n crypt_and_hash \n" \ + "\n : 0 = encrypt, 1 = decrypt\n" \ + "\n example: crypt_and_hash 0 file file.aes AES-128-CBC SHA1 hex:E76B2413958B00E193\n" \ + "\n" + +#if !defined(MBEDTLS_CIPHER_C) || !defined(MBEDTLS_MD_C) || \ + !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_CIPHER_C and/or MBEDTLS_MD_C and/or MBEDTLS_FS_IO not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +int main( int argc, char *argv[] ) +{ + int ret = 1, i; + unsigned n; + int exit_code = MBEDTLS_EXIT_FAILURE; + int mode; + size_t keylen, ilen, olen; + FILE *fkey, *fin = NULL, *fout = NULL; + + char *p; + unsigned char IV[16]; + unsigned char key[512]; + unsigned char digest[MBEDTLS_MD_MAX_SIZE]; + unsigned char buffer[1024]; + unsigned char output[1024]; + unsigned char diff; + + const mbedtls_cipher_info_t *cipher_info; + const mbedtls_md_info_t *md_info; + mbedtls_cipher_context_t cipher_ctx; + mbedtls_md_context_t md_ctx; +#if defined(_WIN32_WCE) + long filesize, offset; +#elif defined(_WIN32) + LARGE_INTEGER li_size; + __int64 filesize, offset; +#else + off_t filesize, offset; +#endif + + mbedtls_cipher_init( &cipher_ctx ); + mbedtls_md_init( &md_ctx ); + + /* + * Parse the command-line arguments. + */ + if( argc != 7 ) + { + const int *list; + + mbedtls_printf( USAGE ); + + mbedtls_printf( "Available ciphers:\n" ); + list = mbedtls_cipher_list(); + while( *list ) + { + cipher_info = mbedtls_cipher_info_from_type( *list ); + mbedtls_printf( " %s\n", cipher_info->name ); + list++; + } + + mbedtls_printf( "\nAvailable message digests:\n" ); + list = mbedtls_md_list(); + while( *list ) + { + md_info = mbedtls_md_info_from_type( *list ); + mbedtls_printf( " %s\n", mbedtls_md_get_name( md_info ) ); + list++; + } + +#if defined(_WIN32) + mbedtls_printf( "\n Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + goto exit; + } + + mode = atoi( argv[1] ); + + if( mode != MODE_ENCRYPT && mode != MODE_DECRYPT ) + { + mbedtls_fprintf( stderr, "invalid operation mode\n" ); + goto exit; + } + + if( strcmp( argv[2], argv[3] ) == 0 ) + { + mbedtls_fprintf( stderr, "input and output filenames must differ\n" ); + goto exit; + } + + if( ( fin = fopen( argv[2], "rb" ) ) == NULL ) + { + mbedtls_fprintf( stderr, "fopen(%s,rb) failed\n", argv[2] ); + goto exit; + } + + if( ( fout = fopen( argv[3], "wb+" ) ) == NULL ) + { + mbedtls_fprintf( stderr, "fopen(%s,wb+) failed\n", argv[3] ); + goto exit; + } + + /* + * Read the Cipher and MD from the command line + */ + cipher_info = mbedtls_cipher_info_from_string( argv[4] ); + if( cipher_info == NULL ) + { + mbedtls_fprintf( stderr, "Cipher '%s' not found\n", argv[4] ); + goto exit; + } + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info) ) != 0 ) + { + mbedtls_fprintf( stderr, "mbedtls_cipher_setup failed\n" ); + goto exit; + } + + md_info = mbedtls_md_info_from_string( argv[5] ); + if( md_info == NULL ) + { + mbedtls_fprintf( stderr, "Message Digest '%s' not found\n", argv[5] ); + goto exit; + } + + if( mbedtls_md_setup( &md_ctx, md_info, 1 ) != 0 ) + { + mbedtls_fprintf( stderr, "mbedtls_md_setup failed\n" ); + goto exit; + } + + /* + * Read the secret key from file or command line + */ + if( ( fkey = fopen( argv[6], "rb" ) ) != NULL ) + { + keylen = fread( key, 1, sizeof( key ), fkey ); + fclose( fkey ); + } + else + { + if( memcmp( argv[6], "hex:", 4 ) == 0 ) + { + p = &argv[6][4]; + keylen = 0; + + while( sscanf( p, "%02X", &n ) > 0 && + keylen < (int) sizeof( key ) ) + { + key[keylen++] = (unsigned char) n; + p += 2; + } + } + else + { + keylen = strlen( argv[6] ); + + if( keylen > (int) sizeof( key ) ) + keylen = (int) sizeof( key ); + + memcpy( key, argv[6], keylen ); + } + } + +#if defined(_WIN32_WCE) + filesize = fseek( fin, 0L, SEEK_END ); +#else +#if defined(_WIN32) + /* + * Support large files (> 2Gb) on Win32 + */ + li_size.QuadPart = 0; + li_size.LowPart = + SetFilePointer( (HANDLE) _get_osfhandle( _fileno( fin ) ), + li_size.LowPart, &li_size.HighPart, FILE_END ); + + if( li_size.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR ) + { + mbedtls_fprintf( stderr, "SetFilePointer(0,FILE_END) failed\n" ); + goto exit; + } + + filesize = li_size.QuadPart; +#else + if( ( filesize = lseek( fileno( fin ), 0, SEEK_END ) ) < 0 ) + { + perror( "lseek" ); + goto exit; + } +#endif +#endif + + if( fseek( fin, 0, SEEK_SET ) < 0 ) + { + mbedtls_fprintf( stderr, "fseek(0,SEEK_SET) failed\n" ); + goto exit; + } + + if( mode == MODE_ENCRYPT ) + { + /* + * Generate the initialization vector as: + * IV = MD( filesize || filename )[0..15] + */ + for( i = 0; i < 8; i++ ) + buffer[i] = (unsigned char)( filesize >> ( i << 3 ) ); + + p = argv[2]; + + mbedtls_md_starts( &md_ctx ); + mbedtls_md_update( &md_ctx, buffer, 8 ); + mbedtls_md_update( &md_ctx, (unsigned char *) p, strlen( p ) ); + mbedtls_md_finish( &md_ctx, digest ); + + memcpy( IV, digest, 16 ); + + /* + * Append the IV at the beginning of the output. + */ + if( fwrite( IV, 1, 16, fout ) != 16 ) + { + mbedtls_fprintf( stderr, "fwrite(%d bytes) failed\n", 16 ); + goto exit; + } + + /* + * Hash the IV and the secret key together 8192 times + * using the result to setup the AES context and HMAC. + */ + memset( digest, 0, 32 ); + memcpy( digest, IV, 16 ); + + for( i = 0; i < 8192; i++ ) + { + mbedtls_md_starts( &md_ctx ); + mbedtls_md_update( &md_ctx, digest, 32 ); + mbedtls_md_update( &md_ctx, key, keylen ); + mbedtls_md_finish( &md_ctx, digest ); + + } + + if( mbedtls_cipher_setkey( &cipher_ctx, digest, cipher_info->key_bitlen, + MBEDTLS_ENCRYPT ) != 0 ) + { + mbedtls_fprintf( stderr, "mbedtls_cipher_setkey() returned error\n"); + goto exit; + } + if( mbedtls_cipher_set_iv( &cipher_ctx, IV, 16 ) != 0 ) + { + mbedtls_fprintf( stderr, "mbedtls_cipher_set_iv() returned error\n"); + goto exit; + } + if( mbedtls_cipher_reset( &cipher_ctx ) != 0 ) + { + mbedtls_fprintf( stderr, "mbedtls_cipher_reset() returned error\n"); + goto exit; + } + + mbedtls_md_hmac_starts( &md_ctx, digest, 32 ); + + /* + * Encrypt and write the ciphertext. + */ + for( offset = 0; offset < filesize; offset += mbedtls_cipher_get_block_size( &cipher_ctx ) ) + { + ilen = ( (unsigned int) filesize - offset > mbedtls_cipher_get_block_size( &cipher_ctx ) ) ? + mbedtls_cipher_get_block_size( &cipher_ctx ) : (unsigned int) ( filesize - offset ); + + if( fread( buffer, 1, ilen, fin ) != ilen ) + { + mbedtls_fprintf( stderr, "fread(%ld bytes) failed\n", (long) ilen ); + goto exit; + } + + if( mbedtls_cipher_update( &cipher_ctx, buffer, ilen, output, &olen ) != 0 ) + { + mbedtls_fprintf( stderr, "mbedtls_cipher_update() returned error\n"); + goto exit; + } + + mbedtls_md_hmac_update( &md_ctx, output, olen ); + + if( fwrite( output, 1, olen, fout ) != olen ) + { + mbedtls_fprintf( stderr, "fwrite(%ld bytes) failed\n", (long) olen ); + goto exit; + } + } + + if( mbedtls_cipher_finish( &cipher_ctx, output, &olen ) != 0 ) + { + mbedtls_fprintf( stderr, "mbedtls_cipher_finish() returned error\n" ); + goto exit; + } + mbedtls_md_hmac_update( &md_ctx, output, olen ); + + if( fwrite( output, 1, olen, fout ) != olen ) + { + mbedtls_fprintf( stderr, "fwrite(%ld bytes) failed\n", (long) olen ); + goto exit; + } + + /* + * Finally write the HMAC. + */ + mbedtls_md_hmac_finish( &md_ctx, digest ); + + if( fwrite( digest, 1, mbedtls_md_get_size( md_info ), fout ) != mbedtls_md_get_size( md_info ) ) + { + mbedtls_fprintf( stderr, "fwrite(%d bytes) failed\n", mbedtls_md_get_size( md_info ) ); + goto exit; + } + } + + if( mode == MODE_DECRYPT ) + { + /* + * The encrypted file must be structured as follows: + * + * 00 .. 15 Initialization Vector + * 16 .. 31 Encrypted Block #1 + * .. + * N*16 .. (N+1)*16 - 1 Encrypted Block #N + * (N+1)*16 .. (N+1)*16 + n Hash(ciphertext) + */ + if( filesize < 16 + mbedtls_md_get_size( md_info ) ) + { + mbedtls_fprintf( stderr, "File too short to be encrypted.\n" ); + goto exit; + } + + if( mbedtls_cipher_get_block_size( &cipher_ctx ) == 0 ) + { + mbedtls_fprintf( stderr, "Invalid cipher block size: 0. \n" ); + goto exit; + } + + /* + * Check the file size. + */ + if( cipher_info->mode != MBEDTLS_MODE_GCM && + ( ( filesize - mbedtls_md_get_size( md_info ) ) % + mbedtls_cipher_get_block_size( &cipher_ctx ) ) != 0 ) + { + mbedtls_fprintf( stderr, "File content not a multiple of the block size (%d).\n", + mbedtls_cipher_get_block_size( &cipher_ctx )); + goto exit; + } + + /* + * Subtract the IV + HMAC length. + */ + filesize -= ( 16 + mbedtls_md_get_size( md_info ) ); + + /* + * Read the IV and original filesize modulo 16. + */ + if( fread( buffer, 1, 16, fin ) != 16 ) + { + mbedtls_fprintf( stderr, "fread(%d bytes) failed\n", 16 ); + goto exit; + } + + memcpy( IV, buffer, 16 ); + + /* + * Hash the IV and the secret key together 8192 times + * using the result to setup the AES context and HMAC. + */ + memset( digest, 0, 32 ); + memcpy( digest, IV, 16 ); + + for( i = 0; i < 8192; i++ ) + { + mbedtls_md_starts( &md_ctx ); + mbedtls_md_update( &md_ctx, digest, 32 ); + mbedtls_md_update( &md_ctx, key, keylen ); + mbedtls_md_finish( &md_ctx, digest ); + } + + if( mbedtls_cipher_setkey( &cipher_ctx, digest, cipher_info->key_bitlen, + MBEDTLS_DECRYPT ) != 0 ) + { + mbedtls_fprintf( stderr, "mbedtls_cipher_setkey() returned error\n" ); + goto exit; + } + + if( mbedtls_cipher_set_iv( &cipher_ctx, IV, 16 ) != 0 ) + { + mbedtls_fprintf( stderr, "mbedtls_cipher_set_iv() returned error\n" ); + goto exit; + } + + if( mbedtls_cipher_reset( &cipher_ctx ) != 0 ) + { + mbedtls_fprintf( stderr, "mbedtls_cipher_reset() returned error\n" ); + goto exit; + } + + mbedtls_md_hmac_starts( &md_ctx, digest, 32 ); + + /* + * Decrypt and write the plaintext. + */ + for( offset = 0; offset < filesize; offset += mbedtls_cipher_get_block_size( &cipher_ctx ) ) + { + ilen = ( (unsigned int) filesize - offset > mbedtls_cipher_get_block_size( &cipher_ctx ) ) ? + mbedtls_cipher_get_block_size( &cipher_ctx ) : (unsigned int) ( filesize - offset ); + + if( fread( buffer, 1, ilen, fin ) != ilen ) + { + mbedtls_fprintf( stderr, "fread(%d bytes) failed\n", + mbedtls_cipher_get_block_size( &cipher_ctx ) ); + goto exit; + } + + mbedtls_md_hmac_update( &md_ctx, buffer, ilen ); + if( mbedtls_cipher_update( &cipher_ctx, buffer, ilen, output, + &olen ) != 0 ) + { + mbedtls_fprintf( stderr, "mbedtls_cipher_update() returned error\n" ); + goto exit; + } + + if( fwrite( output, 1, olen, fout ) != olen ) + { + mbedtls_fprintf( stderr, "fwrite(%ld bytes) failed\n", (long) olen ); + goto exit; + } + } + + /* + * Verify the message authentication code. + */ + mbedtls_md_hmac_finish( &md_ctx, digest ); + + if( fread( buffer, 1, mbedtls_md_get_size( md_info ), fin ) != mbedtls_md_get_size( md_info ) ) + { + mbedtls_fprintf( stderr, "fread(%d bytes) failed\n", mbedtls_md_get_size( md_info ) ); + goto exit; + } + + /* Use constant-time buffer comparison */ + diff = 0; + for( i = 0; i < mbedtls_md_get_size( md_info ); i++ ) + diff |= digest[i] ^ buffer[i]; + + if( diff != 0 ) + { + mbedtls_fprintf( stderr, "HMAC check failed: wrong key, " + "or file corrupted.\n" ); + goto exit; + } + + /* + * Write the final block of data + */ + mbedtls_cipher_finish( &cipher_ctx, output, &olen ); + + if( fwrite( output, 1, olen, fout ) != olen ) + { + mbedtls_fprintf( stderr, "fwrite(%ld bytes) failed\n", (long) olen ); + goto exit; + } + } + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + if( fin ) + fclose( fin ); + if( fout ) + fclose( fout ); + + /* Zeroize all command line arguments to also cover + the case when the user has missed or reordered some, + in which case the key might not be in argv[6]. */ + for( i = 0; i < argc; i++ ) + mbedtls_platform_zeroize( argv[i], strlen( argv[i] ) ); + + mbedtls_platform_zeroize( IV, sizeof( IV ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( buffer, sizeof( buffer ) ); + mbedtls_platform_zeroize( output, sizeof( output ) ); + mbedtls_platform_zeroize( digest, sizeof( digest ) ); + + mbedtls_cipher_free( &cipher_ctx ); + mbedtls_md_free( &md_ctx ); + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_CIPHER_C && MBEDTLS_MD_C && MBEDTLS_FS_IO */ diff --git a/external/mbedtls/programs/hash/CMakeLists.txt b/external/mbedtls/programs/hash/CMakeLists.txt new file mode 100644 index 0000000..eda975b --- /dev/null +++ b/external/mbedtls/programs/hash/CMakeLists.txt @@ -0,0 +1,9 @@ +add_executable(hello hello.c) +target_link_libraries(hello mbedtls) + +add_executable(generic_sum generic_sum.c) +target_link_libraries(generic_sum mbedtls) + +install(TARGETS hello generic_sum + DESTINATION "bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/external/mbedtls/programs/hash/generic_sum.c b/external/mbedtls/programs/hash/generic_sum.c new file mode 100644 index 0000000..d6c5cf8 --- /dev/null +++ b/external/mbedtls/programs/hash/generic_sum.c @@ -0,0 +1,267 @@ +/* + * generic message digest layer demonstration program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_MD_C) && defined(MBEDTLS_FS_IO) +#include "mbedtls/md.h" + +#include +#include +#endif + +#if !defined(MBEDTLS_MD_C) || !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_MD_C and/or MBEDTLS_FS_IO not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +static int generic_wrapper( const mbedtls_md_info_t *md_info, char *filename, unsigned char *sum ) +{ + int ret = mbedtls_md_file( md_info, filename, sum ); + + if( ret == 1 ) + mbedtls_fprintf( stderr, "failed to open: %s\n", filename ); + + if( ret == 2 ) + mbedtls_fprintf( stderr, "failed to read: %s\n", filename ); + + return( ret ); +} + +static int generic_print( const mbedtls_md_info_t *md_info, char *filename ) +{ + int i; + unsigned char sum[MBEDTLS_MD_MAX_SIZE]; + + if( generic_wrapper( md_info, filename, sum ) != 0 ) + return( 1 ); + + for( i = 0; i < mbedtls_md_get_size( md_info ); i++ ) + mbedtls_printf( "%02x", sum[i] ); + + mbedtls_printf( " %s\n", filename ); + return( 0 ); +} + +static int generic_check( const mbedtls_md_info_t *md_info, char *filename ) +{ + int i; + size_t n; + FILE *f; + int nb_err1, nb_err2; + int nb_tot1, nb_tot2; + unsigned char sum[MBEDTLS_MD_MAX_SIZE]; + char line[1024]; + char diff; +#if defined(__clang_analyzer__) + char buf[MBEDTLS_MD_MAX_SIZE * 2 + 1] = { }; +#else + char buf[MBEDTLS_MD_MAX_SIZE * 2 + 1]; +#endif + + if( ( f = fopen( filename, "rb" ) ) == NULL ) + { + mbedtls_printf( "failed to open: %s\n", filename ); + return( 1 ); + } + + nb_err1 = nb_err2 = 0; + nb_tot1 = nb_tot2 = 0; + + memset( line, 0, sizeof( line ) ); + + n = sizeof( line ); + + while( fgets( line, (int) n - 1, f ) != NULL ) + { + n = strlen( line ); + + if( n < (size_t) 2 * mbedtls_md_get_size( md_info ) + 4 ) + { + mbedtls_printf("No '%s' hash found on line.\n", mbedtls_md_get_name( md_info )); + continue; + } + + if( line[2 * mbedtls_md_get_size( md_info )] != ' ' || line[2 * mbedtls_md_get_size( md_info ) + 1] != ' ' ) + { + mbedtls_printf("No '%s' hash found on line.\n", mbedtls_md_get_name( md_info )); + continue; + } + + if( line[n - 1] == '\n' ) { n--; line[n] = '\0'; } + if( line[n - 1] == '\r' ) { n--; line[n] = '\0'; } + + nb_tot1++; + + if( generic_wrapper( md_info, line + 2 + 2 * mbedtls_md_get_size( md_info ), sum ) != 0 ) + { + nb_err1++; + continue; + } + + nb_tot2++; + + for( i = 0; i < mbedtls_md_get_size( md_info ); i++ ) + sprintf( buf + i * 2, "%02x", sum[i] ); + + /* Use constant-time buffer comparison */ + diff = 0; + for( i = 0; i < 2 * mbedtls_md_get_size( md_info ); i++ ) + diff |= line[i] ^ buf[i]; + + if( diff != 0 ) + { + nb_err2++; + mbedtls_fprintf( stderr, "wrong checksum: %s\n", line + 66 ); + } + + n = sizeof( line ); + } + + if( nb_err1 != 0 ) + { + mbedtls_printf( "WARNING: %d (out of %d) input files could " + "not be read\n", nb_err1, nb_tot1 ); + } + + if( nb_err2 != 0 ) + { + mbedtls_printf( "WARNING: %d (out of %d) computed checksums did " + "not match\n", nb_err2, nb_tot2 ); + } + + fclose( f ); + + return( nb_err1 != 0 || nb_err2 != 0 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 1, i; + int exit_code = MBEDTLS_EXIT_FAILURE; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + mbedtls_md_init( &md_ctx ); + + if( argc == 1 ) + { + const int *list; + + mbedtls_printf( "print mode: generic_sum ...\n" ); + mbedtls_printf( "check mode: generic_sum -c \n" ); + + mbedtls_printf( "\nAvailable message digests:\n" ); + list = mbedtls_md_list(); + while( *list ) + { + md_info = mbedtls_md_info_from_type( *list ); + mbedtls_printf( " %s\n", mbedtls_md_get_name( md_info ) ); + list++; + } + +#if defined(_WIN32) + mbedtls_printf( "\n Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); + } + + /* + * Read the MD from the command line + */ + md_info = mbedtls_md_info_from_string( argv[1] ); + if( md_info == NULL ) + { + mbedtls_fprintf( stderr, "Message Digest '%s' not found\n", argv[1] ); + mbedtls_exit( exit_code ); + } + if( mbedtls_md_setup( &md_ctx, md_info, 0 ) ) + { + mbedtls_fprintf( stderr, "Failed to initialize context.\n" ); + mbedtls_exit( exit_code ); + } + + ret = 0; + if( argc == 4 && strcmp( "-c", argv[2] ) == 0 ) + { + ret |= generic_check( md_info, argv[3] ); + goto exit; + } + + for( i = 2; i < argc; i++ ) + ret |= generic_print( md_info, argv[i] ); + + if ( ret == 0 ) + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + mbedtls_md_free( &md_ctx ); + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_MD_C && MBEDTLS_FS_IO */ diff --git a/external/mbedtls/programs/hash/hello.c b/external/mbedtls/programs/hash/hello.c new file mode 100644 index 0000000..ada025b --- /dev/null +++ b/external/mbedtls/programs/hash/hello.c @@ -0,0 +1,100 @@ +/* + * Classic "Hello, world" demonstration program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if !defined(MBEDTLS_MD5_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_MD5_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +int main( void ) +{ + int i, ret; + unsigned char digest[16]; + char str[] = "Hello, world!"; + + mbedtls_printf( "\n MD5('%s') = ", str ); + + if( ( ret = mbedtls_md5_ret( (unsigned char *) str, 13, digest ) ) != 0 ) + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); + + for( i = 0; i < 16; i++ ) + mbedtls_printf( "%02x", digest[i] ); + + mbedtls_printf( "\n\n" ); + +#if defined(_WIN32) + mbedtls_printf( " Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( MBEDTLS_EXIT_SUCCESS ); +} +#endif /* MBEDTLS_MD5_C */ diff --git a/external/mbedtls/programs/pkey/CMakeLists.txt b/external/mbedtls/programs/pkey/CMakeLists.txt new file mode 100644 index 0000000..5a37a42 --- /dev/null +++ b/external/mbedtls/programs/pkey/CMakeLists.txt @@ -0,0 +1,63 @@ +add_executable(dh_client dh_client.c) +target_link_libraries(dh_client mbedtls) + +add_executable(dh_genprime dh_genprime.c) +target_link_libraries(dh_genprime mbedtls) + +add_executable(dh_server dh_server.c) +target_link_libraries(dh_server mbedtls) + +add_executable(ecdh_curve25519 ecdh_curve25519.c) +target_link_libraries(ecdh_curve25519 mbedtls) + +add_executable(ecdsa ecdsa.c) +target_link_libraries(ecdsa mbedtls) + +add_executable(gen_key gen_key.c) +target_link_libraries(gen_key mbedtls) + +add_executable(key_app key_app.c) +target_link_libraries(key_app mbedtls) + +add_executable(key_app_writer key_app_writer.c) +target_link_libraries(key_app_writer mbedtls) + +add_executable(mpi_demo mpi_demo.c) +target_link_libraries(mpi_demo mbedtls) + +add_executable(rsa_genkey rsa_genkey.c) +target_link_libraries(rsa_genkey mbedtls) + +add_executable(rsa_sign rsa_sign.c) +target_link_libraries(rsa_sign mbedtls) + +add_executable(rsa_verify rsa_verify.c) +target_link_libraries(rsa_verify mbedtls) + +add_executable(rsa_sign_pss rsa_sign_pss.c) +target_link_libraries(rsa_sign_pss mbedtls) + +add_executable(rsa_verify_pss rsa_verify_pss.c) +target_link_libraries(rsa_verify_pss mbedtls) + +add_executable(rsa_encrypt rsa_encrypt.c) +target_link_libraries(rsa_encrypt mbedtls) + +add_executable(rsa_decrypt rsa_decrypt.c) +target_link_libraries(rsa_decrypt mbedtls) + +add_executable(pk_sign pk_sign.c) +target_link_libraries(pk_sign mbedtls) + +add_executable(pk_verify pk_verify.c) +target_link_libraries(pk_verify mbedtls) + +add_executable(pk_encrypt pk_encrypt.c) +target_link_libraries(pk_encrypt mbedtls) + +add_executable(pk_decrypt pk_decrypt.c) +target_link_libraries(pk_decrypt mbedtls) + +install(TARGETS dh_client dh_genprime dh_server key_app mpi_demo rsa_genkey rsa_sign rsa_verify rsa_encrypt rsa_decrypt pk_encrypt pk_decrypt pk_sign pk_verify gen_key + DESTINATION "bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/external/mbedtls/programs/pkey/dh_client.c b/external/mbedtls/programs/pkey/dh_client.c new file mode 100644 index 0000000..68f4b71 --- /dev/null +++ b/external/mbedtls/programs/pkey/dh_client.c @@ -0,0 +1,339 @@ +/* + * Diffie-Hellman-Merkle key exchange (client side) + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_time_t time_t +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_AES_C) && defined(MBEDTLS_DHM_C) && \ + defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_NET_C) && \ + defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) && \ + defined(MBEDTLS_FS_IO) && defined(MBEDTLS_CTR_DRBG_C) && \ + defined(MBEDTLS_SHA1_C) +#include "mbedtls/net_sockets.h" +#include "mbedtls/aes.h" +#include "mbedtls/dhm.h" +#include "mbedtls/rsa.h" +#include "mbedtls/sha1.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include +#include +#endif + +#define SERVER_NAME "localhost" +#define SERVER_PORT "11999" + +#if !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_DHM_C) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NET_C) || \ + !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C) || \ + !defined(MBEDTLS_SHA1_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_AES_C and/or MBEDTLS_DHM_C and/or MBEDTLS_ENTROPY_C " + "and/or MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO and/or " + "MBEDTLS_CTR_DRBG_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +int main( void ) +{ + FILE *f; + + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + size_t n, buflen; + mbedtls_net_context server_fd; + + unsigned char *p, *end; + unsigned char buf[2048]; + unsigned char hash[32]; + const char *pers = "dh_client"; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_rsa_context rsa; + mbedtls_dhm_context dhm; + mbedtls_aes_context aes; + + mbedtls_net_init( &server_fd ); + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256 ); + mbedtls_dhm_init( &dhm ); + mbedtls_aes_init( &aes ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + + /* + * 1. Setup the RNG + */ + mbedtls_printf( "\n . Seeding the random number generator" ); + fflush( stdout ); + + mbedtls_entropy_init( &entropy ); + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); + goto exit; + } + + /* + * 2. Read the server's public RSA key + */ + mbedtls_printf( "\n . Reading public key from rsa_pub.txt" ); + fflush( stdout ); + + if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! Could not open rsa_pub.txt\n" \ + " ! Please run rsa_genkey first\n\n" ); + goto exit; + } + + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + + if( ( ret = mbedtls_mpi_read_file( &rsa.N, 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &rsa.E, 16, f ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", ret ); + fclose( f ); + goto exit; + } + + rsa.len = ( mbedtls_mpi_bitlen( &rsa.N ) + 7 ) >> 3; + + fclose( f ); + + /* + * 3. Initiate the connection + */ + mbedtls_printf( "\n . Connecting to tcp/%s/%s", SERVER_NAME, + SERVER_PORT ); + fflush( stdout ); + + if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME, + SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); + goto exit; + } + + /* + * 4a. First get the buffer length + */ + mbedtls_printf( "\n . Receiving the server's DH parameters" ); + fflush( stdout ); + + memset( buf, 0, sizeof( buf ) ); + + if( ( ret = mbedtls_net_recv( &server_fd, buf, 2 ) ) != 2 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_recv returned %d\n\n", ret ); + goto exit; + } + + n = buflen = ( buf[0] << 8 ) | buf[1]; + if( buflen < 1 || buflen > sizeof( buf ) ) + { + mbedtls_printf( " failed\n ! Got an invalid buffer length\n\n" ); + goto exit; + } + + /* + * 4b. Get the DHM parameters: P, G and Ys = G^Xs mod P + */ + memset( buf, 0, sizeof( buf ) ); + + if( ( ret = mbedtls_net_recv( &server_fd, buf, n ) ) != (int) n ) + { + mbedtls_printf( " failed\n ! mbedtls_net_recv returned %d\n\n", ret ); + goto exit; + } + + p = buf, end = buf + buflen; + + if( ( ret = mbedtls_dhm_read_params( &dhm, &p, end ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_dhm_read_params returned %d\n\n", ret ); + goto exit; + } + + if( dhm.len < 64 || dhm.len > 512 ) + { + mbedtls_printf( " failed\n ! Invalid DHM modulus size\n\n" ); + goto exit; + } + + /* + * 5. Check that the server's RSA signature matches + * the SHA-256 hash of (P,G,Ys) + */ + mbedtls_printf( "\n . Verifying the server's RSA signature" ); + fflush( stdout ); + + p += 2; + + if( ( n = (size_t) ( end - p ) ) != rsa.len ) + { + mbedtls_printf( " failed\n ! Invalid RSA signature size\n\n" ); + goto exit; + } + + if( ( ret = mbedtls_sha1_ret( buf, (int)( p - 2 - buf ), hash ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_sha1_ret returned %d\n\n", ret ); + goto exit; + } + + if( ( ret = mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, + MBEDTLS_MD_SHA256, 0, hash, p ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_verify returned %d\n\n", ret ); + goto exit; + } + + /* + * 6. Send our public value: Yc = G ^ Xc mod P + */ + mbedtls_printf( "\n . Sending own public value to server" ); + fflush( stdout ); + + n = dhm.len; + if( ( ret = mbedtls_dhm_make_public( &dhm, (int) dhm.len, buf, n, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_dhm_make_public returned %d\n\n", ret ); + goto exit; + } + + if( ( ret = mbedtls_net_send( &server_fd, buf, n ) ) != (int) n ) + { + mbedtls_printf( " failed\n ! mbedtls_net_send returned %d\n\n", ret ); + goto exit; + } + + /* + * 7. Derive the shared secret: K = Ys ^ Xc mod P + */ + mbedtls_printf( "\n . Shared secret: " ); + fflush( stdout ); + + if( ( ret = mbedtls_dhm_calc_secret( &dhm, buf, sizeof( buf ), &n, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_dhm_calc_secret returned %d\n\n", ret ); + goto exit; + } + + for( n = 0; n < 16; n++ ) + mbedtls_printf( "%02x", buf[n] ); + + /* + * 8. Setup the AES-256 decryption key + * + * This is an overly simplified example; best practice is + * to hash the shared secret with a random value to derive + * the keying material for the encryption/decryption keys, + * IVs and MACs. + */ + mbedtls_printf( "...\n . Receiving and decrypting the ciphertext" ); + fflush( stdout ); + + mbedtls_aes_setkey_dec( &aes, buf, 256 ); + + memset( buf, 0, sizeof( buf ) ); + + if( ( ret = mbedtls_net_recv( &server_fd, buf, 16 ) ) != 16 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_recv returned %d\n\n", ret ); + goto exit; + } + + mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_DECRYPT, buf, buf ); + buf[16] = '\0'; + mbedtls_printf( "\n . Plaintext is \"%s\"\n\n", (char *) buf ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + mbedtls_net_free( &server_fd ); + + mbedtls_aes_free( &aes ); + mbedtls_rsa_free( &rsa ); + mbedtls_dhm_free( &dhm ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_AES_C && MBEDTLS_DHM_C && MBEDTLS_ENTROPY_C && + MBEDTLS_NET_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C && + MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */ diff --git a/external/mbedtls/programs/pkey/dh_genprime.c b/external/mbedtls/programs/pkey/dh_genprime.c new file mode 100644 index 0000000..fcfa5b9 --- /dev/null +++ b/external/mbedtls/programs/pkey/dh_genprime.c @@ -0,0 +1,228 @@ +/* + * Diffie-Hellman-Merkle key exchange (prime generation) + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_time_t time_t +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C) || \ + !defined(MBEDTLS_GENPRIME) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_FS_IO and/or MBEDTLS_CTR_DRBG_C and/or " + "MBEDTLS_GENPRIME not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/bignum.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include +#include + +#define USAGE \ + "\n usage: dh_genprime param=<>...\n" \ + "\n acceprable parameters:\n" \ + " bits=%%d default: 2048\n" + +#define DFL_BITS 2048 + +/* + * Note: G = 4 is always a quadratic residue mod P, + * so it is a generator of order Q (with P = 2*Q+1). + */ +#define GENERATOR "4" + + +int main( int argc, char **argv ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_mpi G, P, Q; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + const char *pers = "dh_genprime"; + FILE *fout; + int nbits = DFL_BITS; + int i; + char *p, *q; + + mbedtls_mpi_init( &G ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + mbedtls_entropy_init( &entropy ); + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + goto exit; + } + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "bits" ) == 0 ) + { + nbits = atoi( q ); + if( nbits < 0 || nbits > MBEDTLS_MPI_MAX_BITS ) + goto usage; + } + else + goto usage; + } + + if( ( ret = mbedtls_mpi_read_string( &G, 10, GENERATOR ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_read_string returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ! Generating large primes may take minutes!\n" ); + + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n . Generating the modulus, please wait..." ); + fflush( stdout ); + + /* + * This can take a long time... + */ + if( ( ret = mbedtls_mpi_gen_prime( &P, nbits, 1, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_gen_prime returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n . Verifying that Q = (P-1)/2 is prime..." ); + fflush( stdout ); + + if( ( ret = mbedtls_mpi_sub_int( &Q, &P, 1 ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_sub_int returned %d\n\n", ret ); + goto exit; + } + + if( ( ret = mbedtls_mpi_div_int( &Q, NULL, &Q, 2 ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_div_int returned %d\n\n", ret ); + goto exit; + } + + if( ( ret = mbedtls_mpi_is_prime_ext( &Q, 50, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_is_prime returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n . Exporting the value in dh_prime.txt..." ); + fflush( stdout ); + + if( ( fout = fopen( "dh_prime.txt", "wb+" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! Could not create dh_prime.txt\n\n" ); + goto exit; + } + + if( ( ret = mbedtls_mpi_write_file( "P = ", &P, 16, fout ) != 0 ) || + ( ret = mbedtls_mpi_write_file( "G = ", &G, 16, fout ) != 0 ) ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_write_file returned %d\n\n", ret ); + fclose( fout ); + goto exit; + } + + mbedtls_printf( " ok\n\n" ); + fclose( fout ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + mbedtls_mpi_free( &G ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_FS_IO && + MBEDTLS_CTR_DRBG_C && MBEDTLS_GENPRIME */ diff --git a/external/mbedtls/programs/pkey/dh_prime.txt b/external/mbedtls/programs/pkey/dh_prime.txt new file mode 100644 index 0000000..de0c281 --- /dev/null +++ b/external/mbedtls/programs/pkey/dh_prime.txt @@ -0,0 +1,2 @@ +P = FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF +G = 02 diff --git a/external/mbedtls/programs/pkey/dh_server.c b/external/mbedtls/programs/pkey/dh_server.c new file mode 100644 index 0000000..5e008ab --- /dev/null +++ b/external/mbedtls/programs/pkey/dh_server.c @@ -0,0 +1,362 @@ +/* + * Diffie-Hellman-Merkle key exchange (server side) + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_time_t time_t +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_AES_C) && defined(MBEDTLS_DHM_C) && \ + defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_NET_C) && \ + defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) && \ + defined(MBEDTLS_FS_IO) && defined(MBEDTLS_CTR_DRBG_C) && \ + defined(MBEDTLS_SHA1_C) +#include "mbedtls/net_sockets.h" +#include "mbedtls/aes.h" +#include "mbedtls/dhm.h" +#include "mbedtls/rsa.h" +#include "mbedtls/sha1.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include +#include +#endif + +#define SERVER_PORT "11999" +#define PLAINTEXT "==Hello there!==" + +#if !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_DHM_C) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NET_C) || \ + !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C) || \ + !defined(MBEDTLS_SHA1_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_AES_C and/or MBEDTLS_DHM_C and/or MBEDTLS_ENTROPY_C " + "and/or MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO and/or " + "MBEDTLS_CTR_DRBG_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +int main( void ) +{ + FILE *f; + + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + size_t n, buflen; + mbedtls_net_context listen_fd, client_fd; + + unsigned char buf[2048]; + unsigned char hash[32]; + unsigned char buf2[2]; + const char *pers = "dh_server"; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_rsa_context rsa; + mbedtls_dhm_context dhm; + mbedtls_aes_context aes; + + mbedtls_mpi N, P, Q, D, E; + + mbedtls_net_init( &listen_fd ); + mbedtls_net_init( &client_fd ); + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256 ); + mbedtls_dhm_init( &dhm ); + mbedtls_aes_init( &aes ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + + mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); + + /* + * 1. Setup the RNG + */ + mbedtls_printf( "\n . Seeding the random number generator" ); + fflush( stdout ); + + mbedtls_entropy_init( &entropy ); + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); + goto exit; + } + + /* + * 2a. Read the server's private RSA key + */ + mbedtls_printf( "\n . Reading private key from rsa_priv.txt" ); + fflush( stdout ); + + if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! Could not open rsa_priv.txt\n" \ + " ! Please run rsa_genkey first\n\n" ); + goto exit; + } + + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + + if( ( ret = mbedtls_mpi_read_file( &N , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &E , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &D , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &P , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &Q , 16, f ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", + ret ); + fclose( f ); + goto exit; + } + fclose( f ); + + if( ( ret = mbedtls_rsa_import( &rsa, &N, &P, &Q, &D, &E ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_import returned %d\n\n", + ret ); + goto exit; + } + + if( ( ret = mbedtls_rsa_complete( &rsa ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_complete returned %d\n\n", + ret ); + goto exit; + } + + /* + * 2b. Get the DHM modulus and generator + */ + mbedtls_printf( "\n . Reading DH parameters from dh_prime.txt" ); + fflush( stdout ); + + if( ( f = fopen( "dh_prime.txt", "rb" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! Could not open dh_prime.txt\n" \ + " ! Please run dh_genprime first\n\n" ); + goto exit; + } + + if( mbedtls_mpi_read_file( &dhm.P, 16, f ) != 0 || + mbedtls_mpi_read_file( &dhm.G, 16, f ) != 0 ) + { + mbedtls_printf( " failed\n ! Invalid DH parameter file\n\n" ); + fclose( f ); + goto exit; + } + + fclose( f ); + + /* + * 3. Wait for a client to connect + */ + mbedtls_printf( "\n . Waiting for a remote connection" ); + fflush( stdout ); + + if( ( ret = mbedtls_net_bind( &listen_fd, NULL, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); + goto exit; + } + + if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, + NULL, 0, NULL ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret ); + goto exit; + } + + /* + * 4. Setup the DH parameters (P,G,Ys) + */ + mbedtls_printf( "\n . Sending the server's DH parameters" ); + fflush( stdout ); + + memset( buf, 0, sizeof( buf ) ); + + if( ( ret = mbedtls_dhm_make_params( &dhm, (int) mbedtls_mpi_size( &dhm.P ), buf, &n, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_dhm_make_params returned %d\n\n", ret ); + goto exit; + } + + /* + * 5. Sign the parameters and send them + */ + if( ( ret = mbedtls_sha1_ret( buf, n, hash ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_sha1_ret returned %d\n\n", ret ); + goto exit; + } + + buf[n ] = (unsigned char)( rsa.len >> 8 ); + buf[n + 1] = (unsigned char)( rsa.len ); + + if( ( ret = mbedtls_rsa_pkcs1_sign( &rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256, + 0, hash, buf + n + 2 ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_sign returned %d\n\n", ret ); + goto exit; + } + + buflen = n + 2 + rsa.len; + buf2[0] = (unsigned char)( buflen >> 8 ); + buf2[1] = (unsigned char)( buflen ); + + if( ( ret = mbedtls_net_send( &client_fd, buf2, 2 ) ) != 2 || + ( ret = mbedtls_net_send( &client_fd, buf, buflen ) ) != (int) buflen ) + { + mbedtls_printf( " failed\n ! mbedtls_net_send returned %d\n\n", ret ); + goto exit; + } + + /* + * 6. Get the client's public value: Yc = G ^ Xc mod P + */ + mbedtls_printf( "\n . Receiving the client's public value" ); + fflush( stdout ); + + memset( buf, 0, sizeof( buf ) ); + + n = dhm.len; + if( ( ret = mbedtls_net_recv( &client_fd, buf, n ) ) != (int) n ) + { + mbedtls_printf( " failed\n ! mbedtls_net_recv returned %d\n\n", ret ); + goto exit; + } + + if( ( ret = mbedtls_dhm_read_public( &dhm, buf, dhm.len ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_dhm_read_public returned %d\n\n", ret ); + goto exit; + } + + /* + * 7. Derive the shared secret: K = Ys ^ Xc mod P + */ + mbedtls_printf( "\n . Shared secret: " ); + fflush( stdout ); + + if( ( ret = mbedtls_dhm_calc_secret( &dhm, buf, sizeof( buf ), &n, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_dhm_calc_secret returned %d\n\n", ret ); + goto exit; + } + + for( n = 0; n < 16; n++ ) + mbedtls_printf( "%02x", buf[n] ); + + /* + * 8. Setup the AES-256 encryption key + * + * This is an overly simplified example; best practice is + * to hash the shared secret with a random value to derive + * the keying material for the encryption/decryption keys + * and MACs. + */ + mbedtls_printf( "...\n . Encrypting and sending the ciphertext" ); + fflush( stdout ); + + mbedtls_aes_setkey_enc( &aes, buf, 256 ); + memcpy( buf, PLAINTEXT, 16 ); + mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_ENCRYPT, buf, buf ); + + if( ( ret = mbedtls_net_send( &client_fd, buf, 16 ) ) != 16 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_send returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( "\n\n" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + mbedtls_mpi_free( &N ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &E ); + + mbedtls_net_free( &client_fd ); + mbedtls_net_free( &listen_fd ); + + mbedtls_aes_free( &aes ); + mbedtls_rsa_free( &rsa ); + mbedtls_dhm_free( &dhm ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_AES_C && MBEDTLS_DHM_C && MBEDTLS_ENTROPY_C && + MBEDTLS_NET_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C && + MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */ diff --git a/external/mbedtls/programs/pkey/ecdh_curve25519.c b/external/mbedtls/programs/pkey/ecdh_curve25519.c new file mode 100644 index 0000000..1c10139 --- /dev/null +++ b/external/mbedtls/programs/pkey/ecdh_curve25519.c @@ -0,0 +1,269 @@ +/* + * Example ECDHE with Curve25519 program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDH_LEGACY_CONTEXT) || \ + !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf( "MBEDTLS_ECDH_C and/or MBEDTLS_ECDH_LEGACY_CONTEXT and/or " + "MBEDTLS_ECP_DP_CURVE25519_ENABLED and/or " + "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C " + "not defined\n" ); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/ecdh.h" + + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_ecdh_context ctx_cli, ctx_srv; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned char cli_to_srv[32], srv_to_cli[32]; + const char pers[] = "ecdh"; + ((void) argc); + ((void) argv); + + mbedtls_ecdh_init( &ctx_cli ); + mbedtls_ecdh_init( &ctx_srv ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + + /* + * Initialize random number generation + */ + mbedtls_printf( " . Seeding the random number generator..." ); + fflush( stdout ); + + mbedtls_entropy_init( &entropy ); + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + sizeof pers ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * Client: inialize context and generate keypair + */ + mbedtls_printf( " . Setting up client context..." ); + fflush( stdout ); + + ret = mbedtls_ecp_group_load( &ctx_cli.grp, MBEDTLS_ECP_DP_CURVE25519 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecp_group_load returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_ecdh_gen_public( &ctx_cli.grp, &ctx_cli.d, &ctx_cli.Q, + mbedtls_ctr_drbg_random, &ctr_drbg ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecdh_gen_public returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_mpi_write_binary( &ctx_cli.Q.X, cli_to_srv, 32 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_write_binary returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * Server: initialize context and generate keypair + */ + mbedtls_printf( " . Setting up server context..." ); + fflush( stdout ); + + ret = mbedtls_ecp_group_load( &ctx_srv.grp, MBEDTLS_ECP_DP_CURVE25519 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecp_group_load returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_ecdh_gen_public( &ctx_srv.grp, &ctx_srv.d, &ctx_srv.Q, + mbedtls_ctr_drbg_random, &ctr_drbg ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecdh_gen_public returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_mpi_write_binary( &ctx_srv.Q.X, srv_to_cli, 32 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_write_binary returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * Server: read peer's key and generate shared secret + */ + mbedtls_printf( " . Server reading client key and computing secret..." ); + fflush( stdout ); + + ret = mbedtls_mpi_lset( &ctx_srv.Qp.Z, 1 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_lset returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_mpi_read_binary( &ctx_srv.Qp.X, cli_to_srv, 32 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_read_binary returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_ecdh_compute_shared( &ctx_srv.grp, &ctx_srv.z, + &ctx_srv.Qp, &ctx_srv.d, + mbedtls_ctr_drbg_random, &ctr_drbg ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecdh_compute_shared returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * Client: read peer's key and generate shared secret + */ + mbedtls_printf( " . Client reading server key and computing secret..." ); + fflush( stdout ); + + ret = mbedtls_mpi_lset( &ctx_cli.Qp.Z, 1 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_lset returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_mpi_read_binary( &ctx_cli.Qp.X, srv_to_cli, 32 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_read_binary returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_ecdh_compute_shared( &ctx_cli.grp, &ctx_cli.z, + &ctx_cli.Qp, &ctx_cli.d, + mbedtls_ctr_drbg_random, &ctr_drbg ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecdh_compute_shared returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * Verification: are the computed secrets equal? + */ + mbedtls_printf( " . Checking if both computed secrets are equal..." ); + fflush( stdout ); + + ret = mbedtls_mpi_cmp_mpi( &ctx_cli.z, &ctx_srv.z ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecdh_compute_shared returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_ecdh_free( &ctx_srv ); + mbedtls_ecdh_free( &ctx_cli ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_ECDH_C && MBEDTLS_ECP_DP_CURVE25519_ENABLED && + MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */ diff --git a/external/mbedtls/programs/pkey/ecdsa.c b/external/mbedtls/programs/pkey/ecdsa.c new file mode 100644 index 0000000..2479164 --- /dev/null +++ b/external/mbedtls/programs/pkey/ecdsa.c @@ -0,0 +1,279 @@ +/* + * Example ECDSA program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_ECDSA_C) && \ + defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/ecdsa.h" +#include "mbedtls/sha256.h" + +#include +#endif + +/* + * Uncomment to show key and signature details + */ +#define VERBOSE + +/* + * Uncomment to force use of a specific curve + */ +#define ECPARAMS MBEDTLS_ECP_DP_SECP192R1 + +#if !defined(ECPARAMS) +#define ECPARAMS mbedtls_ecp_curve_list()->grp_id +#endif + +#if !defined(MBEDTLS_ECDSA_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_ECDSA_C and/or MBEDTLS_SHA256_C and/or " + "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C not defined\n"); + mbedtls_exit( 0 ); +} +#else +#if defined(VERBOSE) +static void dump_buf( const char *title, unsigned char *buf, size_t len ) +{ + size_t i; + + mbedtls_printf( "%s", title ); + for( i = 0; i < len; i++ ) + mbedtls_printf("%c%c", "0123456789ABCDEF" [buf[i] / 16], + "0123456789ABCDEF" [buf[i] % 16] ); + mbedtls_printf( "\n" ); +} + +static void dump_pubkey( const char *title, mbedtls_ecdsa_context *key ) +{ + unsigned char buf[300]; + size_t len; + + if( mbedtls_ecp_point_write_binary( &key->grp, &key->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, &len, buf, sizeof buf ) != 0 ) + { + mbedtls_printf("internal error\n"); + return; + } + + dump_buf( title, buf, len ); +} +#else +#define dump_buf( a, b, c ) +#define dump_pubkey( a, b ) +#endif + + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_ecdsa_context ctx_sign, ctx_verify; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned char message[100]; + unsigned char hash[32]; + unsigned char sig[MBEDTLS_ECDSA_MAX_LEN]; + size_t sig_len; + const char *pers = "ecdsa"; + ((void) argv); + + mbedtls_ecdsa_init( &ctx_sign ); + mbedtls_ecdsa_init( &ctx_verify ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + + memset( sig, 0, sizeof( sig ) ); + memset( message, 0x25, sizeof( message ) ); + + if( argc != 1 ) + { + mbedtls_printf( "usage: ecdsa\n" ); + +#if defined(_WIN32) + mbedtls_printf( "\n" ); +#endif + + goto exit; + } + + /* + * Generate a key pair for signing + */ + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + mbedtls_entropy_init( &entropy ); + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n . Generating key pair..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ecdsa_genkey( &ctx_sign, ECPARAMS, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecdsa_genkey returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok (key size: %d bits)\n", (int) ctx_sign.grp.pbits ); + + dump_pubkey( " + Public key: ", &ctx_sign ); + + /* + * Compute message hash + */ + mbedtls_printf( " . Computing message hash..." ); + fflush( stdout ); + + if( ( ret = mbedtls_sha256_ret( message, sizeof( message ), hash, 0 ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_sha256_ret returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + dump_buf( " + Hash: ", hash, sizeof( hash ) ); + + /* + * Sign message hash + */ + mbedtls_printf( " . Signing message hash..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ecdsa_write_signature( &ctx_sign, MBEDTLS_MD_SHA256, + hash, sizeof( hash ), + sig, &sig_len, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecdsa_write_signature returned %d\n", ret ); + goto exit; + } + mbedtls_printf( " ok (signature length = %u)\n", (unsigned int) sig_len ); + + dump_buf( " + Signature: ", sig, sig_len ); + + /* + * Transfer public information to verifying context + * + * We could use the same context for verification and signatures, but we + * chose to use a new one in order to make it clear that the verifying + * context only needs the public key (Q), and not the private key (d). + */ + mbedtls_printf( " . Preparing verification context..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ecp_group_copy( &ctx_verify.grp, &ctx_sign.grp ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecp_group_copy returned %d\n", ret ); + goto exit; + } + + if( ( ret = mbedtls_ecp_copy( &ctx_verify.Q, &ctx_sign.Q ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecp_copy returned %d\n", ret ); + goto exit; + } + + /* + * Verify signature + */ + mbedtls_printf( " ok\n . Verifying signature..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ecdsa_read_signature( &ctx_verify, + hash, sizeof( hash ), + sig, sig_len ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecdsa_read_signature returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_ecdsa_free( &ctx_verify ); + mbedtls_ecdsa_free( &ctx_sign ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C && + ECPARAMS */ diff --git a/external/mbedtls/programs/pkey/gen_key.c b/external/mbedtls/programs/pkey/gen_key.c new file mode 100644 index 0000000..76ed6d7 --- /dev/null +++ b/external/mbedtls/programs/pkey/gen_key.c @@ -0,0 +1,477 @@ +/* + * Key generation application + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_FS_IO) && \ + defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/error.h" +#include "mbedtls/pk.h" +#include "mbedtls/ecdsa.h" +#include "mbedtls/rsa.h" +#include "mbedtls/error.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include +#include +#include + +#if !defined(_WIN32) +#include + +#define DEV_RANDOM_THRESHOLD 32 + +int dev_random_entropy_poll( void *data, unsigned char *output, + size_t len, size_t *olen ) +{ + FILE *file; + size_t ret, left = len; + unsigned char *p = output; + ((void) data); + + *olen = 0; + + file = fopen( "/dev/random", "rb" ); + if( file == NULL ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + while( left > 0 ) + { + /* /dev/random can return much less than requested. If so, try again */ + ret = fread( p, 1, left, file ); + if( ret == 0 && ferror( file ) ) + { + fclose( file ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + p += ret; + left -= ret; + sleep( 1 ); + } + fclose( file ); + *olen = len; + + return( 0 ); +} +#endif /* !_WIN32 */ +#endif + +#if defined(MBEDTLS_ECP_C) +#define DFL_EC_CURVE mbedtls_ecp_curve_list()->grp_id +#else +#define DFL_EC_CURVE 0 +#endif + +#if !defined(_WIN32) && defined(MBEDTLS_FS_IO) +#define USAGE_DEV_RANDOM \ + " use_dev_random=0|1 default: 0\n" +#else +#define USAGE_DEV_RANDOM "" +#endif /* !_WIN32 && MBEDTLS_FS_IO */ + +#define FORMAT_PEM 0 +#define FORMAT_DER 1 + +#define DFL_TYPE MBEDTLS_PK_RSA +#define DFL_RSA_KEYSIZE 4096 +#define DFL_FILENAME "keyfile.key" +#define DFL_FORMAT FORMAT_PEM +#define DFL_USE_DEV_RANDOM 0 + +#define USAGE \ + "\n usage: gen_key param=<>...\n" \ + "\n acceptable parameters:\n" \ + " type=rsa|ec default: rsa\n" \ + " rsa_keysize=%%d default: 4096\n" \ + " ec_curve=%%s see below\n" \ + " filename=%%s default: keyfile.key\n" \ + " format=pem|der default: pem\n" \ + USAGE_DEV_RANDOM \ + "\n" + +#if !defined(MBEDTLS_PK_WRITE_C) || !defined(MBEDTLS_PEM_WRITE_C) || \ + !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf( "MBEDTLS_PK_WRITE_C and/or MBEDTLS_FS_IO and/or " + "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or " + "MBEDTLS_PEM_WRITE_C" + "not defined.\n" ); + mbedtls_exit( 0 ); +} +#else + + +/* + * global options + */ +struct options +{ + int type; /* the type of key to generate */ + int rsa_keysize; /* length of key in bits */ + int ec_curve; /* curve identifier for EC keys */ + const char *filename; /* filename of the key file */ + int format; /* the output format to use */ + int use_dev_random; /* use /dev/random as entropy source */ +} opt; + +static int write_private_key( mbedtls_pk_context *key, const char *output_file ) +{ + int ret; + FILE *f; + unsigned char output_buf[16000]; + unsigned char *c = output_buf; + size_t len = 0; + + memset(output_buf, 0, 16000); + if( opt.format == FORMAT_PEM ) + { + if( ( ret = mbedtls_pk_write_key_pem( key, output_buf, 16000 ) ) != 0 ) + return( ret ); + + len = strlen( (char *) output_buf ); + } + else + { + if( ( ret = mbedtls_pk_write_key_der( key, output_buf, 16000 ) ) < 0 ) + return( ret ); + + len = ret; + c = output_buf + sizeof(output_buf) - len; + } + + if( ( f = fopen( output_file, "wb" ) ) == NULL ) + return( -1 ); + + if( fwrite( c, 1, len, f ) != len ) + { + fclose( f ); + return( -1 ); + } + + fclose( f ); + + return( 0 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_pk_context key; + char buf[1024]; + int i; + char *p, *q; + mbedtls_mpi N, P, Q, D, E, DP, DQ, QP; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + const char *pers = "gen_key"; +#if defined(MBEDTLS_ECP_C) + const mbedtls_ecp_curve_info *curve_info; +#endif + + /* + * Set to sane values + */ + + mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &DP ); + mbedtls_mpi_init( &DQ ); mbedtls_mpi_init( &QP ); + + mbedtls_pk_init( &key ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + memset( buf, 0, sizeof( buf ) ); + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); +#if defined(MBEDTLS_ECP_C) + mbedtls_printf( " available ec_curve values:\n" ); + curve_info = mbedtls_ecp_curve_list(); + mbedtls_printf( " %s (default)\n", curve_info->name ); + while( ( ++curve_info )->name != NULL ) + mbedtls_printf( " %s\n", curve_info->name ); +#endif /* MBEDTLS_ECP_C */ + goto exit; + } + + opt.type = DFL_TYPE; + opt.rsa_keysize = DFL_RSA_KEYSIZE; + opt.ec_curve = DFL_EC_CURVE; + opt.filename = DFL_FILENAME; + opt.format = DFL_FORMAT; + opt.use_dev_random = DFL_USE_DEV_RANDOM; + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "type" ) == 0 ) + { + if( strcmp( q, "rsa" ) == 0 ) + opt.type = MBEDTLS_PK_RSA; + else if( strcmp( q, "ec" ) == 0 ) + opt.type = MBEDTLS_PK_ECKEY; + else + goto usage; + } + else if( strcmp( p, "format" ) == 0 ) + { + if( strcmp( q, "pem" ) == 0 ) + opt.format = FORMAT_PEM; + else if( strcmp( q, "der" ) == 0 ) + opt.format = FORMAT_DER; + else + goto usage; + } + else if( strcmp( p, "rsa_keysize" ) == 0 ) + { + opt.rsa_keysize = atoi( q ); + if( opt.rsa_keysize < 1024 || + opt.rsa_keysize > MBEDTLS_MPI_MAX_BITS ) + goto usage; + } +#if defined(MBEDTLS_ECP_C) + else if( strcmp( p, "ec_curve" ) == 0 ) + { + if( ( curve_info = mbedtls_ecp_curve_info_from_name( q ) ) == NULL ) + goto usage; + opt.ec_curve = curve_info->grp_id; + } +#endif + else if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else if( strcmp( p, "use_dev_random" ) == 0 ) + { + opt.use_dev_random = atoi( q ); + if( opt.use_dev_random < 0 || opt.use_dev_random > 1 ) + goto usage; + } + else + goto usage; + } + + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + mbedtls_entropy_init( &entropy ); +#if !defined(_WIN32) && defined(MBEDTLS_FS_IO) + if( opt.use_dev_random ) + { + if( ( ret = mbedtls_entropy_add_source( &entropy, dev_random_entropy_poll, + NULL, DEV_RANDOM_THRESHOLD, + MBEDTLS_ENTROPY_SOURCE_STRONG ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_entropy_add_source returned -0x%04x\n", -ret ); + goto exit; + } + + mbedtls_printf("\n Using /dev/random, so can take a long time! " ); + fflush( stdout ); + } +#endif /* !_WIN32 && MBEDTLS_FS_IO */ + + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n", -ret ); + goto exit; + } + + /* + * 1.1. Generate the key + */ + mbedtls_printf( "\n . Generating the private key ..." ); + fflush( stdout ); + + if( ( ret = mbedtls_pk_setup( &key, + mbedtls_pk_info_from_type( (mbedtls_pk_type_t) opt.type ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_setup returned -0x%04x", -ret ); + goto exit; + } + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) + if( opt.type == MBEDTLS_PK_RSA ) + { + ret = mbedtls_rsa_gen_key( mbedtls_pk_rsa( key ), mbedtls_ctr_drbg_random, &ctr_drbg, + opt.rsa_keysize, 65537 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_gen_key returned -0x%04x", -ret ); + goto exit; + } + } + else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( opt.type == MBEDTLS_PK_ECKEY ) + { + ret = mbedtls_ecp_gen_key( (mbedtls_ecp_group_id) opt.ec_curve, + mbedtls_pk_ec( key ), + mbedtls_ctr_drbg_random, &ctr_drbg ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecp_gen_key returned -0x%04x", -ret ); + goto exit; + } + } + else +#endif /* MBEDTLS_ECP_C */ + { + mbedtls_printf( " failed\n ! key type not supported\n" ); + goto exit; + } + + /* + * 1.2 Print the key + */ + mbedtls_printf( " ok\n . Key information:\n" ); + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( &key ) == MBEDTLS_PK_RSA ) + { + mbedtls_rsa_context *rsa = mbedtls_pk_rsa( key ); + + if( ( ret = mbedtls_rsa_export ( rsa, &N, &P, &Q, &D, &E ) ) != 0 || + ( ret = mbedtls_rsa_export_crt( rsa, &DP, &DQ, &QP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! could not export RSA parameters\n\n" ); + goto exit; + } + + mbedtls_mpi_write_file( "N: ", &N, 16, NULL ); + mbedtls_mpi_write_file( "E: ", &E, 16, NULL ); + mbedtls_mpi_write_file( "D: ", &D, 16, NULL ); + mbedtls_mpi_write_file( "P: ", &P, 16, NULL ); + mbedtls_mpi_write_file( "Q: ", &Q, 16, NULL ); + mbedtls_mpi_write_file( "DP: ", &DP, 16, NULL ); + mbedtls_mpi_write_file( "DQ: ", &DQ, 16, NULL ); + mbedtls_mpi_write_file( "QP: ", &QP, 16, NULL ); + } + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( &key ) == MBEDTLS_PK_ECKEY ) + { + mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( key ); + mbedtls_printf( "curve: %s\n", + mbedtls_ecp_curve_info_from_grp_id( ecp->grp.id )->name ); + mbedtls_mpi_write_file( "X_Q: ", &ecp->Q.X, 16, NULL ); + mbedtls_mpi_write_file( "Y_Q: ", &ecp->Q.Y, 16, NULL ); + mbedtls_mpi_write_file( "D: ", &ecp->d , 16, NULL ); + } + else +#endif + mbedtls_printf(" ! key type not supported\n"); + + /* + * 1.3 Export key + */ + mbedtls_printf( " . Writing key to file..." ); + + if( ( ret = write_private_key( &key, opt.filename ) ) != 0 ) + { + mbedtls_printf( " failed\n" ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + if( exit_code != MBEDTLS_EXIT_SUCCESS ) + { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror( ret, buf, sizeof( buf ) ); + mbedtls_printf( " - %s\n", buf ); +#else + mbedtls_printf("\n"); +#endif + } + + mbedtls_mpi_free( &N ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &DP ); + mbedtls_mpi_free( &DQ ); mbedtls_mpi_free( &QP ); + + mbedtls_pk_free( &key ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_PK_WRITE_C && MBEDTLS_PEM_WRITE_C && MBEDTLS_FS_IO && + * MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */ diff --git a/external/mbedtls/programs/pkey/key_app.c b/external/mbedtls/programs/pkey/key_app.c new file mode 100644 index 0000000..c6bd192 --- /dev/null +++ b/external/mbedtls/programs/pkey/key_app.c @@ -0,0 +1,341 @@ +/* + * Key reading application + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_BIGNUM_C) && \ + defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_FS_IO) +#include "mbedtls/error.h" +#include "mbedtls/rsa.h" +#include "mbedtls/x509.h" + +#include +#endif + +#define MODE_NONE 0 +#define MODE_PRIVATE 1 +#define MODE_PUBLIC 2 + +#define DFL_MODE MODE_NONE +#define DFL_FILENAME "keyfile.key" +#define DFL_PASSWORD "" +#define DFL_PASSWORD_FILE "" +#define DFL_DEBUG_LEVEL 0 + +#define USAGE \ + "\n usage: key_app param=<>...\n" \ + "\n acceptable parameters:\n" \ + " mode=private|public default: none\n" \ + " filename=%%s default: keyfile.key\n" \ + " password=%%s default: \"\"\n" \ + " password_file=%%s default: \"\"\n" \ + "\n" + +#if !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_PK_PARSE_C) || !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or " + "MBEDTLS_PK_PARSE_C and/or MBEDTLS_FS_IO not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +/* + * global options + */ +struct options +{ + int mode; /* the mode to run the application in */ + const char *filename; /* filename of the key file */ + const char *password; /* password for the private key */ + const char *password_file; /* password_file for the private key */ +} opt; + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + char buf[1024]; + int i; + char *p, *q; + + mbedtls_pk_context pk; + mbedtls_mpi N, P, Q, D, E, DP, DQ, QP; + + /* + * Set to sane values + */ + mbedtls_pk_init( &pk ); + memset( buf, 0, sizeof(buf) ); + + mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &DP ); + mbedtls_mpi_init( &DQ ); mbedtls_mpi_init( &QP ); + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + goto cleanup; + } + + opt.mode = DFL_MODE; + opt.filename = DFL_FILENAME; + opt.password = DFL_PASSWORD; + opt.password_file = DFL_PASSWORD_FILE; + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "mode" ) == 0 ) + { + if( strcmp( q, "private" ) == 0 ) + opt.mode = MODE_PRIVATE; + else if( strcmp( q, "public" ) == 0 ) + opt.mode = MODE_PUBLIC; + else + goto usage; + } + else if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else if( strcmp( p, "password" ) == 0 ) + opt.password = q; + else if( strcmp( p, "password_file" ) == 0 ) + opt.password_file = q; + else + goto usage; + } + + if( opt.mode == MODE_PRIVATE ) + { + if( strlen( opt.password ) && strlen( opt.password_file ) ) + { + mbedtls_printf( "Error: cannot have both password and password_file\n" ); + goto usage; + } + + if( strlen( opt.password_file ) ) + { + FILE *f; + + mbedtls_printf( "\n . Loading the password file ..." ); + if( ( f = fopen( opt.password_file, "rb" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! fopen returned NULL\n" ); + goto cleanup; + } + if( fgets( buf, sizeof(buf), f ) == NULL ) + { + fclose( f ); + mbedtls_printf( "Error: fgets() failed to retrieve password\n" ); + goto cleanup; + } + fclose( f ); + + i = (int) strlen( buf ); + if( buf[i - 1] == '\n' ) buf[i - 1] = '\0'; + if( buf[i - 2] == '\r' ) buf[i - 2] = '\0'; + opt.password = buf; + } + + /* + * 1.1. Load the key + */ + mbedtls_printf( "\n . Loading the private key ..." ); + fflush( stdout ); + + ret = mbedtls_pk_parse_keyfile( &pk, opt.filename, opt.password ); + + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned -0x%04x\n", -ret ); + goto cleanup; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.2 Print the key + */ + mbedtls_printf( " . Key information ...\n" ); +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( &pk ) == MBEDTLS_PK_RSA ) + { + mbedtls_rsa_context *rsa = mbedtls_pk_rsa( pk ); + + if( ( ret = mbedtls_rsa_export ( rsa, &N, &P, &Q, &D, &E ) ) != 0 || + ( ret = mbedtls_rsa_export_crt( rsa, &DP, &DQ, &QP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! could not export RSA parameters\n\n" ); + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "N: ", &N, 16, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "E: ", &E, 16, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "D: ", &D, 16, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "P: ", &P, 16, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q: ", &Q, 16, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "DP: ", &DP, 16, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "DQ: ", &DQ, 16, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "QP: ", &QP, 16, NULL ) ); + } + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( &pk ) == MBEDTLS_PK_ECKEY ) + { + mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( pk ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "D : ", &ecp->d , 16, NULL ) ); + } + else +#endif + { + mbedtls_printf("Do not know how to print key information for this type\n" ); + goto cleanup; + } + } + else if( opt.mode == MODE_PUBLIC ) + { + /* + * 1.1. Load the key + */ + mbedtls_printf( "\n . Loading the public key ..." ); + fflush( stdout ); + + ret = mbedtls_pk_parse_public_keyfile( &pk, opt.filename ); + + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_public_keyfile returned -0x%04x\n", -ret ); + goto cleanup; + } + + mbedtls_printf( " ok\n" ); + + mbedtls_printf( " . Key information ...\n" ); +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( &pk ) == MBEDTLS_PK_RSA ) + { + mbedtls_rsa_context *rsa = mbedtls_pk_rsa( pk ); + + if( ( ret = mbedtls_rsa_export( rsa, &N, NULL, NULL, + NULL, &E ) ) != 0 ) + { + mbedtls_printf( " failed\n ! could not export RSA parameters\n\n" ); + goto cleanup; + } + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "N: ", &N, 16, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "E: ", &E, 16, NULL ) ); + } + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( &pk ) == MBEDTLS_PK_ECKEY ) + { + mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( pk ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL ) ); + } + else +#endif + { + mbedtls_printf("Do not know how to print key information for this type\n" ); + goto cleanup; + } + } + else + goto usage; + + exit_code = MBEDTLS_EXIT_SUCCESS; + +cleanup: + +#if defined(MBEDTLS_ERROR_C) + if( exit_code != MBEDTLS_EXIT_SUCCESS ) + { + mbedtls_strerror( ret, buf, sizeof( buf ) ); + mbedtls_printf( " ! Last error was: %s\n", buf ); + } +#endif + + mbedtls_pk_free( &pk ); + mbedtls_mpi_free( &N ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &DP ); + mbedtls_mpi_free( &DQ ); mbedtls_mpi_free( &QP ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO */ diff --git a/external/mbedtls/programs/pkey/key_app_writer.c b/external/mbedtls/programs/pkey/key_app_writer.c new file mode 100644 index 0000000..afe024a --- /dev/null +++ b/external/mbedtls/programs/pkey/key_app_writer.c @@ -0,0 +1,466 @@ +/* + * Key writing application + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_FS_IO) +#include "mbedtls/error.h" +#include "mbedtls/pk.h" +#include "mbedtls/error.h" + +#include +#include +#endif + +#if defined(MBEDTLS_PEM_WRITE_C) +#define USAGE_OUT \ + " output_file=%%s default: keyfile.pem\n" \ + " output_format=pem|der default: pem\n" +#else +#define USAGE_OUT \ + " output_file=%%s default: keyfile.der\n" \ + " output_format=der default: der\n" +#endif + +#if defined(MBEDTLS_PEM_WRITE_C) +#define DFL_OUTPUT_FILENAME "keyfile.pem" +#define DFL_OUTPUT_FORMAT OUTPUT_FORMAT_PEM +#else +#define DFL_OUTPUT_FILENAME "keyfile.der" +#define DFL_OUTPUT_FORMAT OUTPUT_FORMAT_DER +#endif + +#define DFL_MODE MODE_NONE +#define DFL_FILENAME "keyfile.key" +#define DFL_DEBUG_LEVEL 0 +#define DFL_OUTPUT_MODE OUTPUT_MODE_NONE + +#define MODE_NONE 0 +#define MODE_PRIVATE 1 +#define MODE_PUBLIC 2 + +#define OUTPUT_MODE_NONE 0 +#define OUTPUT_MODE_PRIVATE 1 +#define OUTPUT_MODE_PUBLIC 2 + +#define OUTPUT_FORMAT_PEM 0 +#define OUTPUT_FORMAT_DER 1 + +#define USAGE \ + "\n usage: key_app_writer param=<>...\n" \ + "\n acceptable parameters:\n" \ + " mode=private|public default: none\n" \ + " filename=%%s default: keyfile.key\n" \ + " output_mode=private|public default: none\n" \ + USAGE_OUT \ + "\n" + +#if !defined(MBEDTLS_PK_PARSE_C) || \ + !defined(MBEDTLS_PK_WRITE_C) || \ + !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf( "MBEDTLS_PK_PARSE_C and/or MBEDTLS_PK_WRITE_C and/or MBEDTLS_FS_IO not defined.\n" ); + mbedtls_exit( 0 ); +} +#else + + +/* + * global options + */ +struct options +{ + int mode; /* the mode to run the application in */ + const char *filename; /* filename of the key file */ + int output_mode; /* the output mode to use */ + const char *output_file; /* where to store the constructed key file */ + int output_format; /* the output format to use */ +} opt; + +static int write_public_key( mbedtls_pk_context *key, const char *output_file ) +{ + int ret; + FILE *f; + unsigned char output_buf[16000]; + unsigned char *c = output_buf; + size_t len = 0; + + memset(output_buf, 0, 16000); + +#if defined(MBEDTLS_PEM_WRITE_C) + if( opt.output_format == OUTPUT_FORMAT_PEM ) + { + if( ( ret = mbedtls_pk_write_pubkey_pem( key, output_buf, 16000 ) ) != 0 ) + return( ret ); + + len = strlen( (char *) output_buf ); + } + else +#endif + { + if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf, 16000 ) ) < 0 ) + return( ret ); + + len = ret; + c = output_buf + sizeof(output_buf) - len; + } + + if( ( f = fopen( output_file, "w" ) ) == NULL ) + return( -1 ); + + if( fwrite( c, 1, len, f ) != len ) + { + fclose( f ); + return( -1 ); + } + + fclose( f ); + + return( 0 ); +} + +static int write_private_key( mbedtls_pk_context *key, const char *output_file ) +{ + int ret; + FILE *f; + unsigned char output_buf[16000]; + unsigned char *c = output_buf; + size_t len = 0; + + memset(output_buf, 0, 16000); + +#if defined(MBEDTLS_PEM_WRITE_C) + if( opt.output_format == OUTPUT_FORMAT_PEM ) + { + if( ( ret = mbedtls_pk_write_key_pem( key, output_buf, 16000 ) ) != 0 ) + return( ret ); + + len = strlen( (char *) output_buf ); + } + else +#endif + { + if( ( ret = mbedtls_pk_write_key_der( key, output_buf, 16000 ) ) < 0 ) + return( ret ); + + len = ret; + c = output_buf + sizeof(output_buf) - len; + } + + if( ( f = fopen( output_file, "w" ) ) == NULL ) + return( -1 ); + + if( fwrite( c, 1, len, f ) != len ) + { + fclose( f ); + return( -1 ); + } + + fclose( f ); + + return( 0 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + char buf[1024]; + int i; + char *p, *q; + + mbedtls_pk_context key; + mbedtls_mpi N, P, Q, D, E, DP, DQ, QP; + + /* + * Set to sane values + */ + mbedtls_pk_init( &key ); + memset( buf, 0, sizeof( buf ) ); + + mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &DP ); + mbedtls_mpi_init( &DQ ); mbedtls_mpi_init( &QP ); + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + goto exit; + } + + opt.mode = DFL_MODE; + opt.filename = DFL_FILENAME; + opt.output_mode = DFL_OUTPUT_MODE; + opt.output_file = DFL_OUTPUT_FILENAME; + opt.output_format = DFL_OUTPUT_FORMAT; + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "mode" ) == 0 ) + { + if( strcmp( q, "private" ) == 0 ) + opt.mode = MODE_PRIVATE; + else if( strcmp( q, "public" ) == 0 ) + opt.mode = MODE_PUBLIC; + else + goto usage; + } + else if( strcmp( p, "output_mode" ) == 0 ) + { + if( strcmp( q, "private" ) == 0 ) + opt.output_mode = OUTPUT_MODE_PRIVATE; + else if( strcmp( q, "public" ) == 0 ) + opt.output_mode = OUTPUT_MODE_PUBLIC; + else + goto usage; + } + else if( strcmp( p, "output_format" ) == 0 ) + { +#if defined(MBEDTLS_PEM_WRITE_C) + if( strcmp( q, "pem" ) == 0 ) + opt.output_format = OUTPUT_FORMAT_PEM; + else +#endif + if( strcmp( q, "der" ) == 0 ) + opt.output_format = OUTPUT_FORMAT_DER; + else + goto usage; + } + else if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else if( strcmp( p, "output_file" ) == 0 ) + opt.output_file = q; + else + goto usage; + } + + if( opt.mode == MODE_NONE && opt.output_mode != OUTPUT_MODE_NONE ) + { + mbedtls_printf( "\nCannot output a key without reading one.\n"); + goto exit; + } + + if( opt.mode == MODE_PUBLIC && opt.output_mode == OUTPUT_MODE_PRIVATE ) + { + mbedtls_printf( "\nCannot output a private key from a public key.\n"); + goto exit; + } + + if( opt.mode == MODE_PRIVATE ) + { + /* + * 1.1. Load the key + */ + mbedtls_printf( "\n . Loading the private key ..." ); + fflush( stdout ); + + ret = mbedtls_pk_parse_keyfile( &key, opt.filename, NULL ); + + if( ret != 0 ) + { + mbedtls_strerror( ret, (char *) buf, sizeof(buf) ); + mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.2 Print the key + */ + mbedtls_printf( " . Key information ...\n" ); + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( &key ) == MBEDTLS_PK_RSA ) + { + mbedtls_rsa_context *rsa = mbedtls_pk_rsa( key ); + + if( ( ret = mbedtls_rsa_export ( rsa, &N, &P, &Q, &D, &E ) ) != 0 || + ( ret = mbedtls_rsa_export_crt( rsa, &DP, &DQ, &QP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! could not export RSA parameters\n\n" ); + goto exit; + } + + mbedtls_mpi_write_file( "N: ", &N, 16, NULL ); + mbedtls_mpi_write_file( "E: ", &E, 16, NULL ); + mbedtls_mpi_write_file( "D: ", &D, 16, NULL ); + mbedtls_mpi_write_file( "P: ", &P, 16, NULL ); + mbedtls_mpi_write_file( "Q: ", &Q, 16, NULL ); + mbedtls_mpi_write_file( "DP: ", &DP, 16, NULL ); + mbedtls_mpi_write_file( "DQ: ", &DQ, 16, NULL ); + mbedtls_mpi_write_file( "QP: ", &QP, 16, NULL ); + } + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( &key ) == MBEDTLS_PK_ECKEY ) + { + mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( key ); + mbedtls_mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL ); + mbedtls_mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL ); + mbedtls_mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL ); + mbedtls_mpi_write_file( "D : ", &ecp->d , 16, NULL ); + } + else +#endif + mbedtls_printf("key type not supported yet\n"); + + } + else if( opt.mode == MODE_PUBLIC ) + { + /* + * 1.1. Load the key + */ + mbedtls_printf( "\n . Loading the public key ..." ); + fflush( stdout ); + + ret = mbedtls_pk_parse_public_keyfile( &key, opt.filename ); + + if( ret != 0 ) + { + mbedtls_strerror( ret, (char *) buf, sizeof(buf) ); + mbedtls_printf( " failed\n ! mbedtls_pk_parse_public_key returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.2 Print the key + */ + mbedtls_printf( " . Key information ...\n" ); + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( &key ) == MBEDTLS_PK_RSA ) + { + mbedtls_rsa_context *rsa = mbedtls_pk_rsa( key ); + + if( ( ret = mbedtls_rsa_export( rsa, &N, NULL, NULL, + NULL, &E ) ) != 0 ) + { + mbedtls_printf( " failed\n ! could not export RSA parameters\n\n" ); + goto exit; + } + mbedtls_mpi_write_file( "N: ", &N, 16, NULL ); + mbedtls_mpi_write_file( "E: ", &E, 16, NULL ); + } + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( &key ) == MBEDTLS_PK_ECKEY ) + { + mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( key ); + mbedtls_mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL ); + mbedtls_mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL ); + mbedtls_mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL ); + } + else +#endif + mbedtls_printf("key type not supported yet\n"); + } + else + goto usage; + + if( opt.output_mode == OUTPUT_MODE_PUBLIC ) + { + write_public_key( &key, opt.output_file ); + } + if( opt.output_mode == OUTPUT_MODE_PRIVATE ) + { + write_private_key( &key, opt.output_file ); + } + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + if( exit_code != MBEDTLS_EXIT_SUCCESS ) + { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror( ret, buf, sizeof( buf ) ); + mbedtls_printf( " - %s\n", buf ); +#else + mbedtls_printf("\n"); +#endif + } + + mbedtls_mpi_free( &N ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &DP ); + mbedtls_mpi_free( &DQ ); mbedtls_mpi_free( &QP ); + + mbedtls_pk_free( &key ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_PK_PARSE_C && MBEDTLS_PK_WRITE_C && MBEDTLS_FS_IO */ diff --git a/external/mbedtls/programs/pkey/mpi_demo.c b/external/mbedtls/programs/pkey/mpi_demo.c new file mode 100644 index 0000000..e7df647 --- /dev/null +++ b/external/mbedtls/programs/pkey/mpi_demo.c @@ -0,0 +1,142 @@ +/* + * Simple MPI demonstration program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_FS_IO) +#include "mbedtls/bignum.h" + +#include +#endif + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_FS_IO not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +int main( void ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_mpi E, P, Q, N, H, D, X, Y, Z; + + mbedtls_mpi_init( &E ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); mbedtls_mpi_init( &N ); + mbedtls_mpi_init( &H ); mbedtls_mpi_init( &D ); mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); + mbedtls_mpi_init( &Z ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P, 10, "2789" ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &Q, 10, "3203" ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 10, "257" ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &N, &P, &Q ) ); + + mbedtls_printf( "\n Public key:\n\n" ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " N = ", &N, 10, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " E = ", &E, 10, NULL ) ); + + mbedtls_printf( "\n Private key:\n\n" ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " P = ", &P, 10, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " Q = ", &Q, 10, NULL ) ); + +#if defined(MBEDTLS_GENPRIME) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P, &P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q, &Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P, &Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &D, &E, &H ) ); + + mbedtls_mpi_write_file( " D = E^-1 mod (P-1)*(Q-1) = ", + &D, 10, NULL ); +#else + mbedtls_printf("\nTest skipped (MBEDTLS_GENPRIME not defined).\n\n"); +#endif + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &X, 10, "55555" ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &Y, &X, &E, &N, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &Z, &Y, &D, &N, NULL ) ); + + mbedtls_printf( "\n RSA operation:\n\n" ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " X (plaintext) = ", &X, 10, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " Y (ciphertext) = X^E mod N = ", &Y, 10, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " Z (decrypted) = Y^D mod N = ", &Z, 10, NULL ) ); + mbedtls_printf( "\n" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +cleanup: + mbedtls_mpi_free( &E ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); mbedtls_mpi_free( &N ); + mbedtls_mpi_free( &H ); mbedtls_mpi_free( &D ); mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); + mbedtls_mpi_free( &Z ); + + if( exit_code != MBEDTLS_EXIT_SUCCESS ) + { + mbedtls_printf( "\nAn error occurred.\n" ); + } + +#if defined(_WIN32) + mbedtls_printf( " Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_FS_IO */ diff --git a/external/mbedtls/programs/pkey/pk_decrypt.c b/external/mbedtls/programs/pkey/pk_decrypt.c new file mode 100644 index 0000000..e53d6fd --- /dev/null +++ b/external/mbedtls/programs/pkey/pk_decrypt.c @@ -0,0 +1,203 @@ +/* + * Public key-based simple decryption program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_PK_PARSE_C) && \ + defined(MBEDTLS_FS_IO) && defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/error.h" +#include "mbedtls/pk.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include +#include +#endif + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_PK_PARSE_C) || \ + !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_PK_PARSE_C and/or " + "MBEDTLS_FS_IO and/or MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_CTR_DRBG_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +int main( int argc, char *argv[] ) +{ + FILE *f; + int ret = 1; + unsigned c; + int exit_code = MBEDTLS_EXIT_FAILURE; + size_t i, olen = 0; + mbedtls_pk_context pk; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned char result[1024]; + unsigned char buf[512]; + const char *pers = "mbedtls_pk_decrypt"; + ((void) argv); + + mbedtls_pk_init( &pk ); + mbedtls_entropy_init( &entropy ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + + memset(result, 0, sizeof( result ) ); + + if( argc != 2 ) + { + mbedtls_printf( "usage: mbedtls_pk_decrypt \n" ); + +#if defined(_WIN32) + mbedtls_printf( "\n" ); +#endif + + goto exit; + } + + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, + &entropy, (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n", + -ret ); + goto exit; + } + + mbedtls_printf( "\n . Reading private key from '%s'", argv[1] ); + fflush( stdout ); + + if( ( ret = mbedtls_pk_parse_keyfile( &pk, argv[1], "" ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned -0x%04x\n", -ret ); + goto exit; + } + + /* + * Extract the RSA encrypted value from the text file + */ + if( ( f = fopen( "result-enc.txt", "rb" ) ) == NULL ) + { + mbedtls_printf( "\n ! Could not open %s\n\n", "result-enc.txt" ); + ret = 1; + goto exit; + } + + i = 0; + while( fscanf( f, "%02X", &c ) > 0 && + i < (int) sizeof( buf ) ) + { + buf[i++] = (unsigned char) c; + } + + fclose( f ); + + /* + * Decrypt the encrypted RSA data and print the result. + */ + mbedtls_printf( "\n . Decrypting the encrypted data" ); + fflush( stdout ); + + if( ( ret = mbedtls_pk_decrypt( &pk, buf, i, result, &olen, sizeof(result), + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_decrypt returned -0x%04x\n", + -ret ); + goto exit; + } + + mbedtls_printf( "\n . OK\n\n" ); + + mbedtls_printf( "The decrypted result is: '%s'\n\n", result ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + mbedtls_pk_free( &pk ); + mbedtls_entropy_free( &entropy ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + +#if defined(MBEDTLS_ERROR_C) + if( exit_code != MBEDTLS_EXIT_SUCCESS ) + { + mbedtls_strerror( ret, (char *) buf, sizeof( buf ) ); + mbedtls_printf( " ! Last error was: %s\n", buf ); + } +#endif + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO && + MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */ diff --git a/external/mbedtls/programs/pkey/pk_encrypt.c b/external/mbedtls/programs/pkey/pk_encrypt.c new file mode 100644 index 0000000..4e359fd --- /dev/null +++ b/external/mbedtls/programs/pkey/pk_encrypt.c @@ -0,0 +1,207 @@ +/* + * RSA simple data encryption program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_PK_PARSE_C) && \ + defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_FS_IO) && \ + defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/error.h" +#include "mbedtls/pk.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include +#include +#endif + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_PK_PARSE_C) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_FS_IO) || \ + !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_PK_PARSE_C and/or " + "MBEDTLS_ENTROPY_C and/or MBEDTLS_FS_IO and/or " + "MBEDTLS_CTR_DRBG_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +int main( int argc, char *argv[] ) +{ + FILE *f; + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + size_t i, olen = 0; + mbedtls_pk_context pk; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned char input[1024]; + unsigned char buf[512]; + const char *pers = "mbedtls_pk_encrypt"; + + mbedtls_ctr_drbg_init( &ctr_drbg ); + mbedtls_entropy_init( &entropy ); + mbedtls_pk_init( &pk ); + + if( argc != 3 ) + { + mbedtls_printf( "usage: mbedtls_pk_encrypt \n" ); + +#if defined(_WIN32) + mbedtls_printf( "\n" ); +#endif + + goto exit; + } + + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, + &entropy, (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n", + -ret ); + goto exit; + } + + mbedtls_printf( "\n . Reading public key from '%s'", argv[1] ); + fflush( stdout ); + + if( ( ret = mbedtls_pk_parse_public_keyfile( &pk, argv[1] ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_public_keyfile returned -0x%04x\n", -ret ); + goto exit; + } + + if( strlen( argv[2] ) > 100 ) + { + mbedtls_printf( " Input data larger than 100 characters.\n\n" ); + goto exit; + } + + memcpy( input, argv[2], strlen( argv[2] ) ); + + /* + * Calculate the RSA encryption of the hash. + */ + mbedtls_printf( "\n . Generating the encrypted value" ); + fflush( stdout ); + + if( ( ret = mbedtls_pk_encrypt( &pk, input, strlen( argv[2] ), + buf, &olen, sizeof(buf), + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_encrypt returned -0x%04x\n", + -ret ); + goto exit; + } + + /* + * Write the signature into result-enc.txt + */ + if( ( f = fopen( "result-enc.txt", "wb+" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! Could not create %s\n\n", + "result-enc.txt" ); + ret = 1; + goto exit; + } + + for( i = 0; i < olen; i++ ) + { + mbedtls_fprintf( f, "%02X%s", buf[i], + ( i + 1 ) % 16 == 0 ? "\r\n" : " " ); + } + + fclose( f ); + + mbedtls_printf( "\n . Done (created \"%s\")\n\n", "result-enc.txt" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + mbedtls_pk_free( &pk ); + mbedtls_entropy_free( &entropy ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + +#if defined(MBEDTLS_ERROR_C) + if( exit_code != MBEDTLS_EXIT_SUCCESS ) + { + mbedtls_strerror( ret, (char *) buf, sizeof( buf ) ); + mbedtls_printf( " ! Last error was: %s\n", buf ); + } +#endif + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_ENTROPY_C && + MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */ diff --git a/external/mbedtls/programs/pkey/pk_sign.c b/external/mbedtls/programs/pkey/pk_sign.c new file mode 100644 index 0000000..8b875b2 --- /dev/null +++ b/external/mbedtls/programs/pkey/pk_sign.c @@ -0,0 +1,216 @@ +/* + * Public key-based signature creation program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_snprintf snprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_MD_C) || \ + !defined(MBEDTLS_PK_PARSE_C) || !defined(MBEDTLS_FS_IO) || \ + !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_SHA256_C and/or MBEDTLS_MD_C and/or " + "MBEDTLS_PK_PARSE_C and/or MBEDTLS_FS_IO and/or " + "MBEDTLS_CTR_DRBG_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/error.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/md.h" +#include "mbedtls/pk.h" + +#include +#include + + +/* + * For the currently used signature algorithms the buffer to store any signature + * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE) + */ +#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE +#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN +#else +#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif + +int main( int argc, char *argv[] ) +{ + FILE *f; + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_pk_context pk; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned char hash[32]; + unsigned char buf[SIGNATURE_MAX_SIZE]; + char filename[512]; + const char *pers = "mbedtls_pk_sign"; + size_t olen = 0; + + mbedtls_entropy_init( &entropy ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + mbedtls_pk_init( &pk ); + + if( argc != 3 ) + { + mbedtls_printf( "usage: mbedtls_pk_sign \n" ); + +#if defined(_WIN32) + mbedtls_printf( "\n" ); +#endif + + goto exit; + } + + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n", -ret ); + goto exit; + } + + mbedtls_printf( "\n . Reading private key from '%s'", argv[1] ); + fflush( stdout ); + + if( ( ret = mbedtls_pk_parse_keyfile( &pk, argv[1], "" ) ) != 0 ) + { + mbedtls_printf( " failed\n ! Could not parse '%s'\n", argv[1] ); + goto exit; + } + + /* + * Compute the SHA-256 hash of the input file, + * then calculate the signature of the hash. + */ + mbedtls_printf( "\n . Generating the SHA-256 signature" ); + fflush( stdout ); + + if( ( ret = mbedtls_md_file( + mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), + argv[2], hash ) ) != 0 ) + { + mbedtls_printf( " failed\n ! Could not open or read %s\n\n", argv[2] ); + goto exit; + } + + if( ( ret = mbedtls_pk_sign( &pk, MBEDTLS_MD_SHA256, hash, 0, buf, &olen, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_sign returned -0x%04x\n", -ret ); + goto exit; + } + + /* + * Write the signature into .sig + */ + mbedtls_snprintf( filename, sizeof(filename), "%s.sig", argv[2] ); + + if( ( f = fopen( filename, "wb+" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! Could not create %s\n\n", filename ); + goto exit; + } + + if( fwrite( buf, 1, olen, f ) != olen ) + { + mbedtls_printf( "failed\n ! fwrite failed\n\n" ); + fclose( f ); + goto exit; + } + + fclose( f ); + + mbedtls_printf( "\n . Done (created \"%s\")\n\n", filename ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + mbedtls_pk_free( &pk ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(MBEDTLS_ERROR_C) + if( exit_code != MBEDTLS_EXIT_SUCCESS ) + { + mbedtls_strerror( ret, (char *) buf, sizeof(buf) ); + mbedtls_printf( " ! Last error was: %s\n", buf ); + } +#endif + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && + MBEDTLS_SHA256_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO && + MBEDTLS_CTR_DRBG_C */ diff --git a/external/mbedtls/programs/pkey/pk_verify.c b/external/mbedtls/programs/pkey/pk_verify.c new file mode 100644 index 0000000..5969488 --- /dev/null +++ b/external/mbedtls/programs/pkey/pk_verify.c @@ -0,0 +1,178 @@ +/* + * Public key-based signature verification program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_snprintf snprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_MD_C) || \ + !defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_PK_PARSE_C) || \ + !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_MD_C and/or " + "MBEDTLS_SHA256_C and/or MBEDTLS_PK_PARSE_C and/or " + "MBEDTLS_FS_IO not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/error.h" +#include "mbedtls/md.h" +#include "mbedtls/pk.h" + +#include +#include + + +int main( int argc, char *argv[] ) +{ + FILE *f; + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + size_t i; + mbedtls_pk_context pk; + unsigned char hash[32]; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + char filename[512]; + + mbedtls_pk_init( &pk ); + + if( argc != 3 ) + { + mbedtls_printf( "usage: mbedtls_pk_verify \n" ); + +#if defined(_WIN32) + mbedtls_printf( "\n" ); +#endif + + goto exit; + } + + mbedtls_printf( "\n . Reading public key from '%s'", argv[1] ); + fflush( stdout ); + + if( ( ret = mbedtls_pk_parse_public_keyfile( &pk, argv[1] ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_public_keyfile returned -0x%04x\n", -ret ); + goto exit; + } + + /* + * Extract the signature from the file + */ + mbedtls_snprintf( filename, sizeof(filename), "%s.sig", argv[2] ); + + if( ( f = fopen( filename, "rb" ) ) == NULL ) + { + mbedtls_printf( "\n ! Could not open %s\n\n", filename ); + goto exit; + } + + i = fread( buf, 1, sizeof(buf), f ); + + fclose( f ); + + /* + * Compute the SHA-256 hash of the input file and + * verify the signature + */ + mbedtls_printf( "\n . Verifying the SHA-256 signature" ); + fflush( stdout ); + + if( ( ret = mbedtls_md_file( + mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), + argv[2], hash ) ) != 0 ) + { + mbedtls_printf( " failed\n ! Could not open or read %s\n\n", argv[2] ); + goto exit; + } + + if( ( ret = mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256, hash, 0, + buf, i ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_verify returned -0x%04x\n", -ret ); + goto exit; + } + + mbedtls_printf( "\n . OK (the signature is valid)\n\n" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + mbedtls_pk_free( &pk ); + +#if defined(MBEDTLS_ERROR_C) + if( exit_code != MBEDTLS_EXIT_SUCCESS ) + { + mbedtls_strerror( ret, (char *) buf, sizeof(buf) ); + mbedtls_printf( " ! Last error was: %s\n", buf ); + } +#endif + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_SHA256_C && + MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO */ diff --git a/external/mbedtls/programs/pkey/rsa_decrypt.c b/external/mbedtls/programs/pkey/rsa_decrypt.c new file mode 100644 index 0000000..3f8823d --- /dev/null +++ b/external/mbedtls/programs/pkey/rsa_decrypt.c @@ -0,0 +1,237 @@ +/* + * RSA simple decryption program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_RSA_C) && \ + defined(MBEDTLS_FS_IO) && defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/rsa.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include + +#endif + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_FS_IO and/or MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_CTR_DRBG_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +int main( int argc, char *argv[] ) +{ + FILE *f; + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + unsigned c; + size_t i; + mbedtls_rsa_context rsa; + mbedtls_mpi N, P, Q, D, E, DP, DQ, QP; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned char result[1024]; + unsigned char buf[512]; + const char *pers = "rsa_decrypt"; + ((void) argv); + + memset(result, 0, sizeof( result ) ); + + if( argc != 1 ) + { + mbedtls_printf( "usage: rsa_decrypt\n" ); + +#if defined(_WIN32) + mbedtls_printf( "\n" ); +#endif + + mbedtls_exit( exit_code ); + } + + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + mbedtls_entropy_init( &entropy ); + mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &DP ); + mbedtls_mpi_init( &DQ ); mbedtls_mpi_init( &QP ); + + ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, + &entropy, (const unsigned char *) pers, + strlen( pers ) ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", + ret ); + goto exit; + } + + mbedtls_printf( "\n . Reading private key from rsa_priv.txt" ); + fflush( stdout ); + + if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! Could not open rsa_priv.txt\n" \ + " ! Please run rsa_genkey first\n\n" ); + goto exit; + } + + if( ( ret = mbedtls_mpi_read_file( &N , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &E , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &D , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &P , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &Q , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &DP , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &DQ , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &QP , 16, f ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", + ret ); + fclose( f ); + goto exit; + } + fclose( f ); + + if( ( ret = mbedtls_rsa_import( &rsa, &N, &P, &Q, &D, &E ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_import returned %d\n\n", + ret ); + goto exit; + } + + if( ( ret = mbedtls_rsa_complete( &rsa ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_complete returned %d\n\n", + ret ); + goto exit; + } + + /* + * Extract the RSA encrypted value from the text file + */ + if( ( f = fopen( "result-enc.txt", "rb" ) ) == NULL ) + { + mbedtls_printf( "\n ! Could not open %s\n\n", "result-enc.txt" ); + goto exit; + } + + i = 0; + + while( fscanf( f, "%02X", &c ) > 0 && + i < (int) sizeof( buf ) ) + buf[i++] = (unsigned char) c; + + fclose( f ); + + if( i != rsa.len ) + { + mbedtls_printf( "\n ! Invalid RSA signature format\n\n" ); + goto exit; + } + + /* + * Decrypt the encrypted RSA data and print the result. + */ + mbedtls_printf( "\n . Decrypting the encrypted data" ); + fflush( stdout ); + + ret = mbedtls_rsa_pkcs1_decrypt( &rsa, mbedtls_ctr_drbg_random, + &ctr_drbg, MBEDTLS_RSA_PRIVATE, &i, + buf, result, 1024 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_decrypt returned %d\n\n", + ret ); + goto exit; + } + + mbedtls_printf( "\n . OK\n\n" ); + + mbedtls_printf( "The decrypted result is: '%s'\n\n", result ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + mbedtls_rsa_free( &rsa ); + mbedtls_mpi_free( &N ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &DP ); + mbedtls_mpi_free( &DQ ); mbedtls_mpi_free( &QP ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_FS_IO */ diff --git a/external/mbedtls/programs/pkey/rsa_encrypt.c b/external/mbedtls/programs/pkey/rsa_encrypt.c new file mode 100644 index 0000000..c206173 --- /dev/null +++ b/external/mbedtls/programs/pkey/rsa_encrypt.c @@ -0,0 +1,215 @@ +/* + * RSA simple data encryption program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_RSA_C) && \ + defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_FS_IO) && \ + defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/rsa.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include +#endif + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_FS_IO) || \ + !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_ENTROPY_C and/or MBEDTLS_FS_IO and/or " + "MBEDTLS_CTR_DRBG_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +int main( int argc, char *argv[] ) +{ + FILE *f; + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + size_t i; + mbedtls_rsa_context rsa; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned char input[1024]; + unsigned char buf[512]; + const char *pers = "rsa_encrypt"; + mbedtls_mpi N, E; + + if( argc != 2 ) + { + mbedtls_printf( "usage: rsa_encrypt \n" ); + +#if defined(_WIN32) + mbedtls_printf( "\n" ); +#endif + + mbedtls_exit( exit_code ); + } + + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + mbedtls_mpi_init( &N ); mbedtls_mpi_init( &E ); + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + mbedtls_entropy_init( &entropy ); + + ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, + &entropy, (const unsigned char *) pers, + strlen( pers ) ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", + ret ); + goto exit; + } + + mbedtls_printf( "\n . Reading public key from rsa_pub.txt" ); + fflush( stdout ); + + if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! Could not open rsa_pub.txt\n" \ + " ! Please run rsa_genkey first\n\n" ); + goto exit; + } + + if( ( ret = mbedtls_mpi_read_file( &N, 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &E, 16, f ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", + ret ); + fclose( f ); + goto exit; + } + fclose( f ); + + if( ( ret = mbedtls_rsa_import( &rsa, &N, NULL, NULL, NULL, &E ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_import returned %d\n\n", + ret ); + goto exit; + } + + if( strlen( argv[1] ) > 100 ) + { + mbedtls_printf( " Input data larger than 100 characters.\n\n" ); + goto exit; + } + + memcpy( input, argv[1], strlen( argv[1] ) ); + + /* + * Calculate the RSA encryption of the hash. + */ + mbedtls_printf( "\n . Generating the RSA encrypted value" ); + fflush( stdout ); + + ret = mbedtls_rsa_pkcs1_encrypt( &rsa, mbedtls_ctr_drbg_random, + &ctr_drbg, MBEDTLS_RSA_PUBLIC, + strlen( argv[1] ), input, buf ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_encrypt returned %d\n\n", + ret ); + goto exit; + } + + /* + * Write the signature into result-enc.txt + */ + if( ( f = fopen( "result-enc.txt", "wb+" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! Could not create %s\n\n", "result-enc.txt" ); + goto exit; + } + + for( i = 0; i < rsa.len; i++ ) + mbedtls_fprintf( f, "%02X%s", buf[i], + ( i + 1 ) % 16 == 0 ? "\r\n" : " " ); + + fclose( f ); + + mbedtls_printf( "\n . Done (created \"%s\")\n\n", "result-enc.txt" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + mbedtls_mpi_free( &N ); mbedtls_mpi_free( &E ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + mbedtls_rsa_free( &rsa ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_ENTROPY_C && + MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */ diff --git a/external/mbedtls/programs/pkey/rsa_genkey.c b/external/mbedtls/programs/pkey/rsa_genkey.c new file mode 100644 index 0000000..7e08c05 --- /dev/null +++ b/external/mbedtls/programs/pkey/rsa_genkey.c @@ -0,0 +1,217 @@ +/* + * Example RSA key generation program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) && \ + defined(MBEDTLS_FS_IO) && defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/bignum.h" +#include "mbedtls/x509.h" +#include "mbedtls/rsa.h" + +#include +#include +#endif + +#define KEY_SIZE 2048 +#define EXPONENT 65537 + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_GENPRIME) || \ + !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_RSA_C and/or MBEDTLS_GENPRIME and/or " + "MBEDTLS_FS_IO and/or MBEDTLS_CTR_DRBG_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +int main( void ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_rsa_context rsa; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_mpi N, P, Q, D, E, DP, DQ, QP; + FILE *fpub = NULL; + FILE *fpriv = NULL; + const char *pers = "rsa_genkey"; + + mbedtls_ctr_drbg_init( &ctr_drbg ); + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &DP ); + mbedtls_mpi_init( &DQ ); mbedtls_mpi_init( &QP ); + + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + mbedtls_entropy_init( &entropy ); + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n . Generating the RSA key [ %d-bit ]...", KEY_SIZE ); + fflush( stdout ); + + if( ( ret = mbedtls_rsa_gen_key( &rsa, mbedtls_ctr_drbg_random, &ctr_drbg, KEY_SIZE, + EXPONENT ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_gen_key returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n . Exporting the public key in rsa_pub.txt...." ); + fflush( stdout ); + + if( ( ret = mbedtls_rsa_export ( &rsa, &N, &P, &Q, &D, &E ) ) != 0 || + ( ret = mbedtls_rsa_export_crt( &rsa, &DP, &DQ, &QP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! could not export RSA parameters\n\n" ); + goto exit; + } + + if( ( fpub = fopen( "rsa_pub.txt", "wb+" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! could not open rsa_pub.txt for writing\n\n" ); + goto exit; + } + + if( ( ret = mbedtls_mpi_write_file( "N = ", &N, 16, fpub ) ) != 0 || + ( ret = mbedtls_mpi_write_file( "E = ", &E, 16, fpub ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_write_file returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n . Exporting the private key in rsa_priv.txt..." ); + fflush( stdout ); + + if( ( fpriv = fopen( "rsa_priv.txt", "wb+" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! could not open rsa_priv.txt for writing\n" ); + goto exit; + } + + if( ( ret = mbedtls_mpi_write_file( "N = " , &N , 16, fpriv ) ) != 0 || + ( ret = mbedtls_mpi_write_file( "E = " , &E , 16, fpriv ) ) != 0 || + ( ret = mbedtls_mpi_write_file( "D = " , &D , 16, fpriv ) ) != 0 || + ( ret = mbedtls_mpi_write_file( "P = " , &P , 16, fpriv ) ) != 0 || + ( ret = mbedtls_mpi_write_file( "Q = " , &Q , 16, fpriv ) ) != 0 || + ( ret = mbedtls_mpi_write_file( "DP = ", &DP, 16, fpriv ) ) != 0 || + ( ret = mbedtls_mpi_write_file( "DQ = ", &DQ, 16, fpriv ) ) != 0 || + ( ret = mbedtls_mpi_write_file( "QP = ", &QP, 16, fpriv ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_write_file returned %d\n\n", ret ); + goto exit; + } +/* + mbedtls_printf( " ok\n . Generating the certificate..." ); + + x509write_init_raw( &cert ); + x509write_add_pubkey( &cert, &rsa ); + x509write_add_subject( &cert, "CN='localhost'" ); + x509write_add_validity( &cert, "2007-09-06 17:00:32", + "2010-09-06 17:00:32" ); + x509write_create_selfsign( &cert, &rsa ); + x509write_crtfile( &cert, "cert.der", X509_OUTPUT_DER ); + x509write_crtfile( &cert, "cert.pem", X509_OUTPUT_PEM ); + x509write_free_raw( &cert ); +*/ + mbedtls_printf( " ok\n\n" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + if( fpub != NULL ) + fclose( fpub ); + + if( fpriv != NULL ) + fclose( fpriv ); + + mbedtls_mpi_free( &N ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &DP ); + mbedtls_mpi_free( &DQ ); mbedtls_mpi_free( &QP ); + mbedtls_rsa_free( &rsa ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_RSA_C && + MBEDTLS_GENPRIME && MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */ diff --git a/external/mbedtls/programs/pkey/rsa_priv.txt b/external/mbedtls/programs/pkey/rsa_priv.txt new file mode 100644 index 0000000..254fcf8 --- /dev/null +++ b/external/mbedtls/programs/pkey/rsa_priv.txt @@ -0,0 +1,8 @@ +N = A1D46FBA2318F8DCEF16C280948B1CF27966B9B47225ED2989F8D74B45BD36049C0AAB5AD0FF003553BA843C8E12782FC5873BB89A3DC84B883D25666CD22BF3ACD5B675969F8BEBFBCAC93FDD927C7442B178B10D1DFF9398E52316AAE0AF74E594650BDC3C670241D418684593CDA1A7B9DC4F20D2FDC6F66344074003E211 +E = 010001 +D = 589552BB4F2F023ADDDD5586D0C8FD857512D82080436678D07F984A29D892D31F1F7000FC5A39A0F73E27D885E47249A4148C8A5653EF69F91F8F736BA9F84841C2D99CD8C24DE8B72B5C9BE0EDBE23F93D731749FEA9CFB4A48DD2B7F35A2703E74AA2D4DB7DE9CEEA7D763AF0ADA7AC176C4E9A22C4CDA65CEC0C65964401 +P = CD083568D2D46C44C40C1FA0101AF2155E59C70B08423112AF0C1202514BBA5210765E29FF13036F56C7495894D80CF8C3BAEE2839BACBB0B86F6A2965F60DB1 +Q = CA0EEEA5E710E8E9811A6B846399420E3AE4A4C16647E426DDF8BBBCB11CD3F35CE2E4B6BCAD07AE2C0EC2ECBFCC601B207CDD77B5673E16382B1130BF465261 +DP = 0D0E21C07BF434B4A83B116472C2147A11D8EB98A33CFBBCF1D275EF19D815941622435AAF3839B6C432CA53CE9E772CFBE1923A937A766FD93E96E6EDEC1DF1 +DQ = 269CEBE6305DFEE4809377F078C814E37B45AE6677114DFC4F76F5097E1F3031D592567AC55B9B98213B40ECD54A4D2361F5FAACA1B1F51F71E4690893C4F081 +QP = 97AC5BB885ABCA314375E9E4DB1BA4B2218C90619F61BD474F5785075ECA81750A735199A8C191FE2D3355E7CF601A70E5CABDE0E02C2538BB9FB4871540B3C1 diff --git a/external/mbedtls/programs/pkey/rsa_pub.txt b/external/mbedtls/programs/pkey/rsa_pub.txt new file mode 100644 index 0000000..1e7ae0c --- /dev/null +++ b/external/mbedtls/programs/pkey/rsa_pub.txt @@ -0,0 +1,2 @@ +N = A1D46FBA2318F8DCEF16C280948B1CF27966B9B47225ED2989F8D74B45BD36049C0AAB5AD0FF003553BA843C8E12782FC5873BB89A3DC84B883D25666CD22BF3ACD5B675969F8BEBFBCAC93FDD927C7442B178B10D1DFF9398E52316AAE0AF74E594650BDC3C670241D418684593CDA1A7B9DC4F20D2FDC6F66344074003E211 +E = 010001 diff --git a/external/mbedtls/programs/pkey/rsa_sign.c b/external/mbedtls/programs/pkey/rsa_sign.c new file mode 100644 index 0000000..ea7e450 --- /dev/null +++ b/external/mbedtls/programs/pkey/rsa_sign.c @@ -0,0 +1,219 @@ +/* + * RSA/SHA-256 signature creation program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_snprintf snprintf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_MD_C) || \ + !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_MD_C and/or " + "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/rsa.h" +#include "mbedtls/md.h" + +#include +#include + + +int main( int argc, char *argv[] ) +{ + FILE *f; + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + size_t i; + mbedtls_rsa_context rsa; + unsigned char hash[32]; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + char filename[512]; + mbedtls_mpi N, P, Q, D, E, DP, DQ, QP; + + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + + mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &DP ); + mbedtls_mpi_init( &DQ ); mbedtls_mpi_init( &QP ); + + if( argc != 2 ) + { + mbedtls_printf( "usage: rsa_sign \n" ); + +#if defined(_WIN32) + mbedtls_printf( "\n" ); +#endif + + goto exit; + } + + mbedtls_printf( "\n . Reading private key from rsa_priv.txt" ); + fflush( stdout ); + + if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! Could not open rsa_priv.txt\n" \ + " ! Please run rsa_genkey first\n\n" ); + goto exit; + } + + if( ( ret = mbedtls_mpi_read_file( &N , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &E , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &D , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &P , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &Q , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &DP , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &DQ , 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &QP , 16, f ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", ret ); + fclose( f ); + goto exit; + } + fclose( f ); + + if( ( ret = mbedtls_rsa_import( &rsa, &N, &P, &Q, &D, &E ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_import returned %d\n\n", + ret ); + goto exit; + } + + if( ( ret = mbedtls_rsa_complete( &rsa ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_complete returned %d\n\n", + ret ); + goto exit; + } + + mbedtls_printf( "\n . Checking the private key" ); + fflush( stdout ); + if( ( ret = mbedtls_rsa_check_privkey( &rsa ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_check_privkey failed with -0x%0x\n", -ret ); + goto exit; + } + + /* + * Compute the SHA-256 hash of the input file, + * then calculate the RSA signature of the hash. + */ + mbedtls_printf( "\n . Generating the RSA/SHA-256 signature" ); + fflush( stdout ); + + if( ( ret = mbedtls_md_file( + mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), + argv[1], hash ) ) != 0 ) + { + mbedtls_printf( " failed\n ! Could not open or read %s\n\n", argv[1] ); + goto exit; + } + + if( ( ret = mbedtls_rsa_pkcs1_sign( &rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256, + 20, hash, buf ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_sign returned -0x%0x\n\n", -ret ); + goto exit; + } + + /* + * Write the signature into .sig + */ + mbedtls_snprintf( filename, sizeof(filename), "%s.sig", argv[1] ); + + if( ( f = fopen( filename, "wb+" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! Could not create %s\n\n", argv[1] ); + goto exit; + } + + for( i = 0; i < rsa.len; i++ ) + mbedtls_fprintf( f, "%02X%s", buf[i], + ( i + 1 ) % 16 == 0 ? "\r\n" : " " ); + + fclose( f ); + + mbedtls_printf( "\n . Done (created \"%s\")\n\n", filename ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + mbedtls_rsa_free( &rsa ); + mbedtls_mpi_free( &N ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &DP ); + mbedtls_mpi_free( &DQ ); mbedtls_mpi_free( &QP ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C && + MBEDTLS_FS_IO */ diff --git a/external/mbedtls/programs/pkey/rsa_sign_pss.c b/external/mbedtls/programs/pkey/rsa_sign_pss.c new file mode 100644 index 0000000..b5ab26e --- /dev/null +++ b/external/mbedtls/programs/pkey/rsa_sign_pss.c @@ -0,0 +1,207 @@ +/* + * RSASSA-PSS/SHA-256 signature creation program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_snprintf snprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_MD_C) || !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_PK_PARSE_C) || !defined(MBEDTLS_FS_IO) || \ + !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_MD_C and/or MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_RSA_C and/or MBEDTLS_SHA256_C and/or " + "MBEDTLS_PK_PARSE_C and/or MBEDTLS_FS_IO and/or " + "MBEDTLS_CTR_DRBG_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/md.h" +#include "mbedtls/rsa.h" +#include "mbedtls/x509.h" + +#include +#include + + +int main( int argc, char *argv[] ) +{ + FILE *f; + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_pk_context pk; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned char hash[32]; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + char filename[512]; + const char *pers = "rsa_sign_pss"; + size_t olen = 0; + + mbedtls_entropy_init( &entropy ); + mbedtls_pk_init( &pk ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + + if( argc != 3 ) + { + mbedtls_printf( "usage: rsa_sign_pss \n" ); + +#if defined(_WIN32) + mbedtls_printf( "\n" ); +#endif + + goto exit; + } + + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( "\n . Reading private key from '%s'", argv[1] ); + fflush( stdout ); + + if( ( ret = mbedtls_pk_parse_keyfile( &pk, argv[1], "" ) ) != 0 ) + { + mbedtls_printf( " failed\n ! Could not read key from '%s'\n", argv[1] ); + mbedtls_printf( " ! mbedtls_pk_parse_public_keyfile returned %d\n\n", ret ); + goto exit; + } + + if( !mbedtls_pk_can_do( &pk, MBEDTLS_PK_RSA ) ) + { + mbedtls_printf( " failed\n ! Key is not an RSA key\n" ); + goto exit; + } + + mbedtls_rsa_set_padding( mbedtls_pk_rsa( pk ), MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256 ); + + /* + * Compute the SHA-256 hash of the input file, + * then calculate the RSA signature of the hash. + */ + mbedtls_printf( "\n . Generating the RSA/SHA-256 signature" ); + fflush( stdout ); + + if( ( ret = mbedtls_md_file( + mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), + argv[2], hash ) ) != 0 ) + { + mbedtls_printf( " failed\n ! Could not open or read %s\n\n", argv[2] ); + goto exit; + } + + if( ( ret = mbedtls_pk_sign( &pk, MBEDTLS_MD_SHA256, hash, 0, buf, &olen, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_sign returned %d\n\n", ret ); + goto exit; + } + + /* + * Write the signature into .sig + */ + mbedtls_snprintf( filename, 512, "%s.sig", argv[2] ); + + if( ( f = fopen( filename, "wb+" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! Could not create %s\n\n", filename ); + goto exit; + } + + if( fwrite( buf, 1, olen, f ) != olen ) + { + mbedtls_printf( "failed\n ! fwrite failed\n\n" ); + fclose( f ); + goto exit; + } + + fclose( f ); + + mbedtls_printf( "\n . Done (created \"%s\")\n\n", filename ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + mbedtls_pk_free( &pk ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_RSA_C && + MBEDTLS_SHA256_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO && + MBEDTLS_CTR_DRBG_C */ diff --git a/external/mbedtls/programs/pkey/rsa_verify.c b/external/mbedtls/programs/pkey/rsa_verify.c new file mode 100644 index 0000000..809c434 --- /dev/null +++ b/external/mbedtls/programs/pkey/rsa_verify.c @@ -0,0 +1,193 @@ +/* + * RSA/SHA-256 signature verification program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_snprintf snprintf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_MD_C) || \ + !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_MD_C and/or " + "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/rsa.h" +#include "mbedtls/md.h" + +#include +#include + + +int main( int argc, char *argv[] ) +{ + FILE *f; + int ret = 1; + unsigned c; + int exit_code = MBEDTLS_EXIT_FAILURE; + size_t i; + mbedtls_rsa_context rsa; + unsigned char hash[32]; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + char filename[512]; + + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + + if( argc != 2 ) + { + mbedtls_printf( "usage: rsa_verify \n" ); + +#if defined(_WIN32) + mbedtls_printf( "\n" ); +#endif + + goto exit; + } + + mbedtls_printf( "\n . Reading public key from rsa_pub.txt" ); + fflush( stdout ); + + if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL ) + { + mbedtls_printf( " failed\n ! Could not open rsa_pub.txt\n" \ + " ! Please run rsa_genkey first\n\n" ); + goto exit; + } + + if( ( ret = mbedtls_mpi_read_file( &rsa.N, 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &rsa.E, 16, f ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", ret ); + fclose( f ); + goto exit; + } + + rsa.len = ( mbedtls_mpi_bitlen( &rsa.N ) + 7 ) >> 3; + + fclose( f ); + + /* + * Extract the RSA signature from the text file + */ + mbedtls_snprintf( filename, sizeof(filename), "%s.sig", argv[1] ); + + if( ( f = fopen( filename, "rb" ) ) == NULL ) + { + mbedtls_printf( "\n ! Could not open %s\n\n", filename ); + goto exit; + } + + i = 0; + while( fscanf( f, "%02X", &c ) > 0 && + i < (int) sizeof( buf ) ) + buf[i++] = (unsigned char) c; + + fclose( f ); + + if( i != rsa.len ) + { + mbedtls_printf( "\n ! Invalid RSA signature format\n\n" ); + goto exit; + } + + /* + * Compute the SHA-256 hash of the input file and + * verify the signature + */ + mbedtls_printf( "\n . Verifying the RSA/SHA-256 signature" ); + fflush( stdout ); + + if( ( ret = mbedtls_md_file( + mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), + argv[1], hash ) ) != 0 ) + { + mbedtls_printf( " failed\n ! Could not open or read %s\n\n", argv[1] ); + goto exit; + } + + if( ( ret = mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, + MBEDTLS_MD_SHA256, 20, hash, buf ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_verify returned -0x%0x\n\n", -ret ); + goto exit; + } + + mbedtls_printf( "\n . OK (the signature is valid)\n\n" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + mbedtls_rsa_free( &rsa ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C && + MBEDTLS_FS_IO */ diff --git a/external/mbedtls/programs/pkey/rsa_verify_pss.c b/external/mbedtls/programs/pkey/rsa_verify_pss.c new file mode 100644 index 0000000..b67be4a --- /dev/null +++ b/external/mbedtls/programs/pkey/rsa_verify_pss.c @@ -0,0 +1,183 @@ +/* + * RSASSA-PSS/SHA-256 signature verification program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_snprintf snprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_MD_C) || !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_PK_PARSE_C) || !defined(MBEDTLS_FS_IO) || \ + !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_MD_C and/or MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_RSA_C and/or MBEDTLS_SHA256_C and/or " + "MBEDTLS_PK_PARSE_C and/or MBEDTLS_FS_IO and/or " + "MBEDTLS_CTR_DRBG_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/md.h" +#include "mbedtls/pem.h" +#include "mbedtls/pk.h" +#include "mbedtls/md.h" +#include "mbedtls/x509.h" + +#include +#include + + +int main( int argc, char *argv[] ) +{ + FILE *f; + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + size_t i; + mbedtls_pk_context pk; + unsigned char hash[32]; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + char filename[512]; + + mbedtls_pk_init( &pk ); + + if( argc != 3 ) + { + mbedtls_printf( "usage: rsa_verify_pss \n" ); + +#if defined(_WIN32) + mbedtls_printf( "\n" ); +#endif + + goto exit; + } + + mbedtls_printf( "\n . Reading public key from '%s'", argv[1] ); + fflush( stdout ); + + if( ( ret = mbedtls_pk_parse_public_keyfile( &pk, argv[1] ) ) != 0 ) + { + mbedtls_printf( " failed\n ! Could not read key from '%s'\n", argv[1] ); + mbedtls_printf( " ! mbedtls_pk_parse_public_keyfile returned %d\n\n", ret ); + goto exit; + } + + if( !mbedtls_pk_can_do( &pk, MBEDTLS_PK_RSA ) ) + { + mbedtls_printf( " failed\n ! Key is not an RSA key\n" ); + goto exit; + } + + mbedtls_rsa_set_padding( mbedtls_pk_rsa( pk ), MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256 ); + + /* + * Extract the RSA signature from the file + */ + mbedtls_snprintf( filename, 512, "%s.sig", argv[2] ); + + if( ( f = fopen( filename, "rb" ) ) == NULL ) + { + mbedtls_printf( "\n ! Could not open %s\n\n", filename ); + goto exit; + } + + i = fread( buf, 1, MBEDTLS_MPI_MAX_SIZE, f ); + + fclose( f ); + + /* + * Compute the SHA-256 hash of the input file and + * verify the signature + */ + mbedtls_printf( "\n . Verifying the RSA/SHA-256 signature" ); + fflush( stdout ); + + if( ( ret = mbedtls_md_file( + mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), + argv[2], hash ) ) != 0 ) + { + mbedtls_printf( " failed\n ! Could not open or read %s\n\n", argv[2] ); + goto exit; + } + + if( ( ret = mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256, hash, 0, + buf, i ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_verify returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( "\n . OK (the signature is valid)\n\n" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + mbedtls_pk_free( &pk ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C && + MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO */ diff --git a/external/mbedtls/programs/random/CMakeLists.txt b/external/mbedtls/programs/random/CMakeLists.txt new file mode 100644 index 0000000..30933d8 --- /dev/null +++ b/external/mbedtls/programs/random/CMakeLists.txt @@ -0,0 +1,12 @@ +add_executable(gen_random_havege gen_random_havege.c) +target_link_libraries(gen_random_havege mbedtls) + +add_executable(gen_random_ctr_drbg gen_random_ctr_drbg.c) +target_link_libraries(gen_random_ctr_drbg mbedtls) + +add_executable(gen_entropy gen_entropy.c) +target_link_libraries(gen_entropy mbedtls) + +install(TARGETS gen_random_havege gen_random_ctr_drbg gen_entropy + DESTINATION "bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/external/mbedtls/programs/random/gen_entropy.c b/external/mbedtls/programs/random/gen_entropy.c new file mode 100644 index 0000000..671df5b --- /dev/null +++ b/external/mbedtls/programs/random/gen_entropy.c @@ -0,0 +1,129 @@ +/** + * \brief Use and generate multiple entropies calls into a file + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_FS_IO) +#include "mbedtls/entropy.h" + +#include +#endif + +#if !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_ENTROPY_C and/or MBEDTLS_FS_IO not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +int main( int argc, char *argv[] ) +{ + FILE *f; + int i, k, ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_entropy_context entropy; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( argc < 2 ) + { + mbedtls_fprintf( stderr, "usage: %s \n", argv[0] ); + mbedtls_exit( exit_code ); + } + + if( ( f = fopen( argv[1], "wb+" ) ) == NULL ) + { + mbedtls_printf( "failed to open '%s' for writing.\n", argv[1] ); + mbedtls_exit( exit_code ); + } + + mbedtls_entropy_init( &entropy ); + + for( i = 0, k = 768; i < k; i++ ) + { + ret = mbedtls_entropy_func( &entropy, buf, sizeof( buf ) ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_entropy_func returned -%04X\n", + ret ); + goto cleanup; + } + + fwrite( buf, 1, sizeof( buf ), f ); + + mbedtls_printf( "Generating %ldkb of data in file '%s'... %04.1f" \ + "%% done\r", (long)(sizeof(buf) * k / 1024), argv[1], (100 * (float) (i + 1)) / k ); + fflush( stdout ); + } + + exit_code = MBEDTLS_EXIT_SUCCESS; + +cleanup: + mbedtls_printf( "\n" ); + + fclose( f ); + mbedtls_entropy_free( &entropy ); + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/external/mbedtls/programs/random/gen_random_ctr_drbg.c b/external/mbedtls/programs/random/gen_random_ctr_drbg.c new file mode 100644 index 0000000..0eb1477 --- /dev/null +++ b/external/mbedtls/programs/random/gen_random_ctr_drbg.c @@ -0,0 +1,162 @@ +/** + * \brief Use and generate random data into a file via the CTR_DBRG based on AES + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_CTR_DRBG_C) && defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_FS_IO) +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include +#endif + +#if !defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_CTR_DRBG_C and/or MBEDTLS_ENTROPY_C and/or MBEDTLS_FS_IO not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +int main( int argc, char *argv[] ) +{ + FILE *f; + int i, k, ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_entropy_context entropy; + unsigned char buf[1024]; + + mbedtls_ctr_drbg_init( &ctr_drbg ); + + if( argc < 2 ) + { + mbedtls_fprintf( stderr, "usage: %s \n", argv[0] ); + mbedtls_exit( exit_code ); + } + + if( ( f = fopen( argv[1], "wb+" ) ) == NULL ) + { + mbedtls_printf( "failed to open '%s' for writing.\n", argv[1] ); + mbedtls_exit( exit_code ); + } + + mbedtls_entropy_init( &entropy ); + ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) "RANDOM_GEN", 10 ); + if( ret != 0 ) + { + mbedtls_printf( "failed in mbedtls_ctr_drbg_seed: %d\n", ret ); + goto cleanup; + } + mbedtls_ctr_drbg_set_prediction_resistance( &ctr_drbg, MBEDTLS_CTR_DRBG_PR_OFF ); + +#if defined(MBEDTLS_FS_IO) + ret = mbedtls_ctr_drbg_update_seed_file( &ctr_drbg, "seedfile" ); + + if( ret == MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ) + { + mbedtls_printf( "Failed to open seedfile. Generating one.\n" ); + ret = mbedtls_ctr_drbg_write_seed_file( &ctr_drbg, "seedfile" ); + if( ret != 0 ) + { + mbedtls_printf( "failed in mbedtls_ctr_drbg_write_seed_file: %d\n", ret ); + goto cleanup; + } + } + else if( ret != 0 ) + { + mbedtls_printf( "failed in mbedtls_ctr_drbg_update_seed_file: %d\n", ret ); + goto cleanup; + } +#endif + + for( i = 0, k = 768; i < k; i++ ) + { + ret = mbedtls_ctr_drbg_random( &ctr_drbg, buf, sizeof( buf ) ); + if( ret != 0 ) + { + mbedtls_printf("failed!\n"); + goto cleanup; + } + + fwrite( buf, 1, sizeof( buf ), f ); + + mbedtls_printf( "Generating %ldkb of data in file '%s'... %04.1f" \ + "%% done\r", (long)(sizeof(buf) * k / 1024), argv[1], (100 * (float) (i + 1)) / k ); + fflush( stdout ); + } + + exit_code = MBEDTLS_EXIT_SUCCESS; + +cleanup: + mbedtls_printf("\n"); + + fclose( f ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_CTR_DRBG_C && MBEDTLS_ENTROPY_C */ diff --git a/external/mbedtls/programs/random/gen_random_havege.c b/external/mbedtls/programs/random/gen_random_havege.c new file mode 100644 index 0000000..6cfd0fa --- /dev/null +++ b/external/mbedtls/programs/random/gen_random_havege.c @@ -0,0 +1,134 @@ +/** + * \brief Generate random data into a file + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_HAVEGE_C) && defined(MBEDTLS_FS_IO) +#include "mbedtls/havege.h" + +#include +#include +#endif + +#if !defined(MBEDTLS_HAVEGE_C) || !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_HAVEGE_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +int main( int argc, char *argv[] ) +{ + FILE *f; + time_t t; + int i, k, ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_havege_state hs; + unsigned char buf[1024]; + + if( argc < 2 ) + { + mbedtls_fprintf( stderr, "usage: %s \n", argv[0] ); + mbedtls_exit( exit_code ); + } + + if( ( f = fopen( argv[1], "wb+" ) ) == NULL ) + { + mbedtls_printf( "failed to open '%s' for writing.\n", argv[1] ); + mbedtls_exit( exit_code ); + } + + mbedtls_havege_init( &hs ); + + t = time( NULL ); + + for( i = 0, k = 768; i < k; i++ ) + { + if( ( ret = mbedtls_havege_random( &hs, buf, sizeof( buf ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_havege_random returned -0x%04X", + -ret ); + goto exit; + } + + fwrite( buf, sizeof( buf ), 1, f ); + + mbedtls_printf( "Generating %ldkb of data in file '%s'... %04.1f" \ + "%% done\r", (long)(sizeof(buf) * k / 1024), argv[1], (100 * (float) (i + 1)) / k ); + fflush( stdout ); + } + + if( t == time( NULL ) ) + t--; + + mbedtls_printf(" \n "); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + mbedtls_havege_free( &hs ); + fclose( f ); + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_HAVEGE_C */ diff --git a/external/mbedtls/programs/ssl/CMakeLists.txt b/external/mbedtls/programs/ssl/CMakeLists.txt new file mode 100644 index 0000000..094543b --- /dev/null +++ b/external/mbedtls/programs/ssl/CMakeLists.txt @@ -0,0 +1,65 @@ +set(THREADS_USE_PTHREADS_WIN32 true) +find_package(Threads) + +set(libs + mbedtls +) + +set(targets + dtls_client + dtls_server + mini_client + ssl_client1 + ssl_client2 + ssl_fork_server + ssl_mail_client + ssl_server + ssl_server2 +) + +if(USE_PKCS11_HELPER_LIBRARY) + set(libs ${libs} pkcs11-helper) +endif(USE_PKCS11_HELPER_LIBRARY) + +if(ENABLE_ZLIB_SUPPORT) + set(libs ${libs} ${ZLIB_LIBRARIES}) +endif(ENABLE_ZLIB_SUPPORT) + +add_executable(dtls_client dtls_client.c) +target_link_libraries(dtls_client ${libs}) + +add_executable(dtls_server dtls_server.c) +target_link_libraries(dtls_server ${libs}) + +add_executable(mini_client mini_client.c) +target_link_libraries(mini_client ${libs}) + +add_executable(ssl_client1 ssl_client1.c) +target_link_libraries(ssl_client1 ${libs}) + +add_executable(ssl_client2 ssl_client2.c + ${CMAKE_CURRENT_SOURCE_DIR}/query_config.c) +target_link_libraries(ssl_client2 ${libs}) + +add_executable(ssl_fork_server ssl_fork_server.c) +target_link_libraries(ssl_fork_server ${libs}) + +add_executable(ssl_mail_client ssl_mail_client.c) +target_link_libraries(ssl_mail_client ${libs}) + +add_executable(ssl_server ssl_server.c) +target_link_libraries(ssl_server ${libs}) + +add_executable(ssl_server2 ssl_server2.c + ${CMAKE_CURRENT_SOURCE_DIR}/query_config.c) +target_link_libraries(ssl_server2 ${libs}) + +if(THREADS_FOUND) + add_executable(ssl_pthread_server ssl_pthread_server.c) + target_link_libraries(ssl_pthread_server ${libs} ${CMAKE_THREAD_LIBS_INIT}) + set(targets ${targets} ssl_pthread_server) +endif(THREADS_FOUND) + +install(TARGETS ${targets} + DESTINATION "bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/external/mbedtls/programs/ssl/dtls_client.c b/external/mbedtls/programs/ssl/dtls_client.c new file mode 100644 index 0000000..69d4f33 --- /dev/null +++ b/external/mbedtls/programs/ssl/dtls_client.c @@ -0,0 +1,389 @@ +/* + * Simple DTLS client demonstration program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_fprintf fprintf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif + +#if !defined(MBEDTLS_SSL_CLI_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) || \ + !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_TIMING_C) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_CERTS_C) || !defined(MBEDTLS_PEM_PARSE_C) +int main( void ) +{ + mbedtls_printf( "MBEDTLS_SSL_CLI_C and/or MBEDTLS_SSL_PROTO_DTLS and/or " + "MBEDTLS_NET_C and/or MBEDTLS_TIMING_C and/or " + "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or " + "MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_CERTS_C and/or MBEDTLS_PEM_PARSE_C not defined.\n" ); + mbedtls_exit( 0 ); +} +#else + +#include + +#include "mbedtls/net_sockets.h" +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "mbedtls/certs.h" +#include "mbedtls/timing.h" + +/* Uncomment out the following line to default to IPv4 and disable IPv6 */ +//#define FORCE_IPV4 + +#define SERVER_PORT "4433" +#define SERVER_NAME "localhost" + +#ifdef FORCE_IPV4 +#define SERVER_ADDR "127.0.0.1" /* Forces IPv4 */ +#else +#define SERVER_ADDR "::1" +#endif + +#define MESSAGE "Echo this" + +#define READ_TIMEOUT_MS 1000 +#define MAX_RETRY 5 + +#define DEBUG_LEVEL 0 + + +static void my_debug( void *ctx, int level, + const char *file, int line, + const char *str ) +{ + ((void) level); + + mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str ); + fflush( (FILE *) ctx ); +} + +int main( int argc, char *argv[] ) +{ + int ret, len; + mbedtls_net_context server_fd; + uint32_t flags; + unsigned char buf[1024]; + const char *pers = "dtls_client"; + int retry_left = MAX_RETRY; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_x509_crt cacert; + mbedtls_timing_delay_context timer; + + ((void) argc); + ((void) argv); + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold( DEBUG_LEVEL ); +#endif + + /* + * 0. Initialize the RNG and the session data + */ + mbedtls_net_init( &server_fd ); + mbedtls_ssl_init( &ssl ); + mbedtls_ssl_config_init( &conf ); + mbedtls_x509_crt_init( &cacert ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + mbedtls_entropy_init( &entropy ); + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 0. Load certificates + */ + mbedtls_printf( " . Loading the CA root certificate ..." ); + fflush( stdout ); + + ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem, + mbedtls_test_cas_pem_len ); + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret ); + goto exit; + } + + mbedtls_printf( " ok (%d skipped)\n", ret ); + + /* + * 1. Start the connection + */ + mbedtls_printf( " . Connecting to udp/%s/%s...", SERVER_NAME, SERVER_PORT ); + fflush( stdout ); + + if( ( ret = mbedtls_net_connect( &server_fd, SERVER_ADDR, + SERVER_PORT, MBEDTLS_NET_PROTO_UDP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 2. Setup stuff + */ + mbedtls_printf( " . Setting up the DTLS structure..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ssl_config_defaults( &conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_DATAGRAM, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); + goto exit; + } + + /* OPTIONAL is usually a bad choice for security, but makes interop easier + * in this simplified example, in which the ca chain is hardcoded. + * Production code should set a proper ca chain and use REQUIRED. */ + mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); + mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); + mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); + mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); + + if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); + goto exit; + } + + if( ( ret = mbedtls_ssl_set_hostname( &ssl, SERVER_NAME ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); + goto exit; + } + + mbedtls_ssl_set_bio( &ssl, &server_fd, + mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout ); + + mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, + mbedtls_timing_get_delay ); + + mbedtls_printf( " ok\n" ); + + /* + * 4. Handshake + */ + mbedtls_printf( " . Performing the DTLS handshake..." ); + fflush( stdout ); + + do ret = mbedtls_ssl_handshake( &ssl ); + while( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 5. Verify the server certificate + */ + mbedtls_printf( " . Verifying peer X.509 certificate..." ); + + /* In real life, we would have used MBEDTLS_SSL_VERIFY_REQUIRED so that the + * handshake would not succeed if the peer's cert is bad. Even if we used + * MBEDTLS_SSL_VERIFY_OPTIONAL, we would bail out here if ret != 0 */ + if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 ) + { + char vrfy_buf[512]; + + mbedtls_printf( " failed\n" ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + + mbedtls_printf( "%s\n", vrfy_buf ); + } + else + mbedtls_printf( " ok\n" ); + + /* + * 6. Write the echo request + */ +send_request: + mbedtls_printf( " > Write to server:" ); + fflush( stdout ); + + len = sizeof( MESSAGE ) - 1; + + do ret = mbedtls_ssl_write( &ssl, (unsigned char *) MESSAGE, len ); + while( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); + goto exit; + } + + len = ret; + mbedtls_printf( " %d bytes written\n\n%s\n\n", len, MESSAGE ); + + /* + * 7. Read the echo response + */ + mbedtls_printf( " < Read from server:" ); + fflush( stdout ); + + len = sizeof( buf ) - 1; + memset( buf, 0, sizeof( buf ) ); + + do ret = mbedtls_ssl_read( &ssl, buf, len ); + while( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + + if( ret <= 0 ) + { + switch( ret ) + { + case MBEDTLS_ERR_SSL_TIMEOUT: + mbedtls_printf( " timeout\n\n" ); + if( retry_left-- > 0 ) + goto send_request; + goto exit; + + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf( " connection was closed gracefully\n" ); + ret = 0; + goto close_notify; + + default: + mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n\n", -ret ); + goto exit; + } + } + + len = ret; + mbedtls_printf( " %d bytes read\n\n%s\n\n", len, buf ); + + /* + * 8. Done, cleanly close the connection + */ +close_notify: + mbedtls_printf( " . Closing the connection..." ); + + /* No error checking, the connection might be closed already */ + do ret = mbedtls_ssl_close_notify( &ssl ); + while( ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + ret = 0; + + mbedtls_printf( " done\n" ); + + /* + * 9. Final clean-ups and exit + */ +exit: + +#ifdef MBEDTLS_ERROR_C + if( ret != 0 ) + { + char error_buf[100]; + mbedtls_strerror( ret, error_buf, 100 ); + mbedtls_printf( "Last error was: %d - %s\n\n", ret, error_buf ); + } +#endif + + mbedtls_net_free( &server_fd ); + + mbedtls_x509_crt_free( &cacert ); + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + /* Shell can not handle large exit numbers -> 1 for errors */ + if( ret < 0 ) + ret = 1; + + mbedtls_exit( ret ); +} +#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_NET_C && + MBEDTLD_TIMING_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C && + MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_RSA_C && MBEDTLS_CERTS_C && + MBEDTLS_PEM_PARSE_C */ diff --git a/external/mbedtls/programs/ssl/dtls_server.c b/external/mbedtls/programs/ssl/dtls_server.c new file mode 100644 index 0000000..8339d9d --- /dev/null +++ b/external/mbedtls/programs/ssl/dtls_server.c @@ -0,0 +1,464 @@ +/* + * Simple DTLS server demonstration program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_fprintf fprintf +#define mbedtls_time_t time_t +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif + +/* Uncomment out the following line to default to IPv4 and disable IPv6 */ +//#define FORCE_IPV4 + +#ifdef FORCE_IPV4 +#define BIND_IP "0.0.0.0" /* Forces IPv4 */ +#else +#define BIND_IP "::" +#endif + +#if !defined(MBEDTLS_SSL_SRV_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) || \ + !defined(MBEDTLS_SSL_COOKIE_C) || !defined(MBEDTLS_NET_C) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_CERTS_C) || !defined(MBEDTLS_PEM_PARSE_C) || \ + !defined(MBEDTLS_TIMING_C) + +int main( void ) +{ + printf( "MBEDTLS_SSL_SRV_C and/or MBEDTLS_SSL_PROTO_DTLS and/or " + "MBEDTLS_SSL_COOKIE_C and/or MBEDTLS_NET_C and/or " + "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or " + "MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_CERTS_C and/or MBEDTLS_PEM_PARSE_C and/or " + "MBEDTLS_TIMING_C not defined.\n" ); + mbedtls_exit( 0 ); +} +#else + +#if defined(_WIN32) +#include +#endif + +#include +#include +#include + +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/x509.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_cookie.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/error.h" +#include "mbedtls/debug.h" +#include "mbedtls/timing.h" + +#if defined(MBEDTLS_SSL_CACHE_C) +#include "mbedtls/ssl_cache.h" +#endif + +#define READ_TIMEOUT_MS 10000 /* 5 seconds */ +#define DEBUG_LEVEL 0 + + +static void my_debug( void *ctx, int level, + const char *file, int line, + const char *str ) +{ + ((void) level); + + mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str ); + fflush( (FILE *) ctx ); +} + +int main( void ) +{ + int ret, len; + mbedtls_net_context listen_fd, client_fd; + unsigned char buf[1024]; + const char *pers = "dtls_server"; + unsigned char client_ip[16] = { 0 }; + size_t cliip_len; + mbedtls_ssl_cookie_ctx cookie_ctx; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_x509_crt srvcert; + mbedtls_pk_context pkey; + mbedtls_timing_delay_context timer; +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_context cache; +#endif + + mbedtls_net_init( &listen_fd ); + mbedtls_net_init( &client_fd ); + mbedtls_ssl_init( &ssl ); + mbedtls_ssl_config_init( &conf ); + mbedtls_ssl_cookie_init( &cookie_ctx ); +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_init( &cache ); +#endif + mbedtls_x509_crt_init( &srvcert ); + mbedtls_pk_init( &pkey ); + mbedtls_entropy_init( &entropy ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold( DEBUG_LEVEL ); +#endif + + /* + * 1. Load the certificates and private RSA key + */ + printf( "\n . Loading the server cert. and key..." ); + fflush( stdout ); + + /* + * This demonstration program uses embedded test certificates. + * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the + * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). + */ + ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, + mbedtls_test_srv_crt_len ); + if( ret != 0 ) + { + printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); + goto exit; + } + + ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem, + mbedtls_test_cas_pem_len ); + if( ret != 0 ) + { + printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); + goto exit; + } + + ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, + mbedtls_test_srv_key_len, NULL, 0 ); + if( ret != 0 ) + { + printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); + goto exit; + } + + printf( " ok\n" ); + + /* + * 2. Setup the "listening" UDP socket + */ + printf( " . Bind on udp/*/4433 ..." ); + fflush( stdout ); + + if( ( ret = mbedtls_net_bind( &listen_fd, BIND_IP, "4433", MBEDTLS_NET_PROTO_UDP ) ) != 0 ) + { + printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); + goto exit; + } + + printf( " ok\n" ); + + /* + * 3. Seed the RNG + */ + printf( " . Seeding the random number generator..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); + goto exit; + } + + printf( " ok\n" ); + + /* + * 4. Setup stuff + */ + printf( " . Setting up the DTLS data..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ssl_config_defaults( &conf, + MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_DATAGRAM, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); + goto exit; + } + + mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); + mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); + +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_conf_session_cache( &conf, &cache, + mbedtls_ssl_cache_get, + mbedtls_ssl_cache_set ); +#endif + + mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL ); + if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 ) + { + printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); + goto exit; + } + + if( ( ret = mbedtls_ssl_cookie_setup( &cookie_ctx, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + printf( " failed\n ! mbedtls_ssl_cookie_setup returned %d\n\n", ret ); + goto exit; + } + + mbedtls_ssl_conf_dtls_cookies( &conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, + &cookie_ctx ); + + if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); + goto exit; + } + + mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, + mbedtls_timing_get_delay ); + + printf( " ok\n" ); + +reset: +#ifdef MBEDTLS_ERROR_C + if( ret != 0 ) + { + char error_buf[100]; + mbedtls_strerror( ret, error_buf, 100 ); + printf("Last error was: %d - %s\n\n", ret, error_buf ); + } +#endif + + mbedtls_net_free( &client_fd ); + + mbedtls_ssl_session_reset( &ssl ); + + /* + * 3. Wait until a client connects + */ + printf( " . Waiting for a remote connection ..." ); + fflush( stdout ); + + if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, + client_ip, sizeof( client_ip ), &cliip_len ) ) != 0 ) + { + printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret ); + goto exit; + } + + /* For HelloVerifyRequest cookies */ + if( ( ret = mbedtls_ssl_set_client_transport_id( &ssl, + client_ip, cliip_len ) ) != 0 ) + { + printf( " failed\n ! " + "mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", -ret ); + goto exit; + } + + mbedtls_ssl_set_bio( &ssl, &client_fd, + mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout ); + + printf( " ok\n" ); + + /* + * 5. Handshake + */ + printf( " . Performing the DTLS handshake..." ); + fflush( stdout ); + + do ret = mbedtls_ssl_handshake( &ssl ); + while( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + + if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) + { + printf( " hello verification requested\n" ); + ret = 0; + goto reset; + } + else if( ret != 0 ) + { + printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); + goto reset; + } + + printf( " ok\n" ); + + /* + * 6. Read the echo Request + */ + printf( " < Read from client:" ); + fflush( stdout ); + + len = sizeof( buf ) - 1; + memset( buf, 0, sizeof( buf ) ); + + do ret = mbedtls_ssl_read( &ssl, buf, len ); + while( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + + if( ret <= 0 ) + { + switch( ret ) + { + case MBEDTLS_ERR_SSL_TIMEOUT: + printf( " timeout\n\n" ); + goto reset; + + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + printf( " connection was closed gracefully\n" ); + ret = 0; + goto close_notify; + + default: + printf( " mbedtls_ssl_read returned -0x%x\n\n", -ret ); + goto reset; + } + } + + len = ret; + printf( " %d bytes read\n\n%s\n\n", len, buf ); + + /* + * 7. Write the 200 Response + */ + printf( " > Write to client:" ); + fflush( stdout ); + + do ret = mbedtls_ssl_write( &ssl, buf, len ); + while( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + + if( ret < 0 ) + { + printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); + goto exit; + } + + len = ret; + printf( " %d bytes written\n\n%s\n\n", len, buf ); + + /* + * 8. Done, cleanly close the connection + */ +close_notify: + printf( " . Closing the connection..." ); + + /* No error checking, the connection might be closed already */ + do ret = mbedtls_ssl_close_notify( &ssl ); + while( ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + ret = 0; + + printf( " done\n" ); + + goto reset; + + /* + * Final clean-ups and exit + */ +exit: + +#ifdef MBEDTLS_ERROR_C + if( ret != 0 ) + { + char error_buf[100]; + mbedtls_strerror( ret, error_buf, 100 ); + printf( "Last error was: %d - %s\n\n", ret, error_buf ); + } +#endif + + mbedtls_net_free( &client_fd ); + mbedtls_net_free( &listen_fd ); + + mbedtls_x509_crt_free( &srvcert ); + mbedtls_pk_free( &pkey ); + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + mbedtls_ssl_cookie_free( &cookie_ctx ); +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_free( &cache ); +#endif + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + printf( " Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + /* Shell can not handle large exit numbers -> 1 for errors */ + if( ret < 0 ) + ret = 1; + + mbedtls_exit( ret ); +} +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_DTLS && + MBEDTLS_SSL_COOKIE_C && MBEDTLS_NET_C && MBEDTLS_ENTROPY_C && + MBEDTLS_CTR_DRBG_C && MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_RSA_C + && MBEDTLS_CERTS_C && MBEDTLS_PEM_PARSE_C && MBEDTLS_TIMING_C */ diff --git a/external/mbedtls/programs/ssl/mini_client.c b/external/mbedtls/programs/ssl/mini_client.c new file mode 100644 index 0000000..3f2ab5a --- /dev/null +++ b/external/mbedtls/programs/ssl/mini_client.c @@ -0,0 +1,326 @@ +/* + * Minimal SSL client, used for memory measurements. + * (meant to be used with config-suite-b.h or config-ccm-psk-tls1_2.h) + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif + +/* + * We're creating and connecting the socket "manually" rather than using the + * NET module, in order to avoid the overhead of getaddrinfo() which tends to + * dominate memory usage in small configurations. For the sake of simplicity, + * only a Unix version is implemented. + * + * Warning: we are breaking some of the abtractions from the NET layer here. + * This is not a good example for general use. This programs has the specific + * goal of minimizing use of the libc functions on full-blown OSes. + */ +#if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__) +#define UNIX +#endif + +#if !defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_SSL_CLI_C) || \ + !defined(UNIX) + +int main( void ) +{ + mbedtls_printf( "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_NET_C and/or MBEDTLS_SSL_CLI_C and/or UNIX " + "not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include + +#include "mbedtls/net_sockets.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include +#include +#include + +/* + * Hardcoded values for server host and port + */ +#define PORT_BE 0x1151 /* 4433 */ +#define PORT_LE 0x5111 +#define ADDR_BE 0x7f000001 /* 127.0.0.1 */ +#define ADDR_LE 0x0100007f +#define HOSTNAME "localhost" /* for cert verification if enabled */ + +#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n" + +const char *pers = "mini_client"; + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +const unsigned char psk[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f +}; +const char psk_id[] = "Client_identity"; +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* This is tests/data_files/test-ca2.crt, a CA using EC secp384r1 */ +const unsigned char ca_cert[] = { + 0x30, 0x82, 0x02, 0x52, 0x30, 0x82, 0x01, 0xd7, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x09, 0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, + 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, + 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x50, 0x6f, 0x6c, + 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, + 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x39, + 0x32, 0x34, 0x31, 0x35, 0x34, 0x39, 0x34, 0x38, 0x5a, 0x17, 0x0d, 0x32, + 0x33, 0x30, 0x39, 0x32, 0x32, 0x31, 0x35, 0x34, 0x39, 0x34, 0x38, 0x5a, + 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, + 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x50, 0x6f, 0x6c, + 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, + 0x43, 0x20, 0x43, 0x41, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, + 0x03, 0x62, 0x00, 0x04, 0xc3, 0xda, 0x2b, 0x34, 0x41, 0x37, 0x58, 0x2f, + 0x87, 0x56, 0xfe, 0xfc, 0x89, 0xba, 0x29, 0x43, 0x4b, 0x4e, 0xe0, 0x6e, + 0xc3, 0x0e, 0x57, 0x53, 0x33, 0x39, 0x58, 0xd4, 0x52, 0xb4, 0x91, 0x95, + 0x39, 0x0b, 0x23, 0xdf, 0x5f, 0x17, 0x24, 0x62, 0x48, 0xfc, 0x1a, 0x95, + 0x29, 0xce, 0x2c, 0x2d, 0x87, 0xc2, 0x88, 0x52, 0x80, 0xaf, 0xd6, 0x6a, + 0xab, 0x21, 0xdd, 0xb8, 0xd3, 0x1c, 0x6e, 0x58, 0xb8, 0xca, 0xe8, 0xb2, + 0x69, 0x8e, 0xf3, 0x41, 0xad, 0x29, 0xc3, 0xb4, 0x5f, 0x75, 0xa7, 0x47, + 0x6f, 0xd5, 0x19, 0x29, 0x55, 0x69, 0x9a, 0x53, 0x3b, 0x20, 0xb4, 0x66, + 0x16, 0x60, 0x33, 0x1e, 0xa3, 0x81, 0xa0, 0x30, 0x81, 0x9d, 0x30, 0x1d, + 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9d, 0x6d, 0x20, + 0x24, 0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, + 0xc9, 0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x6e, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x67, 0x30, 0x65, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, 0x01, + 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, 0xfb, + 0x36, 0x7c, 0xa1, 0x42, 0xa4, 0x40, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, + 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, + 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x82, 0x09, + 0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, 0x30, 0x0c, 0x06, + 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, + 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, + 0x69, 0x00, 0x30, 0x66, 0x02, 0x31, 0x00, 0xc3, 0xb4, 0x62, 0x73, 0x56, + 0x28, 0x95, 0x00, 0x7d, 0x78, 0x12, 0x26, 0xd2, 0x71, 0x7b, 0x19, 0xf8, + 0x8a, 0x98, 0x3e, 0x92, 0xfe, 0x33, 0x9e, 0xe4, 0x79, 0xd2, 0xfe, 0x7a, + 0xb7, 0x87, 0x74, 0x3c, 0x2b, 0xb8, 0xd7, 0x69, 0x94, 0x0b, 0xa3, 0x67, + 0x77, 0xb8, 0xb3, 0xbe, 0xd1, 0x36, 0x32, 0x02, 0x31, 0x00, 0xfd, 0x67, + 0x9c, 0x94, 0x23, 0x67, 0xc0, 0x56, 0xba, 0x4b, 0x33, 0x15, 0x00, 0xc6, + 0xe3, 0xcc, 0x31, 0x08, 0x2c, 0x9c, 0x8b, 0xda, 0xa9, 0x75, 0x23, 0x2f, + 0xb8, 0x28, 0xe7, 0xf2, 0x9c, 0x14, 0x3a, 0x40, 0x01, 0x5c, 0xaf, 0x0c, + 0xb2, 0xcf, 0x74, 0x7f, 0x30, 0x9f, 0x08, 0x43, 0xad, 0x20, +}; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +enum exit_codes +{ + exit_ok = 0, + ctr_drbg_seed_failed, + ssl_config_defaults_failed, + ssl_setup_failed, + hostname_failed, + socket_failed, + connect_failed, + x509_crt_parse_failed, + ssl_handshake_failed, + ssl_write_failed, +}; + + +int main( void ) +{ + int ret = exit_ok; + mbedtls_net_context server_fd; + struct sockaddr_in addr; +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt ca; +#endif + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_ctr_drbg_init( &ctr_drbg ); + + /* + * 0. Initialize and setup stuff + */ + mbedtls_net_init( &server_fd ); + mbedtls_ssl_init( &ssl ); + mbedtls_ssl_config_init( &conf ); +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_init( &ca ); +#endif + + mbedtls_entropy_init( &entropy ); + if( mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, strlen( pers ) ) != 0 ) + { + ret = ctr_drbg_seed_failed; + goto exit; + } + + if( mbedtls_ssl_config_defaults( &conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT ) != 0 ) + { + ret = ssl_config_defaults_failed; + goto exit; + } + + mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + mbedtls_ssl_conf_psk( &conf, psk, sizeof( psk ), + (const unsigned char *) psk_id, sizeof( psk_id ) - 1 ); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( mbedtls_x509_crt_parse_der( &ca, ca_cert, sizeof( ca_cert ) ) != 0 ) + { + ret = x509_crt_parse_failed; + goto exit; + } + + mbedtls_ssl_conf_ca_chain( &conf, &ca, NULL ); + mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_REQUIRED ); +#endif + + if( mbedtls_ssl_setup( &ssl, &conf ) != 0 ) + { + ret = ssl_setup_failed; + goto exit; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( mbedtls_ssl_set_hostname( &ssl, HOSTNAME ) != 0 ) + { + ret = hostname_failed; + goto exit; + } +#endif + + /* + * 1. Start the connection + */ + memset( &addr, 0, sizeof( addr ) ); + addr.sin_family = AF_INET; + + ret = 1; /* for endianness detection */ + addr.sin_port = *((char *) &ret) == ret ? PORT_LE : PORT_BE; + addr.sin_addr.s_addr = *((char *) &ret) == ret ? ADDR_LE : ADDR_BE; + ret = 0; + + if( ( server_fd.fd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) + { + ret = socket_failed; + goto exit; + } + + if( connect( server_fd.fd, + (const struct sockaddr *) &addr, sizeof( addr ) ) < 0 ) + { + ret = connect_failed; + goto exit; + } + + mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); + + if( mbedtls_ssl_handshake( &ssl ) != 0 ) + { + ret = ssl_handshake_failed; + goto exit; + } + + /* + * 2. Write the GET request and close the connection + */ + if( mbedtls_ssl_write( &ssl, (const unsigned char *) GET_REQUEST, + sizeof( GET_REQUEST ) - 1 ) <= 0 ) + { + ret = ssl_write_failed; + goto exit; + } + + mbedtls_ssl_close_notify( &ssl ); + +exit: + mbedtls_net_free( &server_fd ); + + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_free( &ca ); +#endif + + mbedtls_exit( ret ); +} +#endif diff --git a/external/mbedtls/programs/ssl/query_config.c b/external/mbedtls/programs/ssl/query_config.c new file mode 100644 index 0000000..0a7eb1a --- /dev/null +++ b/external/mbedtls/programs/ssl/query_config.c @@ -0,0 +1,2580 @@ +/* + * Query Mbed TLS compile time configurations from config.h + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ + +/* + * Include all the headers with public APIs in case they define a macro to its + * default value when that configuration is not set in the config.h. + */ +#include "mbedtls/aes.h" +#include "mbedtls/aesni.h" +#include "mbedtls/arc4.h" +#include "mbedtls/aria.h" +#include "mbedtls/asn1.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/base64.h" +#include "mbedtls/bignum.h" +#include "mbedtls/blowfish.h" +#include "mbedtls/camellia.h" +#include "mbedtls/ccm.h" +#include "mbedtls/certs.h" +#include "mbedtls/chacha20.h" +#include "mbedtls/chachapoly.h" +#include "mbedtls/cipher.h" +#include "mbedtls/cmac.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/debug.h" +#include "mbedtls/des.h" +#include "mbedtls/dhm.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/ecdsa.h" +#include "mbedtls/ecjpake.h" +#include "mbedtls/ecp.h" +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" +#include "mbedtls/error.h" +#include "mbedtls/gcm.h" +#include "mbedtls/havege.h" +#include "mbedtls/hkdf.h" +#include "mbedtls/hmac_drbg.h" +#include "mbedtls/md.h" +#include "mbedtls/md2.h" +#include "mbedtls/md4.h" +#include "mbedtls/md5.h" +#include "mbedtls/memory_buffer_alloc.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/nist_kw.h" +#include "mbedtls/oid.h" +#include "mbedtls/padlock.h" +#include "mbedtls/pem.h" +#include "mbedtls/pk.h" +#include "mbedtls/pkcs11.h" +#include "mbedtls/pkcs12.h" +#include "mbedtls/pkcs5.h" +#include "mbedtls/platform_time.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/poly1305.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/rsa.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_cache.h" +#include "mbedtls/ssl_ciphersuites.h" +#include "mbedtls/ssl_cookie.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/ssl_ticket.h" +#include "mbedtls/threading.h" +#include "mbedtls/timing.h" +#include "mbedtls/version.h" +#include "mbedtls/x509.h" +#include "mbedtls/x509_crl.h" +#include "mbedtls/x509_crt.h" +#include "mbedtls/x509_csr.h" +#include "mbedtls/xtea.h" + +#include + +/* + * Helper macros to convert a macro or its expansion into a string + * WARNING: This does not work for expanding function-like macros. However, + * Mbed TLS does not currently have configuration options used in this fashion. + */ +#define MACRO_EXPANSION_TO_STR(macro) MACRO_NAME_TO_STR(macro) +#define MACRO_NAME_TO_STR(macro) \ + mbedtls_printf( "%s", strlen( #macro "" ) > 0 ? #macro "\n" : "" ) + +#if defined(_MSC_VER) +/* + * Visual Studio throws the warning 4003 because many Mbed TLS feature macros + * are defined empty. This means that from the preprocessor's point of view + * the macro MBEDTLS_EXPANSION_TO_STR is being invoked without arguments as + * some macros expand to nothing. We suppress that specific warning to get a + * clean build and to ensure that tests treating warnings as errors do not + * fail. + */ +#pragma warning(push) +#pragma warning(disable:4003) +#endif /* _MSC_VER */ + +int query_config( const char *config ) +{ +#if defined(MBEDTLS_HAVE_ASM) + if( strcmp( "MBEDTLS_HAVE_ASM", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_HAVE_ASM ); + return( 0 ); + } +#endif /* MBEDTLS_HAVE_ASM */ + +#if defined(MBEDTLS_NO_UDBL_DIVISION) + if( strcmp( "MBEDTLS_NO_UDBL_DIVISION", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_NO_UDBL_DIVISION ); + return( 0 ); + } +#endif /* MBEDTLS_NO_UDBL_DIVISION */ + +#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) + if( strcmp( "MBEDTLS_NO_64BIT_MULTIPLICATION", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_NO_64BIT_MULTIPLICATION ); + return( 0 ); + } +#endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */ + +#if defined(MBEDTLS_HAVE_SSE2) + if( strcmp( "MBEDTLS_HAVE_SSE2", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_HAVE_SSE2 ); + return( 0 ); + } +#endif /* MBEDTLS_HAVE_SSE2 */ + +#if defined(MBEDTLS_HAVE_TIME) + if( strcmp( "MBEDTLS_HAVE_TIME", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_HAVE_TIME ); + return( 0 ); + } +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_HAVE_TIME_DATE) + if( strcmp( "MBEDTLS_HAVE_TIME_DATE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_HAVE_TIME_DATE ); + return( 0 ); + } +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#if defined(MBEDTLS_PLATFORM_MEMORY) + if( strcmp( "MBEDTLS_PLATFORM_MEMORY", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_MEMORY ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_MEMORY */ + +#if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) + if( strcmp( "MBEDTLS_PLATFORM_NO_STD_FUNCTIONS", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_NO_STD_FUNCTIONS ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) + if( strcmp( "MBEDTLS_PLATFORM_EXIT_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_EXIT_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) + if( strcmp( "MBEDTLS_PLATFORM_TIME_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_TIME_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) + if( strcmp( "MBEDTLS_PLATFORM_FPRINTF_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_FPRINTF_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) + if( strcmp( "MBEDTLS_PLATFORM_PRINTF_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_PRINTF_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) + if( strcmp( "MBEDTLS_PLATFORM_SNPRINTF_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_SNPRINTF_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) + if( strcmp( "MBEDTLS_PLATFORM_NV_SEED_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_NV_SEED_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ + +#if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + if( strcmp( "MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +#if defined(MBEDTLS_DEPRECATED_WARNING) + if( strcmp( "MBEDTLS_DEPRECATED_WARNING", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_DEPRECATED_WARNING ); + return( 0 ); + } +#endif /* MBEDTLS_DEPRECATED_WARNING */ + +#if defined(MBEDTLS_DEPRECATED_REMOVED) + if( strcmp( "MBEDTLS_DEPRECATED_REMOVED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_DEPRECATED_REMOVED ); + return( 0 ); + } +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_CHECK_PARAMS) + if( strcmp( "MBEDTLS_CHECK_PARAMS", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CHECK_PARAMS ); + return( 0 ); + } +#endif /* MBEDTLS_CHECK_PARAMS */ + +#if defined(MBEDTLS_CHECK_PARAMS_ASSERT) + if( strcmp( "MBEDTLS_CHECK_PARAMS_ASSERT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CHECK_PARAMS_ASSERT ); + return( 0 ); + } +#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */ + +#if defined(MBEDTLS_TIMING_ALT) + if( strcmp( "MBEDTLS_TIMING_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_TIMING_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_TIMING_ALT */ + +#if defined(MBEDTLS_AES_ALT) + if( strcmp( "MBEDTLS_AES_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_AES_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_AES_ALT */ + +#if defined(MBEDTLS_ARC4_ALT) + if( strcmp( "MBEDTLS_ARC4_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ARC4_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ARC4_ALT */ + +#if defined(MBEDTLS_ARIA_ALT) + if( strcmp( "MBEDTLS_ARIA_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ARIA_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ARIA_ALT */ + +#if defined(MBEDTLS_BLOWFISH_ALT) + if( strcmp( "MBEDTLS_BLOWFISH_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_BLOWFISH_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_BLOWFISH_ALT */ + +#if defined(MBEDTLS_CAMELLIA_ALT) + if( strcmp( "MBEDTLS_CAMELLIA_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CAMELLIA_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_CAMELLIA_ALT */ + +#if defined(MBEDTLS_CCM_ALT) + if( strcmp( "MBEDTLS_CCM_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CCM_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_CCM_ALT */ + +#if defined(MBEDTLS_CHACHA20_ALT) + if( strcmp( "MBEDTLS_CHACHA20_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CHACHA20_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_CHACHA20_ALT */ + +#if defined(MBEDTLS_CHACHAPOLY_ALT) + if( strcmp( "MBEDTLS_CHACHAPOLY_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CHACHAPOLY_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_CHACHAPOLY_ALT */ + +#if defined(MBEDTLS_CMAC_ALT) + if( strcmp( "MBEDTLS_CMAC_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CMAC_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_CMAC_ALT */ + +#if defined(MBEDTLS_DES_ALT) + if( strcmp( "MBEDTLS_DES_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_DES_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_DES_ALT */ + +#if defined(MBEDTLS_DHM_ALT) + if( strcmp( "MBEDTLS_DHM_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_DHM_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_DHM_ALT */ + +#if defined(MBEDTLS_ECJPAKE_ALT) + if( strcmp( "MBEDTLS_ECJPAKE_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECJPAKE_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECJPAKE_ALT */ + +#if defined(MBEDTLS_GCM_ALT) + if( strcmp( "MBEDTLS_GCM_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_GCM_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_GCM_ALT */ + +#if defined(MBEDTLS_NIST_KW_ALT) + if( strcmp( "MBEDTLS_NIST_KW_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_NIST_KW_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_NIST_KW_ALT */ + +#if defined(MBEDTLS_MD2_ALT) + if( strcmp( "MBEDTLS_MD2_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MD2_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_MD2_ALT */ + +#if defined(MBEDTLS_MD4_ALT) + if( strcmp( "MBEDTLS_MD4_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MD4_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_MD4_ALT */ + +#if defined(MBEDTLS_MD5_ALT) + if( strcmp( "MBEDTLS_MD5_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MD5_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_MD5_ALT */ + +#if defined(MBEDTLS_POLY1305_ALT) + if( strcmp( "MBEDTLS_POLY1305_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_POLY1305_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_POLY1305_ALT */ + +#if defined(MBEDTLS_RIPEMD160_ALT) + if( strcmp( "MBEDTLS_RIPEMD160_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_RIPEMD160_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_RIPEMD160_ALT */ + +#if defined(MBEDTLS_RSA_ALT) + if( strcmp( "MBEDTLS_RSA_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_RSA_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_RSA_ALT */ + +#if defined(MBEDTLS_SHA1_ALT) + if( strcmp( "MBEDTLS_SHA1_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SHA1_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_SHA1_ALT */ + +#if defined(MBEDTLS_SHA256_ALT) + if( strcmp( "MBEDTLS_SHA256_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SHA256_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_SHA256_ALT */ + +#if defined(MBEDTLS_SHA512_ALT) + if( strcmp( "MBEDTLS_SHA512_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SHA512_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_SHA512_ALT */ + +#if defined(MBEDTLS_XTEA_ALT) + if( strcmp( "MBEDTLS_XTEA_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_XTEA_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_XTEA_ALT */ + +#if defined(MBEDTLS_ECP_ALT) + if( strcmp( "MBEDTLS_ECP_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_ALT */ + +#if defined(MBEDTLS_MD2_PROCESS_ALT) + if( strcmp( "MBEDTLS_MD2_PROCESS_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MD2_PROCESS_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_MD2_PROCESS_ALT */ + +#if defined(MBEDTLS_MD4_PROCESS_ALT) + if( strcmp( "MBEDTLS_MD4_PROCESS_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MD4_PROCESS_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_MD4_PROCESS_ALT */ + +#if defined(MBEDTLS_MD5_PROCESS_ALT) + if( strcmp( "MBEDTLS_MD5_PROCESS_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MD5_PROCESS_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_MD5_PROCESS_ALT */ + +#if defined(MBEDTLS_RIPEMD160_PROCESS_ALT) + if( strcmp( "MBEDTLS_RIPEMD160_PROCESS_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_RIPEMD160_PROCESS_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */ + +#if defined(MBEDTLS_SHA1_PROCESS_ALT) + if( strcmp( "MBEDTLS_SHA1_PROCESS_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SHA1_PROCESS_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_SHA1_PROCESS_ALT */ + +#if defined(MBEDTLS_SHA256_PROCESS_ALT) + if( strcmp( "MBEDTLS_SHA256_PROCESS_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SHA256_PROCESS_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_SHA256_PROCESS_ALT */ + +#if defined(MBEDTLS_SHA512_PROCESS_ALT) + if( strcmp( "MBEDTLS_SHA512_PROCESS_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SHA512_PROCESS_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_SHA512_PROCESS_ALT */ + +#if defined(MBEDTLS_DES_SETKEY_ALT) + if( strcmp( "MBEDTLS_DES_SETKEY_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_DES_SETKEY_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_DES_SETKEY_ALT */ + +#if defined(MBEDTLS_DES_CRYPT_ECB_ALT) + if( strcmp( "MBEDTLS_DES_CRYPT_ECB_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_DES_CRYPT_ECB_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_DES_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_DES3_CRYPT_ECB_ALT) + if( strcmp( "MBEDTLS_DES3_CRYPT_ECB_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_DES3_CRYPT_ECB_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_AES_SETKEY_ENC_ALT) + if( strcmp( "MBEDTLS_AES_SETKEY_ENC_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_AES_SETKEY_ENC_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_AES_SETKEY_ENC_ALT */ + +#if defined(MBEDTLS_AES_SETKEY_DEC_ALT) + if( strcmp( "MBEDTLS_AES_SETKEY_DEC_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_AES_SETKEY_DEC_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_AES_SETKEY_DEC_ALT */ + +#if defined(MBEDTLS_AES_ENCRYPT_ALT) + if( strcmp( "MBEDTLS_AES_ENCRYPT_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_AES_ENCRYPT_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_AES_ENCRYPT_ALT */ + +#if defined(MBEDTLS_AES_DECRYPT_ALT) + if( strcmp( "MBEDTLS_AES_DECRYPT_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_AES_DECRYPT_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_AES_DECRYPT_ALT */ + +#if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) + if( strcmp( "MBEDTLS_ECDH_GEN_PUBLIC_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECDH_GEN_PUBLIC_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ + +#if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) + if( strcmp( "MBEDTLS_ECDH_COMPUTE_SHARED_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECDH_COMPUTE_SHARED_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ + +#if defined(MBEDTLS_ECDSA_VERIFY_ALT) + if( strcmp( "MBEDTLS_ECDSA_VERIFY_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECDSA_VERIFY_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ + +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + if( strcmp( "MBEDTLS_ECDSA_SIGN_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECDSA_SIGN_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ + +#if defined(MBEDTLS_ECDSA_GENKEY_ALT) + if( strcmp( "MBEDTLS_ECDSA_GENKEY_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECDSA_GENKEY_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECDSA_GENKEY_ALT */ + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( strcmp( "MBEDTLS_ECP_INTERNAL_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_INTERNAL_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + if( strcmp( "MBEDTLS_ECP_RANDOMIZE_JAC_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_RANDOMIZE_JAC_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + if( strcmp( "MBEDTLS_ECP_ADD_MIXED_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_ADD_MIXED_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + if( strcmp( "MBEDTLS_ECP_DOUBLE_JAC_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DOUBLE_JAC_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + if( strcmp( "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */ + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + if( strcmp( "MBEDTLS_ECP_NORMALIZE_JAC_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_NORMALIZE_JAC_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + if( strcmp( "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + if( strcmp( "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_RANDOMIZE_MXZ_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + if( strcmp( "MBEDTLS_ECP_NORMALIZE_MXZ_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_NORMALIZE_MXZ_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ + +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) + if( strcmp( "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN ); + return( 0 ); + } +#endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */ + +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND) + if( strcmp( "MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND ); + return( 0 ); + } +#endif /* MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + if( strcmp( "MBEDTLS_TEST_NULL_ENTROPY", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_TEST_NULL_ENTROPY ); + return( 0 ); + } +#endif /* MBEDTLS_TEST_NULL_ENTROPY */ + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + if( strcmp( "MBEDTLS_ENTROPY_HARDWARE_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ENTROPY_HARDWARE_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ + +#if defined(MBEDTLS_AES_ROM_TABLES) + if( strcmp( "MBEDTLS_AES_ROM_TABLES", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_AES_ROM_TABLES ); + return( 0 ); + } +#endif /* MBEDTLS_AES_ROM_TABLES */ + +#if defined(MBEDTLS_AES_FEWER_TABLES) + if( strcmp( "MBEDTLS_AES_FEWER_TABLES", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_AES_FEWER_TABLES ); + return( 0 ); + } +#endif /* MBEDTLS_AES_FEWER_TABLES */ + +#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) + if( strcmp( "MBEDTLS_CAMELLIA_SMALL_MEMORY", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CAMELLIA_SMALL_MEMORY ); + return( 0 ); + } +#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( strcmp( "MBEDTLS_CIPHER_MODE_CBC", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CIPHER_MODE_CBC ); + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + if( strcmp( "MBEDTLS_CIPHER_MODE_CFB", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CIPHER_MODE_CFB ); + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + if( strcmp( "MBEDTLS_CIPHER_MODE_CTR", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CIPHER_MODE_CTR ); + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + if( strcmp( "MBEDTLS_CIPHER_MODE_OFB", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CIPHER_MODE_OFB ); + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + if( strcmp( "MBEDTLS_CIPHER_MODE_XTS", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CIPHER_MODE_XTS ); + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( strcmp( "MBEDTLS_CIPHER_NULL_CIPHER", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CIPHER_NULL_CIPHER ); + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + if( strcmp( "MBEDTLS_CIPHER_PADDING_PKCS7", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CIPHER_PADDING_PKCS7 ); + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ + +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + if( strcmp( "MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS ); + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + if( strcmp( "MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN ); + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + if( strcmp( "MBEDTLS_CIPHER_PADDING_ZEROS", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CIPHER_PADDING_ZEROS ); + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ + +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) + if( strcmp( "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CTR_DRBG_USE_128_BIT_KEY ); + return( 0 ); + } +#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ + +#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) + if( strcmp( "MBEDTLS_ENABLE_WEAK_CIPHERSUITES", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ENABLE_WEAK_CIPHERSUITES ); + return( 0 ); + } +#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ + +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + if( strcmp( "MBEDTLS_REMOVE_ARC4_CIPHERSUITES", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_REMOVE_ARC4_CIPHERSUITES ); + return( 0 ); + } +#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ + +#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES) + if( strcmp( "MBEDTLS_REMOVE_3DES_CIPHERSUITES", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_REMOVE_3DES_CIPHERSUITES ); + return( 0 ); + } +#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + if( strcmp( "MBEDTLS_ECP_DP_SECP192R1_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DP_SECP192R1_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + if( strcmp( "MBEDTLS_ECP_DP_SECP224R1_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DP_SECP224R1_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + if( strcmp( "MBEDTLS_ECP_DP_SECP256R1_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DP_SECP256R1_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + if( strcmp( "MBEDTLS_ECP_DP_SECP384R1_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DP_SECP384R1_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + if( strcmp( "MBEDTLS_ECP_DP_SECP521R1_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DP_SECP521R1_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + if( strcmp( "MBEDTLS_ECP_DP_SECP192K1_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DP_SECP192K1_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + if( strcmp( "MBEDTLS_ECP_DP_SECP224K1_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DP_SECP224K1_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + if( strcmp( "MBEDTLS_ECP_DP_SECP256K1_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DP_SECP256K1_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + if( strcmp( "MBEDTLS_ECP_DP_BP256R1_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DP_BP256R1_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + if( strcmp( "MBEDTLS_ECP_DP_BP384R1_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DP_BP384R1_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + if( strcmp( "MBEDTLS_ECP_DP_BP512R1_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DP_BP512R1_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + if( strcmp( "MBEDTLS_ECP_DP_CURVE25519_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DP_CURVE25519_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + if( strcmp( "MBEDTLS_ECP_DP_CURVE448_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_DP_CURVE448_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +#if defined(MBEDTLS_ECP_NIST_OPTIM) + if( strcmp( "MBEDTLS_ECP_NIST_OPTIM", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_NIST_OPTIM ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( strcmp( "MBEDTLS_ECP_NO_INTERNAL_RNG", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_NO_INTERNAL_RNG ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( strcmp( "MBEDTLS_ECP_RESTARTABLE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_RESTARTABLE ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + if( strcmp( "MBEDTLS_ECDSA_DETERMINISTIC", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECDSA_DETERMINISTIC ); + return( 0 ); + } +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( strcmp( "MBEDTLS_KEY_EXCHANGE_PSK_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_KEY_EXCHANGE_PSK_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( strcmp( "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( strcmp( "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( strcmp( "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( strcmp( "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_KEY_EXCHANGE_RSA_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( strcmp( "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + if( strcmp( "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( strcmp( "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( strcmp( "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) + if( strcmp( "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( strcmp( "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED ); + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + if( strcmp( "MBEDTLS_PK_PARSE_EC_EXTENDED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PK_PARSE_EC_EXTENDED ); + return( 0 ); + } +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ + +#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) + if( strcmp( "MBEDTLS_ERROR_STRERROR_DUMMY", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ERROR_STRERROR_DUMMY ); + return( 0 ); + } +#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ + +#if defined(MBEDTLS_GENPRIME) + if( strcmp( "MBEDTLS_GENPRIME", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_GENPRIME ); + return( 0 ); + } +#endif /* MBEDTLS_GENPRIME */ + +#if defined(MBEDTLS_FS_IO) + if( strcmp( "MBEDTLS_FS_IO", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_FS_IO ); + return( 0 ); + } +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) + if( strcmp( "MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES ); + return( 0 ); + } +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ + +#if defined(MBEDTLS_NO_PLATFORM_ENTROPY) + if( strcmp( "MBEDTLS_NO_PLATFORM_ENTROPY", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_NO_PLATFORM_ENTROPY ); + return( 0 ); + } +#endif /* MBEDTLS_NO_PLATFORM_ENTROPY */ + +#if defined(MBEDTLS_ENTROPY_FORCE_SHA256) + if( strcmp( "MBEDTLS_ENTROPY_FORCE_SHA256", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ENTROPY_FORCE_SHA256 ); + return( 0 ); + } +#endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) + if( strcmp( "MBEDTLS_ENTROPY_NV_SEED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ENTROPY_NV_SEED ); + return( 0 ); + } +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_MEMORY_DEBUG) + if( strcmp( "MBEDTLS_MEMORY_DEBUG", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MEMORY_DEBUG ); + return( 0 ); + } +#endif /* MBEDTLS_MEMORY_DEBUG */ + +#if defined(MBEDTLS_MEMORY_BACKTRACE) + if( strcmp( "MBEDTLS_MEMORY_BACKTRACE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MEMORY_BACKTRACE ); + return( 0 ); + } +#endif /* MBEDTLS_MEMORY_BACKTRACE */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) + if( strcmp( "MBEDTLS_PK_RSA_ALT_SUPPORT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PK_RSA_ALT_SUPPORT ); + return( 0 ); + } +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +#if defined(MBEDTLS_PKCS1_V15) + if( strcmp( "MBEDTLS_PKCS1_V15", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PKCS1_V15 ); + return( 0 ); + } +#endif /* MBEDTLS_PKCS1_V15 */ + +#if defined(MBEDTLS_PKCS1_V21) + if( strcmp( "MBEDTLS_PKCS1_V21", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PKCS1_V21 ); + return( 0 ); + } +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_RSA_NO_CRT) + if( strcmp( "MBEDTLS_RSA_NO_CRT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_RSA_NO_CRT ); + return( 0 ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + +#if defined(MBEDTLS_SELF_TEST) + if( strcmp( "MBEDTLS_SELF_TEST", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SELF_TEST ); + return( 0 ); + } +#endif /* MBEDTLS_SELF_TEST */ + +#if defined(MBEDTLS_SHA256_SMALLER) + if( strcmp( "MBEDTLS_SHA256_SMALLER", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SHA256_SMALLER ); + return( 0 ); + } +#endif /* MBEDTLS_SHA256_SMALLER */ + +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( strcmp( "MBEDTLS_SSL_ALL_ALERT_MESSAGES", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_ALL_ALERT_MESSAGES ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( strcmp( "MBEDTLS_SSL_ASYNC_PRIVATE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_ASYNC_PRIVATE ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( strcmp( "MBEDTLS_SSL_DEBUG_ALL", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_DEBUG_ALL ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_DEBUG_ALL */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( strcmp( "MBEDTLS_SSL_ENCRYPT_THEN_MAC", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_ENCRYPT_THEN_MAC ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( strcmp( "MBEDTLS_SSL_EXTENDED_MASTER_SECRET", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_EXTENDED_MASTER_SECRET ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + if( strcmp( "MBEDTLS_SSL_FALLBACK_SCSV", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_FALLBACK_SCSV ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( strcmp( "MBEDTLS_SSL_HW_RECORD_ACCEL", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_HW_RECORD_ACCEL ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + if( strcmp( "MBEDTLS_SSL_CBC_RECORD_SPLITTING", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CBC_RECORD_SPLITTING ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( strcmp( "MBEDTLS_SSL_RENEGOTIATION", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_RENEGOTIATION ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) + if( strcmp( "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ + +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + if( strcmp( "MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( strcmp( "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_MAX_FRAGMENT_LENGTH ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( strcmp( "MBEDTLS_SSL_PROTO_SSL3", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_PROTO_SSL3 ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) + if( strcmp( "MBEDTLS_SSL_PROTO_TLS1", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_PROTO_TLS1 ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( strcmp( "MBEDTLS_SSL_PROTO_TLS1_1", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_PROTO_TLS1_1 ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( strcmp( "MBEDTLS_SSL_PROTO_TLS1_2", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_PROTO_TLS1_2 ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( strcmp( "MBEDTLS_SSL_PROTO_DTLS", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_PROTO_DTLS ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_ALPN) + if( strcmp( "MBEDTLS_SSL_ALPN", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_ALPN ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( strcmp( "MBEDTLS_SSL_DTLS_ANTI_REPLAY", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_DTLS_ANTI_REPLAY ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( strcmp( "MBEDTLS_SSL_DTLS_HELLO_VERIFY", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_DTLS_HELLO_VERIFY ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) + if( strcmp( "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + if( strcmp( "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_DTLS_BADMAC_LIMIT ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( strcmp( "MBEDTLS_SSL_SESSION_TICKETS", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_SESSION_TICKETS ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + if( strcmp( "MBEDTLS_SSL_EXPORT_KEYS", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_EXPORT_KEYS ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( strcmp( "MBEDTLS_SSL_SERVER_NAME_INDICATION", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_SERVER_NAME_INDICATION ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + if( strcmp( "MBEDTLS_SSL_TRUNCATED_HMAC", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_TRUNCATED_HMAC ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) + if( strcmp( "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */ + +#if defined(MBEDTLS_TEST_HOOKS) + if( strcmp( "MBEDTLS_TEST_HOOKS", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_TEST_HOOKS ); + return( 0 ); + } +#endif /* MBEDTLS_TEST_HOOKS */ + +#if defined(MBEDTLS_THREADING_ALT) + if( strcmp( "MBEDTLS_THREADING_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_THREADING_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_THREADING_ALT */ + +#if defined(MBEDTLS_THREADING_PTHREAD) + if( strcmp( "MBEDTLS_THREADING_PTHREAD", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_THREADING_PTHREAD ); + return( 0 ); + } +#endif /* MBEDTLS_THREADING_PTHREAD */ + +#if defined(MBEDTLS_VERSION_FEATURES) + if( strcmp( "MBEDTLS_VERSION_FEATURES", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_VERSION_FEATURES ); + return( 0 ); + } +#endif /* MBEDTLS_VERSION_FEATURES */ + +#if defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) + if( strcmp( "MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 ); + return( 0 ); + } +#endif /* MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 */ + +#if defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( strcmp( "MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION ); + return( 0 ); + } +#endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */ + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( strcmp( "MBEDTLS_X509_CHECK_KEY_USAGE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_CHECK_KEY_USAGE ); + return( 0 ); + } +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + if( strcmp( "MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE ); + return( 0 ); + } +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( strcmp( "MBEDTLS_X509_RSASSA_PSS_SUPPORT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_RSASSA_PSS_SUPPORT ); + return( 0 ); + } +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( strcmp( "MBEDTLS_ZLIB_SUPPORT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ZLIB_SUPPORT ); + return( 0 ); + } +#endif /* MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_AESNI_C) + if( strcmp( "MBEDTLS_AESNI_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_AESNI_C ); + return( 0 ); + } +#endif /* MBEDTLS_AESNI_C */ + +#if defined(MBEDTLS_AES_C) + if( strcmp( "MBEDTLS_AES_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_AES_C ); + return( 0 ); + } +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + if( strcmp( "MBEDTLS_ARC4_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ARC4_C ); + return( 0 ); + } +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_ASN1_PARSE_C) + if( strcmp( "MBEDTLS_ASN1_PARSE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ASN1_PARSE_C ); + return( 0 ); + } +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_ASN1_WRITE_C) + if( strcmp( "MBEDTLS_ASN1_WRITE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ASN1_WRITE_C ); + return( 0 ); + } +#endif /* MBEDTLS_ASN1_WRITE_C */ + +#if defined(MBEDTLS_BASE64_C) + if( strcmp( "MBEDTLS_BASE64_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_BASE64_C ); + return( 0 ); + } +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_BIGNUM_C) + if( strcmp( "MBEDTLS_BIGNUM_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_BIGNUM_C ); + return( 0 ); + } +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + if( strcmp( "MBEDTLS_BLOWFISH_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_BLOWFISH_C ); + return( 0 ); + } +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + if( strcmp( "MBEDTLS_CAMELLIA_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CAMELLIA_C ); + return( 0 ); + } +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_ARIA_C) + if( strcmp( "MBEDTLS_ARIA_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ARIA_C ); + return( 0 ); + } +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_CCM_C) + if( strcmp( "MBEDTLS_CCM_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CCM_C ); + return( 0 ); + } +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_CERTS_C) + if( strcmp( "MBEDTLS_CERTS_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CERTS_C ); + return( 0 ); + } +#endif /* MBEDTLS_CERTS_C */ + +#if defined(MBEDTLS_CHACHA20_C) + if( strcmp( "MBEDTLS_CHACHA20_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CHACHA20_C ); + return( 0 ); + } +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + if( strcmp( "MBEDTLS_CHACHAPOLY_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CHACHAPOLY_C ); + return( 0 ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ + +#if defined(MBEDTLS_CIPHER_C) + if( strcmp( "MBEDTLS_CIPHER_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CIPHER_C ); + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_CMAC_C) + if( strcmp( "MBEDTLS_CMAC_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CMAC_C ); + return( 0 ); + } +#endif /* MBEDTLS_CMAC_C */ + +#if defined(MBEDTLS_CTR_DRBG_C) + if( strcmp( "MBEDTLS_CTR_DRBG_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CTR_DRBG_C ); + return( 0 ); + } +#endif /* MBEDTLS_CTR_DRBG_C */ + +#if defined(MBEDTLS_DEBUG_C) + if( strcmp( "MBEDTLS_DEBUG_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_DEBUG_C ); + return( 0 ); + } +#endif /* MBEDTLS_DEBUG_C */ + +#if defined(MBEDTLS_DES_C) + if( strcmp( "MBEDTLS_DES_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_DES_C ); + return( 0 ); + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_DHM_C) + if( strcmp( "MBEDTLS_DHM_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_DHM_C ); + return( 0 ); + } +#endif /* MBEDTLS_DHM_C */ + +#if defined(MBEDTLS_ECDH_C) + if( strcmp( "MBEDTLS_ECDH_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECDH_C ); + return( 0 ); + } +#endif /* MBEDTLS_ECDH_C */ + +#if defined(MBEDTLS_ECDSA_C) + if( strcmp( "MBEDTLS_ECDSA_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECDSA_C ); + return( 0 ); + } +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_ECJPAKE_C) + if( strcmp( "MBEDTLS_ECJPAKE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECJPAKE_C ); + return( 0 ); + } +#endif /* MBEDTLS_ECJPAKE_C */ + +#if defined(MBEDTLS_ECP_C) + if( strcmp( "MBEDTLS_ECP_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_C ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_ENTROPY_C) + if( strcmp( "MBEDTLS_ENTROPY_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ENTROPY_C ); + return( 0 ); + } +#endif /* MBEDTLS_ENTROPY_C */ + +#if defined(MBEDTLS_ERROR_C) + if( strcmp( "MBEDTLS_ERROR_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ERROR_C ); + return( 0 ); + } +#endif /* MBEDTLS_ERROR_C */ + +#if defined(MBEDTLS_GCM_C) + if( strcmp( "MBEDTLS_GCM_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_GCM_C ); + return( 0 ); + } +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_HAVEGE_C) + if( strcmp( "MBEDTLS_HAVEGE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_HAVEGE_C ); + return( 0 ); + } +#endif /* MBEDTLS_HAVEGE_C */ + +#if defined(MBEDTLS_HKDF_C) + if( strcmp( "MBEDTLS_HKDF_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_HKDF_C ); + return( 0 ); + } +#endif /* MBEDTLS_HKDF_C */ + +#if defined(MBEDTLS_HMAC_DRBG_C) + if( strcmp( "MBEDTLS_HMAC_DRBG_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_HMAC_DRBG_C ); + return( 0 ); + } +#endif /* MBEDTLS_HMAC_DRBG_C */ + +#if defined(MBEDTLS_NIST_KW_C) + if( strcmp( "MBEDTLS_NIST_KW_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_NIST_KW_C ); + return( 0 ); + } +#endif /* MBEDTLS_NIST_KW_C */ + +#if defined(MBEDTLS_MD_C) + if( strcmp( "MBEDTLS_MD_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MD_C ); + return( 0 ); + } +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_MD2_C) + if( strcmp( "MBEDTLS_MD2_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MD2_C ); + return( 0 ); + } +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + if( strcmp( "MBEDTLS_MD4_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MD4_C ); + return( 0 ); + } +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + if( strcmp( "MBEDTLS_MD5_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MD5_C ); + return( 0 ); + } +#endif /* MBEDTLS_MD5_C */ + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + if( strcmp( "MBEDTLS_MEMORY_BUFFER_ALLOC_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MEMORY_BUFFER_ALLOC_C ); + return( 0 ); + } +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ + +#if defined(MBEDTLS_NET_C) + if( strcmp( "MBEDTLS_NET_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_NET_C ); + return( 0 ); + } +#endif /* MBEDTLS_NET_C */ + +#if defined(MBEDTLS_OID_C) + if( strcmp( "MBEDTLS_OID_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_OID_C ); + return( 0 ); + } +#endif /* MBEDTLS_OID_C */ + +#if defined(MBEDTLS_PADLOCK_C) + if( strcmp( "MBEDTLS_PADLOCK_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PADLOCK_C ); + return( 0 ); + } +#endif /* MBEDTLS_PADLOCK_C */ + +#if defined(MBEDTLS_PEM_PARSE_C) + if( strcmp( "MBEDTLS_PEM_PARSE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PEM_PARSE_C ); + return( 0 ); + } +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) + if( strcmp( "MBEDTLS_PEM_WRITE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PEM_WRITE_C ); + return( 0 ); + } +#endif /* MBEDTLS_PEM_WRITE_C */ + +#if defined(MBEDTLS_PK_C) + if( strcmp( "MBEDTLS_PK_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PK_C ); + return( 0 ); + } +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_PK_PARSE_C) + if( strcmp( "MBEDTLS_PK_PARSE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PK_PARSE_C ); + return( 0 ); + } +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) + if( strcmp( "MBEDTLS_PK_WRITE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PK_WRITE_C ); + return( 0 ); + } +#endif /* MBEDTLS_PK_WRITE_C */ + +#if defined(MBEDTLS_PKCS5_C) + if( strcmp( "MBEDTLS_PKCS5_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PKCS5_C ); + return( 0 ); + } +#endif /* MBEDTLS_PKCS5_C */ + +#if defined(MBEDTLS_PKCS11_C) + if( strcmp( "MBEDTLS_PKCS11_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PKCS11_C ); + return( 0 ); + } +#endif /* MBEDTLS_PKCS11_C */ + +#if defined(MBEDTLS_PKCS12_C) + if( strcmp( "MBEDTLS_PKCS12_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PKCS12_C ); + return( 0 ); + } +#endif /* MBEDTLS_PKCS12_C */ + +#if defined(MBEDTLS_PLATFORM_C) + if( strcmp( "MBEDTLS_PLATFORM_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_C ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_POLY1305_C) + if( strcmp( "MBEDTLS_POLY1305_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_POLY1305_C ); + return( 0 ); + } +#endif /* MBEDTLS_POLY1305_C */ + +#if defined(MBEDTLS_RIPEMD160_C) + if( strcmp( "MBEDTLS_RIPEMD160_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_RIPEMD160_C ); + return( 0 ); + } +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_RSA_C) + if( strcmp( "MBEDTLS_RSA_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_RSA_C ); + return( 0 ); + } +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_SHA1_C) + if( strcmp( "MBEDTLS_SHA1_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SHA1_C ); + return( 0 ); + } +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + if( strcmp( "MBEDTLS_SHA256_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SHA256_C ); + return( 0 ); + } +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + if( strcmp( "MBEDTLS_SHA512_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SHA512_C ); + return( 0 ); + } +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SSL_CACHE_C) + if( strcmp( "MBEDTLS_SSL_CACHE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CACHE_C ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_CACHE_C */ + +#if defined(MBEDTLS_SSL_COOKIE_C) + if( strcmp( "MBEDTLS_SSL_COOKIE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_COOKIE_C ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_COOKIE_C */ + +#if defined(MBEDTLS_SSL_TICKET_C) + if( strcmp( "MBEDTLS_SSL_TICKET_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_TICKET_C ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_TICKET_C */ + +#if defined(MBEDTLS_SSL_CLI_C) + if( strcmp( "MBEDTLS_SSL_CLI_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CLI_C ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_SRV_C) + if( strcmp( "MBEDTLS_SSL_SRV_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_SRV_C ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_TLS_C) + if( strcmp( "MBEDTLS_SSL_TLS_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_TLS_C ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_TLS_C */ + +#if defined(MBEDTLS_THREADING_C) + if( strcmp( "MBEDTLS_THREADING_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_THREADING_C ); + return( 0 ); + } +#endif /* MBEDTLS_THREADING_C */ + +#if defined(MBEDTLS_TIMING_C) + if( strcmp( "MBEDTLS_TIMING_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_TIMING_C ); + return( 0 ); + } +#endif /* MBEDTLS_TIMING_C */ + +#if defined(MBEDTLS_VERSION_C) + if( strcmp( "MBEDTLS_VERSION_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_VERSION_C ); + return( 0 ); + } +#endif /* MBEDTLS_VERSION_C */ + +#if defined(MBEDTLS_X509_USE_C) + if( strcmp( "MBEDTLS_X509_USE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_USE_C ); + return( 0 ); + } +#endif /* MBEDTLS_X509_USE_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( strcmp( "MBEDTLS_X509_CRT_PARSE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_CRT_PARSE_C ); + return( 0 ); + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + if( strcmp( "MBEDTLS_X509_CRL_PARSE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_CRL_PARSE_C ); + return( 0 ); + } +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +#if defined(MBEDTLS_X509_CSR_PARSE_C) + if( strcmp( "MBEDTLS_X509_CSR_PARSE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_CSR_PARSE_C ); + return( 0 ); + } +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + +#if defined(MBEDTLS_X509_CREATE_C) + if( strcmp( "MBEDTLS_X509_CREATE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_CREATE_C ); + return( 0 ); + } +#endif /* MBEDTLS_X509_CREATE_C */ + +#if defined(MBEDTLS_X509_CRT_WRITE_C) + if( strcmp( "MBEDTLS_X509_CRT_WRITE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_CRT_WRITE_C ); + return( 0 ); + } +#endif /* MBEDTLS_X509_CRT_WRITE_C */ + +#if defined(MBEDTLS_X509_CSR_WRITE_C) + if( strcmp( "MBEDTLS_X509_CSR_WRITE_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_CSR_WRITE_C ); + return( 0 ); + } +#endif /* MBEDTLS_X509_CSR_WRITE_C */ + +#if defined(MBEDTLS_XTEA_C) + if( strcmp( "MBEDTLS_XTEA_C", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_XTEA_C ); + return( 0 ); + } +#endif /* MBEDTLS_XTEA_C */ + +#if defined(MBEDTLS_MPI_WINDOW_SIZE) + if( strcmp( "MBEDTLS_MPI_WINDOW_SIZE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MPI_WINDOW_SIZE ); + return( 0 ); + } +#endif /* MBEDTLS_MPI_WINDOW_SIZE */ + +#if defined(MBEDTLS_MPI_MAX_SIZE) + if( strcmp( "MBEDTLS_MPI_MAX_SIZE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MPI_MAX_SIZE ); + return( 0 ); + } +#endif /* MBEDTLS_MPI_MAX_SIZE */ + +#if defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) + if( strcmp( "MBEDTLS_CTR_DRBG_ENTROPY_LEN", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CTR_DRBG_ENTROPY_LEN ); + return( 0 ); + } +#endif /* MBEDTLS_CTR_DRBG_ENTROPY_LEN */ + +#if defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) + if( strcmp( "MBEDTLS_CTR_DRBG_RESEED_INTERVAL", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CTR_DRBG_RESEED_INTERVAL ); + return( 0 ); + } +#endif /* MBEDTLS_CTR_DRBG_RESEED_INTERVAL */ + +#if defined(MBEDTLS_CTR_DRBG_MAX_INPUT) + if( strcmp( "MBEDTLS_CTR_DRBG_MAX_INPUT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CTR_DRBG_MAX_INPUT ); + return( 0 ); + } +#endif /* MBEDTLS_CTR_DRBG_MAX_INPUT */ + +#if defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) + if( strcmp( "MBEDTLS_CTR_DRBG_MAX_REQUEST", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CTR_DRBG_MAX_REQUEST ); + return( 0 ); + } +#endif /* MBEDTLS_CTR_DRBG_MAX_REQUEST */ + +#if defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) + if( strcmp( "MBEDTLS_CTR_DRBG_MAX_SEED_INPUT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); + return( 0 ); + } +#endif /* MBEDTLS_CTR_DRBG_MAX_SEED_INPUT */ + +#if defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) + if( strcmp( "MBEDTLS_HMAC_DRBG_RESEED_INTERVAL", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_HMAC_DRBG_RESEED_INTERVAL ); + return( 0 ); + } +#endif /* MBEDTLS_HMAC_DRBG_RESEED_INTERVAL */ + +#if defined(MBEDTLS_HMAC_DRBG_MAX_INPUT) + if( strcmp( "MBEDTLS_HMAC_DRBG_MAX_INPUT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_HMAC_DRBG_MAX_INPUT ); + return( 0 ); + } +#endif /* MBEDTLS_HMAC_DRBG_MAX_INPUT */ + +#if defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST) + if( strcmp( "MBEDTLS_HMAC_DRBG_MAX_REQUEST", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_HMAC_DRBG_MAX_REQUEST ); + return( 0 ); + } +#endif /* MBEDTLS_HMAC_DRBG_MAX_REQUEST */ + +#if defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) + if( strcmp( "MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); + return( 0 ); + } +#endif /* MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT */ + +#if defined(MBEDTLS_ECP_MAX_BITS) + if( strcmp( "MBEDTLS_ECP_MAX_BITS", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_MAX_BITS ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_MAX_BITS */ + +#if defined(MBEDTLS_ECP_WINDOW_SIZE) + if( strcmp( "MBEDTLS_ECP_WINDOW_SIZE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_WINDOW_SIZE ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_WINDOW_SIZE */ + +#if defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) + if( strcmp( "MBEDTLS_ECP_FIXED_POINT_OPTIM", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_FIXED_POINT_OPTIM ); + return( 0 ); + } +#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ + +#if defined(MBEDTLS_ENTROPY_MAX_SOURCES) + if( strcmp( "MBEDTLS_ENTROPY_MAX_SOURCES", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ENTROPY_MAX_SOURCES ); + return( 0 ); + } +#endif /* MBEDTLS_ENTROPY_MAX_SOURCES */ + +#if defined(MBEDTLS_ENTROPY_MAX_GATHER) + if( strcmp( "MBEDTLS_ENTROPY_MAX_GATHER", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ENTROPY_MAX_GATHER ); + return( 0 ); + } +#endif /* MBEDTLS_ENTROPY_MAX_GATHER */ + +#if defined(MBEDTLS_ENTROPY_MIN_HARDWARE) + if( strcmp( "MBEDTLS_ENTROPY_MIN_HARDWARE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_ENTROPY_MIN_HARDWARE ); + return( 0 ); + } +#endif /* MBEDTLS_ENTROPY_MIN_HARDWARE */ + +#if defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE) + if( strcmp( "MBEDTLS_MEMORY_ALIGN_MULTIPLE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_MEMORY_ALIGN_MULTIPLE ); + return( 0 ); + } +#endif /* MBEDTLS_MEMORY_ALIGN_MULTIPLE */ + +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) + if( strcmp( "MBEDTLS_PLATFORM_STD_MEM_HDR", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_STD_MEM_HDR ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_STD_MEM_HDR */ + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) + if( strcmp( "MBEDTLS_PLATFORM_STD_CALLOC", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_STD_CALLOC ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_STD_CALLOC */ + +#if defined(MBEDTLS_PLATFORM_STD_FREE) + if( strcmp( "MBEDTLS_PLATFORM_STD_FREE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_STD_FREE ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_STD_FREE */ + +#if defined(MBEDTLS_PLATFORM_STD_EXIT) + if( strcmp( "MBEDTLS_PLATFORM_STD_EXIT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_STD_EXIT ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_STD_EXIT */ + +#if defined(MBEDTLS_PLATFORM_STD_TIME) + if( strcmp( "MBEDTLS_PLATFORM_STD_TIME", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_STD_TIME ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_STD_TIME */ + +#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) + if( strcmp( "MBEDTLS_PLATFORM_STD_FPRINTF", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_STD_FPRINTF ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_STD_FPRINTF */ + +#if defined(MBEDTLS_PLATFORM_STD_PRINTF) + if( strcmp( "MBEDTLS_PLATFORM_STD_PRINTF", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_STD_PRINTF ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_STD_PRINTF */ + +#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) + if( strcmp( "MBEDTLS_PLATFORM_STD_SNPRINTF", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_STD_SNPRINTF ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_STD_SNPRINTF */ + +#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) + if( strcmp( "MBEDTLS_PLATFORM_STD_EXIT_SUCCESS", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_STD_EXIT_SUCCESS ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_STD_EXIT_SUCCESS */ + +#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) + if( strcmp( "MBEDTLS_PLATFORM_STD_EXIT_FAILURE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_STD_EXIT_FAILURE ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_STD_EXIT_FAILURE */ + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) + if( strcmp( "MBEDTLS_PLATFORM_STD_NV_SEED_READ", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_STD_NV_SEED_READ ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_STD_NV_SEED_READ */ + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) + if( strcmp( "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_STD_NV_SEED_WRITE ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) + if( strcmp( "MBEDTLS_PLATFORM_STD_NV_SEED_FILE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_STD_NV_SEED_FILE ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_STD_NV_SEED_FILE */ + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) + if( strcmp( "MBEDTLS_PLATFORM_CALLOC_MACRO", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_CALLOC_MACRO ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_CALLOC_MACRO */ + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) + if( strcmp( "MBEDTLS_PLATFORM_FREE_MACRO", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_FREE_MACRO ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_FREE_MACRO */ + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) + if( strcmp( "MBEDTLS_PLATFORM_EXIT_MACRO", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_EXIT_MACRO ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) + if( strcmp( "MBEDTLS_PLATFORM_TIME_MACRO", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_TIME_MACRO ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_TIME_MACRO */ + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) + if( strcmp( "MBEDTLS_PLATFORM_TIME_TYPE_MACRO", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_TIME_TYPE_MACRO ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) + if( strcmp( "MBEDTLS_PLATFORM_FPRINTF_MACRO", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_FPRINTF_MACRO ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) + if( strcmp( "MBEDTLS_PLATFORM_PRINTF_MACRO", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_PRINTF_MACRO ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) + if( strcmp( "MBEDTLS_PLATFORM_SNPRINTF_MACRO", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_SNPRINTF_MACRO ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ + +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) + if( strcmp( "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_NV_SEED_READ_MACRO ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_NV_SEED_READ_MACRO */ + +#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) + if( strcmp( "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO */ + +#if defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT) + if( strcmp( "MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT */ + +#if defined(MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES) + if( strcmp( "MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES */ + +#if defined(MBEDTLS_SSL_MAX_CONTENT_LEN) + if( strcmp( "MBEDTLS_SSL_MAX_CONTENT_LEN", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_MAX_CONTENT_LEN ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_MAX_CONTENT_LEN */ + +#if defined(MBEDTLS_SSL_IN_CONTENT_LEN) + if( strcmp( "MBEDTLS_SSL_IN_CONTENT_LEN", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_IN_CONTENT_LEN ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_IN_CONTENT_LEN */ + +#if defined(MBEDTLS_SSL_OUT_CONTENT_LEN) + if( strcmp( "MBEDTLS_SSL_OUT_CONTENT_LEN", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_OUT_CONTENT_LEN ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_OUT_CONTENT_LEN */ + +#if defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING) + if( strcmp( "MBEDTLS_SSL_DTLS_MAX_BUFFERING", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_DTLS_MAX_BUFFERING ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_DTLS_MAX_BUFFERING */ + +#if defined(MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME) + if( strcmp( "MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME */ + +#if defined(MBEDTLS_PSK_MAX_LEN) + if( strcmp( "MBEDTLS_PSK_MAX_LEN", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PSK_MAX_LEN ); + return( 0 ); + } +#endif /* MBEDTLS_PSK_MAX_LEN */ + +#if defined(MBEDTLS_SSL_COOKIE_TIMEOUT) + if( strcmp( "MBEDTLS_SSL_COOKIE_TIMEOUT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_COOKIE_TIMEOUT ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_COOKIE_TIMEOUT */ + +#if defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) + if( strcmp( "MBEDTLS_X509_MAX_INTERMEDIATE_CA", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_MAX_INTERMEDIATE_CA ); + return( 0 ); + } +#endif /* MBEDTLS_X509_MAX_INTERMEDIATE_CA */ + +#if defined(MBEDTLS_X509_MAX_FILE_PATH_LEN) + if( strcmp( "MBEDTLS_X509_MAX_FILE_PATH_LEN", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_MAX_FILE_PATH_LEN ); + return( 0 ); + } +#endif /* MBEDTLS_X509_MAX_FILE_PATH_LEN */ + +#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) + if( strcmp( "MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES ); + return( 0 ); + } +#endif /* MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES */ + +#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE) + if( strcmp( "MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE ); + return( 0 ); + } +#endif /* MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE */ + +#if defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) + if( strcmp( "MBEDTLS_PLATFORM_ZEROIZE_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_ZEROIZE_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ + +#if defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) + if( strcmp( "MBEDTLS_PLATFORM_GMTIME_R_ALT", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_GMTIME_R_ALT ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_GMTIME_R_ALT */ + + /* If the symbol is not found, return an error */ + return( 1 ); +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif /* _MSC_VER */ diff --git a/external/mbedtls/programs/ssl/ssl_client1.c b/external/mbedtls/programs/ssl/ssl_client1.c new file mode 100644 index 0000000..bb07feb --- /dev/null +++ b/external/mbedtls/programs/ssl/ssl_client1.c @@ -0,0 +1,345 @@ +/* + * SSL client demonstration program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_time time +#define mbedtls_time_t time_t +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \ + !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_CERTS_C) || !defined(MBEDTLS_PEM_PARSE_C) || \ + !defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or " + "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C " + "not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/net_sockets.h" +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "mbedtls/certs.h" + +#include + +#define SERVER_PORT "4433" +#define SERVER_NAME "localhost" +#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n" + +#define DEBUG_LEVEL 1 + + +static void my_debug( void *ctx, int level, + const char *file, int line, + const char *str ) +{ + ((void) level); + + mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str ); + fflush( (FILE *) ctx ); +} + +int main( void ) +{ + int ret = 1, len; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_net_context server_fd; + uint32_t flags; + unsigned char buf[1024]; + const char *pers = "ssl_client1"; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_x509_crt cacert; + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold( DEBUG_LEVEL ); +#endif + + /* + * 0. Initialize the RNG and the session data + */ + mbedtls_net_init( &server_fd ); + mbedtls_ssl_init( &ssl ); + mbedtls_ssl_config_init( &conf ); + mbedtls_x509_crt_init( &cacert ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + mbedtls_entropy_init( &entropy ); + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 0. Initialize certificates + */ + mbedtls_printf( " . Loading the CA root certificate ..." ); + fflush( stdout ); + + ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem, + mbedtls_test_cas_pem_len ); + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret ); + goto exit; + } + + mbedtls_printf( " ok (%d skipped)\n", ret ); + + /* + * 1. Start the connection + */ + mbedtls_printf( " . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT ); + fflush( stdout ); + + if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME, + SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 2. Setup stuff + */ + mbedtls_printf( " . Setting up the SSL/TLS structure..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ssl_config_defaults( &conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* OPTIONAL is not optimal for security, + * but makes interop easier in this simplified example */ + mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); + mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); + mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); + mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); + + if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); + goto exit; + } + + if( ( ret = mbedtls_ssl_set_hostname( &ssl, SERVER_NAME ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); + goto exit; + } + + mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); + + /* + * 4. Handshake + */ + mbedtls_printf( " . Performing the SSL/TLS handshake..." ); + fflush( stdout ); + + while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); + goto exit; + } + } + + mbedtls_printf( " ok\n" ); + + /* + * 5. Verify the server certificate + */ + mbedtls_printf( " . Verifying peer X.509 certificate..." ); + + /* In real life, we probably want to bail out when ret != 0 */ + if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 ) + { + char vrfy_buf[512]; + + mbedtls_printf( " failed\n" ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + + mbedtls_printf( "%s\n", vrfy_buf ); + } + else + mbedtls_printf( " ok\n" ); + + /* + * 3. Write the GET request + */ + mbedtls_printf( " > Write to server:" ); + fflush( stdout ); + + len = sprintf( (char *) buf, GET_REQUEST ); + + while( ( ret = mbedtls_ssl_write( &ssl, buf, len ) ) <= 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); + goto exit; + } + } + + len = ret; + mbedtls_printf( " %d bytes written\n\n%s", len, (char *) buf ); + + /* + * 7. Read the HTTP response + */ + mbedtls_printf( " < Read from server:" ); + fflush( stdout ); + + do + { + len = sizeof( buf ) - 1; + memset( buf, 0, sizeof( buf ) ); + ret = mbedtls_ssl_read( &ssl, buf, len ); + + if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) + continue; + + if( ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ) + break; + + if( ret < 0 ) + { + mbedtls_printf( "failed\n ! mbedtls_ssl_read returned %d\n\n", ret ); + break; + } + + if( ret == 0 ) + { + mbedtls_printf( "\n\nEOF\n\n" ); + break; + } + + len = ret; + mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); + } + while( 1 ); + + mbedtls_ssl_close_notify( &ssl ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + +#ifdef MBEDTLS_ERROR_C + if( exit_code != MBEDTLS_EXIT_SUCCESS ) + { + char error_buf[100]; + mbedtls_strerror( ret, error_buf, 100 ); + mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf ); + } +#endif + + mbedtls_net_free( &server_fd ); + + mbedtls_x509_crt_free( &cacert ); + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C && + MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C && + MBEDTLS_CERTS_C && MBEDTLS_PEM_PARSE_C && MBEDTLS_CTR_DRBG_C && + MBEDTLS_X509_CRT_PARSE_C */ diff --git a/external/mbedtls/programs/ssl/ssl_client2.c b/external/mbedtls/programs/ssl/ssl_client2.c new file mode 100644 index 0000000..4f26b57 --- /dev/null +++ b/external/mbedtls/programs/ssl/ssl_client2.c @@ -0,0 +1,2208 @@ +/* + * SSL client with certificate authentication + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_time time +#define mbedtls_time_t time_t +#define mbedtls_printf printf +#define mbedtls_fprintf fprintf +#define mbedtls_snprintf snprintf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif + +#if !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \ + !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or " + "MBEDTLS_NET_C and/or MBEDTLS_CTR_DRBG_C and/or not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/net_sockets.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/x509.h" +#include "mbedtls/error.h" +#include "mbedtls/debug.h" +#include "mbedtls/timing.h" + +#include +#include +#include + +#define MAX_REQUEST_SIZE 20000 +#define MAX_REQUEST_SIZE_STR "20000" + +#define DFL_SERVER_NAME "localhost" +#define DFL_SERVER_ADDR NULL +#define DFL_SERVER_PORT "4433" +#define DFL_REQUEST_PAGE "/" +#define DFL_REQUEST_SIZE -1 +#define DFL_DEBUG_LEVEL 0 +#define DFL_NBIO 0 +#define DFL_EVENT 0 +#define DFL_READ_TIMEOUT 0 +#define DFL_MAX_RESEND 0 +#define DFL_CA_FILE "" +#define DFL_CA_PATH "" +#define DFL_CRT_FILE "" +#define DFL_KEY_FILE "" +#define DFL_PSK "" +#define DFL_PSK_IDENTITY "Client_identity" +#define DFL_ECJPAKE_PW NULL +#define DFL_EC_MAX_OPS -1 +#define DFL_FORCE_CIPHER 0 +#define DFL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION_DISABLED +#define DFL_ALLOW_LEGACY -2 +#define DFL_RENEGOTIATE 0 +#define DFL_EXCHANGES 1 +#define DFL_MIN_VERSION -1 +#define DFL_MAX_VERSION -1 +#define DFL_ARC4 -1 +#define DFL_SHA1 -1 +#define DFL_AUTH_MODE -1 +#define DFL_MFL_CODE MBEDTLS_SSL_MAX_FRAG_LEN_NONE +#define DFL_TRUNC_HMAC -1 +#define DFL_RECSPLIT -1 +#define DFL_DHMLEN -1 +#define DFL_RECONNECT 0 +#define DFL_RECO_DELAY 0 +#define DFL_RECONNECT_HARD 0 +#define DFL_TICKETS MBEDTLS_SSL_SESSION_TICKETS_ENABLED +#define DFL_ALPN_STRING NULL +#define DFL_CURVES NULL +#define DFL_TRANSPORT MBEDTLS_SSL_TRANSPORT_STREAM +#define DFL_HS_TO_MIN 0 +#define DFL_HS_TO_MAX 0 +#define DFL_DTLS_MTU -1 +#define DFL_DGRAM_PACKING 1 +#define DFL_FALLBACK -1 +#define DFL_EXTENDED_MS -1 +#define DFL_ETM -1 +#define DFL_SKIP_CLOSE_NOTIFY 0 + +#define GET_REQUEST "GET %s HTTP/1.0\r\nExtra-header: " +#define GET_REQUEST_END "\r\n\r\n" + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_FS_IO) +#define USAGE_IO \ + " ca_file=%%s The single file containing the top-level CA(s) you fully trust\n" \ + " default: \"\" (pre-loaded)\n" \ + " use \"none\" to skip loading any top-level CAs.\n" \ + " ca_path=%%s The path containing the top-level CA(s) you fully trust\n" \ + " default: \"\" (pre-loaded) (overrides ca_file)\n" \ + " use \"none\" to skip loading any top-level CAs.\n" \ + " crt_file=%%s Your own cert and chain (in bottom to top order, top may be omitted)\n" \ + " default: \"\" (pre-loaded)\n" \ + " key_file=%%s default: \"\" (pre-loaded)\n" +#else +#define USAGE_IO \ + " No file operations available (MBEDTLS_FS_IO not defined)\n" +#endif /* MBEDTLS_FS_IO */ +#else +#define USAGE_IO "" +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#define USAGE_PSK \ + " psk=%%s default: \"\" (in hex, without 0x)\n" \ + " psk_identity=%%s default: \"Client_identity\"\n" +#else +#define USAGE_PSK "" +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#define USAGE_TICKETS \ + " tickets=%%d default: 1 (enabled)\n" +#else +#define USAGE_TICKETS "" +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#define USAGE_TRUNC_HMAC \ + " trunc_hmac=%%d default: library default\n" +#else +#define USAGE_TRUNC_HMAC "" +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +#define USAGE_MAX_FRAG_LEN \ + " max_frag_len=%%d default: 16384 (tls default)\n" \ + " options: 512, 1024, 2048, 4096\n" +#else +#define USAGE_MAX_FRAG_LEN "" +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +#define USAGE_RECSPLIT \ + " recsplit=0/1 default: (library default: on)\n" +#else +#define USAGE_RECSPLIT +#endif + +#if defined(MBEDTLS_DHM_C) +#define USAGE_DHMLEN \ + " dhmlen=%%d default: (library default: 1024 bits)\n" +#else +#define USAGE_DHMLEN +#endif + +#if defined(MBEDTLS_SSL_ALPN) +#define USAGE_ALPN \ + " alpn=%%s default: \"\" (disabled)\n" \ + " example: spdy/1,http/1.1\n" +#else +#define USAGE_ALPN "" +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_ECP_C) +#define USAGE_CURVES \ + " curves=a,b,c,d default: \"default\" (library default)\n" \ + " example: \"secp521r1,brainpoolP512r1\"\n" \ + " - use \"none\" for empty list\n" \ + " - see mbedtls_ecp_curve_list()\n" \ + " for acceptable curve names\n" +#else +#define USAGE_CURVES "" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +#define USAGE_DTLS \ + " dtls=%%d default: 0 (TLS)\n" \ + " hs_timeout=%%d-%%d default: (library default: 1000-60000)\n" \ + " range of DTLS handshake timeouts in millisecs\n" \ + " mtu=%%d default: (library default: unlimited)\n" \ + " dgram_packing=%%d default: 1 (allowed)\n" \ + " allow or forbid packing of multiple\n" \ + " records within a single datgram.\n" +#else +#define USAGE_DTLS "" +#endif + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) +#define USAGE_FALLBACK \ + " fallback=0/1 default: (library default: off)\n" +#else +#define USAGE_FALLBACK "" +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +#define USAGE_EMS \ + " extended_ms=0/1 default: (library default: on)\n" +#else +#define USAGE_EMS "" +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +#define USAGE_ETM \ + " etm=0/1 default: (library default: on)\n" +#else +#define USAGE_ETM "" +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +#define USAGE_RENEGO \ + " renegotiation=%%d default: 0 (disabled)\n" \ + " renegotiate=%%d default: 0 (disabled)\n" +#else +#define USAGE_RENEGO "" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#define USAGE_ECJPAKE \ + " ecjpake_pw=%%s default: none (disabled)\n" +#else +#define USAGE_ECJPAKE "" +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) +#define USAGE_ECRESTART \ + " ec_max_ops=%%s default: library default (restart disabled)\n" +#else +#define USAGE_ECRESTART "" +#endif + +/* USAGE is arbitrarily split to stay under the portable string literal + * length limit: 4095 bytes in C99. */ +#define USAGE1 \ + "\n usage: ssl_client2 param=<>...\n" \ + "\n acceptable parameters:\n" \ + " server_name=%%s default: localhost\n" \ + " server_addr=%%s default: given by name\n" \ + " server_port=%%d default: 4433\n" \ + " request_page=%%s default: \".\"\n" \ + " request_size=%%d default: about 34 (basic request)\n" \ + " (minimum: 0, max: " MAX_REQUEST_SIZE_STR ")\n" \ + " If 0, in the first exchange only an empty\n" \ + " application data message is sent followed by\n" \ + " a second non-empty message before attempting\n" \ + " to read a response from the server\n" \ + " debug_level=%%d default: 0 (disabled)\n" \ + " nbio=%%d default: 0 (blocking I/O)\n" \ + " options: 1 (non-blocking), 2 (added delays)\n" \ + " event=%%d default: 0 (loop)\n" \ + " options: 1 (level-triggered, implies nbio=1),\n" \ + " read_timeout=%%d default: 0 ms (no timeout)\n" \ + " max_resend=%%d default: 0 (no resend on timeout)\n" \ + " skip_close_notify=%%d default: 0 (send close_notify)\n" \ + "\n" \ + USAGE_DTLS \ + "\n" +#define USAGE2 \ + " auth_mode=%%s default: (library default: none)\n" \ + " options: none, optional, required\n" \ + USAGE_IO \ + "\n" \ + USAGE_PSK \ + USAGE_ECJPAKE \ + USAGE_ECRESTART \ + "\n" +#define USAGE3 \ + " allow_legacy=%%d default: (library default: no)\n" \ + USAGE_RENEGO \ + " exchanges=%%d default: 1\n" \ + " reconnect=%%d default: 0 (disabled)\n" \ + " reco_delay=%%d default: 0 seconds\n" \ + " reconnect_hard=%%d default: 0 (disabled)\n" \ + USAGE_TICKETS \ + USAGE_MAX_FRAG_LEN \ + USAGE_TRUNC_HMAC \ + USAGE_ALPN \ + USAGE_FALLBACK \ + USAGE_EMS \ + USAGE_ETM \ + USAGE_CURVES \ + USAGE_RECSPLIT \ + USAGE_DHMLEN \ + "\n" +#define USAGE4 \ + " arc4=%%d default: (library default: 0)\n" \ + " allow_sha1=%%d default: 0\n" \ + " min_version=%%s default: (library default: tls1)\n" \ + " max_version=%%s default: (library default: tls1_2)\n" \ + " force_version=%%s default: \"\" (none)\n" \ + " options: ssl3, tls1, tls1_1, tls1_2, dtls1, dtls1_2\n" \ + "\n" \ + " force_ciphersuite= default: all enabled\n"\ + " query_config= return 0 if the specified\n" \ + " configuration macro is defined and 1\n" \ + " otherwise. The expansion of the macro\n" \ + " is printed if it is defined\n" \ + " acceptable ciphersuite names:\n" + +#define ALPN_LIST_SIZE 10 +#define CURVE_LIST_SIZE 20 + + +/* + * global options + */ +struct options +{ + const char *server_name; /* hostname of the server (client only) */ + const char *server_addr; /* address of the server (client only) */ + const char *server_port; /* port on which the ssl service runs */ + int debug_level; /* level of debugging */ + int nbio; /* should I/O be blocking? */ + int event; /* loop or event-driven IO? level or edge triggered? */ + uint32_t read_timeout; /* timeout on mbedtls_ssl_read() in milliseconds */ + int max_resend; /* DTLS times to resend on read timeout */ + const char *request_page; /* page on server to request */ + int request_size; /* pad request with header to requested size */ + const char *ca_file; /* the file with the CA certificate(s) */ + const char *ca_path; /* the path with the CA certificate(s) reside */ + const char *crt_file; /* the file with the client certificate */ + const char *key_file; /* the file with the client key */ + const char *psk; /* the pre-shared key */ + const char *psk_identity; /* the pre-shared key identity */ + const char *ecjpake_pw; /* the EC J-PAKE password */ + int ec_max_ops; /* EC consecutive operations limit */ + int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */ + int renegotiation; /* enable / disable renegotiation */ + int allow_legacy; /* allow legacy renegotiation */ + int renegotiate; /* attempt renegotiation? */ + int renego_delay; /* delay before enforcing renegotiation */ + int exchanges; /* number of data exchanges */ + int min_version; /* minimum protocol version accepted */ + int max_version; /* maximum protocol version accepted */ + int arc4; /* flag for arc4 suites support */ + int allow_sha1; /* flag for SHA-1 support */ + int auth_mode; /* verify mode for connection */ + unsigned char mfl_code; /* code for maximum fragment length */ + int trunc_hmac; /* negotiate truncated hmac or not */ + int recsplit; /* enable record splitting? */ + int dhmlen; /* minimum DHM params len in bits */ + int reconnect; /* attempt to resume session */ + int reco_delay; /* delay in seconds before resuming session */ + int reconnect_hard; /* unexpectedly reconnect from the same port */ + int tickets; /* enable / disable session tickets */ + const char *curves; /* list of supported elliptic curves */ + const char *alpn_string; /* ALPN supported protocols */ + int transport; /* TLS or DTLS? */ + uint32_t hs_to_min; /* Initial value of DTLS handshake timer */ + uint32_t hs_to_max; /* Max value of DTLS handshake timer */ + int dtls_mtu; /* UDP Maximum tranport unit for DTLS */ + int fallback; /* is this a fallback connection? */ + int dgram_packing; /* allow/forbid datagram packing */ + int extended_ms; /* negotiate extended master secret? */ + int etm; /* negotiate encrypt then mac? */ + int skip_close_notify; /* skip sending the close_notify alert */ +} opt; + +int query_config( const char *config ); + +static void my_debug( void *ctx, int level, + const char *file, int line, + const char *str ) +{ + const char *p, *basename; + + /* Extract basename from file */ + for( p = basename = file; *p != '\0'; p++ ) + if( *p == '/' || *p == '\\' ) + basename = p + 1; + + mbedtls_fprintf( (FILE *) ctx, "%s:%04d: |%d| %s", + basename, line, level, str ); + fflush( (FILE *) ctx ); +} + +/* + * Test recv/send functions that make sure each try returns + * WANT_READ/WANT_WRITE at least once before sucesseding + */ +static int my_recv( void *ctx, unsigned char *buf, size_t len ) +{ + static int first_try = 1; + int ret; + + if( first_try ) + { + first_try = 0; + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + + ret = mbedtls_net_recv( ctx, buf, len ); + if( ret != MBEDTLS_ERR_SSL_WANT_READ ) + first_try = 1; /* Next call will be a new operation */ + return( ret ); +} + +static int my_send( void *ctx, const unsigned char *buf, size_t len ) +{ + static int first_try = 1; + int ret; + + if( first_try ) + { + first_try = 0; + return( MBEDTLS_ERR_SSL_WANT_WRITE ); + } + + ret = mbedtls_net_send( ctx, buf, len ); + if( ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + first_try = 1; /* Next call will be a new operation */ + return( ret ); +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * Enabled if debug_level > 1 in code below + */ +static int my_verify( void *data, mbedtls_x509_crt *crt, + int depth, uint32_t *flags ) +{ + char buf[1024]; + ((void) data); + + mbedtls_printf( "\nVerify requested for (Depth %d):\n", depth ); + mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); + mbedtls_printf( "%s", buf ); + + if ( ( *flags ) == 0 ) + mbedtls_printf( " This certificate has no flags\n" ); + else + { + mbedtls_x509_crt_verify_info( buf, sizeof( buf ), " ! ", *flags ); + mbedtls_printf( "%s\n", buf ); + } + + return( 0 ); +} + +static int ssl_sig_hashes_for_test[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, + MBEDTLS_MD_SHA384, +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif +#if defined(MBEDTLS_SHA1_C) + /* Allow SHA-1 as we use it extensively in tests. */ + MBEDTLS_MD_SHA1, +#endif + MBEDTLS_MD_NONE +}; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Wait for an event from the underlying transport or the timer + * (Used in event-driven IO mode). + */ +#if !defined(MBEDTLS_TIMING_C) +int idle( mbedtls_net_context *fd, + int idle_reason ) +#else +int idle( mbedtls_net_context *fd, + mbedtls_timing_delay_context *timer, + int idle_reason ) +#endif +{ + + int ret; + int poll_type = 0; + + if( idle_reason == MBEDTLS_ERR_SSL_WANT_WRITE ) + poll_type = MBEDTLS_NET_POLL_WRITE; + else if( idle_reason == MBEDTLS_ERR_SSL_WANT_READ ) + poll_type = MBEDTLS_NET_POLL_READ; +#if !defined(MBEDTLS_TIMING_C) + else + return( 0 ); +#endif + + while( 1 ) + { + /* Check if timer has expired */ +#if defined(MBEDTLS_TIMING_C) + if( timer != NULL && + mbedtls_timing_get_delay( timer ) == 2 ) + { + break; + } +#endif /* MBEDTLS_TIMING_C */ + + /* Check if underlying transport became available */ + if( poll_type != 0 ) + { + ret = mbedtls_net_poll( fd, poll_type, 0 ); + if( ret < 0 ) + return( ret ); + if( ret == poll_type ) + break; + } + } + + return( 0 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 0, len, tail_len, i, written, frags, retry_left; + mbedtls_net_context server_fd; + + unsigned char buf[MAX_REQUEST_SIZE + 1]; + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + unsigned char psk[MBEDTLS_PSK_MAX_LEN]; + size_t psk_len = 0; +#endif +#if defined(MBEDTLS_SSL_ALPN) + const char *alpn_list[ALPN_LIST_SIZE]; +#endif +#if defined(MBEDTLS_ECP_C) + mbedtls_ecp_group_id curve_list[CURVE_LIST_SIZE]; + const mbedtls_ecp_curve_info *curve_cur; +#endif + + const char *pers = "ssl_client2"; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_profile crt_profile_for_test = mbedtls_x509_crt_profile_default; +#endif + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_ssl_session saved_session; +#if defined(MBEDTLS_TIMING_C) + mbedtls_timing_delay_context timer; +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) + uint32_t flags; + mbedtls_x509_crt cacert; + mbedtls_x509_crt clicert; + mbedtls_pk_context pkey; +#endif + char *p, *q; + const int *list; + + /* + * Make sure memory references are valid. + */ + mbedtls_net_init( &server_fd ); + mbedtls_ssl_init( &ssl ); + mbedtls_ssl_config_init( &conf ); + memset( &saved_session, 0, sizeof( mbedtls_ssl_session ) ); + mbedtls_ctr_drbg_init( &ctr_drbg ); +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_init( &cacert ); + mbedtls_x509_crt_init( &clicert ); + mbedtls_pk_init( &pkey ); +#endif +#if defined(MBEDTLS_SSL_ALPN) + memset( (void * ) alpn_list, 0, sizeof( alpn_list ) ); +#endif + + if( argc == 0 ) + { + usage: + if( ret == 0 ) + ret = 1; + + mbedtls_printf( USAGE1 ); + mbedtls_printf( USAGE2 ); + mbedtls_printf( USAGE3 ); + mbedtls_printf( USAGE4 ); + + list = mbedtls_ssl_list_ciphersuites(); + while( *list ) + { + mbedtls_printf(" %-42s", mbedtls_ssl_get_ciphersuite_name( *list ) ); + list++; + if( !*list ) + break; + mbedtls_printf(" %s\n", mbedtls_ssl_get_ciphersuite_name( *list ) ); + list++; + } + mbedtls_printf("\n"); + goto exit; + } + + opt.server_name = DFL_SERVER_NAME; + opt.server_addr = DFL_SERVER_ADDR; + opt.server_port = DFL_SERVER_PORT; + opt.debug_level = DFL_DEBUG_LEVEL; + opt.nbio = DFL_NBIO; + opt.event = DFL_EVENT; + opt.read_timeout = DFL_READ_TIMEOUT; + opt.max_resend = DFL_MAX_RESEND; + opt.request_page = DFL_REQUEST_PAGE; + opt.request_size = DFL_REQUEST_SIZE; + opt.ca_file = DFL_CA_FILE; + opt.ca_path = DFL_CA_PATH; + opt.crt_file = DFL_CRT_FILE; + opt.key_file = DFL_KEY_FILE; + opt.psk = DFL_PSK; + opt.psk_identity = DFL_PSK_IDENTITY; + opt.ecjpake_pw = DFL_ECJPAKE_PW; + opt.ec_max_ops = DFL_EC_MAX_OPS; + opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; + opt.renegotiation = DFL_RENEGOTIATION; + opt.allow_legacy = DFL_ALLOW_LEGACY; + opt.renegotiate = DFL_RENEGOTIATE; + opt.exchanges = DFL_EXCHANGES; + opt.min_version = DFL_MIN_VERSION; + opt.max_version = DFL_MAX_VERSION; + opt.arc4 = DFL_ARC4; + opt.allow_sha1 = DFL_SHA1; + opt.auth_mode = DFL_AUTH_MODE; + opt.mfl_code = DFL_MFL_CODE; + opt.trunc_hmac = DFL_TRUNC_HMAC; + opt.recsplit = DFL_RECSPLIT; + opt.dhmlen = DFL_DHMLEN; + opt.reconnect = DFL_RECONNECT; + opt.reco_delay = DFL_RECO_DELAY; + opt.reconnect_hard = DFL_RECONNECT_HARD; + opt.tickets = DFL_TICKETS; + opt.alpn_string = DFL_ALPN_STRING; + opt.curves = DFL_CURVES; + opt.transport = DFL_TRANSPORT; + opt.hs_to_min = DFL_HS_TO_MIN; + opt.hs_to_max = DFL_HS_TO_MAX; + opt.dtls_mtu = DFL_DTLS_MTU; + opt.fallback = DFL_FALLBACK; + opt.extended_ms = DFL_EXTENDED_MS; + opt.etm = DFL_ETM; + opt.dgram_packing = DFL_DGRAM_PACKING; + opt.skip_close_notify = DFL_SKIP_CLOSE_NOTIFY; + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "server_name" ) == 0 ) + opt.server_name = q; + else if( strcmp( p, "server_addr" ) == 0 ) + opt.server_addr = q; + else if( strcmp( p, "server_port" ) == 0 ) + opt.server_port = q; + else if( strcmp( p, "dtls" ) == 0 ) + { + int t = atoi( q ); + if( t == 0 ) + opt.transport = MBEDTLS_SSL_TRANSPORT_STREAM; + else if( t == 1 ) + opt.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + else + goto usage; + } + else if( strcmp( p, "debug_level" ) == 0 ) + { + opt.debug_level = atoi( q ); + if( opt.debug_level < 0 || opt.debug_level > 65535 ) + goto usage; + } + else if( strcmp( p, "nbio" ) == 0 ) + { + opt.nbio = atoi( q ); + if( opt.nbio < 0 || opt.nbio > 2 ) + goto usage; + } + else if( strcmp( p, "event" ) == 0 ) + { + opt.event = atoi( q ); + if( opt.event < 0 || opt.event > 2 ) + goto usage; + } + else if( strcmp( p, "read_timeout" ) == 0 ) + opt.read_timeout = atoi( q ); + else if( strcmp( p, "max_resend" ) == 0 ) + { + opt.max_resend = atoi( q ); + if( opt.max_resend < 0 ) + goto usage; + } + else if( strcmp( p, "request_page" ) == 0 ) + opt.request_page = q; + else if( strcmp( p, "request_size" ) == 0 ) + { + opt.request_size = atoi( q ); + if( opt.request_size < 0 || + opt.request_size > MAX_REQUEST_SIZE ) + goto usage; + } + else if( strcmp( p, "ca_file" ) == 0 ) + opt.ca_file = q; + else if( strcmp( p, "ca_path" ) == 0 ) + opt.ca_path = q; + else if( strcmp( p, "crt_file" ) == 0 ) + opt.crt_file = q; + else if( strcmp( p, "key_file" ) == 0 ) + opt.key_file = q; + else if( strcmp( p, "psk" ) == 0 ) + opt.psk = q; + else if( strcmp( p, "psk_identity" ) == 0 ) + opt.psk_identity = q; + else if( strcmp( p, "ecjpake_pw" ) == 0 ) + opt.ecjpake_pw = q; + else if( strcmp( p, "ec_max_ops" ) == 0 ) + opt.ec_max_ops = atoi( q ); + else if( strcmp( p, "force_ciphersuite" ) == 0 ) + { + opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q ); + + if( opt.force_ciphersuite[0] == 0 ) + { + ret = 2; + goto usage; + } + opt.force_ciphersuite[1] = 0; + } + else if( strcmp( p, "renegotiation" ) == 0 ) + { + opt.renegotiation = (atoi( q )) ? + MBEDTLS_SSL_RENEGOTIATION_ENABLED : + MBEDTLS_SSL_RENEGOTIATION_DISABLED; + } + else if( strcmp( p, "allow_legacy" ) == 0 ) + { + switch( atoi( q ) ) + { + case -1: + opt.allow_legacy = MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE; + break; + case 0: + opt.allow_legacy = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION; + break; + case 1: + opt.allow_legacy = MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION; + break; + default: goto usage; + } + } + else if( strcmp( p, "renegotiate" ) == 0 ) + { + opt.renegotiate = atoi( q ); + if( opt.renegotiate < 0 || opt.renegotiate > 1 ) + goto usage; + } + else if( strcmp( p, "exchanges" ) == 0 ) + { + opt.exchanges = atoi( q ); + if( opt.exchanges < 1 ) + goto usage; + } + else if( strcmp( p, "reconnect" ) == 0 ) + { + opt.reconnect = atoi( q ); + if( opt.reconnect < 0 || opt.reconnect > 2 ) + goto usage; + } + else if( strcmp( p, "reco_delay" ) == 0 ) + { + opt.reco_delay = atoi( q ); + if( opt.reco_delay < 0 ) + goto usage; + } + else if( strcmp( p, "reconnect_hard" ) == 0 ) + { + opt.reconnect_hard = atoi( q ); + if( opt.reconnect_hard < 0 || opt.reconnect_hard > 1 ) + goto usage; + } + else if( strcmp( p, "tickets" ) == 0 ) + { + opt.tickets = atoi( q ); + if( opt.tickets < 0 || opt.tickets > 2 ) + goto usage; + } + else if( strcmp( p, "alpn" ) == 0 ) + { + opt.alpn_string = q; + } + else if( strcmp( p, "fallback" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.fallback = MBEDTLS_SSL_IS_NOT_FALLBACK; break; + case 1: opt.fallback = MBEDTLS_SSL_IS_FALLBACK; break; + default: goto usage; + } + } + else if( strcmp( p, "extended_ms" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: + opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_DISABLED; + break; + case 1: + opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + break; + default: goto usage; + } + } + else if( strcmp( p, "curves" ) == 0 ) + opt.curves = q; + else if( strcmp( p, "etm" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.etm = MBEDTLS_SSL_ETM_DISABLED; break; + case 1: opt.etm = MBEDTLS_SSL_ETM_ENABLED; break; + default: goto usage; + } + } + else if( strcmp( p, "min_version" ) == 0 ) + { + if( strcmp( q, "ssl3" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_0; + else if( strcmp( q, "tls1" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_1; + else if( strcmp( q, "tls1_1" ) == 0 || + strcmp( q, "dtls1" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + else if( strcmp( q, "tls1_2" ) == 0 || + strcmp( q, "dtls1_2" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3; + else + goto usage; + } + else if( strcmp( p, "max_version" ) == 0 ) + { + if( strcmp( q, "ssl3" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_0; + else if( strcmp( q, "tls1" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_1; + else if( strcmp( q, "tls1_1" ) == 0 || + strcmp( q, "dtls1" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2; + else if( strcmp( q, "tls1_2" ) == 0 || + strcmp( q, "dtls1_2" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3; + else + goto usage; + } + else if( strcmp( p, "arc4" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.arc4 = MBEDTLS_SSL_ARC4_DISABLED; break; + case 1: opt.arc4 = MBEDTLS_SSL_ARC4_ENABLED; break; + default: goto usage; + } + } + else if( strcmp( p, "allow_sha1" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.allow_sha1 = 0; break; + case 1: opt.allow_sha1 = 1; break; + default: goto usage; + } + } + else if( strcmp( p, "force_version" ) == 0 ) + { + if( strcmp( q, "ssl3" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_0; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_0; + } + else if( strcmp( q, "tls1" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_1; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_1; + } + else if( strcmp( q, "tls1_1" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2; + } + else if( strcmp( q, "tls1_2" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3; + } + else if( strcmp( q, "dtls1" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2; + opt.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + } + else if( strcmp( q, "dtls1_2" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3; + opt.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + } + else + goto usage; + } + else if( strcmp( p, "auth_mode" ) == 0 ) + { + if( strcmp( q, "none" ) == 0 ) + opt.auth_mode = MBEDTLS_SSL_VERIFY_NONE; + else if( strcmp( q, "optional" ) == 0 ) + opt.auth_mode = MBEDTLS_SSL_VERIFY_OPTIONAL; + else if( strcmp( q, "required" ) == 0 ) + opt.auth_mode = MBEDTLS_SSL_VERIFY_REQUIRED; + else + goto usage; + } + else if( strcmp( p, "max_frag_len" ) == 0 ) + { + if( strcmp( q, "512" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_512; + else if( strcmp( q, "1024" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_1024; + else if( strcmp( q, "2048" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_2048; + else if( strcmp( q, "4096" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_4096; + else + goto usage; + } + else if( strcmp( p, "trunc_hmac" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_DISABLED; break; + case 1: opt.trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; break; + default: goto usage; + } + } + else if( strcmp( p, "hs_timeout" ) == 0 ) + { + if( ( p = strchr( q, '-' ) ) == NULL ) + goto usage; + *p++ = '\0'; + opt.hs_to_min = atoi( q ); + opt.hs_to_max = atoi( p ); + if( opt.hs_to_min == 0 || opt.hs_to_max < opt.hs_to_min ) + goto usage; + } + else if( strcmp( p, "mtu" ) == 0 ) + { + opt.dtls_mtu = atoi( q ); + if( opt.dtls_mtu < 0 ) + goto usage; + } + else if( strcmp( p, "dgram_packing" ) == 0 ) + { + opt.dgram_packing = atoi( q ); + if( opt.dgram_packing != 0 && + opt.dgram_packing != 1 ) + { + goto usage; + } + } + else if( strcmp( p, "recsplit" ) == 0 ) + { + opt.recsplit = atoi( q ); + if( opt.recsplit < 0 || opt.recsplit > 1 ) + goto usage; + } + else if( strcmp( p, "dhmlen" ) == 0 ) + { + opt.dhmlen = atoi( q ); + if( opt.dhmlen < 0 ) + goto usage; + } + else if( strcmp( p, "query_config" ) == 0 ) + { + mbedtls_exit( query_config( q ) ); + } + else if( strcmp( p, "skip_close_notify" ) == 0 ) + { + opt.skip_close_notify = atoi( q ); + if( opt.skip_close_notify < 0 || opt.skip_close_notify > 1 ) + goto usage; + } + else + goto usage; + } + + /* Event-driven IO is incompatible with the above custom + * receive and send functions, as the polling builds on + * refers to the underlying net_context. */ + if( opt.event == 1 && opt.nbio != 1 ) + { + mbedtls_printf( "Warning: event-driven IO mandates nbio=1 - overwrite\n" ); + opt.nbio = 1; + } + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold( opt.debug_level ); +#endif + + if( opt.force_ciphersuite[0] > 0 ) + { + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] ); + + if( opt.max_version != -1 && + ciphersuite_info->min_minor_ver > opt.max_version ) + { + mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" ); + ret = 2; + goto usage; + } + if( opt.min_version != -1 && + ciphersuite_info->max_minor_ver < opt.min_version ) + { + mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" ); + ret = 2; + goto usage; + } + + /* If the server selects a version that's not supported by + * this suite, then there will be no common ciphersuite... */ + if( opt.max_version == -1 || + opt.max_version > ciphersuite_info->max_minor_ver ) + { + opt.max_version = ciphersuite_info->max_minor_ver; + } + if( opt.min_version < ciphersuite_info->min_minor_ver ) + { + opt.min_version = ciphersuite_info->min_minor_ver; + /* DTLS starts with TLS 1.1 */ + if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + opt.min_version < MBEDTLS_SSL_MINOR_VERSION_2 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + } + + /* Enable RC4 if needed and not explicitly disabled */ + if( ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + { + if( opt.arc4 == MBEDTLS_SSL_ARC4_DISABLED ) + { + mbedtls_printf( "forced RC4 ciphersuite with RC4 disabled\n" ); + ret = 2; + goto usage; + } + + opt.arc4 = MBEDTLS_SSL_ARC4_ENABLED; + } + } + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + /* + * Unhexify the pre-shared key if any is given + */ + if( strlen( opt.psk ) ) + { + unsigned char c; + size_t j; + + if( strlen( opt.psk ) % 2 != 0 ) + { + mbedtls_printf( "pre-shared key not valid hex\n" ); + goto exit; + } + + psk_len = strlen( opt.psk ) / 2; + + for( j = 0; j < strlen( opt.psk ); j += 2 ) + { + c = opt.psk[j]; + if( c >= '0' && c <= '9' ) + c -= '0'; + else if( c >= 'a' && c <= 'f' ) + c -= 'a' - 10; + else if( c >= 'A' && c <= 'F' ) + c -= 'A' - 10; + else + { + mbedtls_printf( "pre-shared key not valid hex\n" ); + goto exit; + } + psk[ j / 2 ] = c << 4; + + c = opt.psk[j + 1]; + if( c >= '0' && c <= '9' ) + c -= '0'; + else if( c >= 'a' && c <= 'f' ) + c -= 'a' - 10; + else if( c >= 'A' && c <= 'F' ) + c -= 'A' - 10; + else + { + mbedtls_printf( "pre-shared key not valid hex\n" ); + goto exit; + } + psk[ j / 2 ] |= c; + } + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_ECP_C) + if( opt.curves != NULL ) + { + p = (char *) opt.curves; + i = 0; + + if( strcmp( p, "none" ) == 0 ) + { + curve_list[0] = MBEDTLS_ECP_DP_NONE; + } + else if( strcmp( p, "default" ) != 0 ) + { + /* Leave room for a final NULL in curve list */ + while( i < CURVE_LIST_SIZE - 1 && *p != '\0' ) + { + q = p; + + /* Terminate the current string */ + while( *p != ',' && *p != '\0' ) + p++; + if( *p == ',' ) + *p++ = '\0'; + + if( ( curve_cur = mbedtls_ecp_curve_info_from_name( q ) ) != NULL ) + { + curve_list[i++] = curve_cur->grp_id; + } + else + { + mbedtls_printf( "unknown curve %s\n", q ); + mbedtls_printf( "supported curves: " ); + for( curve_cur = mbedtls_ecp_curve_list(); + curve_cur->grp_id != MBEDTLS_ECP_DP_NONE; + curve_cur++ ) + { + mbedtls_printf( "%s ", curve_cur->name ); + } + mbedtls_printf( "\n" ); + goto exit; + } + } + + mbedtls_printf("Number of curves: %d\n", i ); + + if( i == CURVE_LIST_SIZE - 1 && *p != '\0' ) + { + mbedtls_printf( "curves list too long, maximum %d", + CURVE_LIST_SIZE - 1 ); + goto exit; + } + + curve_list[i] = MBEDTLS_ECP_DP_NONE; + } + } +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_SSL_ALPN) + if( opt.alpn_string != NULL ) + { + p = (char *) opt.alpn_string; + i = 0; + + /* Leave room for a final NULL in alpn_list */ + while( i < ALPN_LIST_SIZE - 1 && *p != '\0' ) + { + alpn_list[i++] = p; + + /* Terminate the current string and move on to next one */ + while( *p != ',' && *p != '\0' ) + p++; + if( *p == ',' ) + *p++ = '\0'; + } + } +#endif /* MBEDTLS_SSL_ALPN */ + + /* + * 0. Initialize the RNG and the session data + */ + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + mbedtls_entropy_init( &entropy ); + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, + &entropy, (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", + -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * 1.1. Load the trusted CA + */ + mbedtls_printf( " . Loading the CA root certificate ..." ); + fflush( stdout ); + + if( strcmp( opt.ca_path, "none" ) == 0 || + strcmp( opt.ca_file, "none" ) == 0 ) + { + ret = 0; + } + else +#if defined(MBEDTLS_FS_IO) + if( strlen( opt.ca_path ) ) + ret = mbedtls_x509_crt_parse_path( &cacert, opt.ca_path ); + else if( strlen( opt.ca_file ) ) + ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file ); + else +#endif +#if defined(MBEDTLS_CERTS_C) + { +#if defined(MBEDTLS_PEM_PARSE_C) + for( i = 0; mbedtls_test_cas[i] != NULL; i++ ) + { + ret = mbedtls_x509_crt_parse( &cacert, + (const unsigned char *) mbedtls_test_cas[i], + mbedtls_test_cas_len[i] ); + if( ret != 0 ) + break; + } + if( ret == 0 ) +#endif /* MBEDTLS_PEM_PARSE_C */ + for( i = 0; mbedtls_test_cas_der[i] != NULL; i++ ) + { + ret = mbedtls_x509_crt_parse_der( &cacert, + (const unsigned char *) mbedtls_test_cas_der[i], + mbedtls_test_cas_der_len[i] ); + if( ret != 0 ) + break; + } + } +#else + { + ret = 1; + mbedtls_printf( "MBEDTLS_CERTS_C not defined." ); + } +#endif /* MBEDTLS_CERTS_C */ + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", + -ret ); + goto exit; + } + + mbedtls_printf( " ok (%d skipped)\n", ret ); + + /* + * 1.2. Load own certificate and private key + * + * (can be skipped if client authentication is not required) + */ + mbedtls_printf( " . Loading the client cert. and key..." ); + fflush( stdout ); + + if( strcmp( opt.crt_file, "none" ) == 0 ) + ret = 0; + else +#if defined(MBEDTLS_FS_IO) + if( strlen( opt.crt_file ) ) + ret = mbedtls_x509_crt_parse_file( &clicert, opt.crt_file ); + else +#endif +#if defined(MBEDTLS_CERTS_C) + ret = mbedtls_x509_crt_parse( &clicert, + (const unsigned char *) mbedtls_test_cli_crt, + mbedtls_test_cli_crt_len ); +#else + { + ret = 1; + mbedtls_printf( "MBEDTLS_CERTS_C not defined." ); + } +#endif + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", + -ret ); + goto exit; + } + + if( strcmp( opt.key_file, "none" ) == 0 ) + ret = 0; + else +#if defined(MBEDTLS_FS_IO) + if( strlen( opt.key_file ) ) + ret = mbedtls_pk_parse_keyfile( &pkey, opt.key_file, "" ); + else +#endif +#if defined(MBEDTLS_CERTS_C) + ret = mbedtls_pk_parse_key( &pkey, + (const unsigned char *) mbedtls_test_cli_key, + mbedtls_test_cli_key_len, NULL, 0 ); +#else + { + ret = 1; + mbedtls_printf( "MBEDTLS_CERTS_C not defined." ); + } +#endif + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n", + -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + /* + * 2. Start the connection + */ + if( opt.server_addr == NULL) + opt.server_addr = opt.server_name; + + mbedtls_printf( " . Connecting to %s/%s/%s...", + opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ? "tcp" : "udp", + opt.server_addr, opt.server_port ); + fflush( stdout ); + + if( ( ret = mbedtls_net_connect( &server_fd, + opt.server_addr, opt.server_port, + opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ? + MBEDTLS_NET_PROTO_TCP : MBEDTLS_NET_PROTO_UDP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_connect returned -0x%x\n\n", + -ret ); + goto exit; + } + + if( opt.nbio > 0 ) + ret = mbedtls_net_set_nonblock( &server_fd ); + else + ret = mbedtls_net_set_block( &server_fd ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! net_set_(non)block() returned -0x%x\n\n", + -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 3. Setup stuff + */ + mbedtls_printf( " . Setting up the SSL/TLS structure..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ssl_config_defaults( &conf, + MBEDTLS_SSL_IS_CLIENT, + opt.transport, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", + -ret ); + goto exit; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* The default algorithms profile disables SHA-1, but our tests still + rely on it heavily. */ + if( opt.allow_sha1 > 0 ) + { + crt_profile_for_test.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ); + mbedtls_ssl_conf_cert_profile( &conf, &crt_profile_for_test ); + mbedtls_ssl_conf_sig_hashes( &conf, ssl_sig_hashes_for_test ); + } + + if( opt.debug_level > 0 ) + mbedtls_ssl_conf_verify( &conf, my_verify, NULL ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( opt.auth_mode != DFL_AUTH_MODE ) + mbedtls_ssl_conf_authmode( &conf, opt.auth_mode ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( opt.hs_to_min != DFL_HS_TO_MIN || opt.hs_to_max != DFL_HS_TO_MAX ) + mbedtls_ssl_conf_handshake_timeout( &conf, opt.hs_to_min, + opt.hs_to_max ); + + if( opt.dgram_packing != DFL_DGRAM_PACKING ) + mbedtls_ssl_set_datagram_packing( &ssl, opt.dgram_packing ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( ( ret = mbedtls_ssl_conf_max_frag_len( &conf, opt.mfl_code ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_max_frag_len returned %d\n\n", + ret ); + goto exit; + } +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + if( opt.trunc_hmac != DFL_TRUNC_HMAC ) + mbedtls_ssl_conf_truncated_hmac( &conf, opt.trunc_hmac ); +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( opt.extended_ms != DFL_EXTENDED_MS ) + mbedtls_ssl_conf_extended_master_secret( &conf, opt.extended_ms ); +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( opt.etm != DFL_ETM ) + mbedtls_ssl_conf_encrypt_then_mac( &conf, opt.etm ); +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + if( opt.recsplit != DFL_RECSPLIT ) + mbedtls_ssl_conf_cbc_record_splitting( &conf, opt.recsplit + ? MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED + : MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ); +#endif + +#if defined(MBEDTLS_DHM_C) + if( opt.dhmlen != DFL_DHMLEN ) + mbedtls_ssl_conf_dhm_min_bitlen( &conf, opt.dhmlen ); +#endif + +#if defined(MBEDTLS_SSL_ALPN) + if( opt.alpn_string != NULL ) + if( ( ret = mbedtls_ssl_conf_alpn_protocols( &conf, alpn_list ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_alpn_protocols returned %d\n\n", + ret ); + goto exit; + } +#endif + + mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); + mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); + + mbedtls_ssl_conf_read_timeout( &conf, opt.read_timeout ); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_conf_session_tickets( &conf, opt.tickets ); +#endif + + if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER ) + mbedtls_ssl_conf_ciphersuites( &conf, opt.force_ciphersuite ); + +#if defined(MBEDTLS_ARC4_C) + if( opt.arc4 != DFL_ARC4 ) + mbedtls_ssl_conf_arc4_support( &conf, opt.arc4 ); +#endif + + if( opt.allow_legacy != DFL_ALLOW_LEGACY ) + mbedtls_ssl_conf_legacy_renegotiation( &conf, opt.allow_legacy ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + mbedtls_ssl_conf_renegotiation( &conf, opt.renegotiation ); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( strcmp( opt.ca_path, "none" ) != 0 && + strcmp( opt.ca_file, "none" ) != 0 ) + { + mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); + } + if( strcmp( opt.crt_file, "none" ) != 0 && + strcmp( opt.key_file, "none" ) != 0 ) + { + if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &clicert, &pkey ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", + ret ); + goto exit; + } + } +#endif + +#if defined(MBEDTLS_ECP_C) + if( opt.curves != NULL && + strcmp( opt.curves, "default" ) != 0 ) + { + mbedtls_ssl_conf_curves( &conf, curve_list ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( ( ret = mbedtls_ssl_conf_psk( &conf, psk, psk_len, + (const unsigned char *) opt.psk_identity, + strlen( opt.psk_identity ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_psk returned %d\n\n", + ret ); + goto exit; + } +#endif + + if( opt.min_version != DFL_MIN_VERSION ) + mbedtls_ssl_conf_min_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, + opt.min_version ); + + if( opt.max_version != DFL_MAX_VERSION ) + mbedtls_ssl_conf_max_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, + opt.max_version ); + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + if( opt.fallback != DFL_FALLBACK ) + mbedtls_ssl_conf_fallback( &conf, opt.fallback ); +#endif + + if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", + -ret ); + goto exit; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( ( ret = mbedtls_ssl_set_hostname( &ssl, opt.server_name ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", + ret ); + goto exit; + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( opt.ecjpake_pw != DFL_ECJPAKE_PW ) + { + if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl, + (const unsigned char *) opt.ecjpake_pw, + strlen( opt.ecjpake_pw ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", + ret ); + goto exit; + } + } +#endif + + if( opt.nbio == 2 ) + mbedtls_ssl_set_bio( &ssl, &server_fd, my_send, my_recv, NULL ); + else + mbedtls_ssl_set_bio( &ssl, &server_fd, + mbedtls_net_send, mbedtls_net_recv, + opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( opt.dtls_mtu != DFL_DTLS_MTU ) + mbedtls_ssl_set_mtu( &ssl, opt.dtls_mtu ); +#endif + +#if defined(MBEDTLS_TIMING_C) + mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, + mbedtls_timing_get_delay ); +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( opt.ec_max_ops != DFL_EC_MAX_OPS ) + mbedtls_ecp_set_max_ops( opt.ec_max_ops ); +#endif + + mbedtls_printf( " ok\n" ); + + /* + * 4. Handshake + */ + mbedtls_printf( " . Performing the SSL/TLS handshake..." ); + fflush( stdout ); + + while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n", + -ret ); + if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) + mbedtls_printf( + " Unable to verify the server's certificate. " + "Either it is invalid,\n" + " or you didn't set ca_file or ca_path " + "to an appropriate value.\n" + " Alternatively, you may want to use " + "auth_mode=optional for testing purposes.\n" ); + mbedtls_printf( "\n" ); + goto exit; + } + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + continue; +#endif + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + ret = idle( &server_fd, &timer, ret ); +#else + ret = idle( &server_fd, ret ); +#endif + if( ret != 0 ) + goto exit; + } + } + + mbedtls_printf( " ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n", + mbedtls_ssl_get_version( &ssl ), + mbedtls_ssl_get_ciphersuite( &ssl ) ); + + if( ( ret = mbedtls_ssl_get_record_expansion( &ssl ) ) >= 0 ) + mbedtls_printf( " [ Record expansion is %d ]\n", ret ); + else + mbedtls_printf( " [ Record expansion is unknown (compression) ]\n" ); + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + mbedtls_printf( " [ Maximum fragment length is %u ]\n", + (unsigned int) mbedtls_ssl_get_max_frag_len( &ssl ) ); +#endif + +#if defined(MBEDTLS_SSL_ALPN) + if( opt.alpn_string != NULL ) + { + const char *alp = mbedtls_ssl_get_alpn_protocol( &ssl ); + mbedtls_printf( " [ Application Layer Protocol is %s ]\n", + alp ? alp : "(none)" ); + } +#endif + + if( opt.reconnect != 0 ) + { + mbedtls_printf(" . Saving session for reuse..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ssl_get_session( &ssl, &saved_session ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_get_session returned -0x%x\n\n", + -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * 5. Verify the server certificate + */ + mbedtls_printf( " . Verifying peer X.509 certificate..." ); + + if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 ) + { + char vrfy_buf[512]; + + mbedtls_printf( " failed\n" ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), + " ! ", flags ); + + mbedtls_printf( "%s\n", vrfy_buf ); + } + else + mbedtls_printf( " ok\n" ); + + if( mbedtls_ssl_get_peer_cert( &ssl ) != NULL ) + { + mbedtls_printf( " . Peer certificate information ...\n" ); + mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ", + mbedtls_ssl_get_peer_cert( &ssl ) ); + mbedtls_printf( "%s\n", buf ); + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( opt.renegotiate ) + { + /* + * Perform renegotiation (this must be done when the server is waiting + * for input from our side). + */ + mbedtls_printf( " . Performing renegotiation..." ); + fflush( stdout ); + while( ( ret = mbedtls_ssl_renegotiate( &ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", + ret ); + goto exit; + } + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + continue; +#endif + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &server_fd, &timer, ret ); +#else + idle( &server_fd, ret ); +#endif + } + + } + mbedtls_printf( " ok\n" ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* + * 6. Write the GET request + */ + retry_left = opt.max_resend; +send_request: + mbedtls_printf( " > Write to server:" ); + fflush( stdout ); + + len = mbedtls_snprintf( (char *) buf, sizeof( buf ) - 1, GET_REQUEST, + opt.request_page ); + tail_len = (int) strlen( GET_REQUEST_END ); + + /* Add padding to GET request to reach opt.request_size in length */ + if( opt.request_size != DFL_REQUEST_SIZE && + len + tail_len < opt.request_size ) + { + memset( buf + len, 'A', opt.request_size - len - tail_len ); + len += opt.request_size - len - tail_len; + } + + strncpy( (char *) buf + len, GET_REQUEST_END, sizeof( buf ) - len - 1 ); + len += tail_len; + + /* Truncate if request size is smaller than the "natural" size */ + if( opt.request_size != DFL_REQUEST_SIZE && + len > opt.request_size ) + { + len = opt.request_size; + + /* Still end with \r\n unless that's really not possible */ + if( len >= 2 ) buf[len - 2] = '\r'; + if( len >= 1 ) buf[len - 1] = '\n'; + } + + if( opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ) + { + written = 0; + frags = 0; + + do + { + while( ( ret = mbedtls_ssl_write( &ssl, buf + written, + len - written ) ) < 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_write returned -0x%x\n\n", + -ret ); + goto exit; + } + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &server_fd, &timer, ret ); +#else + idle( &server_fd, ret ); +#endif + } + } + + frags++; + written += ret; + } + while( written < len ); + } + else /* Not stream, so datagram */ + { + while( 1 ) + { + ret = mbedtls_ssl_write( &ssl, buf, len ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + continue; +#endif + + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + break; + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &server_fd, &timer, ret ); +#else + idle( &server_fd, ret ); +#endif + } + } + + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", + ret ); + goto exit; + } + + frags = 1; + written = ret; + + if( written < len ) + { + mbedtls_printf( " warning\n ! request didn't fit into single datagram and " + "was truncated to size %u", (unsigned) written ); + } + } + + buf[written] = '\0'; + mbedtls_printf( " %d bytes written in %d fragments\n\n%s\n", + written, frags, (char *) buf ); + + /* Send a non-empty request if request_size == 0 */ + if ( len == 0 ) + { + opt.request_size = DFL_REQUEST_SIZE; + goto send_request; + } + + /* + * 7. Read the HTTP response + */ + mbedtls_printf( " < Read from server:" ); + fflush( stdout ); + + /* + * TLS and DTLS need different reading styles (stream vs datagram) + */ + if( opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ) + { + do + { + len = sizeof( buf ) - 1; + memset( buf, 0, sizeof( buf ) ); + ret = mbedtls_ssl_read( &ssl, buf, len ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + continue; +#endif + + if( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE ) + { + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &server_fd, &timer, ret ); +#else + idle( &server_fd, ret ); +#endif + } + continue; + } + + if( ret <= 0 ) + { + switch( ret ) + { + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf( " connection was closed gracefully\n" ); + ret = 0; + goto close_notify; + + case 0: + case MBEDTLS_ERR_NET_CONN_RESET: + mbedtls_printf( " connection was reset by peer\n" ); + ret = 0; + goto reconnect; + + default: + mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", + -ret ); + goto exit; + } + } + + len = ret; + buf[len] = '\0'; + mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); + + /* End of message should be detected according to the syntax of the + * application protocol (eg HTTP), just use a dummy test here. */ + if( ret > 0 && buf[len-1] == '\n' ) + { + ret = 0; + break; + } + } + while( 1 ); + } + else /* Not stream, so datagram */ + { + len = sizeof( buf ) - 1; + memset( buf, 0, sizeof( buf ) ); + + while( 1 ) + { + ret = mbedtls_ssl_read( &ssl, buf, len ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + continue; +#endif + + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + break; + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &server_fd, &timer, ret ); +#else + idle( &server_fd, ret ); +#endif + } + } + + if( ret <= 0 ) + { + switch( ret ) + { + case MBEDTLS_ERR_SSL_TIMEOUT: + mbedtls_printf( " timeout\n" ); + if( retry_left-- > 0 ) + goto send_request; + goto exit; + + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf( " connection was closed gracefully\n" ); + ret = 0; + goto close_notify; + + default: + mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", -ret ); + goto exit; + } + } + + len = ret; + buf[len] = '\0'; + mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); + ret = 0; + } + + /* + * 7b. Simulate hard reset and reconnect from same port? + */ + if( opt.reconnect_hard != 0 ) + { + opt.reconnect_hard = 0; + + mbedtls_printf( " . Restarting connection from same port..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n", + -ret ); + goto exit; + } + + while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", + -ret ); + goto exit; + } + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &server_fd, &timer, ret ); +#else + idle( &server_fd, ret ); +#endif + } + } + + mbedtls_printf( " ok\n" ); + + goto send_request; + } + + /* + * 7c. Continue doing data exchanges? + */ + if( --opt.exchanges > 0 ) + goto send_request; + + /* + * 8. Done, cleanly close the connection + */ +close_notify: + mbedtls_printf( " . Closing the connection..." ); + fflush( stdout ); + + /* + * Most of the time sending a close_notify before closing is the right + * thing to do. However, when the server already knows how many messages + * are expected and closes the connection by itself, this alert becomes + * redundant. Sometimes with DTLS this redundancy becomes a problem by + * leading to a race condition where the server might close the connection + * before seeing the alert, and since UDP is connection-less when the + * alert arrives it will be seen as a new connection, which will fail as + * the alert is clearly not a valid ClientHello. This may cause spurious + * failures in tests that use DTLS and resumption with ssl_server2 in + * ssl-opt.sh, avoided by enabling skip_close_notify client-side. + */ + if( opt.skip_close_notify == 0 ) + { + /* No error checking, the connection might be closed already */ + do ret = mbedtls_ssl_close_notify( &ssl ); + while( ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + ret = 0; + } + + mbedtls_printf( " done\n" ); + + /* + * 9. Reconnect? + */ +reconnect: + if( opt.reconnect != 0 ) + { + --opt.reconnect; + + mbedtls_net_free( &server_fd ); + +#if defined(MBEDTLS_TIMING_C) + if( opt.reco_delay > 0 ) + mbedtls_net_usleep( 1000000 * opt.reco_delay ); +#endif + + mbedtls_printf( " . Reconnecting with saved session..." ); + + if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n", + -ret ); + goto exit; + } + + if( ( ret = mbedtls_ssl_set_session( &ssl, &saved_session ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_session returned %d\n\n", + ret ); + goto exit; + } + + if( ( ret = mbedtls_net_connect( &server_fd, + opt.server_addr, opt.server_port, + opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ? + MBEDTLS_NET_PROTO_TCP : MBEDTLS_NET_PROTO_UDP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_connect returned -0x%x\n\n", + -ret ); + goto exit; + } + + if( opt.nbio > 0 ) + ret = mbedtls_net_set_nonblock( &server_fd ); + else + ret = mbedtls_net_set_block( &server_fd ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! net_set_(non)block() returned -0x%x\n\n", + -ret ); + goto exit; + } + + while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", + -ret ); + goto exit; + } + } + + mbedtls_printf( " ok\n" ); + + goto send_request; + } + + /* + * Cleanup and exit + */ +exit: +#ifdef MBEDTLS_ERROR_C + if( ret != 0 ) + { + char error_buf[100]; + mbedtls_strerror( ret, error_buf, 100 ); + mbedtls_printf("Last error was: -0x%X - %s\n\n", -ret, error_buf ); + } +#endif + + mbedtls_net_free( &server_fd ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_free( &clicert ); + mbedtls_x509_crt_free( &cacert ); + mbedtls_pk_free( &pkey ); +#endif + mbedtls_ssl_session_free( &saved_session ); + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + // Shell can not handle large exit numbers -> 1 for errors + if( ret < 0 ) + ret = 1; + + mbedtls_exit( ret ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C && + MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C && + MBEDTLS_CTR_DRBG_C MBEDTLS_TIMING_C */ diff --git a/external/mbedtls/programs/ssl/ssl_fork_server.c b/external/mbedtls/programs/ssl/ssl_fork_server.c new file mode 100644 index 0000000..9713c34 --- /dev/null +++ b/external/mbedtls/programs/ssl/ssl_fork_server.c @@ -0,0 +1,449 @@ +/* + * SSL server demonstration program using fork() for handling multiple clients + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_time_t time_t +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_CERTS_C) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_SSL_TLS_C) || \ + !defined(MBEDTLS_SSL_SRV_C) || !defined(MBEDTLS_NET_C) || \ + !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_CTR_DRBG_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_TIMING_C) || \ + !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_PEM_PARSE_C) +int main( int argc, char *argv[] ) +{ + ((void) argc); + ((void) argv); + + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_CERTS_C and/or MBEDTLS_ENTROPY_C " + "and/or MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_SRV_C and/or " + "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C and/or " + "MBEDTLS_TIMING_C and/or MBEDTLS_PEM_PARSE_C not defined.\n"); + mbedtls_exit( 0 ); +} +#elif defined(_WIN32) +int main( void ) +{ + mbedtls_printf("_WIN32 defined. This application requires fork() and signals " + "to work correctly.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/x509.h" +#include "mbedtls/ssl.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/timing.h" + +#include +#include + +#if !defined(_MSC_VER) || defined(EFIX64) || defined(EFI32) +#include +#endif + +#define HTTP_RESPONSE \ + "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ + "

mbed TLS Test Server

\r\n" \ + "

Successful connection using: %s

\r\n" + +#define DEBUG_LEVEL 0 + + +static void my_debug( void *ctx, int level, + const char *file, int line, + const char *str ) +{ + ((void) level); + + mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str ); + fflush( (FILE *) ctx ); +} + +int main( void ) +{ + int ret = 1, len, cnt = 0, pid; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_net_context listen_fd, client_fd; + unsigned char buf[1024]; + const char *pers = "ssl_fork_server"; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_x509_crt srvcert; + mbedtls_pk_context pkey; + + mbedtls_net_init( &listen_fd ); + mbedtls_net_init( &client_fd ); + mbedtls_ssl_init( &ssl ); + mbedtls_ssl_config_init( &conf ); + mbedtls_entropy_init( &entropy ); + mbedtls_pk_init( &pkey ); + mbedtls_x509_crt_init( &srvcert ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + + signal( SIGCHLD, SIG_IGN ); + + /* + * 0. Initial seeding of the RNG + */ + mbedtls_printf( "\n . Initial seeding of the random generator..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed! mbedtls_ctr_drbg_seed returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1. Load the certificates and private RSA key + */ + mbedtls_printf( " . Loading the server cert. and key..." ); + fflush( stdout ); + + /* + * This demonstration program uses embedded test certificates. + * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the + * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). + */ + ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, + mbedtls_test_srv_crt_len ); + if( ret != 0 ) + { + mbedtls_printf( " failed! mbedtls_x509_crt_parse returned %d\n\n", ret ); + goto exit; + } + + ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem, + mbedtls_test_cas_pem_len ); + if( ret != 0 ) + { + mbedtls_printf( " failed! mbedtls_x509_crt_parse returned %d\n\n", ret ); + goto exit; + } + + ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, + mbedtls_test_srv_key_len, NULL, 0 ); + if( ret != 0 ) + { + mbedtls_printf( " failed! mbedtls_pk_parse_key returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1b. Prepare SSL configuration + */ + mbedtls_printf( " . Configuring SSL..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ssl_config_defaults( &conf, + MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) + { + mbedtls_printf( " failed! mbedtls_ssl_config_defaults returned %d\n\n", ret ); + goto exit; + } + + mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); + mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); + + mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL ); + if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 ) + { + mbedtls_printf( " failed! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 2. Setup the listening TCP socket + */ + mbedtls_printf( " . Bind on https://localhost:4433/ ..." ); + fflush( stdout ); + + if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP ) ) != 0 ) + { + mbedtls_printf( " failed! mbedtls_net_bind returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + while( 1 ) + { + /* + * 3. Wait until a client connects + */ + mbedtls_net_init( &client_fd ); + mbedtls_ssl_init( &ssl ); + + mbedtls_printf( " . Waiting for a remote connection ...\n" ); + fflush( stdout ); + + if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, + NULL, 0, NULL ) ) != 0 ) + { + mbedtls_printf( " failed! mbedtls_net_accept returned %d\n\n", ret ); + goto exit; + } + + /* + * 3.5. Forking server thread + */ + + mbedtls_printf( " . Forking to handle connection ..." ); + fflush( stdout ); + + pid = fork(); + + if( pid < 0 ) + { + mbedtls_printf(" failed! fork returned %d\n\n", pid ); + goto exit; + } + + if( pid != 0 ) + { + mbedtls_printf( " ok\n" ); + + if( ( ret = mbedtls_ctr_drbg_reseed( &ctr_drbg, + (const unsigned char *) "parent", + 6 ) ) != 0 ) + { + mbedtls_printf( " failed! mbedtls_ctr_drbg_reseed returned %d\n\n", ret ); + goto exit; + } + + continue; + } + + mbedtls_net_init( &listen_fd ); + + pid = getpid(); + + /* + * 4. Setup stuff + */ + mbedtls_printf( "pid %d: Setting up the SSL data.\n", pid ); + fflush( stdout ); + + if( ( ret = mbedtls_ctr_drbg_reseed( &ctr_drbg, + (const unsigned char *) "child", + 5 ) ) != 0 ) + { + mbedtls_printf( + "pid %d: SSL setup failed! mbedtls_ctr_drbg_reseed returned %d\n\n", + pid, ret ); + goto exit; + } + + if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + mbedtls_printf( + "pid %d: SSL setup failed! mbedtls_ssl_setup returned %d\n\n", + pid, ret ); + goto exit; + } + + mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); + + mbedtls_printf( "pid %d: SSL setup ok\n", pid ); + + /* + * 5. Handshake + */ + mbedtls_printf( "pid %d: Performing the SSL/TLS handshake.\n", pid ); + fflush( stdout ); + + while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + mbedtls_printf( + "pid %d: SSL handshake failed! mbedtls_ssl_handshake returned %d\n\n", + pid, ret ); + goto exit; + } + } + + mbedtls_printf( "pid %d: SSL handshake ok\n", pid ); + + /* + * 6. Read the HTTP Request + */ + mbedtls_printf( "pid %d: Start reading from client.\n", pid ); + fflush( stdout ); + + do + { + len = sizeof( buf ) - 1; + memset( buf, 0, sizeof( buf ) ); + ret = mbedtls_ssl_read( &ssl, buf, len ); + + if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) + continue; + + if( ret <= 0 ) + { + switch( ret ) + { + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf( "pid %d: connection was closed gracefully\n", pid ); + break; + + case MBEDTLS_ERR_NET_CONN_RESET: + mbedtls_printf( "pid %d: connection was reset by peer\n", pid ); + break; + + default: + mbedtls_printf( "pid %d: mbedtls_ssl_read returned %d\n", pid, ret ); + break; + } + + break; + } + + len = ret; + mbedtls_printf( "pid %d: %d bytes read\n\n%s", pid, len, (char *) buf ); + + if( ret > 0 ) + break; + } + while( 1 ); + + /* + * 7. Write the 200 Response + */ + mbedtls_printf( "pid %d: Start writing to client.\n", pid ); + fflush( stdout ); + + len = sprintf( (char *) buf, HTTP_RESPONSE, + mbedtls_ssl_get_ciphersuite( &ssl ) ); + + while( cnt++ < 100 ) + { + while( ( ret = mbedtls_ssl_write( &ssl, buf, len ) ) <= 0 ) + { + if( ret == MBEDTLS_ERR_NET_CONN_RESET ) + { + mbedtls_printf( + "pid %d: Write failed! peer closed the connection\n\n", pid ); + goto exit; + } + + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + mbedtls_printf( + "pid %d: Write failed! mbedtls_ssl_write returned %d\n\n", + pid, ret ); + goto exit; + } + } + len = ret; + mbedtls_printf( "pid %d: %d bytes written\n\n%s\n", pid, len, (char *) buf ); + + mbedtls_net_usleep( 1000000 ); + } + + mbedtls_ssl_close_notify( &ssl ); + goto exit; + } + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + mbedtls_net_free( &client_fd ); + mbedtls_net_free( &listen_fd ); + + mbedtls_x509_crt_free( &srvcert ); + mbedtls_pk_free( &pkey ); + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_CERTS_C && MBEDTLS_ENTROPY_C && + MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C && + MBEDTLS_RSA_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_PEM_PARSE_C && + ! _WIN32 */ diff --git a/external/mbedtls/programs/ssl/ssl_mail_client.c b/external/mbedtls/programs/ssl/ssl_mail_client.c new file mode 100644 index 0000000..d0e65e1 --- /dev/null +++ b/external/mbedtls/programs/ssl/ssl_mail_client.c @@ -0,0 +1,889 @@ +/* + * SSL client for SMTP servers + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* Enable definition of gethostname() even when compiling with -std=c99. Must + * be set before config.h, which pulls in glibc's features.h indirectly. + * Harmless on other platforms. */ +#define _POSIX_C_SOURCE 200112L + +#if defined(__NetBSD__) +#define _XOPEN_SOURCE 600 +#endif + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_time time +#define mbedtls_time_t time_t +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \ + !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or " + "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C " + "not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/base64.h" +#include "mbedtls/error.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/x509.h" + +#include +#include + +#if !defined(_MSC_VER) || defined(EFIX64) || defined(EFI32) +#include +#else +#include +#endif + +#if defined(_WIN32) || defined(_WIN32_WCE) +#include +#include + +#if defined(_MSC_VER) +#if defined(_WIN32_WCE) +#pragma comment( lib, "ws2.lib" ) +#else +#pragma comment( lib, "ws2_32.lib" ) +#endif +#endif /* _MSC_VER */ +#endif + +#define DFL_SERVER_NAME "localhost" +#define DFL_SERVER_PORT "465" +#define DFL_USER_NAME "user" +#define DFL_USER_PWD "password" +#define DFL_MAIL_FROM "" +#define DFL_MAIL_TO "" +#define DFL_DEBUG_LEVEL 0 +#define DFL_CA_FILE "" +#define DFL_CRT_FILE "" +#define DFL_KEY_FILE "" +#define DFL_FORCE_CIPHER 0 +#define DFL_MODE 0 +#define DFL_AUTHENTICATION 0 + +#define MODE_SSL_TLS 0 +#define MODE_STARTTLS 0 + +#if defined(MBEDTLS_BASE64_C) +#define USAGE_AUTH \ + " authentication=%%d default: 0 (disabled)\n" \ + " user_name=%%s default: \"" DFL_USER_NAME "\"\n" \ + " user_pwd=%%s default: \"" DFL_USER_PWD "\"\n" +#else +#define USAGE_AUTH \ + " authentication options disabled. (Require MBEDTLS_BASE64_C)\n" +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_FS_IO) +#define USAGE_IO \ + " ca_file=%%s default: \"\" (pre-loaded)\n" \ + " crt_file=%%s default: \"\" (pre-loaded)\n" \ + " key_file=%%s default: \"\" (pre-loaded)\n" +#else +#define USAGE_IO \ + " No file operations available (MBEDTLS_FS_IO not defined)\n" +#endif /* MBEDTLS_FS_IO */ + +#define USAGE \ + "\n usage: ssl_mail_client param=<>...\n" \ + "\n acceptable parameters:\n" \ + " server_name=%%s default: " DFL_SERVER_NAME "\n" \ + " server_port=%%d default: " DFL_SERVER_PORT "\n" \ + " debug_level=%%d default: 0 (disabled)\n" \ + " mode=%%d default: 0 (SSL/TLS) (1 for STARTTLS)\n" \ + USAGE_AUTH \ + " mail_from=%%s default: \"\"\n" \ + " mail_to=%%s default: \"\"\n" \ + USAGE_IO \ + " force_ciphersuite= default: all enabled\n" \ + " acceptable ciphersuite names:\n" + + +/* + * global options + */ +struct options +{ + const char *server_name; /* hostname of the server (client only) */ + const char *server_port; /* port on which the ssl service runs */ + int debug_level; /* level of debugging */ + int authentication; /* if authentication is required */ + int mode; /* SSL/TLS (0) or STARTTLS (1) */ + const char *user_name; /* username to use for authentication */ + const char *user_pwd; /* password to use for authentication */ + const char *mail_from; /* E-Mail address to use as sender */ + const char *mail_to; /* E-Mail address to use as recipient */ + const char *ca_file; /* the file with the CA certificate(s) */ + const char *crt_file; /* the file with the client certificate */ + const char *key_file; /* the file with the client key */ + int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */ +} opt; + +static void my_debug( void *ctx, int level, + const char *file, int line, + const char *str ) +{ + ((void) level); + + mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str ); + fflush( (FILE *) ctx ); +} + +static int do_handshake( mbedtls_ssl_context *ssl ) +{ + int ret; + uint32_t flags; + unsigned char buf[1024]; + memset(buf, 0, 1024); + + /* + * 4. Handshake + */ + mbedtls_printf( " . Performing the SSL/TLS handshake..." ); + fflush( stdout ); + + while( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { +#if defined(MBEDTLS_ERROR_C) + mbedtls_strerror( ret, (char *) buf, 1024 ); +#endif + mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d: %s\n\n", ret, buf ); + return( -1 ); + } + } + + mbedtls_printf( " ok\n [ Ciphersuite is %s ]\n", + mbedtls_ssl_get_ciphersuite( ssl ) ); + + /* + * 5. Verify the server certificate + */ + mbedtls_printf( " . Verifying peer X.509 certificate..." ); + + /* In real life, we probably want to bail out when ret != 0 */ + if( ( flags = mbedtls_ssl_get_verify_result( ssl ) ) != 0 ) + { + char vrfy_buf[512]; + + mbedtls_printf( " failed\n" ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + + mbedtls_printf( "%s\n", vrfy_buf ); + } + else + mbedtls_printf( " ok\n" ); + + mbedtls_printf( " . Peer certificate information ...\n" ); + mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ", + mbedtls_ssl_get_peer_cert( ssl ) ); + mbedtls_printf( "%s\n", buf ); + + return( 0 ); +} + +static int write_ssl_data( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) +{ + int ret; + + mbedtls_printf("\n%s", buf); + while( len && ( ret = mbedtls_ssl_write( ssl, buf, len ) ) <= 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); + return -1; + } + } + + return( 0 ); +} + +static int write_ssl_and_get_response( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) +{ + int ret; + unsigned char data[128]; + char code[4]; + size_t i, idx = 0; + + mbedtls_printf("\n%s", buf); + while( len && ( ret = mbedtls_ssl_write( ssl, buf, len ) ) <= 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); + return -1; + } + } + + do + { + len = sizeof( data ) - 1; + memset( data, 0, sizeof( data ) ); + ret = mbedtls_ssl_read( ssl, data, len ); + + if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) + continue; + + if( ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ) + return -1; + + if( ret <= 0 ) + { + mbedtls_printf( "failed\n ! mbedtls_ssl_read returned %d\n\n", ret ); + return -1; + } + + mbedtls_printf("\n%s", data); + len = ret; + for( i = 0; i < len; i++ ) + { + if( data[i] != '\n' ) + { + if( idx < 4 ) + code[ idx++ ] = data[i]; + continue; + } + + if( idx == 4 && code[0] >= '0' && code[0] <= '9' && code[3] == ' ' ) + { + code[3] = '\0'; + return atoi( code ); + } + + idx = 0; + } + } + while( 1 ); +} + +static int write_and_get_response( mbedtls_net_context *sock_fd, unsigned char *buf, size_t len ) +{ + int ret; + unsigned char data[128]; + char code[4]; + size_t i, idx = 0; + + mbedtls_printf("\n%s", buf); + if( len && ( ret = mbedtls_net_send( sock_fd, buf, len ) ) <= 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_send returned %d\n\n", ret ); + return -1; + } + + do + { + len = sizeof( data ) - 1; + memset( data, 0, sizeof( data ) ); + ret = mbedtls_net_recv( sock_fd, data, len ); + + if( ret <= 0 ) + { + mbedtls_printf( "failed\n ! mbedtls_net_recv returned %d\n\n", ret ); + return -1; + } + + data[len] = '\0'; + mbedtls_printf("\n%s", data); + len = ret; + for( i = 0; i < len; i++ ) + { + if( data[i] != '\n' ) + { + if( idx < 4 ) + code[ idx++ ] = data[i]; + continue; + } + + if( idx == 4 && code[0] >= '0' && code[0] <= '9' && code[3] == ' ' ) + { + code[3] = '\0'; + return atoi( code ); + } + + idx = 0; + } + } + while( 1 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 1, len; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_net_context server_fd; +#if defined(MBEDTLS_BASE64_C) + unsigned char base[1024]; + /* buf is used as the destination buffer for printing base with the format: + * "%s\r\n". Hence, the size of buf should be at least the size of base + * plus 2 bytes for the \r and \n characters. + */ + unsigned char buf[sizeof( base ) + 2]; +#else + unsigned char buf[1024]; +#endif + char hostname[32]; + const char *pers = "ssl_mail_client"; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_x509_crt cacert; + mbedtls_x509_crt clicert; + mbedtls_pk_context pkey; + int i; + size_t n; + char *p, *q; + const int *list; + + /* + * Make sure memory references are valid in case we exit early. + */ + mbedtls_net_init( &server_fd ); + mbedtls_ssl_init( &ssl ); + mbedtls_ssl_config_init( &conf ); + memset( &buf, 0, sizeof( buf ) ); + mbedtls_x509_crt_init( &cacert ); + mbedtls_x509_crt_init( &clicert ); + mbedtls_pk_init( &pkey ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + + list = mbedtls_ssl_list_ciphersuites(); + while( *list ) + { + mbedtls_printf(" %s\n", mbedtls_ssl_get_ciphersuite_name( *list ) ); + list++; + } + mbedtls_printf("\n"); + goto exit; + } + + opt.server_name = DFL_SERVER_NAME; + opt.server_port = DFL_SERVER_PORT; + opt.debug_level = DFL_DEBUG_LEVEL; + opt.authentication = DFL_AUTHENTICATION; + opt.mode = DFL_MODE; + opt.user_name = DFL_USER_NAME; + opt.user_pwd = DFL_USER_PWD; + opt.mail_from = DFL_MAIL_FROM; + opt.mail_to = DFL_MAIL_TO; + opt.ca_file = DFL_CA_FILE; + opt.crt_file = DFL_CRT_FILE; + opt.key_file = DFL_KEY_FILE; + opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "server_name" ) == 0 ) + opt.server_name = q; + else if( strcmp( p, "server_port" ) == 0 ) + opt.server_port = q; + else if( strcmp( p, "debug_level" ) == 0 ) + { + opt.debug_level = atoi( q ); + if( opt.debug_level < 0 || opt.debug_level > 65535 ) + goto usage; + } + else if( strcmp( p, "authentication" ) == 0 ) + { + opt.authentication = atoi( q ); + if( opt.authentication < 0 || opt.authentication > 1 ) + goto usage; + } + else if( strcmp( p, "mode" ) == 0 ) + { + opt.mode = atoi( q ); + if( opt.mode < 0 || opt.mode > 1 ) + goto usage; + } + else if( strcmp( p, "user_name" ) == 0 ) + opt.user_name = q; + else if( strcmp( p, "user_pwd" ) == 0 ) + opt.user_pwd = q; + else if( strcmp( p, "mail_from" ) == 0 ) + opt.mail_from = q; + else if( strcmp( p, "mail_to" ) == 0 ) + opt.mail_to = q; + else if( strcmp( p, "ca_file" ) == 0 ) + opt.ca_file = q; + else if( strcmp( p, "crt_file" ) == 0 ) + opt.crt_file = q; + else if( strcmp( p, "key_file" ) == 0 ) + opt.key_file = q; + else if( strcmp( p, "force_ciphersuite" ) == 0 ) + { + opt.force_ciphersuite[0] = -1; + + opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q ); + + if( opt.force_ciphersuite[0] <= 0 ) + goto usage; + + opt.force_ciphersuite[1] = 0; + } + else + goto usage; + } + + /* + * 0. Initialize the RNG and the session data + */ + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + mbedtls_entropy_init( &entropy ); + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.1. Load the trusted CA + */ + mbedtls_printf( " . Loading the CA root certificate ..." ); + fflush( stdout ); + +#if defined(MBEDTLS_FS_IO) + if( strlen( opt.ca_file ) ) + ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file ); + else +#endif +#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_PEM_PARSE_C) + ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem, + mbedtls_test_cas_pem_len ); +#else + { + mbedtls_printf("MBEDTLS_CERTS_C and/or MBEDTLS_PEM_PARSE_C not defined."); + goto exit; + } +#endif + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok (%d skipped)\n", ret ); + + /* + * 1.2. Load own certificate and private key + * + * (can be skipped if client authentication is not required) + */ + mbedtls_printf( " . Loading the client cert. and key..." ); + fflush( stdout ); + +#if defined(MBEDTLS_FS_IO) + if( strlen( opt.crt_file ) ) + ret = mbedtls_x509_crt_parse_file( &clicert, opt.crt_file ); + else +#endif +#if defined(MBEDTLS_CERTS_C) + ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, + mbedtls_test_cli_crt_len ); +#else + { + mbedtls_printf("MBEDTLS_CERTS_C not defined."); + goto exit; + } +#endif + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); + goto exit; + } + +#if defined(MBEDTLS_FS_IO) + if( strlen( opt.key_file ) ) + ret = mbedtls_pk_parse_keyfile( &pkey, opt.key_file, "" ); + else +#endif +#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_PEM_PARSE_C) + ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_cli_key, + mbedtls_test_cli_key_len, NULL, 0 ); +#else + { + mbedtls_printf("MBEDTLS_CERTS_C or MBEDTLS_PEM_PARSE_C not defined."); + goto exit; + } +#endif + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 2. Start the connection + */ + mbedtls_printf( " . Connecting to tcp/%s/%s...", opt.server_name, + opt.server_port ); + fflush( stdout ); + + if( ( ret = mbedtls_net_connect( &server_fd, opt.server_name, + opt.server_port, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 3. Setup stuff + */ + mbedtls_printf( " . Setting up the SSL/TLS structure..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ssl_config_defaults( &conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); + goto exit; + } + + /* OPTIONAL is not optimal for security, + * but makes interop easier in this simplified example */ + mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); + + mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); + mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); + + if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER ) + mbedtls_ssl_conf_ciphersuites( &conf, opt.force_ciphersuite ); + + mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); + if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &clicert, &pkey ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); + goto exit; + } + + if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); + goto exit; + } + + if( ( ret = mbedtls_ssl_set_hostname( &ssl, opt.server_name ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); + goto exit; + } + + mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); + + mbedtls_printf( " ok\n" ); + + if( opt.mode == MODE_SSL_TLS ) + { + if( do_handshake( &ssl ) != 0 ) + goto exit; + + mbedtls_printf( " > Get header from server:" ); + fflush( stdout ); + + ret = write_ssl_and_get_response( &ssl, buf, 0 ); + if( ret < 200 || ret > 299 ) + { + mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); + goto exit; + } + + mbedtls_printf(" ok\n" ); + + mbedtls_printf( " > Write EHLO to server:" ); + fflush( stdout ); + + gethostname( hostname, 32 ); + len = sprintf( (char *) buf, "EHLO %s\r\n", hostname ); + ret = write_ssl_and_get_response( &ssl, buf, len ); + if( ret < 200 || ret > 299 ) + { + mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); + goto exit; + } + } + else + { + mbedtls_printf( " > Get header from server:" ); + fflush( stdout ); + + ret = write_and_get_response( &server_fd, buf, 0 ); + if( ret < 200 || ret > 299 ) + { + mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); + goto exit; + } + + mbedtls_printf(" ok\n" ); + + mbedtls_printf( " > Write EHLO to server:" ); + fflush( stdout ); + + gethostname( hostname, 32 ); + len = sprintf( (char *) buf, "EHLO %s\r\n", hostname ); + ret = write_and_get_response( &server_fd, buf, len ); + if( ret < 200 || ret > 299 ) + { + mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); + goto exit; + } + + mbedtls_printf(" ok\n" ); + + mbedtls_printf( " > Write STARTTLS to server:" ); + fflush( stdout ); + + gethostname( hostname, 32 ); + len = sprintf( (char *) buf, "STARTTLS\r\n" ); + ret = write_and_get_response( &server_fd, buf, len ); + if( ret < 200 || ret > 299 ) + { + mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); + goto exit; + } + + mbedtls_printf(" ok\n" ); + + if( do_handshake( &ssl ) != 0 ) + goto exit; + } + +#if defined(MBEDTLS_BASE64_C) + if( opt.authentication ) + { + mbedtls_printf( " > Write AUTH LOGIN to server:" ); + fflush( stdout ); + + len = sprintf( (char *) buf, "AUTH LOGIN\r\n" ); + ret = write_ssl_and_get_response( &ssl, buf, len ); + if( ret < 200 || ret > 399 ) + { + mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); + goto exit; + } + + mbedtls_printf(" ok\n" ); + + mbedtls_printf( " > Write username to server: %s", opt.user_name ); + fflush( stdout ); + + ret = mbedtls_base64_encode( base, sizeof( base ), &n, (const unsigned char *) opt.user_name, + strlen( opt.user_name ) ); + + if( ret != 0 ) { + mbedtls_printf( " failed\n ! mbedtls_base64_encode returned %d\n\n", ret ); + goto exit; + } + len = sprintf( (char *) buf, "%s\r\n", base ); + ret = write_ssl_and_get_response( &ssl, buf, len ); + if( ret < 300 || ret > 399 ) + { + mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); + goto exit; + } + + mbedtls_printf(" ok\n" ); + + mbedtls_printf( " > Write password to server: %s", opt.user_pwd ); + fflush( stdout ); + + ret = mbedtls_base64_encode( base, sizeof( base ), &n, (const unsigned char *) opt.user_pwd, + strlen( opt.user_pwd ) ); + + if( ret != 0 ) { + mbedtls_printf( " failed\n ! mbedtls_base64_encode returned %d\n\n", ret ); + goto exit; + } + len = sprintf( (char *) buf, "%s\r\n", base ); + ret = write_ssl_and_get_response( &ssl, buf, len ); + if( ret < 200 || ret > 399 ) + { + mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); + goto exit; + } + + mbedtls_printf(" ok\n" ); + } +#endif + + mbedtls_printf( " > Write MAIL FROM to server:" ); + fflush( stdout ); + + len = sprintf( (char *) buf, "MAIL FROM:<%s>\r\n", opt.mail_from ); + ret = write_ssl_and_get_response( &ssl, buf, len ); + if( ret < 200 || ret > 299 ) + { + mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); + goto exit; + } + + mbedtls_printf(" ok\n" ); + + mbedtls_printf( " > Write RCPT TO to server:" ); + fflush( stdout ); + + len = sprintf( (char *) buf, "RCPT TO:<%s>\r\n", opt.mail_to ); + ret = write_ssl_and_get_response( &ssl, buf, len ); + if( ret < 200 || ret > 299 ) + { + mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); + goto exit; + } + + mbedtls_printf(" ok\n" ); + + mbedtls_printf( " > Write DATA to server:" ); + fflush( stdout ); + + len = sprintf( (char *) buf, "DATA\r\n" ); + ret = write_ssl_and_get_response( &ssl, buf, len ); + if( ret < 300 || ret > 399 ) + { + mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); + goto exit; + } + + mbedtls_printf(" ok\n" ); + + mbedtls_printf( " > Write content to server:" ); + fflush( stdout ); + + len = sprintf( (char *) buf, "From: %s\r\nSubject: mbed TLS Test mail\r\n\r\n" + "This is a simple test mail from the " + "mbed TLS mail client example.\r\n" + "\r\n" + "Enjoy!", opt.mail_from ); + ret = write_ssl_data( &ssl, buf, len ); + + len = sprintf( (char *) buf, "\r\n.\r\n"); + ret = write_ssl_and_get_response( &ssl, buf, len ); + if( ret < 200 || ret > 299 ) + { + mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); + goto exit; + } + + mbedtls_printf(" ok\n" ); + + mbedtls_ssl_close_notify( &ssl ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + mbedtls_net_free( &server_fd ); + mbedtls_x509_crt_free( &clicert ); + mbedtls_x509_crt_free( &cacert ); + mbedtls_pk_free( &pkey ); + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C && + MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C ** + MBEDTLS_CTR_DRBG_C */ diff --git a/external/mbedtls/programs/ssl/ssl_pthread_server.c b/external/mbedtls/programs/ssl/ssl_pthread_server.c new file mode 100644 index 0000000..5e8737a --- /dev/null +++ b/external/mbedtls/programs/ssl/ssl_pthread_server.c @@ -0,0 +1,558 @@ +/* + * SSL server demonstration program using pthread for handling multiple + * clients. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_snprintf snprintf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_CERTS_C) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_SSL_TLS_C) || \ + !defined(MBEDTLS_SSL_SRV_C) || !defined(MBEDTLS_NET_C) || \ + !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_CTR_DRBG_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) || \ + !defined(MBEDTLS_THREADING_C) || !defined(MBEDTLS_THREADING_PTHREAD) || \ + !defined(MBEDTLS_PEM_PARSE_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_CERTS_C and/or MBEDTLS_ENTROPY_C " + "and/or MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_SRV_C and/or " + "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C and/or " + "MBEDTLS_THREADING_C and/or MBEDTLS_THREADING_PTHREAD " + "and/or MBEDTLS_PEM_PARSE_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include +#include + +#if defined(_WIN32) +#include +#endif + +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/x509.h" +#include "mbedtls/ssl.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_SSL_CACHE_C) +#include "mbedtls/ssl_cache.h" +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" +#endif + + +#define HTTP_RESPONSE \ + "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ + "

mbed TLS Test Server

\r\n" \ + "

Successful connection using: %s

\r\n" + +#define DEBUG_LEVEL 0 + +#define MAX_NUM_THREADS 5 + +mbedtls_threading_mutex_t debug_mutex; + +static void my_mutexed_debug( void *ctx, int level, + const char *file, int line, + const char *str ) +{ + long int thread_id = (long int) pthread_self(); + + mbedtls_mutex_lock( &debug_mutex ); + + ((void) level); + mbedtls_fprintf( (FILE *) ctx, "%s:%04d: [ #%ld ] %s", + file, line, thread_id, str ); + fflush( (FILE *) ctx ); + + mbedtls_mutex_unlock( &debug_mutex ); +} + +typedef struct { + mbedtls_net_context client_fd; + int thread_complete; + const mbedtls_ssl_config *config; +} thread_info_t; + +typedef struct { + int active; + thread_info_t data; + pthread_t thread; +} pthread_info_t; + +static thread_info_t base_info; +static pthread_info_t threads[MAX_NUM_THREADS]; + +static void *handle_ssl_connection( void *data ) +{ + int ret, len; + thread_info_t *thread_info = (thread_info_t *) data; + mbedtls_net_context *client_fd = &thread_info->client_fd; + long int thread_id = (long int) pthread_self(); + unsigned char buf[1024]; + mbedtls_ssl_context ssl; + + /* Make sure memory references are valid */ + mbedtls_ssl_init( &ssl ); + + mbedtls_printf( " [ #%ld ] Setting up SSL/TLS data\n", thread_id ); + + /* + * 4. Get the SSL context ready + */ + if( ( ret = mbedtls_ssl_setup( &ssl, thread_info->config ) ) != 0 ) + { + mbedtls_printf( " [ #%ld ] failed: mbedtls_ssl_setup returned -0x%04x\n", + thread_id, -ret ); + goto thread_exit; + } + + mbedtls_ssl_set_bio( &ssl, client_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); + + /* + * 5. Handshake + */ + mbedtls_printf( " [ #%ld ] Performing the SSL/TLS handshake\n", thread_id ); + + while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + mbedtls_printf( " [ #%ld ] failed: mbedtls_ssl_handshake returned -0x%04x\n", + thread_id, -ret ); + goto thread_exit; + } + } + + mbedtls_printf( " [ #%ld ] ok\n", thread_id ); + + /* + * 6. Read the HTTP Request + */ + mbedtls_printf( " [ #%ld ] < Read from client\n", thread_id ); + + do + { + len = sizeof( buf ) - 1; + memset( buf, 0, sizeof( buf ) ); + ret = mbedtls_ssl_read( &ssl, buf, len ); + + if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) + continue; + + if( ret <= 0 ) + { + switch( ret ) + { + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf( " [ #%ld ] connection was closed gracefully\n", + thread_id ); + goto thread_exit; + + case MBEDTLS_ERR_NET_CONN_RESET: + mbedtls_printf( " [ #%ld ] connection was reset by peer\n", + thread_id ); + goto thread_exit; + + default: + mbedtls_printf( " [ #%ld ] mbedtls_ssl_read returned -0x%04x\n", + thread_id, -ret ); + goto thread_exit; + } + } + + len = ret; + mbedtls_printf( " [ #%ld ] %d bytes read\n=====\n%s\n=====\n", + thread_id, len, (char *) buf ); + + if( ret > 0 ) + break; + } + while( 1 ); + + /* + * 7. Write the 200 Response + */ + mbedtls_printf( " [ #%ld ] > Write to client:\n", thread_id ); + + len = sprintf( (char *) buf, HTTP_RESPONSE, + mbedtls_ssl_get_ciphersuite( &ssl ) ); + + while( ( ret = mbedtls_ssl_write( &ssl, buf, len ) ) <= 0 ) + { + if( ret == MBEDTLS_ERR_NET_CONN_RESET ) + { + mbedtls_printf( " [ #%ld ] failed: peer closed the connection\n", + thread_id ); + goto thread_exit; + } + + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + mbedtls_printf( " [ #%ld ] failed: mbedtls_ssl_write returned -0x%04x\n", + thread_id, ret ); + goto thread_exit; + } + } + + len = ret; + mbedtls_printf( " [ #%ld ] %d bytes written\n=====\n%s\n=====\n", + thread_id, len, (char *) buf ); + + mbedtls_printf( " [ #%ld ] . Closing the connection...", thread_id ); + + while( ( ret = mbedtls_ssl_close_notify( &ssl ) ) < 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + mbedtls_printf( " [ #%ld ] failed: mbedtls_ssl_close_notify returned -0x%04x\n", + thread_id, ret ); + goto thread_exit; + } + } + + mbedtls_printf( " ok\n" ); + + ret = 0; + +thread_exit: + +#ifdef MBEDTLS_ERROR_C + if( ret != 0 ) + { + char error_buf[100]; + mbedtls_strerror( ret, error_buf, 100 ); + mbedtls_printf(" [ #%ld ] Last error was: -0x%04x - %s\n\n", + thread_id, -ret, error_buf ); + } +#endif + + mbedtls_net_free( client_fd ); + mbedtls_ssl_free( &ssl ); + + thread_info->thread_complete = 1; + + return( NULL ); +} + +static int thread_create( mbedtls_net_context *client_fd ) +{ + int ret, i; + + /* + * Find in-active or finished thread slot + */ + for( i = 0; i < MAX_NUM_THREADS; i++ ) + { + if( threads[i].active == 0 ) + break; + + if( threads[i].data.thread_complete == 1 ) + { + mbedtls_printf( " [ main ] Cleaning up thread %d\n", i ); + pthread_join(threads[i].thread, NULL ); + memset( &threads[i], 0, sizeof(pthread_info_t) ); + break; + } + } + + if( i == MAX_NUM_THREADS ) + return( -1 ); + + /* + * Fill thread-info for thread + */ + memcpy( &threads[i].data, &base_info, sizeof(base_info) ); + threads[i].active = 1; + memcpy( &threads[i].data.client_fd, client_fd, sizeof( mbedtls_net_context ) ); + + if( ( ret = pthread_create( &threads[i].thread, NULL, handle_ssl_connection, + &threads[i].data ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int main( void ) +{ + int ret; + mbedtls_net_context listen_fd, client_fd; + const char pers[] = "ssl_pthread_server"; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_config conf; + mbedtls_x509_crt srvcert; + mbedtls_x509_crt cachain; + mbedtls_pk_context pkey; +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + unsigned char alloc_buf[100000]; +#endif +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_context cache; +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) ); +#endif + +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_init( &cache ); +#endif + + mbedtls_x509_crt_init( &srvcert ); + mbedtls_x509_crt_init( &cachain ); + + mbedtls_ssl_config_init( &conf ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + memset( threads, 0, sizeof(threads) ); + mbedtls_net_init( &listen_fd ); + mbedtls_net_init( &client_fd ); + + mbedtls_mutex_init( &debug_mutex ); + + base_info.config = &conf; + + /* + * We use only a single entropy source that is used in all the threads. + */ + mbedtls_entropy_init( &entropy ); + + /* + * 1. Load the certificates and private RSA key + */ + mbedtls_printf( "\n . Loading the server cert. and key..." ); + fflush( stdout ); + + /* + * This demonstration program uses embedded test certificates. + * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the + * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). + */ + ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, + mbedtls_test_srv_crt_len ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); + goto exit; + } + + ret = mbedtls_x509_crt_parse( &cachain, (const unsigned char *) mbedtls_test_cas_pem, + mbedtls_test_cas_pem_len ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); + goto exit; + } + + mbedtls_pk_init( &pkey ); + ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, + mbedtls_test_srv_key_len, NULL, 0 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1b. Seed the random number generator + */ + mbedtls_printf( " . Seeding the random number generator..." ); + + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed: mbedtls_ctr_drbg_seed returned -0x%04x\n", + -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1c. Prepare SSL configuration + */ + mbedtls_printf( " . Setting up the SSL data...." ); + + if( ( ret = mbedtls_ssl_config_defaults( &conf, + MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) + { + mbedtls_printf( " failed: mbedtls_ssl_config_defaults returned -0x%04x\n", + -ret ); + goto exit; + } + + mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); + mbedtls_ssl_conf_dbg( &conf, my_mutexed_debug, stdout ); + + /* mbedtls_ssl_cache_get() and mbedtls_ssl_cache_set() are thread-safe if + * MBEDTLS_THREADING_C is set. + */ +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_conf_session_cache( &conf, &cache, + mbedtls_ssl_cache_get, + mbedtls_ssl_cache_set ); +#endif + + mbedtls_ssl_conf_ca_chain( &conf, &cachain, NULL ); + if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 2. Setup the listening TCP socket + */ + mbedtls_printf( " . Bind on https://localhost:4433/ ..." ); + fflush( stdout ); + + if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + +reset: +#ifdef MBEDTLS_ERROR_C + if( ret != 0 ) + { + char error_buf[100]; + mbedtls_strerror( ret, error_buf, 100 ); + mbedtls_printf( " [ main ] Last error was: -0x%04x - %s\n", -ret, error_buf ); + } +#endif + + /* + * 3. Wait until a client connects + */ + mbedtls_printf( " [ main ] Waiting for a remote connection\n" ); + + if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, + NULL, 0, NULL ) ) != 0 ) + { + mbedtls_printf( " [ main ] failed: mbedtls_net_accept returned -0x%04x\n", ret ); + goto exit; + } + + mbedtls_printf( " [ main ] ok\n" ); + mbedtls_printf( " [ main ] Creating a new thread\n" ); + + if( ( ret = thread_create( &client_fd ) ) != 0 ) + { + mbedtls_printf( " [ main ] failed: thread_create returned %d\n", ret ); + mbedtls_net_free( &client_fd ); + goto reset; + } + + ret = 0; + goto reset; + +exit: + mbedtls_x509_crt_free( &srvcert ); + mbedtls_pk_free( &pkey ); +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_free( &cache ); +#endif + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + mbedtls_ssl_config_free( &conf ); + + mbedtls_net_free( &listen_fd ); + + mbedtls_mutex_free( &debug_mutex ); + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + mbedtls_memory_buffer_alloc_free(); +#endif + +#if defined(_WIN32) + mbedtls_printf( " Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( ret ); +} + +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_CERTS_C && MBEDTLS_ENTROPY_C && + MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C && + MBEDTLS_RSA_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_THREADING_C && + MBEDTLS_THREADING_PTHREAD && MBEDTLS_PEM_PARSE_C */ diff --git a/external/mbedtls/programs/ssl/ssl_server.c b/external/mbedtls/programs/ssl/ssl_server.c new file mode 100644 index 0000000..242680e --- /dev/null +++ b/external/mbedtls/programs/ssl/ssl_server.c @@ -0,0 +1,430 @@ +/* + * SSL server demonstration program + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_time time +#define mbedtls_time_t time_t +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_CERTS_C) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_SSL_TLS_C) || \ + !defined(MBEDTLS_SSL_SRV_C) || !defined(MBEDTLS_NET_C) || \ + !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_CTR_DRBG_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) || \ + !defined(MBEDTLS_PEM_PARSE_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_CERTS_C and/or MBEDTLS_ENTROPY_C " + "and/or MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_SRV_C and/or " + "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C " + "and/or MBEDTLS_PEM_PARSE_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include +#include + +#if defined(_WIN32) +#include +#endif + +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/x509.h" +#include "mbedtls/ssl.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/error.h" +#include "mbedtls/debug.h" + +#if defined(MBEDTLS_SSL_CACHE_C) +#include "mbedtls/ssl_cache.h" +#endif + +#define HTTP_RESPONSE \ + "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ + "

mbed TLS Test Server

\r\n" \ + "

Successful connection using: %s

\r\n" + +#define DEBUG_LEVEL 0 + + +static void my_debug( void *ctx, int level, + const char *file, int line, + const char *str ) +{ + ((void) level); + + mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str ); + fflush( (FILE *) ctx ); +} + +int main( void ) +{ + int ret, len; + mbedtls_net_context listen_fd, client_fd; + unsigned char buf[1024]; + const char *pers = "ssl_server"; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_x509_crt srvcert; + mbedtls_pk_context pkey; +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_context cache; +#endif + + mbedtls_net_init( &listen_fd ); + mbedtls_net_init( &client_fd ); + mbedtls_ssl_init( &ssl ); + mbedtls_ssl_config_init( &conf ); +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_init( &cache ); +#endif + mbedtls_x509_crt_init( &srvcert ); + mbedtls_pk_init( &pkey ); + mbedtls_entropy_init( &entropy ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold( DEBUG_LEVEL ); +#endif + + /* + * 1. Load the certificates and private RSA key + */ + mbedtls_printf( "\n . Loading the server cert. and key..." ); + fflush( stdout ); + + /* + * This demonstration program uses embedded test certificates. + * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the + * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). + */ + ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, + mbedtls_test_srv_crt_len ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); + goto exit; + } + + ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem, + mbedtls_test_cas_pem_len ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); + goto exit; + } + + ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, + mbedtls_test_srv_key_len, NULL, 0 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 2. Setup the listening TCP socket + */ + mbedtls_printf( " . Bind on https://localhost:4433/ ..." ); + fflush( stdout ); + + if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 3. Seed the RNG + */ + mbedtls_printf( " . Seeding the random number generator..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 4. Setup stuff + */ + mbedtls_printf( " . Setting up the SSL data...." ); + fflush( stdout ); + + if( ( ret = mbedtls_ssl_config_defaults( &conf, + MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); + goto exit; + } + + mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); + mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); + +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_conf_session_cache( &conf, &cache, + mbedtls_ssl_cache_get, + mbedtls_ssl_cache_set ); +#endif + + mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL ); + if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); + goto exit; + } + + if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + +reset: +#ifdef MBEDTLS_ERROR_C + if( ret != 0 ) + { + char error_buf[100]; + mbedtls_strerror( ret, error_buf, 100 ); + mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf ); + } +#endif + + mbedtls_net_free( &client_fd ); + + mbedtls_ssl_session_reset( &ssl ); + + /* + * 3. Wait until a client connects + */ + mbedtls_printf( " . Waiting for a remote connection ..." ); + fflush( stdout ); + + if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, + NULL, 0, NULL ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret ); + goto exit; + } + + mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); + + mbedtls_printf( " ok\n" ); + + /* + * 5. Handshake + */ + mbedtls_printf( " . Performing the SSL/TLS handshake..." ); + fflush( stdout ); + + while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d\n\n", ret ); + goto reset; + } + } + + mbedtls_printf( " ok\n" ); + + /* + * 6. Read the HTTP Request + */ + mbedtls_printf( " < Read from client:" ); + fflush( stdout ); + + do + { + len = sizeof( buf ) - 1; + memset( buf, 0, sizeof( buf ) ); + ret = mbedtls_ssl_read( &ssl, buf, len ); + + if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) + continue; + + if( ret <= 0 ) + { + switch( ret ) + { + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf( " connection was closed gracefully\n" ); + break; + + case MBEDTLS_ERR_NET_CONN_RESET: + mbedtls_printf( " connection was reset by peer\n" ); + break; + + default: + mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", -ret ); + break; + } + + break; + } + + len = ret; + mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); + + if( ret > 0 ) + break; + } + while( 1 ); + + /* + * 7. Write the 200 Response + */ + mbedtls_printf( " > Write to client:" ); + fflush( stdout ); + + len = sprintf( (char *) buf, HTTP_RESPONSE, + mbedtls_ssl_get_ciphersuite( &ssl ) ); + + while( ( ret = mbedtls_ssl_write( &ssl, buf, len ) ) <= 0 ) + { + if( ret == MBEDTLS_ERR_NET_CONN_RESET ) + { + mbedtls_printf( " failed\n ! peer closed the connection\n\n" ); + goto reset; + } + + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); + goto exit; + } + } + + len = ret; + mbedtls_printf( " %d bytes written\n\n%s\n", len, (char *) buf ); + + mbedtls_printf( " . Closing the connection..." ); + + while( ( ret = mbedtls_ssl_close_notify( &ssl ) ) < 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_close_notify returned %d\n\n", ret ); + goto reset; + } + } + + mbedtls_printf( " ok\n" ); + + ret = 0; + goto reset; + +exit: + +#ifdef MBEDTLS_ERROR_C + if( ret != 0 ) + { + char error_buf[100]; + mbedtls_strerror( ret, error_buf, 100 ); + mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf ); + } +#endif + + mbedtls_net_free( &client_fd ); + mbedtls_net_free( &listen_fd ); + + mbedtls_x509_crt_free( &srvcert ); + mbedtls_pk_free( &pkey ); + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_free( &cache ); +#endif + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( ret ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_CERTS_C && MBEDTLS_ENTROPY_C && + MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C && + MBEDTLS_RSA_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_X509_CRT_PARSE_C + && MBEDTLS_FS_IO && MBEDTLS_PEM_PARSE_C */ diff --git a/external/mbedtls/programs/ssl/ssl_server2.c b/external/mbedtls/programs/ssl/ssl_server2.c new file mode 100644 index 0000000..3115966 --- /dev/null +++ b/external/mbedtls/programs/ssl/ssl_server2.c @@ -0,0 +1,3257 @@ +/* + * SSL client with options + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_time time +#define mbedtls_time_t time_t +#define mbedtls_calloc calloc +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif + +#if !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_SRV_C) || \ + !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_SRV_C and/or " + "MBEDTLS_NET_C and/or MBEDTLS_CTR_DRBG_C and/or not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/net_sockets.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/x509.h" +#include "mbedtls/error.h" +#include "mbedtls/debug.h" +#include "mbedtls/timing.h" + +#include +#include +#include +#include + +#if !defined(_MSC_VER) +#include +#endif + +#if !defined(_WIN32) +#include +#endif + +#if defined(MBEDTLS_SSL_CACHE_C) +#include "mbedtls/ssl_cache.h" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) +#include "mbedtls/ssl_ticket.h" +#endif + +#if defined(MBEDTLS_SSL_COOKIE_C) +#include "mbedtls/ssl_cookie.h" +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && defined(MBEDTLS_FS_IO) +#define SNI_OPTION +#endif + +#if defined(_WIN32) +#include +#endif + +/* Size of memory to be allocated for the heap, when using the library's memory + * management and MBEDTLS_MEMORY_BUFFER_ALLOC_C is enabled. */ +#define MEMORY_HEAP_SIZE 120000 + +#define DFL_SERVER_ADDR NULL +#define DFL_SERVER_PORT "4433" +#define DFL_RESPONSE_SIZE -1 +#define DFL_DEBUG_LEVEL 0 +#define DFL_NBIO 0 +#define DFL_EVENT 0 +#define DFL_READ_TIMEOUT 0 +#define DFL_CA_FILE "" +#define DFL_CA_PATH "" +#define DFL_CRT_FILE "" +#define DFL_KEY_FILE "" +#define DFL_CRT_FILE2 "" +#define DFL_KEY_FILE2 "" +#define DFL_ASYNC_OPERATIONS "-" +#define DFL_ASYNC_PRIVATE_DELAY1 ( -1 ) +#define DFL_ASYNC_PRIVATE_DELAY2 ( -1 ) +#define DFL_ASYNC_PRIVATE_ERROR ( 0 ) +#define DFL_PSK "" +#define DFL_PSK_IDENTITY "Client_identity" +#define DFL_ECJPAKE_PW NULL +#define DFL_PSK_LIST NULL +#define DFL_FORCE_CIPHER 0 +#define DFL_VERSION_SUITES NULL +#define DFL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION_DISABLED +#define DFL_ALLOW_LEGACY -2 +#define DFL_RENEGOTIATE 0 +#define DFL_RENEGO_DELAY -2 +#define DFL_RENEGO_PERIOD ( (uint64_t)-1 ) +#define DFL_EXCHANGES 1 +#define DFL_MIN_VERSION -1 +#define DFL_MAX_VERSION -1 +#define DFL_ARC4 -1 +#define DFL_SHA1 -1 +#define DFL_AUTH_MODE -1 +#define DFL_CERT_REQ_CA_LIST MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED +#define DFL_MFL_CODE MBEDTLS_SSL_MAX_FRAG_LEN_NONE +#define DFL_TRUNC_HMAC -1 +#define DFL_TICKETS MBEDTLS_SSL_SESSION_TICKETS_ENABLED +#define DFL_TICKET_TIMEOUT 86400 +#define DFL_CACHE_MAX -1 +#define DFL_CACHE_TIMEOUT -1 +#define DFL_SNI NULL +#define DFL_ALPN_STRING NULL +#define DFL_CURVES NULL +#define DFL_DHM_FILE NULL +#define DFL_TRANSPORT MBEDTLS_SSL_TRANSPORT_STREAM +#define DFL_COOKIES 1 +#define DFL_ANTI_REPLAY -1 +#define DFL_HS_TO_MIN 0 +#define DFL_HS_TO_MAX 0 +#define DFL_DTLS_MTU -1 +#define DFL_BADMAC_LIMIT -1 +#define DFL_DGRAM_PACKING 1 +#define DFL_EXTENDED_MS -1 +#define DFL_ETM -1 + +#define LONG_RESPONSE "

01-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "02-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "03-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "04-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "05-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "06-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "07-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah

\r\n" + +/* Uncomment LONG_RESPONSE at the end of HTTP_RESPONSE to test sending longer + * packets (for fragmentation purposes) */ +#define HTTP_RESPONSE \ + "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ + "

mbed TLS Test Server

\r\n" \ + "

Successful connection using: %s

\r\n" // LONG_RESPONSE + +/* + * Size of the basic I/O buffer. Able to hold our default response. + * + * You will need to adapt the mbedtls_ssl_get_bytes_avail() test in ssl-opt.sh + * if you change this value to something outside the range <= 100 or > 500 + */ +#define DFL_IO_BUF_LEN 200 + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_FS_IO) +#define USAGE_IO \ + " ca_file=%%s The single file containing the top-level CA(s) you fully trust\n" \ + " default: \"\" (pre-loaded)\n" \ + " use \"none\" to skip loading any top-level CAs.\n" \ + " ca_path=%%s The path containing the top-level CA(s) you fully trust\n" \ + " default: \"\" (pre-loaded) (overrides ca_file)\n" \ + " use \"none\" to skip loading any top-level CAs.\n" \ + " crt_file=%%s Your own cert and chain (in bottom to top order, top may be omitted)\n" \ + " default: see note after key_file2\n" \ + " key_file=%%s default: see note after key_file2\n" \ + " crt_file2=%%s Your second cert and chain (in bottom to top order, top may be omitted)\n" \ + " default: see note after key_file2\n" \ + " key_file2=%%s default: see note below\n" \ + " note: if neither crt_file/key_file nor crt_file2/key_file2 are used,\n" \ + " preloaded certificate(s) and key(s) are used if available\n" \ + " dhm_file=%%s File containing Diffie-Hellman parameters\n" \ + " default: preloaded parameters\n" +#else +#define USAGE_IO \ + "\n" \ + " No file operations available (MBEDTLS_FS_IO not defined)\n" \ + "\n" +#endif /* MBEDTLS_FS_IO */ +#else +#define USAGE_IO "" +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#define USAGE_SSL_ASYNC \ + " async_operations=%%c... d=decrypt, s=sign (default: -=off)\n" \ + " async_private_delay1=%%d Asynchronous delay for key_file or preloaded key\n" \ + " async_private_delay2=%%d Asynchronous delay for key_file2 and sni\n" \ + " default: -1 (not asynchronous)\n" \ + " async_private_error=%%d Async callback error injection (default=0=none,\n" \ + " 1=start, 2=cancel, 3=resume, negative=first time only)" +#else +#define USAGE_SSL_ASYNC "" +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#define USAGE_PSK \ + " psk=%%s default: \"\" (in hex, without 0x)\n" \ + " psk_list=%%s default: \"\"\n" \ + " A list of (PSK identity, PSK value) pairs.\n" \ + " The PSK values are in hex, without 0x.\n" \ + " id1,psk1[,id2,psk2[,...]]\n" \ + " psk_identity=%%s default: \"Client_identity\"\n" +#else +#define USAGE_PSK "" +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#define USAGE_TICKETS \ + " tickets=%%d default: 1 (enabled)\n" \ + " ticket_timeout=%%d default: 86400 (one day)\n" +#else +#define USAGE_TICKETS "" +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_CACHE_C) +#define USAGE_CACHE \ + " cache_max=%%d default: cache default (50)\n" \ + " cache_timeout=%%d default: cache default (1d)\n" +#else +#define USAGE_CACHE "" +#endif /* MBEDTLS_SSL_CACHE_C */ + +#if defined(SNI_OPTION) +#if defined(MBEDTLS_X509_CRL_PARSE_C) +#define SNI_CRL ",crl" +#else +#define SNI_CRL "" +#endif + +#define USAGE_SNI \ + " sni=%%s name1,cert1,key1,ca1"SNI_CRL",auth1[,...]\n" \ + " default: disabled\n" +#else +#define USAGE_SNI "" +#endif /* SNI_OPTION */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +#define USAGE_MAX_FRAG_LEN \ + " max_frag_len=%%d default: 16384 (tls default)\n" \ + " options: 512, 1024, 2048, 4096\n" +#else +#define USAGE_MAX_FRAG_LEN "" +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#define USAGE_TRUNC_HMAC \ + " trunc_hmac=%%d default: library default\n" +#else +#define USAGE_TRUNC_HMAC "" +#endif + +#if defined(MBEDTLS_SSL_ALPN) +#define USAGE_ALPN \ + " alpn=%%s default: \"\" (disabled)\n" \ + " example: spdy/1,http/1.1\n" +#else +#define USAGE_ALPN "" +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +#define USAGE_COOKIES \ + " cookies=0/1/-1 default: 1 (enabled)\n" \ + " 0: disabled, -1: library default (broken)\n" +#else +#define USAGE_COOKIES "" +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +#define USAGE_ANTI_REPLAY \ + " anti_replay=0/1 default: (library default: enabled)\n" +#else +#define USAGE_ANTI_REPLAY "" +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +#define USAGE_BADMAC_LIMIT \ + " badmac_limit=%%d default: (library default: disabled)\n" +#else +#define USAGE_BADMAC_LIMIT "" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +#define USAGE_DTLS \ + " dtls=%%d default: 0 (TLS)\n" \ + " hs_timeout=%%d-%%d default: (library default: 1000-60000)\n" \ + " range of DTLS handshake timeouts in millisecs\n" \ + " mtu=%%d default: (library default: unlimited)\n" \ + " dgram_packing=%%d default: 1 (allowed)\n" \ + " allow or forbid packing of multiple\n" \ + " records within a single datgram.\n" +#else +#define USAGE_DTLS "" +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +#define USAGE_EMS \ + " extended_ms=0/1 default: (library default: on)\n" +#else +#define USAGE_EMS "" +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +#define USAGE_ETM \ + " etm=0/1 default: (library default: on)\n" +#else +#define USAGE_ETM "" +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +#define USAGE_RENEGO \ + " renegotiation=%%d default: 0 (disabled)\n" \ + " renegotiate=%%d default: 0 (disabled)\n" \ + " renego_delay=%%d default: -2 (library default)\n" \ + " renego_period=%%d default: (2^64 - 1 for TLS, 2^48 - 1 for DTLS)\n" +#else +#define USAGE_RENEGO "" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#define USAGE_ECJPAKE \ + " ecjpake_pw=%%s default: none (disabled)\n" +#else +#define USAGE_ECJPAKE "" +#endif + +#if defined(MBEDTLS_ECP_C) +#define USAGE_CURVES \ + " curves=a,b,c,d default: \"default\" (library default)\n" \ + " example: \"secp521r1,brainpoolP512r1\"\n" \ + " - use \"none\" for empty list\n" \ + " - see mbedtls_ecp_curve_list()\n" \ + " for acceptable curve names\n" +#else +#define USAGE_CURVES "" +#endif + +/* USAGE is arbitrarily split to stay under the portable string literal + * length limit: 4095 bytes in C99. */ +#define USAGE1 \ + "\n usage: ssl_server2 param=<>...\n" \ + "\n acceptable parameters:\n" \ + " server_addr=%%s default: (all interfaces)\n" \ + " server_port=%%d default: 4433\n" \ + " debug_level=%%d default: 0 (disabled)\n" \ + " buffer_size=%%d default: 200 \n" \ + " (minimum: 1, max: 16385)\n" \ + " response_size=%%d default: about 152 (basic response)\n" \ + " (minimum: 0, max: 16384)\n" \ + " increases buffer_size if bigger\n"\ + " nbio=%%d default: 0 (blocking I/O)\n" \ + " options: 1 (non-blocking), 2 (added delays)\n" \ + " event=%%d default: 0 (loop)\n" \ + " options: 1 (level-triggered, implies nbio=1),\n" \ + " read_timeout=%%d default: 0 ms (no timeout)\n" \ + "\n" \ + USAGE_DTLS \ + USAGE_COOKIES \ + USAGE_ANTI_REPLAY \ + USAGE_BADMAC_LIMIT \ + "\n" +#define USAGE2 \ + " auth_mode=%%s default: (library default: none)\n" \ + " options: none, optional, required\n" \ + " cert_req_ca_list=%%d default: 1 (send ca list)\n" \ + " options: 1 (send ca list), 0 (don't send)\n" \ + USAGE_IO \ + USAGE_SSL_ASYNC \ + USAGE_SNI \ + "\n" \ + USAGE_PSK \ + USAGE_ECJPAKE \ + "\n" +#define USAGE3 \ + " allow_legacy=%%d default: (library default: no)\n" \ + USAGE_RENEGO \ + " exchanges=%%d default: 1\n" \ + "\n" \ + USAGE_TICKETS \ + USAGE_CACHE \ + USAGE_MAX_FRAG_LEN \ + USAGE_TRUNC_HMAC \ + USAGE_ALPN \ + USAGE_EMS \ + USAGE_ETM \ + USAGE_CURVES \ + "\n" +#define USAGE4 \ + " arc4=%%d default: (library default: 0)\n" \ + " allow_sha1=%%d default: 0\n" \ + " min_version=%%s default: (library default: tls1)\n" \ + " max_version=%%s default: (library default: tls1_2)\n" \ + " force_version=%%s default: \"\" (none)\n" \ + " options: ssl3, tls1, tls1_1, tls1_2, dtls1, dtls1_2\n" \ + "\n" \ + " version_suites=a,b,c,d per-version ciphersuites\n" \ + " in order from ssl3 to tls1_2\n" \ + " default: all enabled\n" \ + " force_ciphersuite= default: all enabled\n" \ + " query_config= return 0 if the specified\n" \ + " configuration macro is defined and 1\n" \ + " otherwise. The expansion of the macro\n" \ + " is printed if it is defined\n" \ + " acceptable ciphersuite names:\n" + +#define ALPN_LIST_SIZE 10 +#define CURVE_LIST_SIZE 20 + +#define PUT_UINT64_BE(out_be,in_le,i) \ +{ \ + (out_be)[(i) + 0] = (unsigned char)( ( (in_le) >> 56 ) & 0xFF ); \ + (out_be)[(i) + 1] = (unsigned char)( ( (in_le) >> 48 ) & 0xFF ); \ + (out_be)[(i) + 2] = (unsigned char)( ( (in_le) >> 40 ) & 0xFF ); \ + (out_be)[(i) + 3] = (unsigned char)( ( (in_le) >> 32 ) & 0xFF ); \ + (out_be)[(i) + 4] = (unsigned char)( ( (in_le) >> 24 ) & 0xFF ); \ + (out_be)[(i) + 5] = (unsigned char)( ( (in_le) >> 16 ) & 0xFF ); \ + (out_be)[(i) + 6] = (unsigned char)( ( (in_le) >> 8 ) & 0xFF ); \ + (out_be)[(i) + 7] = (unsigned char)( ( (in_le) >> 0 ) & 0xFF ); \ +} + + +/* + * global options + */ +struct options +{ + const char *server_addr; /* address on which the ssl service runs */ + const char *server_port; /* port on which the ssl service runs */ + int debug_level; /* level of debugging */ + int nbio; /* should I/O be blocking? */ + int event; /* loop or event-driven IO? level or edge triggered? */ + uint32_t read_timeout; /* timeout on mbedtls_ssl_read() in milliseconds */ + int response_size; /* pad response with header to requested size */ + uint16_t buffer_size; /* IO buffer size */ + const char *ca_file; /* the file with the CA certificate(s) */ + const char *ca_path; /* the path with the CA certificate(s) reside */ + const char *crt_file; /* the file with the server certificate */ + const char *key_file; /* the file with the server key */ + const char *crt_file2; /* the file with the 2nd server certificate */ + const char *key_file2; /* the file with the 2nd server key */ + const char *async_operations; /* supported SSL asynchronous operations */ + int async_private_delay1; /* number of times f_async_resume needs to be called for key 1, or -1 for no async */ + int async_private_delay2; /* number of times f_async_resume needs to be called for key 2, or -1 for no async */ + int async_private_error; /* inject error in async private callback */ + const char *psk; /* the pre-shared key */ + const char *psk_identity; /* the pre-shared key identity */ + char *psk_list; /* list of PSK id/key pairs for callback */ + const char *ecjpake_pw; /* the EC J-PAKE password */ + int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */ + const char *version_suites; /* per-version ciphersuites */ + int renegotiation; /* enable / disable renegotiation */ + int allow_legacy; /* allow legacy renegotiation */ + int renegotiate; /* attempt renegotiation? */ + int renego_delay; /* delay before enforcing renegotiation */ + uint64_t renego_period; /* period for automatic renegotiation */ + int exchanges; /* number of data exchanges */ + int min_version; /* minimum protocol version accepted */ + int max_version; /* maximum protocol version accepted */ + int arc4; /* flag for arc4 suites support */ + int allow_sha1; /* flag for SHA-1 support */ + int auth_mode; /* verify mode for connection */ + int cert_req_ca_list; /* should we send the CA list? */ + unsigned char mfl_code; /* code for maximum fragment length */ + int trunc_hmac; /* accept truncated hmac? */ + int tickets; /* enable / disable session tickets */ + int ticket_timeout; /* session ticket lifetime */ + int cache_max; /* max number of session cache entries */ + int cache_timeout; /* expiration delay of session cache entries */ + char *sni; /* string describing sni information */ + const char *curves; /* list of supported elliptic curves */ + const char *alpn_string; /* ALPN supported protocols */ + const char *dhm_file; /* the file with the DH parameters */ + int extended_ms; /* allow negotiation of extended MS? */ + int etm; /* allow negotiation of encrypt-then-MAC? */ + int transport; /* TLS or DTLS? */ + int cookies; /* Use cookies for DTLS? -1 to break them */ + int anti_replay; /* Use anti-replay for DTLS? -1 for default */ + uint32_t hs_to_min; /* Initial value of DTLS handshake timer */ + uint32_t hs_to_max; /* Max value of DTLS handshake timer */ + int dtls_mtu; /* UDP Maximum tranport unit for DTLS */ + int dgram_packing; /* allow/forbid datagram packing */ + int badmac_limit; /* Limit of records with bad MAC */ +} opt; + +int query_config( const char *config ); + +static void my_debug( void *ctx, int level, + const char *file, int line, + const char *str ) +{ + const char *p, *basename; + + /* Extract basename from file */ + for( p = basename = file; *p != '\0'; p++ ) + if( *p == '/' || *p == '\\' ) + basename = p + 1; + + mbedtls_fprintf( (FILE *) ctx, "%s:%04d: |%d| %s", basename, line, level, str ); + fflush( (FILE *) ctx ); +} + +/* + * Test recv/send functions that make sure each try returns + * WANT_READ/WANT_WRITE at least once before sucesseding + */ +static int my_recv( void *ctx, unsigned char *buf, size_t len ) +{ + static int first_try = 1; + int ret; + + if( first_try ) + { + first_try = 0; + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + + ret = mbedtls_net_recv( ctx, buf, len ); + if( ret != MBEDTLS_ERR_SSL_WANT_READ ) + first_try = 1; /* Next call will be a new operation */ + return( ret ); +} + +static int my_send( void *ctx, const unsigned char *buf, size_t len ) +{ + static int first_try = 1; + int ret; + + if( first_try ) + { + first_try = 0; + return( MBEDTLS_ERR_SSL_WANT_WRITE ); + } + + ret = mbedtls_net_send( ctx, buf, len ); + if( ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + first_try = 1; /* Next call will be a new operation */ + return( ret ); +} + +/* + * Return authmode from string, or -1 on error + */ +static int get_auth_mode( const char *s ) +{ + if( strcmp( s, "none" ) == 0 ) + return( MBEDTLS_SSL_VERIFY_NONE ); + if( strcmp( s, "optional" ) == 0 ) + return( MBEDTLS_SSL_VERIFY_OPTIONAL ); + if( strcmp( s, "required" ) == 0 ) + return( MBEDTLS_SSL_VERIFY_REQUIRED ); + + return( -1 ); +} + +/* + * Used by sni_parse and psk_parse to handle coma-separated lists + */ +#define GET_ITEM( dst ) \ + do \ + { \ + (dst) = p; \ + while( *p != ',' ) \ + if( ++p > end ) \ + goto error; \ + *p++ = '\0'; \ + } while( 0 ) + +#if defined(SNI_OPTION) +typedef struct _sni_entry sni_entry; + +struct _sni_entry { + const char *name; + mbedtls_x509_crt *cert; + mbedtls_pk_context *key; + mbedtls_x509_crt* ca; + mbedtls_x509_crl* crl; + int authmode; + sni_entry *next; +}; + +void sni_free( sni_entry *head ) +{ + sni_entry *cur = head, *next; + + while( cur != NULL ) + { + mbedtls_x509_crt_free( cur->cert ); + mbedtls_free( cur->cert ); + + mbedtls_pk_free( cur->key ); + mbedtls_free( cur->key ); + + mbedtls_x509_crt_free( cur->ca ); + mbedtls_free( cur->ca ); +#if defined(MBEDTLS_X509_CRL_PARSE_C) + mbedtls_x509_crl_free( cur->crl ); + mbedtls_free( cur->crl ); +#endif + next = cur->next; + mbedtls_free( cur ); + cur = next; + } +} + +/* + * Parse a string of sextuples name1,crt1,key1,ca1,crl1,auth1[,...] + * into a usable sni_entry list. For ca1, crl1, auth1, the special value + * '-' means unset. If ca1 is unset, then crl1 is ignored too. + * + * Modifies the input string! This is not production quality! + */ +sni_entry *sni_parse( char *sni_string ) +{ + sni_entry *cur = NULL, *new = NULL; + char *p = sni_string; + char *end = p; + char *crt_file, *key_file, *ca_file, *auth_str; +#if defined(MBEDTLS_X509_CRL_PARSE_C) + char *crl_file; +#endif + + while( *end != '\0' ) + ++end; + *end = ','; + + while( p <= end ) + { + if( ( new = mbedtls_calloc( 1, sizeof( sni_entry ) ) ) == NULL ) + { + sni_free( cur ); + return( NULL ); + } + + GET_ITEM( new->name ); + GET_ITEM( crt_file ); + GET_ITEM( key_file ); + GET_ITEM( ca_file ); +#if defined(MBEDTLS_X509_CRL_PARSE_C) + GET_ITEM( crl_file ); +#endif + GET_ITEM( auth_str ); + + if( ( new->cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ) ) == NULL || + ( new->key = mbedtls_calloc( 1, sizeof( mbedtls_pk_context ) ) ) == NULL ) + goto error; + + mbedtls_x509_crt_init( new->cert ); + mbedtls_pk_init( new->key ); + + if( mbedtls_x509_crt_parse_file( new->cert, crt_file ) != 0 || + mbedtls_pk_parse_keyfile( new->key, key_file, "" ) != 0 ) + goto error; + + if( strcmp( ca_file, "-" ) != 0 ) + { + if( ( new->ca = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ) ) == NULL ) + goto error; + + mbedtls_x509_crt_init( new->ca ); + + if( mbedtls_x509_crt_parse_file( new->ca, ca_file ) != 0 ) + goto error; + } + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + if( strcmp( crl_file, "-" ) != 0 ) + { + if( ( new->crl = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) ) ) == NULL ) + goto error; + + mbedtls_x509_crl_init( new->crl ); + + if( mbedtls_x509_crl_parse_file( new->crl, crl_file ) != 0 ) + goto error; + } +#endif + + if( strcmp( auth_str, "-" ) != 0 ) + { + if( ( new->authmode = get_auth_mode( auth_str ) ) < 0 ) + goto error; + } + else + new->authmode = DFL_AUTH_MODE; + + new->next = cur; + cur = new; + } + + return( cur ); + +error: + sni_free( new ); + sni_free( cur ); + return( NULL ); +} + +/* + * SNI callback. + */ +int sni_callback( void *p_info, mbedtls_ssl_context *ssl, + const unsigned char *name, size_t name_len ) +{ + const sni_entry *cur = (const sni_entry *) p_info; + + while( cur != NULL ) + { + if( name_len == strlen( cur->name ) && + memcmp( name, cur->name, name_len ) == 0 ) + { + if( cur->ca != NULL ) + mbedtls_ssl_set_hs_ca_chain( ssl, cur->ca, cur->crl ); + + if( cur->authmode != DFL_AUTH_MODE ) + mbedtls_ssl_set_hs_authmode( ssl, cur->authmode ); + + return( mbedtls_ssl_set_hs_own_cert( ssl, cur->cert, cur->key ) ); + } + + cur = cur->next; + } + + return( -1 ); +} + +#endif /* SNI_OPTION */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + +#define HEX2NUM( c ) \ + do \ + { \ + if( (c) >= '0' && (c) <= '9' ) \ + (c) -= '0'; \ + else if( (c) >= 'a' && (c) <= 'f' ) \ + (c) -= 'a' - 10; \ + else if( (c) >= 'A' && (c) <= 'F' ) \ + (c) -= 'A' - 10; \ + else \ + return( -1 ); \ + } while( 0 ) + +/* + * Convert a hex string to bytes. + * Return 0 on success, -1 on error. + */ +int unhexify( unsigned char *output, const char *input, size_t *olen ) +{ + unsigned char c; + size_t j; + + *olen = strlen( input ); + if( *olen % 2 != 0 || *olen / 2 > MBEDTLS_PSK_MAX_LEN ) + return( -1 ); + *olen /= 2; + + for( j = 0; j < *olen * 2; j += 2 ) + { + c = input[j]; + HEX2NUM( c ); + output[ j / 2 ] = c << 4; + + c = input[j + 1]; + HEX2NUM( c ); + output[ j / 2 ] |= c; + } + + return( 0 ); +} + +typedef struct _psk_entry psk_entry; + +struct _psk_entry +{ + const char *name; + size_t key_len; + unsigned char key[MBEDTLS_PSK_MAX_LEN]; + psk_entry *next; +}; + +/* + * Free a list of psk_entry's + */ +void psk_free( psk_entry *head ) +{ + psk_entry *next; + + while( head != NULL ) + { + next = head->next; + mbedtls_free( head ); + head = next; + } +} + +/* + * Parse a string of pairs name1,key1[,name2,key2[,...]] + * into a usable psk_entry list. + * + * Modifies the input string! This is not production quality! + */ +psk_entry *psk_parse( char *psk_string ) +{ + psk_entry *cur = NULL, *new = NULL; + char *p = psk_string; + char *end = p; + char *key_hex; + + while( *end != '\0' ) + ++end; + *end = ','; + + while( p <= end ) + { + if( ( new = mbedtls_calloc( 1, sizeof( psk_entry ) ) ) == NULL ) + goto error; + + memset( new, 0, sizeof( psk_entry ) ); + + GET_ITEM( new->name ); + GET_ITEM( key_hex ); + + if( unhexify( new->key, key_hex, &new->key_len ) != 0 ) + goto error; + + new->next = cur; + cur = new; + } + + return( cur ); + +error: + psk_free( new ); + psk_free( cur ); + return( 0 ); +} + +/* + * PSK callback + */ +int psk_callback( void *p_info, mbedtls_ssl_context *ssl, + const unsigned char *name, size_t name_len ) +{ + psk_entry *cur = (psk_entry *) p_info; + + while( cur != NULL ) + { + if( name_len == strlen( cur->name ) && + memcmp( name, cur->name, name_len ) == 0 ) + { + return( mbedtls_ssl_set_hs_psk( ssl, cur->key, cur->key_len ) ); + } + + cur = cur->next; + } + + return( -1 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +static mbedtls_net_context listen_fd, client_fd; + +/* Interruption handler to ensure clean exit (for valgrind testing) */ +#if !defined(_WIN32) +static int received_sigterm = 0; +void term_handler( int sig ) +{ + ((void) sig); + received_sigterm = 1; + mbedtls_net_free( &listen_fd ); /* causes mbedtls_net_accept() to abort */ + mbedtls_net_free( &client_fd ); /* causes net_read() to abort */ +} +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static int ssl_sig_hashes_for_test[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, + MBEDTLS_MD_SHA384, +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif +#if defined(MBEDTLS_SHA1_C) + /* Allow SHA-1 as we use it extensively in tests. */ + MBEDTLS_MD_SHA1, +#endif + MBEDTLS_MD_NONE +}; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** Return true if \p ret is a status code indicating that there is an + * operation in progress on an SSL connection, and false if it indicates + * success or a fatal error. + * + * The possible operations in progress are: + * + * - A read, when the SSL input buffer does not contain a full message. + * - A write, when the SSL output buffer contains some data that has not + * been sent over the network yet. + * - An asynchronous callback that has not completed yet. */ +static int mbedtls_status_is_ssl_in_progress( int ret ) +{ + return( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE || + ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); +} + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +typedef struct +{ + mbedtls_x509_crt *cert; /*!< Certificate corresponding to the key */ + mbedtls_pk_context *pk; /*!< Private key */ + unsigned delay; /*!< Number of resume steps to go through */ + unsigned pk_owned : 1; /*!< Whether to free the pk object on exit */ +} ssl_async_key_slot_t; + +typedef enum { + SSL_ASYNC_INJECT_ERROR_NONE = 0, /*!< Let the callbacks succeed */ + SSL_ASYNC_INJECT_ERROR_START, /*!< Inject error during start */ + SSL_ASYNC_INJECT_ERROR_CANCEL, /*!< Close the connection after async start */ + SSL_ASYNC_INJECT_ERROR_RESUME, /*!< Inject error during resume */ +#define SSL_ASYNC_INJECT_ERROR_MAX SSL_ASYNC_INJECT_ERROR_RESUME +} ssl_async_inject_error_t; + +typedef struct +{ + ssl_async_key_slot_t slots[4]; /* key, key2, sni1, sni2 */ + size_t slots_used; + ssl_async_inject_error_t inject_error; + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; +} ssl_async_key_context_t; + +int ssl_async_set_key( ssl_async_key_context_t *ctx, + mbedtls_x509_crt *cert, + mbedtls_pk_context *pk, + int pk_take_ownership, + unsigned delay ) +{ + if( ctx->slots_used >= sizeof( ctx->slots ) / sizeof( *ctx->slots ) ) + return( -1 ); + ctx->slots[ctx->slots_used].cert = cert; + ctx->slots[ctx->slots_used].pk = pk; + ctx->slots[ctx->slots_used].delay = delay; + ctx->slots[ctx->slots_used].pk_owned = pk_take_ownership; + ++ctx->slots_used; + return( 0 ); +} + +#define SSL_ASYNC_INPUT_MAX_SIZE 512 + +typedef enum +{ + ASYNC_OP_SIGN, + ASYNC_OP_DECRYPT, +} ssl_async_operation_type_t; +/* Note that the enum above and the array below need to be kept in sync! + * `ssl_async_operation_names[op]` is the name of op for each value `op` + * of type `ssl_async_operation_type_t`. */ +static const char *const ssl_async_operation_names[] = +{ + "sign", + "decrypt", +}; + +typedef struct +{ + unsigned slot; + ssl_async_operation_type_t operation_type; + mbedtls_md_type_t md_alg; + unsigned char input[SSL_ASYNC_INPUT_MAX_SIZE]; + size_t input_len; + unsigned remaining_delay; +} ssl_async_operation_context_t; + +static int ssl_async_start( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + ssl_async_operation_type_t op_type, + mbedtls_md_type_t md_alg, + const unsigned char *input, + size_t input_len ) +{ + ssl_async_key_context_t *config_data = + mbedtls_ssl_conf_get_async_config_data( ssl->conf ); + unsigned slot; + ssl_async_operation_context_t *ctx = NULL; + const char *op_name = ssl_async_operation_names[op_type]; + + { + char dn[100]; + if( mbedtls_x509_dn_gets( dn, sizeof( dn ), &cert->subject ) > 0 ) + mbedtls_printf( "Async %s callback: looking for DN=%s\n", + op_name, dn ); + } + + /* Look for a private key that matches the public key in cert. + * Since this test code has the private key inside Mbed TLS, + * we call mbedtls_pk_check_pair to match a private key with the + * public key. */ + for( slot = 0; slot < config_data->slots_used; slot++ ) + { + if( mbedtls_pk_check_pair( &cert->pk, + config_data->slots[slot].pk ) == 0 ) + break; + } + if( slot == config_data->slots_used ) + { + mbedtls_printf( "Async %s callback: no key matches this certificate.\n", + op_name ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ); + } + mbedtls_printf( "Async %s callback: using key slot %u, delay=%u.\n", + op_name, slot, config_data->slots[slot].delay ); + + if( config_data->inject_error == SSL_ASYNC_INJECT_ERROR_START ) + { + mbedtls_printf( "Async %s callback: injected error\n", op_name ); + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + } + + if( input_len > SSL_ASYNC_INPUT_MAX_SIZE ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ctx = mbedtls_calloc( 1, sizeof( *ctx ) ); + if( ctx == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + ctx->slot = slot; + ctx->operation_type = op_type; + ctx->md_alg = md_alg; + memcpy( ctx->input, input, input_len ); + ctx->input_len = input_len; + ctx->remaining_delay = config_data->slots[slot].delay; + mbedtls_ssl_set_async_operation_data( ssl, ctx ); + + if( ctx->remaining_delay == 0 ) + return( 0 ); + else + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); +} + +static int ssl_async_sign( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + mbedtls_md_type_t md_alg, + const unsigned char *hash, + size_t hash_len ) +{ + return( ssl_async_start( ssl, cert, + ASYNC_OP_SIGN, md_alg, + hash, hash_len ) ); +} + +static int ssl_async_decrypt( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + const unsigned char *input, + size_t input_len ) +{ + return( ssl_async_start( ssl, cert, + ASYNC_OP_DECRYPT, MBEDTLS_MD_NONE, + input, input_len ) ); +} + +static int ssl_async_resume( mbedtls_ssl_context *ssl, + unsigned char *output, + size_t *output_len, + size_t output_size ) +{ + ssl_async_operation_context_t *ctx = mbedtls_ssl_get_async_operation_data( ssl ); + ssl_async_key_context_t *config_data = + mbedtls_ssl_conf_get_async_config_data( ssl->conf ); + ssl_async_key_slot_t *key_slot = &config_data->slots[ctx->slot]; + int ret; + const char *op_name; + + if( ctx->remaining_delay > 0 ) + { + --ctx->remaining_delay; + mbedtls_printf( "Async resume (slot %u): call %u more times.\n", + ctx->slot, ctx->remaining_delay ); + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + } + + switch( ctx->operation_type ) + { + case ASYNC_OP_DECRYPT: + ret = mbedtls_pk_decrypt( key_slot->pk, + ctx->input, ctx->input_len, + output, output_len, output_size, + config_data->f_rng, config_data->p_rng ); + break; + case ASYNC_OP_SIGN: + ret = mbedtls_pk_sign( key_slot->pk, + ctx->md_alg, + ctx->input, ctx->input_len, + output, output_len, + config_data->f_rng, config_data->p_rng ); + break; + default: + mbedtls_printf( "Async resume (slot %u): unknown operation type %ld. This shouldn't happen.\n", + ctx->slot, (long) ctx->operation_type ); + mbedtls_free( ctx ); + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + break; + } + + op_name = ssl_async_operation_names[ctx->operation_type]; + + if( config_data->inject_error == SSL_ASYNC_INJECT_ERROR_RESUME ) + { + mbedtls_printf( "Async resume callback: %s done but injected error\n", + op_name ); + mbedtls_free( ctx ); + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + } + + mbedtls_printf( "Async resume (slot %u): %s done, status=%d.\n", + ctx->slot, op_name, ret ); + mbedtls_free( ctx ); + return( ret ); +} + +static void ssl_async_cancel( mbedtls_ssl_context *ssl ) +{ + ssl_async_operation_context_t *ctx = mbedtls_ssl_get_async_operation_data( ssl ); + mbedtls_printf( "Async cancel callback.\n" ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +/* + * Wait for an event from the underlying transport or the timer + * (Used in event-driven IO mode). + */ +#if !defined(MBEDTLS_TIMING_C) +int idle( mbedtls_net_context *fd, + int idle_reason ) +#else +int idle( mbedtls_net_context *fd, + mbedtls_timing_delay_context *timer, + int idle_reason ) +#endif +{ + int ret; + int poll_type = 0; + + if( idle_reason == MBEDTLS_ERR_SSL_WANT_WRITE ) + poll_type = MBEDTLS_NET_POLL_WRITE; + else if( idle_reason == MBEDTLS_ERR_SSL_WANT_READ ) + poll_type = MBEDTLS_NET_POLL_READ; +#if !defined(MBEDTLS_TIMING_C) + else + return( 0 ); +#endif + + while( 1 ) + { + /* Check if timer has expired */ +#if defined(MBEDTLS_TIMING_C) + if( timer != NULL && + mbedtls_timing_get_delay( timer ) == 2 ) + { + break; + } +#endif /* MBEDTLS_TIMING_C */ + + /* Check if underlying transport became available */ + if( poll_type != 0 ) + { + ret = mbedtls_net_poll( fd, poll_type, 0 ); + if( ret < 0 ) + return( ret ); + if( ret == poll_type ) + break; + } + } + + return( 0 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 0, len, written, frags, exchanges_left; + int version_suites[4][2]; + unsigned char* buf = 0; +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + unsigned char psk[MBEDTLS_PSK_MAX_LEN]; + size_t psk_len = 0; + psk_entry *psk_info = NULL; +#endif + const char *pers = "ssl_server2"; + unsigned char client_ip[16] = { 0 }; + size_t cliip_len; +#if defined(MBEDTLS_SSL_COOKIE_C) + mbedtls_ssl_cookie_ctx cookie_ctx; +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_profile crt_profile_for_test = mbedtls_x509_crt_profile_default; +#endif + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; +#if defined(MBEDTLS_TIMING_C) + mbedtls_timing_delay_context timer; +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + unsigned char renego_period[8] = { 0 }; +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) + uint32_t flags; + mbedtls_x509_crt cacert; + mbedtls_x509_crt srvcert; + mbedtls_pk_context pkey; + mbedtls_x509_crt srvcert2; + mbedtls_pk_context pkey2; + int key_cert_init = 0, key_cert_init2 = 0; +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + ssl_async_key_context_t ssl_async_keys; +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO) + mbedtls_dhm_context dhm; +#endif +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_context cache; +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_ticket_context ticket_ctx; +#endif +#if defined(SNI_OPTION) + sni_entry *sni_info = NULL; +#endif +#if defined(MBEDTLS_ECP_C) + mbedtls_ecp_group_id curve_list[CURVE_LIST_SIZE]; + const mbedtls_ecp_curve_info * curve_cur; +#endif +#if defined(MBEDTLS_SSL_ALPN) + const char *alpn_list[ALPN_LIST_SIZE]; +#endif +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + unsigned char alloc_buf[MEMORY_HEAP_SIZE]; +#endif + + int i; + char *p, *q; + const int *list; + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) ); +#endif + + /* + * Make sure memory references are valid in case we exit early. + */ + mbedtls_net_init( &client_fd ); + mbedtls_net_init( &listen_fd ); + mbedtls_ssl_init( &ssl ); + mbedtls_ssl_config_init( &conf ); + mbedtls_ctr_drbg_init( &ctr_drbg ); +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_init( &cacert ); + mbedtls_x509_crt_init( &srvcert ); + mbedtls_pk_init( &pkey ); + mbedtls_x509_crt_init( &srvcert2 ); + mbedtls_pk_init( &pkey2 ); +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + memset( &ssl_async_keys, 0, sizeof( ssl_async_keys ) ); +#endif +#endif +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO) + mbedtls_dhm_init( &dhm ); +#endif +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_init( &cache ); +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_ticket_init( &ticket_ctx ); +#endif +#if defined(MBEDTLS_SSL_ALPN) + memset( (void *) alpn_list, 0, sizeof( alpn_list ) ); +#endif +#if defined(MBEDTLS_SSL_COOKIE_C) + mbedtls_ssl_cookie_init( &cookie_ctx ); +#endif + +#if !defined(_WIN32) + /* Abort cleanly on SIGTERM and SIGINT */ + signal( SIGTERM, term_handler ); + signal( SIGINT, term_handler ); +#endif + + if( argc == 0 ) + { + usage: + if( ret == 0 ) + ret = 1; + + mbedtls_printf( USAGE1 ); + mbedtls_printf( USAGE2 ); + mbedtls_printf( USAGE3 ); + mbedtls_printf( USAGE4 ); + + list = mbedtls_ssl_list_ciphersuites(); + while( *list ) + { + mbedtls_printf(" %-42s", mbedtls_ssl_get_ciphersuite_name( *list ) ); + list++; + if( !*list ) + break; + mbedtls_printf(" %s\n", mbedtls_ssl_get_ciphersuite_name( *list ) ); + list++; + } + mbedtls_printf("\n"); + goto exit; + } + + opt.buffer_size = DFL_IO_BUF_LEN; + opt.server_addr = DFL_SERVER_ADDR; + opt.server_port = DFL_SERVER_PORT; + opt.debug_level = DFL_DEBUG_LEVEL; + opt.event = DFL_EVENT; + opt.response_size = DFL_RESPONSE_SIZE; + opt.nbio = DFL_NBIO; + opt.read_timeout = DFL_READ_TIMEOUT; + opt.ca_file = DFL_CA_FILE; + opt.ca_path = DFL_CA_PATH; + opt.crt_file = DFL_CRT_FILE; + opt.key_file = DFL_KEY_FILE; + opt.crt_file2 = DFL_CRT_FILE2; + opt.key_file2 = DFL_KEY_FILE2; + opt.async_operations = DFL_ASYNC_OPERATIONS; + opt.async_private_delay1 = DFL_ASYNC_PRIVATE_DELAY1; + opt.async_private_delay2 = DFL_ASYNC_PRIVATE_DELAY2; + opt.async_private_error = DFL_ASYNC_PRIVATE_ERROR; + opt.psk = DFL_PSK; + opt.psk_identity = DFL_PSK_IDENTITY; + opt.psk_list = DFL_PSK_LIST; + opt.ecjpake_pw = DFL_ECJPAKE_PW; + opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; + opt.version_suites = DFL_VERSION_SUITES; + opt.renegotiation = DFL_RENEGOTIATION; + opt.allow_legacy = DFL_ALLOW_LEGACY; + opt.renegotiate = DFL_RENEGOTIATE; + opt.renego_delay = DFL_RENEGO_DELAY; + opt.renego_period = DFL_RENEGO_PERIOD; + opt.exchanges = DFL_EXCHANGES; + opt.min_version = DFL_MIN_VERSION; + opt.max_version = DFL_MAX_VERSION; + opt.arc4 = DFL_ARC4; + opt.allow_sha1 = DFL_SHA1; + opt.auth_mode = DFL_AUTH_MODE; + opt.cert_req_ca_list = DFL_CERT_REQ_CA_LIST; + opt.mfl_code = DFL_MFL_CODE; + opt.trunc_hmac = DFL_TRUNC_HMAC; + opt.tickets = DFL_TICKETS; + opt.ticket_timeout = DFL_TICKET_TIMEOUT; + opt.cache_max = DFL_CACHE_MAX; + opt.cache_timeout = DFL_CACHE_TIMEOUT; + opt.sni = DFL_SNI; + opt.alpn_string = DFL_ALPN_STRING; + opt.curves = DFL_CURVES; + opt.dhm_file = DFL_DHM_FILE; + opt.transport = DFL_TRANSPORT; + opt.cookies = DFL_COOKIES; + opt.anti_replay = DFL_ANTI_REPLAY; + opt.hs_to_min = DFL_HS_TO_MIN; + opt.hs_to_max = DFL_HS_TO_MAX; + opt.dtls_mtu = DFL_DTLS_MTU; + opt.dgram_packing = DFL_DGRAM_PACKING; + opt.badmac_limit = DFL_BADMAC_LIMIT; + opt.extended_ms = DFL_EXTENDED_MS; + opt.etm = DFL_ETM; + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "server_port" ) == 0 ) + opt.server_port = q; + else if( strcmp( p, "server_addr" ) == 0 ) + opt.server_addr = q; + else if( strcmp( p, "dtls" ) == 0 ) + { + int t = atoi( q ); + if( t == 0 ) + opt.transport = MBEDTLS_SSL_TRANSPORT_STREAM; + else if( t == 1 ) + opt.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + else + goto usage; + } + else if( strcmp( p, "debug_level" ) == 0 ) + { + opt.debug_level = atoi( q ); + if( opt.debug_level < 0 || opt.debug_level > 65535 ) + goto usage; + } + else if( strcmp( p, "nbio" ) == 0 ) + { + opt.nbio = atoi( q ); + if( opt.nbio < 0 || opt.nbio > 2 ) + goto usage; + } + else if( strcmp( p, "event" ) == 0 ) + { + opt.event = atoi( q ); + if( opt.event < 0 || opt.event > 2 ) + goto usage; + } + else if( strcmp( p, "read_timeout" ) == 0 ) + opt.read_timeout = atoi( q ); + else if( strcmp( p, "buffer_size" ) == 0 ) + { + opt.buffer_size = atoi( q ); + if( opt.buffer_size < 1 || opt.buffer_size > MBEDTLS_SSL_MAX_CONTENT_LEN + 1 ) + goto usage; + } + else if( strcmp( p, "response_size" ) == 0 ) + { + opt.response_size = atoi( q ); + if( opt.response_size < 0 || opt.response_size > MBEDTLS_SSL_MAX_CONTENT_LEN ) + goto usage; + if( opt.buffer_size < opt.response_size ) + opt.buffer_size = opt.response_size; + } + else if( strcmp( p, "ca_file" ) == 0 ) + opt.ca_file = q; + else if( strcmp( p, "ca_path" ) == 0 ) + opt.ca_path = q; + else if( strcmp( p, "crt_file" ) == 0 ) + opt.crt_file = q; + else if( strcmp( p, "key_file" ) == 0 ) + opt.key_file = q; + else if( strcmp( p, "crt_file2" ) == 0 ) + opt.crt_file2 = q; + else if( strcmp( p, "key_file2" ) == 0 ) + opt.key_file2 = q; + else if( strcmp( p, "dhm_file" ) == 0 ) + opt.dhm_file = q; +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + else if( strcmp( p, "async_operations" ) == 0 ) + opt.async_operations = q; + else if( strcmp( p, "async_private_delay1" ) == 0 ) + opt.async_private_delay1 = atoi( q ); + else if( strcmp( p, "async_private_delay2" ) == 0 ) + opt.async_private_delay2 = atoi( q ); + else if( strcmp( p, "async_private_error" ) == 0 ) + { + int n = atoi( q ); + if( n < -SSL_ASYNC_INJECT_ERROR_MAX || + n > SSL_ASYNC_INJECT_ERROR_MAX ) + { + ret = 2; + goto usage; + } + opt.async_private_error = n; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + else if( strcmp( p, "psk" ) == 0 ) + opt.psk = q; + else if( strcmp( p, "psk_identity" ) == 0 ) + opt.psk_identity = q; + else if( strcmp( p, "psk_list" ) == 0 ) + opt.psk_list = q; + else if( strcmp( p, "ecjpake_pw" ) == 0 ) + opt.ecjpake_pw = q; + else if( strcmp( p, "force_ciphersuite" ) == 0 ) + { + opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q ); + + if( opt.force_ciphersuite[0] == 0 ) + { + ret = 2; + goto usage; + } + opt.force_ciphersuite[1] = 0; + } + else if( strcmp( p, "curves" ) == 0 ) + opt.curves = q; + else if( strcmp( p, "version_suites" ) == 0 ) + opt.version_suites = q; + else if( strcmp( p, "renegotiation" ) == 0 ) + { + opt.renegotiation = (atoi( q )) ? + MBEDTLS_SSL_RENEGOTIATION_ENABLED : + MBEDTLS_SSL_RENEGOTIATION_DISABLED; + } + else if( strcmp( p, "allow_legacy" ) == 0 ) + { + switch( atoi( q ) ) + { + case -1: + opt.allow_legacy = MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE; + break; + case 0: + opt.allow_legacy = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION; + break; + case 1: + opt.allow_legacy = MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION; + break; + default: goto usage; + } + } + else if( strcmp( p, "renegotiate" ) == 0 ) + { + opt.renegotiate = atoi( q ); + if( opt.renegotiate < 0 || opt.renegotiate > 1 ) + goto usage; + } + else if( strcmp( p, "renego_delay" ) == 0 ) + { + opt.renego_delay = atoi( q ); + } + else if( strcmp( p, "renego_period" ) == 0 ) + { +#if defined(_MSC_VER) + opt.renego_period = _strtoui64( q, NULL, 10 ); +#else + if( sscanf( q, "%" SCNu64, &opt.renego_period ) != 1 ) + goto usage; +#endif /* _MSC_VER */ + if( opt.renego_period < 2 ) + goto usage; + } + else if( strcmp( p, "exchanges" ) == 0 ) + { + opt.exchanges = atoi( q ); + if( opt.exchanges < 0 ) + goto usage; + } + else if( strcmp( p, "min_version" ) == 0 ) + { + if( strcmp( q, "ssl3" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_0; + else if( strcmp( q, "tls1" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_1; + else if( strcmp( q, "tls1_1" ) == 0 || + strcmp( q, "dtls1" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + else if( strcmp( q, "tls1_2" ) == 0 || + strcmp( q, "dtls1_2" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3; + else + goto usage; + } + else if( strcmp( p, "max_version" ) == 0 ) + { + if( strcmp( q, "ssl3" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_0; + else if( strcmp( q, "tls1" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_1; + else if( strcmp( q, "tls1_1" ) == 0 || + strcmp( q, "dtls1" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2; + else if( strcmp( q, "tls1_2" ) == 0 || + strcmp( q, "dtls1_2" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3; + else + goto usage; + } + else if( strcmp( p, "arc4" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.arc4 = MBEDTLS_SSL_ARC4_DISABLED; break; + case 1: opt.arc4 = MBEDTLS_SSL_ARC4_ENABLED; break; + default: goto usage; + } + } + else if( strcmp( p, "allow_sha1" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.allow_sha1 = 0; break; + case 1: opt.allow_sha1 = 1; break; + default: goto usage; + } + } + else if( strcmp( p, "force_version" ) == 0 ) + { + if( strcmp( q, "ssl3" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_0; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_0; + } + else if( strcmp( q, "tls1" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_1; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_1; + } + else if( strcmp( q, "tls1_1" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2; + } + else if( strcmp( q, "tls1_2" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3; + } + else if( strcmp( q, "dtls1" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2; + opt.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + } + else if( strcmp( q, "dtls1_2" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3; + opt.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + } + else + goto usage; + } + else if( strcmp( p, "auth_mode" ) == 0 ) + { + if( ( opt.auth_mode = get_auth_mode( q ) ) < 0 ) + goto usage; + } + else if( strcmp( p, "cert_req_ca_list" ) == 0 ) + { + opt.cert_req_ca_list = atoi( q ); + if( opt.cert_req_ca_list < 0 || opt.cert_req_ca_list > 1 ) + goto usage; + } + else if( strcmp( p, "max_frag_len" ) == 0 ) + { + if( strcmp( q, "512" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_512; + else if( strcmp( q, "1024" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_1024; + else if( strcmp( q, "2048" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_2048; + else if( strcmp( q, "4096" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_4096; + else + goto usage; + } + else if( strcmp( p, "alpn" ) == 0 ) + { + opt.alpn_string = q; + } + else if( strcmp( p, "trunc_hmac" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_DISABLED; break; + case 1: opt.trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; break; + default: goto usage; + } + } + else if( strcmp( p, "extended_ms" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: + opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_DISABLED; + break; + case 1: + opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + break; + default: goto usage; + } + } + else if( strcmp( p, "etm" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.etm = MBEDTLS_SSL_ETM_DISABLED; break; + case 1: opt.etm = MBEDTLS_SSL_ETM_ENABLED; break; + default: goto usage; + } + } + else if( strcmp( p, "tickets" ) == 0 ) + { + opt.tickets = atoi( q ); + if( opt.tickets < 0 || opt.tickets > 1 ) + goto usage; + } + else if( strcmp( p, "ticket_timeout" ) == 0 ) + { + opt.ticket_timeout = atoi( q ); + if( opt.ticket_timeout < 0 ) + goto usage; + } + else if( strcmp( p, "cache_max" ) == 0 ) + { + opt.cache_max = atoi( q ); + if( opt.cache_max < 0 ) + goto usage; + } + else if( strcmp( p, "cache_timeout" ) == 0 ) + { + opt.cache_timeout = atoi( q ); + if( opt.cache_timeout < 0 ) + goto usage; + } + else if( strcmp( p, "cookies" ) == 0 ) + { + opt.cookies = atoi( q ); + if( opt.cookies < -1 || opt.cookies > 1) + goto usage; + } + else if( strcmp( p, "anti_replay" ) == 0 ) + { + opt.anti_replay = atoi( q ); + if( opt.anti_replay < 0 || opt.anti_replay > 1) + goto usage; + } + else if( strcmp( p, "badmac_limit" ) == 0 ) + { + opt.badmac_limit = atoi( q ); + if( opt.badmac_limit < 0 ) + goto usage; + } + else if( strcmp( p, "hs_timeout" ) == 0 ) + { + if( ( p = strchr( q, '-' ) ) == NULL ) + goto usage; + *p++ = '\0'; + opt.hs_to_min = atoi( q ); + opt.hs_to_max = atoi( p ); + if( opt.hs_to_min == 0 || opt.hs_to_max < opt.hs_to_min ) + goto usage; + } + else if( strcmp( p, "mtu" ) == 0 ) + { + opt.dtls_mtu = atoi( q ); + if( opt.dtls_mtu < 0 ) + goto usage; + } + else if( strcmp( p, "dgram_packing" ) == 0 ) + { + opt.dgram_packing = atoi( q ); + if( opt.dgram_packing != 0 && + opt.dgram_packing != 1 ) + { + goto usage; + } + } + else if( strcmp( p, "sni" ) == 0 ) + { + opt.sni = q; + } + else if( strcmp( p, "query_config" ) == 0 ) + { + mbedtls_exit( query_config( q ) ); + } + else + goto usage; + } + + /* Event-driven IO is incompatible with the above custom + * receive and send functions, as the polling builds on + * refers to the underlying net_context. */ + if( opt.event == 1 && opt.nbio != 1 ) + { + mbedtls_printf( "Warning: event-driven IO mandates nbio=1 - overwrite\n" ); + opt.nbio = 1; + } + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold( opt.debug_level ); +#endif + buf = mbedtls_calloc( 1, opt.buffer_size + 1 ); + if( buf == NULL ) + { + mbedtls_printf( "Could not allocate %u bytes\n", opt.buffer_size ); + ret = 3; + goto exit; + } + + if( opt.force_ciphersuite[0] > 0 ) + { + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] ); + + if( opt.max_version != -1 && + ciphersuite_info->min_minor_ver > opt.max_version ) + { + mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" ); + ret = 2; + goto usage; + } + if( opt.min_version != -1 && + ciphersuite_info->max_minor_ver < opt.min_version ) + { + mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" ); + ret = 2; + goto usage; + } + + /* If we select a version that's not supported by + * this suite, then there will be no common ciphersuite... */ + if( opt.max_version == -1 || + opt.max_version > ciphersuite_info->max_minor_ver ) + { + opt.max_version = ciphersuite_info->max_minor_ver; + } + if( opt.min_version < ciphersuite_info->min_minor_ver ) + { + opt.min_version = ciphersuite_info->min_minor_ver; + /* DTLS starts with TLS 1.1 */ + if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + opt.min_version < MBEDTLS_SSL_MINOR_VERSION_2 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + } + + /* Enable RC4 if needed and not explicitly disabled */ + if( ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + { + if( opt.arc4 == MBEDTLS_SSL_ARC4_DISABLED ) + { + mbedtls_printf("forced RC4 ciphersuite with RC4 disabled\n"); + ret = 2; + goto usage; + } + + opt.arc4 = MBEDTLS_SSL_ARC4_ENABLED; + } + } + + if( opt.version_suites != NULL ) + { + const char *name[4] = { 0 }; + + /* Parse 4-element coma-separated list */ + for( i = 0, p = (char *) opt.version_suites; + i < 4 && *p != '\0'; + i++ ) + { + name[i] = p; + + /* Terminate the current string and move on to next one */ + while( *p != ',' && *p != '\0' ) + p++; + if( *p == ',' ) + *p++ = '\0'; + } + + if( i != 4 ) + { + mbedtls_printf( "too few values for version_suites\n" ); + ret = 1; + goto exit; + } + + memset( version_suites, 0, sizeof( version_suites ) ); + + /* Get the suites identifiers from their name */ + for( i = 0; i < 4; i++ ) + { + version_suites[i][0] = mbedtls_ssl_get_ciphersuite_id( name[i] ); + + if( version_suites[i][0] == 0 ) + { + mbedtls_printf( "unknown ciphersuite: '%s'\n", name[i] ); + ret = 2; + goto usage; + } + } + } + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + /* + * Unhexify the pre-shared key and parse the list if any given + */ + if( unhexify( psk, opt.psk, &psk_len ) != 0 ) + { + mbedtls_printf( "pre-shared key not valid hex\n" ); + goto exit; + } + + if( opt.psk_list != NULL ) + { + if( ( psk_info = psk_parse( opt.psk_list ) ) == NULL ) + { + mbedtls_printf( "psk_list invalid" ); + goto exit; + } + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_ECP_C) + if( opt.curves != NULL ) + { + p = (char *) opt.curves; + i = 0; + + if( strcmp( p, "none" ) == 0 ) + { + curve_list[0] = MBEDTLS_ECP_DP_NONE; + } + else if( strcmp( p, "default" ) != 0 ) + { + /* Leave room for a final NULL in curve list */ + while( i < CURVE_LIST_SIZE - 1 && *p != '\0' ) + { + q = p; + + /* Terminate the current string */ + while( *p != ',' && *p != '\0' ) + p++; + if( *p == ',' ) + *p++ = '\0'; + + if( ( curve_cur = mbedtls_ecp_curve_info_from_name( q ) ) != NULL ) + { + curve_list[i++] = curve_cur->grp_id; + } + else + { + mbedtls_printf( "unknown curve %s\n", q ); + mbedtls_printf( "supported curves: " ); + for( curve_cur = mbedtls_ecp_curve_list(); + curve_cur->grp_id != MBEDTLS_ECP_DP_NONE; + curve_cur++ ) + { + mbedtls_printf( "%s ", curve_cur->name ); + } + mbedtls_printf( "\n" ); + goto exit; + } + } + + mbedtls_printf("Number of curves: %d\n", i ); + + if( i == CURVE_LIST_SIZE - 1 && *p != '\0' ) + { + mbedtls_printf( "curves list too long, maximum %d", + CURVE_LIST_SIZE - 1 ); + goto exit; + } + + curve_list[i] = MBEDTLS_ECP_DP_NONE; + } + } +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_SSL_ALPN) + if( opt.alpn_string != NULL ) + { + p = (char *) opt.alpn_string; + i = 0; + + /* Leave room for a final NULL in alpn_list */ + while( i < ALPN_LIST_SIZE - 1 && *p != '\0' ) + { + alpn_list[i++] = p; + + /* Terminate the current string and move on to next one */ + while( *p != ',' && *p != '\0' ) + p++; + if( *p == ',' ) + *p++ = '\0'; + } + } +#endif /* MBEDTLS_SSL_ALPN */ + + /* + * 0. Initialize the RNG and the session data + */ + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + mbedtls_entropy_init( &entropy ); + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, + &entropy, (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", + -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * 1.1. Load the trusted CA + */ + mbedtls_printf( " . Loading the CA root certificate ..." ); + fflush( stdout ); + + if( strcmp( opt.ca_path, "none" ) == 0 || + strcmp( opt.ca_file, "none" ) == 0 ) + { + ret = 0; + } + else +#if defined(MBEDTLS_FS_IO) + if( strlen( opt.ca_path ) ) + ret = mbedtls_x509_crt_parse_path( &cacert, opt.ca_path ); + else if( strlen( opt.ca_file ) ) + ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file ); + else +#endif +#if defined(MBEDTLS_CERTS_C) + { +#if defined(MBEDTLS_PEM_PARSE_C) + for( i = 0; mbedtls_test_cas[i] != NULL; i++ ) + { + ret = mbedtls_x509_crt_parse( &cacert, + (const unsigned char *) mbedtls_test_cas[i], + mbedtls_test_cas_len[i] ); + if( ret != 0 ) + break; + } + if( ret == 0 ) +#endif /* MBEDTLS_PEM_PARSE_C */ + for( i = 0; mbedtls_test_cas_der[i] != NULL; i++ ) + { + ret = mbedtls_x509_crt_parse_der( &cacert, + (const unsigned char *) mbedtls_test_cas_der[i], + mbedtls_test_cas_der_len[i] ); + if( ret != 0 ) + break; + } + } +#else + { + ret = 1; + mbedtls_printf( "MBEDTLS_CERTS_C not defined." ); + } +#endif /* MBEDTLS_CERTS_C */ + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret ); + goto exit; + } + + mbedtls_printf( " ok (%d skipped)\n", ret ); + + /* + * 1.2. Load own certificate and private key + */ + mbedtls_printf( " . Loading the server cert. and key..." ); + fflush( stdout ); + +#if defined(MBEDTLS_FS_IO) + if( strlen( opt.crt_file ) && strcmp( opt.crt_file, "none" ) != 0 ) + { + key_cert_init++; + if( ( ret = mbedtls_x509_crt_parse_file( &srvcert, opt.crt_file ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file returned -0x%x\n\n", + -ret ); + goto exit; + } + } + if( strlen( opt.key_file ) && strcmp( opt.key_file, "none" ) != 0 ) + { + key_cert_init++; + if( ( ret = mbedtls_pk_parse_keyfile( &pkey, opt.key_file, "" ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned -0x%x\n\n", -ret ); + goto exit; + } + } + if( key_cert_init == 1 ) + { + mbedtls_printf( " failed\n ! crt_file without key_file or vice-versa\n\n" ); + goto exit; + } + + if( strlen( opt.crt_file2 ) && strcmp( opt.crt_file2, "none" ) != 0 ) + { + key_cert_init2++; + if( ( ret = mbedtls_x509_crt_parse_file( &srvcert2, opt.crt_file2 ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file(2) returned -0x%x\n\n", + -ret ); + goto exit; + } + } + if( strlen( opt.key_file2 ) && strcmp( opt.key_file2, "none" ) != 0 ) + { + key_cert_init2++; + if( ( ret = mbedtls_pk_parse_keyfile( &pkey2, opt.key_file2, "" ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile(2) returned -0x%x\n\n", + -ret ); + goto exit; + } + } + if( key_cert_init2 == 1 ) + { + mbedtls_printf( " failed\n ! crt_file2 without key_file2 or vice-versa\n\n" ); + goto exit; + } +#endif + if( key_cert_init == 0 && + strcmp( opt.crt_file, "none" ) != 0 && + strcmp( opt.key_file, "none" ) != 0 && + key_cert_init2 == 0 && + strcmp( opt.crt_file2, "none" ) != 0 && + strcmp( opt.key_file2, "none" ) != 0 ) + { +#if !defined(MBEDTLS_CERTS_C) + mbedtls_printf( "Not certificated or key provided, and \nMBEDTLS_CERTS_C not defined!\n" ); + goto exit; +#else +#if defined(MBEDTLS_RSA_C) + if( ( ret = mbedtls_x509_crt_parse( &srvcert, + (const unsigned char *) mbedtls_test_srv_crt_rsa, + mbedtls_test_srv_crt_rsa_len ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", + -ret ); + goto exit; + } + if( ( ret = mbedtls_pk_parse_key( &pkey, + (const unsigned char *) mbedtls_test_srv_key_rsa, + mbedtls_test_srv_key_rsa_len, NULL, 0 ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n", + -ret ); + goto exit; + } + key_cert_init = 2; +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) + if( ( ret = mbedtls_x509_crt_parse( &srvcert2, + (const unsigned char *) mbedtls_test_srv_crt_ec, + mbedtls_test_srv_crt_ec_len ) ) != 0 ) + { + mbedtls_printf( " failed\n ! x509_crt_parse2 returned -0x%x\n\n", + -ret ); + goto exit; + } + if( ( ret = mbedtls_pk_parse_key( &pkey2, + (const unsigned char *) mbedtls_test_srv_key_ec, + mbedtls_test_srv_key_ec_len, NULL, 0 ) ) != 0 ) + { + mbedtls_printf( " failed\n ! pk_parse_key2 returned -0x%x\n\n", + -ret ); + goto exit; + } + key_cert_init2 = 2; +#endif /* MBEDTLS_ECDSA_C */ +#endif /* MBEDTLS_CERTS_C */ + } + + mbedtls_printf( " ok\n" ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO) + if( opt.dhm_file != NULL ) + { + mbedtls_printf( " . Loading DHM parameters..." ); + fflush( stdout ); + + if( ( ret = mbedtls_dhm_parse_dhmfile( &dhm, opt.dhm_file ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_dhm_parse_dhmfile returned -0x%04X\n\n", + -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } +#endif + +#if defined(SNI_OPTION) + if( opt.sni != NULL ) + { + mbedtls_printf( " . Setting up SNI information..." ); + fflush( stdout ); + + if( ( sni_info = sni_parse( opt.sni ) ) == NULL ) + { + mbedtls_printf( " failed\n" ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } +#endif /* SNI_OPTION */ + + /* + * 2. Setup the listening TCP socket + */ + mbedtls_printf( " . Bind on %s://%s:%s/ ...", + opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ? "tcp" : "udp", + opt.server_addr ? opt.server_addr : "*", + opt.server_port ); + fflush( stdout ); + + if( ( ret = mbedtls_net_bind( &listen_fd, opt.server_addr, opt.server_port, + opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ? + MBEDTLS_NET_PROTO_TCP : MBEDTLS_NET_PROTO_UDP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_bind returned -0x%x\n\n", -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 3. Setup stuff + */ + mbedtls_printf( " . Setting up the SSL/TLS structure..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ssl_config_defaults( &conf, + MBEDTLS_SSL_IS_SERVER, + opt.transport, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret ); + goto exit; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* The default algorithms profile disables SHA-1, but our tests still + rely on it heavily. Hence we allow it here. A real-world server + should use the default profile unless there is a good reason not to. */ + if( opt.allow_sha1 > 0 ) + { + crt_profile_for_test.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ); + mbedtls_ssl_conf_cert_profile( &conf, &crt_profile_for_test ); + mbedtls_ssl_conf_sig_hashes( &conf, ssl_sig_hashes_for_test ); + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( opt.auth_mode != DFL_AUTH_MODE ) + mbedtls_ssl_conf_authmode( &conf, opt.auth_mode ); + + if( opt.cert_req_ca_list != DFL_CERT_REQ_CA_LIST ) + mbedtls_ssl_conf_cert_req_ca_list( &conf, opt.cert_req_ca_list ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( opt.hs_to_min != DFL_HS_TO_MIN || opt.hs_to_max != DFL_HS_TO_MAX ) + mbedtls_ssl_conf_handshake_timeout( &conf, opt.hs_to_min, opt.hs_to_max ); + + if( opt.dgram_packing != DFL_DGRAM_PACKING ) + mbedtls_ssl_set_datagram_packing( &ssl, opt.dgram_packing ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( ( ret = mbedtls_ssl_conf_max_frag_len( &conf, opt.mfl_code ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_max_frag_len returned %d\n\n", ret ); + goto exit; + }; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + if( opt.trunc_hmac != DFL_TRUNC_HMAC ) + mbedtls_ssl_conf_truncated_hmac( &conf, opt.trunc_hmac ); +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( opt.extended_ms != DFL_EXTENDED_MS ) + mbedtls_ssl_conf_extended_master_secret( &conf, opt.extended_ms ); +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( opt.etm != DFL_ETM ) + mbedtls_ssl_conf_encrypt_then_mac( &conf, opt.etm ); +#endif + +#if defined(MBEDTLS_SSL_ALPN) + if( opt.alpn_string != NULL ) + if( ( ret = mbedtls_ssl_conf_alpn_protocols( &conf, alpn_list ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_alpn_protocols returned %d\n\n", ret ); + goto exit; + } +#endif + + mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); + mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); + +#if defined(MBEDTLS_SSL_CACHE_C) + if( opt.cache_max != -1 ) + mbedtls_ssl_cache_set_max_entries( &cache, opt.cache_max ); + + if( opt.cache_timeout != -1 ) + mbedtls_ssl_cache_set_timeout( &cache, opt.cache_timeout ); + + mbedtls_ssl_conf_session_cache( &conf, &cache, + mbedtls_ssl_cache_get, + mbedtls_ssl_cache_set ); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( opt.tickets == MBEDTLS_SSL_SESSION_TICKETS_ENABLED ) + { + if( ( ret = mbedtls_ssl_ticket_setup( &ticket_ctx, + mbedtls_ctr_drbg_random, &ctr_drbg, + MBEDTLS_CIPHER_AES_256_GCM, + opt.ticket_timeout ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_ticket_setup returned %d\n\n", ret ); + goto exit; + } + + mbedtls_ssl_conf_session_tickets_cb( &conf, + mbedtls_ssl_ticket_write, + mbedtls_ssl_ticket_parse, + &ticket_ctx ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { +#if defined(MBEDTLS_SSL_COOKIE_C) + if( opt.cookies > 0 ) + { + if( ( ret = mbedtls_ssl_cookie_setup( &cookie_ctx, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_cookie_setup returned %d\n\n", ret ); + goto exit; + } + + mbedtls_ssl_conf_dtls_cookies( &conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, + &cookie_ctx ); + } + else +#endif /* MBEDTLS_SSL_COOKIE_C */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( opt.cookies == 0 ) + { + mbedtls_ssl_conf_dtls_cookies( &conf, NULL, NULL, NULL ); + } + else +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + { + ; /* Nothing to do */ + } + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( opt.anti_replay != DFL_ANTI_REPLAY ) + mbedtls_ssl_conf_dtls_anti_replay( &conf, opt.anti_replay ); +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + if( opt.badmac_limit != DFL_BADMAC_LIMIT ) + mbedtls_ssl_conf_dtls_badmac_limit( &conf, opt.badmac_limit ); +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER ) + mbedtls_ssl_conf_ciphersuites( &conf, opt.force_ciphersuite ); + +#if defined(MBEDTLS_ARC4_C) + if( opt.arc4 != DFL_ARC4 ) + mbedtls_ssl_conf_arc4_support( &conf, opt.arc4 ); +#endif + + if( opt.version_suites != NULL ) + { + mbedtls_ssl_conf_ciphersuites_for_version( &conf, version_suites[0], + MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_0 ); + mbedtls_ssl_conf_ciphersuites_for_version( &conf, version_suites[1], + MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_1 ); + mbedtls_ssl_conf_ciphersuites_for_version( &conf, version_suites[2], + MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_2 ); + mbedtls_ssl_conf_ciphersuites_for_version( &conf, version_suites[3], + MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_3 ); + } + + if( opt.allow_legacy != DFL_ALLOW_LEGACY ) + mbedtls_ssl_conf_legacy_renegotiation( &conf, opt.allow_legacy ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + mbedtls_ssl_conf_renegotiation( &conf, opt.renegotiation ); + + if( opt.renego_delay != DFL_RENEGO_DELAY ) + mbedtls_ssl_conf_renegotiation_enforced( &conf, opt.renego_delay ); + + if( opt.renego_period != DFL_RENEGO_PERIOD ) + { + PUT_UINT64_BE( renego_period, opt.renego_period, 0 ); + mbedtls_ssl_conf_renegotiation_period( &conf, renego_period ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( strcmp( opt.ca_path, "none" ) != 0 && + strcmp( opt.ca_file, "none" ) != 0 ) + { + mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); + } + if( key_cert_init ) + { + mbedtls_pk_context *pk = &pkey; +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( opt.async_private_delay1 >= 0 ) + { + ret = ssl_async_set_key( &ssl_async_keys, &srvcert, pk, 0, + opt.async_private_delay1 ); + if( ret < 0 ) + { + mbedtls_printf( " Test error: ssl_async_set_key failed (%d)\n", + ret ); + goto exit; + } + pk = NULL; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, pk ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); + goto exit; + } + } + if( key_cert_init2 ) + { + mbedtls_pk_context *pk = &pkey2; +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( opt.async_private_delay2 >= 0 ) + { + ret = ssl_async_set_key( &ssl_async_keys, &srvcert2, pk, 0, + opt.async_private_delay2 ); + if( ret < 0 ) + { + mbedtls_printf( " Test error: ssl_async_set_key failed (%d)\n", + ret ); + goto exit; + } + pk = NULL; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert2, pk ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); + goto exit; + } + } + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( opt.async_operations[0] != '-' ) + { + mbedtls_ssl_async_sign_t *sign = NULL; + mbedtls_ssl_async_decrypt_t *decrypt = NULL; + const char *r; + for( r = opt.async_operations; *r; r++ ) + { + switch( *r ) + { + case 'd': + decrypt = ssl_async_decrypt; + break; + case 's': + sign = ssl_async_sign; + break; + } + } + ssl_async_keys.inject_error = ( opt.async_private_error < 0 ? + - opt.async_private_error : + opt.async_private_error ); + ssl_async_keys.f_rng = mbedtls_ctr_drbg_random; + ssl_async_keys.p_rng = &ctr_drbg; + mbedtls_ssl_conf_async_private_cb( &conf, + sign, + decrypt, + ssl_async_resume, + ssl_async_cancel, + &ssl_async_keys ); + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(SNI_OPTION) + if( opt.sni != NULL ) + { + mbedtls_ssl_conf_sni( &conf, sni_callback, sni_info ); +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( opt.async_private_delay2 >= 0 ) + { + sni_entry *cur; + for( cur = sni_info; cur != NULL; cur = cur->next ) + { + ret = ssl_async_set_key( &ssl_async_keys, + cur->cert, cur->key, 1, + opt.async_private_delay2 ); + if( ret < 0 ) + { + mbedtls_printf( " Test error: ssl_async_set_key failed (%d)\n", + ret ); + goto exit; + } + cur->key = NULL; + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + } +#endif + +#if defined(MBEDTLS_ECP_C) + if( opt.curves != NULL && + strcmp( opt.curves, "default" ) != 0 ) + { + mbedtls_ssl_conf_curves( &conf, curve_list ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( strlen( opt.psk ) != 0 && strlen( opt.psk_identity ) != 0 ) + { + ret = mbedtls_ssl_conf_psk( &conf, psk, psk_len, + (const unsigned char *) opt.psk_identity, + strlen( opt.psk_identity ) ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n mbedtls_ssl_conf_psk returned -0x%04X\n\n", - ret ); + goto exit; + } + } + + if( opt.psk_list != NULL ) + mbedtls_ssl_conf_psk_cb( &conf, psk_callback, psk_info ); +#endif + +#if defined(MBEDTLS_DHM_C) + /* + * Use different group than default DHM group + */ +#if defined(MBEDTLS_FS_IO) + if( opt.dhm_file != NULL ) + ret = mbedtls_ssl_conf_dh_param_ctx( &conf, &dhm ); +#endif + if( ret != 0 ) + { + mbedtls_printf( " failed\n mbedtls_ssl_conf_dh_param returned -0x%04X\n\n", - ret ); + goto exit; + } +#endif + + if( opt.min_version != DFL_MIN_VERSION ) + mbedtls_ssl_conf_min_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, opt.min_version ); + + if( opt.max_version != DFL_MIN_VERSION ) + mbedtls_ssl_conf_max_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, opt.max_version ); + + if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret ); + goto exit; + } + + if( opt.nbio == 2 ) + mbedtls_ssl_set_bio( &ssl, &client_fd, my_send, my_recv, NULL ); + else + mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, + opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( opt.dtls_mtu != DFL_DTLS_MTU ) + mbedtls_ssl_set_mtu( &ssl, opt.dtls_mtu ); +#endif + +#if defined(MBEDTLS_TIMING_C) + mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, + mbedtls_timing_get_delay ); +#endif + + mbedtls_printf( " ok\n" ); + +reset: +#if !defined(_WIN32) + if( received_sigterm ) + { + mbedtls_printf( " interrupted by SIGTERM (not in net_accept())\n" ); + if( ret == MBEDTLS_ERR_NET_INVALID_CONTEXT ) + ret = 0; + + goto exit; + } +#endif + + if( ret == MBEDTLS_ERR_SSL_CLIENT_RECONNECT ) + { + mbedtls_printf( " ! Client initiated reconnection from same port\n" ); + goto handshake; + } + +#ifdef MBEDTLS_ERROR_C + if( ret != 0 ) + { + char error_buf[100]; + mbedtls_strerror( ret, error_buf, 100 ); + mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf ); + } +#endif + + mbedtls_net_free( &client_fd ); + + mbedtls_ssl_session_reset( &ssl ); + + /* + * 3. Wait until a client connects + */ + mbedtls_printf( " . Waiting for a remote connection ..." ); + fflush( stdout ); + + if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, + client_ip, sizeof( client_ip ), &cliip_len ) ) != 0 ) + { +#if !defined(_WIN32) + if( received_sigterm ) + { + mbedtls_printf( " interrupted by SIGTERM (in net_accept())\n" ); + if( ret == MBEDTLS_ERR_NET_ACCEPT_FAILED ) + ret = 0; + + goto exit; + } +#endif + + mbedtls_printf( " failed\n ! mbedtls_net_accept returned -0x%x\n\n", -ret ); + goto exit; + } + + if( opt.nbio > 0 ) + ret = mbedtls_net_set_nonblock( &client_fd ); + else + ret = mbedtls_net_set_block( &client_fd ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret ); + goto exit; + } + + mbedtls_ssl_conf_read_timeout( &conf, opt.read_timeout ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ( ret = mbedtls_ssl_set_client_transport_id( &ssl, + client_ip, cliip_len ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", + -ret ); + goto exit; + } + } +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( opt.ecjpake_pw != DFL_ECJPAKE_PW ) + { + if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl, + (const unsigned char *) opt.ecjpake_pw, + strlen( opt.ecjpake_pw ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", ret ); + goto exit; + } + } +#endif + + mbedtls_printf( " ok\n" ); + + /* + * 4. Handshake + */ +handshake: + mbedtls_printf( " . Performing the SSL/TLS handshake..." ); + fflush( stdout ); + + while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS && + ssl_async_keys.inject_error == SSL_ASYNC_INJECT_ERROR_CANCEL ) + { + mbedtls_printf( " cancelling on injected error\n" ); + break; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( ! mbedtls_status_is_ssl_in_progress( ret ) ) + break; + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + ret = idle( &client_fd, &timer, ret ); +#else + ret = idle( &client_fd, ret ); +#endif + if( ret != 0 ) + goto reset; + } + } + + if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) + { + mbedtls_printf( " hello verification requested\n" ); + ret = 0; + goto reset; + } + else if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) + { + char vrfy_buf[512]; + flags = mbedtls_ssl_get_verify_result( &ssl ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + + mbedtls_printf( "%s\n", vrfy_buf ); + } +#endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( opt.async_private_error < 0 ) + /* Injected error only the first time round, to test reset */ + ssl_async_keys.inject_error = SSL_ASYNC_INJECT_ERROR_NONE; +#endif + goto reset; + } + else /* ret == 0 */ + { + mbedtls_printf( " ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n", + mbedtls_ssl_get_version( &ssl ), mbedtls_ssl_get_ciphersuite( &ssl ) ); + } + + if( ( ret = mbedtls_ssl_get_record_expansion( &ssl ) ) >= 0 ) + mbedtls_printf( " [ Record expansion is %d ]\n", ret ); + else + mbedtls_printf( " [ Record expansion is unknown (compression) ]\n" ); + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + mbedtls_printf( " [ Maximum fragment length is %u ]\n", + (unsigned int) mbedtls_ssl_get_max_frag_len( &ssl ) ); +#endif + +#if defined(MBEDTLS_SSL_ALPN) + if( opt.alpn_string != NULL ) + { + const char *alp = mbedtls_ssl_get_alpn_protocol( &ssl ); + mbedtls_printf( " [ Application Layer Protocol is %s ]\n", + alp ? alp : "(none)" ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * 5. Verify the client certificate + */ + mbedtls_printf( " . Verifying peer X.509 certificate..." ); + + if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 ) + { + char vrfy_buf[512]; + + mbedtls_printf( " failed\n" ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + + mbedtls_printf( "%s\n", vrfy_buf ); + } + else + mbedtls_printf( " ok\n" ); + + if( mbedtls_ssl_get_peer_cert( &ssl ) != NULL ) + { + char crt_buf[512]; + + mbedtls_printf( " . Peer certificate information ...\n" ); + mbedtls_x509_crt_info( crt_buf, sizeof( crt_buf ), " ", + mbedtls_ssl_get_peer_cert( &ssl ) ); + mbedtls_printf( "%s\n", crt_buf ); + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( opt.exchanges == 0 ) + goto close_notify; + + exchanges_left = opt.exchanges; +data_exchange: + /* + * 6. Read the HTTP Request + */ + mbedtls_printf( " < Read from client:" ); + fflush( stdout ); + + /* + * TLS and DTLS need different reading styles (stream vs datagram) + */ + if( opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ) + { + do + { + int terminated = 0; + len = opt.buffer_size - 1; + memset( buf, 0, opt.buffer_size ); + ret = mbedtls_ssl_read( &ssl, buf, len ); + + if( mbedtls_status_is_ssl_in_progress( ret ) ) + { + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &client_fd, &timer, ret ); +#else + idle( &client_fd, ret ); +#endif + } + + continue; + } + + if( ret <= 0 ) + { + switch( ret ) + { + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf( " connection was closed gracefully\n" ); + goto close_notify; + + case 0: + case MBEDTLS_ERR_NET_CONN_RESET: + mbedtls_printf( " connection was reset by peer\n" ); + ret = MBEDTLS_ERR_NET_CONN_RESET; + goto reset; + + default: + mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", -ret ); + goto reset; + } + } + + if( mbedtls_ssl_get_bytes_avail( &ssl ) == 0 ) + { + len = ret; + buf[len] = '\0'; + mbedtls_printf( " %d bytes read\n\n%s\n", len, (char *) buf ); + + /* End of message should be detected according to the syntax of the + * application protocol (eg HTTP), just use a dummy test here. */ + if( buf[len - 1] == '\n' ) + terminated = 1; + } + else + { + int extra_len, ori_len; + unsigned char *larger_buf; + + ori_len = ret; + extra_len = (int) mbedtls_ssl_get_bytes_avail( &ssl ); + + larger_buf = mbedtls_calloc( 1, ori_len + extra_len + 1 ); + if( larger_buf == NULL ) + { + mbedtls_printf( " ! memory allocation failed\n" ); + ret = 1; + goto reset; + } + + memset( larger_buf, 0, ori_len + extra_len ); + memcpy( larger_buf, buf, ori_len ); + + /* This read should never fail and get the whole cached data */ + ret = mbedtls_ssl_read( &ssl, larger_buf + ori_len, extra_len ); + if( ret != extra_len || + mbedtls_ssl_get_bytes_avail( &ssl ) != 0 ) + { + mbedtls_printf( " ! mbedtls_ssl_read failed on cached data\n" ); + ret = 1; + goto reset; + } + + larger_buf[ori_len + extra_len] = '\0'; + mbedtls_printf( " %u bytes read (%u + %u)\n\n%s\n", + ori_len + extra_len, ori_len, extra_len, + (char *) larger_buf ); + + /* End of message should be detected according to the syntax of the + * application protocol (eg HTTP), just use a dummy test here. */ + if( larger_buf[ori_len + extra_len - 1] == '\n' ) + terminated = 1; + + mbedtls_free( larger_buf ); + } + + if( terminated ) + { + ret = 0; + break; + } + } + while( 1 ); + } + else /* Not stream, so datagram */ + { + len = opt.buffer_size - 1; + memset( buf, 0, opt.buffer_size ); + + do + { + /* Without the call to `mbedtls_ssl_check_pending`, it might + * happen that the client sends application data in the same + * datagram as the Finished message concluding the handshake. + * In this case, the application data would be ready to be + * processed while the underlying transport wouldn't signal + * any further incoming data. + * + * See the test 'Event-driven I/O: session-id resume, UDP packing' + * in tests/ssl-opt.sh. + */ + + /* For event-driven IO, wait for socket to become available */ + if( mbedtls_ssl_check_pending( &ssl ) == 0 && + opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &client_fd, &timer, MBEDTLS_ERR_SSL_WANT_READ ); +#else + idle( &client_fd, MBEDTLS_ERR_SSL_WANT_READ ); +#endif + } + + ret = mbedtls_ssl_read( &ssl, buf, len ); + + /* Note that even if `mbedtls_ssl_check_pending` returns true, + * it can happen that the subsequent call to `mbedtls_ssl_read` + * returns `MBEDTLS_ERR_SSL_WANT_READ`, because the pending messages + * might be discarded (e.g. because they are retransmissions). */ + } + while( mbedtls_status_is_ssl_in_progress( ret ) ); + + if( ret <= 0 ) + { + switch( ret ) + { + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf( " connection was closed gracefully\n" ); + ret = 0; + goto close_notify; + + default: + mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", -ret ); + goto reset; + } + } + + len = ret; + buf[len] = '\0'; + mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); + ret = 0; + } + + /* + * 7a. Request renegotiation while client is waiting for input from us. + * (only on the first exchange, to be able to test retransmission) + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( opt.renegotiate && exchanges_left == opt.exchanges ) + { + mbedtls_printf( " . Requestion renegotiation..." ); + fflush( stdout ); + + while( ( ret = mbedtls_ssl_renegotiate( &ssl ) ) != 0 ) + { + if( ! mbedtls_status_is_ssl_in_progress( ret ) ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", ret ); + goto reset; + } + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &client_fd, &timer, ret ); +#else + idle( &client_fd, ret ); +#endif + } + } + + mbedtls_printf( " ok\n" ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* + * 7. Write the 200 Response + */ + mbedtls_printf( " > Write to client:" ); + fflush( stdout ); + + len = sprintf( (char *) buf, HTTP_RESPONSE, + mbedtls_ssl_get_ciphersuite( &ssl ) ); + + /* Add padding to the response to reach opt.response_size in length */ + if( opt.response_size != DFL_RESPONSE_SIZE && + len < opt.response_size ) + { + memset( buf + len, 'B', opt.response_size - len ); + len += opt.response_size - len; + } + + /* Truncate if response size is smaller than the "natural" size */ + if( opt.response_size != DFL_RESPONSE_SIZE && + len > opt.response_size ) + { + len = opt.response_size; + + /* Still end with \r\n unless that's really not possible */ + if( len >= 2 ) buf[len - 2] = '\r'; + if( len >= 1 ) buf[len - 1] = '\n'; + } + + if( opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ) + { + for( written = 0, frags = 0; written < len; written += ret, frags++ ) + { + while( ( ret = mbedtls_ssl_write( &ssl, buf + written, len - written ) ) + <= 0 ) + { + if( ret == MBEDTLS_ERR_NET_CONN_RESET ) + { + mbedtls_printf( " failed\n ! peer closed the connection\n\n" ); + goto reset; + } + + if( ! mbedtls_status_is_ssl_in_progress( ret ) ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); + goto reset; + } + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &client_fd, &timer, ret ); +#else + idle( &client_fd, ret ); +#endif + } + } + } + } + else /* Not stream, so datagram */ + { + while( 1 ) + { + ret = mbedtls_ssl_write( &ssl, buf, len ); + + if( ! mbedtls_status_is_ssl_in_progress( ret ) ) + break; + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &client_fd, &timer, ret ); +#else + idle( &client_fd, ret ); +#endif + } + } + + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); + goto reset; + } + + frags = 1; + written = ret; + } + + buf[written] = '\0'; + mbedtls_printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (char *) buf ); + ret = 0; + + /* + * 7b. Continue doing data exchanges? + */ + if( --exchanges_left > 0 ) + goto data_exchange; + + /* + * 8. Done, cleanly close the connection + */ +close_notify: + mbedtls_printf( " . Closing the connection..." ); + + /* No error checking, the connection might be closed already */ + do ret = mbedtls_ssl_close_notify( &ssl ); + while( ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + ret = 0; + + mbedtls_printf( " done\n" ); + + goto reset; + + /* + * Cleanup and exit + */ +exit: +#ifdef MBEDTLS_ERROR_C + if( ret != 0 ) + { + char error_buf[100]; + mbedtls_strerror( ret, error_buf, 100 ); + mbedtls_printf("Last error was: -0x%X - %s\n\n", -ret, error_buf ); + } +#endif + + mbedtls_printf( " . Cleaning up..." ); + fflush( stdout ); + + mbedtls_net_free( &client_fd ); + mbedtls_net_free( &listen_fd ); + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO) + mbedtls_dhm_free( &dhm ); +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_free( &cacert ); + mbedtls_x509_crt_free( &srvcert ); + mbedtls_pk_free( &pkey ); + mbedtls_x509_crt_free( &srvcert2 ); + mbedtls_pk_free( &pkey2 ); +#endif +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + for( i = 0; (size_t) i < ssl_async_keys.slots_used; i++ ) + { + if( ssl_async_keys.slots[i].pk_owned ) + { + mbedtls_pk_free( ssl_async_keys.slots[i].pk ); + mbedtls_free( ssl_async_keys.slots[i].pk ); + ssl_async_keys.slots[i].pk = NULL; + } + } +#endif +#if defined(SNI_OPTION) + sni_free( sni_info ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + psk_free( psk_info ); +#endif +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO) + mbedtls_dhm_free( &dhm ); +#endif + + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_free( &cache ); +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_ticket_free( &ticket_ctx ); +#endif +#if defined(MBEDTLS_SSL_COOKIE_C) + mbedtls_ssl_cookie_free( &cookie_ctx ); +#endif + + mbedtls_free( buf ); + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_memory_buffer_alloc_status(); +#endif + mbedtls_memory_buffer_alloc_free(); +#endif + + mbedtls_printf( " done.\n" ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + // Shell can not handle large exit numbers -> 1 for errors + if( ret < 0 ) + ret = 1; + + mbedtls_exit( ret ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C && + MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C && MBEDTLS_RSA_C && + MBEDTLS_CTR_DRBG_C */ diff --git a/external/mbedtls/programs/util/CMakeLists.txt b/external/mbedtls/programs/util/CMakeLists.txt new file mode 100644 index 0000000..f9b6604 --- /dev/null +++ b/external/mbedtls/programs/util/CMakeLists.txt @@ -0,0 +1,13 @@ +set(libs + mbedtls +) + +add_executable(strerror strerror.c) +target_link_libraries(strerror ${libs}) + +add_executable(pem2der pem2der.c) +target_link_libraries(pem2der ${libs}) + +install(TARGETS strerror pem2der + DESTINATION "bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/external/mbedtls/programs/util/pem2der.c b/external/mbedtls/programs/util/pem2der.c new file mode 100644 index 0000000..153b4fc --- /dev/null +++ b/external/mbedtls/programs/util/pem2der.c @@ -0,0 +1,320 @@ +/* + * Convert PEM to DER + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_FS_IO) +#include "mbedtls/error.h" +#include "mbedtls/base64.h" + +#include +#include +#include +#endif + +#define DFL_FILENAME "file.pem" +#define DFL_OUTPUT_FILENAME "file.der" + +#define USAGE \ + "\n usage: pem2der param=<>...\n" \ + "\n acceptable parameters:\n" \ + " filename=%%s default: file.pem\n" \ + " output_file=%%s default: file.der\n" \ + "\n" + +#if !defined(MBEDTLS_BASE64_C) || !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BASE64_C and/or MBEDTLS_FS_IO not defined.\n"); + mbedtls_exit( 0 ); +} +#else + + +/* + * global options + */ +struct options +{ + const char *filename; /* filename of the input file */ + const char *output_file; /* where to store the output */ +} opt; + +int convert_pem_to_der( const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ) +{ + int ret; + const unsigned char *s1, *s2, *end = input + ilen; + size_t len = 0; + + s1 = (unsigned char *) strstr( (const char *) input, "-----BEGIN" ); + if( s1 == NULL ) + return( -1 ); + + s2 = (unsigned char *) strstr( (const char *) input, "-----END" ); + if( s2 == NULL ) + return( -1 ); + + s1 += 10; + while( s1 < end && *s1 != '-' ) + s1++; + while( s1 < end && *s1 == '-' ) + s1++; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + + if( s2 <= s1 || s2 > end ) + return( -1 ); + + ret = mbedtls_base64_decode( NULL, 0, &len, (const unsigned char *) s1, s2 - s1 ); + if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) + return( ret ); + + if( len > *olen ) + return( -1 ); + + if( ( ret = mbedtls_base64_decode( output, len, &len, (const unsigned char *) s1, + s2 - s1 ) ) != 0 ) + { + return( ret ); + } + + *olen = len; + + return( 0 ); +} + +/* + * Load all data from a file into a given buffer. + */ +static int load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( -1 ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( -1 ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( -1 ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + free( *buf ); + *buf = NULL; + return( -1 ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + return( 0 ); +} + +/* + * Write buffer to a file + */ +static int write_file( const char *path, unsigned char *buf, size_t n ) +{ + FILE *f; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( -1 ); + + if( fwrite( buf, 1, n, f ) != n ) + { + fclose( f ); + return( -1 ); + } + + fclose( f ); + return( 0 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + unsigned char *pem_buffer = NULL; + unsigned char der_buffer[4096]; + char buf[1024]; + size_t pem_size, der_size = sizeof(der_buffer); + int i; + char *p, *q; + + /* + * Set to sane values + */ + memset( buf, 0, sizeof(buf) ); + memset( der_buffer, 0, sizeof(der_buffer) ); + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + goto exit; + } + + opt.filename = DFL_FILENAME; + opt.output_file = DFL_OUTPUT_FILENAME; + + for( i = 1; i < argc; i++ ) + { + + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else if( strcmp( p, "output_file" ) == 0 ) + opt.output_file = q; + else + goto usage; + } + + /* + * 1.1. Load the PEM file + */ + mbedtls_printf( "\n . Loading the PEM file ..." ); + fflush( stdout ); + + ret = load_file( opt.filename, &pem_buffer, &pem_size ); + + if( ret != 0 ) + { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror( ret, buf, 1024 ); +#endif + mbedtls_printf( " failed\n ! load_file returned %d - %s\n\n", ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.2. Convert from PEM to DER + */ + mbedtls_printf( " . Converting from PEM to DER ..." ); + fflush( stdout ); + + if( ( ret = convert_pem_to_der( pem_buffer, pem_size, der_buffer, &der_size ) ) != 0 ) + { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror( ret, buf, 1024 ); +#endif + mbedtls_printf( " failed\n ! convert_pem_to_der %d - %s\n\n", ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.3. Write the DER file + */ + mbedtls_printf( " . Writing the DER file ..." ); + fflush( stdout ); + + ret = write_file( opt.output_file, der_buffer, der_size ); + + if( ret != 0 ) + { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror( ret, buf, 1024 ); +#endif + mbedtls_printf( " failed\n ! write_file returned %d - %s\n\n", ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + free( pem_buffer ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BASE64_C && MBEDTLS_FS_IO */ diff --git a/external/mbedtls/programs/util/strerror.c b/external/mbedtls/programs/util/strerror.c new file mode 100644 index 0000000..4ea9d32 --- /dev/null +++ b/external/mbedtls/programs/util/strerror.c @@ -0,0 +1,119 @@ +/* + * Translate error code to error string + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#endif + +#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) +#include "mbedtls/error.h" + +#include +#include +#include +#endif + +#define USAGE \ + "\n usage: strerror \n" \ + "\n where can be a decimal or hexadecimal (starts with 0x or -0x)\n" + +#if !defined(MBEDTLS_ERROR_C) && !defined(MBEDTLS_ERROR_STRERROR_DUMMY) +int main( void ) +{ + mbedtls_printf("MBEDTLS_ERROR_C and/or MBEDTLS_ERROR_STRERROR_DUMMY not defined.\n"); + mbedtls_exit( 0 ); +} +#else +int main( int argc, char *argv[] ) +{ + long int val; + char *end = argv[1]; + + if( argc != 2 ) + { + mbedtls_printf( USAGE ); + mbedtls_exit( 0 ); + } + + val = strtol( argv[1], &end, 10 ); + if( *end != '\0' ) + { + val = strtol( argv[1], &end, 16 ); + if( *end != '\0' ) + { + mbedtls_printf( USAGE ); + return( 0 ); + } + } + if( val > 0 ) + val = -val; + + if( val != 0 ) + { + char error_buf[200]; + mbedtls_strerror( val, error_buf, 200 ); + mbedtls_printf("Last error was: -0x%04x - %s\n\n", (int) -val, error_buf ); + } + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( val ); +} +#endif /* MBEDTLS_ERROR_C */ diff --git a/external/mbedtls/programs/wince_main.c b/external/mbedtls/programs/wince_main.c new file mode 100644 index 0000000..511542a --- /dev/null +++ b/external/mbedtls/programs/wince_main.c @@ -0,0 +1,70 @@ +/* + * Windows CE console application entry point + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if defined(_WIN32_WCE) + +#include + +extern int main( int, const char ** ); + +int _tmain( int argc, _TCHAR* targv[] ) +{ + char **argv; + int i; + + argv = ( char ** ) calloc( argc, sizeof( char * ) ); + + for ( i = 0; i < argc; i++ ) { + size_t len; + len = _tcslen( targv[i] ) + 1; + argv[i] = ( char * ) calloc( len, sizeof( char ) ); + wcstombs( argv[i], targv[i], len ); + } + + return main( argc, argv ); +} + +#endif /* defined(_WIN32_WCE) */ diff --git a/external/mbedtls/programs/x509/CMakeLists.txt b/external/mbedtls/programs/x509/CMakeLists.txt new file mode 100644 index 0000000..39b8b5b --- /dev/null +++ b/external/mbedtls/programs/x509/CMakeLists.txt @@ -0,0 +1,30 @@ +set(libs + mbedtls +) + +if(USE_PKCS11_HELPER_LIBRARY) + set(libs ${libs} pkcs11-helper) +endif(USE_PKCS11_HELPER_LIBRARY) + +if(ENABLE_ZLIB_SUPPORT) + set(libs ${libs} ${ZLIB_LIBRARIES}) +endif(ENABLE_ZLIB_SUPPORT) + +add_executable(cert_app cert_app.c) +target_link_libraries(cert_app ${libs}) + +add_executable(crl_app crl_app.c) +target_link_libraries(crl_app ${libs}) + +add_executable(req_app req_app.c) +target_link_libraries(req_app ${libs}) + +add_executable(cert_req cert_req.c) +target_link_libraries(cert_req ${libs}) + +add_executable(cert_write cert_write.c) +target_link_libraries(cert_write ${libs}) + +install(TARGETS cert_app crl_app req_app cert_req cert_write + DESTINATION "bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/external/mbedtls/programs/x509/cert_app.c b/external/mbedtls/programs/x509/cert_app.c new file mode 100644 index 0000000..022e2e3 --- /dev/null +++ b/external/mbedtls/programs/x509/cert_app.c @@ -0,0 +1,525 @@ +/* + * Certificate reading application + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_time time +#define mbedtls_time_t time_t +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \ + !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) || \ + !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or " + "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_FS_IO and/or " + "MBEDTLS_CTR_DRBG_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/ssl.h" +#include "mbedtls/x509.h" +#include "mbedtls/debug.h" + +#include +#include +#include + +#define MODE_NONE 0 +#define MODE_FILE 1 +#define MODE_SSL 2 + +#define DFL_MODE MODE_NONE +#define DFL_FILENAME "cert.crt" +#define DFL_CA_FILE "" +#define DFL_CRL_FILE "" +#define DFL_CA_PATH "" +#define DFL_SERVER_NAME "localhost" +#define DFL_SERVER_PORT "4433" +#define DFL_DEBUG_LEVEL 0 +#define DFL_PERMISSIVE 0 + +#define USAGE_IO \ + " ca_file=%%s The single file containing the top-level CA(s) you fully trust\n" \ + " default: \"\" (none)\n" \ + " crl_file=%%s The single CRL file you want to use\n" \ + " default: \"\" (none)\n" \ + " ca_path=%%s The path containing the top-level CA(s) you fully trust\n" \ + " default: \"\" (none) (overrides ca_file)\n" + +#define USAGE \ + "\n usage: cert_app param=<>...\n" \ + "\n acceptable parameters:\n" \ + " mode=file|ssl default: none\n" \ + " filename=%%s default: cert.crt\n" \ + USAGE_IO \ + " server_name=%%s default: localhost\n" \ + " server_port=%%d default: 4433\n" \ + " debug_level=%%d default: 0 (disabled)\n" \ + " permissive=%%d default: 0 (disabled)\n" \ + "\n" + + +/* + * global options + */ +struct options +{ + int mode; /* the mode to run the application in */ + const char *filename; /* filename of the certificate file */ + const char *ca_file; /* the file with the CA certificate(s) */ + const char *crl_file; /* the file with the CRL to use */ + const char *ca_path; /* the path with the CA certificate(s) reside */ + const char *server_name; /* hostname of the server (client only) */ + const char *server_port; /* port on which the ssl service runs */ + int debug_level; /* level of debugging */ + int permissive; /* permissive parsing */ +} opt; + +static void my_debug( void *ctx, int level, + const char *file, int line, + const char *str ) +{ + ((void) level); + + mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str ); + fflush( (FILE *) ctx ); +} + +static int my_verify( void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags ) +{ + char buf[1024]; + ((void) data); + + mbedtls_printf( "\nVerify requested for (Depth %d):\n", depth ); + mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); + mbedtls_printf( "%s", buf ); + + if ( ( *flags ) == 0 ) + mbedtls_printf( " This certificate has no flags\n" ); + else + { + mbedtls_x509_crt_verify_info( buf, sizeof( buf ), " ! ", *flags ); + mbedtls_printf( "%s\n", buf ); + } + + return( 0 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_net_context server_fd; + unsigned char buf[1024]; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_x509_crt cacert; + mbedtls_x509_crl cacrl; + int i, j; + uint32_t flags; + int verify = 0; + char *p, *q; + const char *pers = "cert_app"; + + /* + * Set to sane values + */ + mbedtls_net_init( &server_fd ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + mbedtls_ssl_init( &ssl ); + mbedtls_ssl_config_init( &conf ); + mbedtls_x509_crt_init( &cacert ); +#if defined(MBEDTLS_X509_CRL_PARSE_C) + mbedtls_x509_crl_init( &cacrl ); +#else + /* Zeroize structure as CRL parsing is not supported and we have to pass + it to the verify function */ + memset( &cacrl, 0, sizeof(mbedtls_x509_crl) ); +#endif + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + goto exit; + } + + opt.mode = DFL_MODE; + opt.filename = DFL_FILENAME; + opt.ca_file = DFL_CA_FILE; + opt.crl_file = DFL_CRL_FILE; + opt.ca_path = DFL_CA_PATH; + opt.server_name = DFL_SERVER_NAME; + opt.server_port = DFL_SERVER_PORT; + opt.debug_level = DFL_DEBUG_LEVEL; + opt.permissive = DFL_PERMISSIVE; + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + for( j = 0; p + j < q; j++ ) + { + if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' ) + argv[i][j] |= 0x20; + } + + if( strcmp( p, "mode" ) == 0 ) + { + if( strcmp( q, "file" ) == 0 ) + opt.mode = MODE_FILE; + else if( strcmp( q, "ssl" ) == 0 ) + opt.mode = MODE_SSL; + else + goto usage; + } + else if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else if( strcmp( p, "ca_file" ) == 0 ) + opt.ca_file = q; + else if( strcmp( p, "crl_file" ) == 0 ) + opt.crl_file = q; + else if( strcmp( p, "ca_path" ) == 0 ) + opt.ca_path = q; + else if( strcmp( p, "server_name" ) == 0 ) + opt.server_name = q; + else if( strcmp( p, "server_port" ) == 0 ) + opt.server_port = q; + else if( strcmp( p, "debug_level" ) == 0 ) + { + opt.debug_level = atoi( q ); + if( opt.debug_level < 0 || opt.debug_level > 65535 ) + goto usage; + } + else if( strcmp( p, "permissive" ) == 0 ) + { + opt.permissive = atoi( q ); + if( opt.permissive < 0 || opt.permissive > 1 ) + goto usage; + } + else + goto usage; + } + + /* + * 1.1. Load the trusted CA + */ + mbedtls_printf( " . Loading the CA root certificate ..." ); + fflush( stdout ); + + if( strlen( opt.ca_path ) ) + { + if( ( ret = mbedtls_x509_crt_parse_path( &cacert, opt.ca_path ) ) < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_path returned -0x%x\n\n", -ret ); + goto exit; + } + + verify = 1; + } + else if( strlen( opt.ca_file ) ) + { + if( ( ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file ) ) < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file returned -0x%x\n\n", -ret ); + goto exit; + } + + verify = 1; + } + + mbedtls_printf( " ok (%d skipped)\n", ret ); + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + if( strlen( opt.crl_file ) ) + { + if( ( ret = mbedtls_x509_crl_parse_file( &cacrl, opt.crl_file ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crl_parse returned -0x%x\n\n", -ret ); + goto exit; + } + + verify = 1; + } +#endif + + if( opt.mode == MODE_FILE ) + { + mbedtls_x509_crt crt; + mbedtls_x509_crt *cur = &crt; + mbedtls_x509_crt_init( &crt ); + + /* + * 1.1. Load the certificate(s) + */ + mbedtls_printf( "\n . Loading the certificate(s) ..." ); + fflush( stdout ); + + ret = mbedtls_x509_crt_parse_file( &crt, opt.filename ); + + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file returned %d\n\n", ret ); + mbedtls_x509_crt_free( &crt ); + goto exit; + } + + if( opt.permissive == 0 && ret > 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse failed to parse %d certificates\n\n", ret ); + mbedtls_x509_crt_free( &crt ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.2 Print the certificate(s) + */ + while( cur != NULL ) + { + mbedtls_printf( " . Peer certificate information ...\n" ); + ret = mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ", + cur ); + if( ret == -1 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_info returned %d\n\n", ret ); + mbedtls_x509_crt_free( &crt ); + goto exit; + } + + mbedtls_printf( "%s\n", buf ); + + cur = cur->next; + } + + /* + * 1.3 Verify the certificate + */ + if( verify ) + { + mbedtls_printf( " . Verifying X.509 certificate..." ); + + if( ( ret = mbedtls_x509_crt_verify( &crt, &cacert, &cacrl, NULL, &flags, + my_verify, NULL ) ) != 0 ) + { + char vrfy_buf[512]; + + mbedtls_printf( " failed\n" ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + + mbedtls_printf( "%s\n", vrfy_buf ); + } + else + mbedtls_printf( " ok\n" ); + } + + mbedtls_x509_crt_free( &crt ); + } + else if( opt.mode == MODE_SSL ) + { + /* + * 1. Initialize the RNG and the session data + */ + mbedtls_printf( "\n . Seeding the random number generator..." ); + fflush( stdout ); + + mbedtls_entropy_init( &entropy ); + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); + goto ssl_exit; + } + + mbedtls_printf( " ok\n" ); + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold( opt.debug_level ); +#endif + + /* + * 2. Start the connection + */ + mbedtls_printf( " . SSL connection to tcp/%s/%s...", opt.server_name, + opt.server_port ); + fflush( stdout ); + + if( ( ret = mbedtls_net_connect( &server_fd, opt.server_name, + opt.server_port, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); + goto ssl_exit; + } + + /* + * 3. Setup stuff + */ + if( ( ret = mbedtls_ssl_config_defaults( &conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); + goto exit; + } + + if( verify ) + { + mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_REQUIRED ); + mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); + mbedtls_ssl_conf_verify( &conf, my_verify, NULL ); + } + else + mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_NONE ); + + mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); + mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); + + if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); + goto ssl_exit; + } + + if( ( ret = mbedtls_ssl_set_hostname( &ssl, opt.server_name ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); + goto ssl_exit; + } + + mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); + + /* + * 4. Handshake + */ + while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d\n\n", ret ); + goto ssl_exit; + } + } + + mbedtls_printf( " ok\n" ); + + /* + * 5. Print the certificate + */ + mbedtls_printf( " . Peer certificate information ...\n" ); + ret = mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ", + ssl.session->peer_cert ); + if( ret == -1 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_info returned %d\n\n", ret ); + goto ssl_exit; + } + + mbedtls_printf( "%s\n", buf ); + + mbedtls_ssl_close_notify( &ssl ); + +ssl_exit: + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + } + else + goto usage; + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + mbedtls_net_free( &server_fd ); + mbedtls_x509_crt_free( &cacert ); +#if defined(MBEDTLS_X509_CRL_PARSE_C) + mbedtls_x509_crl_free( &cacrl ); +#endif + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C && + MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C && + MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */ diff --git a/external/mbedtls/programs/x509/cert_req.c b/external/mbedtls/programs/x509/cert_req.c new file mode 100644 index 0000000..dc79603 --- /dev/null +++ b/external/mbedtls/programs/x509/cert_req.c @@ -0,0 +1,430 @@ +/* + * Certificate request generation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_X509_CSR_WRITE_C) || !defined(MBEDTLS_FS_IO) || \ + !defined(MBEDTLS_PK_PARSE_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \ + !defined(MBEDTLS_PEM_WRITE_C) +int main( void ) +{ + mbedtls_printf( "MBEDTLS_X509_CSR_WRITE_C and/or MBEDTLS_FS_IO and/or " + "MBEDTLS_PK_PARSE_C and/or MBEDTLS_SHA256_C and/or " + "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C " + "not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/x509_csr.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" + +#include +#include +#include + +#define DFL_FILENAME "keyfile.key" +#define DFL_PASSWORD NULL +#define DFL_DEBUG_LEVEL 0 +#define DFL_OUTPUT_FILENAME "cert.req" +#define DFL_SUBJECT_NAME "CN=Cert,O=mbed TLS,C=UK" +#define DFL_KEY_USAGE 0 +#define DFL_FORCE_KEY_USAGE 0 +#define DFL_NS_CERT_TYPE 0 +#define DFL_FORCE_NS_CERT_TYPE 0 +#define DFL_MD_ALG MBEDTLS_MD_SHA256 + +#define USAGE \ + "\n usage: cert_req param=<>...\n" \ + "\n acceptable parameters:\n" \ + " filename=%%s default: keyfile.key\n" \ + " password=%%s default: NULL\n" \ + " debug_level=%%d default: 0 (disabled)\n" \ + " output_file=%%s default: cert.req\n" \ + " subject_name=%%s default: CN=Cert,O=mbed TLS,C=UK\n" \ + " key_usage=%%s default: (empty)\n" \ + " Comma-separated-list of values:\n" \ + " digital_signature\n" \ + " non_repudiation\n" \ + " key_encipherment\n" \ + " data_encipherment\n" \ + " key_agreement\n" \ + " key_cert_sign\n" \ + " crl_sign\n" \ + " force_key_usage=0/1 default: off\n" \ + " Add KeyUsage even if it is empty\n" \ + " ns_cert_type=%%s default: (empty)\n" \ + " Comma-separated-list of values:\n" \ + " ssl_client\n" \ + " ssl_server\n" \ + " email\n" \ + " object_signing\n" \ + " ssl_ca\n" \ + " email_ca\n" \ + " object_signing_ca\n" \ + " force_ns_cert_type=0/1 default: off\n" \ + " Add NsCertType even if it is empty\n" \ + " md=%%s default: SHA256\n" \ + " possible values:\n" \ + " MD2, MD4, MD5, RIPEMD160, SHA1,\n" \ + " SHA224, SHA256, SHA384, SHA512\n" \ + "\n" + + +/* + * global options + */ +struct options +{ + const char *filename; /* filename of the key file */ + const char *password; /* password for the key file */ + int debug_level; /* level of debugging */ + const char *output_file; /* where to store the constructed key file */ + const char *subject_name; /* subject name for certificate request */ + unsigned char key_usage; /* key usage flags */ + int force_key_usage; /* Force adding the KeyUsage extension */ + unsigned char ns_cert_type; /* NS cert type */ + int force_ns_cert_type; /* Force adding NsCertType extension */ + mbedtls_md_type_t md_alg; /* Hash algorithm used for signature. */ +} opt; + +int write_certificate_request( mbedtls_x509write_csr *req, const char *output_file, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + FILE *f; + unsigned char output_buf[4096]; + size_t len = 0; + + memset( output_buf, 0, 4096 ); + if( ( ret = mbedtls_x509write_csr_pem( req, output_buf, 4096, f_rng, p_rng ) ) < 0 ) + return( ret ); + + len = strlen( (char *) output_buf ); + + if( ( f = fopen( output_file, "w" ) ) == NULL ) + return( -1 ); + + if( fwrite( output_buf, 1, len, f ) != len ) + { + fclose( f ); + return( -1 ); + } + + fclose( f ); + + return( 0 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_pk_context key; + char buf[1024]; + int i; + char *p, *q, *r; + mbedtls_x509write_csr req; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + const char *pers = "csr example app"; + + /* + * Set to sane values + */ + mbedtls_x509write_csr_init( &req ); + mbedtls_pk_init( &key ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + memset( buf, 0, sizeof( buf ) ); + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + goto exit; + } + + opt.filename = DFL_FILENAME; + opt.password = DFL_PASSWORD; + opt.debug_level = DFL_DEBUG_LEVEL; + opt.output_file = DFL_OUTPUT_FILENAME; + opt.subject_name = DFL_SUBJECT_NAME; + opt.key_usage = DFL_KEY_USAGE; + opt.force_key_usage = DFL_FORCE_KEY_USAGE; + opt.ns_cert_type = DFL_NS_CERT_TYPE; + opt.force_ns_cert_type = DFL_FORCE_NS_CERT_TYPE; + opt.md_alg = DFL_MD_ALG; + + for( i = 1; i < argc; i++ ) + { + + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else if( strcmp( p, "password" ) == 0 ) + opt.password = q; + else if( strcmp( p, "output_file" ) == 0 ) + opt.output_file = q; + else if( strcmp( p, "debug_level" ) == 0 ) + { + opt.debug_level = atoi( q ); + if( opt.debug_level < 0 || opt.debug_level > 65535 ) + goto usage; + } + else if( strcmp( p, "subject_name" ) == 0 ) + { + opt.subject_name = q; + } + else if( strcmp( p, "md" ) == 0 ) + { + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_string( q ); + if( md_info == NULL ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + opt.md_alg = mbedtls_md_get_type( md_info ); + } + else if( strcmp( p, "key_usage" ) == 0 ) + { + while( q != NULL ) + { + if( ( r = strchr( q, ',' ) ) != NULL ) + *r++ = '\0'; + + if( strcmp( q, "digital_signature" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + else if( strcmp( q, "non_repudiation" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_NON_REPUDIATION; + else if( strcmp( q, "key_encipherment" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_KEY_ENCIPHERMENT; + else if( strcmp( q, "data_encipherment" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_DATA_ENCIPHERMENT; + else if( strcmp( q, "key_agreement" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT; + else if( strcmp( q, "key_cert_sign" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_KEY_CERT_SIGN; + else if( strcmp( q, "crl_sign" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_CRL_SIGN; + else + goto usage; + + q = r; + } + } + else if( strcmp( p, "force_key_usage" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.force_key_usage = 0; break; + case 1: opt.force_key_usage = 1; break; + default: goto usage; + } + } + else if( strcmp( p, "ns_cert_type" ) == 0 ) + { + while( q != NULL ) + { + if( ( r = strchr( q, ',' ) ) != NULL ) + *r++ = '\0'; + + if( strcmp( q, "ssl_client" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT; + else if( strcmp( q, "ssl_server" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER; + else if( strcmp( q, "email" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL; + else if( strcmp( q, "object_signing" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING; + else if( strcmp( q, "ssl_ca" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA; + else if( strcmp( q, "email_ca" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA; + else if( strcmp( q, "object_signing_ca" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA; + else + goto usage; + + q = r; + } + } + else if( strcmp( p, "force_ns_cert_type" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.force_ns_cert_type = 0; break; + case 1: opt.force_ns_cert_type = 1; break; + default: goto usage; + } + } + else + goto usage; + } + + mbedtls_x509write_csr_set_md_alg( &req, opt.md_alg ); + + if( opt.key_usage || opt.force_key_usage == 1 ) + mbedtls_x509write_csr_set_key_usage( &req, opt.key_usage ); + + if( opt.ns_cert_type || opt.force_ns_cert_type == 1 ) + mbedtls_x509write_csr_set_ns_cert_type( &req, opt.ns_cert_type ); + + /* + * 0. Seed the PRNG + */ + mbedtls_printf( " . Seeding the random number generator..." ); + fflush( stdout ); + + mbedtls_entropy_init( &entropy ); + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.0. Check the subject name for validity + */ + mbedtls_printf( " . Checking subject name..." ); + fflush( stdout ); + + if( ( ret = mbedtls_x509write_csr_set_subject_name( &req, opt.subject_name ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509write_csr_set_subject_name returned %d", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.1. Load the key + */ + mbedtls_printf( " . Loading the private key ..." ); + fflush( stdout ); + + ret = mbedtls_pk_parse_keyfile( &key, opt.filename, opt.password ); + + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned %d", ret ); + goto exit; + } + + mbedtls_x509write_csr_set_key( &req, &key ); + + mbedtls_printf( " ok\n" ); + + /* + * 1.2. Writing the request + */ + mbedtls_printf( " . Writing the certificate request ..." ); + fflush( stdout ); + + if( ( ret = write_certificate_request( &req, opt.output_file, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! write_certifcate_request %d", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + if( exit_code != MBEDTLS_EXIT_SUCCESS ) + { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror( ret, buf, sizeof( buf ) ); + mbedtls_printf( " - %s\n", buf ); +#else + mbedtls_printf("\n"); +#endif + } + + mbedtls_x509write_csr_free( &req ); + mbedtls_pk_free( &key ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_X509_CSR_WRITE_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO && + MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_PEM_WRITE_C */ diff --git a/external/mbedtls/programs/x509/cert_write.c b/external/mbedtls/programs/x509/cert_write.c new file mode 100644 index 0000000..f0f044d --- /dev/null +++ b/external/mbedtls/programs/x509/cert_write.c @@ -0,0 +1,835 @@ +/* + * Certificate generation and signing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_X509_CRT_WRITE_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \ + !defined(MBEDTLS_ERROR_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_PEM_WRITE_C) +int main( void ) +{ + mbedtls_printf( "MBEDTLS_X509_CRT_WRITE_C and/or MBEDTLS_X509_CRT_PARSE_C and/or " + "MBEDTLS_FS_IO and/or MBEDTLS_SHA256_C and/or " + "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or " + "MBEDTLS_ERROR_C not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/x509_crt.h" +#include "mbedtls/x509_csr.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/md.h" +#include "mbedtls/error.h" + +#include +#include +#include + +#if defined(MBEDTLS_X509_CSR_PARSE_C) +#define USAGE_CSR \ + " request_file=%%s default: (empty)\n" \ + " If request_file is specified, subject_key,\n" \ + " subject_pwd and subject_name are ignored!\n" +#else +#define USAGE_CSR "" +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + +#define DFL_ISSUER_CRT "" +#define DFL_REQUEST_FILE "" +#define DFL_SUBJECT_KEY "subject.key" +#define DFL_ISSUER_KEY "ca.key" +#define DFL_SUBJECT_PWD "" +#define DFL_ISSUER_PWD "" +#define DFL_OUTPUT_FILENAME "cert.crt" +#define DFL_SUBJECT_NAME "CN=Cert,O=mbed TLS,C=UK" +#define DFL_ISSUER_NAME "CN=CA,O=mbed TLS,C=UK" +#define DFL_NOT_BEFORE "20010101000000" +#define DFL_NOT_AFTER "20301231235959" +#define DFL_SERIAL "1" +#define DFL_SELFSIGN 0 +#define DFL_IS_CA 0 +#define DFL_MAX_PATHLEN -1 +#define DFL_KEY_USAGE 0 +#define DFL_NS_CERT_TYPE 0 +#define DFL_VERSION 3 +#define DFL_AUTH_IDENT 1 +#define DFL_SUBJ_IDENT 1 +#define DFL_CONSTRAINTS 1 +#define DFL_DIGEST MBEDTLS_MD_SHA256 + +#define USAGE \ + "\n usage: cert_write param=<>...\n" \ + "\n acceptable parameters:\n" \ + USAGE_CSR \ + " subject_key=%%s default: subject.key\n" \ + " subject_pwd=%%s default: (empty)\n" \ + " subject_name=%%s default: CN=Cert,O=mbed TLS,C=UK\n" \ + "\n" \ + " issuer_crt=%%s default: (empty)\n" \ + " If issuer_crt is specified, issuer_name is\n" \ + " ignored!\n" \ + " issuer_name=%%s default: CN=CA,O=mbed TLS,C=UK\n" \ + "\n" \ + " selfsign=%%d default: 0 (false)\n" \ + " If selfsign is enabled, issuer_name and\n" \ + " issuer_key are required (issuer_crt and\n" \ + " subject_* are ignored\n" \ + " issuer_key=%%s default: ca.key\n" \ + " issuer_pwd=%%s default: (empty)\n" \ + " output_file=%%s default: cert.crt\n" \ + " serial=%%s default: 1\n" \ + " not_before=%%s default: 20010101000000\n"\ + " not_after=%%s default: 20301231235959\n"\ + " is_ca=%%d default: 0 (disabled)\n" \ + " max_pathlen=%%d default: -1 (none)\n" \ + " md=%%s default: SHA256\n" \ + " Supported values (if enabled):\n" \ + " MD2, MD4, MD5, RIPEMD160, SHA1,\n" \ + " SHA224, SHA256, SHA384, SHA512\n" \ + " version=%%d default: 3\n" \ + " Possible values: 1, 2, 3\n"\ + " subject_identifier=%%s default: 1\n" \ + " Possible values: 0, 1\n" \ + " (Considered for v3 only)\n"\ + " authority_identifier=%%s default: 1\n" \ + " Possible values: 0, 1\n" \ + " (Considered for v3 only)\n"\ + " basic_constraints=%%d default: 1\n" \ + " Possible values: 0, 1\n" \ + " (Considered for v3 only)\n"\ + " key_usage=%%s default: (empty)\n" \ + " Comma-separated-list of values:\n" \ + " digital_signature\n" \ + " non_repudiation\n" \ + " key_encipherment\n" \ + " data_encipherment\n" \ + " key_agreement\n" \ + " key_cert_sign\n" \ + " crl_sign\n" \ + " (Considered for v3 only)\n"\ + " ns_cert_type=%%s default: (empty)\n" \ + " Comma-separated-list of values:\n" \ + " ssl_client\n" \ + " ssl_server\n" \ + " email\n" \ + " object_signing\n" \ + " ssl_ca\n" \ + " email_ca\n" \ + " object_signing_ca\n" \ + "\n" + + +/* + * global options + */ +struct options +{ + const char *issuer_crt; /* filename of the issuer certificate */ + const char *request_file; /* filename of the certificate request */ + const char *subject_key; /* filename of the subject key file */ + const char *issuer_key; /* filename of the issuer key file */ + const char *subject_pwd; /* password for the subject key file */ + const char *issuer_pwd; /* password for the issuer key file */ + const char *output_file; /* where to store the constructed CRT */ + const char *subject_name; /* subject name for certificate */ + const char *issuer_name; /* issuer name for certificate */ + const char *not_before; /* validity period not before */ + const char *not_after; /* validity period not after */ + const char *serial; /* serial number string */ + int selfsign; /* selfsign the certificate */ + int is_ca; /* is a CA certificate */ + int max_pathlen; /* maximum CA path length */ + int authority_identifier; /* add authority identifier to CRT */ + int subject_identifier; /* add subject identifier to CRT */ + int basic_constraints; /* add basic constraints ext to CRT */ + int version; /* CRT version */ + mbedtls_md_type_t md; /* Hash used for signing */ + unsigned char key_usage; /* key usage flags */ + unsigned char ns_cert_type; /* NS cert type */ +} opt; + +int write_certificate( mbedtls_x509write_cert *crt, const char *output_file, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + FILE *f; + unsigned char output_buf[4096]; + size_t len = 0; + + memset( output_buf, 0, 4096 ); + if( ( ret = mbedtls_x509write_crt_pem( crt, output_buf, 4096, + f_rng, p_rng ) ) < 0 ) + return( ret ); + + len = strlen( (char *) output_buf ); + + if( ( f = fopen( output_file, "w" ) ) == NULL ) + return( -1 ); + + if( fwrite( output_buf, 1, len, f ) != len ) + { + fclose( f ); + return( -1 ); + } + + fclose( f ); + + return( 0 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_x509_crt issuer_crt; + mbedtls_pk_context loaded_issuer_key, loaded_subject_key; + mbedtls_pk_context *issuer_key = &loaded_issuer_key, + *subject_key = &loaded_subject_key; + char buf[1024]; + char issuer_name[256]; + int i; + char *p, *q, *r; +#if defined(MBEDTLS_X509_CSR_PARSE_C) + char subject_name[256]; + mbedtls_x509_csr csr; +#endif + mbedtls_x509write_cert crt; + mbedtls_mpi serial; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + const char *pers = "crt example app"; + + /* + * Set to sane values + */ + mbedtls_x509write_crt_init( &crt ); + mbedtls_pk_init( &loaded_issuer_key ); + mbedtls_pk_init( &loaded_subject_key ); + mbedtls_mpi_init( &serial ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + mbedtls_entropy_init( &entropy ); +#if defined(MBEDTLS_X509_CSR_PARSE_C) + mbedtls_x509_csr_init( &csr ); +#endif + mbedtls_x509_crt_init( &issuer_crt ); + memset( buf, 0, 1024 ); + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + goto exit; + } + + opt.issuer_crt = DFL_ISSUER_CRT; + opt.request_file = DFL_REQUEST_FILE; + opt.subject_key = DFL_SUBJECT_KEY; + opt.issuer_key = DFL_ISSUER_KEY; + opt.subject_pwd = DFL_SUBJECT_PWD; + opt.issuer_pwd = DFL_ISSUER_PWD; + opt.output_file = DFL_OUTPUT_FILENAME; + opt.subject_name = DFL_SUBJECT_NAME; + opt.issuer_name = DFL_ISSUER_NAME; + opt.not_before = DFL_NOT_BEFORE; + opt.not_after = DFL_NOT_AFTER; + opt.serial = DFL_SERIAL; + opt.selfsign = DFL_SELFSIGN; + opt.is_ca = DFL_IS_CA; + opt.max_pathlen = DFL_MAX_PATHLEN; + opt.key_usage = DFL_KEY_USAGE; + opt.ns_cert_type = DFL_NS_CERT_TYPE; + opt.version = DFL_VERSION - 1; + opt.md = DFL_DIGEST; + opt.subject_identifier = DFL_SUBJ_IDENT; + opt.authority_identifier = DFL_AUTH_IDENT; + opt.basic_constraints = DFL_CONSTRAINTS; + + for( i = 1; i < argc; i++ ) + { + + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "request_file" ) == 0 ) + opt.request_file = q; + else if( strcmp( p, "subject_key" ) == 0 ) + opt.subject_key = q; + else if( strcmp( p, "issuer_key" ) == 0 ) + opt.issuer_key = q; + else if( strcmp( p, "subject_pwd" ) == 0 ) + opt.subject_pwd = q; + else if( strcmp( p, "issuer_pwd" ) == 0 ) + opt.issuer_pwd = q; + else if( strcmp( p, "issuer_crt" ) == 0 ) + opt.issuer_crt = q; + else if( strcmp( p, "output_file" ) == 0 ) + opt.output_file = q; + else if( strcmp( p, "subject_name" ) == 0 ) + { + opt.subject_name = q; + } + else if( strcmp( p, "issuer_name" ) == 0 ) + { + opt.issuer_name = q; + } + else if( strcmp( p, "not_before" ) == 0 ) + { + opt.not_before = q; + } + else if( strcmp( p, "not_after" ) == 0 ) + { + opt.not_after = q; + } + else if( strcmp( p, "serial" ) == 0 ) + { + opt.serial = q; + } + else if( strcmp( p, "authority_identifier" ) == 0 ) + { + opt.authority_identifier = atoi( q ); + if( opt.authority_identifier != 0 && + opt.authority_identifier != 1 ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + } + else if( strcmp( p, "subject_identifier" ) == 0 ) + { + opt.subject_identifier = atoi( q ); + if( opt.subject_identifier != 0 && + opt.subject_identifier != 1 ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + } + else if( strcmp( p, "basic_constraints" ) == 0 ) + { + opt.basic_constraints = atoi( q ); + if( opt.basic_constraints != 0 && + opt.basic_constraints != 1 ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + } + else if( strcmp( p, "md" ) == 0 ) + { + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_string( q ); + if( md_info == NULL ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + opt.md = mbedtls_md_get_type( md_info ); + } + else if( strcmp( p, "version" ) == 0 ) + { + opt.version = atoi( q ); + if( opt.version < 1 || opt.version > 3 ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + opt.version--; + } + else if( strcmp( p, "selfsign" ) == 0 ) + { + opt.selfsign = atoi( q ); + if( opt.selfsign < 0 || opt.selfsign > 1 ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + } + else if( strcmp( p, "is_ca" ) == 0 ) + { + opt.is_ca = atoi( q ); + if( opt.is_ca < 0 || opt.is_ca > 1 ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + } + else if( strcmp( p, "max_pathlen" ) == 0 ) + { + opt.max_pathlen = atoi( q ); + if( opt.max_pathlen < -1 || opt.max_pathlen > 127 ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + } + else if( strcmp( p, "key_usage" ) == 0 ) + { + while( q != NULL ) + { + if( ( r = strchr( q, ',' ) ) != NULL ) + *r++ = '\0'; + + if( strcmp( q, "digital_signature" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + else if( strcmp( q, "non_repudiation" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_NON_REPUDIATION; + else if( strcmp( q, "key_encipherment" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_KEY_ENCIPHERMENT; + else if( strcmp( q, "data_encipherment" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_DATA_ENCIPHERMENT; + else if( strcmp( q, "key_agreement" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT; + else if( strcmp( q, "key_cert_sign" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_KEY_CERT_SIGN; + else if( strcmp( q, "crl_sign" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_CRL_SIGN; + else + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + + q = r; + } + } + else if( strcmp( p, "ns_cert_type" ) == 0 ) + { + while( q != NULL ) + { + if( ( r = strchr( q, ',' ) ) != NULL ) + *r++ = '\0'; + + if( strcmp( q, "ssl_client" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT; + else if( strcmp( q, "ssl_server" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER; + else if( strcmp( q, "email" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL; + else if( strcmp( q, "object_signing" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING; + else if( strcmp( q, "ssl_ca" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA; + else if( strcmp( q, "email_ca" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA; + else if( strcmp( q, "object_signing_ca" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA; + else + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + + q = r; + } + } + else + goto usage; + } + + mbedtls_printf("\n"); + + /* + * 0. Seed the PRNG + */ + mbedtls_printf( " . Seeding the random number generator..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d - %s\n", + ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + // Parse serial to MPI + // + mbedtls_printf( " . Reading serial number..." ); + fflush( stdout ); + + if( ( ret = mbedtls_mpi_read_string( &serial, 10, opt.serial ) ) != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_mpi_read_string " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + // Parse issuer certificate if present + // + if( !opt.selfsign && strlen( opt.issuer_crt ) ) + { + /* + * 1.0.a. Load the certificates + */ + mbedtls_printf( " . Loading the issuer certificate ..." ); + fflush( stdout ); + + if( ( ret = mbedtls_x509_crt_parse_file( &issuer_crt, opt.issuer_crt ) ) != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + ret = mbedtls_x509_dn_gets( issuer_name, sizeof(issuer_name), + &issuer_crt.subject ); + if( ret < 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509_dn_gets " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + opt.issuer_name = issuer_name; + + mbedtls_printf( " ok\n" ); + } + +#if defined(MBEDTLS_X509_CSR_PARSE_C) + // Parse certificate request if present + // + if( !opt.selfsign && strlen( opt.request_file ) ) + { + /* + * 1.0.b. Load the CSR + */ + mbedtls_printf( " . Loading the certificate request ..." ); + fflush( stdout ); + + if( ( ret = mbedtls_x509_csr_parse_file( &csr, opt.request_file ) ) != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509_csr_parse_file " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + ret = mbedtls_x509_dn_gets( subject_name, sizeof(subject_name), + &csr.subject ); + if( ret < 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509_dn_gets " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + opt.subject_name = subject_name; + subject_key = &csr.pk; + + mbedtls_printf( " ok\n" ); + } +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + + /* + * 1.1. Load the keys + */ + if( !opt.selfsign && !strlen( opt.request_file ) ) + { + mbedtls_printf( " . Loading the subject key ..." ); + fflush( stdout ); + + ret = mbedtls_pk_parse_keyfile( &loaded_subject_key, opt.subject_key, + opt.subject_pwd ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } + + mbedtls_printf( " . Loading the issuer key ..." ); + fflush( stdout ); + + ret = mbedtls_pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key, + opt.issuer_pwd ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile " + "returned -x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + // Check if key and issuer certificate match + // + if( strlen( opt.issuer_crt ) ) + { + if( mbedtls_pk_check_pair( &issuer_crt.pk, issuer_key ) != 0 ) + { + mbedtls_printf( " failed\n ! issuer_key does not match " + "issuer certificate\n\n" ); + goto exit; + } + } + + mbedtls_printf( " ok\n" ); + + if( opt.selfsign ) + { + opt.subject_name = opt.issuer_name; + subject_key = issuer_key; + } + + mbedtls_x509write_crt_set_subject_key( &crt, subject_key ); + mbedtls_x509write_crt_set_issuer_key( &crt, issuer_key ); + + /* + * 1.0. Check the names for validity + */ + if( ( ret = mbedtls_x509write_crt_set_subject_name( &crt, opt.subject_name ) ) != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_subject_name " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + if( ( ret = mbedtls_x509write_crt_set_issuer_name( &crt, opt.issuer_name ) ) != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_issuer_name " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " . Setting certificate values ..." ); + fflush( stdout ); + + mbedtls_x509write_crt_set_version( &crt, opt.version ); + mbedtls_x509write_crt_set_md_alg( &crt, opt.md ); + + ret = mbedtls_x509write_crt_set_serial( &crt, &serial ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_serial " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + ret = mbedtls_x509write_crt_set_validity( &crt, opt.not_before, opt.not_after ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_validity " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + if( opt.version == MBEDTLS_X509_CRT_VERSION_3 && + opt.basic_constraints != 0 ) + { + mbedtls_printf( " . Adding the Basic Constraints extension ..." ); + fflush( stdout ); + + ret = mbedtls_x509write_crt_set_basic_constraints( &crt, opt.is_ca, + opt.max_pathlen ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! x509write_crt_set_basic_contraints " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } + +#if defined(MBEDTLS_SHA1_C) + if( opt.version == MBEDTLS_X509_CRT_VERSION_3 && + opt.subject_identifier != 0 ) + { + mbedtls_printf( " . Adding the Subject Key Identifier ..." ); + fflush( stdout ); + + ret = mbedtls_x509write_crt_set_subject_key_identifier( &crt ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_subject" + "_key_identifier returned -0x%04x - %s\n\n", + -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } + + if( opt.version == MBEDTLS_X509_CRT_VERSION_3 && + opt.authority_identifier != 0 ) + { + mbedtls_printf( " . Adding the Authority Key Identifier ..." ); + fflush( stdout ); + + ret = mbedtls_x509write_crt_set_authority_key_identifier( &crt ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_authority_" + "key_identifier returned -0x%04x - %s\n\n", + -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } +#endif /* MBEDTLS_SHA1_C */ + + if( opt.version == MBEDTLS_X509_CRT_VERSION_3 && + opt.key_usage != 0 ) + { + mbedtls_printf( " . Adding the Key Usage extension ..." ); + fflush( stdout ); + + ret = mbedtls_x509write_crt_set_key_usage( &crt, opt.key_usage ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_key_usage " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } + + if( opt.version == MBEDTLS_X509_CRT_VERSION_3 && + opt.ns_cert_type != 0 ) + { + mbedtls_printf( " . Adding the NS Cert Type extension ..." ); + fflush( stdout ); + + ret = mbedtls_x509write_crt_set_ns_cert_type( &crt, opt.ns_cert_type ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_ns_cert_type " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } + + /* + * 1.2. Writing the certificate + */ + mbedtls_printf( " . Writing the certificate..." ); + fflush( stdout ); + + if( ( ret = write_certificate( &crt, opt.output_file, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! write_certificate -0x%04x - %s\n\n", + -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: +#if defined(MBEDTLS_X509_CSR_PARSE_C) + mbedtls_x509_csr_free( &csr ); +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + mbedtls_x509_crt_free( &issuer_crt ); + mbedtls_x509write_crt_free( &crt ); + mbedtls_pk_free( &loaded_subject_key ); + mbedtls_pk_free( &loaded_issuer_key ); + mbedtls_mpi_free( &serial ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_X509_CRT_WRITE_C && MBEDTLS_X509_CRT_PARSE_C && + MBEDTLS_FS_IO && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C && + MBEDTLS_ERROR_C && MBEDTLS_PEM_WRITE_C */ diff --git a/external/mbedtls/programs/x509/crl_app.c b/external/mbedtls/programs/x509/crl_app.c new file mode 100644 index 0000000..aa6f285 --- /dev/null +++ b/external/mbedtls/programs/x509/crl_app.c @@ -0,0 +1,178 @@ +/* + * CRL reading application + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRL_PARSE_C) || !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_X509_CRL_PARSE_C and/or MBEDTLS_FS_IO not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/x509_crl.h" + +#include +#include +#include + +#define DFL_FILENAME "crl.pem" +#define DFL_DEBUG_LEVEL 0 + +#define USAGE \ + "\n usage: crl_app param=<>...\n" \ + "\n acceptable parameters:\n" \ + " filename=%%s default: crl.pem\n" \ + "\n" + + +/* + * global options + */ +struct options +{ + const char *filename; /* filename of the certificate file */ +} opt; + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + unsigned char buf[100000]; + mbedtls_x509_crl crl; + int i; + char *p, *q; + + /* + * Set to sane values + */ + mbedtls_x509_crl_init( &crl ); + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + goto exit; + } + + opt.filename = DFL_FILENAME; + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else + goto usage; + } + + /* + * 1.1. Load the CRL + */ + mbedtls_printf( "\n . Loading the CRL ..." ); + fflush( stdout ); + + ret = mbedtls_x509_crl_parse_file( &crl, opt.filename ); + + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crl_parse_file returned %d\n\n", ret ); + mbedtls_x509_crl_free( &crl ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.2 Print the CRL + */ + mbedtls_printf( " . CRL information ...\n" ); + ret = mbedtls_x509_crl_info( (char *) buf, sizeof( buf ) - 1, " ", &crl ); + if( ret == -1 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crl_info returned %d\n\n", ret ); + mbedtls_x509_crl_free( &crl ); + goto exit; + } + + mbedtls_printf( "%s\n", buf ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + mbedtls_x509_crl_free( &crl ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_X509_CRL_PARSE_C && + MBEDTLS_FS_IO */ diff --git a/external/mbedtls/programs/x509/req_app.c b/external/mbedtls/programs/x509/req_app.c new file mode 100644 index 0000000..03ec943 --- /dev/null +++ b/external/mbedtls/programs/x509/req_app.c @@ -0,0 +1,178 @@ +/* + * Certificate request reading application + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CSR_PARSE_C) || !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_X509_CSR_PARSE_C and/or MBEDTLS_FS_IO not defined.\n"); + mbedtls_exit( 0 ); +} +#else + +#include "mbedtls/x509_csr.h" + +#include +#include +#include + +#define DFL_FILENAME "cert.req" +#define DFL_DEBUG_LEVEL 0 + +#define USAGE \ + "\n usage: req_app param=<>...\n" \ + "\n acceptable parameters:\n" \ + " filename=%%s default: cert.req\n" \ + "\n" + + +/* + * global options + */ +struct options +{ + const char *filename; /* filename of the certificate request */ +} opt; + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + unsigned char buf[100000]; + mbedtls_x509_csr csr; + int i; + char *p, *q; + + /* + * Set to sane values + */ + mbedtls_x509_csr_init( &csr ); + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + goto exit; + } + + opt.filename = DFL_FILENAME; + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else + goto usage; + } + + /* + * 1.1. Load the CSR + */ + mbedtls_printf( "\n . Loading the CSR ..." ); + fflush( stdout ); + + ret = mbedtls_x509_csr_parse_file( &csr, opt.filename ); + + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_csr_parse_file returned %d\n\n", ret ); + mbedtls_x509_csr_free( &csr ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.2 Print the CSR + */ + mbedtls_printf( " . CSR information ...\n" ); + ret = mbedtls_x509_csr_info( (char *) buf, sizeof( buf ) - 1, " ", &csr ); + if( ret == -1 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_csr_info returned %d\n\n", ret ); + mbedtls_x509_csr_free( &csr ); + goto exit; + } + + mbedtls_printf( "%s\n", buf ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + mbedtls_x509_csr_free( &csr ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_exit( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_X509_CSR_PARSE_C && + MBEDTLS_FS_IO */ diff --git a/external/mbedtls/scripts/abi_check.py b/external/mbedtls/scripts/abi_check.py new file mode 100644 index 0000000..07c726a --- /dev/null +++ b/external/mbedtls/scripts/abi_check.py @@ -0,0 +1,473 @@ +#!/usr/bin/env python3 +""" +Purpose + +This script is a small wrapper around the abi-compliance-checker and +abi-dumper tools, applying them to compare the ABI and API of the library +files from two different Git revisions within an Mbed TLS repository. +The results of the comparison are either formatted as HTML and stored at +a configurable location, or are given as a brief list of problems. +Returns 0 on success, 1 on ABI/API non-compliance, and 2 if there is an error +while running the script. Note: must be run from Mbed TLS root. +""" + +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** + +import os +import sys +import traceback +import shutil +import subprocess +import argparse +import logging +import tempfile +import fnmatch +from types import SimpleNamespace + +import xml.etree.ElementTree as ET + + +class AbiChecker: + """API and ABI checker.""" + + def __init__(self, old_version, new_version, configuration): + """Instantiate the API/ABI checker. + + old_version: RepoVersion containing details to compare against + new_version: RepoVersion containing details to check + configuration.report_dir: directory for output files + configuration.keep_all_reports: if false, delete old reports + configuration.brief: if true, output shorter report to stdout + configuration.skip_file: path to file containing symbols and types to skip + """ + self.repo_path = "." + self.log = None + self.verbose = configuration.verbose + self._setup_logger() + self.report_dir = os.path.abspath(configuration.report_dir) + self.keep_all_reports = configuration.keep_all_reports + self.can_remove_report_dir = not (os.path.exists(self.report_dir) or + self.keep_all_reports) + self.old_version = old_version + self.new_version = new_version + self.skip_file = configuration.skip_file + self.brief = configuration.brief + self.git_command = "git" + self.make_command = "make" + + @staticmethod + def check_repo_path(): + if not all(os.path.isdir(d) for d in ["include", "library", "tests"]): + raise Exception("Must be run from Mbed TLS root") + + def _setup_logger(self): + self.log = logging.getLogger() + if self.verbose: + self.log.setLevel(logging.DEBUG) + else: + self.log.setLevel(logging.INFO) + self.log.addHandler(logging.StreamHandler()) + + @staticmethod + def check_abi_tools_are_installed(): + for command in ["abi-dumper", "abi-compliance-checker"]: + if not shutil.which(command): + raise Exception("{} not installed, aborting".format(command)) + + def _get_clean_worktree_for_git_revision(self, version): + """Make a separate worktree with version.revision checked out. + Do not modify the current worktree.""" + git_worktree_path = tempfile.mkdtemp() + if version.repository: + self.log.debug( + "Checking out git worktree for revision {} from {}".format( + version.revision, version.repository + ) + ) + fetch_output = subprocess.check_output( + [self.git_command, "fetch", + version.repository, version.revision], + cwd=self.repo_path, + stderr=subprocess.STDOUT + ) + self.log.debug(fetch_output.decode("utf-8")) + worktree_rev = "FETCH_HEAD" + else: + self.log.debug("Checking out git worktree for revision {}".format( + version.revision + )) + worktree_rev = version.revision + worktree_output = subprocess.check_output( + [self.git_command, "worktree", "add", "--detach", + git_worktree_path, worktree_rev], + cwd=self.repo_path, + stderr=subprocess.STDOUT + ) + self.log.debug(worktree_output.decode("utf-8")) + version.commit = subprocess.check_output( + [self.git_command, "rev-parse", "HEAD"], + cwd=git_worktree_path, + stderr=subprocess.STDOUT + ).decode("ascii").rstrip() + self.log.debug("Commit is {}".format(version.commit)) + return git_worktree_path + + def _update_git_submodules(self, git_worktree_path, version): + """If the crypto submodule is present, initialize it. + if version.crypto_revision exists, update it to that revision, + otherwise update it to the default revision""" + update_output = subprocess.check_output( + [self.git_command, "submodule", "update", "--init", '--recursive'], + cwd=git_worktree_path, + stderr=subprocess.STDOUT + ) + self.log.debug(update_output.decode("utf-8")) + if not (os.path.exists(os.path.join(git_worktree_path, "crypto")) + and version.crypto_revision): + return + + if version.crypto_repository: + fetch_output = subprocess.check_output( + [self.git_command, "fetch", version.crypto_repository, + version.crypto_revision], + cwd=os.path.join(git_worktree_path, "crypto"), + stderr=subprocess.STDOUT + ) + self.log.debug(fetch_output.decode("utf-8")) + crypto_rev = "FETCH_HEAD" + else: + crypto_rev = version.crypto_revision + + checkout_output = subprocess.check_output( + [self.git_command, "checkout", crypto_rev], + cwd=os.path.join(git_worktree_path, "crypto"), + stderr=subprocess.STDOUT + ) + self.log.debug(checkout_output.decode("utf-8")) + + def _build_shared_libraries(self, git_worktree_path, version): + """Build the shared libraries in the specified worktree.""" + my_environment = os.environ.copy() + my_environment["CFLAGS"] = "-g -Og" + my_environment["SHARED"] = "1" + if os.path.exists(os.path.join(git_worktree_path, "crypto")): + my_environment["USE_CRYPTO_SUBMODULE"] = "1" + make_output = subprocess.check_output( + [self.make_command, "lib"], + env=my_environment, + cwd=git_worktree_path, + stderr=subprocess.STDOUT + ) + self.log.debug(make_output.decode("utf-8")) + for root, _dirs, files in os.walk(git_worktree_path): + for file in fnmatch.filter(files, "*.so"): + version.modules[os.path.splitext(file)[0]] = ( + os.path.join(root, file) + ) + + @staticmethod + def _pretty_revision(version): + if version.revision == version.commit: + return version.revision + else: + return "{} ({})".format(version.revision, version.commit) + + def _get_abi_dumps_from_shared_libraries(self, version): + """Generate the ABI dumps for the specified git revision. + The shared libraries must have been built and the module paths + present in version.modules.""" + for mbed_module, module_path in version.modules.items(): + output_path = os.path.join( + self.report_dir, "{}-{}-{}.dump".format( + mbed_module, version.revision, version.version + ) + ) + abi_dump_command = [ + "abi-dumper", + module_path, + "-o", output_path, + "-lver", self._pretty_revision(version), + ] + abi_dump_output = subprocess.check_output( + abi_dump_command, + stderr=subprocess.STDOUT + ) + self.log.debug(abi_dump_output.decode("utf-8")) + version.abi_dumps[mbed_module] = output_path + + def _cleanup_worktree(self, git_worktree_path): + """Remove the specified git worktree.""" + shutil.rmtree(git_worktree_path) + worktree_output = subprocess.check_output( + [self.git_command, "worktree", "prune"], + cwd=self.repo_path, + stderr=subprocess.STDOUT + ) + self.log.debug(worktree_output.decode("utf-8")) + + def _get_abi_dump_for_ref(self, version): + """Generate the ABI dumps for the specified git revision.""" + git_worktree_path = self._get_clean_worktree_for_git_revision(version) + self._update_git_submodules(git_worktree_path, version) + self._build_shared_libraries(git_worktree_path, version) + self._get_abi_dumps_from_shared_libraries(version) + self._cleanup_worktree(git_worktree_path) + + def _remove_children_with_tag(self, parent, tag): + children = parent.getchildren() + for child in children: + if child.tag == tag: + parent.remove(child) + else: + self._remove_children_with_tag(child, tag) + + def _remove_extra_detail_from_report(self, report_root): + for tag in ['test_info', 'test_results', 'problem_summary', + 'added_symbols', 'affected']: + self._remove_children_with_tag(report_root, tag) + + for report in report_root: + for problems in report.getchildren()[:]: + if not problems.getchildren(): + report.remove(problems) + + def _abi_compliance_command(self, mbed_module, output_path): + """Build the command to run to analyze the library mbed_module. + The report will be placed in output_path.""" + abi_compliance_command = [ + "abi-compliance-checker", + "-l", mbed_module, + "-old", self.old_version.abi_dumps[mbed_module], + "-new", self.new_version.abi_dumps[mbed_module], + "-strict", + "-report-path", output_path, + ] + if self.skip_file: + abi_compliance_command += ["-skip-symbols", self.skip_file, + "-skip-types", self.skip_file] + if self.brief: + abi_compliance_command += ["-report-format", "xml", + "-stdout"] + return abi_compliance_command + + def _is_library_compatible(self, mbed_module, compatibility_report): + """Test if the library mbed_module has remained compatible. + Append a message regarding compatibility to compatibility_report.""" + output_path = os.path.join( + self.report_dir, "{}-{}-{}.html".format( + mbed_module, self.old_version.revision, + self.new_version.revision + ) + ) + try: + subprocess.check_output( + self._abi_compliance_command(mbed_module, output_path), + stderr=subprocess.STDOUT + ) + except subprocess.CalledProcessError as err: + if err.returncode != 1: + raise err + if self.brief: + self.log.info( + "Compatibility issues found for {}".format(mbed_module) + ) + report_root = ET.fromstring(err.output.decode("utf-8")) + self._remove_extra_detail_from_report(report_root) + self.log.info(ET.tostring(report_root).decode("utf-8")) + else: + self.can_remove_report_dir = False + compatibility_report.append( + "Compatibility issues found for {}, " + "for details see {}".format(mbed_module, output_path) + ) + return False + compatibility_report.append( + "No compatibility issues for {}".format(mbed_module) + ) + if not (self.keep_all_reports or self.brief): + os.remove(output_path) + return True + + def get_abi_compatibility_report(self): + """Generate a report of the differences between the reference ABI + and the new ABI. ABI dumps from self.old_version and self.new_version + must be available.""" + compatibility_report = ["Checking evolution from {} to {}".format( + self._pretty_revision(self.old_version), + self._pretty_revision(self.new_version) + )] + compliance_return_code = 0 + shared_modules = list(set(self.old_version.modules.keys()) & + set(self.new_version.modules.keys())) + for mbed_module in shared_modules: + if not self._is_library_compatible(mbed_module, + compatibility_report): + compliance_return_code = 1 + for version in [self.old_version, self.new_version]: + for mbed_module, mbed_module_dump in version.abi_dumps.items(): + os.remove(mbed_module_dump) + if self.can_remove_report_dir: + os.rmdir(self.report_dir) + self.log.info("\n".join(compatibility_report)) + return compliance_return_code + + def check_for_abi_changes(self): + """Generate a report of ABI differences + between self.old_rev and self.new_rev.""" + self.check_repo_path() + self.check_abi_tools_are_installed() + self._get_abi_dump_for_ref(self.old_version) + self._get_abi_dump_for_ref(self.new_version) + return self.get_abi_compatibility_report() + + +def run_main(): + try: + parser = argparse.ArgumentParser( + description=( + """This script is a small wrapper around the + abi-compliance-checker and abi-dumper tools, applying them + to compare the ABI and API of the library files from two + different Git revisions within an Mbed TLS repository. + The results of the comparison are either formatted as HTML and + stored at a configurable location, or are given as a brief list + of problems. Returns 0 on success, 1 on ABI/API non-compliance, + and 2 if there is an error while running the script. + Note: must be run from Mbed TLS root.""" + ) + ) + parser.add_argument( + "-v", "--verbose", action="store_true", + help="set verbosity level", + ) + parser.add_argument( + "-r", "--report-dir", type=str, default="reports", + help="directory where reports are stored, default is reports", + ) + parser.add_argument( + "-k", "--keep-all-reports", action="store_true", + help="keep all reports, even if there are no compatibility issues", + ) + parser.add_argument( + "-o", "--old-rev", type=str, help="revision for old version.", + required=True, + ) + parser.add_argument( + "-or", "--old-repo", type=str, help="repository for old version." + ) + parser.add_argument( + "-oc", "--old-crypto-rev", type=str, + help="revision for old crypto submodule." + ) + parser.add_argument( + "-ocr", "--old-crypto-repo", type=str, + help="repository for old crypto submodule." + ) + parser.add_argument( + "-n", "--new-rev", type=str, help="revision for new version", + required=True, + ) + parser.add_argument( + "-nr", "--new-repo", type=str, help="repository for new version." + ) + parser.add_argument( + "-nc", "--new-crypto-rev", type=str, + help="revision for new crypto version" + ) + parser.add_argument( + "-ncr", "--new-crypto-repo", type=str, + help="repository for new crypto submodule." + ) + parser.add_argument( + "-s", "--skip-file", type=str, + help=("path to file containing symbols and types to skip " + "(typically \"-s identifiers\" after running " + "\"tests/scripts/list-identifiers.sh --internal\")") + ) + parser.add_argument( + "-b", "--brief", action="store_true", + help="output only the list of issues to stdout, instead of a full report", + ) + abi_args = parser.parse_args() + if os.path.isfile(abi_args.report_dir): + print("Error: {} is not a directory".format(abi_args.report_dir)) + parser.exit() + old_version = SimpleNamespace( + version="old", + repository=abi_args.old_repo, + revision=abi_args.old_rev, + commit=None, + crypto_repository=abi_args.old_crypto_repo, + crypto_revision=abi_args.old_crypto_rev, + abi_dumps={}, + modules={} + ) + new_version = SimpleNamespace( + version="new", + repository=abi_args.new_repo, + revision=abi_args.new_rev, + commit=None, + crypto_repository=abi_args.new_crypto_repo, + crypto_revision=abi_args.new_crypto_rev, + abi_dumps={}, + modules={} + ) + configuration = SimpleNamespace( + verbose=abi_args.verbose, + report_dir=abi_args.report_dir, + keep_all_reports=abi_args.keep_all_reports, + brief=abi_args.brief, + skip_file=abi_args.skip_file + ) + abi_check = AbiChecker(old_version, new_version, configuration) + return_code = abi_check.check_for_abi_changes() + sys.exit(return_code) + except Exception: # pylint: disable=broad-except + # Print the backtrace and exit explicitly so as to exit with + # status 2, not 1. + traceback.print_exc() + sys.exit(2) + + +if __name__ == "__main__": + run_main() diff --git a/external/mbedtls/scripts/apidoc_full.sh b/external/mbedtls/scripts/apidoc_full.sh new file mode 100644 index 0000000..f2f511a --- /dev/null +++ b/external/mbedtls/scripts/apidoc_full.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +# Generate doxygen documentation with a full config.h (this ensures that every +# available flag is documented, and avoids warnings about documentation +# without a corresponding #define). +# +# /!\ This must not be a Makefile target, as it would create a race condition +# when multiple targets are invoked in the same parallel build. +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** + +set -eu + +CONFIG_H='include/mbedtls/config.h' + +if [ -r $CONFIG_H ]; then :; else + echo "$CONFIG_H not found" >&2 + exit 1 +fi + +CONFIG_BAK=${CONFIG_H}.bak +cp -p $CONFIG_H $CONFIG_BAK + +scripts/config.pl realfull +make apidoc + +mv $CONFIG_BAK $CONFIG_H diff --git a/external/mbedtls/scripts/assemble_changelog.py b/external/mbedtls/scripts/assemble_changelog.py new file mode 100644 index 0000000..02bae25 --- /dev/null +++ b/external/mbedtls/scripts/assemble_changelog.py @@ -0,0 +1,530 @@ +#!/usr/bin/env python3 + +"""Assemble Mbed TLS change log entries into the change log file. + +Add changelog entries to the first level-2 section. +Create a new level-2 section for unreleased changes if needed. +Remove the input files unless --keep-entries is specified. + +In each level-3 section, entries are sorted in chronological order +(oldest first). From oldest to newest: +* Merged entry files are sorted according to their merge date (date of + the merge commit that brought the commit that created the file into + the target branch). +* Committed but unmerged entry files are sorted according to the date + of the commit that adds them. +* Uncommitted entry files are sorted according to their modification time. + +You must run this program from within a git working directory. +""" + +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** + +import argparse +from collections import OrderedDict, namedtuple +import datetime +import functools +import glob +import os +import re +import subprocess +import sys + +class InputFormatError(Exception): + def __init__(self, filename, line_number, message, *args, **kwargs): + message = '{}:{}: {}'.format(filename, line_number, + message.format(*args, **kwargs)) + super().__init__(message) + +class CategoryParseError(Exception): + def __init__(self, line_offset, error_message): + self.line_offset = line_offset + self.error_message = error_message + super().__init__('{}: {}'.format(line_offset, error_message)) + +class LostContent(Exception): + def __init__(self, filename, line): + message = ('Lost content from {}: "{}"'.format(filename, line)) + super().__init__(message) + +# The category names we use in the changelog. +# If you edit this, update ChangeLog.d/README.md. +STANDARD_CATEGORIES = ( + b'API changes', + b'Default behavior changes', + b'Requirement changes', + b'New deprecations', + b'Removals', + b'Features', + b'Security', + b'Bugfix', + b'Changes', +) + +CategoryContent = namedtuple('CategoryContent', [ + 'name', 'title_line', # Title text and line number of the title + 'body', 'body_line', # Body text and starting line number of the body +]) + +class ChangelogFormat: + """Virtual class documenting how to write a changelog format class.""" + + @classmethod + def extract_top_version(cls, changelog_file_content): + """Split out the top version section. + + If the top version is already released, create a new top + version section for an unreleased version. + + Return ``(header, top_version_title, top_version_body, trailer)`` + where the "top version" is the existing top version section if it's + for unreleased changes, and a newly created section otherwise. + To assemble the changelog after modifying top_version_body, + concatenate the four pieces. + """ + raise NotImplementedError + + @classmethod + def version_title_text(cls, version_title): + """Return the text of a formatted version section title.""" + raise NotImplementedError + + @classmethod + def split_categories(cls, version_body): + """Split a changelog version section body into categories. + + Return a list of `CategoryContent` the name is category title + without any formatting. + """ + raise NotImplementedError + + @classmethod + def format_category(cls, title, body): + """Construct the text of a category section from its title and body.""" + raise NotImplementedError + +class TextChangelogFormat(ChangelogFormat): + """The traditional Mbed TLS changelog format.""" + + _unreleased_version_text = b'= mbed TLS x.x.x branch released xxxx-xx-xx' + @classmethod + def is_released_version(cls, title): + # Look for an incomplete release date + return not re.search(br'[0-9x]{4}-[0-9x]{2}-[0-9x]?x', title) + + _top_version_re = re.compile(br'(?:\A|\n)(=[^\n]*\n+)(.*?\n)(?:=|$)', + re.DOTALL) + @classmethod + def extract_top_version(cls, changelog_file_content): + """A version section starts with a line starting with '='.""" + m = re.search(cls._top_version_re, changelog_file_content) + top_version_start = m.start(1) + top_version_end = m.end(2) + top_version_title = m.group(1) + top_version_body = m.group(2) + if cls.is_released_version(top_version_title): + top_version_end = top_version_start + top_version_title = cls._unreleased_version_text + b'\n\n' + top_version_body = b'' + return (changelog_file_content[:top_version_start], + top_version_title, top_version_body, + changelog_file_content[top_version_end:]) + + @classmethod + def version_title_text(cls, version_title): + return re.sub(br'\n.*', version_title, re.DOTALL) + + _category_title_re = re.compile(br'(^\w.*)\n+', re.MULTILINE) + @classmethod + def split_categories(cls, version_body): + """A category title is a line with the title in column 0.""" + if not version_body: + return [] + title_matches = list(re.finditer(cls._category_title_re, version_body)) + if not title_matches or title_matches[0].start() != 0: + # There is junk before the first category. + raise CategoryParseError(0, 'Junk found where category expected') + title_starts = [m.start(1) for m in title_matches] + body_starts = [m.end(0) for m in title_matches] + body_ends = title_starts[1:] + [len(version_body)] + bodies = [version_body[body_start:body_end].rstrip(b'\n') + b'\n' + for (body_start, body_end) in zip(body_starts, body_ends)] + title_lines = [version_body[:pos].count(b'\n') for pos in title_starts] + body_lines = [version_body[:pos].count(b'\n') for pos in body_starts] + return [CategoryContent(title_match.group(1), title_line, + body, body_line) + for title_match, title_line, body, body_line + in zip(title_matches, title_lines, bodies, body_lines)] + + @classmethod + def format_category(cls, title, body): + # `split_categories` ensures that each body ends with a newline. + # Make sure that there is additionally a blank line between categories. + if not body.endswith(b'\n\n'): + body += b'\n' + return title + b'\n' + body + +class ChangeLog: + """An Mbed TLS changelog. + + A changelog file consists of some header text followed by one or + more version sections. The version sections are in reverse + chronological order. Each version section consists of a title and a body. + + The body of a version section consists of zero or more category + subsections. Each category subsection consists of a title and a body. + + A changelog entry file has the same format as the body of a version section. + + A `ChangelogFormat` object defines the concrete syntax of the changelog. + Entry files must have the same format as the changelog file. + """ + + # Only accept dotted version numbers (e.g. "3.1", not "3"). + # Refuse ".x" in a version number where x is a letter: this indicates + # a version that is not yet released. Something like "3.1a" is accepted. + _version_number_re = re.compile(br'[0-9]+\.[0-9A-Za-z.]+') + _incomplete_version_number_re = re.compile(br'.*\.[A-Za-z]') + + def add_categories_from_text(self, filename, line_offset, + text, allow_unknown_category): + """Parse a version section or entry file.""" + try: + categories = self.format.split_categories(text) + except CategoryParseError as e: + raise InputFormatError(filename, line_offset + e.line_offset, + e.error_message) + for category in categories: + if not allow_unknown_category and \ + category.name not in self.categories: + raise InputFormatError(filename, + line_offset + category.title_line, + 'Unknown category: "{}"', + category.name.decode('utf8')) + self.categories[category.name] += category.body + + def __init__(self, input_stream, changelog_format): + """Create a changelog object. + + Populate the changelog object from the content of the file + input_stream. + """ + self.format = changelog_format + whole_file = input_stream.read() + (self.header, + self.top_version_title, top_version_body, + self.trailer) = self.format.extract_top_version(whole_file) + # Split the top version section into categories. + self.categories = OrderedDict() + for category in STANDARD_CATEGORIES: + self.categories[category] = b'' + offset = (self.header + self.top_version_title).count(b'\n') + 1 + self.add_categories_from_text(input_stream.name, offset, + top_version_body, True) + + def add_file(self, input_stream): + """Add changelog entries from a file. + """ + self.add_categories_from_text(input_stream.name, 1, + input_stream.read(), False) + + def write(self, filename): + """Write the changelog to the specified file. + """ + with open(filename, 'wb') as out: + out.write(self.header) + out.write(self.top_version_title) + for title, body in self.categories.items(): + if not body: + continue + out.write(self.format.format_category(title, body)) + out.write(self.trailer) + + +@functools.total_ordering +class EntryFileSortKey: + """This classes defines an ordering on changelog entry files: older < newer. + + * Merged entry files are sorted according to their merge date (date of + the merge commit that brought the commit that created the file into + the target branch). + * Committed but unmerged entry files are sorted according to the date + of the commit that adds them. + * Uncommitted entry files are sorted according to their modification time. + + This class assumes that the file is in a git working directory with + the target branch checked out. + """ + + # Categories of files. A lower number is considered older. + MERGED = 0 + COMMITTED = 1 + LOCAL = 2 + + @staticmethod + def creation_hash(filename): + """Return the git commit id at which the given file was created. + + Return None if the file was never checked into git. + """ + hashes = subprocess.check_output(['git', 'log', '--format=%H', + '--follow', + '--', filename]) + m = re.search(b'(.+)$', hashes) + if not m: + # The git output is empty. This means that the file was + # never checked in. + return None + # The last commit in the log is the oldest one, which is when the + # file was created. + return m.group(0) + + @staticmethod + def list_merges(some_hash, target, *options): + """List merge commits from some_hash to target. + + Pass options to git to select which commits are included. + """ + text = subprocess.check_output(['git', 'rev-list', + '--merges', *options, + b'..'.join([some_hash, target])]) + return text.rstrip(b'\n').split(b'\n') + + @classmethod + def merge_hash(cls, some_hash): + """Return the git commit id at which the given commit was merged. + + Return None if the given commit was never merged. + """ + target = b'HEAD' + # List the merges from some_hash to the target in two ways. + # The ancestry list is the ones that are both descendants of + # some_hash and ancestors of the target. + ancestry = frozenset(cls.list_merges(some_hash, target, + '--ancestry-path')) + # The first_parents list only contains merges that are directly + # on the target branch. We want it in reverse order (oldest first). + first_parents = cls.list_merges(some_hash, target, + '--first-parent', '--reverse') + # Look for the oldest merge commit that's both on the direct path + # and directly on the target branch. That's the place where some_hash + # was merged on the target branch. See + # https://stackoverflow.com/questions/8475448/find-merge-commit-which-include-a-specific-commit + for commit in first_parents: + if commit in ancestry: + return commit + return None + + @staticmethod + def commit_timestamp(commit_id): + """Return the timestamp of the given commit.""" + text = subprocess.check_output(['git', 'show', '-s', + '--format=%ct', + commit_id]) + return datetime.datetime.utcfromtimestamp(int(text)) + + @staticmethod + def file_timestamp(filename): + """Return the modification timestamp of the given file.""" + mtime = os.stat(filename).st_mtime + return datetime.datetime.fromtimestamp(mtime) + + def __init__(self, filename): + """Determine position of the file in the changelog entry order. + + This constructor returns an object that can be used with comparison + operators, with `sort` and `sorted`, etc. Older entries are sorted + before newer entries. + """ + self.filename = filename + creation_hash = self.creation_hash(filename) + if not creation_hash: + self.category = self.LOCAL + self.datetime = self.file_timestamp(filename) + return + merge_hash = self.merge_hash(creation_hash) + if not merge_hash: + self.category = self.COMMITTED + self.datetime = self.commit_timestamp(creation_hash) + return + self.category = self.MERGED + self.datetime = self.commit_timestamp(merge_hash) + + def sort_key(self): + """"Return a concrete sort key for this entry file sort key object. + + ``ts1 < ts2`` is implemented as ``ts1.sort_key() < ts2.sort_key()``. + """ + return (self.category, self.datetime, self.filename) + + def __eq__(self, other): + return self.sort_key() == other.sort_key() + + def __lt__(self, other): + return self.sort_key() < other.sort_key() + + +def check_output(generated_output_file, main_input_file, merged_files): + """Make sanity checks on the generated output. + + The intent of these sanity checks is to have reasonable confidence + that no content has been lost. + + The sanity check is that every line that is present in an input file + is also present in an output file. This is not perfect but good enough + for now. + """ + generated_output = set(open(generated_output_file, 'rb')) + for line in open(main_input_file, 'rb'): + if line not in generated_output: + raise LostContent('original file', line) + for merged_file in merged_files: + for line in open(merged_file, 'rb'): + if line not in generated_output: + raise LostContent(merged_file, line) + +def finish_output(changelog, output_file, input_file, merged_files): + """Write the changelog to the output file. + + The input file and the list of merged files are used only for sanity + checks on the output. + """ + if os.path.exists(output_file) and not os.path.isfile(output_file): + # The output is a non-regular file (e.g. pipe). Write to it directly. + output_temp = output_file + else: + # The output is a regular file. Write to a temporary file, + # then move it into place atomically. + output_temp = output_file + '.tmp' + changelog.write(output_temp) + check_output(output_temp, input_file, merged_files) + if output_temp != output_file: + os.rename(output_temp, output_file) + +def remove_merged_entries(files_to_remove): + for filename in files_to_remove: + os.remove(filename) + +def list_files_to_merge(options): + """List the entry files to merge, oldest first. + + "Oldest" is defined by `EntryFileSortKey`. + """ + files_to_merge = glob.glob(os.path.join(options.dir, '*.txt')) + files_to_merge.sort(key=EntryFileSortKey) + return files_to_merge + +def merge_entries(options): + """Merge changelog entries into the changelog file. + + Read the changelog file from options.input. + Read entries to merge from the directory options.dir. + Write the new changelog to options.output. + Remove the merged entries if options.keep_entries is false. + """ + with open(options.input, 'rb') as input_file: + changelog = ChangeLog(input_file, TextChangelogFormat) + files_to_merge = list_files_to_merge(options) + if not files_to_merge: + sys.stderr.write('There are no pending changelog entries.\n') + return + for filename in files_to_merge: + with open(filename, 'rb') as input_file: + changelog.add_file(input_file) + finish_output(changelog, options.output, options.input, files_to_merge) + if not options.keep_entries: + remove_merged_entries(files_to_merge) + +def show_file_timestamps(options): + """List the files to merge and their timestamp. + + This is only intended for debugging purposes. + """ + files = list_files_to_merge(options) + for filename in files: + ts = EntryFileSortKey(filename) + print(ts.category, ts.datetime, filename) + +def set_defaults(options): + """Add default values for missing options.""" + output_file = getattr(options, 'output', None) + if output_file is None: + options.output = options.input + if getattr(options, 'keep_entries', None) is None: + options.keep_entries = (output_file is not None) + +def main(): + """Command line entry point.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--dir', '-d', metavar='DIR', + default='ChangeLog.d', + help='Directory to read entries from' + ' (default: ChangeLog.d)') + parser.add_argument('--input', '-i', metavar='FILE', + default='ChangeLog', + help='Existing changelog file to read from and augment' + ' (default: ChangeLog)') + parser.add_argument('--keep-entries', + action='store_true', dest='keep_entries', default=None, + help='Keep the files containing entries' + ' (default: remove them if --output/-o is not specified)') + parser.add_argument('--no-keep-entries', + action='store_false', dest='keep_entries', + help='Remove the files containing entries after they are merged' + ' (default: remove them if --output/-o is not specified)') + parser.add_argument('--output', '-o', metavar='FILE', + help='Output changelog file' + ' (default: overwrite the input)') + parser.add_argument('--list-files-only', + action='store_true', + help=('Only list the files that would be processed ' + '(with some debugging information)')) + options = parser.parse_args() + set_defaults(options) + if options.list_files_only: + show_file_timestamps(options) + return + merge_entries(options) + +if __name__ == '__main__': + main() diff --git a/external/mbedtls/scripts/bump_version.sh b/external/mbedtls/scripts/bump_version.sh new file mode 100644 index 0000000..5ac117f --- /dev/null +++ b/external/mbedtls/scripts/bump_version.sh @@ -0,0 +1,181 @@ +#!/bin/bash +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** +# +# Purpose +# +# Sets the version numbers in the source code to those given. +# +# Usage: bump_version.sh [ --version ] [ --so-crypto ] +# [ --so-x509 ] [ --so-tls ] +# [ -v | --verbose ] [ -h | --help ] +# + +VERSION="" +SOVERSION="" + +# Parse arguments +# +until [ -z "$1" ] +do + case "$1" in + --version) + # Version to use + shift + VERSION=$1 + ;; + --so-crypto) + shift + SO_CRYPTO=$1 + ;; + --so-x509) + shift + SO_X509=$1 + ;; + --so-tls) + shift + SO_TLS=$1 + ;; + -v|--verbose) + # Be verbose + VERBOSE="1" + ;; + -h|--help) + # print help + echo "Usage: $0" + echo -e " -h|--help\t\tPrint this help." + echo -e " --version \tVersion to bump to." + echo -e " --so-crypto \tSO version to bump libmbedcrypto to." + echo -e " --so-x509 \tSO version to bump libmbedx509 to." + echo -e " --so-tls \tSO version to bump libmbedtls to." + echo -e " -v|--verbose\t\tVerbose." + exit 1 + ;; + *) + # print error + echo "Unknown argument: '$1'" + exit 1 + ;; + esac + shift +done + +if [ "X" = "X$VERSION" ]; +then + echo "No version specified. Unable to continue." + exit 1 +fi + +[ $VERBOSE ] && echo "Bumping VERSION in library/CMakeLists.txt" +sed -e "s/ VERSION [0-9.]\{1,\}/ VERSION $VERSION/g" < library/CMakeLists.txt > tmp +mv tmp library/CMakeLists.txt + +if [ "X" != "X$SO_CRYPTO" ]; +then + [ $VERBOSE ] && echo "Bumping SOVERSION for libmbedcrypto in library/CMakeLists.txt" + sed -e "/mbedcrypto/ s/ SOVERSION [0-9]\{1,\}/ SOVERSION $SO_CRYPTO/g" < library/CMakeLists.txt > tmp + mv tmp library/CMakeLists.txt + + [ $VERBOSE ] && echo "Bumping SOVERSION for libmbedcrypto in library/Makefile" + sed -e "s/SOEXT_CRYPTO=so.[0-9]\{1,\}/SOEXT_CRYPTO=so.$SO_CRYPTO/g" < library/Makefile > tmp + mv tmp library/Makefile +fi + +if [ "X" != "X$SO_X509" ]; +then + [ $VERBOSE ] && echo "Bumping SOVERSION for libmbedx509 in library/CMakeLists.txt" + sed -e "/mbedx509/ s/ SOVERSION [0-9]\{1,\}/ SOVERSION $SO_X509/g" < library/CMakeLists.txt > tmp + mv tmp library/CMakeLists.txt + + [ $VERBOSE ] && echo "Bumping SOVERSION for libmbedx509 in library/Makefile" + sed -e "s/SOEXT_X509=so.[0-9]\{1,\}/SOEXT_X509=so.$SO_X509/g" < library/Makefile > tmp + mv tmp library/Makefile +fi + +if [ "X" != "X$SO_TLS" ]; +then + [ $VERBOSE ] && echo "Bumping SOVERSION for libmbedtls in library/CMakeLists.txt" + sed -e "/mbedtls/ s/ SOVERSION [0-9]\{1,\}/ SOVERSION $SO_TLS/g" < library/CMakeLists.txt > tmp + mv tmp library/CMakeLists.txt + + [ $VERBOSE ] && echo "Bumping SOVERSION for libmbedtls in library/Makefile" + sed -e "s/SOEXT_TLS=so.[0-9]\{1,\}/SOEXT_TLS=so.$SO_TLS/g" < library/Makefile > tmp + mv tmp library/Makefile +fi + +[ $VERBOSE ] && echo "Bumping VERSION in include/mbedtls/version.h" +read MAJOR MINOR PATCH <<<$(IFS="."; echo $VERSION) +VERSION_NR="$( printf "0x%02X%02X%02X00" $MAJOR $MINOR $PATCH )" +cat include/mbedtls/version.h | \ + sed -e "s/_VERSION_MAJOR .\{1,\}/_VERSION_MAJOR $MAJOR/" | \ + sed -e "s/_VERSION_MINOR .\{1,\}/_VERSION_MINOR $MINOR/" | \ + sed -e "s/_VERSION_PATCH .\{1,\}/_VERSION_PATCH $PATCH/" | \ + sed -e "s/_VERSION_NUMBER .\{1,\}/_VERSION_NUMBER $VERSION_NR/" | \ + sed -e "s/_VERSION_STRING .\{1,\}/_VERSION_STRING \"$VERSION\"/" | \ + sed -e "s/_VERSION_STRING_FULL .\{1,\}/_VERSION_STRING_FULL \"mbed TLS $VERSION\"/" \ + > tmp +mv tmp include/mbedtls/version.h + +[ $VERBOSE ] && echo "Bumping version in tests/suites/test_suite_version.data" +sed -e "s/version:\".\{1,\}/version:\"$VERSION\"/g" < tests/suites/test_suite_version.data > tmp +mv tmp tests/suites/test_suite_version.data + +[ $VERBOSE ] && echo "Bumping PROJECT_NAME in doxygen/mbedtls.doxyfile and doxygen/input/doc_mainpage.h" +for i in doxygen/mbedtls.doxyfile doxygen/input/doc_mainpage.h; +do + sed -e "s/mbed TLS v[0-9\.]\{1,\}/mbed TLS v$VERSION/g" < $i > tmp + mv tmp $i +done + +[ $VERBOSE ] && echo "Re-generating library/error.c" +scripts/generate_errors.pl + +[ $VERBOSE ] && echo "Re-generating programs/ssl/query_config.c" +scripts/generate_query_config.pl + +[ $VERBOSE ] && echo "Re-generating library/version_features.c" +scripts/generate_features.pl + +[ $VERBOSE ] && echo "Re-generating visualc files" +scripts/generate_visualc_files.pl + diff --git a/external/mbedtls/scripts/config.pl b/external/mbedtls/scripts/config.pl new file mode 100644 index 0000000..e5cc697 --- /dev/null +++ b/external/mbedtls/scripts/config.pl @@ -0,0 +1,336 @@ +#!/usr/bin/env perl +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** +# +# Purpose +# +# Comments and uncomments #define lines in the given header file and optionally +# sets their value or can get the value. This is to provide scripting control of +# what preprocessor symbols, and therefore what build time configuration flags +# are set in the 'config.h' file. +# +# Usage: config.pl [-f | --file ] [-o | --force] +# [set | unset | get | +# full | realfull] +# +# Full usage description provided below. +# +# The following options are disabled instead of enabled with "full". +# +# * Options that require additional build dependencies or unusual hardware. +# * Options that make testing less effective. +# * Options that are incompatible with other options, or more generally that +# interact with other parts of the code in such a way that a bulk enabling +# is not a good way to test them. +# * Options that remove features. +# +# The baremetal configuration excludes options that require a library or +# operating system feature that is typically not present on bare metal +# systems. Features that are excluded from "full" won't be in "baremetal" +# either. + +use warnings; +use strict; + +my $config_file = "include/mbedtls/config.h"; +my $usage = < | --file ] [-o | --force] + [set | unset | get | + full | realfull | baremetal] + +Commands + set [] - Uncomments or adds a #define for the to + the configuration file, and optionally making it + of . + If the symbol isn't present in the file an error + is returned. + unset - Comments out the #define for the given symbol if + present in the configuration file. + get - Finds the #define for the given symbol, returning + an exitcode of 0 if the symbol is found, and 1 if + not. The value of the symbol is output if one is + specified in the configuration file. + full - Uncomments all #define's in the configuration file + excluding some reserved symbols, until the + 'Module configuration options' section + realfull - Uncomments all #define's with no exclusions + baremetal - Sets full configuration suitable for baremetal build. + +Options + -f | --file - The file or file path for the configuration file + to edit. When omitted, the following default is + used: + $config_file + -o | --force - If the symbol isn't present in the configuration + file when setting its value, a #define is + appended to the end of the file. + +EOU + +my @excluded = qw( +MBEDTLS_CTR_DRBG_USE_128_BIT_KEY +MBEDTLS_DEPRECATED_REMOVED +MBEDTLS_DEPRECATED_WARNING +MBEDTLS_ECP_NO_INTERNAL_RNG +MBEDTLS_HAVE_SSE2 +MBEDTLS_MEMORY_BACKTRACE +MBEDTLS_MEMORY_BUFFER_ALLOC_C +MBEDTLS_MEMORY_DEBUG +MBEDTLS_NO_64BIT_MULTIPLICATION +MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +MBEDTLS_NO_PLATFORM_ENTROPY +MBEDTLS_NO_UDBL_DIVISION +MBEDTLS_PKCS11_C +MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +MBEDTLS_REMOVE_3DES_CIPHERSUITES +MBEDTLS_REMOVE_ARC4_CIPHERSUITES +MBEDTLS_RSA_NO_CRT +MBEDTLS_SSL_HW_RECORD_ACCEL +MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN +MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND +MBEDTLS_TEST_NULL_ENTROPY +MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +MBEDTLS_ZLIB_SUPPORT +_ALT\s*$ +); + +# Things that should be disabled in "baremetal" +my @excluded_baremetal = qw( +MBEDTLS_ENTROPY_NV_SEED +MBEDTLS_FS_IO +MBEDTLS_HAVEGE_C +MBEDTLS_HAVE_TIME +MBEDTLS_HAVE_TIME_DATE +MBEDTLS_MEMORY_BACKTRACE +MBEDTLS_MEMORY_BUFFER_ALLOC_C +MBEDTLS_NET_C +MBEDTLS_PLATFORM_FPRINTF_ALT +MBEDTLS_PLATFORM_NV_SEED_ALT +MBEDTLS_PLATFORM_TIME_ALT +MBEDTLS_THREADING_C +MBEDTLS_THREADING_PTHREAD +MBEDTLS_TIMING_C +); + +# Things that should be enabled in "full" even if they match @excluded. +# Platform ALTs enable global variables that allow configuring the behavior +# but default to the default behavior, except for PLATFORM_SETUP_TEARDOWN_ALT +# which requires the application to provide relevant functions like +# non-platform ALTs. +my @non_excluded = qw( +PLATFORM_(?!SETUP_TEARDOWN_)[A-Z_0-9]+_ALT +); + +# Things that should be enabled in "baremetal" +my @non_excluded_baremetal = qw( +MBEDTLS_NO_PLATFORM_ENTROPY +); + +# Process the command line arguments + +my $force_option = 0; + +my ($arg, $name, $value, $action); + +while ($arg = shift) { + + # Check if the argument is an option + if ($arg eq "-f" || $arg eq "--file") { + $config_file = shift; + + -f $config_file or die "No such file: $config_file\n"; + + } + elsif ($arg eq "-o" || $arg eq "--force") { + $force_option = 1; + + } + else + { + # ...else assume it's a command + $action = $arg; + + if ($action eq "full" || $action eq "realfull" || $action eq "baremetal" ) { + # No additional parameters + die $usage if @ARGV; + + } + elsif ($action eq "unset" || $action eq "get") { + die $usage unless @ARGV; + $name = shift; + + } + elsif ($action eq "set") { + die $usage unless @ARGV; + $name = shift; + $value = shift if @ARGV; + + } + else { + die "Command '$action' not recognised.\n\n".$usage; + } + } +} + +# If no command was specified, exit... +if ( not defined($action) ){ die $usage; } + +# Check the config file is present +if (! -f $config_file) { + + chdir '..' or die; + + # Confirm this is the project root directory and try again + if ( !(-d 'scripts' && -d 'include' && -d 'library' && -f $config_file) ) { + die "If no file specified, must be run from the project root or scripts directory.\n"; + } +} + + +# Now read the file and process the contents + +open my $config_read, '<', $config_file or die "read $config_file: $!\n"; +my @config_lines = <$config_read>; +close $config_read; + +# Add required baremetal symbols to the list that is included. +if ( $action eq "baremetal" ) { + @non_excluded = ( @non_excluded, @non_excluded_baremetal ); +} + +my ($exclude_re, $no_exclude_re, $exclude_baremetal_re); +if ($action eq "realfull") { + $exclude_re = qr/^$/; + $no_exclude_re = qr/./; +} else { + $exclude_re = join '|', @excluded; + $no_exclude_re = join '|', @non_excluded; +} +if ( $action eq "baremetal" ) { + $exclude_baremetal_re = join '|', @excluded_baremetal; +} + +my $config_write = undef; +if ($action ne "get") { + open $config_write, '>', $config_file or die "write $config_file: $!\n"; +} + +my $done; +for my $line (@config_lines) { + if ($action eq "full" || $action eq "realfull" || $action eq "baremetal" ) { + if ($line =~ /name SECTION: Module configuration options/) { + $done = 1; + } + + if (!$done && $line =~ m!^//\s?#define! && + ( $line !~ /$exclude_re/ || $line =~ /$no_exclude_re/ ) && + ( $action ne "baremetal" || ( $line !~ /$exclude_baremetal_re/ ) ) ) { + $line =~ s!^//\s?!!; + } + if (!$done && $line =~ m!^\s?#define! && + ! ( ( $line !~ /$exclude_re/ || $line =~ /$no_exclude_re/ ) && + ( $action ne "baremetal" || ( $line !~ /$exclude_baremetal_re/ ) ) ) ) { + $line =~ s!^!//!; + } + } elsif ($action eq "unset") { + if (!$done && $line =~ /^\s*#define\s*$name\b/) { + $line = '//' . $line; + $done = 1; + } + } elsif (!$done && $action eq "set") { + if ($line =~ m!^(?://)?\s*#define\s*$name\b!) { + $line = "#define $name"; + $line .= " $value" if defined $value && $value ne ""; + $line .= "\n"; + $done = 1; + } + } elsif (!$done && $action eq "get") { + if ($line =~ /^\s*#define\s*$name(?:\s+(.*?))\s*(?:$|\/\*|\/\/)/) { + $value = $1; + $done = 1; + } + } + + if (defined $config_write) { + print $config_write $line or die "write $config_file: $!\n"; + } +} + +# Did the set command work? +if ($action eq "set" && $force_option && !$done) { + + # If the force option was set, append the symbol to the end of the file + my $line = "#define $name"; + $line .= " $value" if defined $value && $value ne ""; + $line .= "\n"; + $done = 1; + + print $config_write $line or die "write $config_file: $!\n"; +} + +if (defined $config_write) { + close $config_write or die "close $config_file: $!\n"; +} + +if ($action eq "get") { + if ($done) { + if ($value ne '') { + print "$value\n"; + } + exit 0; + } else { + # If the symbol was not found, return an error + exit 1; + } +} + +if ($action eq "full" && !$done) { + die "Configuration section was not found in $config_file\n"; + +} + +if ($action ne "full" && $action ne "unset" && !$done) { + die "A #define for the symbol $name was not found in $config_file\n"; +} + +__END__ diff --git a/external/mbedtls/scripts/data_files/error.fmt b/external/mbedtls/scripts/data_files/error.fmt new file mode 100644 index 0000000..c5c8707 --- /dev/null +++ b/external/mbedtls/scripts/data_files/error.fmt @@ -0,0 +1,145 @@ +/* + * Error message information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) + +#include "mbedtls/error.h" + +#if defined(MBEDTLS_ERROR_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +#include +#include + +HEADER_INCLUDED + +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + size_t len; + int use_ret; + + if( buflen == 0 ) + return; + + memset( buf, 0x00, buflen ); + + if( ret < 0 ) + ret = -ret; + + if( ret & 0xFF80 ) + { + use_ret = ret & 0xFF80; + + // High level error codes + // + // BEGIN generated code +HIGH_LEVEL_CODE_CHECKS + // END generated code + + if( strlen( buf ) == 0 ) + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); + } + + use_ret = ret & ~0xFF80; + + if( use_ret == 0 ) + return; + + // If high level code is present, make a concatenation between both + // error strings. + // + len = strlen( buf ); + + if( len > 0 ) + { + if( buflen - len < 5 ) + return; + + mbedtls_snprintf( buf + len, buflen - len, " : " ); + + buf += len + 3; + buflen -= len + 3; + } + + // Low level error codes + // + // BEGIN generated code +LOW_LEVEL_CODE_CHECKS + // END generated code + + if( strlen( buf ) != 0 ) + return; + + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); +} + +#else /* MBEDTLS_ERROR_C */ + +/* + * Provide an non-function in case MBEDTLS_ERROR_C is not defined + */ +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + ((void) ret); + + if( buflen > 0 ) + buf[0] = '\0'; +} + +#endif /* MBEDTLS_ERROR_C */ + +#endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */ diff --git a/external/mbedtls/scripts/data_files/query_config.fmt b/external/mbedtls/scripts/data_files/query_config.fmt new file mode 100644 index 0000000..dc91d83 --- /dev/null +++ b/external/mbedtls/scripts/data_files/query_config.fmt @@ -0,0 +1,164 @@ +/* + * Query Mbed TLS compile time configurations from config.h + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ + +/* + * Include all the headers with public APIs in case they define a macro to its + * default value when that configuration is not set in the config.h. + */ +#include "mbedtls/aes.h" +#include "mbedtls/aesni.h" +#include "mbedtls/arc4.h" +#include "mbedtls/aria.h" +#include "mbedtls/asn1.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/base64.h" +#include "mbedtls/bignum.h" +#include "mbedtls/blowfish.h" +#include "mbedtls/camellia.h" +#include "mbedtls/ccm.h" +#include "mbedtls/certs.h" +#include "mbedtls/chacha20.h" +#include "mbedtls/chachapoly.h" +#include "mbedtls/cipher.h" +#include "mbedtls/cmac.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/debug.h" +#include "mbedtls/des.h" +#include "mbedtls/dhm.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/ecdsa.h" +#include "mbedtls/ecjpake.h" +#include "mbedtls/ecp.h" +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" +#include "mbedtls/error.h" +#include "mbedtls/gcm.h" +#include "mbedtls/havege.h" +#include "mbedtls/hkdf.h" +#include "mbedtls/hmac_drbg.h" +#include "mbedtls/md.h" +#include "mbedtls/md2.h" +#include "mbedtls/md4.h" +#include "mbedtls/md5.h" +#include "mbedtls/memory_buffer_alloc.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/nist_kw.h" +#include "mbedtls/oid.h" +#include "mbedtls/padlock.h" +#include "mbedtls/pem.h" +#include "mbedtls/pk.h" +#include "mbedtls/pkcs11.h" +#include "mbedtls/pkcs12.h" +#include "mbedtls/pkcs5.h" +#include "mbedtls/platform_time.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/poly1305.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/rsa.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_cache.h" +#include "mbedtls/ssl_ciphersuites.h" +#include "mbedtls/ssl_cookie.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/ssl_ticket.h" +#include "mbedtls/threading.h" +#include "mbedtls/timing.h" +#include "mbedtls/version.h" +#include "mbedtls/x509.h" +#include "mbedtls/x509_crl.h" +#include "mbedtls/x509_crt.h" +#include "mbedtls/x509_csr.h" +#include "mbedtls/xtea.h" + +#include + +/* + * Helper macros to convert a macro or its expansion into a string + * WARNING: This does not work for expanding function-like macros. However, + * Mbed TLS does not currently have configuration options used in this fashion. + */ +#define MACRO_EXPANSION_TO_STR(macro) MACRO_NAME_TO_STR(macro) +#define MACRO_NAME_TO_STR(macro) \ + mbedtls_printf( "%s", strlen( #macro "" ) > 0 ? #macro "\n" : "" ) + +#if defined(_MSC_VER) +/* + * Visual Studio throws the warning 4003 because many Mbed TLS feature macros + * are defined empty. This means that from the preprocessor's point of view + * the macro MBEDTLS_EXPANSION_TO_STR is being invoked without arguments as + * some macros expand to nothing. We suppress that specific warning to get a + * clean build and to ensure that tests treating warnings as errors do not + * fail. + */ +#pragma warning(push) +#pragma warning(disable:4003) +#endif /* _MSC_VER */ + +int query_config( const char *config ) +{ +CHECK_CONFIG /* If the symbol is not found, return an error */ + return( 1 ); +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif /* _MSC_VER */ diff --git a/external/mbedtls/scripts/data_files/rename-1.3-2.0.txt b/external/mbedtls/scripts/data_files/rename-1.3-2.0.txt new file mode 100644 index 0000000..cb3381a --- /dev/null +++ b/external/mbedtls/scripts/data_files/rename-1.3-2.0.txt @@ -0,0 +1,2174 @@ +AES_DECRYPT MBEDTLS_AES_DECRYPT +AES_ENCRYPT MBEDTLS_AES_ENCRYPT +ASN1_BIT_STRING MBEDTLS_ASN1_BIT_STRING +ASN1_BMP_STRING MBEDTLS_ASN1_BMP_STRING +ASN1_BOOLEAN MBEDTLS_ASN1_BOOLEAN +ASN1_CHK_ADD MBEDTLS_ASN1_CHK_ADD +ASN1_CONSTRUCTED MBEDTLS_ASN1_CONSTRUCTED +ASN1_CONTEXT_SPECIFIC MBEDTLS_ASN1_CONTEXT_SPECIFIC +ASN1_GENERALIZED_TIME MBEDTLS_ASN1_GENERALIZED_TIME +ASN1_IA5_STRING MBEDTLS_ASN1_IA5_STRING +ASN1_INTEGER MBEDTLS_ASN1_INTEGER +ASN1_NULL MBEDTLS_ASN1_NULL +ASN1_OCTET_STRING MBEDTLS_ASN1_OCTET_STRING +ASN1_OID MBEDTLS_ASN1_OID +ASN1_PRIMITIVE MBEDTLS_ASN1_PRIMITIVE +ASN1_PRINTABLE_STRING MBEDTLS_ASN1_PRINTABLE_STRING +ASN1_SEQUENCE MBEDTLS_ASN1_SEQUENCE +ASN1_SET MBEDTLS_ASN1_SET +ASN1_T61_STRING MBEDTLS_ASN1_T61_STRING +ASN1_UNIVERSAL_STRING MBEDTLS_ASN1_UNIVERSAL_STRING +ASN1_UTC_TIME MBEDTLS_ASN1_UTC_TIME +ASN1_UTF8_STRING MBEDTLS_ASN1_UTF8_STRING +BADCERT_CN_MISMATCH MBEDTLS_X509_BADCERT_CN_MISMATCH +BADCERT_EXPIRED MBEDTLS_X509_BADCERT_EXPIRED +BADCERT_EXT_KEY_USAGE MBEDTLS_X509_BADCERT_EXT_KEY_USAGE +BADCERT_FUTURE MBEDTLS_X509_BADCERT_FUTURE +BADCERT_KEY_USAGE MBEDTLS_X509_BADCERT_KEY_USAGE +BADCERT_MISSING MBEDTLS_X509_BADCERT_MISSING +BADCERT_NOT_TRUSTED MBEDTLS_X509_BADCERT_NOT_TRUSTED +BADCERT_NS_CERT_TYPE MBEDTLS_X509_BADCERT_NS_CERT_TYPE +BADCERT_OTHER MBEDTLS_X509_BADCERT_OTHER +BADCERT_REVOKED MBEDTLS_X509_BADCERT_REVOKED +BADCERT_SKIP_VERIFY MBEDTLS_X509_BADCERT_SKIP_VERIFY +BADCRL_EXPIRED MBEDTLS_X509_BADCRL_EXPIRED +BADCRL_FUTURE MBEDTLS_X509_BADCRL_FUTURE +BADCRL_NOT_TRUSTED MBEDTLS_X509_BADCRL_NOT_TRUSTED +BLOWFISH_BLOCKSIZE MBEDTLS_BLOWFISH_BLOCKSIZE +BLOWFISH_DECRYPT MBEDTLS_BLOWFISH_DECRYPT +BLOWFISH_ENCRYPT MBEDTLS_BLOWFISH_ENCRYPT +BLOWFISH_MAX_KEY MBEDTLS_BLOWFISH_MAX_KEY_BITS +BLOWFISH_MIN_KEY MBEDTLS_BLOWFISH_MIN_KEY_BITS +BLOWFISH_ROUNDS MBEDTLS_BLOWFISH_ROUNDS +CAMELLIA_DECRYPT MBEDTLS_CAMELLIA_DECRYPT +CAMELLIA_ENCRYPT MBEDTLS_CAMELLIA_ENCRYPT +COLLECT_SIZE MBEDTLS_HAVEGE_COLLECT_SIZE +CTR_DRBG_BLOCKSIZE MBEDTLS_CTR_DRBG_BLOCKSIZE +CTR_DRBG_ENTROPY_LEN MBEDTLS_CTR_DRBG_ENTROPY_LEN +CTR_DRBG_KEYBITS MBEDTLS_CTR_DRBG_KEYBITS +CTR_DRBG_KEYSIZE MBEDTLS_CTR_DRBG_KEYSIZE +CTR_DRBG_MAX_INPUT MBEDTLS_CTR_DRBG_MAX_INPUT +CTR_DRBG_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST +CTR_DRBG_MAX_SEED_INPUT MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +CTR_DRBG_PR_OFF MBEDTLS_CTR_DRBG_PR_OFF +CTR_DRBG_PR_ON MBEDTLS_CTR_DRBG_PR_ON +CTR_DRBG_RESEED_INTERVAL MBEDTLS_CTR_DRBG_RESEED_INTERVAL +CTR_DRBG_SEEDLEN MBEDTLS_CTR_DRBG_SEEDLEN +DEPRECATED MBEDTLS_DEPRECATED +DES_DECRYPT MBEDTLS_DES_DECRYPT +DES_ENCRYPT MBEDTLS_DES_ENCRYPT +DES_KEY_SIZE MBEDTLS_DES_KEY_SIZE +ENTROPY_BLOCK_SIZE MBEDTLS_ENTROPY_BLOCK_SIZE +ENTROPY_MAX_GATHER MBEDTLS_ENTROPY_MAX_GATHER +ENTROPY_MAX_SEED_SIZE MBEDTLS_ENTROPY_MAX_SEED_SIZE +ENTROPY_MAX_SOURCES MBEDTLS_ENTROPY_MAX_SOURCES +ENTROPY_MIN_HARDCLOCK MBEDTLS_ENTROPY_MIN_HARDCLOCK +ENTROPY_MIN_HAVEGE MBEDTLS_ENTROPY_MIN_HAVEGE +ENTROPY_MIN_PLATFORM MBEDTLS_ENTROPY_MIN_PLATFORM +ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_SOURCE_MANUAL +EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER +EXT_BASIC_CONSTRAINTS MBEDTLS_X509_EXT_BASIC_CONSTRAINTS +EXT_CERTIFICATE_POLICIES MBEDTLS_X509_EXT_CERTIFICATE_POLICIES +EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS +EXT_EXTENDED_KEY_USAGE MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE +EXT_FRESHEST_CRL MBEDTLS_X509_EXT_FRESHEST_CRL +EXT_INIHIBIT_ANYPOLICY MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY +EXT_ISSUER_ALT_NAME MBEDTLS_X509_EXT_ISSUER_ALT_NAME +EXT_KEY_USAGE MBEDTLS_X509_EXT_KEY_USAGE +EXT_NAME_CONSTRAINTS MBEDTLS_X509_EXT_NAME_CONSTRAINTS +EXT_NS_CERT_TYPE MBEDTLS_X509_EXT_NS_CERT_TYPE +EXT_POLICY_CONSTRAINTS MBEDTLS_X509_EXT_POLICY_CONSTRAINTS +EXT_POLICY_MAPPINGS MBEDTLS_X509_EXT_POLICY_MAPPINGS +EXT_SUBJECT_ALT_NAME MBEDTLS_X509_EXT_SUBJECT_ALT_NAME +EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS +EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER +GCM_DECRYPT MBEDTLS_GCM_DECRYPT +GCM_ENCRYPT MBEDTLS_GCM_ENCRYPT +KU_CRL_SIGN MBEDTLS_X509_KU_CRL_SIGN +KU_DATA_ENCIPHERMENT MBEDTLS_X509_KU_DATA_ENCIPHERMENT +KU_DIGITAL_SIGNATURE MBEDTLS_X509_KU_DIGITAL_SIGNATURE +KU_KEY_AGREEMENT MBEDTLS_X509_KU_KEY_AGREEMENT +KU_KEY_CERT_SIGN MBEDTLS_X509_KU_KEY_CERT_SIGN +KU_KEY_ENCIPHERMENT MBEDTLS_X509_KU_KEY_ENCIPHERMENT +KU_NON_REPUDIATION MBEDTLS_X509_KU_NON_REPUDIATION +LN_2_DIV_LN_10_SCALE100 MBEDTLS_LN_2_DIV_LN_10_SCALE100 +MD_CONTEXT_T_INIT MBEDTLS_MD_CONTEXT_T_INIT +MEMORY_VERIFY_ALLOC MBEDTLS_MEMORY_VERIFY_ALLOC +MEMORY_VERIFY_ALWAYS MBEDTLS_MEMORY_VERIFY_ALWAYS +MEMORY_VERIFY_FREE MBEDTLS_MEMORY_VERIFY_FREE +MEMORY_VERIFY_NONE MBEDTLS_MEMORY_VERIFY_NONE +MPI_CHK MBEDTLS_MPI_CHK +NET_PROTO_TCP MBEDTLS_NET_PROTO_TCP +NET_PROTO_UDP MBEDTLS_NET_PROTO_UDP +NS_CERT_TYPE_EMAIL MBEDTLS_X509_NS_CERT_TYPE_EMAIL +NS_CERT_TYPE_EMAIL_CA MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA +NS_CERT_TYPE_OBJECT_SIGNING MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING +NS_CERT_TYPE_OBJECT_SIGNING_CA MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA +NS_CERT_TYPE_RESERVED MBEDTLS_X509_NS_CERT_TYPE_RESERVED +NS_CERT_TYPE_SSL_CA MBEDTLS_X509_NS_CERT_TYPE_SSL_CA +NS_CERT_TYPE_SSL_CLIENT MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT +NS_CERT_TYPE_SSL_SERVER MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER +OID_ANSI_X9_62 MBEDTLS_OID_ANSI_X9_62 +OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE +OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD +OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62_SIG +OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 +OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE +OID_AT MBEDTLS_OID_AT +OID_AT_CN MBEDTLS_OID_AT_CN +OID_AT_COUNTRY MBEDTLS_OID_AT_COUNTRY +OID_AT_DN_QUALIFIER MBEDTLS_OID_AT_DN_QUALIFIER +OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT_GENERATION_QUALIFIER +OID_AT_GIVEN_NAME MBEDTLS_OID_AT_GIVEN_NAME +OID_AT_INITIALS MBEDTLS_OID_AT_INITIALS +OID_AT_LOCALITY MBEDTLS_OID_AT_LOCALITY +OID_AT_ORGANIZATION MBEDTLS_OID_AT_ORGANIZATION +OID_AT_ORG_UNIT MBEDTLS_OID_AT_ORG_UNIT +OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT_POSTAL_ADDRESS +OID_AT_POSTAL_CODE MBEDTLS_OID_AT_POSTAL_CODE +OID_AT_PSEUDONYM MBEDTLS_OID_AT_PSEUDONYM +OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT_SERIAL_NUMBER +OID_AT_STATE MBEDTLS_OID_AT_STATE +OID_AT_SUR_NAME MBEDTLS_OID_AT_SUR_NAME +OID_AT_TITLE MBEDTLS_OID_AT_TITLE +OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT_UNIQUE_IDENTIFIER +OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER +OID_BASIC_CONSTRAINTS MBEDTLS_OID_BASIC_CONSTRAINTS +OID_CERTICOM MBEDTLS_OID_CERTICOM +OID_CERTIFICATE_POLICIES MBEDTLS_OID_CERTIFICATE_POLICIES +OID_CLIENT_AUTH MBEDTLS_OID_CLIENT_AUTH +OID_CMP MBEDTLS_OID_CMP +OID_CODE_SIGNING MBEDTLS_OID_CODE_SIGNING +OID_COUNTRY_US MBEDTLS_OID_COUNTRY_US +OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_CRL_DISTRIBUTION_POINTS +OID_CRL_NUMBER MBEDTLS_OID_CRL_NUMBER +OID_DES_CBC MBEDTLS_OID_DES_CBC +OID_DES_EDE3_CBC MBEDTLS_OID_DES_EDE3_CBC +OID_DIGEST_ALG_MD2 MBEDTLS_OID_DIGEST_ALG_MD2 +OID_DIGEST_ALG_MD4 MBEDTLS_OID_DIGEST_ALG_MD4 +OID_DIGEST_ALG_MD5 MBEDTLS_OID_DIGEST_ALG_MD5 +OID_DIGEST_ALG_SHA1 MBEDTLS_OID_DIGEST_ALG_SHA1 +OID_DIGEST_ALG_SHA224 MBEDTLS_OID_DIGEST_ALG_SHA224 +OID_DIGEST_ALG_SHA256 MBEDTLS_OID_DIGEST_ALG_SHA256 +OID_DIGEST_ALG_SHA384 MBEDTLS_OID_DIGEST_ALG_SHA384 +OID_DIGEST_ALG_SHA512 MBEDTLS_OID_DIGEST_ALG_SHA512 +OID_DOMAIN_COMPONENT MBEDTLS_OID_DOMAIN_COMPONENT +OID_ECDSA_SHA1 MBEDTLS_OID_ECDSA_SHA1 +OID_ECDSA_SHA224 MBEDTLS_OID_ECDSA_SHA224 +OID_ECDSA_SHA256 MBEDTLS_OID_ECDSA_SHA256 +OID_ECDSA_SHA384 MBEDTLS_OID_ECDSA_SHA384 +OID_ECDSA_SHA512 MBEDTLS_OID_ECDSA_SHA512 +OID_EC_ALG_ECDH MBEDTLS_OID_EC_ALG_ECDH +OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_EC_ALG_UNRESTRICTED +OID_EC_BRAINPOOL_V1 MBEDTLS_OID_EC_BRAINPOOL_V1 +OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_GRP_BP256R1 +OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_GRP_BP384R1 +OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_GRP_BP512R1 +OID_EC_GRP_SECP192K1 MBEDTLS_OID_EC_GRP_SECP192K1 +OID_EC_GRP_SECP192R1 MBEDTLS_OID_EC_GRP_SECP192R1 +OID_EC_GRP_SECP224K1 MBEDTLS_OID_EC_GRP_SECP224K1 +OID_EC_GRP_SECP224R1 MBEDTLS_OID_EC_GRP_SECP224R1 +OID_EC_GRP_SECP256K1 MBEDTLS_OID_EC_GRP_SECP256K1 +OID_EC_GRP_SECP256R1 MBEDTLS_OID_EC_GRP_SECP256R1 +OID_EC_GRP_SECP384R1 MBEDTLS_OID_EC_GRP_SECP384R1 +OID_EC_GRP_SECP521R1 MBEDTLS_OID_EC_GRP_SECP521R1 +OID_EMAIL_PROTECTION MBEDTLS_OID_EMAIL_PROTECTION +OID_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE +OID_FRESHEST_CRL MBEDTLS_OID_FRESHEST_CRL +OID_GOV MBEDTLS_OID_GOV +OID_HMAC_SHA1 MBEDTLS_OID_HMAC_SHA1 +OID_ID_CE MBEDTLS_OID_ID_CE +OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_INIHIBIT_ANYPOLICY +OID_ISO_CCITT_DS MBEDTLS_OID_ISO_CCITT_DS +OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ISO_IDENTIFIED_ORG +OID_ISO_ITU_COUNTRY MBEDTLS_OID_ISO_ITU_COUNTRY +OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_US_ORG +OID_ISO_MEMBER_BODIES MBEDTLS_OID_ISO_MEMBER_BODIES +OID_ISSUER_ALT_NAME MBEDTLS_OID_ISSUER_ALT_NAME +OID_KEY_USAGE MBEDTLS_OID_KEY_USAGE +OID_KP MBEDTLS_OID_KP +OID_MGF1 MBEDTLS_OID_MGF1 +OID_NAME_CONSTRAINTS MBEDTLS_OID_NAME_CONSTRAINTS +OID_NETSCAPE MBEDTLS_OID_NETSCAPE +OID_NS_BASE_URL MBEDTLS_OID_NS_BASE_URL +OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CA_POLICY_URL +OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CA_REVOCATION_URL +OID_NS_CERT MBEDTLS_OID_NS_CERT +OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_CERT_SEQUENCE +OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT_TYPE +OID_NS_COMMENT MBEDTLS_OID_NS_COMMENT +OID_NS_DATA_TYPE MBEDTLS_OID_NS_DATA_TYPE +OID_NS_RENEWAL_URL MBEDTLS_OID_NS_RENEWAL_URL +OID_NS_REVOCATION_URL MBEDTLS_OID_NS_REVOCATION_URL +OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_SSL_SERVER_NAME +OID_OCSP_SIGNING MBEDTLS_OID_OCSP_SIGNING +OID_OIW_SECSIG MBEDTLS_OID_OIW_SECSIG +OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG_ALG +OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_SHA1 +OID_ORGANIZATION MBEDTLS_OID_ORGANIZATION +OID_ORG_ANSI_X9_62 MBEDTLS_OID_ORG_ANSI_X9_62 +OID_ORG_CERTICOM MBEDTLS_OID_ORG_CERTICOM +OID_ORG_DOD MBEDTLS_OID_ORG_DOD +OID_ORG_GOV MBEDTLS_OID_ORG_GOV +OID_ORG_NETSCAPE MBEDTLS_OID_ORG_NETSCAPE +OID_ORG_OIW MBEDTLS_OID_ORG_OIW +OID_ORG_RSA_DATA_SECURITY MBEDTLS_OID_ORG_RSA_DATA_SECURITY +OID_ORG_TELETRUST MBEDTLS_OID_ORG_TELETRUST +OID_PKCS MBEDTLS_OID_PKCS +OID_PKCS1 MBEDTLS_OID_PKCS1 +OID_PKCS12 MBEDTLS_OID_PKCS12 +OID_PKCS12_PBE MBEDTLS_OID_PKCS12_PBE +OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC +OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC +OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC +OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC +OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 +OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 +OID_PKCS1_MD2 MBEDTLS_OID_PKCS1_MD2 +OID_PKCS1_MD4 MBEDTLS_OID_PKCS1_MD4 +OID_PKCS1_MD5 MBEDTLS_OID_PKCS1_MD5 +OID_PKCS1_RSA MBEDTLS_OID_PKCS1_RSA +OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1_SHA1 +OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1_SHA224 +OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1_SHA256 +OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1_SHA384 +OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1_SHA512 +OID_PKCS5 MBEDTLS_OID_PKCS5 +OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5_PBES2 +OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC +OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC +OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC +OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC +OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC +OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC +OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5_PBKDF2 +OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5_PBMAC1 +OID_PKCS9 MBEDTLS_OID_PKCS9 +OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9_CSR_EXT_REQ +OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9_EMAIL +OID_PKIX MBEDTLS_OID_PKIX +OID_POLICY_CONSTRAINTS MBEDTLS_OID_POLICY_CONSTRAINTS +OID_POLICY_MAPPINGS MBEDTLS_OID_POLICY_MAPPINGS +OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD +OID_RSASSA_PSS MBEDTLS_OID_RSASSA_PSS +OID_RSA_COMPANY MBEDTLS_OID_RSA_COMPANY +OID_RSA_SHA_OBS MBEDTLS_OID_RSA_SHA_OBS +OID_SERVER_AUTH MBEDTLS_OID_SERVER_AUTH +OID_SIZE MBEDTLS_OID_SIZE +OID_SUBJECT_ALT_NAME MBEDTLS_OID_SUBJECT_ALT_NAME +OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS +OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER +OID_TELETRUST MBEDTLS_OID_TELETRUST +OID_TIME_STAMPING MBEDTLS_OID_TIME_STAMPING +PADLOCK_ACE MBEDTLS_PADLOCK_ACE +PADLOCK_ALIGN16 MBEDTLS_PADLOCK_ALIGN16 +PADLOCK_PHE MBEDTLS_PADLOCK_PHE +PADLOCK_PMM MBEDTLS_PADLOCK_PMM +PADLOCK_RNG MBEDTLS_PADLOCK_RNG +PKCS12_DERIVE_IV MBEDTLS_PKCS12_DERIVE_IV +PKCS12_DERIVE_KEY MBEDTLS_PKCS12_DERIVE_KEY +PKCS12_DERIVE_MAC_KEY MBEDTLS_PKCS12_DERIVE_MAC_KEY +PKCS12_PBE_DECRYPT MBEDTLS_PKCS12_PBE_DECRYPT +PKCS12_PBE_ENCRYPT MBEDTLS_PKCS12_PBE_ENCRYPT +PKCS5_DECRYPT MBEDTLS_PKCS5_DECRYPT +PKCS5_ENCRYPT MBEDTLS_PKCS5_ENCRYPT +POLARSSL_AESNI_AES MBEDTLS_AESNI_AES +POLARSSL_AESNI_C MBEDTLS_AESNI_C +POLARSSL_AESNI_CLMUL MBEDTLS_AESNI_CLMUL +POLARSSL_AESNI_H MBEDTLS_AESNI_H +POLARSSL_AES_ALT MBEDTLS_AES_ALT +POLARSSL_AES_C MBEDTLS_AES_C +POLARSSL_AES_H MBEDTLS_AES_H +POLARSSL_AES_ROM_TABLES MBEDTLS_AES_ROM_TABLES +POLARSSL_ARC4_ALT MBEDTLS_ARC4_ALT +POLARSSL_ARC4_C MBEDTLS_ARC4_C +POLARSSL_ARC4_H MBEDTLS_ARC4_H +POLARSSL_ASN1_H MBEDTLS_ASN1_H +POLARSSL_ASN1_PARSE_C MBEDTLS_ASN1_PARSE_C +POLARSSL_ASN1_WRITE_C MBEDTLS_ASN1_WRITE_C +POLARSSL_ASN1_WRITE_H MBEDTLS_ASN1_WRITE_H +POLARSSL_BASE64_C MBEDTLS_BASE64_C +POLARSSL_BASE64_H MBEDTLS_BASE64_H +POLARSSL_BIGNUM_C MBEDTLS_BIGNUM_C +POLARSSL_BIGNUM_H MBEDTLS_BIGNUM_H +POLARSSL_BLOWFISH_ALT MBEDTLS_BLOWFISH_ALT +POLARSSL_BLOWFISH_C MBEDTLS_BLOWFISH_C +POLARSSL_BLOWFISH_H MBEDTLS_BLOWFISH_H +POLARSSL_BN_MUL_H MBEDTLS_BN_MUL_H +POLARSSL_CAMELLIA_ALT MBEDTLS_CAMELLIA_ALT +POLARSSL_CAMELLIA_C MBEDTLS_CAMELLIA_C +POLARSSL_CAMELLIA_H MBEDTLS_CAMELLIA_H +POLARSSL_CAMELLIA_SMALL_MEMORY MBEDTLS_CAMELLIA_SMALL_MEMORY +POLARSSL_CCM_C MBEDTLS_CCM_C +POLARSSL_CCM_H MBEDTLS_CCM_H +POLARSSL_CERTS_C MBEDTLS_CERTS_C +POLARSSL_CERTS_H MBEDTLS_CERTS_H +POLARSSL_CHECK_CONFIG_H MBEDTLS_CHECK_CONFIG_H +POLARSSL_CIPHERSUITE_NODTLS MBEDTLS_CIPHERSUITE_NODTLS +POLARSSL_CIPHERSUITE_SHORT_TAG MBEDTLS_CIPHERSUITE_SHORT_TAG +POLARSSL_CIPHERSUITE_WEAK MBEDTLS_CIPHERSUITE_WEAK +POLARSSL_CIPHER_AES_128_CBC MBEDTLS_CIPHER_AES_128_CBC +POLARSSL_CIPHER_AES_128_CCM MBEDTLS_CIPHER_AES_128_CCM +POLARSSL_CIPHER_AES_128_CFB128 MBEDTLS_CIPHER_AES_128_CFB128 +POLARSSL_CIPHER_AES_128_CTR MBEDTLS_CIPHER_AES_128_CTR +POLARSSL_CIPHER_AES_128_ECB MBEDTLS_CIPHER_AES_128_ECB +POLARSSL_CIPHER_AES_128_GCM MBEDTLS_CIPHER_AES_128_GCM +POLARSSL_CIPHER_AES_192_CBC MBEDTLS_CIPHER_AES_192_CBC +POLARSSL_CIPHER_AES_192_CCM MBEDTLS_CIPHER_AES_192_CCM +POLARSSL_CIPHER_AES_192_CFB128 MBEDTLS_CIPHER_AES_192_CFB128 +POLARSSL_CIPHER_AES_192_CTR MBEDTLS_CIPHER_AES_192_CTR +POLARSSL_CIPHER_AES_192_ECB MBEDTLS_CIPHER_AES_192_ECB +POLARSSL_CIPHER_AES_192_GCM MBEDTLS_CIPHER_AES_192_GCM +POLARSSL_CIPHER_AES_256_CBC MBEDTLS_CIPHER_AES_256_CBC +POLARSSL_CIPHER_AES_256_CCM MBEDTLS_CIPHER_AES_256_CCM +POLARSSL_CIPHER_AES_256_CFB128 MBEDTLS_CIPHER_AES_256_CFB128 +POLARSSL_CIPHER_AES_256_CTR MBEDTLS_CIPHER_AES_256_CTR +POLARSSL_CIPHER_AES_256_ECB MBEDTLS_CIPHER_AES_256_ECB +POLARSSL_CIPHER_AES_256_GCM MBEDTLS_CIPHER_AES_256_GCM +POLARSSL_CIPHER_ARC4_128 MBEDTLS_CIPHER_ARC4_128 +POLARSSL_CIPHER_BLOWFISH_CBC MBEDTLS_CIPHER_BLOWFISH_CBC +POLARSSL_CIPHER_BLOWFISH_CFB64 MBEDTLS_CIPHER_BLOWFISH_CFB64 +POLARSSL_CIPHER_BLOWFISH_CTR MBEDTLS_CIPHER_BLOWFISH_CTR +POLARSSL_CIPHER_BLOWFISH_ECB MBEDTLS_CIPHER_BLOWFISH_ECB +POLARSSL_CIPHER_C MBEDTLS_CIPHER_C +POLARSSL_CIPHER_CAMELLIA_128_CBC MBEDTLS_CIPHER_CAMELLIA_128_CBC +POLARSSL_CIPHER_CAMELLIA_128_CCM MBEDTLS_CIPHER_CAMELLIA_128_CCM +POLARSSL_CIPHER_CAMELLIA_128_CFB128 MBEDTLS_CIPHER_CAMELLIA_128_CFB128 +POLARSSL_CIPHER_CAMELLIA_128_CTR MBEDTLS_CIPHER_CAMELLIA_128_CTR +POLARSSL_CIPHER_CAMELLIA_128_ECB MBEDTLS_CIPHER_CAMELLIA_128_ECB +POLARSSL_CIPHER_CAMELLIA_128_GCM MBEDTLS_CIPHER_CAMELLIA_128_GCM +POLARSSL_CIPHER_CAMELLIA_192_CBC MBEDTLS_CIPHER_CAMELLIA_192_CBC +POLARSSL_CIPHER_CAMELLIA_192_CCM MBEDTLS_CIPHER_CAMELLIA_192_CCM +POLARSSL_CIPHER_CAMELLIA_192_CFB128 MBEDTLS_CIPHER_CAMELLIA_192_CFB128 +POLARSSL_CIPHER_CAMELLIA_192_CTR MBEDTLS_CIPHER_CAMELLIA_192_CTR +POLARSSL_CIPHER_CAMELLIA_192_ECB MBEDTLS_CIPHER_CAMELLIA_192_ECB +POLARSSL_CIPHER_CAMELLIA_192_GCM MBEDTLS_CIPHER_CAMELLIA_192_GCM +POLARSSL_CIPHER_CAMELLIA_256_CBC MBEDTLS_CIPHER_CAMELLIA_256_CBC +POLARSSL_CIPHER_CAMELLIA_256_CCM MBEDTLS_CIPHER_CAMELLIA_256_CCM +POLARSSL_CIPHER_CAMELLIA_256_CFB128 MBEDTLS_CIPHER_CAMELLIA_256_CFB128 +POLARSSL_CIPHER_CAMELLIA_256_CTR MBEDTLS_CIPHER_CAMELLIA_256_CTR +POLARSSL_CIPHER_CAMELLIA_256_ECB MBEDTLS_CIPHER_CAMELLIA_256_ECB +POLARSSL_CIPHER_CAMELLIA_256_GCM MBEDTLS_CIPHER_CAMELLIA_256_GCM +POLARSSL_CIPHER_DES_CBC MBEDTLS_CIPHER_DES_CBC +POLARSSL_CIPHER_DES_ECB MBEDTLS_CIPHER_DES_ECB +POLARSSL_CIPHER_DES_EDE3_CBC MBEDTLS_CIPHER_DES_EDE3_CBC +POLARSSL_CIPHER_DES_EDE3_ECB MBEDTLS_CIPHER_DES_EDE3_ECB +POLARSSL_CIPHER_DES_EDE_CBC MBEDTLS_CIPHER_DES_EDE_CBC +POLARSSL_CIPHER_DES_EDE_ECB MBEDTLS_CIPHER_DES_EDE_ECB +POLARSSL_CIPHER_H MBEDTLS_CIPHER_H +POLARSSL_CIPHER_ID_3DES MBEDTLS_CIPHER_ID_3DES +POLARSSL_CIPHER_ID_AES MBEDTLS_CIPHER_ID_AES +POLARSSL_CIPHER_ID_ARC4 MBEDTLS_CIPHER_ID_ARC4 +POLARSSL_CIPHER_ID_BLOWFISH MBEDTLS_CIPHER_ID_BLOWFISH +POLARSSL_CIPHER_ID_CAMELLIA MBEDTLS_CIPHER_ID_CAMELLIA +POLARSSL_CIPHER_ID_DES MBEDTLS_CIPHER_ID_DES +POLARSSL_CIPHER_ID_NONE MBEDTLS_CIPHER_ID_NONE +POLARSSL_CIPHER_ID_NULL MBEDTLS_CIPHER_ID_NULL +POLARSSL_CIPHER_MODE_AEAD MBEDTLS_CIPHER_MODE_AEAD +POLARSSL_CIPHER_MODE_CBC MBEDTLS_CIPHER_MODE_CBC +POLARSSL_CIPHER_MODE_CFB MBEDTLS_CIPHER_MODE_CFB +POLARSSL_CIPHER_MODE_CTR MBEDTLS_CIPHER_MODE_CTR +POLARSSL_CIPHER_MODE_STREAM MBEDTLS_CIPHER_MODE_STREAM +POLARSSL_CIPHER_MODE_WITH_PADDING MBEDTLS_CIPHER_MODE_WITH_PADDING +POLARSSL_CIPHER_NONE MBEDTLS_CIPHER_NONE +POLARSSL_CIPHER_NULL MBEDTLS_CIPHER_NULL +POLARSSL_CIPHER_NULL_CIPHER MBEDTLS_CIPHER_NULL_CIPHER +POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +POLARSSL_CIPHER_PADDING_PKCS7 MBEDTLS_CIPHER_PADDING_PKCS7 +POLARSSL_CIPHER_PADDING_ZEROS MBEDTLS_CIPHER_PADDING_ZEROS +POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +POLARSSL_CIPHER_VARIABLE_IV_LEN MBEDTLS_CIPHER_VARIABLE_IV_LEN +POLARSSL_CIPHER_VARIABLE_KEY_LEN MBEDTLS_CIPHER_VARIABLE_KEY_LEN +POLARSSL_CIPHER_WRAP_H MBEDTLS_CIPHER_WRAP_H +POLARSSL_CONFIG_FILE MBEDTLS_CONFIG_FILE +POLARSSL_CONFIG_H MBEDTLS_CONFIG_H +POLARSSL_CTR_DRBG_C MBEDTLS_CTR_DRBG_C +POLARSSL_CTR_DRBG_H MBEDTLS_CTR_DRBG_H +POLARSSL_DEBUG_C MBEDTLS_DEBUG_C +POLARSSL_DEBUG_DFL_MODE MBEDTLS_DEBUG_DFL_MODE +POLARSSL_DEBUG_H MBEDTLS_DEBUG_H +POLARSSL_DEBUG_LOG_FULL MBEDTLS_DEBUG_LOG_FULL +POLARSSL_DEBUG_LOG_RAW MBEDTLS_DEBUG_LOG_RAW +POLARSSL_DECRYPT MBEDTLS_DECRYPT +POLARSSL_DEPRECATED_REMOVED MBEDTLS_DEPRECATED_REMOVED +POLARSSL_DEPRECATED_WARNING MBEDTLS_DEPRECATED_WARNING +POLARSSL_DES_ALT MBEDTLS_DES_ALT +POLARSSL_DES_C MBEDTLS_DES_C +POLARSSL_DES_H MBEDTLS_DES_H +POLARSSL_DHM_C MBEDTLS_DHM_C +POLARSSL_DHM_H MBEDTLS_DHM_H +POLARSSL_DHM_RFC2409_MODP_1024_G MBEDTLS_DHM_RFC2409_MODP_1024_G +POLARSSL_DHM_RFC2409_MODP_1024_P MBEDTLS_DHM_RFC2409_MODP_1024_P +POLARSSL_DHM_RFC3526_MODP_2048_G MBEDTLS_DHM_RFC3526_MODP_2048_G +POLARSSL_DHM_RFC3526_MODP_2048_P MBEDTLS_DHM_RFC3526_MODP_2048_P +POLARSSL_DHM_RFC3526_MODP_3072_G MBEDTLS_DHM_RFC3526_MODP_3072_G +POLARSSL_DHM_RFC3526_MODP_3072_P MBEDTLS_DHM_RFC3526_MODP_3072_P +POLARSSL_DHM_RFC5114_MODP_1024_G MBEDTLS_DHM_RFC5114_MODP_1024_G +POLARSSL_DHM_RFC5114_MODP_1024_P MBEDTLS_DHM_RFC5114_MODP_1024_P +POLARSSL_DHM_RFC5114_MODP_2048_G MBEDTLS_DHM_RFC5114_MODP_2048_G +POLARSSL_DHM_RFC5114_MODP_2048_P MBEDTLS_DHM_RFC5114_MODP_2048_P +POLARSSL_ECDH_C MBEDTLS_ECDH_C +POLARSSL_ECDH_H MBEDTLS_ECDH_H +POLARSSL_ECDH_OURS MBEDTLS_ECDH_OURS +POLARSSL_ECDH_THEIRS MBEDTLS_ECDH_THEIRS +POLARSSL_ECDSA_C MBEDTLS_ECDSA_C +POLARSSL_ECDSA_DETERMINISTIC MBEDTLS_ECDSA_DETERMINISTIC +POLARSSL_ECDSA_H MBEDTLS_ECDSA_H +POLARSSL_ECP_C MBEDTLS_ECP_C +POLARSSL_ECP_DP_BP256R1 MBEDTLS_ECP_DP_BP256R1 +POLARSSL_ECP_DP_BP256R1_ENABLED MBEDTLS_ECP_DP_BP256R1_ENABLED +POLARSSL_ECP_DP_BP384R1 MBEDTLS_ECP_DP_BP384R1 +POLARSSL_ECP_DP_BP384R1_ENABLED MBEDTLS_ECP_DP_BP384R1_ENABLED +POLARSSL_ECP_DP_BP512R1 MBEDTLS_ECP_DP_BP512R1 +POLARSSL_ECP_DP_BP512R1_ENABLED MBEDTLS_ECP_DP_BP512R1_ENABLED +POLARSSL_ECP_DP_M255 MBEDTLS_ECP_DP_CURVE25519 +POLARSSL_ECP_DP_M255_ENABLED MBEDTLS_ECP_DP_CURVE25519_ENABLED +POLARSSL_ECP_DP_MAX MBEDTLS_ECP_DP_MAX +POLARSSL_ECP_DP_NONE MBEDTLS_ECP_DP_NONE +POLARSSL_ECP_DP_SECP192K1 MBEDTLS_ECP_DP_SECP192K1 +POLARSSL_ECP_DP_SECP192K1_ENABLED MBEDTLS_ECP_DP_SECP192K1_ENABLED +POLARSSL_ECP_DP_SECP192R1 MBEDTLS_ECP_DP_SECP192R1 +POLARSSL_ECP_DP_SECP192R1_ENABLED MBEDTLS_ECP_DP_SECP192R1_ENABLED +POLARSSL_ECP_DP_SECP224K1 MBEDTLS_ECP_DP_SECP224K1 +POLARSSL_ECP_DP_SECP224K1_ENABLED MBEDTLS_ECP_DP_SECP224K1_ENABLED +POLARSSL_ECP_DP_SECP224R1 MBEDTLS_ECP_DP_SECP224R1 +POLARSSL_ECP_DP_SECP224R1_ENABLED MBEDTLS_ECP_DP_SECP224R1_ENABLED +POLARSSL_ECP_DP_SECP256K1 MBEDTLS_ECP_DP_SECP256K1 +POLARSSL_ECP_DP_SECP256K1_ENABLED MBEDTLS_ECP_DP_SECP256K1_ENABLED +POLARSSL_ECP_DP_SECP256R1 MBEDTLS_ECP_DP_SECP256R1 +POLARSSL_ECP_DP_SECP256R1_ENABLED MBEDTLS_ECP_DP_SECP256R1_ENABLED +POLARSSL_ECP_DP_SECP384R1 MBEDTLS_ECP_DP_SECP384R1 +POLARSSL_ECP_DP_SECP384R1_ENABLED MBEDTLS_ECP_DP_SECP384R1_ENABLED +POLARSSL_ECP_DP_SECP521R1 MBEDTLS_ECP_DP_SECP521R1 +POLARSSL_ECP_DP_SECP521R1_ENABLED MBEDTLS_ECP_DP_SECP521R1_ENABLED +POLARSSL_ECP_FIXED_POINT_OPTIM MBEDTLS_ECP_FIXED_POINT_OPTIM +POLARSSL_ECP_H MBEDTLS_ECP_H +POLARSSL_ECP_MAX_BITS MBEDTLS_ECP_MAX_BITS +POLARSSL_ECP_MAX_BYTES MBEDTLS_ECP_MAX_BYTES +POLARSSL_ECP_MAX_PT_LEN MBEDTLS_ECP_MAX_PT_LEN +POLARSSL_ECP_NIST_OPTIM MBEDTLS_ECP_NIST_OPTIM +POLARSSL_ECP_PF_COMPRESSED MBEDTLS_ECP_PF_COMPRESSED +POLARSSL_ECP_PF_UNCOMPRESSED MBEDTLS_ECP_PF_UNCOMPRESSED +POLARSSL_ECP_TLS_NAMED_CURVE MBEDTLS_ECP_TLS_NAMED_CURVE +POLARSSL_ECP_WINDOW_SIZE MBEDTLS_ECP_WINDOW_SIZE +POLARSSL_ENABLE_WEAK_CIPHERSUITES MBEDTLS_ENABLE_WEAK_CIPHERSUITES +POLARSSL_ENCRYPT MBEDTLS_ENCRYPT +POLARSSL_ENTROPY_C MBEDTLS_ENTROPY_C +POLARSSL_ENTROPY_FORCE_SHA256 MBEDTLS_ENTROPY_FORCE_SHA256 +POLARSSL_ENTROPY_H MBEDTLS_ENTROPY_H +POLARSSL_ENTROPY_POLL_H MBEDTLS_ENTROPY_POLL_H +POLARSSL_ENTROPY_SHA256_ACCUMULATOR MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +POLARSSL_ENTROPY_SHA512_ACCUMULATOR MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +POLARSSL_ERROR_C MBEDTLS_ERROR_C +POLARSSL_ERROR_H MBEDTLS_ERROR_H +POLARSSL_ERROR_STRERROR_BC MBEDTLS_ERROR_STRERROR_BC +POLARSSL_ERROR_STRERROR_DUMMY MBEDTLS_ERROR_STRERROR_DUMMY +POLARSSL_ERR_AES_INVALID_INPUT_LENGTH MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH +POLARSSL_ERR_AES_INVALID_KEY_LENGTH MBEDTLS_ERR_AES_INVALID_KEY_LENGTH +POLARSSL_ERR_ASN1_BUF_TOO_SMALL MBEDTLS_ERR_ASN1_BUF_TOO_SMALL +POLARSSL_ERR_ASN1_INVALID_DATA MBEDTLS_ERR_ASN1_INVALID_DATA +POLARSSL_ERR_ASN1_INVALID_LENGTH MBEDTLS_ERR_ASN1_INVALID_LENGTH +POLARSSL_ERR_ASN1_LENGTH_MISMATCH MBEDTLS_ERR_ASN1_LENGTH_MISMATCH +POLARSSL_ERR_ASN1_MALLOC_FAILED MBEDTLS_ERR_ASN1_ALLOC_FAILED +POLARSSL_ERR_ASN1_OUT_OF_DATA MBEDTLS_ERR_ASN1_OUT_OF_DATA +POLARSSL_ERR_ASN1_UNEXPECTED_TAG MBEDTLS_ERR_ASN1_UNEXPECTED_TAG +POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL +POLARSSL_ERR_BASE64_INVALID_CHARACTER MBEDTLS_ERR_BASE64_INVALID_CHARACTER +POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH +POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH +POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH +POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH +POLARSSL_ERR_CCM_AUTH_FAILED MBEDTLS_ERR_CCM_AUTH_FAILED +POLARSSL_ERR_CCM_BAD_INPUT MBEDTLS_ERR_CCM_BAD_INPUT +POLARSSL_ERR_CIPHER_ALLOC_FAILED MBEDTLS_ERR_CIPHER_ALLOC_FAILED +POLARSSL_ERR_CIPHER_AUTH_FAILED MBEDTLS_ERR_CIPHER_AUTH_FAILED +POLARSSL_ERR_CIPHER_BAD_INPUT_DATA MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA +POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE +POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED +POLARSSL_ERR_CIPHER_INVALID_PADDING MBEDTLS_ERR_CIPHER_INVALID_PADDING +POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED +POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR +POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG +POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG +POLARSSL_ERR_DES_INVALID_INPUT_LENGTH MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH +POLARSSL_ERR_DHM_BAD_INPUT_DATA MBEDTLS_ERR_DHM_BAD_INPUT_DATA +POLARSSL_ERR_DHM_CALC_SECRET_FAILED MBEDTLS_ERR_DHM_CALC_SECRET_FAILED +POLARSSL_ERR_DHM_FILE_IO_ERROR MBEDTLS_ERR_DHM_FILE_IO_ERROR +POLARSSL_ERR_DHM_INVALID_FORMAT MBEDTLS_ERR_DHM_INVALID_FORMAT +POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED +POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED +POLARSSL_ERR_DHM_MALLOC_FAILED MBEDTLS_ERR_DHM_ALLOC_FAILED +POLARSSL_ERR_DHM_READ_PARAMS_FAILED MBEDTLS_ERR_DHM_READ_PARAMS_FAILED +POLARSSL_ERR_DHM_READ_PUBLIC_FAILED MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED +POLARSSL_ERR_ECP_BAD_INPUT_DATA MBEDTLS_ERR_ECP_BAD_INPUT_DATA +POLARSSL_ERR_ECP_BUFFER_TOO_SMALL MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL +POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE +POLARSSL_ERR_ECP_INVALID_KEY MBEDTLS_ERR_ECP_INVALID_KEY +POLARSSL_ERR_ECP_MALLOC_FAILED MBEDTLS_ERR_ECP_ALLOC_FAILED +POLARSSL_ERR_ECP_RANDOM_FAILED MBEDTLS_ERR_ECP_RANDOM_FAILED +POLARSSL_ERR_ECP_SIG_LEN_MISMATCH MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH +POLARSSL_ERR_ECP_VERIFY_FAILED MBEDTLS_ERR_ECP_VERIFY_FAILED +POLARSSL_ERR_ENTROPY_FILE_IO_ERROR MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR +POLARSSL_ERR_ENTROPY_MAX_SOURCES MBEDTLS_ERR_ENTROPY_MAX_SOURCES +POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED +POLARSSL_ERR_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_ENTROPY_SOURCE_FAILED +POLARSSL_ERR_GCM_AUTH_FAILED MBEDTLS_ERR_GCM_AUTH_FAILED +POLARSSL_ERR_GCM_BAD_INPUT MBEDTLS_ERR_GCM_BAD_INPUT +POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED +POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR +POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG +POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG +POLARSSL_ERR_MD2_FILE_IO_ERROR MBEDTLS_ERR_MD2_FILE_IO_ERROR +POLARSSL_ERR_MD4_FILE_IO_ERROR MBEDTLS_ERR_MD4_FILE_IO_ERROR +POLARSSL_ERR_MD5_FILE_IO_ERROR MBEDTLS_ERR_MD5_FILE_IO_ERROR +POLARSSL_ERR_MD_ALLOC_FAILED MBEDTLS_ERR_MD_ALLOC_FAILED +POLARSSL_ERR_MD_BAD_INPUT_DATA MBEDTLS_ERR_MD_BAD_INPUT_DATA +POLARSSL_ERR_MD_FEATURE_UNAVAILABLE MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE +POLARSSL_ERR_MD_FILE_IO_ERROR MBEDTLS_ERR_MD_FILE_IO_ERROR +POLARSSL_ERR_MPI_BAD_INPUT_DATA MBEDTLS_ERR_MPI_BAD_INPUT_DATA +POLARSSL_ERR_MPI_BUFFER_TOO_SMALL MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL +POLARSSL_ERR_MPI_DIVISION_BY_ZERO MBEDTLS_ERR_MPI_DIVISION_BY_ZERO +POLARSSL_ERR_MPI_FILE_IO_ERROR MBEDTLS_ERR_MPI_FILE_IO_ERROR +POLARSSL_ERR_MPI_INVALID_CHARACTER MBEDTLS_ERR_MPI_INVALID_CHARACTER +POLARSSL_ERR_MPI_MALLOC_FAILED MBEDTLS_ERR_MPI_ALLOC_FAILED +POLARSSL_ERR_MPI_NEGATIVE_VALUE MBEDTLS_ERR_MPI_NEGATIVE_VALUE +POLARSSL_ERR_MPI_NOT_ACCEPTABLE MBEDTLS_ERR_MPI_NOT_ACCEPTABLE +POLARSSL_ERR_NET_ACCEPT_FAILED MBEDTLS_ERR_NET_ACCEPT_FAILED +POLARSSL_ERR_NET_BIND_FAILED MBEDTLS_ERR_NET_BIND_FAILED +POLARSSL_ERR_NET_CONNECT_FAILED MBEDTLS_ERR_NET_CONNECT_FAILED +POLARSSL_ERR_NET_CONN_RESET MBEDTLS_ERR_NET_CONN_RESET +POLARSSL_ERR_NET_LISTEN_FAILED MBEDTLS_ERR_NET_LISTEN_FAILED +POLARSSL_ERR_NET_RECV_FAILED MBEDTLS_ERR_NET_RECV_FAILED +POLARSSL_ERR_NET_SEND_FAILED MBEDTLS_ERR_NET_SEND_FAILED +POLARSSL_ERR_NET_SOCKET_FAILED MBEDTLS_ERR_NET_SOCKET_FAILED +POLARSSL_ERR_NET_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT +POLARSSL_ERR_NET_UNKNOWN_HOST MBEDTLS_ERR_NET_UNKNOWN_HOST +POLARSSL_ERR_NET_WANT_READ MBEDTLS_ERR_SSL_WANT_READ +POLARSSL_ERR_NET_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE +POLARSSL_ERR_OID_BUF_TOO_SMALL MBEDTLS_ERR_OID_BUF_TOO_SMALL +POLARSSL_ERR_OID_NOT_FOUND MBEDTLS_ERR_OID_NOT_FOUND +POLARSSL_ERR_PADLOCK_DATA_MISALIGNED MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED +POLARSSL_ERR_PBKDF2_BAD_INPUT_DATA MBEDTLS_ERR_PBKDF2_BAD_INPUT_DATA +POLARSSL_ERR_PEM_BAD_INPUT_DATA MBEDTLS_ERR_PEM_BAD_INPUT_DATA +POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE +POLARSSL_ERR_PEM_INVALID_DATA MBEDTLS_ERR_PEM_INVALID_DATA +POLARSSL_ERR_PEM_INVALID_ENC_IV MBEDTLS_ERR_PEM_INVALID_ENC_IV +POLARSSL_ERR_PEM_MALLOC_FAILED MBEDTLS_ERR_PEM_ALLOC_FAILED +POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT +POLARSSL_ERR_PEM_PASSWORD_MISMATCH MBEDTLS_ERR_PEM_PASSWORD_MISMATCH +POLARSSL_ERR_PEM_PASSWORD_REQUIRED MBEDTLS_ERR_PEM_PASSWORD_REQUIRED +POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG +POLARSSL_ERR_PKCS12_BAD_INPUT_DATA MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA +POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE +POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH +POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT +POLARSSL_ERR_PKCS5_BAD_INPUT_DATA MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA +POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE +POLARSSL_ERR_PKCS5_INVALID_FORMAT MBEDTLS_ERR_PKCS5_INVALID_FORMAT +POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH +POLARSSL_ERR_PK_BAD_INPUT_DATA MBEDTLS_ERR_PK_BAD_INPUT_DATA +POLARSSL_ERR_PK_FEATURE_UNAVAILABLE MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE +POLARSSL_ERR_PK_FILE_IO_ERROR MBEDTLS_ERR_PK_FILE_IO_ERROR +POLARSSL_ERR_PK_INVALID_ALG MBEDTLS_ERR_PK_INVALID_ALG +POLARSSL_ERR_PK_INVALID_PUBKEY MBEDTLS_ERR_PK_INVALID_PUBKEY +POLARSSL_ERR_PK_KEY_INVALID_FORMAT MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +POLARSSL_ERR_PK_KEY_INVALID_VERSION MBEDTLS_ERR_PK_KEY_INVALID_VERSION +POLARSSL_ERR_PK_MALLOC_FAILED MBEDTLS_ERR_PK_ALLOC_FAILED +POLARSSL_ERR_PK_PASSWORD_MISMATCH MBEDTLS_ERR_PK_PASSWORD_MISMATCH +POLARSSL_ERR_PK_PASSWORD_REQUIRED MBEDTLS_ERR_PK_PASSWORD_REQUIRED +POLARSSL_ERR_PK_SIG_LEN_MISMATCH MBEDTLS_ERR_PK_SIG_LEN_MISMATCH +POLARSSL_ERR_PK_TYPE_MISMATCH MBEDTLS_ERR_PK_TYPE_MISMATCH +POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE +POLARSSL_ERR_PK_UNKNOWN_PK_ALG MBEDTLS_ERR_PK_UNKNOWN_PK_ALG +POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR MBEDTLS_ERR_RIPEMD160_FILE_IO_ERROR +POLARSSL_ERR_RSA_BAD_INPUT_DATA MBEDTLS_ERR_RSA_BAD_INPUT_DATA +POLARSSL_ERR_RSA_INVALID_PADDING MBEDTLS_ERR_RSA_INVALID_PADDING +POLARSSL_ERR_RSA_KEY_CHECK_FAILED MBEDTLS_ERR_RSA_KEY_CHECK_FAILED +POLARSSL_ERR_RSA_KEY_GEN_FAILED MBEDTLS_ERR_RSA_KEY_GEN_FAILED +POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE +POLARSSL_ERR_RSA_PRIVATE_FAILED MBEDTLS_ERR_RSA_PRIVATE_FAILED +POLARSSL_ERR_RSA_PUBLIC_FAILED MBEDTLS_ERR_RSA_PUBLIC_FAILED +POLARSSL_ERR_RSA_RNG_FAILED MBEDTLS_ERR_RSA_RNG_FAILED +POLARSSL_ERR_RSA_VERIFY_FAILED MBEDTLS_ERR_RSA_VERIFY_FAILED +POLARSSL_ERR_SHA1_FILE_IO_ERROR MBEDTLS_ERR_SHA1_FILE_IO_ERROR +POLARSSL_ERR_SHA256_FILE_IO_ERROR MBEDTLS_ERR_SHA256_FILE_IO_ERROR +POLARSSL_ERR_SHA512_FILE_IO_ERROR MBEDTLS_ERR_SHA512_FILE_IO_ERROR +POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE +POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST +POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY +POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC +POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO +POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE +POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS +POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP +POLARSSL_ERR_SSL_BAD_HS_FINISHED MBEDTLS_ERR_SSL_BAD_HS_FINISHED +POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET +POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION +POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO +POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE +POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE +POLARSSL_ERR_SSL_BAD_INPUT_DATA MBEDTLS_ERR_SSL_BAD_INPUT_DATA +POLARSSL_ERR_SSL_BUFFER_TOO_SMALL MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL +POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED +POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED +POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE +POLARSSL_ERR_SSL_COMPRESSION_FAILED MBEDTLS_ERR_SSL_COMPRESSION_FAILED +POLARSSL_ERR_SSL_CONN_EOF MBEDTLS_ERR_SSL_CONN_EOF +POLARSSL_ERR_SSL_COUNTER_WRAPPING MBEDTLS_ERR_SSL_COUNTER_WRAPPING +POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE +POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE +POLARSSL_ERR_SSL_HELLO_VERIFY_REQUIRED MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED +POLARSSL_ERR_SSL_HW_ACCEL_FAILED MBEDTLS_ERR_SSL_HW_ACCEL_FAILED +POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH +POLARSSL_ERR_SSL_INTERNAL_ERROR MBEDTLS_ERR_SSL_INTERNAL_ERROR +POLARSSL_ERR_SSL_INVALID_MAC MBEDTLS_ERR_SSL_INVALID_MAC +POLARSSL_ERR_SSL_INVALID_RECORD MBEDTLS_ERR_SSL_INVALID_RECORD +POLARSSL_ERR_SSL_MALLOC_FAILED MBEDTLS_ERR_SSL_ALLOC_FAILED +POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN +POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE +POLARSSL_ERR_SSL_NO_RNG MBEDTLS_ERR_SSL_NO_RNG +POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE +POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY +POLARSSL_ERR_SSL_PEER_VERIFY_FAILED MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED +POLARSSL_ERR_SSL_PK_TYPE_MISMATCH MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH +POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED +POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED +POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE +POLARSSL_ERR_SSL_UNKNOWN_CIPHER MBEDTLS_ERR_SSL_UNKNOWN_CIPHER +POLARSSL_ERR_SSL_UNKNOWN_IDENTITY MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY +POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO +POLARSSL_ERR_THREADING_BAD_INPUT_DATA MBEDTLS_ERR_THREADING_BAD_INPUT_DATA +POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE +POLARSSL_ERR_THREADING_MUTEX_ERROR MBEDTLS_ERR_THREADING_MUTEX_ERROR +POLARSSL_ERR_X509_BAD_INPUT_DATA MBEDTLS_ERR_X509_BAD_INPUT_DATA +POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT +POLARSSL_ERR_X509_CERT_VERIFY_FAILED MBEDTLS_ERR_X509_CERT_VERIFY_FAILED +POLARSSL_ERR_X509_FEATURE_UNAVAILABLE MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE +POLARSSL_ERR_X509_FILE_IO_ERROR MBEDTLS_ERR_X509_FILE_IO_ERROR +POLARSSL_ERR_X509_INVALID_ALG MBEDTLS_ERR_X509_INVALID_ALG +POLARSSL_ERR_X509_INVALID_DATE MBEDTLS_ERR_X509_INVALID_DATE +POLARSSL_ERR_X509_INVALID_EXTENSIONS MBEDTLS_ERR_X509_INVALID_EXTENSIONS +POLARSSL_ERR_X509_INVALID_FORMAT MBEDTLS_ERR_X509_INVALID_FORMAT +POLARSSL_ERR_X509_INVALID_NAME MBEDTLS_ERR_X509_INVALID_NAME +POLARSSL_ERR_X509_INVALID_SERIAL MBEDTLS_ERR_X509_INVALID_SERIAL +POLARSSL_ERR_X509_INVALID_SIGNATURE MBEDTLS_ERR_X509_INVALID_SIGNATURE +POLARSSL_ERR_X509_INVALID_VERSION MBEDTLS_ERR_X509_INVALID_VERSION +POLARSSL_ERR_X509_MALLOC_FAILED MBEDTLS_ERR_X509_ALLOC_FAILED +POLARSSL_ERR_X509_SIG_MISMATCH MBEDTLS_ERR_X509_SIG_MISMATCH +POLARSSL_ERR_X509_UNKNOWN_OID MBEDTLS_ERR_X509_UNKNOWN_OID +POLARSSL_ERR_X509_UNKNOWN_SIG_ALG MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG +POLARSSL_ERR_X509_UNKNOWN_VERSION MBEDTLS_ERR_X509_UNKNOWN_VERSION +POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH +POLARSSL_FS_IO MBEDTLS_FS_IO +POLARSSL_GCM_C MBEDTLS_GCM_C +POLARSSL_GCM_H MBEDTLS_GCM_H +POLARSSL_GENPRIME MBEDTLS_GENPRIME +POLARSSL_HAVEGE_C MBEDTLS_HAVEGE_C +POLARSSL_HAVEGE_H MBEDTLS_HAVEGE_H +POLARSSL_HAVE_ASM MBEDTLS_HAVE_ASM +POLARSSL_HAVE_INT16 MBEDTLS_HAVE_INT16 +POLARSSL_HAVE_INT32 MBEDTLS_HAVE_INT32 +POLARSSL_HAVE_INT64 MBEDTLS_HAVE_INT64 +POLARSSL_HAVE_INT8 MBEDTLS_HAVE_INT8 +POLARSSL_HAVE_IPV6 MBEDTLS_HAVE_IPV6 +POLARSSL_HAVE_LONGLONG MBEDTLS_HAVE_LONGLONG +POLARSSL_HAVE_SSE2 MBEDTLS_HAVE_SSE2 +POLARSSL_HAVE_TIME MBEDTLS_HAVE_TIME +POLARSSL_HAVE_UDBL MBEDTLS_HAVE_UDBL +POLARSSL_HAVE_X86 MBEDTLS_HAVE_X86 +POLARSSL_HAVE_X86_64 MBEDTLS_HAVE_X86_64 +POLARSSL_HMAC_DRBG_C MBEDTLS_HMAC_DRBG_C +POLARSSL_HMAC_DRBG_H MBEDTLS_HMAC_DRBG_H +POLARSSL_HMAC_DRBG_MAX_INPUT MBEDTLS_HMAC_DRBG_MAX_INPUT +POLARSSL_HMAC_DRBG_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST +POLARSSL_HMAC_DRBG_MAX_SEED_INPUT MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT +POLARSSL_HMAC_DRBG_PR_OFF MBEDTLS_HMAC_DRBG_PR_OFF +POLARSSL_HMAC_DRBG_PR_ON MBEDTLS_HMAC_DRBG_PR_ON +POLARSSL_HMAC_DRBG_RESEED_INTERVAL MBEDTLS_HMAC_DRBG_RESEED_INTERVAL +POLARSSL_KEY_EXCHANGE_DHE_PSK MBEDTLS_KEY_EXCHANGE_DHE_PSK +POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +POLARSSL_KEY_EXCHANGE_DHE_RSA MBEDTLS_KEY_EXCHANGE_DHE_RSA +POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA +POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +POLARSSL_KEY_EXCHANGE_ECDHE_PSK MBEDTLS_KEY_EXCHANGE_ECDHE_PSK +POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +POLARSSL_KEY_EXCHANGE_ECDHE_RSA MBEDTLS_KEY_EXCHANGE_ECDHE_RSA +POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +POLARSSL_KEY_EXCHANGE_ECDH_ECDSA MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA +POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +POLARSSL_KEY_EXCHANGE_ECDH_RSA MBEDTLS_KEY_EXCHANGE_ECDH_RSA +POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +POLARSSL_KEY_EXCHANGE_NONE MBEDTLS_KEY_EXCHANGE_NONE +POLARSSL_KEY_EXCHANGE_PSK MBEDTLS_KEY_EXCHANGE_PSK +POLARSSL_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +POLARSSL_KEY_EXCHANGE_RSA MBEDTLS_KEY_EXCHANGE_RSA +POLARSSL_KEY_EXCHANGE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +POLARSSL_KEY_EXCHANGE_RSA_PSK MBEDTLS_KEY_EXCHANGE_RSA_PSK +POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED +POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED +POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED +POLARSSL_KEY_LENGTH_DES MBEDTLS_KEY_LENGTH_DES +POLARSSL_KEY_LENGTH_DES_EDE MBEDTLS_KEY_LENGTH_DES_EDE +POLARSSL_KEY_LENGTH_DES_EDE3 MBEDTLS_KEY_LENGTH_DES_EDE3 +POLARSSL_KEY_LENGTH_NONE MBEDTLS_KEY_LENGTH_NONE +POLARSSL_MAX_BLOCK_LENGTH MBEDTLS_MAX_BLOCK_LENGTH +POLARSSL_MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH +POLARSSL_MD2_ALT MBEDTLS_MD2_ALT +POLARSSL_MD2_C MBEDTLS_MD2_C +POLARSSL_MD2_H MBEDTLS_MD2_H +POLARSSL_MD4_ALT MBEDTLS_MD4_ALT +POLARSSL_MD4_C MBEDTLS_MD4_C +POLARSSL_MD4_H MBEDTLS_MD4_H +POLARSSL_MD5_ALT MBEDTLS_MD5_ALT +POLARSSL_MD5_C MBEDTLS_MD5_C +POLARSSL_MD5_H MBEDTLS_MD5_H +POLARSSL_MD_C MBEDTLS_MD_C +POLARSSL_MD_H MBEDTLS_MD_H +POLARSSL_MD_MAX_SIZE MBEDTLS_MD_MAX_SIZE +POLARSSL_MD_MD2 MBEDTLS_MD_MD2 +POLARSSL_MD_MD4 MBEDTLS_MD_MD4 +POLARSSL_MD_MD5 MBEDTLS_MD_MD5 +POLARSSL_MD_NONE MBEDTLS_MD_NONE +POLARSSL_MD_RIPEMD160 MBEDTLS_MD_RIPEMD160 +POLARSSL_MD_SHA1 MBEDTLS_MD_SHA1 +POLARSSL_MD_SHA224 MBEDTLS_MD_SHA224 +POLARSSL_MD_SHA256 MBEDTLS_MD_SHA256 +POLARSSL_MD_SHA384 MBEDTLS_MD_SHA384 +POLARSSL_MD_SHA512 MBEDTLS_MD_SHA512 +POLARSSL_MD_WRAP_H MBEDTLS_MD_WRAP_H +POLARSSL_MEMORY_ALIGN_MULTIPLE MBEDTLS_MEMORY_ALIGN_MULTIPLE +POLARSSL_MEMORY_BACKTRACE MBEDTLS_MEMORY_BACKTRACE +POLARSSL_MEMORY_BUFFER_ALLOC_C MBEDTLS_MEMORY_BUFFER_ALLOC_C +POLARSSL_MEMORY_BUFFER_ALLOC_H MBEDTLS_MEMORY_BUFFER_ALLOC_H +POLARSSL_MEMORY_C MBEDTLS_MEMORY_C +POLARSSL_MEMORY_DEBUG MBEDTLS_MEMORY_DEBUG +POLARSSL_MEMORY_H MBEDTLS_MEMORY_H +POLARSSL_MODE_CBC MBEDTLS_MODE_CBC +POLARSSL_MODE_CCM MBEDTLS_MODE_CCM +POLARSSL_MODE_CFB MBEDTLS_MODE_CFB +POLARSSL_MODE_CTR MBEDTLS_MODE_CTR +POLARSSL_MODE_ECB MBEDTLS_MODE_ECB +POLARSSL_MODE_GCM MBEDTLS_MODE_GCM +POLARSSL_MODE_NONE MBEDTLS_MODE_NONE +POLARSSL_MODE_OFB MBEDTLS_MODE_OFB +POLARSSL_MODE_STREAM MBEDTLS_MODE_STREAM +POLARSSL_MPI_MAX_BITS MBEDTLS_MPI_MAX_BITS +POLARSSL_MPI_MAX_BITS_SCALE100 MBEDTLS_MPI_MAX_BITS_SCALE100 +POLARSSL_MPI_MAX_LIMBS MBEDTLS_MPI_MAX_LIMBS +POLARSSL_MPI_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +POLARSSL_MPI_RW_BUFFER_SIZE MBEDTLS_MPI_RW_BUFFER_SIZE +POLARSSL_MPI_WINDOW_SIZE MBEDTLS_MPI_WINDOW_SIZE +POLARSSL_NET_C MBEDTLS_NET_C +POLARSSL_NET_H MBEDTLS_NET_H +POLARSSL_NET_LISTEN_BACKLOG MBEDTLS_NET_LISTEN_BACKLOG +POLARSSL_NO_DEFAULT_ENTROPY_SOURCES MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +POLARSSL_NO_PLATFORM_ENTROPY MBEDTLS_NO_PLATFORM_ENTROPY +POLARSSL_OID_C MBEDTLS_OID_C +POLARSSL_OID_H MBEDTLS_OID_H +POLARSSL_OPERATION_NONE MBEDTLS_OPERATION_NONE +POLARSSL_PADDING_NONE MBEDTLS_PADDING_NONE +POLARSSL_PADDING_ONE_AND_ZEROS MBEDTLS_PADDING_ONE_AND_ZEROS +POLARSSL_PADDING_PKCS7 MBEDTLS_PADDING_PKCS7 +POLARSSL_PADDING_ZEROS MBEDTLS_PADDING_ZEROS +POLARSSL_PADDING_ZEROS_AND_LEN MBEDTLS_PADDING_ZEROS_AND_LEN +POLARSSL_PADLOCK_C MBEDTLS_PADLOCK_C +POLARSSL_PADLOCK_H MBEDTLS_PADLOCK_H +POLARSSL_PBKDF2_C MBEDTLS_PBKDF2_C +POLARSSL_PBKDF2_H MBEDTLS_PBKDF2_H +POLARSSL_PEM_H MBEDTLS_PEM_H +POLARSSL_PEM_PARSE_C MBEDTLS_PEM_PARSE_C +POLARSSL_PEM_WRITE_C MBEDTLS_PEM_WRITE_C +POLARSSL_PKCS11_C MBEDTLS_PKCS11_C +POLARSSL_PKCS11_H MBEDTLS_PKCS11_H +POLARSSL_PKCS12_C MBEDTLS_PKCS12_C +POLARSSL_PKCS12_H MBEDTLS_PKCS12_H +POLARSSL_PKCS1_V15 MBEDTLS_PKCS1_V15 +POLARSSL_PKCS1_V21 MBEDTLS_PKCS1_V21 +POLARSSL_PKCS5_C MBEDTLS_PKCS5_C +POLARSSL_PKCS5_H MBEDTLS_PKCS5_H +POLARSSL_PK_C MBEDTLS_PK_C +POLARSSL_PK_DEBUG_ECP MBEDTLS_PK_DEBUG_ECP +POLARSSL_PK_DEBUG_MAX_ITEMS MBEDTLS_PK_DEBUG_MAX_ITEMS +POLARSSL_PK_DEBUG_MPI MBEDTLS_PK_DEBUG_MPI +POLARSSL_PK_DEBUG_NONE MBEDTLS_PK_DEBUG_NONE +POLARSSL_PK_ECDSA MBEDTLS_PK_ECDSA +POLARSSL_PK_ECKEY MBEDTLS_PK_ECKEY +POLARSSL_PK_ECKEY_DH MBEDTLS_PK_ECKEY_DH +POLARSSL_PK_H MBEDTLS_PK_H +POLARSSL_PK_NONE MBEDTLS_PK_NONE +POLARSSL_PK_PARSE_C MBEDTLS_PK_PARSE_C +POLARSSL_PK_PARSE_EC_EXTENDED MBEDTLS_PK_PARSE_EC_EXTENDED +POLARSSL_PK_RSA MBEDTLS_PK_RSA +POLARSSL_PK_RSASSA_PSS MBEDTLS_PK_RSASSA_PSS +POLARSSL_PK_RSA_ALT MBEDTLS_PK_RSA_ALT +POLARSSL_PK_WRAP_H MBEDTLS_PK_WRAP_H +POLARSSL_PK_WRITE_C MBEDTLS_PK_WRITE_C +POLARSSL_PLATFORM_C MBEDTLS_PLATFORM_C +POLARSSL_PLATFORM_EXIT_ALT MBEDTLS_PLATFORM_EXIT_ALT +POLARSSL_PLATFORM_EXIT_MACRO MBEDTLS_PLATFORM_EXIT_MACRO +POLARSSL_PLATFORM_FPRINTF_ALT MBEDTLS_PLATFORM_FPRINTF_ALT +POLARSSL_PLATFORM_FPRINTF_MACRO MBEDTLS_PLATFORM_FPRINTF_MACRO +POLARSSL_PLATFORM_FREE_MACRO MBEDTLS_PLATFORM_FREE_MACRO +POLARSSL_PLATFORM_H MBEDTLS_PLATFORM_H +POLARSSL_PLATFORM_MALLOC_MACRO MBEDTLS_PLATFORM_ALLOC_MACRO +POLARSSL_PLATFORM_MEMORY MBEDTLS_PLATFORM_MEMORY +POLARSSL_PLATFORM_NO_STD_FUNCTIONS MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +POLARSSL_PLATFORM_PRINTF_ALT MBEDTLS_PLATFORM_PRINTF_ALT +POLARSSL_PLATFORM_PRINTF_MACRO MBEDTLS_PLATFORM_PRINTF_MACRO +POLARSSL_PLATFORM_SNPRINTF_ALT MBEDTLS_PLATFORM_SNPRINTF_ALT +POLARSSL_PLATFORM_SNPRINTF_MACRO MBEDTLS_PLATFORM_SNPRINTF_MACRO +POLARSSL_PLATFORM_STD_EXIT MBEDTLS_PLATFORM_STD_EXIT +POLARSSL_PLATFORM_STD_FPRINTF MBEDTLS_PLATFORM_STD_FPRINTF +POLARSSL_PLATFORM_STD_FREE MBEDTLS_PLATFORM_STD_FREE +POLARSSL_PLATFORM_STD_MALLOC MBEDTLS_PLATFORM_STD_CALLOC +POLARSSL_PLATFORM_STD_MEM_HDR MBEDTLS_PLATFORM_STD_MEM_HDR +POLARSSL_PLATFORM_STD_PRINTF MBEDTLS_PLATFORM_STD_PRINTF +POLARSSL_PLATFORM_STD_SNPRINTF MBEDTLS_PLATFORM_STD_SNPRINTF +POLARSSL_PREMASTER_SIZE MBEDTLS_PREMASTER_SIZE +POLARSSL_PSK_MAX_LEN MBEDTLS_PSK_MAX_LEN +POLARSSL_REMOVE_ARC4_CIPHERSUITES MBEDTLS_REMOVE_ARC4_CIPHERSUITES +POLARSSL_RIPEMD160_ALT MBEDTLS_RIPEMD160_ALT +POLARSSL_RIPEMD160_C MBEDTLS_RIPEMD160_C +POLARSSL_RIPEMD160_H MBEDTLS_RIPEMD160_H +POLARSSL_RSA_C MBEDTLS_RSA_C +POLARSSL_RSA_H MBEDTLS_RSA_H +POLARSSL_RSA_NO_CRT MBEDTLS_RSA_NO_CRT +POLARSSL_SELF_TEST MBEDTLS_SELF_TEST +POLARSSL_SHA1_ALT MBEDTLS_SHA1_ALT +POLARSSL_SHA1_C MBEDTLS_SHA1_C +POLARSSL_SHA1_H MBEDTLS_SHA1_H +POLARSSL_SHA256_ALT MBEDTLS_SHA256_ALT +POLARSSL_SHA256_C MBEDTLS_SHA256_C +POLARSSL_SHA256_H MBEDTLS_SHA256_H +POLARSSL_SHA512_ALT MBEDTLS_SHA512_ALT +POLARSSL_SHA512_C MBEDTLS_SHA512_C +POLARSSL_SHA512_H MBEDTLS_SHA512_H +POLARSSL_SSL_AEAD_RANDOM_IV MBEDTLS_SSL_AEAD_RANDOM_IV +POLARSSL_SSL_ALERT_MESSAGES MBEDTLS_SSL_ALERT_MESSAGES +POLARSSL_SSL_ALPN MBEDTLS_SSL_ALPN +POLARSSL_SSL_CACHE_C MBEDTLS_SSL_CACHE_C +POLARSSL_SSL_CACHE_H MBEDTLS_SSL_CACHE_H +POLARSSL_SSL_CBC_RECORD_SPLITTING MBEDTLS_SSL_CBC_RECORD_SPLITTING +POLARSSL_SSL_CIPHERSUITES_H MBEDTLS_SSL_CIPHERSUITES_H +POLARSSL_SSL_CLI_C MBEDTLS_SSL_CLI_C +POLARSSL_SSL_COOKIE_C MBEDTLS_SSL_COOKIE_C +POLARSSL_SSL_COOKIE_H MBEDTLS_SSL_COOKIE_H +POLARSSL_SSL_COOKIE_TIMEOUT MBEDTLS_SSL_COOKIE_TIMEOUT +POLARSSL_SSL_DEBUG_ALL MBEDTLS_SSL_DEBUG_ALL +POLARSSL_SSL_DISABLE_RENEGOTIATION MBEDTLS_SSL_DISABLE_RENEGOTIATION +POLARSSL_SSL_DTLS_ANTI_REPLAY MBEDTLS_SSL_DTLS_ANTI_REPLAY +POLARSSL_SSL_DTLS_BADMAC_LIMIT MBEDTLS_SSL_DTLS_BADMAC_LIMIT +POLARSSL_SSL_DTLS_HELLO_VERIFY MBEDTLS_SSL_DTLS_HELLO_VERIFY +POLARSSL_SSL_ENCRYPT_THEN_MAC MBEDTLS_SSL_ENCRYPT_THEN_MAC +POLARSSL_SSL_EXTENDED_MASTER_SECRET MBEDTLS_SSL_EXTENDED_MASTER_SECRET +POLARSSL_SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV +POLARSSL_SSL_H MBEDTLS_SSL_H +POLARSSL_SSL_HW_RECORD_ACCEL MBEDTLS_SSL_HW_RECORD_ACCEL +POLARSSL_SSL_MAX_FRAGMENT_LENGTH MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +POLARSSL_SSL_PROTO_DTLS MBEDTLS_SSL_PROTO_DTLS +POLARSSL_SSL_PROTO_SSL3 MBEDTLS_SSL_PROTO_SSL3 +POLARSSL_SSL_PROTO_TLS1 MBEDTLS_SSL_PROTO_TLS1 +POLARSSL_SSL_PROTO_TLS1_1 MBEDTLS_SSL_PROTO_TLS1_1 +POLARSSL_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_2 +POLARSSL_SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION +POLARSSL_SSL_SERVER_NAME_INDICATION MBEDTLS_SSL_SERVER_NAME_INDICATION +POLARSSL_SSL_SESSION_TICKETS MBEDTLS_SSL_SESSION_TICKETS +POLARSSL_SSL_SRV_C MBEDTLS_SSL_SRV_C +POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE +POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO +POLARSSL_SSL_TLS_C MBEDTLS_SSL_TLS_C +POLARSSL_SSL_TRUNCATED_HMAC MBEDTLS_SSL_TRUNCATED_HMAC +POLARSSL_THREADING_ALT MBEDTLS_THREADING_ALT +POLARSSL_THREADING_C MBEDTLS_THREADING_C +POLARSSL_THREADING_H MBEDTLS_THREADING_H +POLARSSL_THREADING_IMPL MBEDTLS_THREADING_IMPL +POLARSSL_THREADING_PTHREAD MBEDTLS_THREADING_PTHREAD +POLARSSL_TIMING_ALT MBEDTLS_TIMING_ALT +POLARSSL_TIMING_C MBEDTLS_TIMING_C +POLARSSL_TIMING_H MBEDTLS_TIMING_H +POLARSSL_VERSION_C MBEDTLS_VERSION_C +POLARSSL_VERSION_FEATURES MBEDTLS_VERSION_FEATURES +POLARSSL_VERSION_H MBEDTLS_VERSION_H +POLARSSL_VERSION_MAJOR MBEDTLS_VERSION_MAJOR +POLARSSL_VERSION_MINOR MBEDTLS_VERSION_MINOR +POLARSSL_VERSION_NUMBER MBEDTLS_VERSION_NUMBER +POLARSSL_VERSION_PATCH MBEDTLS_VERSION_PATCH +POLARSSL_VERSION_STRING MBEDTLS_VERSION_STRING +POLARSSL_VERSION_STRING_FULL MBEDTLS_VERSION_STRING_FULL +POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 +POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +POLARSSL_X509_CHECK_KEY_USAGE MBEDTLS_X509_CHECK_KEY_USAGE +POLARSSL_X509_CREATE_C MBEDTLS_X509_CREATE_C +POLARSSL_X509_CRL_H MBEDTLS_X509_CRL_H +POLARSSL_X509_CRL_PARSE_C MBEDTLS_X509_CRL_PARSE_C +POLARSSL_X509_CRT_H MBEDTLS_X509_CRT_H +POLARSSL_X509_CRT_PARSE_C MBEDTLS_X509_CRT_PARSE_C +POLARSSL_X509_CRT_WRITE_C MBEDTLS_X509_CRT_WRITE_C +POLARSSL_X509_CSR_H MBEDTLS_X509_CSR_H +POLARSSL_X509_CSR_PARSE_C MBEDTLS_X509_CSR_PARSE_C +POLARSSL_X509_CSR_WRITE_C MBEDTLS_X509_CSR_WRITE_C +POLARSSL_X509_H MBEDTLS_X509_H +POLARSSL_X509_MAX_INTERMEDIATE_CA MBEDTLS_X509_MAX_INTERMEDIATE_CA +POLARSSL_X509_RSASSA_PSS_SUPPORT MBEDTLS_X509_RSASSA_PSS_SUPPORT +POLARSSL_X509_USE_C MBEDTLS_X509_USE_C +POLARSSL_XTEA_ALT MBEDTLS_XTEA_ALT +POLARSSL_XTEA_C MBEDTLS_XTEA_C +POLARSSL_XTEA_H MBEDTLS_XTEA_H +POLARSSL_ZLIB_SUPPORT MBEDTLS_ZLIB_SUPPORT +RSA_CRYPT MBEDTLS_RSA_CRYPT +RSA_PKCS_V15 MBEDTLS_RSA_PKCS_V15 +RSA_PKCS_V21 MBEDTLS_RSA_PKCS_V21 +RSA_PRIVATE MBEDTLS_RSA_PRIVATE +RSA_PUBLIC MBEDTLS_RSA_PUBLIC +RSA_SALT_LEN_ANY MBEDTLS_RSA_SALT_LEN_ANY +RSA_SIGN MBEDTLS_RSA_SIGN +SSL_ALERT_LEVEL_FATAL MBEDTLS_SSL_ALERT_LEVEL_FATAL +SSL_ALERT_LEVEL_WARNING MBEDTLS_SSL_ALERT_LEVEL_WARNING +SSL_ALERT_MSG_ACCESS_DENIED MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED +SSL_ALERT_MSG_BAD_CERT MBEDTLS_SSL_ALERT_MSG_BAD_CERT +SSL_ALERT_MSG_BAD_RECORD_MAC MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC +SSL_ALERT_MSG_CERT_EXPIRED MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED +SSL_ALERT_MSG_CERT_REVOKED MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED +SSL_ALERT_MSG_CERT_UNKNOWN MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN +SSL_ALERT_MSG_CLOSE_NOTIFY MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY +SSL_ALERT_MSG_DECODE_ERROR MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR +SSL_ALERT_MSG_DECOMPRESSION_FAILURE MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE +SSL_ALERT_MSG_DECRYPTION_FAILED MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED +SSL_ALERT_MSG_DECRYPT_ERROR MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR +SSL_ALERT_MSG_EXPORT_RESTRICTION MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION +SSL_ALERT_MSG_HANDSHAKE_FAILURE MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE +SSL_ALERT_MSG_ILLEGAL_PARAMETER MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER +SSL_ALERT_MSG_INAPROPRIATE_FALLBACK MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK +SSL_ALERT_MSG_INSUFFICIENT_SECURITY MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY +SSL_ALERT_MSG_INTERNAL_ERROR MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR +SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL +SSL_ALERT_MSG_NO_CERT MBEDTLS_SSL_ALERT_MSG_NO_CERT +SSL_ALERT_MSG_NO_RENEGOTIATION MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION +SSL_ALERT_MSG_PROTOCOL_VERSION MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION +SSL_ALERT_MSG_RECORD_OVERFLOW MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW +SSL_ALERT_MSG_UNEXPECTED_MESSAGE MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE +SSL_ALERT_MSG_UNKNOWN_CA MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA +SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY +SSL_ALERT_MSG_UNRECOGNIZED_NAME MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME +SSL_ALERT_MSG_UNSUPPORTED_CERT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT +SSL_ALERT_MSG_UNSUPPORTED_EXT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT +SSL_ALERT_MSG_USER_CANCELED MBEDTLS_SSL_ALERT_MSG_USER_CANCELED +SSL_ANTI_REPLAY_DISABLED MBEDTLS_SSL_ANTI_REPLAY_DISABLED +SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED +SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED +SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED +SSL_BUFFER_LEN MBEDTLS_SSL_BUFFER_LEN +SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES +SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT +SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED +SSL_CBC_RECORD_SPLITTING_ENABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED +SSL_CERTIFICATE_REQUEST MBEDTLS_SSL_CERTIFICATE_REQUEST +SSL_CERTIFICATE_VERIFY MBEDTLS_SSL_CERTIFICATE_VERIFY +SSL_CERT_TYPE_ECDSA_SIGN MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN +SSL_CERT_TYPE_RSA_SIGN MBEDTLS_SSL_CERT_TYPE_RSA_SIGN +SSL_CHANNEL_INBOUND MBEDTLS_SSL_CHANNEL_INBOUND +SSL_CHANNEL_OUTBOUND MBEDTLS_SSL_CHANNEL_OUTBOUND +SSL_CIPHERSUITES MBEDTLS_SSL_CIPHERSUITES +SSL_CLIENT_CERTIFICATE MBEDTLS_SSL_CLIENT_CERTIFICATE +SSL_CLIENT_CHANGE_CIPHER_SPEC MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC +SSL_CLIENT_FINISHED MBEDTLS_SSL_CLIENT_FINISHED +SSL_CLIENT_HELLO MBEDTLS_SSL_CLIENT_HELLO +SSL_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_CLIENT_KEY_EXCHANGE +SSL_COMPRESSION_ADD MBEDTLS_SSL_COMPRESSION_ADD +SSL_COMPRESS_DEFLATE MBEDTLS_SSL_COMPRESS_DEFLATE +SSL_COMPRESS_NULL MBEDTLS_SSL_COMPRESS_NULL +SSL_DEBUG_BUF MBEDTLS_SSL_DEBUG_BUF +SSL_DEBUG_CRT MBEDTLS_SSL_DEBUG_CRT +SSL_DEBUG_ECP MBEDTLS_SSL_DEBUG_ECP +SSL_DEBUG_MPI MBEDTLS_SSL_DEBUG_MPI +SSL_DEBUG_MSG MBEDTLS_SSL_DEBUG_MSG +SSL_DEBUG_RET MBEDTLS_SSL_DEBUG_RET +SSL_DEFAULT_TICKET_LIFETIME MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME +SSL_DTLS_TIMEOUT_DFL_MAX MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX +SSL_DTLS_TIMEOUT_DFL_MIN MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN +SSL_EMPTY_RENEGOTIATION_INFO MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO +SSL_ETM_DISABLED MBEDTLS_SSL_ETM_DISABLED +SSL_ETM_ENABLED MBEDTLS_SSL_ETM_ENABLED +SSL_EXTENDED_MS_DISABLED MBEDTLS_SSL_EXTENDED_MS_DISABLED +SSL_EXTENDED_MS_ENABLED MBEDTLS_SSL_EXTENDED_MS_ENABLED +SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV +SSL_FLUSH_BUFFERS MBEDTLS_SSL_FLUSH_BUFFERS +SSL_HANDSHAKE_OVER MBEDTLS_SSL_HANDSHAKE_OVER +SSL_HANDSHAKE_WRAPUP MBEDTLS_SSL_HANDSHAKE_WRAPUP +SSL_HASH_MD5 MBEDTLS_SSL_HASH_MD5 +SSL_HASH_NONE MBEDTLS_SSL_HASH_NONE +SSL_HASH_SHA1 MBEDTLS_SSL_HASH_SHA1 +SSL_HASH_SHA224 MBEDTLS_SSL_HASH_SHA224 +SSL_HASH_SHA256 MBEDTLS_SSL_HASH_SHA256 +SSL_HASH_SHA384 MBEDTLS_SSL_HASH_SHA384 +SSL_HASH_SHA512 MBEDTLS_SSL_HASH_SHA512 +SSL_HELLO_REQUEST MBEDTLS_SSL_HELLO_REQUEST +SSL_HS_CERTIFICATE MBEDTLS_SSL_HS_CERTIFICATE +SSL_HS_CERTIFICATE_REQUEST MBEDTLS_SSL_HS_CERTIFICATE_REQUEST +SSL_HS_CERTIFICATE_VERIFY MBEDTLS_SSL_HS_CERTIFICATE_VERIFY +SSL_HS_CLIENT_HELLO MBEDTLS_SSL_HS_CLIENT_HELLO +SSL_HS_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE +SSL_HS_FINISHED MBEDTLS_SSL_HS_FINISHED +SSL_HS_HELLO_REQUEST MBEDTLS_SSL_HS_HELLO_REQUEST +SSL_HS_HELLO_VERIFY_REQUEST MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST +SSL_HS_NEW_SESSION_TICKET MBEDTLS_SSL_HS_NEW_SESSION_TICKET +SSL_HS_SERVER_HELLO MBEDTLS_SSL_HS_SERVER_HELLO +SSL_HS_SERVER_HELLO_DONE MBEDTLS_SSL_HS_SERVER_HELLO_DONE +SSL_HS_SERVER_KEY_EXCHANGE MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE +SSL_INITIAL_HANDSHAKE MBEDTLS_SSL_INITIAL_HANDSHAKE +SSL_IS_CLIENT MBEDTLS_SSL_IS_CLIENT +SSL_IS_FALLBACK MBEDTLS_SSL_IS_FALLBACK +SSL_IS_NOT_FALLBACK MBEDTLS_SSL_IS_NOT_FALLBACK +SSL_IS_SERVER MBEDTLS_SSL_IS_SERVER +SSL_LEGACY_ALLOW_RENEGOTIATION MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION +SSL_LEGACY_BREAK_HANDSHAKE MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE +SSL_LEGACY_NO_RENEGOTIATION MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION +SSL_LEGACY_RENEGOTIATION MBEDTLS_SSL_LEGACY_RENEGOTIATION +SSL_MAC_ADD MBEDTLS_SSL_MAC_ADD +SSL_MAJOR_VERSION_3 MBEDTLS_SSL_MAJOR_VERSION_3 +SSL_MAX_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +SSL_MAX_FRAG_LEN_1024 MBEDTLS_SSL_MAX_FRAG_LEN_1024 +SSL_MAX_FRAG_LEN_2048 MBEDTLS_SSL_MAX_FRAG_LEN_2048 +SSL_MAX_FRAG_LEN_4096 MBEDTLS_SSL_MAX_FRAG_LEN_4096 +SSL_MAX_FRAG_LEN_512 MBEDTLS_SSL_MAX_FRAG_LEN_512 +SSL_MAX_FRAG_LEN_INVALID MBEDTLS_SSL_MAX_FRAG_LEN_INVALID +SSL_MAX_FRAG_LEN_NONE MBEDTLS_SSL_MAX_FRAG_LEN_NONE +SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAX_MAJOR_VERSION +SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MAX_MINOR_VERSION +SSL_MINOR_VERSION_0 MBEDTLS_SSL_MINOR_VERSION_0 +SSL_MINOR_VERSION_1 MBEDTLS_SSL_MINOR_VERSION_1 +SSL_MINOR_VERSION_2 MBEDTLS_SSL_MINOR_VERSION_2 +SSL_MINOR_VERSION_3 MBEDTLS_SSL_MINOR_VERSION_3 +SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MIN_MAJOR_VERSION +SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MIN_MINOR_VERSION +SSL_MSG_ALERT MBEDTLS_SSL_MSG_ALERT +SSL_MSG_APPLICATION_DATA MBEDTLS_SSL_MSG_APPLICATION_DATA +SSL_MSG_CHANGE_CIPHER_SPEC MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC +SSL_MSG_HANDSHAKE MBEDTLS_SSL_MSG_HANDSHAKE +SSL_PADDING_ADD MBEDTLS_SSL_PADDING_ADD +SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION +SSL_RENEGOTIATION_DISABLED MBEDTLS_SSL_RENEGOTIATION_DISABLED +SSL_RENEGOTIATION_DONE MBEDTLS_SSL_RENEGOTIATION_DONE +SSL_RENEGOTIATION_ENABLED MBEDTLS_SSL_RENEGOTIATION_ENABLED +SSL_RENEGOTIATION_NOT_ENFORCED MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED +SSL_RENEGOTIATION_PENDING MBEDTLS_SSL_RENEGOTIATION_PENDING +SSL_RENEGO_MAX_RECORDS_DEFAULT MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT +SSL_RETRANS_FINISHED MBEDTLS_SSL_RETRANS_FINISHED +SSL_RETRANS_PREPARING MBEDTLS_SSL_RETRANS_PREPARING +SSL_RETRANS_SENDING MBEDTLS_SSL_RETRANS_SENDING +SSL_RETRANS_WAITING MBEDTLS_SSL_RETRANS_WAITING +SSL_SECURE_RENEGOTIATION MBEDTLS_SSL_SECURE_RENEGOTIATION +SSL_SERVER_CERTIFICATE MBEDTLS_SSL_SERVER_CERTIFICATE +SSL_SERVER_CHANGE_CIPHER_SPEC MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC +SSL_SERVER_FINISHED MBEDTLS_SSL_SERVER_FINISHED +SSL_SERVER_HELLO MBEDTLS_SSL_SERVER_HELLO +SSL_SERVER_HELLO_DONE MBEDTLS_SSL_SERVER_HELLO_DONE +SSL_SERVER_HELLO_VERIFY_REQUEST_SENT MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT +SSL_SERVER_KEY_EXCHANGE MBEDTLS_SSL_SERVER_KEY_EXCHANGE +SSL_SERVER_NEW_SESSION_TICKET MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET +SSL_SESSION_TICKETS_DISABLED MBEDTLS_SSL_SESSION_TICKETS_DISABLED +SSL_SESSION_TICKETS_ENABLED MBEDTLS_SSL_SESSION_TICKETS_ENABLED +SSL_SIG_ANON MBEDTLS_SSL_SIG_ANON +SSL_SIG_ECDSA MBEDTLS_SSL_SIG_ECDSA +SSL_SIG_RSA MBEDTLS_SSL_SIG_RSA +SSL_TRANSPORT_DATAGRAM MBEDTLS_SSL_TRANSPORT_DATAGRAM +SSL_TRANSPORT_STREAM MBEDTLS_SSL_TRANSPORT_STREAM +SSL_TRUNCATED_HMAC_LEN MBEDTLS_SSL_TRUNCATED_HMAC_LEN +SSL_TRUNC_HMAC_DISABLED MBEDTLS_SSL_TRUNC_HMAC_DISABLED +SSL_TRUNC_HMAC_ENABLED MBEDTLS_SSL_TRUNC_HMAC_ENABLED +SSL_VERIFY_DATA_MAX_LEN MBEDTLS_SSL_VERIFY_DATA_MAX_LEN +SSL_VERIFY_NONE MBEDTLS_SSL_VERIFY_NONE +SSL_VERIFY_OPTIONAL MBEDTLS_SSL_VERIFY_OPTIONAL +SSL_VERIFY_REQUIRED MBEDTLS_SSL_VERIFY_REQUIRED +TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA +TLS_DHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA +TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 +TLS_DHE_PSK_WITH_AES_128_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM +TLS_DHE_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 +TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 +TLS_DHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA +TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 +TLS_DHE_PSK_WITH_AES_256_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM +TLS_DHE_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 +TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 +TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 +TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 +TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 +TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 +TLS_DHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA +TLS_DHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 +TLS_DHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 +TLS_DHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA +TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA +TLS_DHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA +TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 +TLS_DHE_RSA_WITH_AES_128_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM +TLS_DHE_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 +TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 +TLS_DHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA +TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 +TLS_DHE_RSA_WITH_AES_256_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM +TLS_DHE_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 +TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 +TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA +TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 +TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA +TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 +TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +TLS_DHE_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA +TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA +TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA +TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 +TLS_ECDHE_ECDSA_WITH_AES_128_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM +TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 +TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA +TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 +TLS_ECDHE_ECDSA_WITH_AES_256_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM +TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 +TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 +TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 +TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +TLS_ECDHE_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA +TLS_ECDHE_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA +TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA +TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA +TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 +TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA +TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 +TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 +TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 +TLS_ECDHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA +TLS_ECDHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 +TLS_ECDHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 +TLS_ECDHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA +TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA +TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA +TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 +TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 +TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 +TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 +TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +TLS_ECDHE_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA +TLS_ECDHE_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA +TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA +TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA +TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 +TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 +TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA +TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 +TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 +TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 +TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 +TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +TLS_ECDH_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA +TLS_ECDH_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA +TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA +TLS_ECDH_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA +TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 +TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 +TLS_ECDH_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA +TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 +TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 +TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 +TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 +TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 +TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 +TLS_ECDH_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA +TLS_ECDH_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA +TLS_EXT_ALPN MBEDTLS_TLS_EXT_ALPN +TLS_EXT_ENCRYPT_THEN_MAC MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC +TLS_EXT_EXTENDED_MASTER_SECRET MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET +TLS_EXT_MAX_FRAGMENT_LENGTH MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH +TLS_EXT_RENEGOTIATION_INFO MBEDTLS_TLS_EXT_RENEGOTIATION_INFO +TLS_EXT_SERVERNAME MBEDTLS_TLS_EXT_SERVERNAME +TLS_EXT_SERVERNAME_HOSTNAME MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME +TLS_EXT_SESSION_TICKET MBEDTLS_TLS_EXT_SESSION_TICKET +TLS_EXT_SIG_ALG MBEDTLS_TLS_EXT_SIG_ALG +TLS_EXT_SUPPORTED_ELLIPTIC_CURVES MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES +TLS_EXT_SUPPORTED_POINT_FORMATS MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS +TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT +TLS_EXT_TRUNCATED_HMAC MBEDTLS_TLS_EXT_TRUNCATED_HMAC +TLS_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA +TLS_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA +TLS_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 +TLS_PSK_WITH_AES_128_CCM MBEDTLS_TLS_PSK_WITH_AES_128_CCM +TLS_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 +TLS_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 +TLS_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA +TLS_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 +TLS_PSK_WITH_AES_256_CCM MBEDTLS_TLS_PSK_WITH_AES_256_CCM +TLS_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 +TLS_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 +TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 +TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 +TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 +TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 +TLS_PSK_WITH_NULL_SHA MBEDTLS_TLS_PSK_WITH_NULL_SHA +TLS_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_PSK_WITH_NULL_SHA256 +TLS_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_PSK_WITH_NULL_SHA384 +TLS_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_PSK_WITH_RC4_128_SHA +TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA +TLS_RSA_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA +TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 +TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 +TLS_RSA_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA +TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 +TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 +TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 +TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 +TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 +TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 +TLS_RSA_PSK_WITH_NULL_SHA MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA +TLS_RSA_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 +TLS_RSA_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 +TLS_RSA_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA +TLS_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA +TLS_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA +TLS_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 +TLS_RSA_WITH_AES_128_CCM MBEDTLS_TLS_RSA_WITH_AES_128_CCM +TLS_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 +TLS_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 +TLS_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA +TLS_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 +TLS_RSA_WITH_AES_256_CCM MBEDTLS_TLS_RSA_WITH_AES_256_CCM +TLS_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 +TLS_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 +TLS_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA +TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 +TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 +TLS_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA +TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 +TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 +TLS_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA +TLS_RSA_WITH_NULL_MD5 MBEDTLS_TLS_RSA_WITH_NULL_MD5 +TLS_RSA_WITH_NULL_SHA MBEDTLS_TLS_RSA_WITH_NULL_SHA +TLS_RSA_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_WITH_NULL_SHA256 +TLS_RSA_WITH_RC4_128_MD5 MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 +TLS_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_WITH_RC4_128_SHA +X509_CRT_VERSION_1 MBEDTLS_X509_CRT_VERSION_1 +X509_CRT_VERSION_2 MBEDTLS_X509_CRT_VERSION_2 +X509_CRT_VERSION_3 MBEDTLS_X509_CRT_VERSION_3 +X509_FORMAT_DER MBEDTLS_X509_FORMAT_DER +X509_FORMAT_PEM MBEDTLS_X509_FORMAT_PEM +X509_MAX_DN_NAME_SIZE MBEDTLS_X509_MAX_DN_NAME_SIZE +X509_RFC5280_MAX_SERIAL_LEN MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN +X509_RFC5280_UTC_TIME_LEN MBEDTLS_X509_RFC5280_UTC_TIME_LEN +XTEA_DECRYPT MBEDTLS_XTEA_DECRYPT +XTEA_ENCRYPT MBEDTLS_XTEA_ENCRYPT +_asn1_bitstring mbedtls_asn1_bitstring +_asn1_buf mbedtls_asn1_buf +_asn1_named_data mbedtls_asn1_named_data +_asn1_sequence mbedtls_asn1_sequence +_ssl_cache_context mbedtls_ssl_cache_context +_ssl_cache_entry mbedtls_ssl_cache_entry +_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t +_ssl_context mbedtls_ssl_context +_ssl_flight_item mbedtls_ssl_flight_item +_ssl_handshake_params mbedtls_ssl_handshake_params +_ssl_key_cert mbedtls_ssl_key_cert +_ssl_premaster_secret mbedtls_ssl_premaster_secret +_ssl_session mbedtls_ssl_session +_ssl_ticket_keys mbedtls_ssl_ticket_keys +_ssl_transform mbedtls_ssl_transform +_x509_crl mbedtls_x509_crl +_x509_crl_entry mbedtls_x509_crl_entry +_x509_crt mbedtls_x509_crt +_x509_csr mbedtls_x509_csr +_x509_time mbedtls_x509_time +_x509write_cert mbedtls_x509write_cert +_x509write_csr mbedtls_x509write_csr +aes_context mbedtls_aes_context +aes_crypt_cbc mbedtls_aes_crypt_cbc +aes_crypt_cfb128 mbedtls_aes_crypt_cfb128 +aes_crypt_cfb8 mbedtls_aes_crypt_cfb8 +aes_crypt_ctr mbedtls_aes_crypt_ctr +aes_crypt_ecb mbedtls_aes_crypt_ecb +aes_free mbedtls_aes_free +aes_init mbedtls_aes_init +aes_self_test mbedtls_aes_self_test +aes_setkey_dec mbedtls_aes_setkey_dec +aes_setkey_enc mbedtls_aes_setkey_enc +aesni_crypt_ecb mbedtls_aesni_crypt_ecb +aesni_gcm_mult mbedtls_aesni_gcm_mult +aesni_inverse_key mbedtls_aesni_inverse_key +aesni_setkey_enc mbedtls_aesni_setkey_enc +aesni_supports mbedtls_aesni_has_support +alarmed mbedtls_timing_alarmed +arc4_context mbedtls_arc4_context +arc4_crypt mbedtls_arc4_crypt +arc4_free mbedtls_arc4_free +arc4_init mbedtls_arc4_init +arc4_self_test mbedtls_arc4_self_test +arc4_setup mbedtls_arc4_setup +asn1_bitstring mbedtls_asn1_bitstring +asn1_buf mbedtls_asn1_buf +asn1_find_named_data mbedtls_asn1_find_named_data +asn1_free_named_data mbedtls_asn1_free_named_data +asn1_free_named_data_list mbedtls_asn1_free_named_data_list +asn1_get_alg mbedtls_asn1_get_alg +asn1_get_alg_null mbedtls_asn1_get_alg_null +asn1_get_bitstring mbedtls_asn1_get_bitstring +asn1_get_bitstring_null mbedtls_asn1_get_bitstring_null +asn1_get_bool mbedtls_asn1_get_bool +asn1_get_int mbedtls_asn1_get_int +asn1_get_len mbedtls_asn1_get_len +asn1_get_mpi mbedtls_asn1_get_mpi +asn1_get_sequence_of mbedtls_asn1_get_sequence_of +asn1_get_tag mbedtls_asn1_get_tag +asn1_named_data mbedtls_asn1_named_data +asn1_sequence mbedtls_asn1_sequence +asn1_store_named_data mbedtls_asn1_store_named_data +asn1_write_algorithm_identifier mbedtls_asn1_write_algorithm_identifier +asn1_write_bitstring mbedtls_asn1_write_bitstring +asn1_write_bool mbedtls_asn1_write_bool +asn1_write_ia5_string mbedtls_asn1_write_ia5_string +asn1_write_int mbedtls_asn1_write_int +asn1_write_len mbedtls_asn1_write_len +asn1_write_mpi mbedtls_asn1_write_mpi +asn1_write_null mbedtls_asn1_write_null +asn1_write_octet_string mbedtls_asn1_write_octet_string +asn1_write_oid mbedtls_asn1_write_oid +asn1_write_printable_string mbedtls_asn1_write_printable_string +asn1_write_raw_buffer mbedtls_asn1_write_raw_buffer +asn1_write_tag mbedtls_asn1_write_tag +base64_decode mbedtls_base64_decode +base64_encode mbedtls_base64_encode +base64_self_test mbedtls_base64_self_test +blowfish_context mbedtls_blowfish_context +blowfish_crypt_cbc mbedtls_blowfish_crypt_cbc +blowfish_crypt_cfb64 mbedtls_blowfish_crypt_cfb64 +blowfish_crypt_ctr mbedtls_blowfish_crypt_ctr +blowfish_crypt_ecb mbedtls_blowfish_crypt_ecb +blowfish_free mbedtls_blowfish_free +blowfish_init mbedtls_blowfish_init +blowfish_setkey mbedtls_blowfish_setkey +camellia_context mbedtls_camellia_context +camellia_crypt_cbc mbedtls_camellia_crypt_cbc +camellia_crypt_cfb128 mbedtls_camellia_crypt_cfb128 +camellia_crypt_ctr mbedtls_camellia_crypt_ctr +camellia_crypt_ecb mbedtls_camellia_crypt_ecb +camellia_free mbedtls_camellia_free +camellia_init mbedtls_camellia_init +camellia_self_test mbedtls_camellia_self_test +camellia_setkey_dec mbedtls_camellia_setkey_dec +camellia_setkey_enc mbedtls_camellia_setkey_enc +ccm_auth_decrypt mbedtls_ccm_auth_decrypt +ccm_context mbedtls_ccm_context +ccm_encrypt_and_tag mbedtls_ccm_encrypt_and_tag +ccm_free mbedtls_ccm_free +ccm_init mbedtls_ccm_init +ccm_self_test mbedtls_ccm_self_test +cipher_auth_decrypt mbedtls_cipher_auth_decrypt +cipher_auth_encrypt mbedtls_cipher_auth_encrypt +cipher_base_t mbedtls_cipher_base_t +cipher_check_tag mbedtls_cipher_check_tag +cipher_context_t mbedtls_cipher_context_t +cipher_crypt mbedtls_cipher_crypt +cipher_definition_t mbedtls_cipher_definition_t +cipher_definitions mbedtls_cipher_definitions +cipher_finish mbedtls_cipher_finish +cipher_free mbedtls_cipher_free +cipher_free_ctx mbedtls_cipher_free_ctx +cipher_get_block_size mbedtls_cipher_get_block_size +cipher_get_cipher_mode mbedtls_cipher_get_cipher_mode +cipher_get_iv_size mbedtls_cipher_get_iv_size +cipher_get_key_size mbedtls_cipher_get_key_bitlen +cipher_get_name mbedtls_cipher_get_name +cipher_get_operation mbedtls_cipher_get_operation +cipher_get_type mbedtls_cipher_get_type +cipher_id_t mbedtls_cipher_id_t +cipher_info_from_string mbedtls_cipher_info_from_string +cipher_info_from_type mbedtls_cipher_info_from_type +cipher_info_from_values mbedtls_cipher_info_from_values +cipher_info_t mbedtls_cipher_info_t +cipher_init mbedtls_cipher_init +cipher_init_ctx mbedtls_cipher_setup +cipher_list mbedtls_cipher_list +cipher_mode_t mbedtls_cipher_mode_t +cipher_padding_t mbedtls_cipher_padding_t +cipher_reset mbedtls_cipher_reset +cipher_self_test mbedtls_cipher_self_test +cipher_set_iv mbedtls_cipher_set_iv +cipher_set_padding_mode mbedtls_cipher_set_padding_mode +cipher_setkey mbedtls_cipher_setkey +cipher_type_t mbedtls_cipher_type_t +cipher_update mbedtls_cipher_update +cipher_update_ad mbedtls_cipher_update_ad +cipher_write_tag mbedtls_cipher_write_tag +ctr_drbg_context mbedtls_ctr_drbg_context +ctr_drbg_free mbedtls_ctr_drbg_free +ctr_drbg_init mbedtls_ctr_drbg_init +ctr_drbg_init_entropy_len mbedtls_ctr_drbg_init_entropy_len +ctr_drbg_random mbedtls_ctr_drbg_random +ctr_drbg_random_with_add mbedtls_ctr_drbg_random_with_add +ctr_drbg_reseed mbedtls_ctr_drbg_reseed +ctr_drbg_self_test mbedtls_ctr_drbg_self_test +ctr_drbg_set_entropy_len mbedtls_ctr_drbg_set_entropy_len +ctr_drbg_set_prediction_resistance mbedtls_ctr_drbg_set_prediction_resistance +ctr_drbg_set_reseed_interval mbedtls_ctr_drbg_set_reseed_interval +ctr_drbg_update mbedtls_ctr_drbg_update +ctr_drbg_update_seed_file mbedtls_ctr_drbg_update_seed_file +ctr_drbg_write_seed_file mbedtls_ctr_drbg_write_seed_file +debug_fmt mbedtls_debug_fmt +debug_print_buf mbedtls_debug_print_buf +debug_print_crt mbedtls_debug_print_crt +debug_print_ecp mbedtls_debug_print_ecp +debug_print_mpi mbedtls_debug_print_mpi +debug_print_msg mbedtls_debug_print_msg +debug_print_ret mbedtls_debug_print_ret +debug_set_log_mode mbedtls_debug_set_log_mode +debug_set_threshold mbedtls_debug_set_threshold +des3_context mbedtls_des3_context +des3_crypt_cbc mbedtls_des3_crypt_cbc +des3_crypt_ecb mbedtls_des3_crypt_ecb +des3_free mbedtls_des3_free +des3_init mbedtls_des3_init +des3_set2key_dec mbedtls_des3_set2key_dec +des3_set2key_enc mbedtls_des3_set2key_enc +des3_set3key_dec mbedtls_des3_set3key_dec +des3_set3key_enc mbedtls_des3_set3key_enc +des_context mbedtls_des_context +des_crypt_cbc mbedtls_des_crypt_cbc +des_crypt_ecb mbedtls_des_crypt_ecb +des_free mbedtls_des_free +des_init mbedtls_des_init +des_key_check_key_parity mbedtls_des_key_check_key_parity +des_key_check_weak mbedtls_des_key_check_weak +des_key_set_parity mbedtls_des_key_set_parity +des_self_test mbedtls_des_self_test +des_setkey_dec mbedtls_des_setkey_dec +des_setkey_enc mbedtls_des_setkey_enc +dhm_calc_secret mbedtls_dhm_calc_secret +dhm_context mbedtls_dhm_context +dhm_free mbedtls_dhm_free +dhm_init mbedtls_dhm_init +dhm_make_params mbedtls_dhm_make_params +dhm_make_public mbedtls_dhm_make_public +dhm_parse_dhm mbedtls_dhm_parse_dhm +dhm_parse_dhmfile mbedtls_dhm_parse_dhmfile +dhm_read_params mbedtls_dhm_read_params +dhm_read_public mbedtls_dhm_read_public +dhm_self_test mbedtls_dhm_self_test +ecdh_calc_secret mbedtls_ecdh_calc_secret +ecdh_compute_shared mbedtls_ecdh_compute_shared +ecdh_context mbedtls_ecdh_context +ecdh_free mbedtls_ecdh_free +ecdh_gen_public mbedtls_ecdh_gen_public +ecdh_get_params mbedtls_ecdh_get_params +ecdh_init mbedtls_ecdh_init +ecdh_make_params mbedtls_ecdh_make_params +ecdh_make_public mbedtls_ecdh_make_public +ecdh_read_params mbedtls_ecdh_read_params +ecdh_read_public mbedtls_ecdh_read_public +ecdh_self_test mbedtls_ecdh_self_test +ecdh_side mbedtls_ecdh_side +ecdsa_context mbedtls_ecdsa_context +ecdsa_free mbedtls_ecdsa_free +ecdsa_from_keypair mbedtls_ecdsa_from_keypair +ecdsa_genkey mbedtls_ecdsa_genkey +ecdsa_info mbedtls_ecdsa_info +ecdsa_init mbedtls_ecdsa_init +ecdsa_read_signature mbedtls_ecdsa_read_signature +ecdsa_self_test mbedtls_ecdsa_self_test +ecdsa_sign mbedtls_ecdsa_sign +ecdsa_sign_det mbedtls_ecdsa_sign_det +ecdsa_verify mbedtls_ecdsa_verify +ecdsa_write_signature mbedtls_ecdsa_write_signature +ecdsa_write_signature_det mbedtls_ecdsa_write_signature_det +eckey_info mbedtls_eckey_info +eckeydh_info mbedtls_eckeydh_info +ecp_add mbedtls_ecp_add +ecp_check_privkey mbedtls_ecp_check_privkey +ecp_check_pub_priv mbedtls_ecp_check_pub_priv +ecp_check_pubkey mbedtls_ecp_check_pubkey +ecp_copy mbedtls_ecp_copy +ecp_curve_info mbedtls_ecp_curve_info +ecp_curve_info_from_grp_id mbedtls_ecp_curve_info_from_grp_id +ecp_curve_info_from_name mbedtls_ecp_curve_info_from_name +ecp_curve_info_from_tls_id mbedtls_ecp_curve_info_from_tls_id +ecp_curve_list mbedtls_ecp_curve_list +ecp_gen_key mbedtls_ecp_gen_key +ecp_gen_keypair mbedtls_ecp_gen_keypair +ecp_group mbedtls_ecp_group +ecp_group_copy mbedtls_ecp_group_copy +ecp_group_free mbedtls_ecp_group_free +ecp_group_id mbedtls_ecp_group_id +ecp_group_init mbedtls_ecp_group_init +ecp_group_read_string mbedtls_ecp_group_read_string +ecp_grp_id_list mbedtls_ecp_grp_id_list +ecp_is_zero mbedtls_ecp_is_zero +ecp_keypair mbedtls_ecp_keypair +ecp_keypair_free mbedtls_ecp_keypair_free +ecp_keypair_init mbedtls_ecp_keypair_init +ecp_mul mbedtls_ecp_mul +ecp_point mbedtls_ecp_point +ecp_point_free mbedtls_ecp_point_free +ecp_point_init mbedtls_ecp_point_init +ecp_point_read_binary mbedtls_ecp_point_read_binary +ecp_point_read_string mbedtls_ecp_point_read_string +ecp_point_write_binary mbedtls_ecp_point_write_binary +ecp_self_test mbedtls_ecp_self_test +ecp_set_zero mbedtls_ecp_set_zero +ecp_sub mbedtls_ecp_sub +ecp_tls_read_group mbedtls_ecp_tls_read_group +ecp_tls_read_point mbedtls_ecp_tls_read_point +ecp_tls_write_group mbedtls_ecp_tls_write_group +ecp_tls_write_point mbedtls_ecp_tls_write_point +ecp_use_known_dp mbedtls_ecp_group_load +entropy_add_source mbedtls_entropy_add_source +entropy_context mbedtls_entropy_context +entropy_free mbedtls_entropy_free +entropy_func mbedtls_entropy_func +entropy_gather mbedtls_entropy_gather +entropy_init mbedtls_entropy_init +entropy_self_test mbedtls_entropy_self_test +entropy_update_manual mbedtls_entropy_update_manual +entropy_update_seed_file mbedtls_entropy_update_seed_file +entropy_write_seed_file mbedtls_entropy_write_seed_file +error_strerror mbedtls_strerror +f_source_ptr mbedtls_entropy_f_source_ptr +gcm_auth_decrypt mbedtls_gcm_auth_decrypt +gcm_context mbedtls_gcm_context +gcm_crypt_and_tag mbedtls_gcm_crypt_and_tag +gcm_finish mbedtls_gcm_finish +gcm_free mbedtls_gcm_free +gcm_init mbedtls_gcm_init +gcm_self_test mbedtls_gcm_self_test +gcm_starts mbedtls_gcm_starts +gcm_update mbedtls_gcm_update +get_timer mbedtls_timing_get_timer +hardclock mbedtls_timing_hardclock +hardclock_poll mbedtls_hardclock_poll +havege_free mbedtls_havege_free +havege_init mbedtls_havege_init +havege_poll mbedtls_havege_poll +havege_random mbedtls_havege_random +havege_state mbedtls_havege_state +hmac_drbg_context mbedtls_hmac_drbg_context +hmac_drbg_free mbedtls_hmac_drbg_free +hmac_drbg_init mbedtls_hmac_drbg_init +hmac_drbg_init_buf mbedtls_hmac_drbg_init_buf +hmac_drbg_random mbedtls_hmac_drbg_random +hmac_drbg_random_with_add mbedtls_hmac_drbg_random_with_add +hmac_drbg_reseed mbedtls_hmac_drbg_reseed +hmac_drbg_self_test mbedtls_hmac_drbg_self_test +hmac_drbg_set_entropy_len mbedtls_hmac_drbg_set_entropy_len +hmac_drbg_set_prediction_resistance mbedtls_hmac_drbg_set_prediction_resistance +hmac_drbg_set_reseed_interval mbedtls_hmac_drbg_set_reseed_interval +hmac_drbg_update mbedtls_hmac_drbg_update +hmac_drbg_update_seed_file mbedtls_hmac_drbg_update_seed_file +hmac_drbg_write_seed_file mbedtls_hmac_drbg_write_seed_file +hr_time mbedtls_timing_hr_time +key_exchange_type_t mbedtls_key_exchange_type_t +m_sleep mbedtls_timing_m_sleep +md mbedtls_md +md2 mbedtls_md2 +md2_context mbedtls_md2_context +md2_file mbedtls_md2_file +md2_finish mbedtls_md2_finish +md2_free mbedtls_md2_free +md2_hmac mbedtls_md2_hmac +md2_hmac_finish mbedtls_md2_hmac_finish +md2_hmac_reset mbedtls_md2_hmac_reset +md2_hmac_starts mbedtls_md2_hmac_starts +md2_hmac_update mbedtls_md2_hmac_update +md2_info mbedtls_md2_info +md2_init mbedtls_md2_init +md2_process mbedtls_md2_process +md2_self_test mbedtls_md2_self_test +md2_starts mbedtls_md2_starts +md2_update mbedtls_md2_update +md4 mbedtls_md4 +md4_context mbedtls_md4_context +md4_file mbedtls_md4_file +md4_finish mbedtls_md4_finish +md4_free mbedtls_md4_free +md4_hmac mbedtls_md4_hmac +md4_hmac_finish mbedtls_md4_hmac_finish +md4_hmac_reset mbedtls_md4_hmac_reset +md4_hmac_starts mbedtls_md4_hmac_starts +md4_hmac_update mbedtls_md4_hmac_update +md4_info mbedtls_md4_info +md4_init mbedtls_md4_init +md4_process mbedtls_md4_process +md4_self_test mbedtls_md4_self_test +md4_starts mbedtls_md4_starts +md4_update mbedtls_md4_update +md5 mbedtls_md5 +md5_context mbedtls_md5_context +md5_file mbedtls_md5_file +md5_finish mbedtls_md5_finish +md5_free mbedtls_md5_free +md5_hmac mbedtls_md5_hmac +md5_hmac_finish mbedtls_md5_hmac_finish +md5_hmac_reset mbedtls_md5_hmac_reset +md5_hmac_starts mbedtls_md5_hmac_starts +md5_hmac_update mbedtls_md5_hmac_update +md5_info mbedtls_md5_info +md5_init mbedtls_md5_init +md5_process mbedtls_md5_process +md5_self_test mbedtls_md5_self_test +md5_starts mbedtls_md5_starts +md5_update mbedtls_md5_update +md_context_t mbedtls_md_context_t +md_file mbedtls_md_file +md_finish mbedtls_md_finish +md_free mbedtls_md_free +md_free_ctx mbedtls_md_free_ctx +md_get_name mbedtls_md_get_name +md_get_size mbedtls_md_get_size +md_get_type mbedtls_md_get_type +md_hmac mbedtls_md_hmac +md_hmac_finish mbedtls_md_hmac_finish +md_hmac_reset mbedtls_md_hmac_reset +md_hmac_starts mbedtls_md_hmac_starts +md_hmac_update mbedtls_md_hmac_update +md_info_from_string mbedtls_md_info_from_string +md_info_from_type mbedtls_md_info_from_type +md_info_t mbedtls_md_info_t +md_init mbedtls_md_init +md_init_ctx mbedtls_md_init_ctx +md_list mbedtls_md_list +md_process mbedtls_md_process +md_starts mbedtls_md_starts +md_type_t mbedtls_md_type_t +md_update mbedtls_md_update +memory_buffer_alloc_cur_get mbedtls_memory_buffer_alloc_cur_get +memory_buffer_alloc_free mbedtls_memory_buffer_alloc_free +memory_buffer_alloc_init mbedtls_memory_buffer_alloc_init +memory_buffer_alloc_max_get mbedtls_memory_buffer_alloc_max_get +memory_buffer_alloc_max_reset mbedtls_memory_buffer_alloc_max_reset +memory_buffer_alloc_self_test mbedtls_memory_buffer_alloc_self_test +memory_buffer_alloc_status mbedtls_memory_buffer_alloc_status +memory_buffer_alloc_verify mbedtls_memory_buffer_alloc_verify +memory_buffer_set_verify mbedtls_memory_buffer_set_verify +memory_set_own mbedtls_memory_set_own +mpi mbedtls_mpi +mpi_add_abs mbedtls_mpi_add_abs +mpi_add_int mbedtls_mpi_add_int +mpi_add_mpi mbedtls_mpi_add_mpi +mpi_cmp_abs mbedtls_mpi_cmp_abs +mpi_cmp_int mbedtls_mpi_cmp_int +mpi_cmp_mpi mbedtls_mpi_cmp_mpi +mpi_copy mbedtls_mpi_copy +mpi_div_int mbedtls_mpi_div_int +mpi_div_mpi mbedtls_mpi_div_mpi +mpi_exp_mod mbedtls_mpi_exp_mod +mpi_fill_random mbedtls_mpi_fill_random +mpi_free mbedtls_mpi_free +mpi_gcd mbedtls_mpi_gcd +mpi_gen_prime mbedtls_mpi_gen_prime +mpi_get_bit mbedtls_mpi_get_bit +mpi_grow mbedtls_mpi_grow +mpi_init mbedtls_mpi_init +mpi_inv_mod mbedtls_mpi_inv_mod +mpi_is_prime mbedtls_mpi_is_prime +mpi_lsb mbedtls_mpi_lsb +mpi_lset mbedtls_mpi_lset +mpi_mod_int mbedtls_mpi_mod_int +mpi_mod_mpi mbedtls_mpi_mod_mpi +mpi_msb mbedtls_mpi_bitlen +mpi_mul_int mbedtls_mpi_mul_int +mpi_mul_mpi mbedtls_mpi_mul_mpi +mpi_read_binary mbedtls_mpi_read_binary +mpi_read_file mbedtls_mpi_read_file +mpi_read_string mbedtls_mpi_read_string +mpi_safe_cond_assign mbedtls_mpi_safe_cond_assign +mpi_safe_cond_swap mbedtls_mpi_safe_cond_swap +mpi_self_test mbedtls_mpi_self_test +mpi_set_bit mbedtls_mpi_set_bit +mpi_shift_l mbedtls_mpi_shift_l +mpi_shift_r mbedtls_mpi_shift_r +mpi_shrink mbedtls_mpi_shrink +mpi_size mbedtls_mpi_size +mpi_sub_abs mbedtls_mpi_sub_abs +mpi_sub_int mbedtls_mpi_sub_int +mpi_sub_mpi mbedtls_mpi_sub_mpi +mpi_swap mbedtls_mpi_swap +mpi_write_binary mbedtls_mpi_write_binary +mpi_write_file mbedtls_mpi_write_file +mpi_write_string mbedtls_mpi_write_string +net_accept mbedtls_net_accept +net_bind mbedtls_net_bind +net_close mbedtls_net_free +net_connect mbedtls_net_connect +net_recv mbedtls_net_recv +net_recv_timeout mbedtls_net_recv_timeout +net_send mbedtls_net_send +net_set_block mbedtls_net_set_block +net_set_nonblock mbedtls_net_set_nonblock +net_usleep mbedtls_net_usleep +oid_descriptor_t mbedtls_oid_descriptor_t +oid_get_attr_short_name mbedtls_oid_get_attr_short_name +oid_get_cipher_alg mbedtls_oid_get_cipher_alg +oid_get_ec_grp mbedtls_oid_get_ec_grp +oid_get_extended_key_usage mbedtls_oid_get_extended_key_usage +oid_get_md_alg mbedtls_oid_get_md_alg +oid_get_numeric_string mbedtls_oid_get_numeric_string +oid_get_oid_by_ec_grp mbedtls_oid_get_oid_by_ec_grp +oid_get_oid_by_md mbedtls_oid_get_oid_by_md +oid_get_oid_by_pk_alg mbedtls_oid_get_oid_by_pk_alg +oid_get_oid_by_sig_alg mbedtls_oid_get_oid_by_sig_alg +oid_get_pk_alg mbedtls_oid_get_pk_alg +oid_get_pkcs12_pbe_alg mbedtls_oid_get_pkcs12_pbe_alg +oid_get_sig_alg mbedtls_oid_get_sig_alg +oid_get_sig_alg_desc mbedtls_oid_get_sig_alg_desc +oid_get_x509_ext_type mbedtls_oid_get_x509_ext_type +operation_t mbedtls_operation_t +padlock_supports mbedtls_padlock_has_support +padlock_xcryptcbc mbedtls_padlock_xcryptcbc +padlock_xcryptecb mbedtls_padlock_xcryptecb +pem_context mbedtls_pem_context +pem_free mbedtls_pem_free +pem_init mbedtls_pem_init +pem_read_buffer mbedtls_pem_read_buffer +pem_write_buffer mbedtls_pem_write_buffer +pk_can_do mbedtls_pk_can_do +pk_check_pair mbedtls_pk_check_pair +pk_context mbedtls_pk_context +pk_debug mbedtls_pk_debug +pk_debug_item mbedtls_pk_debug_item +pk_debug_type mbedtls_pk_debug_type +pk_decrypt mbedtls_pk_decrypt +pk_ec mbedtls_pk_ec +pk_encrypt mbedtls_pk_encrypt +pk_free mbedtls_pk_free +pk_get_len mbedtls_pk_get_len +pk_get_name mbedtls_pk_get_name +pk_get_size mbedtls_pk_get_bitlen +pk_get_type mbedtls_pk_get_type +pk_info_from_type mbedtls_pk_info_from_type +pk_info_t mbedtls_pk_info_t +pk_init mbedtls_pk_init +pk_init_ctx mbedtls_pk_setup +pk_init_ctx_rsa_alt mbedtls_pk_setup_rsa_alt +pk_load_file mbedtls_pk_load_file +pk_parse_key mbedtls_pk_parse_key +pk_parse_keyfile mbedtls_pk_parse_keyfile +pk_parse_public_key mbedtls_pk_parse_public_key +pk_parse_public_keyfile mbedtls_pk_parse_public_keyfile +pk_parse_subpubkey mbedtls_pk_parse_subpubkey +pk_rsa mbedtls_pk_rsa +pk_rsa_alt_decrypt_func mbedtls_pk_rsa_alt_decrypt_func +pk_rsa_alt_key_len_func mbedtls_pk_rsa_alt_key_len_func +pk_rsa_alt_sign_func mbedtls_pk_rsa_alt_sign_func +pk_rsassa_pss_options mbedtls_pk_rsassa_pss_options +pk_sign mbedtls_pk_sign +pk_type_t mbedtls_pk_type_t +pk_verify mbedtls_pk_verify +pk_verify_ext mbedtls_pk_verify_ext +pk_write_key_der mbedtls_pk_write_key_der +pk_write_key_pem mbedtls_pk_write_key_pem +pk_write_pubkey mbedtls_pk_write_pubkey +pk_write_pubkey_der mbedtls_pk_write_pubkey_der +pk_write_pubkey_pem mbedtls_pk_write_pubkey_pem +pkcs11_context mbedtls_pkcs11_context +pkcs11_decrypt mbedtls_pkcs11_decrypt +pkcs11_priv_key_free mbedtls_pkcs11_priv_key_free +pkcs11_priv_key_init mbedtls_pkcs11_priv_key_bind +pkcs11_sign mbedtls_pkcs11_sign +pkcs11_x509_cert_init mbedtls_pkcs11_x509_cert_bind +pkcs12_derivation mbedtls_pkcs12_derivation +pkcs12_pbe mbedtls_pkcs12_pbe +pkcs12_pbe_sha1_rc4_128 mbedtls_pkcs12_pbe_sha1_rc4_128 +pkcs5_pbes2 mbedtls_pkcs5_pbes2 +pkcs5_pbkdf2_hmac mbedtls_pkcs5_pbkdf2_hmac +pkcs5_self_test mbedtls_pkcs5_self_test +platform_entropy_poll mbedtls_platform_entropy_poll +platform_set_exit mbedtls_platform_set_exit +platform_set_fprintf mbedtls_platform_set_fprintf +platform_set_malloc_free mbedtls_platform_set_malloc_free +platform_set_printf mbedtls_platform_set_printf +platform_set_snprintf mbedtls_platform_set_snprintf +polarssl_exit mbedtls_exit +polarssl_fprintf mbedtls_fprintf +polarssl_free mbedtls_free +polarssl_malloc mbedtls_malloc +polarssl_mutex_free mbedtls_mutex_free +polarssl_mutex_init mbedtls_mutex_init +polarssl_mutex_lock mbedtls_mutex_lock +polarssl_mutex_unlock mbedtls_mutex_unlock +polarssl_printf mbedtls_printf +polarssl_snprintf mbedtls_snprintf +polarssl_strerror mbedtls_strerror +ripemd160 mbedtls_ripemd160 +ripemd160_context mbedtls_ripemd160_context +ripemd160_file mbedtls_ripemd160_file +ripemd160_finish mbedtls_ripemd160_finish +ripemd160_free mbedtls_ripemd160_free +ripemd160_hmac mbedtls_ripemd160_hmac +ripemd160_hmac_finish mbedtls_ripemd160_hmac_finish +ripemd160_hmac_reset mbedtls_ripemd160_hmac_reset +ripemd160_hmac_starts mbedtls_ripemd160_hmac_starts +ripemd160_hmac_update mbedtls_ripemd160_hmac_update +ripemd160_info mbedtls_ripemd160_info +ripemd160_init mbedtls_ripemd160_init +ripemd160_process mbedtls_ripemd160_process +ripemd160_self_test mbedtls_ripemd160_self_test +ripemd160_starts mbedtls_ripemd160_starts +ripemd160_update mbedtls_ripemd160_update +rsa_alt_context mbedtls_rsa_alt_context +rsa_alt_info mbedtls_rsa_alt_info +rsa_check_privkey mbedtls_rsa_check_privkey +rsa_check_pub_priv mbedtls_rsa_check_pub_priv +rsa_check_pubkey mbedtls_rsa_check_pubkey +rsa_context mbedtls_rsa_context +rsa_copy mbedtls_rsa_copy +rsa_decrypt_func mbedtls_rsa_decrypt_func +rsa_free mbedtls_rsa_free +rsa_gen_key mbedtls_rsa_gen_key +rsa_info mbedtls_rsa_info +rsa_init mbedtls_rsa_init +rsa_key_len_func mbedtls_rsa_key_len_func +rsa_pkcs1_decrypt mbedtls_rsa_pkcs1_decrypt +rsa_pkcs1_encrypt mbedtls_rsa_pkcs1_encrypt +rsa_pkcs1_sign mbedtls_rsa_pkcs1_sign +rsa_pkcs1_verify mbedtls_rsa_pkcs1_verify +rsa_private mbedtls_rsa_private +rsa_public mbedtls_rsa_public +rsa_rsaes_oaep_decrypt mbedtls_rsa_rsaes_oaep_decrypt +rsa_rsaes_oaep_encrypt mbedtls_rsa_rsaes_oaep_encrypt +rsa_rsaes_pkcs1_v15_decrypt mbedtls_rsa_rsaes_pkcs1_v15_decrypt +rsa_rsaes_pkcs1_v15_encrypt mbedtls_rsa_rsaes_pkcs1_v15_encrypt +rsa_rsassa_pkcs1_v15_sign mbedtls_rsa_rsassa_pkcs1_v15_sign +rsa_rsassa_pkcs1_v15_verify mbedtls_rsa_rsassa_pkcs1_v15_verify +rsa_rsassa_pss_sign mbedtls_rsa_rsassa_pss_sign +rsa_rsassa_pss_verify mbedtls_rsa_rsassa_pss_verify +rsa_rsassa_pss_verify_ext mbedtls_rsa_rsassa_pss_verify_ext +rsa_self_test mbedtls_rsa_self_test +rsa_set_padding mbedtls_rsa_set_padding +rsa_sign_func mbedtls_rsa_sign_func +safer_memcmp mbedtls_ssl_safer_memcmp +set_alarm mbedtls_set_alarm +sha1 mbedtls_sha1 +sha1_context mbedtls_sha1_context +sha1_file mbedtls_sha1_file +sha1_finish mbedtls_sha1_finish +sha1_free mbedtls_sha1_free +sha1_hmac mbedtls_sha1_hmac +sha1_hmac_finish mbedtls_sha1_hmac_finish +sha1_hmac_reset mbedtls_sha1_hmac_reset +sha1_hmac_starts mbedtls_sha1_hmac_starts +sha1_hmac_update mbedtls_sha1_hmac_update +sha1_info mbedtls_sha1_info +sha1_init mbedtls_sha1_init +sha1_process mbedtls_sha1_process +sha1_self_test mbedtls_sha1_self_test +sha1_starts mbedtls_sha1_starts +sha1_update mbedtls_sha1_update +sha224_info mbedtls_sha224_info +sha256 mbedtls_sha256 +sha256_context mbedtls_sha256_context +sha256_file mbedtls_sha256_file +sha256_finish mbedtls_sha256_finish +sha256_free mbedtls_sha256_free +sha256_hmac mbedtls_sha256_hmac +sha256_hmac_finish mbedtls_sha256_hmac_finish +sha256_hmac_reset mbedtls_sha256_hmac_reset +sha256_hmac_starts mbedtls_sha256_hmac_starts +sha256_hmac_update mbedtls_sha256_hmac_update +sha256_info mbedtls_sha256_info +sha256_init mbedtls_sha256_init +sha256_process mbedtls_sha256_process +sha256_self_test mbedtls_sha256_self_test +sha256_starts mbedtls_sha256_starts +sha256_update mbedtls_sha256_update +sha384_info mbedtls_sha384_info +sha512 mbedtls_sha512 +sha512_context mbedtls_sha512_context +sha512_file mbedtls_sha512_file +sha512_finish mbedtls_sha512_finish +sha512_free mbedtls_sha512_free +sha512_hmac mbedtls_sha512_hmac +sha512_hmac_finish mbedtls_sha512_hmac_finish +sha512_hmac_reset mbedtls_sha512_hmac_reset +sha512_hmac_starts mbedtls_sha512_hmac_starts +sha512_hmac_update mbedtls_sha512_hmac_update +sha512_info mbedtls_sha512_info +sha512_init mbedtls_sha512_init +sha512_process mbedtls_sha512_process +sha512_self_test mbedtls_sha512_self_test +sha512_starts mbedtls_sha512_starts +sha512_update mbedtls_sha512_update +source_state mbedtls_entropy_source_state +ssl_cache_context mbedtls_ssl_cache_context +ssl_cache_entry mbedtls_ssl_cache_entry +ssl_cache_free mbedtls_ssl_cache_free +ssl_cache_get mbedtls_ssl_cache_get +ssl_cache_init mbedtls_ssl_cache_init +ssl_cache_set mbedtls_ssl_cache_set +ssl_cache_set_max_entries mbedtls_ssl_cache_set_max_entries +ssl_cache_set_timeout mbedtls_ssl_cache_set_timeout +ssl_check_cert_usage mbedtls_ssl_check_cert_usage +ssl_ciphersuite_from_id mbedtls_ssl_ciphersuite_from_id +ssl_ciphersuite_from_string mbedtls_ssl_ciphersuite_from_string +ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t +ssl_ciphersuite_uses_ec mbedtls_ssl_ciphersuite_uses_ec +ssl_ciphersuite_uses_psk mbedtls_ssl_ciphersuite_uses_psk +ssl_close_notify mbedtls_ssl_close_notify +ssl_context mbedtls_ssl_context +ssl_cookie_check mbedtls_ssl_cookie_check +ssl_cookie_check_t mbedtls_ssl_cookie_check_t +ssl_cookie_ctx mbedtls_ssl_cookie_ctx +ssl_cookie_free mbedtls_ssl_cookie_free +ssl_cookie_init mbedtls_ssl_cookie_init +ssl_cookie_set_timeout mbedtls_ssl_cookie_set_timeout +ssl_cookie_setup mbedtls_ssl_cookie_setup +ssl_cookie_write mbedtls_ssl_cookie_write +ssl_cookie_write_t mbedtls_ssl_cookie_write_t +ssl_curve_is_acceptable mbedtls_ssl_curve_is_acceptable +ssl_derive_keys mbedtls_ssl_derive_keys +ssl_dtls_replay_check mbedtls_ssl_dtls_replay_check +ssl_dtls_replay_update mbedtls_ssl_dtls_replay_update +ssl_fetch_input mbedtls_ssl_fetch_input +ssl_flight_item mbedtls_ssl_flight_item +ssl_flush_output mbedtls_ssl_flush_output +ssl_free mbedtls_ssl_free +ssl_get_alpn_protocol mbedtls_ssl_get_alpn_protocol +ssl_get_bytes_avail mbedtls_ssl_get_bytes_avail +ssl_get_ciphersuite mbedtls_ssl_get_ciphersuite +ssl_get_ciphersuite_id mbedtls_ssl_get_ciphersuite_id +ssl_get_ciphersuite_name mbedtls_ssl_get_ciphersuite_name +ssl_get_ciphersuite_sig_pk_alg mbedtls_ssl_get_ciphersuite_sig_pk_alg +ssl_get_peer_cert mbedtls_ssl_get_peer_cert +ssl_get_record_expansion mbedtls_ssl_get_record_expansion +ssl_get_session mbedtls_ssl_get_session +ssl_get_verify_result mbedtls_ssl_get_verify_result +ssl_get_version mbedtls_ssl_get_version +ssl_handshake mbedtls_ssl_handshake +ssl_handshake_client_step mbedtls_ssl_handshake_client_step +ssl_handshake_free mbedtls_ssl_handshake_free +ssl_handshake_params mbedtls_ssl_handshake_params +ssl_handshake_server_step mbedtls_ssl_handshake_server_step +ssl_handshake_step mbedtls_ssl_handshake_step +ssl_handshake_wrapup mbedtls_ssl_handshake_wrapup +ssl_hdr_len mbedtls_ssl_hdr_len +ssl_hs_hdr_len mbedtls_ssl_hs_hdr_len +ssl_hw_record_activate mbedtls_ssl_hw_record_activate +ssl_hw_record_finish mbedtls_ssl_hw_record_finish +ssl_hw_record_init mbedtls_ssl_hw_record_init +ssl_hw_record_read mbedtls_ssl_hw_record_read +ssl_hw_record_reset mbedtls_ssl_hw_record_reset +ssl_hw_record_write mbedtls_ssl_hw_record_write +ssl_init mbedtls_ssl_init +ssl_key_cert mbedtls_ssl_key_cert +ssl_legacy_renegotiation mbedtls_ssl_conf_legacy_renegotiation +ssl_list_ciphersuites mbedtls_ssl_list_ciphersuites +ssl_md_alg_from_hash mbedtls_ssl_md_alg_from_hash +ssl_optimize_checksum mbedtls_ssl_optimize_checksum +ssl_own_cert mbedtls_ssl_own_cert +ssl_own_key mbedtls_ssl_own_key +ssl_parse_certificate mbedtls_ssl_parse_certificate +ssl_parse_change_cipher_spec mbedtls_ssl_parse_change_cipher_spec +ssl_parse_finished mbedtls_ssl_parse_finished +ssl_pk_alg_from_sig mbedtls_ssl_pk_alg_from_sig +ssl_pkcs11_decrypt mbedtls_ssl_pkcs11_decrypt +ssl_pkcs11_key_len mbedtls_ssl_pkcs11_key_len +ssl_pkcs11_sign mbedtls_ssl_pkcs11_sign +ssl_psk_derive_premaster mbedtls_ssl_psk_derive_premaster +ssl_read mbedtls_ssl_read +ssl_read_record mbedtls_ssl_read_record +ssl_read_version mbedtls_ssl_read_version +ssl_recv_flight_completed mbedtls_ssl_recv_flight_completed +ssl_renegotiate mbedtls_ssl_renegotiate +ssl_resend mbedtls_ssl_resend +ssl_reset_checksum mbedtls_ssl_reset_checksum +ssl_send_alert_message mbedtls_ssl_send_alert_message +ssl_send_fatal_handshake_failure mbedtls_ssl_send_fatal_handshake_failure +ssl_send_flight_completed mbedtls_ssl_send_flight_completed +ssl_session mbedtls_ssl_session +ssl_session_free mbedtls_ssl_session_free +ssl_session_init mbedtls_ssl_session_init +ssl_session_reset mbedtls_ssl_session_reset +ssl_set_alpn_protocols mbedtls_ssl_conf_alpn_protocols +ssl_set_arc4_support mbedtls_ssl_conf_arc4_support +ssl_set_authmode mbedtls_ssl_conf_authmode +ssl_set_bio mbedtls_ssl_set_bio +ssl_set_ca_chain mbedtls_ssl_conf_ca_chain +ssl_set_cbc_record_splitting mbedtls_ssl_conf_cbc_record_splitting +ssl_set_ciphersuites mbedtls_ssl_conf_ciphersuites +ssl_set_ciphersuites_for_version mbedtls_ssl_conf_ciphersuites_for_version +ssl_set_client_transport_id mbedtls_ssl_set_client_transport_id +ssl_set_curves mbedtls_ssl_conf_curves +ssl_set_dbg mbedtls_ssl_conf_dbg +ssl_set_dh_param mbedtls_ssl_conf_dh_param +ssl_set_dh_param_ctx mbedtls_ssl_conf_dh_param_ctx +ssl_set_dtls_anti_replay mbedtls_ssl_conf_dtls_anti_replay +ssl_set_dtls_badmac_limit mbedtls_ssl_conf_dtls_badmac_limit +ssl_set_dtls_cookies mbedtls_ssl_conf_dtls_cookies +ssl_set_encrypt_then_mac mbedtls_ssl_conf_encrypt_then_mac +ssl_set_endpoint mbedtls_ssl_conf_endpoint +ssl_set_extended_master_secret mbedtls_ssl_conf_extended_master_secret +ssl_set_fallback mbedtls_ssl_conf_fallback +ssl_set_handshake_timeout mbedtls_ssl_conf_handshake_timeout +ssl_set_hostname mbedtls_ssl_set_hostname +ssl_set_max_frag_len mbedtls_ssl_conf_max_frag_len +ssl_set_max_version mbedtls_ssl_conf_max_version +ssl_set_min_version mbedtls_ssl_conf_min_version +ssl_set_own_cert mbedtls_ssl_conf_own_cert +ssl_set_own_cert_alt mbedtls_ssl_set_own_cert_alt +ssl_set_own_cert_rsa mbedtls_ssl_set_own_cert_rsa +ssl_set_psk mbedtls_ssl_conf_psk +ssl_set_psk_cb mbedtls_ssl_conf_psk_cb +ssl_set_renegotiation mbedtls_ssl_conf_renegotiation +ssl_set_renegotiation_enforced mbedtls_ssl_conf_renegotiation_enforced +ssl_set_renegotiation_period mbedtls_ssl_conf_renegotiation_period +ssl_set_rng mbedtls_ssl_conf_rng +ssl_set_session mbedtls_ssl_set_session +ssl_set_session_cache mbedtls_ssl_conf_session_cache +ssl_set_session_ticket_lifetime mbedtls_ssl_conf_session_ticket_lifetime +ssl_set_session_tickets mbedtls_ssl_conf_session_tickets +ssl_set_sni mbedtls_ssl_conf_sni +ssl_set_transport mbedtls_ssl_conf_transport +ssl_set_truncated_hmac mbedtls_ssl_conf_truncated_hmac +ssl_set_verify mbedtls_ssl_conf_verify +ssl_sig_from_pk mbedtls_ssl_sig_from_pk +ssl_states mbedtls_ssl_states +ssl_ticket_keys mbedtls_ssl_ticket_keys +ssl_transform mbedtls_ssl_transform +ssl_transform_free mbedtls_ssl_transform_free +ssl_write mbedtls_ssl_write +ssl_write_certificate mbedtls_ssl_write_certificate +ssl_write_change_cipher_spec mbedtls_ssl_write_change_cipher_spec +ssl_write_finished mbedtls_ssl_write_finished +ssl_write_record mbedtls_ssl_write_record +ssl_write_version mbedtls_ssl_write_version +supported_ciphers mbedtls_cipher_supported +t_sint mbedtls_mpi_sint +t_udbl mbedtls_t_udbl +t_uint mbedtls_mpi_uint +test_ca_crt mbedtls_test_ca_crt +test_ca_crt_ec mbedtls_test_ca_crt_ec +test_ca_crt_rsa mbedtls_test_ca_crt_rsa +test_ca_key mbedtls_test_ca_key +test_ca_key_ec mbedtls_test_ca_key_ec +test_ca_key_rsa mbedtls_test_ca_key_rsa +test_ca_list mbedtls_test_cas_pem +test_ca_pwd mbedtls_test_ca_pwd +test_ca_pwd_ec mbedtls_test_ca_pwd_ec +test_ca_pwd_rsa mbedtls_test_ca_pwd_rsa +test_cli_crt mbedtls_test_cli_crt +test_cli_crt_ec mbedtls_test_cli_crt_ec +test_cli_crt_rsa mbedtls_test_cli_crt_rsa +test_cli_key mbedtls_test_cli_key +test_cli_key_ec mbedtls_test_cli_key_ec +test_cli_key_rsa mbedtls_test_cli_key_rsa +test_dhm_params mbedtls_test_dhm_params +test_srv_crt mbedtls_test_srv_crt +test_srv_crt_ec mbedtls_test_srv_crt_ec +test_srv_crt_rsa mbedtls_test_srv_crt_rsa +test_srv_key mbedtls_test_srv_key +test_srv_key_ec mbedtls_test_srv_key_ec +test_srv_key_rsa mbedtls_test_srv_key_rsa +threading_mutex_t mbedtls_threading_mutex_t +threading_set_alt mbedtls_threading_set_alt +timing_self_test mbedtls_timing_self_test +version_check_feature mbedtls_version_check_feature +version_get_number mbedtls_version_get_number +version_get_string mbedtls_version_get_string +version_get_string_full mbedtls_version_get_string_full +x509_bitstring mbedtls_x509_bitstring +x509_buf mbedtls_x509_buf +x509_crl mbedtls_x509_crl +x509_crl_entry mbedtls_x509_crl_entry +x509_crl_free mbedtls_x509_crl_free +x509_crl_info mbedtls_x509_crl_info +x509_crl_init mbedtls_x509_crl_init +x509_crl_parse mbedtls_x509_crl_parse +x509_crl_parse_der mbedtls_x509_crl_parse_der +x509_crl_parse_file mbedtls_x509_crl_parse_file +x509_crt mbedtls_x509_crt +x509_crt_check_extended_key_usage mbedtls_x509_crt_check_extended_key_usage +x509_crt_check_key_usage mbedtls_x509_crt_check_key_usage +x509_crt_free mbedtls_x509_crt_free +x509_crt_info mbedtls_x509_crt_info +x509_crt_init mbedtls_x509_crt_init +x509_crt_parse mbedtls_x509_crt_parse +x509_crt_parse_der mbedtls_x509_crt_parse_der +x509_crt_parse_file mbedtls_x509_crt_parse_file +x509_crt_parse_path mbedtls_x509_crt_parse_path +x509_crt_revoked mbedtls_x509_crt_is_revoked +x509_crt_verify mbedtls_x509_crt_verify +x509_crt_verify_info mbedtls_x509_crt_verify_info +x509_csr mbedtls_x509_csr +x509_csr_free mbedtls_x509_csr_free +x509_csr_info mbedtls_x509_csr_info +x509_csr_init mbedtls_x509_csr_init +x509_csr_parse mbedtls_x509_csr_parse +x509_csr_parse_der mbedtls_x509_csr_parse_der +x509_csr_parse_file mbedtls_x509_csr_parse_file +x509_dn_gets mbedtls_x509_dn_gets +x509_get_alg mbedtls_x509_get_alg +x509_get_alg_null mbedtls_x509_get_alg_null +x509_get_ext mbedtls_x509_get_ext +x509_get_name mbedtls_x509_get_name +x509_get_rsassa_pss_params mbedtls_x509_get_rsassa_pss_params +x509_get_serial mbedtls_x509_get_serial +x509_get_sig mbedtls_x509_get_sig +x509_get_sig_alg mbedtls_x509_get_sig_alg +x509_get_time mbedtls_x509_get_time +x509_key_size_helper mbedtls_x509_key_size_helper +x509_name mbedtls_x509_name +x509_oid_get_description mbedtls_x509_oid_get_description +x509_oid_get_numeric_string mbedtls_x509_oid_get_numeric_string +x509_self_test mbedtls_x509_self_test +x509_sequence mbedtls_x509_sequence +x509_serial_gets mbedtls_x509_serial_gets +x509_set_extension mbedtls_x509_set_extension +x509_sig_alg_gets mbedtls_x509_sig_alg_gets +x509_string_to_names mbedtls_x509_string_to_names +x509_time mbedtls_x509_time +x509_time_expired mbedtls_x509_time_is_past +x509_time_future mbedtls_x509_time_is_future +x509_write_extensions mbedtls_x509_write_extensions +x509_write_names mbedtls_x509_write_names +x509_write_sig mbedtls_x509_write_sig +x509write_cert mbedtls_x509write_cert +x509write_crt_der mbedtls_x509write_crt_der +x509write_crt_free mbedtls_x509write_crt_free +x509write_crt_init mbedtls_x509write_crt_init +x509write_crt_pem mbedtls_x509write_crt_pem +x509write_crt_set_authority_key_identifier mbedtls_x509write_crt_set_authority_key_identifier +x509write_crt_set_basic_constraints mbedtls_x509write_crt_set_basic_constraints +x509write_crt_set_extension mbedtls_x509write_crt_set_extension +x509write_crt_set_issuer_key mbedtls_x509write_crt_set_issuer_key +x509write_crt_set_issuer_name mbedtls_x509write_crt_set_issuer_name +x509write_crt_set_key_usage mbedtls_x509write_crt_set_key_usage +x509write_crt_set_md_alg mbedtls_x509write_crt_set_md_alg +x509write_crt_set_ns_cert_type mbedtls_x509write_crt_set_ns_cert_type +x509write_crt_set_serial mbedtls_x509write_crt_set_serial +x509write_crt_set_subject_key mbedtls_x509write_crt_set_subject_key +x509write_crt_set_subject_key_identifier mbedtls_x509write_crt_set_subject_key_identifier +x509write_crt_set_subject_name mbedtls_x509write_crt_set_subject_name +x509write_crt_set_validity mbedtls_x509write_crt_set_validity +x509write_crt_set_version mbedtls_x509write_crt_set_version +x509write_csr mbedtls_x509write_csr +x509write_csr_der mbedtls_x509write_csr_der +x509write_csr_free mbedtls_x509write_csr_free +x509write_csr_init mbedtls_x509write_csr_init +x509write_csr_pem mbedtls_x509write_csr_pem +x509write_csr_set_extension mbedtls_x509write_csr_set_extension +x509write_csr_set_key mbedtls_x509write_csr_set_key +x509write_csr_set_key_usage mbedtls_x509write_csr_set_key_usage +x509write_csr_set_md_alg mbedtls_x509write_csr_set_md_alg +x509write_csr_set_ns_cert_type mbedtls_x509write_csr_set_ns_cert_type +x509write_csr_set_subject_name mbedtls_x509write_csr_set_subject_name +xtea_context mbedtls_xtea_context +xtea_crypt_cbc mbedtls_xtea_crypt_cbc +xtea_crypt_ecb mbedtls_xtea_crypt_ecb +xtea_free mbedtls_xtea_free +xtea_init mbedtls_xtea_init +xtea_self_test mbedtls_xtea_self_test +xtea_setup mbedtls_xtea_setup diff --git a/external/mbedtls/scripts/data_files/version_features.fmt b/external/mbedtls/scripts/data_files/version_features.fmt new file mode 100644 index 0000000..68868b7 --- /dev/null +++ b/external/mbedtls/scripts/data_files/version_features.fmt @@ -0,0 +1,85 @@ +/* + * Version feature information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_VERSION_C) + +#include "mbedtls/version.h" + +#include + +static const char *features[] = { +#if defined(MBEDTLS_VERSION_FEATURES) +FEATURE_DEFINES +#endif /* MBEDTLS_VERSION_FEATURES */ + NULL +}; + +int mbedtls_version_check_feature( const char *feature ) +{ + const char **idx = features; + + if( *idx == NULL ) + return( -2 ); + + if( feature == NULL ) + return( -1 ); + + while( *idx != NULL ) + { + if( !strcmp( *idx, feature ) ) + return( 0 ); + idx++; + } + return( -1 ); +} + +#endif /* MBEDTLS_VERSION_C */ diff --git a/external/mbedtls/scripts/data_files/vs2010-app-template.vcxproj b/external/mbedtls/scripts/data_files/vs2010-app-template.vcxproj new file mode 100644 index 0000000..7bbc804 --- /dev/null +++ b/external/mbedtls/scripts/data_files/vs2010-app-template.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + + Win32Proj + + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/scripts/data_files/vs2010-main-template.vcxproj b/external/mbedtls/scripts/data_files/vs2010-main-template.vcxproj new file mode 100644 index 0000000..b6ee93a --- /dev/null +++ b/external/mbedtls/scripts/data_files/vs2010-main-template.vcxproj @@ -0,0 +1,156 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {46CF2D25-6A36-4189-B59C-E4815388E554} + Win32Proj + mbedTLS + + + + StaticLibrary + true + Unicode + + + StaticLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + StaticLibrary + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MBEDTLS_EXPORTS;%(PreprocessorDefinitions) + ../../include + CompileAsC + + + Windows + true + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MBEDTLS_EXPORTS;%(PreprocessorDefinitions) + ../../include + CompileAsC + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;MBEDTLS_EXPORTS;%(PreprocessorDefinitions) + ../../include + + + Windows + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_WINDOWS;_USRDLL;MBEDTLS_EXPORTS;%(PreprocessorDefinitions) + ../../include + + + Windows + true + true + true + + + +HEADER_ENTRIES + + +SOURCE_ENTRIES + + + + + diff --git a/external/mbedtls/scripts/data_files/vs2010-sln-template.sln b/external/mbedtls/scripts/data_files/vs2010-sln-template.sln new file mode 100644 index 0000000..1c7ad2b --- /dev/null +++ b/external/mbedtls/scripts/data_files/vs2010-sln-template.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mbedTLS", "mbedTLS.vcxproj", "{46CF2D25-6A36-4189-B59C-E4815388E554}" +EndProject +APP_ENTRIES +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|Win32.ActiveCfg = Debug|Win32 + {46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|Win32.Build.0 = Debug|Win32 + {46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|x64.ActiveCfg = Debug|x64 + {46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|x64.Build.0 = Debug|x64 + {46CF2D25-6A36-4189-B59C-E4815388E554}.Release|Win32.ActiveCfg = Release|Win32 + {46CF2D25-6A36-4189-B59C-E4815388E554}.Release|Win32.Build.0 = Release|Win32 + {46CF2D25-6A36-4189-B59C-E4815388E554}.Release|x64.ActiveCfg = Release|x64 + {46CF2D25-6A36-4189-B59C-E4815388E554}.Release|x64.Build.0 = Release|x64 +CONF_ENTRIES + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/external/mbedtls/scripts/data_files/vs6-app-template.dsp b/external/mbedtls/scripts/data_files/vs6-app-template.dsp new file mode 100644 index 0000000..ff7c00e --- /dev/null +++ b/external/mbedtls/scripts/data_files/vs6-app-template.dsp @@ -0,0 +1,101 @@ +# Microsoft Developer Studio Project File - Name="" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG= - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f ".mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f ".mak" CFG=" - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE " - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE " - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == " - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "" +# PROP BASE Intermediate_Dir "temp" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "" +# PROP Intermediate_Dir "temp" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == " - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "" +# PROP BASE Intermediate_Dir "temp" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "" +# PROP Intermediate_Dir "temp" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name " - Win32 Release" +# Name " - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\programs\.c +# ADD CPP /I "../../include" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/external/mbedtls/scripts/data_files/vs6-main-template.dsp b/external/mbedtls/scripts/data_files/vs6-main-template.dsp new file mode 100644 index 0000000..3f4d5c4 --- /dev/null +++ b/external/mbedtls/scripts/data_files/vs6-main-template.dsp @@ -0,0 +1,94 @@ +# Microsoft Developer Studio Project File - Name="mbedtls" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=mbedtls - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mbedtls.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mbedtls.mak" CFG="mbedtls - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mbedtls - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "mbedtls - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mbedtls - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "" +# PROP BASE Intermediate_Dir "temp" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "" +# PROP Intermediate_Dir "temp" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "mbedtls - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "" +# PROP BASE Intermediate_Dir "temp" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "" +# PROP Intermediate_Dir "temp" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /GX /Z7 /Od /I "../../include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "mbedtls - Win32 Release" +# Name "mbedtls - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +SOURCE_ENTRIES +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +HEADER_ENTRIES +# End Group +# End Target +# End Project diff --git a/external/mbedtls/scripts/data_files/vs6-workspace-template.dsw b/external/mbedtls/scripts/data_files/vs6-workspace-template.dsw new file mode 100644 index 0000000..9b2e262 --- /dev/null +++ b/external/mbedtls/scripts/data_files/vs6-workspace-template.dsw @@ -0,0 +1,18 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +APP_ENTRIES +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/external/mbedtls/scripts/ecc-heap.sh b/external/mbedtls/scripts/ecc-heap.sh new file mode 100644 index 0000000..097f36b --- /dev/null +++ b/external/mbedtls/scripts/ecc-heap.sh @@ -0,0 +1,116 @@ +#!/bin/sh + +# Measure heap usage (and performance) of ECC operations with various values of +# the relevant tunable compile-time parameters. +# +# Usage (preferably on a 32-bit platform): +# cmake -D CMAKE_BUILD_TYPE=Release . +# scripts/ecc-heap.sh | tee ecc-heap.log +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** + +set -eu + +CONFIG_H='include/mbedtls/config.h' + +if [ -r $CONFIG_H ]; then :; else + echo "$CONFIG_H not found" >&2 + exit 1 +fi + +if grep -i cmake Makefile >/dev/null; then :; else + echo "Needs Cmake" >&2 + exit 1 +fi + +if git status | grep -F $CONFIG_H >/dev/null 2>&1; then + echo "config.h not clean" >&2 + exit 1 +fi + +CONFIG_BAK=${CONFIG_H}.bak +cp $CONFIG_H $CONFIG_BAK + +cat << EOF >$CONFIG_H +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_PLATFORM_MEMORY +#define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_MEMORY_DEBUG + +#define MBEDTLS_TIMING_C + +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECDH_C + +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED + +#include "check_config.h" + +//#define MBEDTLS_ECP_WINDOW_SIZE 6 +//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 +EOF + +for F in 0 1; do + for W in 2 3 4 5 6; do + scripts/config.pl set MBEDTLS_ECP_WINDOW_SIZE $W + scripts/config.pl set MBEDTLS_ECP_FIXED_POINT_OPTIM $F + make benchmark >/dev/null 2>&1 + echo "fixed point optim = $F, max window size = $W" + echo "--------------------------------------------" + programs/test/benchmark + done +done + +# cleanup + +mv $CONFIG_BAK $CONFIG_H +make clean diff --git a/external/mbedtls/scripts/find-mem-leak.cocci b/external/mbedtls/scripts/find-mem-leak.cocci new file mode 100644 index 0000000..8179e2b --- /dev/null +++ b/external/mbedtls/scripts/find-mem-leak.cocci @@ -0,0 +1,20 @@ +@@ +expression x, y; +statement S; +@@ + x = mbedtls_calloc(...); + y = mbedtls_calloc(...); + ... +* if (x == NULL || y == NULL) + S + +@@ +expression x, y; +statement S; +@@ + if ( +* (x = mbedtls_calloc(...)) == NULL + || +* (y = mbedtls_calloc(...)) == NULL + ) + S diff --git a/external/mbedtls/scripts/footprint.sh b/external/mbedtls/scripts/footprint.sh new file mode 100644 index 0000000..461d6e4 --- /dev/null +++ b/external/mbedtls/scripts/footprint.sh @@ -0,0 +1,147 @@ +#!/bin/sh +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** +# +# Purpose +# +# This script determines ROM size (or code size) for the standard mbed TLS +# configurations, when built for a Cortex M3/M4 target. +# +# Configurations included: +# default include/mbedtls/config.h +# thread configs/config-thread.h +# suite-b configs/config-suite-b.h +# psk configs/config-ccm-psk-tls1_2.h +# +# Usage: footprint.sh +# +set -eu + +CONFIG_H='include/mbedtls/config.h' + +if [ -r $CONFIG_H ]; then :; else + echo "$CONFIG_H not found" >&2 + echo "This script needs to be run from the root of" >&2 + echo "a git checkout or uncompressed tarball" >&2 + exit 1 +fi + +if grep -i cmake Makefile >/dev/null; then + echo "Not compatible with CMake" >&2 + exit 1 +fi + +if which arm-none-eabi-gcc >/dev/null 2>&1; then :; else + echo "You need the ARM-GCC toolchain in your path" >&2 + echo "See https://launchpad.net/gcc-arm-embedded/" >&2 + exit 1 +fi + +ARMGCC_FLAGS='-Os -march=armv7-m -mthumb' +OUTFILE='00-footprint-summary.txt' + +log() +{ + echo "$@" + echo "$@" >> "$OUTFILE" +} + +doit() +{ + NAME="$1" + FILE="$2" + + log "" + log "$NAME ($FILE):" + + cp $CONFIG_H ${CONFIG_H}.bak + if [ "$FILE" != $CONFIG_H ]; then + cp "$FILE" $CONFIG_H + fi + + { + scripts/config.pl unset MBEDTLS_NET_C || true + scripts/config.pl unset MBEDTLS_TIMING_C || true + scripts/config.pl unset MBEDTLS_FS_IO || true + scripts/config.pl --force set MBEDTLS_NO_PLATFORM_ENTROPY || true + } >/dev/null 2>&1 + + make clean >/dev/null + CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld \ + CFLAGS="$ARMGCC_FLAGS" make lib >/dev/null + + OUT="size-${NAME}.txt" + arm-none-eabi-size -t library/libmbed*.a > "$OUT" + log "$( head -n1 "$OUT" )" + log "$( tail -n1 "$OUT" )" + + cp ${CONFIG_H}.bak $CONFIG_H +} + +# truncate the file just this time +echo "(generated by $0)" > "$OUTFILE" +echo "" >> "$OUTFILE" + +log "Footprint of standard configurations (minus net_sockets.c, timing.c, fs_io)" +log "for bare-metal ARM Cortex-M3/M4 microcontrollers." + +VERSION_H="include/mbedtls/version.h" +MBEDTLS_VERSION=$( sed -n 's/.*VERSION_STRING *"\(.*\)"/\1/p' $VERSION_H ) +if git rev-parse HEAD >/dev/null; then + GIT_HEAD=$( git rev-parse HEAD | head -c 10 ) + GIT_VERSION=" (git head: $GIT_HEAD)" +else + GIT_VERSION="" +fi + +log "" +log "mbed TLS $MBEDTLS_VERSION$GIT_VERSION" +log "$( arm-none-eabi-gcc --version | head -n1 )" +log "CFLAGS=$ARMGCC_FLAGS" + +doit default include/mbedtls/config.h +doit thread configs/config-thread.h +doit suite-b configs/config-suite-b.h +doit psk configs/config-ccm-psk-tls1_2.h + +zip mbedtls-footprint.zip "$OUTFILE" size-*.txt >/dev/null diff --git a/external/mbedtls/scripts/generate_errors.pl b/external/mbedtls/scripts/generate_errors.pl new file mode 100644 index 0000000..a2ff4f6 --- /dev/null +++ b/external/mbedtls/scripts/generate_errors.pl @@ -0,0 +1,266 @@ +#!/usr/bin/env perl + +# Generate error.c +# +# Usage: ./generate_errors.pl or scripts/generate_errors.pl without arguments, +# or generate_errors.pl include_dir data_dir error_file +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** + +use strict; + +my ($include_dir, $data_dir, $error_file); + +if( @ARGV ) { + die "Invalid number of arguments" if scalar @ARGV != 3; + ($include_dir, $data_dir, $error_file) = @ARGV; + + -d $include_dir or die "No such directory: $include_dir\n"; + -d $data_dir or die "No such directory: $data_dir\n"; +} else { + $include_dir = 'include/mbedtls'; + $data_dir = 'scripts/data_files'; + $error_file = 'library/error.c'; + + unless( -d $include_dir && -d $data_dir ) { + chdir '..' or die; + -d $include_dir && -d $data_dir + or die "Without arguments, must be run from root or scripts\n" + } +} + +my $error_format_file = $data_dir.'/error.fmt'; + +my @low_level_modules = qw( AES ARC4 ARIA ASN1 BASE64 BIGNUM BLOWFISH + CAMELLIA CCM CHACHA20 CHACHAPOLY CMAC CTR_DRBG DES + ENTROPY GCM HKDF HMAC_DRBG MD2 MD4 MD5 + NET OID PADLOCK PBKDF2 PLATFORM POLY1305 RIPEMD160 + SHA1 SHA256 SHA512 THREADING XTEA ); +my @high_level_modules = qw( CIPHER DHM ECP MD + PEM PK PKCS12 PKCS5 + RSA SSL X509 ); + +my $line_separator = $/; +undef $/; + +open(FORMAT_FILE, "$error_format_file") or die "Opening error format file '$error_format_file': $!"; +my $error_format = ; +close(FORMAT_FILE); + +$/ = $line_separator; + +my @files = <$include_dir/*.h>; +my @necessary_include_files; +my @matches; +foreach my $file (@files) { + open(FILE, "$file"); + my @grep_res = grep(/^\s*#define\s+MBEDTLS_ERR_\w+\s+\-0x[0-9A-Fa-f]+/, ); + push(@matches, @grep_res); + close FILE; + my $include_name = $file; + $include_name =~ s!.*/!!; + push @necessary_include_files, $include_name if @grep_res; +} + +my $ll_old_define = ""; +my $hl_old_define = ""; + +my $ll_code_check = ""; +my $hl_code_check = ""; + +my $headers = ""; +my %included_headers; + +my %error_codes_seen; + +foreach my $line (@matches) +{ + next if ($line =~ /compat-1.2.h/); + my ($error_name, $error_code) = $line =~ /(MBEDTLS_ERR_\w+)\s+\-(0x\w+)/; + my ($description) = $line =~ /\/\*\*< (.*?)\.? \*\//; + + die "Duplicated error code: $error_code ($error_name)\n" + if( $error_codes_seen{$error_code}++ ); + + $description =~ s/\\/\\\\/g; + if ($description eq "") { + $description = "DESCRIPTION MISSING"; + warn "Missing description for $error_name\n"; + } + + my ($module_name) = $error_name =~ /^MBEDTLS_ERR_([^_]+)/; + + # Fix faulty ones + $module_name = "BIGNUM" if ($module_name eq "MPI"); + $module_name = "CTR_DRBG" if ($module_name eq "CTR"); + $module_name = "HMAC_DRBG" if ($module_name eq "HMAC"); + + my $define_name = $module_name; + $define_name = "X509_USE,X509_CREATE" if ($define_name eq "X509"); + $define_name = "ASN1_PARSE" if ($define_name eq "ASN1"); + $define_name = "SSL_TLS" if ($define_name eq "SSL"); + $define_name = "PEM_PARSE,PEM_WRITE" if ($define_name eq "PEM"); + + my $include_name = $module_name; + $include_name =~ tr/A-Z/a-z/; + + # Fix faulty ones + $include_name = "net_sockets" if ($module_name eq "NET"); + + $included_headers{"${include_name}.h"} = $module_name; + + my $found_ll = grep $_ eq $module_name, @low_level_modules; + my $found_hl = grep $_ eq $module_name, @high_level_modules; + if (!$found_ll && !$found_hl) + { + printf("Error: Do not know how to handle: $module_name\n"); + exit 1; + } + + my $code_check; + my $old_define; + my $white_space; + my $first; + + if ($found_ll) + { + $code_check = \$ll_code_check; + $old_define = \$ll_old_define; + $white_space = ' '; + } + else + { + $code_check = \$hl_code_check; + $old_define = \$hl_old_define; + $white_space = ' '; + } + + if ($define_name ne ${$old_define}) + { + if (${$old_define} ne "") + { + ${$code_check} .= "#endif /* "; + $first = 0; + foreach my $dep (split(/,/, ${$old_define})) + { + ${$code_check} .= " || " if ($first++); + ${$code_check} .= "MBEDTLS_${dep}_C"; + } + ${$code_check} .= " */\n\n"; + } + + ${$code_check} .= "#if "; + $headers .= "#if " if ($include_name ne ""); + $first = 0; + foreach my $dep (split(/,/, ${define_name})) + { + ${$code_check} .= " || " if ($first); + $headers .= " || " if ($first++); + + ${$code_check} .= "defined(MBEDTLS_${dep}_C)"; + $headers .= "defined(MBEDTLS_${dep}_C)" if + ($include_name ne ""); + } + ${$code_check} .= "\n"; + $headers .= "\n#include \"mbedtls/${include_name}.h\"\n". + "#endif\n\n" if ($include_name ne ""); + ${$old_define} = $define_name; + } + + if ($error_name eq "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE") + { + ${$code_check} .= "${white_space}if( use_ret == -($error_name) )\n". + "${white_space}\{\n". + "${white_space} mbedtls_snprintf( buf, buflen, \"$module_name - $description\" );\n". + "${white_space} return;\n". + "${white_space}}\n" + } + else + { + ${$code_check} .= "${white_space}if( use_ret == -($error_name) )\n". + "${white_space} mbedtls_snprintf( buf, buflen, \"$module_name - $description\" );\n" + } +}; + +if ($ll_old_define ne "") +{ + $ll_code_check .= "#endif /* "; + my $first = 0; + foreach my $dep (split(/,/, $ll_old_define)) + { + $ll_code_check .= " || " if ($first++); + $ll_code_check .= "MBEDTLS_${dep}_C"; + } + $ll_code_check .= " */\n"; +} +if ($hl_old_define ne "") +{ + $hl_code_check .= "#endif /* "; + my $first = 0; + foreach my $dep (split(/,/, $hl_old_define)) + { + $hl_code_check .= " || " if ($first++); + $hl_code_check .= "MBEDTLS_${dep}_C"; + } + $hl_code_check .= " */\n"; +} + +$error_format =~ s/HEADER_INCLUDED\n/$headers/g; +$error_format =~ s/LOW_LEVEL_CODE_CHECKS\n/$ll_code_check/g; +$error_format =~ s/HIGH_LEVEL_CODE_CHECKS\n/$hl_code_check/g; + +open(ERROR_FILE, ">$error_file") or die "Opening destination file '$error_file': $!"; +print ERROR_FILE $error_format; +close(ERROR_FILE); + +my $errors = 0; +for my $include_name (@necessary_include_files) +{ + if (not $included_headers{$include_name}) + { + print STDERR "The header file \"$include_name\" defines error codes but has not been included!\n"; + ++$errors; + } +} + +exit !!$errors; diff --git a/external/mbedtls/scripts/generate_features.pl b/external/mbedtls/scripts/generate_features.pl new file mode 100644 index 0000000..3a83620 --- /dev/null +++ b/external/mbedtls/scripts/generate_features.pl @@ -0,0 +1,115 @@ +#!/usr/bin/env perl +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** + +use strict; + +my ($include_dir, $data_dir, $feature_file); + +if( @ARGV ) { + die "Invalid number of arguments" if scalar @ARGV != 3; + ($include_dir, $data_dir, $feature_file) = @ARGV; + + -d $include_dir or die "No such directory: $include_dir\n"; + -d $data_dir or die "No such directory: $data_dir\n"; +} else { + $include_dir = 'include/mbedtls'; + $data_dir = 'scripts/data_files'; + $feature_file = 'library/version_features.c'; + + unless( -d $include_dir && -d $data_dir ) { + chdir '..' or die; + -d $include_dir && -d $data_dir + or die "Without arguments, must be run from root or scripts\n" + } +} + +my $feature_format_file = $data_dir.'/version_features.fmt'; + +my @sections = ( "System support", "mbed TLS modules", + "mbed TLS feature support" ); + +my $line_separator = $/; +undef $/; + +open(FORMAT_FILE, "$feature_format_file") or die "Opening feature format file '$feature_format_file': $!"; +my $feature_format = ; +close(FORMAT_FILE); + +$/ = $line_separator; + +open(CONFIG_H, "$include_dir/config.h") || die("Failure when opening config.h: $!"); + +my $feature_defines = ""; +my $in_section = 0; + +while (my $line = ) +{ + next if ($in_section && $line !~ /#define/ && $line !~ /SECTION/); + next if (!$in_section && $line !~ /SECTION/); + + if ($in_section) { + if ($line =~ /SECTION/) { + $in_section = 0; + next; + } + + my ($define) = $line =~ /#define (\w+)/; + $feature_defines .= "#if defined(${define})\n"; + $feature_defines .= " \"${define}\",\n"; + $feature_defines .= "#endif /* ${define} */\n"; + } + + if (!$in_section) { + my ($section_name) = $line =~ /SECTION: ([\w ]+)/; + my $found_section = grep $_ eq $section_name, @sections; + + $in_section = 1 if ($found_section); + } +}; + +$feature_format =~ s/FEATURE_DEFINES\n/$feature_defines/g; + +open(ERROR_FILE, ">$feature_file") or die "Opening destination file '$feature_file': $!"; +print ERROR_FILE $feature_format; +close(ERROR_FILE); diff --git a/external/mbedtls/scripts/generate_query_config.pl b/external/mbedtls/scripts/generate_query_config.pl new file mode 100644 index 0000000..8d7b316 --- /dev/null +++ b/external/mbedtls/scripts/generate_query_config.pl @@ -0,0 +1,117 @@ +#! /usr/bin/env perl + +# Generate query_config.c +# +# The file query_config.c contains a C function that can be used to check if +# a configuration macro is defined and to retrieve its expansion in string +# form (if any). This facilitates querying the compile time configuration of +# the library, for example, for testing. +# +# The query_config.c is generated from the current configuration at +# include/mbedtls/config.h. The idea is that the config.h contains ALL the +# compile time configurations available in Mbed TLS (commented or uncommented). +# This script extracts the configuration macros from the config.h and this +# information is used to automatically generate the body of the query_config() +# function by using the template in scripts/data_files/query_config.fmt. +# +# Usage: ./scripts/generate_query_config.pl without arguments +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** + +use strict; + +my $config_file = "./include/mbedtls/config.h"; + +my $query_config_format_file = "./scripts/data_files/query_config.fmt"; +my $query_config_file = "./programs/ssl/query_config.c"; + +# Excluded macros from the generated query_config.c. For example, macros that +# have commas or function-like macros cannot be transformed into strings easily +# using the preprocessor, so they should be excluded or the preprocessor will +# throw errors. +my @excluded = qw( +MBEDTLS_SSL_CIPHERSUITES +MBEDTLS_PARAM_FAILED +); +my $excluded_re = join '|', @excluded; + +open(CONFIG_FILE, "$config_file") or die "Opening config file '$config_file': $!"; + +# This variable will contain the string to replace in the CHECK_CONFIG of the +# format file +my $config_check = ""; + +while (my $line = ) { + if ($line =~ /^(\/\/)?\s*#\s*define\s+(MBEDTLS_\w+).*/) { + my $name = $2; + + # Skip over the macro that prevents multiple inclusion + next if "MBEDTLS_CONFIG_H" eq $name; + + # Skip over the macro if it is in the ecluded list + next if $name =~ /$excluded_re/; + + $config_check .= "#if defined($name)\n"; + $config_check .= " if( strcmp( \"$name\", config ) == 0 )\n"; + $config_check .= " {\n"; + $config_check .= " MACRO_EXPANSION_TO_STR( $name );\n"; + $config_check .= " return( 0 );\n"; + $config_check .= " }\n"; + $config_check .= "#endif /* $name */\n"; + $config_check .= "\n"; + } +} + +# Read the full format file into a string +local $/; +open(FORMAT_FILE, "$query_config_format_file") or die "Opening query config format file '$query_config_format_file': $!"; +my $query_config_format = ; +close(FORMAT_FILE); + +# Replace the body of the query_config() function with the code we just wrote +$query_config_format =~ s/CHECK_CONFIG/$config_check/g; + +# Rewrite the query_config.c file +open(QUERY_CONFIG_FILE, ">$query_config_file") or die "Opening destination file '$query_config_file': $!"; +print QUERY_CONFIG_FILE $query_config_format; +close(QUERY_CONFIG_FILE); diff --git a/external/mbedtls/scripts/generate_visualc_files.pl b/external/mbedtls/scripts/generate_visualc_files.pl new file mode 100644 index 0000000..6979f94 --- /dev/null +++ b/external/mbedtls/scripts/generate_visualc_files.pl @@ -0,0 +1,252 @@ +#!/usr/bin/env perl + +# Generate main file, individual apps and solution files for MS Visual Studio +# 2010 +# +# Must be run from mbedTLS root or scripts directory. +# Takes no argument. +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** + +use warnings; +use strict; +use Digest::MD5 'md5_hex'; + +my $vsx_dir = "visualc/VS2010"; +my $vsx_ext = "vcxproj"; +my $vsx_app_tpl_file = "scripts/data_files/vs2010-app-template.$vsx_ext"; +my $vsx_main_tpl_file = "scripts/data_files/vs2010-main-template.$vsx_ext"; +my $vsx_main_file = "$vsx_dir/mbedTLS.$vsx_ext"; +my $vsx_sln_tpl_file = "scripts/data_files/vs2010-sln-template.sln"; +my $vsx_sln_file = "$vsx_dir/mbedTLS.sln"; + +my $programs_dir = 'programs'; +my $header_dir = 'include/mbedtls'; +my $source_dir = 'library'; + +# Need windows line endings! +my $vsx_hdr_tpl = <\r +EOT +my $vsx_src_tpl = <\r +EOT + +my $vsx_sln_app_entry_tpl = <; + close $fh; + + return $content; +} + +sub content_to_file { + my ($content, $filename) = @_; + + open my $fh, '>', $filename or die "Could not write to $filename\n"; + print $fh $content; + close $fh; +} + +sub gen_app_guid { + my ($path) = @_; + + my $guid = md5_hex( "mbedTLS:$path" ); + $guid =~ s/(.{8})(.{4})(.{4})(.{4})(.{12})/\U{$1-$2-$3-$4-$5}/; + + return $guid; +} + +sub gen_app { + my ($path, $template, $dir, $ext) = @_; + + my $guid = gen_app_guid( $path ); + $path =~ s!/!\\!g; + (my $appname = $path) =~ s/.*\\//; + + my $srcs = ""; + if( $appname eq "ssl_client2" or $appname eq "ssl_server2" or + $appname eq "query_compile_time_config" ) { + $srcs .= "\r\n "; + } + + my $content = $template; + $content =~ s//$srcs/g; + $content =~ s//$appname/g; + $content =~ s//$guid/g; + + content_to_file( $content, "$dir/$appname.$ext" ); +} + +sub get_app_list { + my $app_list = `cd $programs_dir && make list`; + die "make list failed: $!\n" if $?; + + return split /\s+/, $app_list; +} + +sub gen_app_files { + my @app_list = @_; + + my $vsx_tpl = slurp_file( $vsx_app_tpl_file ); + + for my $app ( @app_list ) { + gen_app( $app, $vsx_tpl, $vsx_dir, $vsx_ext ); + } +} + +sub gen_entry_list { + my ($tpl, @names) = @_; + + my $entries; + for my $name (@names) { + (my $entry = $tpl) =~ s/{NAME}/$name/g; + $entries .= $entry; + } + + return $entries; +} + +sub gen_main_file { + my ($headers, $sources, $hdr_tpl, $src_tpl, $main_tpl, $main_out) = @_; + + my $header_entries = gen_entry_list( $hdr_tpl, @$headers ); + my $source_entries = gen_entry_list( $src_tpl, @$sources ); + + my $out = slurp_file( $main_tpl ); + $out =~ s/SOURCE_ENTRIES\r\n/$source_entries/m; + $out =~ s/HEADER_ENTRIES\r\n/$header_entries/m; + + content_to_file( $out, $main_out ); +} + +sub gen_vsx_solution { + my (@app_names) = @_; + + my ($app_entries, $conf_entries); + for my $path (@app_names) { + my $guid = gen_app_guid( $path ); + (my $appname = $path) =~ s!.*/!!; + + my $app_entry = $vsx_sln_app_entry_tpl; + $app_entry =~ s/{APPNAME}/$appname/g; + $app_entry =~ s/{GUID}/$guid/g; + + $app_entries .= $app_entry; + + my $conf_entry = $vsx_sln_conf_entry_tpl; + $conf_entry =~ s/{GUID}/$guid/g; + + $conf_entries .= $conf_entry; + } + + my $out = slurp_file( $vsx_sln_tpl_file ); + $out =~ s/APP_ENTRIES\r\n/$app_entries/m; + $out =~ s/CONF_ENTRIES\r\n/$conf_entries/m; + + content_to_file( $out, $vsx_sln_file ); +} + +sub del_vsx_files { + unlink glob "'$vsx_dir/*.$vsx_ext'"; + unlink $vsx_main_file; + unlink $vsx_sln_file; +} + +sub main { + if( ! check_dirs() ) { + chdir '..' or die; + check_dirs or die "Must but run from mbedTLS root or scripts dir\n"; + } + + # Remove old files to ensure that, for example, project files from deleted + # apps are not kept + del_vsx_files(); + + my @app_list = get_app_list(); + my @headers = <$header_dir/*.h>; + my @sources = <$source_dir/*.c>; + map { s!/!\\!g } @headers; + map { s!/!\\!g } @sources; + + gen_app_files( @app_list ); + + gen_main_file( \@headers, \@sources, + $vsx_hdr_tpl, $vsx_src_tpl, + $vsx_main_tpl_file, $vsx_main_file ); + + gen_vsx_solution( @app_list ); + + return 0; +} diff --git a/external/mbedtls/scripts/massif_max.pl b/external/mbedtls/scripts/massif_max.pl new file mode 100644 index 0000000..2dc4222 --- /dev/null +++ b/external/mbedtls/scripts/massif_max.pl @@ -0,0 +1,75 @@ +#!/usr/bin/env perl + +# Parse a massif.out.xxx file and output peak total memory usage +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** + +use warnings; +use strict; + +use utf8; +use open qw(:std utf8); + +die unless @ARGV == 1; + +my @snaps; +open my $fh, '<', $ARGV[0] or die; +{ local $/ = 'snapshot='; @snaps = <$fh>; } +close $fh or die; + +my ($max, $max_heap, $max_he, $max_stack) = (0, 0, 0, 0); +for (@snaps) +{ + my ($heap, $heap_extra, $stack) = m{ + mem_heap_B=(\d+)\n + mem_heap_extra_B=(\d+)\n + mem_stacks_B=(\d+) + }xm; + next unless defined $heap; + my $total = $heap + $heap_extra + $stack; + if( $total > $max ) { + ($max, $max_heap, $max_he, $max_stack) = ($total, $heap, $heap_extra, $stack); + } +} + +printf "$max (heap $max_heap+$max_he, stack $max_stack)\n"; diff --git a/external/mbedtls/scripts/memory.sh b/external/mbedtls/scripts/memory.sh new file mode 100644 index 0000000..8f8dcd7 --- /dev/null +++ b/external/mbedtls/scripts/memory.sh @@ -0,0 +1,168 @@ +#!/bin/sh + +# Measure memory usage of a minimal client using a small configuration +# Currently hardwired to ccm-psk and suite-b, may be expanded later +# +# Use different build options for measuring executable size and memory usage, +# since for memory we want debug information. +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** + +set -eu + +CONFIG_H='include/mbedtls/config.h' + +CLIENT='mini_client' + +CFLAGS_EXEC='-fno-asynchronous-unwind-tables -Wl,--gc-section -ffunction-sections -fdata-sections' +CFLAGS_MEM=-g3 + +if [ -r $CONFIG_H ]; then :; else + echo "$CONFIG_H not found" >&2 + exit 1 +fi + +if grep -i cmake Makefile >/dev/null; then + echo "Not compatible with CMake" >&2 + exit 1 +fi + +if [ $( uname ) != Linux ]; then + echo "Only work on Linux" >&2 + exit 1 +fi + +if git status | grep -F $CONFIG_H >/dev/null 2>&1; then + echo "config.h not clean" >&2 + exit 1 +fi + +# make measurements with one configuration +# usage: do_config +do_config() +{ + NAME=$1 + UNSET_LIST=$2 + SERVER_ARGS=$3 + + echo "" + echo "config-$NAME:" + cp configs/config-$NAME.h $CONFIG_H + scripts/config.pl unset MBEDTLS_SSL_SRV_C + + for FLAG in $UNSET_LIST; do + scripts/config.pl unset $FLAG + done + + grep -F SSL_MAX_CONTENT_LEN $CONFIG_H || echo 'SSL_MAX_CONTENT_LEN=16384' + + printf " Executable size... " + + make clean + CFLAGS=$CFLAGS_EXEC make OFLAGS=-Os lib >/dev/null 2>&1 + cd programs + CFLAGS=$CFLAGS_EXEC make OFLAGS=-Os ssl/$CLIENT >/dev/null + strip ssl/$CLIENT + stat -c '%s' ssl/$CLIENT + cd .. + + printf " Peak ram usage... " + + make clean + CFLAGS=$CFLAGS_MEM make OFLAGS=-Os lib >/dev/null 2>&1 + cd programs + CFLAGS=$CFLAGS_MEM make OFLAGS=-Os ssl/$CLIENT >/dev/null + cd .. + + ./ssl_server2 $SERVER_ARGS >/dev/null & + SRV_PID=$! + sleep 1; + + if valgrind --tool=massif --stacks=yes programs/ssl/$CLIENT >/dev/null 2>&1 + then + FAILED=0 + else + echo "client failed" >&2 + FAILED=1 + fi + + kill $SRV_PID + wait $SRV_PID + + scripts/massif_max.pl massif.out.* + mv massif.out.* massif-$NAME.$$ +} + +# preparation + +CONFIG_BAK=${CONFIG_H}.bak +cp $CONFIG_H $CONFIG_BAK + +rm -f massif.out.* + +printf "building server... " + +make clean +make lib >/dev/null 2>&1 +(cd programs && make ssl/ssl_server2) >/dev/null +cp programs/ssl/ssl_server2 . + +echo "done" + +# actual measurements + +do_config "ccm-psk-tls1_2" \ + "" \ + "psk=000102030405060708090A0B0C0D0E0F" + +do_config "suite-b" \ + "MBEDTLS_BASE64_C MBEDTLS_PEM_PARSE_C MBEDTLS_CERTS_C" \ + "" + +# cleanup + +mv $CONFIG_BAK $CONFIG_H +make clean +rm ssl_server2 + +exit $FAILED diff --git a/external/mbedtls/scripts/output_env.sh b/external/mbedtls/scripts/output_env.sh new file mode 100644 index 0000000..a39a3d9 --- /dev/null +++ b/external/mbedtls/scripts/output_env.sh @@ -0,0 +1,219 @@ +#! /usr/bin/env sh + +# output_env.sh +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** +# +# Purpose +# +# To print out all the relevant information about the development environment. +# +# This includes: +# - architecture of the system +# - type and version of the operating system +# - version of make and cmake +# - version of armcc, clang, gcc-arm and gcc compilers +# - version of libc, clang, asan and valgrind if installed +# - version of gnuTLS and OpenSSL + +print_version() +{ + BIN="$1" + shift + ARGS="$1" + shift + VARIANT="$1" + shift + + if [ -n "$VARIANT" ]; then + VARIANT=" ($VARIANT)" + fi + + if ! type "$BIN" > /dev/null 2>&1; then + echo " * ${BIN##*/}$VARIANT: Not found." + return 0 + fi + + BIN=`which "$BIN"` + VERSION_STR=`$BIN $ARGS 2>&1` + + # Apply all filters + while [ $# -gt 0 ]; do + FILTER="$1" + shift + VERSION_STR=`echo "$VERSION_STR" | $FILTER` + done + + if [ -z "$VERSION_STR" ]; then + VERSION_STR="Version could not be determined." + fi + + echo " * ${BIN##*/}$VARIANT: ${BIN} : ${VERSION_STR} " +} + +echo "** Platform:" +echo + +if [ `uname -s` = "Linux" ]; then + echo "Linux variant" + lsb_release -d -c +else + echo "Unknown Unix variant" +fi + +echo + +print_version "uname" "-a" "" + +echo +echo +echo "** Tool Versions:" +echo + +print_version "make" "--version" "" "head -n 1" +echo + +print_version "cmake" "--version" "" "head -n 1" +echo + +if [ "${RUN_ARMCC:-1}" -ne 0 ]; then + : "${ARMC5_CC:=armcc}" + print_version "$ARMC5_CC" "--vsn" "" "head -n 2" + echo + + : "${ARMC6_CC:=armclang}" + print_version "$ARMC6_CC" "--vsn" "" "head -n 2" + echo +fi + +print_version "arm-none-eabi-gcc" "--version" "" "head -n 1" +echo + +print_version "gcc" "--version" "" "head -n 1" +echo + +print_version "clang" "--version" "" "head -n 2" +echo + +print_version "ldd" "--version" "" "head -n 1" +echo + +print_version "valgrind" "--version" "" +echo + +print_version "gdb" "--version" "" "head -n 1" +echo + +print_version "perl" "--version" "" "head -n 2" "grep ." +echo + +print_version "python" "--version" "" "head -n 1" +echo + +print_version "python3" "--version" "" "head -n 1" +echo + +# Find the installed version of Pylint. Installed as a distro package this can +# be pylint3 and as a PEP egg, pylint. In test scripts We prefer pylint over +# pylint3 +if type pylint >/dev/null 2>/dev/null; then + print_version "pylint" "--version" "" "sed /^.*config/d" "grep pylint" +elif type pylint3 >/dev/null 2>/dev/null; then + print_version "pylint3" "--version" "" "sed /^.*config/d" "grep pylint" +else + echo " * pylint or pylint3: Not found." +fi +echo + +: ${OPENSSL:=openssl} +print_version "$OPENSSL" "version" "default" +echo + +if [ -n "${OPENSSL_LEGACY+set}" ]; then + print_version "$OPENSSL_LEGACY" "version" "legacy" +else + echo " * openssl (legacy): Not configured." +fi +echo + +if [ -n "${OPENSSL_NEXT+set}" ]; then + print_version "$OPENSSL_NEXT" "version" "next" +else + echo " * openssl (next): Not configured." +fi +echo + +: ${GNUTLS_CLI:=gnutls-cli} +print_version "$GNUTLS_CLI" "--version" "default" "head -n 1" +echo + +: ${GNUTLS_SERV:=gnutls-serv} +print_version "$GNUTLS_SERV" "--version" "default" "head -n 1" +echo + +if [ -n "${GNUTLS_LEGACY_CLI+set}" ]; then + print_version "$GNUTLS_LEGACY_CLI" "--version" "legacy" "head -n 1" +else + echo " * gnutls-cli (legacy): Not configured." +fi +echo + +if [ -n "${GNUTLS_LEGACY_SERV+set}" ]; then + print_version "$GNUTLS_LEGACY_SERV" "--version" "legacy" "head -n 1" +else + echo " * gnutls-serv (legacy): Not configured." +fi +echo + +echo " * Installed asan versions:" +if type dpkg-query >/dev/null 2>/dev/null; then + if ! dpkg-query -f '${Status} ${Package}: ${Version}\n' -W 'libasan*' | + awk '$3 == "installed" && $4 !~ /-/ {print $4, $5}' | + grep . + then + echo " No asan versions installed." + fi +else + echo " Unable to determine the asan version without dpkg." +fi +echo diff --git a/external/mbedtls/scripts/rename.pl b/external/mbedtls/scripts/rename.pl new file mode 100644 index 0000000..3f47bf2 --- /dev/null +++ b/external/mbedtls/scripts/rename.pl @@ -0,0 +1,160 @@ +#!/usr/bin/env perl +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** +# +# Purpose +# +# This script migrates application source code from the mbed TLS 1.3 API to the +# mbed TLS 2.0 API. +# +# The script processes the given source code and renames identifiers - functions +# types, enums etc, as +# +# Usage: rename.pl [-f datafile] [-s] [--] [filenames...] +# + +use warnings; +use strict; + +use utf8; +use Path::Class; +use open qw(:std utf8); + +my $usage = "Usage: $0 [-f datafile] [-s] [--] [filenames...]\n"; + +(my $datafile = $0) =~ s/rename.pl$/data_files\/rename-1.3-2.0.txt/; +my $do_strings = 0; + +while( @ARGV && $ARGV[0] =~ /^-/ ) { + my $opt = shift; + if( $opt eq '--' ) { + last; + } elsif( $opt eq '-f' ) { + $datafile = shift; + } elsif( $opt eq '-s' ) { + $do_strings = 1; shift; + } else { + die $usage; + } +} + +my %subst; +open my $nfh, '<', $datafile or die "Could not read $datafile\n"; +my $ident = qr/[_A-Za-z][_A-Za-z0-9]*/; +while( my $line = <$nfh> ) { + chomp $line; + my ( $old, $new ) = ( $line =~ /^($ident)\s+($ident)$/ ); + if( ! $old || ! $new ) { + die "$0: $datafile:$.: bad input '$line'\n"; + } + $subst{$old} = $new; +} +close $nfh or die; + +my $string = qr/"(?:\\.|[^\\"])*"/; +my $space = qr/\s+/; +my $idnum = qr/[a-zA-Z0-9_]+/; +my $symbols = qr/[-!#\$%&'()*+,.\/:;<=>?@[\\\]^_`{|}~]+|"/; + +my $lib_include_dir = dir($0)->parent->parent->subdir('include', 'mbedtls'); +my $lib_source_dir = dir($0)->parent->parent->subdir('library'); + +# if we replace inside strings, we don't consider them a token +my $token = $do_strings ? qr/$space|$idnum|$symbols/ + : qr/$string|$space|$idnum|$symbols/; + +my %warnings; + +# If no files were passed, exit... +if ( not defined($ARGV[0]) ){ die $usage; } + +while( my $filename = shift ) +{ + print STDERR "$filename... "; + + if( dir($filename)->parent eq $lib_include_dir || + dir($filename)->parent eq $lib_source_dir ) + { + die "Script cannot be executed on the mbed TLS library itself."; + } + + if( -d $filename ) { print STDERR "skip (directory)\n"; next } + + open my $rfh, '<', $filename or die; + my @lines = <$rfh>; + close $rfh or die; + + my @out; + for my $line (@lines) { + if( $line =~ /#include/ ) { + $line =~ s/polarssl/mbedtls/; + $line =~ s/POLARSSL/MBEDTLS/; + push( @out, $line ); + next; + } + + my @words = ($line =~ /$token/g); + my $checkline = join '', @words; + if( $checkline eq $line ) { + my @new = map { exists $subst{$_} ? $subst{$_} : $_ } @words; + push( @out, join '', @new ); + } else { + $warnings{$filename} = [] unless $warnings{$filename}; + push @{ $warnings{$filename} }, $line; + push( @out, $line ); + } + } + + open my $wfh, '>', $filename or die; + print $wfh $_ for @out; + close $wfh or die; + print STDERR "done\n"; +} + +if( %warnings ) { + print "\nWarning: lines skipped due to unexpected characters:\n"; + for my $filename (sort keys %warnings) { + print "in $filename:\n"; + print for @{ $warnings{$filename} }; + } +} diff --git a/external/mbedtls/scripts/rm-calloc-cast.cocci b/external/mbedtls/scripts/rm-calloc-cast.cocci new file mode 100644 index 0000000..89481c0 --- /dev/null +++ b/external/mbedtls/scripts/rm-calloc-cast.cocci @@ -0,0 +1,7 @@ +@rm_calloc_cast@ +expression x, n, m; +type T; +@@ + x = +- (T *) + mbedtls_calloc(n, m) diff --git a/external/mbedtls/scripts/tmp_ignore_makefiles.sh b/external/mbedtls/scripts/tmp_ignore_makefiles.sh new file mode 100644 index 0000000..427e33b --- /dev/null +++ b/external/mbedtls/scripts/tmp_ignore_makefiles.sh @@ -0,0 +1,86 @@ +#!/bin/bash + +# Temporarily (de)ignore Makefiles generated by CMake to allow easier +# git development +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +# This file is provided under the Apache License 2.0, or the +# GNU General Public License v2.0 or later. +# +# ********** +# Apache License 2.0: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ********** +# +# ********** +# GNU General Public License v2.0 or later: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ********** + +IGNORE="" + +# Parse arguments +# +until [ -z "$1" ] +do + case "$1" in + -u|--undo) + IGNORE="0" + ;; + -v|--verbose) + # Be verbose + VERBOSE="1" + ;; + -h|--help) + # print help + echo "Usage: $0" + echo -e " -h|--help\t\tPrint this help." + echo -e " -u|--undo\t\tRemove ignores and continue tracking." + echo -e " -v|--verbose\t\tVerbose." + exit 1 + ;; + *) + # print error + echo "Unknown argument: '$1'" + exit 1 + ;; + esac + shift +done + +if [ "X" = "X$IGNORE" ]; +then + [ $VERBOSE ] && echo "Ignoring Makefiles" + git update-index --assume-unchanged Makefile library/Makefile programs/Makefile tests/Makefile +else + [ $VERBOSE ] && echo "Tracking Makefiles" + git update-index --no-assume-unchanged Makefile library/Makefile programs/Makefile tests/Makefile +fi diff --git a/external/mbedtls/scripts/windows_msbuild.bat b/external/mbedtls/scripts/windows_msbuild.bat new file mode 100644 index 0000000..cfb5f01 --- /dev/null +++ b/external/mbedtls/scripts/windows_msbuild.bat @@ -0,0 +1,20 @@ +@rem Build and test Mbed TLS with Visual Studio using msbuild. +@rem Usage: windows_msbuild [RETARGET] +@rem RETARGET: version of Visual Studio to emulate +@rem https://docs.microsoft.com/en-us/cpp/build/how-to-modify-the-target-framework-and-platform-toolset + +@rem These parameters are hard-coded for now. +set "arch=x64" & @rem "x86" or "x64" +set "cfg=Release" & @rem "Debug" or "Release" +set "vcvarsall=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" + +if not "%~1"=="" set "retarget=,PlatformToolset=%1" + +@rem If the %USERPROFILE%\Source directory exists, then running +@rem vcvarsall.bat will silently change the directory to that directory. +@rem Setting the VSCMD_START_DIR environment variable causes it to change +@rem to that directory instead. +set "VSCMD_START_DIR=%~dp0\..\visualc\VS2010" + +"%vcvarsall%" x64 && ^ +msbuild /t:Rebuild /p:Configuration=%cfg%%retarget% /m mbedTLS.sln diff --git a/external/mbedtls/visualc/VS2010/aescrypt2.vcxproj b/external/mbedtls/visualc/VS2010/aescrypt2.vcxproj new file mode 100644 index 0000000..346e6f6 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/aescrypt2.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8} + Win32Proj + aescrypt2 + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/benchmark.vcxproj b/external/mbedtls/visualc/VS2010/benchmark.vcxproj new file mode 100644 index 0000000..5662662 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/benchmark.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA} + Win32Proj + benchmark + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/cert_app.vcxproj b/external/mbedtls/visualc/VS2010/cert_app.vcxproj new file mode 100644 index 0000000..d4e569a --- /dev/null +++ b/external/mbedtls/visualc/VS2010/cert_app.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {D4D691D4-137C-CBFA-735B-D46636D7E4D8} + Win32Proj + cert_app + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/cert_req.vcxproj b/external/mbedtls/visualc/VS2010/cert_req.vcxproj new file mode 100644 index 0000000..12fbc0b --- /dev/null +++ b/external/mbedtls/visualc/VS2010/cert_req.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE} + Win32Proj + cert_req + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/cert_write.vcxproj b/external/mbedtls/visualc/VS2010/cert_write.vcxproj new file mode 100644 index 0000000..7544db9 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/cert_write.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {35E52E46-3BA9-4361-41D3-53663C2E9B8A} + Win32Proj + cert_write + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/crl_app.vcxproj b/external/mbedtls/visualc/VS2010/crl_app.vcxproj new file mode 100644 index 0000000..70bc71e --- /dev/null +++ b/external/mbedtls/visualc/VS2010/crl_app.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {DB904B85-AD31-B7FB-114F-88760CC485F2} + Win32Proj + crl_app + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/crypt_and_hash.vcxproj b/external/mbedtls/visualc/VS2010/crypt_and_hash.vcxproj new file mode 100644 index 0000000..49098fe --- /dev/null +++ b/external/mbedtls/visualc/VS2010/crypt_and_hash.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7} + Win32Proj + crypt_and_hash + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/dh_client.vcxproj b/external/mbedtls/visualc/VS2010/dh_client.vcxproj new file mode 100644 index 0000000..0c75938 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/dh_client.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE} + Win32Proj + dh_client + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/dh_genprime.vcxproj b/external/mbedtls/visualc/VS2010/dh_genprime.vcxproj new file mode 100644 index 0000000..14a0616 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/dh_genprime.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {718960D9-5DA6-7B56-39AD-637E81076C71} + Win32Proj + dh_genprime + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/dh_server.vcxproj b/external/mbedtls/visualc/VS2010/dh_server.vcxproj new file mode 100644 index 0000000..1ed632c --- /dev/null +++ b/external/mbedtls/visualc/VS2010/dh_server.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {8D91B804-E2CE-142D-8E06-FBB037ED1F65} + Win32Proj + dh_server + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/dtls_client.vcxproj b/external/mbedtls/visualc/VS2010/dtls_client.vcxproj new file mode 100644 index 0000000..e71384d --- /dev/null +++ b/external/mbedtls/visualc/VS2010/dtls_client.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5} + Win32Proj + dtls_client + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/dtls_server.vcxproj b/external/mbedtls/visualc/VS2010/dtls_server.vcxproj new file mode 100644 index 0000000..d519495 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/dtls_server.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317} + Win32Proj + dtls_server + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/ecdh_curve25519.vcxproj b/external/mbedtls/visualc/VS2010/ecdh_curve25519.vcxproj new file mode 100644 index 0000000..f125036 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/ecdh_curve25519.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {82EE497E-12CC-7C5B-A072-665678ACB43E} + Win32Proj + ecdh_curve25519 + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/ecdsa.vcxproj b/external/mbedtls/visualc/VS2010/ecdsa.vcxproj new file mode 100644 index 0000000..59ad211 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/ecdsa.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {F58142CC-0CC7-0B18-5A0F-53642CFBA18E} + Win32Proj + ecdsa + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/gen_entropy.vcxproj b/external/mbedtls/visualc/VS2010/gen_entropy.vcxproj new file mode 100644 index 0000000..1b05feb --- /dev/null +++ b/external/mbedtls/visualc/VS2010/gen_entropy.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {DE695064-13C3-18B0-378D-8B22672BF3F4} + Win32Proj + gen_entropy + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/gen_key.vcxproj b/external/mbedtls/visualc/VS2010/gen_key.vcxproj new file mode 100644 index 0000000..9c69909 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/gen_key.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52} + Win32Proj + gen_key + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/gen_random_ctr_drbg.vcxproj b/external/mbedtls/visualc/VS2010/gen_random_ctr_drbg.vcxproj new file mode 100644 index 0000000..4603bcb --- /dev/null +++ b/external/mbedtls/visualc/VS2010/gen_random_ctr_drbg.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E} + Win32Proj + gen_random_ctr_drbg + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/gen_random_havege.vcxproj b/external/mbedtls/visualc/VS2010/gen_random_havege.vcxproj new file mode 100644 index 0000000..6e33c9c --- /dev/null +++ b/external/mbedtls/visualc/VS2010/gen_random_havege.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {71257802-BBCA-99F5-E9D2-905738F30893} + Win32Proj + gen_random_havege + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/generic_sum.vcxproj b/external/mbedtls/visualc/VS2010/generic_sum.vcxproj new file mode 100644 index 0000000..8b443c7 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/generic_sum.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {D071CCF7-ACA0-21F8-D382-52A759AEA261} + Win32Proj + generic_sum + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/hello.vcxproj b/external/mbedtls/visualc/VS2010/hello.vcxproj new file mode 100644 index 0000000..fef5c49 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/hello.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D} + Win32Proj + hello + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/key_app.vcxproj b/external/mbedtls/visualc/VS2010/key_app.vcxproj new file mode 100644 index 0000000..234fb13 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/key_app.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {10AE376F-1A70-0297-0216-1FD01AD15D19} + Win32Proj + key_app + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/key_app_writer.vcxproj b/external/mbedtls/visualc/VS2010/key_app_writer.vcxproj new file mode 100644 index 0000000..a5f21aa --- /dev/null +++ b/external/mbedtls/visualc/VS2010/key_app_writer.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8} + Win32Proj + key_app_writer + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/mbedTLS.sln b/external/mbedtls/visualc/VS2010/mbedTLS.sln new file mode 100644 index 0000000..349d150 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/mbedTLS.sln @@ -0,0 +1,650 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mbedTLS", "mbedTLS.vcxproj", "{46CF2D25-6A36-4189-B59C-E4815388E554}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "aescrypt2", "aescrypt2.vcxproj", "{7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crypt_and_hash", "crypt_and_hash.vcxproj", "{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello", "hello.vcxproj", "{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "generic_sum", "generic_sum.vcxproj", "{D071CCF7-ACA0-21F8-D382-52A759AEA261}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dh_client", "dh_client.vcxproj", "{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dh_genprime", "dh_genprime.vcxproj", "{718960D9-5DA6-7B56-39AD-637E81076C71}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dh_server", "dh_server.vcxproj", "{8D91B804-E2CE-142D-8E06-FBB037ED1F65}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ecdh_curve25519", "ecdh_curve25519.vcxproj", "{82EE497E-12CC-7C5B-A072-665678ACB43E}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ecdsa", "ecdsa.vcxproj", "{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_key", "gen_key.vcxproj", "{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "key_app", "key_app.vcxproj", "{10AE376F-1A70-0297-0216-1FD01AD15D19}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "key_app_writer", "key_app_writer.vcxproj", "{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mpi_demo", "mpi_demo.vcxproj", "{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pk_decrypt", "pk_decrypt.vcxproj", "{1EC6CBA3-6187-D456-D9B7-A35399395D71}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pk_encrypt", "pk_encrypt.vcxproj", "{55007179-7746-9CFB-97EC-65102FB272C8}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pk_sign", "pk_sign.vcxproj", "{F2E8CA55-597F-7FDC-6456-D8650FB970A3}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pk_verify", "pk_verify.vcxproj", "{C429B336-1B30-119C-3B34-21A186D6744F}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_genkey", "rsa_genkey.vcxproj", "{F472475C-F677-0E7F-F127-45BF5B64F622}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_decrypt", "rsa_decrypt.vcxproj", "{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_encrypt", "rsa_encrypt.vcxproj", "{D06CF12E-F222-9273-41BF-B8A052FA5527}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_sign", "rsa_sign.vcxproj", "{10790F49-6887-AAB6-2D86-BCBD516F8D26}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_verify", "rsa_verify.vcxproj", "{689E28CF-89ED-BA38-3A14-78A75D891D46}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_sign_pss", "rsa_sign_pss.vcxproj", "{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_verify_pss", "rsa_verify_pss.vcxproj", "{95C50864-854C-2A11-4C91-BCE654E344FB}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dtls_client", "dtls_client.vcxproj", "{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dtls_server", "dtls_server.vcxproj", "{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_client1", "ssl_client1.vcxproj", "{487A2F80-3CA3-678D-88D5-82194872CF08}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_client2", "ssl_client2.vcxproj", "{4E590E9D-E28F-87FF-385B-D58736388231}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_server", "ssl_server.vcxproj", "{E08E0065-896A-7487-DEA5-D3B80B71F975}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_server2", "ssl_server2.vcxproj", "{A4DA7463-1047-BDF5-E1B3-5632CB573F41}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_fork_server", "ssl_fork_server.vcxproj", "{918CD402-047D-8467-E11C-E1132053F916}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mini_client", "mini_client.vcxproj", "{C4FE29EA-266D-5295-4840-976B9B5B3843}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_mail_client", "ssl_mail_client.vcxproj", "{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_entropy", "gen_entropy.vcxproj", "{DE695064-13C3-18B0-378D-8B22672BF3F4}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_random_havege", "gen_random_havege.vcxproj", "{71257802-BBCA-99F5-E9D2-905738F30893}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_random_ctr_drbg", "gen_random_ctr_drbg.vcxproj", "{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "benchmark", "benchmark.vcxproj", "{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "selftest", "selftest.vcxproj", "{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "udp_proxy", "udp_proxy.vcxproj", "{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zeroize", "zeroize.vcxproj", "{10C01E94-4926-063E-9F56-C84ED190D349}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "query_compile_time_config", "query_compile_time_config.vcxproj", "{D6F58AF2-9D80-562A-E2B0-F743281522B9}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pem2der", "pem2der.vcxproj", "{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "strerror", "strerror.vcxproj", "{23EF735C-CC4C-3EC4-A75E-903DB340F04A}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cert_app", "cert_app.vcxproj", "{D4D691D4-137C-CBFA-735B-D46636D7E4D8}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crl_app", "crl_app.vcxproj", "{DB904B85-AD31-B7FB-114F-88760CC485F2}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cert_req", "cert_req.vcxproj", "{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cert_write", "cert_write.vcxproj", "{35E52E46-3BA9-4361-41D3-53663C2E9B8A}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "req_app", "req_app.vcxproj", "{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|Win32.ActiveCfg = Debug|Win32 + {46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|Win32.Build.0 = Debug|Win32 + {46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|x64.ActiveCfg = Debug|x64 + {46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|x64.Build.0 = Debug|x64 + {46CF2D25-6A36-4189-B59C-E4815388E554}.Release|Win32.ActiveCfg = Release|Win32 + {46CF2D25-6A36-4189-B59C-E4815388E554}.Release|Win32.Build.0 = Release|Win32 + {46CF2D25-6A36-4189-B59C-E4815388E554}.Release|x64.ActiveCfg = Release|x64 + {46CF2D25-6A36-4189-B59C-E4815388E554}.Release|x64.Build.0 = Release|x64 + {7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Debug|Win32.ActiveCfg = Debug|Win32 + {7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Debug|Win32.Build.0 = Debug|Win32 + {7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Debug|x64.ActiveCfg = Debug|x64 + {7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Debug|x64.Build.0 = Debug|x64 + {7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Release|Win32.ActiveCfg = Release|Win32 + {7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Release|Win32.Build.0 = Release|Win32 + {7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Release|x64.ActiveCfg = Release|x64 + {7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Release|x64.Build.0 = Release|x64 + {5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Debug|Win32.ActiveCfg = Debug|Win32 + {5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Debug|Win32.Build.0 = Debug|Win32 + {5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Debug|x64.ActiveCfg = Debug|x64 + {5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Debug|x64.Build.0 = Debug|x64 + {5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Release|Win32.ActiveCfg = Release|Win32 + {5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Release|Win32.Build.0 = Release|Win32 + {5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Release|x64.ActiveCfg = Release|x64 + {5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Release|x64.Build.0 = Release|x64 + {B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Debug|Win32.ActiveCfg = Debug|Win32 + {B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Debug|Win32.Build.0 = Debug|Win32 + {B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Debug|x64.ActiveCfg = Debug|x64 + {B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Debug|x64.Build.0 = Debug|x64 + {B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Release|Win32.ActiveCfg = Release|Win32 + {B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Release|Win32.Build.0 = Release|Win32 + {B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Release|x64.ActiveCfg = Release|x64 + {B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Release|x64.Build.0 = Release|x64 + {D071CCF7-ACA0-21F8-D382-52A759AEA261}.Debug|Win32.ActiveCfg = Debug|Win32 + {D071CCF7-ACA0-21F8-D382-52A759AEA261}.Debug|Win32.Build.0 = Debug|Win32 + {D071CCF7-ACA0-21F8-D382-52A759AEA261}.Debug|x64.ActiveCfg = Debug|x64 + {D071CCF7-ACA0-21F8-D382-52A759AEA261}.Debug|x64.Build.0 = Debug|x64 + {D071CCF7-ACA0-21F8-D382-52A759AEA261}.Release|Win32.ActiveCfg = Release|Win32 + {D071CCF7-ACA0-21F8-D382-52A759AEA261}.Release|Win32.Build.0 = Release|Win32 + {D071CCF7-ACA0-21F8-D382-52A759AEA261}.Release|x64.ActiveCfg = Release|x64 + {D071CCF7-ACA0-21F8-D382-52A759AEA261}.Release|x64.Build.0 = Release|x64 + {4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Debug|Win32.ActiveCfg = Debug|Win32 + {4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Debug|Win32.Build.0 = Debug|Win32 + {4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Debug|x64.ActiveCfg = Debug|x64 + {4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Debug|x64.Build.0 = Debug|x64 + {4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Release|Win32.ActiveCfg = Release|Win32 + {4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Release|Win32.Build.0 = Release|Win32 + {4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Release|x64.ActiveCfg = Release|x64 + {4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Release|x64.Build.0 = Release|x64 + {718960D9-5DA6-7B56-39AD-637E81076C71}.Debug|Win32.ActiveCfg = Debug|Win32 + {718960D9-5DA6-7B56-39AD-637E81076C71}.Debug|Win32.Build.0 = Debug|Win32 + {718960D9-5DA6-7B56-39AD-637E81076C71}.Debug|x64.ActiveCfg = Debug|x64 + {718960D9-5DA6-7B56-39AD-637E81076C71}.Debug|x64.Build.0 = Debug|x64 + {718960D9-5DA6-7B56-39AD-637E81076C71}.Release|Win32.ActiveCfg = Release|Win32 + {718960D9-5DA6-7B56-39AD-637E81076C71}.Release|Win32.Build.0 = Release|Win32 + {718960D9-5DA6-7B56-39AD-637E81076C71}.Release|x64.ActiveCfg = Release|x64 + {718960D9-5DA6-7B56-39AD-637E81076C71}.Release|x64.Build.0 = Release|x64 + {8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Debug|Win32.ActiveCfg = Debug|Win32 + {8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Debug|Win32.Build.0 = Debug|Win32 + {8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Debug|x64.ActiveCfg = Debug|x64 + {8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Debug|x64.Build.0 = Debug|x64 + {8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Release|Win32.ActiveCfg = Release|Win32 + {8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Release|Win32.Build.0 = Release|Win32 + {8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Release|x64.ActiveCfg = Release|x64 + {8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Release|x64.Build.0 = Release|x64 + {82EE497E-12CC-7C5B-A072-665678ACB43E}.Debug|Win32.ActiveCfg = Debug|Win32 + {82EE497E-12CC-7C5B-A072-665678ACB43E}.Debug|Win32.Build.0 = Debug|Win32 + {82EE497E-12CC-7C5B-A072-665678ACB43E}.Debug|x64.ActiveCfg = Debug|x64 + {82EE497E-12CC-7C5B-A072-665678ACB43E}.Debug|x64.Build.0 = Debug|x64 + {82EE497E-12CC-7C5B-A072-665678ACB43E}.Release|Win32.ActiveCfg = Release|Win32 + {82EE497E-12CC-7C5B-A072-665678ACB43E}.Release|Win32.Build.0 = Release|Win32 + {82EE497E-12CC-7C5B-A072-665678ACB43E}.Release|x64.ActiveCfg = Release|x64 + {82EE497E-12CC-7C5B-A072-665678ACB43E}.Release|x64.Build.0 = Release|x64 + {F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Debug|Win32.ActiveCfg = Debug|Win32 + {F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Debug|Win32.Build.0 = Debug|Win32 + {F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Debug|x64.ActiveCfg = Debug|x64 + {F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Debug|x64.Build.0 = Debug|x64 + {F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Release|Win32.ActiveCfg = Release|Win32 + {F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Release|Win32.Build.0 = Release|Win32 + {F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Release|x64.ActiveCfg = Release|x64 + {F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Release|x64.Build.0 = Release|x64 + {BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Debug|Win32.ActiveCfg = Debug|Win32 + {BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Debug|Win32.Build.0 = Debug|Win32 + {BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Debug|x64.ActiveCfg = Debug|x64 + {BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Debug|x64.Build.0 = Debug|x64 + {BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Release|Win32.ActiveCfg = Release|Win32 + {BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Release|Win32.Build.0 = Release|Win32 + {BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Release|x64.ActiveCfg = Release|x64 + {BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Release|x64.Build.0 = Release|x64 + {10AE376F-1A70-0297-0216-1FD01AD15D19}.Debug|Win32.ActiveCfg = Debug|Win32 + {10AE376F-1A70-0297-0216-1FD01AD15D19}.Debug|Win32.Build.0 = Debug|Win32 + {10AE376F-1A70-0297-0216-1FD01AD15D19}.Debug|x64.ActiveCfg = Debug|x64 + {10AE376F-1A70-0297-0216-1FD01AD15D19}.Debug|x64.Build.0 = Debug|x64 + {10AE376F-1A70-0297-0216-1FD01AD15D19}.Release|Win32.ActiveCfg = Release|Win32 + {10AE376F-1A70-0297-0216-1FD01AD15D19}.Release|Win32.Build.0 = Release|Win32 + {10AE376F-1A70-0297-0216-1FD01AD15D19}.Release|x64.ActiveCfg = Release|x64 + {10AE376F-1A70-0297-0216-1FD01AD15D19}.Release|x64.Build.0 = Release|x64 + {E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Debug|Win32.ActiveCfg = Debug|Win32 + {E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Debug|Win32.Build.0 = Debug|Win32 + {E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Debug|x64.ActiveCfg = Debug|x64 + {E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Debug|x64.Build.0 = Debug|x64 + {E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Release|Win32.ActiveCfg = Release|Win32 + {E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Release|Win32.Build.0 = Release|Win32 + {E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Release|x64.ActiveCfg = Release|x64 + {E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Release|x64.Build.0 = Release|x64 + {A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Debug|Win32.ActiveCfg = Debug|Win32 + {A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Debug|Win32.Build.0 = Debug|Win32 + {A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Debug|x64.ActiveCfg = Debug|x64 + {A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Debug|x64.Build.0 = Debug|x64 + {A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Release|Win32.ActiveCfg = Release|Win32 + {A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Release|Win32.Build.0 = Release|Win32 + {A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Release|x64.ActiveCfg = Release|x64 + {A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Release|x64.Build.0 = Release|x64 + {1EC6CBA3-6187-D456-D9B7-A35399395D71}.Debug|Win32.ActiveCfg = Debug|Win32 + {1EC6CBA3-6187-D456-D9B7-A35399395D71}.Debug|Win32.Build.0 = Debug|Win32 + {1EC6CBA3-6187-D456-D9B7-A35399395D71}.Debug|x64.ActiveCfg = Debug|x64 + {1EC6CBA3-6187-D456-D9B7-A35399395D71}.Debug|x64.Build.0 = Debug|x64 + {1EC6CBA3-6187-D456-D9B7-A35399395D71}.Release|Win32.ActiveCfg = Release|Win32 + {1EC6CBA3-6187-D456-D9B7-A35399395D71}.Release|Win32.Build.0 = Release|Win32 + {1EC6CBA3-6187-D456-D9B7-A35399395D71}.Release|x64.ActiveCfg = Release|x64 + {1EC6CBA3-6187-D456-D9B7-A35399395D71}.Release|x64.Build.0 = Release|x64 + {55007179-7746-9CFB-97EC-65102FB272C8}.Debug|Win32.ActiveCfg = Debug|Win32 + {55007179-7746-9CFB-97EC-65102FB272C8}.Debug|Win32.Build.0 = Debug|Win32 + {55007179-7746-9CFB-97EC-65102FB272C8}.Debug|x64.ActiveCfg = Debug|x64 + {55007179-7746-9CFB-97EC-65102FB272C8}.Debug|x64.Build.0 = Debug|x64 + {55007179-7746-9CFB-97EC-65102FB272C8}.Release|Win32.ActiveCfg = Release|Win32 + {55007179-7746-9CFB-97EC-65102FB272C8}.Release|Win32.Build.0 = Release|Win32 + {55007179-7746-9CFB-97EC-65102FB272C8}.Release|x64.ActiveCfg = Release|x64 + {55007179-7746-9CFB-97EC-65102FB272C8}.Release|x64.Build.0 = Release|x64 + {F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Debug|Win32.ActiveCfg = Debug|Win32 + {F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Debug|Win32.Build.0 = Debug|Win32 + {F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Debug|x64.ActiveCfg = Debug|x64 + {F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Debug|x64.Build.0 = Debug|x64 + {F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Release|Win32.ActiveCfg = Release|Win32 + {F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Release|Win32.Build.0 = Release|Win32 + {F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Release|x64.ActiveCfg = Release|x64 + {F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Release|x64.Build.0 = Release|x64 + {C429B336-1B30-119C-3B34-21A186D6744F}.Debug|Win32.ActiveCfg = Debug|Win32 + {C429B336-1B30-119C-3B34-21A186D6744F}.Debug|Win32.Build.0 = Debug|Win32 + {C429B336-1B30-119C-3B34-21A186D6744F}.Debug|x64.ActiveCfg = Debug|x64 + {C429B336-1B30-119C-3B34-21A186D6744F}.Debug|x64.Build.0 = Debug|x64 + {C429B336-1B30-119C-3B34-21A186D6744F}.Release|Win32.ActiveCfg = Release|Win32 + {C429B336-1B30-119C-3B34-21A186D6744F}.Release|Win32.Build.0 = Release|Win32 + {C429B336-1B30-119C-3B34-21A186D6744F}.Release|x64.ActiveCfg = Release|x64 + {C429B336-1B30-119C-3B34-21A186D6744F}.Release|x64.Build.0 = Release|x64 + {F472475C-F677-0E7F-F127-45BF5B64F622}.Debug|Win32.ActiveCfg = Debug|Win32 + {F472475C-F677-0E7F-F127-45BF5B64F622}.Debug|Win32.Build.0 = Debug|Win32 + {F472475C-F677-0E7F-F127-45BF5B64F622}.Debug|x64.ActiveCfg = Debug|x64 + {F472475C-F677-0E7F-F127-45BF5B64F622}.Debug|x64.Build.0 = Debug|x64 + {F472475C-F677-0E7F-F127-45BF5B64F622}.Release|Win32.ActiveCfg = Release|Win32 + {F472475C-F677-0E7F-F127-45BF5B64F622}.Release|Win32.Build.0 = Release|Win32 + {F472475C-F677-0E7F-F127-45BF5B64F622}.Release|x64.ActiveCfg = Release|x64 + {F472475C-F677-0E7F-F127-45BF5B64F622}.Release|x64.Build.0 = Release|x64 + {E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Debug|Win32.ActiveCfg = Debug|Win32 + {E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Debug|Win32.Build.0 = Debug|Win32 + {E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Debug|x64.ActiveCfg = Debug|x64 + {E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Debug|x64.Build.0 = Debug|x64 + {E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Release|Win32.ActiveCfg = Release|Win32 + {E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Release|Win32.Build.0 = Release|Win32 + {E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Release|x64.ActiveCfg = Release|x64 + {E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Release|x64.Build.0 = Release|x64 + {D06CF12E-F222-9273-41BF-B8A052FA5527}.Debug|Win32.ActiveCfg = Debug|Win32 + {D06CF12E-F222-9273-41BF-B8A052FA5527}.Debug|Win32.Build.0 = Debug|Win32 + {D06CF12E-F222-9273-41BF-B8A052FA5527}.Debug|x64.ActiveCfg = Debug|x64 + {D06CF12E-F222-9273-41BF-B8A052FA5527}.Debug|x64.Build.0 = Debug|x64 + {D06CF12E-F222-9273-41BF-B8A052FA5527}.Release|Win32.ActiveCfg = Release|Win32 + {D06CF12E-F222-9273-41BF-B8A052FA5527}.Release|Win32.Build.0 = Release|Win32 + {D06CF12E-F222-9273-41BF-B8A052FA5527}.Release|x64.ActiveCfg = Release|x64 + {D06CF12E-F222-9273-41BF-B8A052FA5527}.Release|x64.Build.0 = Release|x64 + {10790F49-6887-AAB6-2D86-BCBD516F8D26}.Debug|Win32.ActiveCfg = Debug|Win32 + {10790F49-6887-AAB6-2D86-BCBD516F8D26}.Debug|Win32.Build.0 = Debug|Win32 + {10790F49-6887-AAB6-2D86-BCBD516F8D26}.Debug|x64.ActiveCfg = Debug|x64 + {10790F49-6887-AAB6-2D86-BCBD516F8D26}.Debug|x64.Build.0 = Debug|x64 + {10790F49-6887-AAB6-2D86-BCBD516F8D26}.Release|Win32.ActiveCfg = Release|Win32 + {10790F49-6887-AAB6-2D86-BCBD516F8D26}.Release|Win32.Build.0 = Release|Win32 + {10790F49-6887-AAB6-2D86-BCBD516F8D26}.Release|x64.ActiveCfg = Release|x64 + {10790F49-6887-AAB6-2D86-BCBD516F8D26}.Release|x64.Build.0 = Release|x64 + {689E28CF-89ED-BA38-3A14-78A75D891D46}.Debug|Win32.ActiveCfg = Debug|Win32 + {689E28CF-89ED-BA38-3A14-78A75D891D46}.Debug|Win32.Build.0 = Debug|Win32 + {689E28CF-89ED-BA38-3A14-78A75D891D46}.Debug|x64.ActiveCfg = Debug|x64 + {689E28CF-89ED-BA38-3A14-78A75D891D46}.Debug|x64.Build.0 = Debug|x64 + {689E28CF-89ED-BA38-3A14-78A75D891D46}.Release|Win32.ActiveCfg = Release|Win32 + {689E28CF-89ED-BA38-3A14-78A75D891D46}.Release|Win32.Build.0 = Release|Win32 + {689E28CF-89ED-BA38-3A14-78A75D891D46}.Release|x64.ActiveCfg = Release|x64 + {689E28CF-89ED-BA38-3A14-78A75D891D46}.Release|x64.Build.0 = Release|x64 + {DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Debug|Win32.ActiveCfg = Debug|Win32 + {DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Debug|Win32.Build.0 = Debug|Win32 + {DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Debug|x64.ActiveCfg = Debug|x64 + {DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Debug|x64.Build.0 = Debug|x64 + {DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Release|Win32.ActiveCfg = Release|Win32 + {DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Release|Win32.Build.0 = Release|Win32 + {DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Release|x64.ActiveCfg = Release|x64 + {DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Release|x64.Build.0 = Release|x64 + {95C50864-854C-2A11-4C91-BCE654E344FB}.Debug|Win32.ActiveCfg = Debug|Win32 + {95C50864-854C-2A11-4C91-BCE654E344FB}.Debug|Win32.Build.0 = Debug|Win32 + {95C50864-854C-2A11-4C91-BCE654E344FB}.Debug|x64.ActiveCfg = Debug|x64 + {95C50864-854C-2A11-4C91-BCE654E344FB}.Debug|x64.Build.0 = Debug|x64 + {95C50864-854C-2A11-4C91-BCE654E344FB}.Release|Win32.ActiveCfg = Release|Win32 + {95C50864-854C-2A11-4C91-BCE654E344FB}.Release|Win32.Build.0 = Release|Win32 + {95C50864-854C-2A11-4C91-BCE654E344FB}.Release|x64.ActiveCfg = Release|x64 + {95C50864-854C-2A11-4C91-BCE654E344FB}.Release|x64.Build.0 = Release|x64 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|Win32.ActiveCfg = Debug|Win32 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|Win32.Build.0 = Debug|Win32 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|x64.ActiveCfg = Debug|x64 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|x64.Build.0 = Debug|x64 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|Win32.ActiveCfg = Release|Win32 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|Win32.Build.0 = Release|Win32 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|x64.ActiveCfg = Release|x64 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|x64.Build.0 = Release|x64 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|Win32.ActiveCfg = Debug|Win32 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|Win32.Build.0 = Debug|Win32 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|x64.ActiveCfg = Debug|x64 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|x64.Build.0 = Debug|x64 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|Win32.ActiveCfg = Release|Win32 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|Win32.Build.0 = Release|Win32 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|x64.ActiveCfg = Release|x64 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|x64.Build.0 = Release|x64 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|Win32.ActiveCfg = Debug|Win32 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|Win32.Build.0 = Debug|Win32 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|x64.ActiveCfg = Debug|x64 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|x64.Build.0 = Debug|x64 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Release|Win32.ActiveCfg = Release|Win32 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Release|Win32.Build.0 = Release|Win32 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Release|x64.ActiveCfg = Release|x64 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Release|x64.Build.0 = Release|x64 + {4E590E9D-E28F-87FF-385B-D58736388231}.Debug|Win32.ActiveCfg = Debug|Win32 + {4E590E9D-E28F-87FF-385B-D58736388231}.Debug|Win32.Build.0 = Debug|Win32 + {4E590E9D-E28F-87FF-385B-D58736388231}.Debug|x64.ActiveCfg = Debug|x64 + {4E590E9D-E28F-87FF-385B-D58736388231}.Debug|x64.Build.0 = Debug|x64 + {4E590E9D-E28F-87FF-385B-D58736388231}.Release|Win32.ActiveCfg = Release|Win32 + {4E590E9D-E28F-87FF-385B-D58736388231}.Release|Win32.Build.0 = Release|Win32 + {4E590E9D-E28F-87FF-385B-D58736388231}.Release|x64.ActiveCfg = Release|x64 + {4E590E9D-E28F-87FF-385B-D58736388231}.Release|x64.Build.0 = Release|x64 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|Win32.ActiveCfg = Debug|Win32 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|Win32.Build.0 = Debug|Win32 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|x64.ActiveCfg = Debug|x64 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|x64.Build.0 = Debug|x64 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|Win32.ActiveCfg = Release|Win32 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|Win32.Build.0 = Release|Win32 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|x64.ActiveCfg = Release|x64 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|x64.Build.0 = Release|x64 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|Win32.ActiveCfg = Debug|Win32 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|Win32.Build.0 = Debug|Win32 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|x64.ActiveCfg = Debug|x64 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|x64.Build.0 = Debug|x64 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|Win32.ActiveCfg = Release|Win32 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|Win32.Build.0 = Release|Win32 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|x64.ActiveCfg = Release|x64 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|x64.Build.0 = Release|x64 + {918CD402-047D-8467-E11C-E1132053F916}.Debug|Win32.ActiveCfg = Debug|Win32 + {918CD402-047D-8467-E11C-E1132053F916}.Debug|Win32.Build.0 = Debug|Win32 + {918CD402-047D-8467-E11C-E1132053F916}.Debug|x64.ActiveCfg = Debug|x64 + {918CD402-047D-8467-E11C-E1132053F916}.Debug|x64.Build.0 = Debug|x64 + {918CD402-047D-8467-E11C-E1132053F916}.Release|Win32.ActiveCfg = Release|Win32 + {918CD402-047D-8467-E11C-E1132053F916}.Release|Win32.Build.0 = Release|Win32 + {918CD402-047D-8467-E11C-E1132053F916}.Release|x64.ActiveCfg = Release|x64 + {918CD402-047D-8467-E11C-E1132053F916}.Release|x64.Build.0 = Release|x64 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|Win32.ActiveCfg = Debug|Win32 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|Win32.Build.0 = Debug|Win32 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|x64.ActiveCfg = Debug|x64 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|x64.Build.0 = Debug|x64 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|Win32.ActiveCfg = Release|Win32 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|Win32.Build.0 = Release|Win32 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|x64.ActiveCfg = Release|x64 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|x64.Build.0 = Release|x64 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|Win32.ActiveCfg = Debug|Win32 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|Win32.Build.0 = Debug|Win32 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|x64.ActiveCfg = Debug|x64 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|x64.Build.0 = Debug|x64 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|Win32.ActiveCfg = Release|Win32 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|Win32.Build.0 = Release|Win32 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|x64.ActiveCfg = Release|x64 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|x64.Build.0 = Release|x64 + {DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|Win32.ActiveCfg = Debug|Win32 + {DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|Win32.Build.0 = Debug|Win32 + {DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|x64.ActiveCfg = Debug|x64 + {DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|x64.Build.0 = Debug|x64 + {DE695064-13C3-18B0-378D-8B22672BF3F4}.Release|Win32.ActiveCfg = Release|Win32 + {DE695064-13C3-18B0-378D-8B22672BF3F4}.Release|Win32.Build.0 = Release|Win32 + {DE695064-13C3-18B0-378D-8B22672BF3F4}.Release|x64.ActiveCfg = Release|x64 + {DE695064-13C3-18B0-378D-8B22672BF3F4}.Release|x64.Build.0 = Release|x64 + {71257802-BBCA-99F5-E9D2-905738F30893}.Debug|Win32.ActiveCfg = Debug|Win32 + {71257802-BBCA-99F5-E9D2-905738F30893}.Debug|Win32.Build.0 = Debug|Win32 + {71257802-BBCA-99F5-E9D2-905738F30893}.Debug|x64.ActiveCfg = Debug|x64 + {71257802-BBCA-99F5-E9D2-905738F30893}.Debug|x64.Build.0 = Debug|x64 + {71257802-BBCA-99F5-E9D2-905738F30893}.Release|Win32.ActiveCfg = Release|Win32 + {71257802-BBCA-99F5-E9D2-905738F30893}.Release|Win32.Build.0 = Release|Win32 + {71257802-BBCA-99F5-E9D2-905738F30893}.Release|x64.ActiveCfg = Release|x64 + {71257802-BBCA-99F5-E9D2-905738F30893}.Release|x64.Build.0 = Release|x64 + {5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Debug|Win32.ActiveCfg = Debug|Win32 + {5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Debug|Win32.Build.0 = Debug|Win32 + {5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Debug|x64.ActiveCfg = Debug|x64 + {5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Debug|x64.Build.0 = Debug|x64 + {5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|Win32.ActiveCfg = Release|Win32 + {5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|Win32.Build.0 = Release|Win32 + {5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|x64.ActiveCfg = Release|x64 + {5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|x64.Build.0 = Release|x64 + {90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|Win32.ActiveCfg = Debug|Win32 + {90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|Win32.Build.0 = Debug|Win32 + {90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|x64.ActiveCfg = Debug|x64 + {90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|x64.Build.0 = Debug|x64 + {90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Release|Win32.ActiveCfg = Release|Win32 + {90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Release|Win32.Build.0 = Release|Win32 + {90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Release|x64.ActiveCfg = Release|x64 + {90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Release|x64.Build.0 = Release|x64 + {7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Debug|Win32.ActiveCfg = Debug|Win32 + {7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Debug|Win32.Build.0 = Debug|Win32 + {7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Debug|x64.ActiveCfg = Debug|x64 + {7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Debug|x64.Build.0 = Debug|x64 + {7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|Win32.ActiveCfg = Release|Win32 + {7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|Win32.Build.0 = Release|Win32 + {7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|x64.ActiveCfg = Release|x64 + {7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|x64.Build.0 = Release|x64 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|Win32.ActiveCfg = Debug|Win32 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|Win32.Build.0 = Debug|Win32 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|x64.ActiveCfg = Debug|x64 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|x64.Build.0 = Debug|x64 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|Win32.ActiveCfg = Release|Win32 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|Win32.Build.0 = Release|Win32 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|x64.ActiveCfg = Release|x64 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|x64.Build.0 = Release|x64 + {10C01E94-4926-063E-9F56-C84ED190D349}.Debug|Win32.ActiveCfg = Debug|Win32 + {10C01E94-4926-063E-9F56-C84ED190D349}.Debug|Win32.Build.0 = Debug|Win32 + {10C01E94-4926-063E-9F56-C84ED190D349}.Debug|x64.ActiveCfg = Debug|x64 + {10C01E94-4926-063E-9F56-C84ED190D349}.Debug|x64.Build.0 = Debug|x64 + {10C01E94-4926-063E-9F56-C84ED190D349}.Release|Win32.ActiveCfg = Release|Win32 + {10C01E94-4926-063E-9F56-C84ED190D349}.Release|Win32.Build.0 = Release|Win32 + {10C01E94-4926-063E-9F56-C84ED190D349}.Release|x64.ActiveCfg = Release|x64 + {10C01E94-4926-063E-9F56-C84ED190D349}.Release|x64.Build.0 = Release|x64 + {D6F58AF2-9D80-562A-E2B0-F743281522B9}.Debug|Win32.ActiveCfg = Debug|Win32 + {D6F58AF2-9D80-562A-E2B0-F743281522B9}.Debug|Win32.Build.0 = Debug|Win32 + {D6F58AF2-9D80-562A-E2B0-F743281522B9}.Debug|x64.ActiveCfg = Debug|x64 + {D6F58AF2-9D80-562A-E2B0-F743281522B9}.Debug|x64.Build.0 = Debug|x64 + {D6F58AF2-9D80-562A-E2B0-F743281522B9}.Release|Win32.ActiveCfg = Release|Win32 + {D6F58AF2-9D80-562A-E2B0-F743281522B9}.Release|Win32.Build.0 = Release|Win32 + {D6F58AF2-9D80-562A-E2B0-F743281522B9}.Release|x64.ActiveCfg = Release|x64 + {D6F58AF2-9D80-562A-E2B0-F743281522B9}.Release|x64.Build.0 = Release|x64 + {D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|Win32.ActiveCfg = Debug|Win32 + {D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|Win32.Build.0 = Debug|Win32 + {D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|x64.ActiveCfg = Debug|x64 + {D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|x64.Build.0 = Debug|x64 + {D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Release|Win32.ActiveCfg = Release|Win32 + {D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Release|Win32.Build.0 = Release|Win32 + {D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Release|x64.ActiveCfg = Release|x64 + {D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Release|x64.Build.0 = Release|x64 + {23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Debug|Win32.ActiveCfg = Debug|Win32 + {23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Debug|Win32.Build.0 = Debug|Win32 + {23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Debug|x64.ActiveCfg = Debug|x64 + {23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Debug|x64.Build.0 = Debug|x64 + {23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|Win32.ActiveCfg = Release|Win32 + {23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|Win32.Build.0 = Release|Win32 + {23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|x64.ActiveCfg = Release|x64 + {23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|x64.Build.0 = Release|x64 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|Win32.ActiveCfg = Debug|Win32 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|Win32.Build.0 = Debug|Win32 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|x64.ActiveCfg = Debug|x64 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|x64.Build.0 = Debug|x64 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|Win32.ActiveCfg = Release|Win32 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|Win32.Build.0 = Release|Win32 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|x64.ActiveCfg = Release|x64 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|x64.Build.0 = Release|x64 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|Win32.ActiveCfg = Debug|Win32 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|Win32.Build.0 = Debug|Win32 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|x64.ActiveCfg = Debug|x64 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|x64.Build.0 = Debug|x64 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|Win32.ActiveCfg = Release|Win32 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|Win32.Build.0 = Release|Win32 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|x64.ActiveCfg = Release|x64 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|x64.Build.0 = Release|x64 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|Win32.ActiveCfg = Debug|Win32 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|Win32.Build.0 = Debug|Win32 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|x64.ActiveCfg = Debug|x64 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|x64.Build.0 = Debug|x64 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|Win32.ActiveCfg = Release|Win32 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|Win32.Build.0 = Release|Win32 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|x64.ActiveCfg = Release|x64 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|x64.Build.0 = Release|x64 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|Win32.ActiveCfg = Debug|Win32 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|Win32.Build.0 = Debug|Win32 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|x64.ActiveCfg = Debug|x64 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|x64.Build.0 = Debug|x64 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|Win32.ActiveCfg = Release|Win32 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|Win32.Build.0 = Release|Win32 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|x64.ActiveCfg = Release|x64 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|x64.Build.0 = Release|x64 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|Win32.ActiveCfg = Debug|Win32 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|Win32.Build.0 = Debug|Win32 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|x64.ActiveCfg = Debug|x64 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|x64.Build.0 = Debug|x64 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|Win32.ActiveCfg = Release|Win32 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|Win32.Build.0 = Release|Win32 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|x64.ActiveCfg = Release|x64 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/external/mbedtls/visualc/VS2010/mbedTLS.vcxproj b/external/mbedtls/visualc/VS2010/mbedTLS.vcxproj new file mode 100644 index 0000000..50246ae --- /dev/null +++ b/external/mbedtls/visualc/VS2010/mbedTLS.vcxproj @@ -0,0 +1,311 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {46CF2D25-6A36-4189-B59C-E4815388E554} + Win32Proj + mbedTLS + + + + StaticLibrary + true + Unicode + + + StaticLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + StaticLibrary + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MBEDTLS_EXPORTS;%(PreprocessorDefinitions) + ../../include + CompileAsC + + + Windows + true + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MBEDTLS_EXPORTS;%(PreprocessorDefinitions) + ../../include + CompileAsC + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;MBEDTLS_EXPORTS;%(PreprocessorDefinitions) + ../../include + + + Windows + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_WINDOWS;_USRDLL;MBEDTLS_EXPORTS;%(PreprocessorDefinitions) + ../../include + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/external/mbedtls/visualc/VS2010/mini_client.vcxproj b/external/mbedtls/visualc/VS2010/mini_client.vcxproj new file mode 100644 index 0000000..fce706b --- /dev/null +++ b/external/mbedtls/visualc/VS2010/mini_client.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {C4FE29EA-266D-5295-4840-976B9B5B3843} + Win32Proj + mini_client + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/mpi_demo.vcxproj b/external/mbedtls/visualc/VS2010/mpi_demo.vcxproj new file mode 100644 index 0000000..cf5cfe8 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/mpi_demo.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {A59FAA0B-9C34-1F99-794D-A365A3AA8CCE} + Win32Proj + mpi_demo + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/pem2der.vcxproj b/external/mbedtls/visualc/VS2010/pem2der.vcxproj new file mode 100644 index 0000000..ce2f13f --- /dev/null +++ b/external/mbedtls/visualc/VS2010/pem2der.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {D3C6FBD6-D78E-7180-8345-5E09B492DBEC} + Win32Proj + pem2der + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/pk_decrypt.vcxproj b/external/mbedtls/visualc/VS2010/pk_decrypt.vcxproj new file mode 100644 index 0000000..c747401 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/pk_decrypt.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {1EC6CBA3-6187-D456-D9B7-A35399395D71} + Win32Proj + pk_decrypt + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/pk_encrypt.vcxproj b/external/mbedtls/visualc/VS2010/pk_encrypt.vcxproj new file mode 100644 index 0000000..9765c2d --- /dev/null +++ b/external/mbedtls/visualc/VS2010/pk_encrypt.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {55007179-7746-9CFB-97EC-65102FB272C8} + Win32Proj + pk_encrypt + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/pk_sign.vcxproj b/external/mbedtls/visualc/VS2010/pk_sign.vcxproj new file mode 100644 index 0000000..9e3d9a3 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/pk_sign.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {F2E8CA55-597F-7FDC-6456-D8650FB970A3} + Win32Proj + pk_sign + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/pk_verify.vcxproj b/external/mbedtls/visualc/VS2010/pk_verify.vcxproj new file mode 100644 index 0000000..aa899c2 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/pk_verify.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {C429B336-1B30-119C-3B34-21A186D6744F} + Win32Proj + pk_verify + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/query_compile_time_config.vcxproj b/external/mbedtls/visualc/VS2010/query_compile_time_config.vcxproj new file mode 100644 index 0000000..8470c1c --- /dev/null +++ b/external/mbedtls/visualc/VS2010/query_compile_time_config.vcxproj @@ -0,0 +1,174 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {D6F58AF2-9D80-562A-E2B0-F743281522B9} + Win32Proj + query_compile_time_config + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/req_app.vcxproj b/external/mbedtls/visualc/VS2010/req_app.vcxproj new file mode 100644 index 0000000..d85438a --- /dev/null +++ b/external/mbedtls/visualc/VS2010/req_app.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3} + Win32Proj + req_app + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/rsa_decrypt.vcxproj b/external/mbedtls/visualc/VS2010/rsa_decrypt.vcxproj new file mode 100644 index 0000000..b9f85cd --- /dev/null +++ b/external/mbedtls/visualc/VS2010/rsa_decrypt.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9} + Win32Proj + rsa_decrypt + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/rsa_encrypt.vcxproj b/external/mbedtls/visualc/VS2010/rsa_encrypt.vcxproj new file mode 100644 index 0000000..aeb08e8 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/rsa_encrypt.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {D06CF12E-F222-9273-41BF-B8A052FA5527} + Win32Proj + rsa_encrypt + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/rsa_genkey.vcxproj b/external/mbedtls/visualc/VS2010/rsa_genkey.vcxproj new file mode 100644 index 0000000..d68f5c0 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/rsa_genkey.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {F472475C-F677-0E7F-F127-45BF5B64F622} + Win32Proj + rsa_genkey + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/rsa_sign.vcxproj b/external/mbedtls/visualc/VS2010/rsa_sign.vcxproj new file mode 100644 index 0000000..ddf15bc --- /dev/null +++ b/external/mbedtls/visualc/VS2010/rsa_sign.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {10790F49-6887-AAB6-2D86-BCBD516F8D26} + Win32Proj + rsa_sign + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/rsa_sign_pss.vcxproj b/external/mbedtls/visualc/VS2010/rsa_sign_pss.vcxproj new file mode 100644 index 0000000..81dc4ab --- /dev/null +++ b/external/mbedtls/visualc/VS2010/rsa_sign_pss.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D} + Win32Proj + rsa_sign_pss + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/rsa_verify.vcxproj b/external/mbedtls/visualc/VS2010/rsa_verify.vcxproj new file mode 100644 index 0000000..1458f55 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/rsa_verify.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {689E28CF-89ED-BA38-3A14-78A75D891D46} + Win32Proj + rsa_verify + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/rsa_verify_pss.vcxproj b/external/mbedtls/visualc/VS2010/rsa_verify_pss.vcxproj new file mode 100644 index 0000000..59b7a92 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/rsa_verify_pss.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {95C50864-854C-2A11-4C91-BCE654E344FB} + Win32Proj + rsa_verify_pss + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/selftest.vcxproj b/external/mbedtls/visualc/VS2010/selftest.vcxproj new file mode 100644 index 0000000..5b4e985 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/selftest.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {7DBC5F77-3DA1-5F73-8421-E693D95FC66A} + Win32Proj + selftest + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/ssl_client1.vcxproj b/external/mbedtls/visualc/VS2010/ssl_client1.vcxproj new file mode 100644 index 0000000..f2f6ddc --- /dev/null +++ b/external/mbedtls/visualc/VS2010/ssl_client1.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {487A2F80-3CA3-678D-88D5-82194872CF08} + Win32Proj + ssl_client1 + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/ssl_client2.vcxproj b/external/mbedtls/visualc/VS2010/ssl_client2.vcxproj new file mode 100644 index 0000000..5abb4c3 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/ssl_client2.vcxproj @@ -0,0 +1,174 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {4E590E9D-E28F-87FF-385B-D58736388231} + Win32Proj + ssl_client2 + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/ssl_fork_server.vcxproj b/external/mbedtls/visualc/VS2010/ssl_fork_server.vcxproj new file mode 100644 index 0000000..ecf2840 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/ssl_fork_server.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {918CD402-047D-8467-E11C-E1132053F916} + Win32Proj + ssl_fork_server + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/ssl_mail_client.vcxproj b/external/mbedtls/visualc/VS2010/ssl_mail_client.vcxproj new file mode 100644 index 0000000..ee11ba2 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/ssl_mail_client.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD} + Win32Proj + ssl_mail_client + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/ssl_server.vcxproj b/external/mbedtls/visualc/VS2010/ssl_server.vcxproj new file mode 100644 index 0000000..4fab466 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/ssl_server.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {E08E0065-896A-7487-DEA5-D3B80B71F975} + Win32Proj + ssl_server + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/ssl_server2.vcxproj b/external/mbedtls/visualc/VS2010/ssl_server2.vcxproj new file mode 100644 index 0000000..168337b --- /dev/null +++ b/external/mbedtls/visualc/VS2010/ssl_server2.vcxproj @@ -0,0 +1,174 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {A4DA7463-1047-BDF5-E1B3-5632CB573F41} + Win32Proj + ssl_server2 + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/strerror.vcxproj b/external/mbedtls/visualc/VS2010/strerror.vcxproj new file mode 100644 index 0000000..74fbf86 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/strerror.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {23EF735C-CC4C-3EC4-A75E-903DB340F04A} + Win32Proj + strerror + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/udp_proxy.vcxproj b/external/mbedtls/visualc/VS2010/udp_proxy.vcxproj new file mode 100644 index 0000000..4682601 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/udp_proxy.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A} + Win32Proj + udp_proxy + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/mbedtls/visualc/VS2010/zeroize.vcxproj b/external/mbedtls/visualc/VS2010/zeroize.vcxproj new file mode 100644 index 0000000..64cdea2 --- /dev/null +++ b/external/mbedtls/visualc/VS2010/zeroize.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {10C01E94-4926-063E-9F56-C84ED190D349} + Win32Proj + zeroize + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/external/nano-pb/LICENSE.txt b/external/nano-pb/LICENSE.txt new file mode 100644 index 0000000..d11c9af --- /dev/null +++ b/external/nano-pb/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2011 Petteri Aimonen + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. diff --git a/external/nano-pb/generator/camel_case_splitter.py b/external/nano-pb/generator/camel_case_splitter.py new file mode 100644 index 0000000..4397b66 --- /dev/null +++ b/external/nano-pb/generator/camel_case_splitter.py @@ -0,0 +1,35 @@ +def split_camel_case(input): + def remove_camel_case(camel_case_input): + no_camel_case = "" + if len(camel_case_input) <= 0: + return "" + no_camel_case += camel_case_input[0].lower() + for c in camel_case_input[1:]: + if c.isupper(): + no_camel_case += "_" + c.lower() + else: + no_camel_case += c + return no_camel_case + + underscore_split = input.split("_") + retval = "" + for i in underscore_split: + if is_camel_case_name(i): + retval += remove_camel_case(i) + "_" + else: + retval += i + "_" + + return retval[:-1].replace("__", "_") + + +def is_camel_case_name(input): + if '_' in input: + return False + + if input.islower(): + return False + + if input.isupper(): + return False + + return True \ No newline at end of file diff --git a/external/nano-pb/generator/nanopb_generator.py b/external/nano-pb/generator/nanopb_generator.py new file mode 100644 index 0000000..aec5123 --- /dev/null +++ b/external/nano-pb/generator/nanopb_generator.py @@ -0,0 +1,1604 @@ +#!/usr/bin/env python + +from __future__ import unicode_literals + +'''Generate header file for nanopb from a ProtoBuf FileDescriptorSet.''' +nanopb_version = "nanopb-0.3.6-dev" + +import sys +import re +from functools import reduce + +try: + # Add some dummy imports to keep packaging tools happy. + import google, distutils.util # bbfreeze seems to need these + import pkg_resources # pyinstaller / protobuf 2.5 seem to need these +except: + # Don't care, we will error out later if it is actually important. + pass + +try: + import google.protobuf.text_format as text_format + import google.protobuf.descriptor_pb2 as descriptor +except: + sys.stderr.write(''' + ************************************************************* + *** Could not import the Google protobuf Python libraries *** + *** Try installing package 'python-protobuf' or similar. *** + ************************************************************* + ''' + '\n') + raise + +try: + import proto.nanopb_pb2 as nanopb_pb2 + import proto.plugin_pb2 as plugin_pb2 +except: + sys.stderr.write(''' + ******************************************************************** + *** Failed to import the protocol definitions for generator. *** + *** You have to run 'make' in the nanopb/generator/proto folder. *** + ******************************************************************** + ''' + '\n') + raise + +# --------------------------------------------------------------------------- +# Generation of single fields +# --------------------------------------------------------------------------- + +import time +import os.path + +# Values are tuple (c type, pb type, encoded size, int_size_allowed) +FieldD = descriptor.FieldDescriptorProto +datatypes = { + FieldD.TYPE_BOOL: ('bool', 'BOOL', 1, False), + FieldD.TYPE_DOUBLE: ('double', 'DOUBLE', 8, False), + FieldD.TYPE_FIXED32: ('uint32_t', 'FIXED32', 4, False), + FieldD.TYPE_FIXED64: ('uint64_t', 'FIXED64', 8, False), + FieldD.TYPE_FLOAT: ('float', 'FLOAT', 4, False), + FieldD.TYPE_INT32: ('int32_t', 'INT32', 10, True), + FieldD.TYPE_INT64: ('int64_t', 'INT64', 10, True), + FieldD.TYPE_SFIXED32: ('int32_t', 'SFIXED32', 4, False), + FieldD.TYPE_SFIXED64: ('int64_t', 'SFIXED64', 8, False), + FieldD.TYPE_SINT32: ('int32_t', 'SINT32', 5, True), + FieldD.TYPE_SINT64: ('int64_t', 'SINT64', 10, True), + FieldD.TYPE_UINT32: ('uint32_t', 'UINT32', 5, True), + FieldD.TYPE_UINT64: ('uint64_t', 'UINT64', 10, True) +} + +# Integer size overrides (from .proto settings) +intsizes = { + nanopb_pb2.IS_8: 'int8_t', + nanopb_pb2.IS_16: 'int16_t', + nanopb_pb2.IS_32: 'int32_t', + nanopb_pb2.IS_64: 'int64_t', +} + +# String types (for python 2 / python 3 compatibility) +try: + strtypes = (unicode, str) +except NameError: + strtypes = (str, ) + +from camel_case_splitter import split_camel_case + +class Names: + '''Keeps a set of nested names and formats them to C identifier.''' + def __init__(self, parts = ()): + if isinstance(parts, Names): + parts = parts.parts + self.parts = tuple(parts) + + def __str__(self): + name_str = '_'.join(self.parts) + return split_camel_case(name_str) + + def __add__(self, other): + if isinstance(other, strtypes): + return Names(self.parts + (other,)) + elif isinstance(other, tuple): + return Names(self.parts + other) + else: + raise ValueError("Name parts should be of type str") + + def __eq__(self, other): + return isinstance(other, Names) and self.parts == other.parts + +def names_from_type_name(type_name): + '''Parse Names() from FieldDescriptorProto type_name''' + if type_name[0] != '.': + raise NotImplementedError("Lookup of non-absolute type names is not supported") + return Names(type_name[1:].split('.')) + +def varint_max_size(max_value): + '''Returns the maximum number of bytes a varint can take when encoded.''' + if max_value < 0: + max_value = 2**64 - max_value + for i in range(1, 11): + if (max_value >> (i * 7)) == 0: + return i + raise ValueError("Value too large for varint: " + str(max_value)) + +assert varint_max_size(-1) == 10 +assert varint_max_size(0) == 1 +assert varint_max_size(127) == 1 +assert varint_max_size(128) == 2 + +class EncodedSize: + '''Class used to represent the encoded size of a field or a message. + Consists of a combination of symbolic sizes and integer sizes.''' + def __init__(self, value = 0, symbols = []): + if isinstance(value, EncodedSize): + self.value = value.value + self.symbols = value.symbols + elif isinstance(value, strtypes + (Names,)): + self.symbols = [str(value)] + self.value = 0 + else: + self.value = value + self.symbols = symbols + + def __add__(self, other): + if isinstance(other, int): + return EncodedSize(self.value + other, self.symbols) + elif isinstance(other, strtypes + (Names,)): + return EncodedSize(self.value, self.symbols + [str(other)]) + elif isinstance(other, EncodedSize): + return EncodedSize(self.value + other.value, self.symbols + other.symbols) + else: + raise ValueError("Cannot add size: " + repr(other)) + + def __mul__(self, other): + if isinstance(other, int): + return EncodedSize(self.value * other, [str(other) + '*' + s for s in self.symbols]) + else: + raise ValueError("Cannot multiply size: " + repr(other)) + + def __str__(self): + if not self.symbols: + return str(self.value) + else: + return '(' + str(self.value) + ' + ' + ' + '.join(self.symbols) + ')' + + def upperlimit(self): + if not self.symbols: + return self.value + else: + return 2**32 - 1 + +class Enum: + def __init__(self, names, desc, enum_options): + '''desc is EnumDescriptorProto''' + + self.options = enum_options + self.names = names + desc.name + self.names_t = self.names + "_t" + self.names_upper = str(self.names).upper() + + if enum_options.long_names: + self.values = [(str(self.names + x.name).upper(), x.number) for x in desc.value] + else: + self.values = [(str(names + x.name).upper(), x.number) for x in desc.value] + + self.value_longnames = [str(self.names + x.name).upper() for x in desc.value] + self.packed = enum_options.packed_enum + + def has_negative(self): + for n, v in self.values: + if v < 0: + return True + return False + + def encoded_size(self): + return max([varint_max_size(v) for n,v in self.values]) + + def __str__(self): + # result = 'typedef enum _%s {\n' % self.names_t + result = 'typedef enum\n{\n' + result += ',\n'.join([" %s = %d" % x for x in self.values]) + result += '\n}' + + if self.packed: + result += ' pb_packed' + + result += ' %s;' % self.names_t + + result += '\n#define %s_MIN %s' % (self.names_upper, self.values[0][0]) + result += '\n#define %s_MAX %s' % (self.names_upper, self.values[-1][0]) + result += '\n#define %s_ARRAYSIZE ((%s)(%s+1))' % (self.names_upper, str(self.names_t), self.values[-1][0]) + + if not self.options.long_names: + # Define the long names always so that enum value references + # from other files work properly. + for i, x in enumerate(self.values): + result += '\n#define %s %s' % (self.value_longnames[i], x[0]) + + return result + +class FieldMaxSize: + def __init__(self, worst = 0, checks = [], field_name = 'undefined'): + if isinstance(worst, list): + self.worst = max(i for i in worst if i is not None) + else: + self.worst = worst + + self.worst_field = field_name + self.checks = checks + + def extend(self, extend, field_name = None): + self.worst = max(self.worst, extend.worst) + + if self.worst == extend.worst: + self.worst_field = extend.worst_field + + self.checks.extend(extend.checks) + +class Field: + def __init__(self, struct_name, desc, field_options): + '''desc is FieldDescriptorProto''' + self.tag = desc.number + self.struct_name = struct_name + self.union_name = None + self.name = desc.name + self.default = None + self.max_size = None + self.max_count = None + self.array_decl = "" + self.enc_size = None + self.ctype = None + self.ctype_t = None + + # Parse field options + if field_options.HasField("max_size"): + self.max_size = field_options.max_size + + if field_options.HasField("max_count"): + self.max_count = field_options.max_count + + if desc.HasField('default_value'): + self.default = desc.default_value + + # Check field rules, i.e. required/optional/repeated. + can_be_static = True + if desc.label == FieldD.LABEL_REQUIRED: + self.rules = 'REQUIRED' + elif desc.label == FieldD.LABEL_OPTIONAL: + self.rules = 'OPTIONAL' + elif desc.label == FieldD.LABEL_REPEATED: + self.rules = 'REPEATED' + if self.max_count is None: + can_be_static = False + else: + self.array_decl = '[%d]' % self.max_count + else: + raise NotImplementedError(desc.label) + + # Check if the field can be implemented with static allocation + # i.e. whether the data size is known. + if desc.type == FieldD.TYPE_STRING and self.max_size is None: + can_be_static = False + + if desc.type == FieldD.TYPE_BYTES and self.max_size is None: + can_be_static = False + + # Decide how the field data will be allocated + if field_options.type == nanopb_pb2.FT_DEFAULT: + if can_be_static: + field_options.type = nanopb_pb2.FT_STATIC + else: + field_options.type = nanopb_pb2.FT_CALLBACK + + if field_options.type == nanopb_pb2.FT_STATIC and not can_be_static: + raise Exception("Field %s is defined as static, but max_size or " + "max_count is not given." % self.name) + + if field_options.type == nanopb_pb2.FT_STATIC: + self.allocation = 'STATIC' + elif field_options.type == nanopb_pb2.FT_POINTER: + self.allocation = 'POINTER' + elif field_options.type == nanopb_pb2.FT_CALLBACK: + self.allocation = 'CALLBACK' + else: + raise NotImplementedError(field_options.type) + + # Decide the C data type to use in the struct. + if desc.type in datatypes: + self.ctype, self.pbtype, self.enc_size, isa = datatypes[desc.type] + self.ctype_t = self.ctype + + # Override the field size if user wants to use smaller integers + if isa and field_options.int_size != nanopb_pb2.IS_DEFAULT: + self.ctype = intsizes[field_options.int_size] + self.ctype_t = self.ctype + if desc.type == FieldD.TYPE_UINT32 or desc.type == FieldD.TYPE_UINT64: + self.ctype = 'u' + self.ctype; + self.ctype_t = self.ctype + elif desc.type == FieldD.TYPE_ENUM: + self.pbtype = 'ENUM' + self.ctype = names_from_type_name(desc.type_name) + self.ctype_t = self.ctype + "_t" + if self.default is not None: + self.default = self.ctype + self.default + self.enc_size = None # Needs to be filled in when enum values are known + elif desc.type == FieldD.TYPE_STRING: + self.pbtype = 'STRING' + self.ctype = 'char' + self.ctype_t = self.ctype + if self.allocation == 'STATIC': + self.ctype = 'char' + self.array_decl += '[%d]' % self.max_size + self.enc_size = varint_max_size(self.max_size) + self.max_size + elif desc.type == FieldD.TYPE_BYTES: + self.pbtype = 'BYTES' + if self.allocation == 'STATIC': + self.ctype = self.struct_name + self.name + 't' + self.ctype_t = self.ctype + self.enc_size = varint_max_size(self.max_size) + self.max_size + elif self.allocation == 'POINTER': + self.ctype = 'pb_bytes_array_t' + self.ctype_t = self.ctype + elif desc.type == FieldD.TYPE_MESSAGE: + self.pbtype = 'MESSAGE' + self.ctype = self.submsgname = names_from_type_name(desc.type_name) + self.ctype_t = self.ctype + "_t" + self.enc_size = None # Needs to be filled in after the message type is available + else: + raise NotImplementedError(desc.type) + + def __lt__(self, other): + return self.tag < other.tag + + def __str__(self): + result = '' + if self.allocation == 'POINTER': + if self.rules == 'REPEATED': + result += ' pb_size_t ' + self.name + '_count;\n' + + if self.pbtype == 'MESSAGE': + # Use struct definition, so recursive submessages are possible + result += ' struct _%s *%s;' % (self.ctype_t, self.name) + elif self.rules == 'REPEATED' and self.pbtype in ['STRING', 'BYTES']: + # String/bytes arrays need to be defined as pointers to pointers + result += ' %s **%s;' % (self.ctype_t, self.name) + else: + result += ' %s *%s;' % (self.ctype_t, self.name) + elif self.allocation == 'CALLBACK': + result += ' pb_callback_t %s;' % self.name + else: + if self.rules == 'OPTIONAL' and self.allocation == 'STATIC': + result += ' bool has_' + self.name + ';\n' + elif self.rules == 'REPEATED' and self.allocation == 'STATIC': + result += ' pb_size_t ' + self.name + '_count;\n' + result += ' %s %s%s;' % (self.ctype_t, self.name, self.array_decl) + return result + + def types(self): + '''Return definitions for any special types this field might need.''' + if self.pbtype == 'BYTES' and self.allocation == 'STATIC': + result = 'typedef PB_BYTES_ARRAY_T(%d) %s;\n' % (self.max_size, self.ctype) + else: + result = '' + return result + + def get_dependencies(self): + '''Get list of type names used by this field.''' + if self.allocation == 'STATIC': + return [str(self.ctype)] + else: + return [] + + def get_initializer(self, null_init, inner_init_only = False): + '''Return literal expression for this field's default value. + null_init: If True, initialize to a 0 value instead of default from .proto + inner_init_only: If True, exclude initialization for any count/has fields + ''' + + inner_init = None + if self.pbtype == 'MESSAGE': + if null_init: + inner_init = '%s_init_zero' % self.ctype + else: + inner_init = '%s_init_default' % self.ctype + elif self.default is None or null_init: + if self.pbtype == 'STRING': + inner_init = '""' + elif self.pbtype == 'BYTES': + inner_init = '{0, {0}}' + elif self.pbtype in ('ENUM', 'UENUM'): + inner_init = '(%s)0' % self.ctype_t + else: + inner_init = '0' + else: + if self.pbtype == 'STRING': + inner_init = self.default.replace('"', '\\"') + inner_init = '"' + inner_init + '"' + elif self.pbtype == 'BYTES': + data = ['0x%02x' % ord(c) for c in self.default] + if len(data) == 0: + inner_init = '{0, {0}}' + else: + inner_init = '{%d, {%s}}' % (len(data), ','.join(data)) + elif self.pbtype in ['FIXED32', 'UINT32']: + inner_init = str(self.default) + 'u' + elif self.pbtype in ['FIXED64', 'UINT64']: + inner_init = str(self.default) + 'ull' + elif self.pbtype in ['SFIXED64', 'INT64']: + inner_init = str(self.default) + 'll' + elif self.pbtype in ('ENUM', 'UENUM'): + inner_init = str(self.default).upper() + else: + inner_init = str(self.default) + + if inner_init_only: + return inner_init + + outer_init = None + if self.allocation == 'STATIC': + if self.rules == 'REPEATED': + outer_init = '0, {' + outer_init += ', '.join([inner_init] * self.max_count) + outer_init += '}' + elif self.rules == 'OPTIONAL': + outer_init = 'false, ' + inner_init + else: + outer_init = inner_init + elif self.allocation == 'POINTER': + if self.rules == 'REPEATED': + outer_init = '0, NULL' + else: + outer_init = 'NULL' + elif self.allocation == 'CALLBACK': + if self.pbtype == 'EXTENSION': + outer_init = 'NULL' + else: + outer_init = '{{NULL}, NULL}' + + return outer_init + + def default_decl(self, declaration_only = False): + '''Return definition for this field's default value.''' + if self.default is None: + return None + + ctype = self.ctype_t + default = self.get_initializer(False, True) + array_decl = '' + + if self.pbtype == 'STRING': + if self.allocation != 'STATIC': + return None # Not implemented + array_decl = '[%d]' % self.max_size + elif self.pbtype == 'BYTES': + if self.allocation != 'STATIC': + return None # Not implemented + + if declaration_only: + return 'extern const %s %s_default%s;' % (ctype, self.struct_name + self.name, array_decl) + else: + return 'const %s %s_default%s = %s;' % (ctype, self.struct_name + self.name, array_decl, default) + + def tags(self): + '''Return the #define for the tag number of this field.''' + identifier = ('%s_%s_tag' % (self.struct_name, self.name)).upper() + return '#define %-40s %d\n' % (identifier, self.tag) + + def pb_field_t(self, prev_field_name): + '''Return the pb_field_t initializer to use in the constant array. + prev_field_name is the name of the previous field or None. + ''' + + if self.rules == 'ONEOF': + if self.anonymous: + result = ' PB_ANONYMOUS_ONEOF_FIELD(%s, ' % self.union_name + else: + result = ' PB_ONEOF_FIELD(%s, ' % self.union_name + else: + result = ' PB_FIELD(' + + result += '%3d, ' % self.tag + result += '%-8s, ' % self.pbtype + result += '%s, ' % self.rules + result += '%-8s, ' % self.allocation + result += '%s, ' % ("FIRST" if not prev_field_name else "OTHER") + result += '%s, ' % (str(self.struct_name) + "_t") + result += '%s, ' % self.name + result += '%s, ' % (prev_field_name or self.name) + + if self.pbtype == 'MESSAGE': + result += '&%s_fields)' % str(self.submsgname) + elif self.default is None: + result += '0)' + elif self.pbtype in ['BYTES', 'STRING'] and self.allocation != 'STATIC': + result += '0)' # Arbitrary size default values not implemented + elif self.rules == 'OPTEXT': + result += '0)' # Default value for extensions is not implemented + else: + result += '&%s_default)' % (self.struct_name + self.name) + + return result + + def get_last_field_name(self): + return self.name + + def largest_field_value(self): + '''Determine if this field needs 16bit or 32bit pb_field_t structure to compile properly. + Returns numeric value or a C-expression for assert.''' + check = [] + if self.pbtype == 'MESSAGE': + if self.rules == 'REPEATED' and self.allocation == 'STATIC': + check.append('pb_membersize(%s, %s[0])' % (self.struct_name+"_t", self.name)) + elif self.rules == 'ONEOF': + if self.anonymous: + check.append('pb_membersize(%s, %s)' % (self.struct_name+"_t", self.name)) + else: + check.append('pb_membersize(%s, %s.%s)' % (self.struct_name+"_t", self.union_name, self.name)) + else: + check.append('pb_membersize(%s, %s)' % (self.struct_name+"_t", self.name)) + + return FieldMaxSize([self.tag, self.max_size, self.max_count], + check, + ('%s.%s' % (self.struct_name, self.name))) + + def encoded_size(self, dependencies): + '''Return the maximum size that this field can take when encoded, + including the field tag. If the size cannot be determined, returns + None.''' + + if self.allocation != 'STATIC': + return None + + if self.pbtype == 'MESSAGE': + encsize = None + if str(self.submsgname) in dependencies: + submsg = dependencies[str(self.submsgname)] + encsize = submsg.encoded_size(dependencies) + if encsize is not None: + # Include submessage length prefix + encsize += varint_max_size(encsize.upperlimit()) + + if encsize is None: + # Submessage or its size cannot be found. + # This can occur if submessage is defined in different + # file, and it or its .options could not be found. + # Instead of direct numeric value, reference the size that + # has been #defined in the other file. + encsize = EncodedSize(self.submsgname + 'size') + + # We will have to make a conservative assumption on the length + # prefix size, though. + encsize += 5 + + elif self.pbtype in ['ENUM', 'UENUM']: + if str(self.ctype) in dependencies: + enumtype = dependencies[str(self.ctype)] + encsize = enumtype.encoded_size() + else: + # Conservative assumption + encsize = 10 + + elif self.enc_size is None: + raise RuntimeError("Could not determine encoded size for %s.%s" + % (self.struct_name, self.name)) + else: + encsize = EncodedSize(self.enc_size) + + encsize += varint_max_size(self.tag << 3) # Tag + wire type + + if self.rules == 'REPEATED': + # Decoders must be always able to handle unpacked arrays. + # Therefore we have to reserve space for it, even though + # we emit packed arrays ourselves. + encsize *= self.max_count + + return encsize + + +class ExtensionRange(Field): + def __init__(self, struct_name, range_start, field_options): + '''Implements a special pb_extension_t* field in an extensible message + structure. The range_start signifies the index at which the extensions + start. Not necessarily all tags above this are extensions, it is merely + a speed optimization. + ''' + self.tag = range_start + self.struct_name = struct_name + self.name = 'extensions' + self.pbtype = 'EXTENSION' + self.rules = 'OPTIONAL' + self.allocation = 'CALLBACK' + self.ctype = 'pb_extension_t' + self.array_decl = '' + self.default = None + self.max_size = 0 + self.max_count = 0 + + def __str__(self): + return ' pb_extension_t *extensions;' + + def types(self): + return '' + + def tags(self): + return '' + + def encoded_size(self, dependencies): + # We exclude extensions from the count, because they cannot be known + # until runtime. Other option would be to return None here, but this + # way the value remains useful if extensions are not used. + return EncodedSize(0) + +class ExtensionField(Field): + def __init__(self, struct_name, desc, field_options): + self.fullname = struct_name + desc.name + self.extendee_name = names_from_type_name(desc.extendee) + Field.__init__(self, self.fullname + 'struct', desc, field_options) + + if self.rules != 'OPTIONAL': + self.skip = True + else: + self.skip = False + self.rules = 'OPTEXT' + + def tags(self): + '''Return the #define for the tag number of this field.''' + identifier = ('%s_tag' % self.fullname).upper() + return '#define %-40s %d\n' % (identifier, self.tag) + + def extension_decl(self): + '''Declaration of the extension type in the .pb.h file''' + if self.skip: + msg = '/* Extension field %s was skipped because only "optional"\n' % self.fullname + msg +=' type of extension fields is currently supported. */\n' + return msg + + return ('extern const pb_extension_type_t %s; /* field type: %s */\n' % + (self.fullname, str(self).strip())) + + def extension_def(self): + '''Definition of the extension type in the .pb.c file''' + + if self.skip: + return '' + + result = 'typedef struct {\n' + result += str(self) + result += '\n} %s_t;\n\n' % self.struct_name + result += ('static const pb_field_t %s_field = \n %s;\n\n' % + (self.fullname, self.pb_field_t(None))) + result += 'const pb_extension_type_t %s = {\n' % self.fullname + result += ' NULL,\n' + result += ' NULL,\n' + result += ' &%s_field\n' % self.fullname + result += '};\n' + return result + + +# --------------------------------------------------------------------------- +# Generation of oneofs (unions) +# --------------------------------------------------------------------------- + +class OneOf(Field): + def __init__(self, struct_name, oneof_desc): + self.struct_name = struct_name + self.name = oneof_desc.name + self.ctype = 'union' + self.pbtype = 'oneof' + self.fields = [] + self.allocation = 'ONEOF' + self.default = None + self.rules = 'ONEOF' + self.anonymous = False + + def add_field(self, field): + if field.allocation == 'CALLBACK': + raise Exception("Callback fields inside of oneof are not supported" + + " (field %s)" % field.name) + + field.union_name = self.name + field.rules = 'ONEOF' + field.anonymous = self.anonymous + self.fields.append(field) + self.fields.sort(key = lambda f: f.tag) + + # Sort by the lowest tag number inside union + self.tag = min([f.tag for f in self.fields]) + + def __str__(self): + result = '' + if self.fields: + result += ' pb_size_t which_' + self.name + ";\n" + result += ' union {\n' + for f in self.fields: + result += ' ' + str(f).replace('\n', '\n ') + '\n' + if self.anonymous: + result += ' };' + else: + result += ' } ' + self.name + ';' + return result + + def types(self): + return ''.join([f.types() for f in self.fields]) + + def get_dependencies(self): + deps = [] + for f in self.fields: + deps += f.get_dependencies() + return deps + + def get_initializer(self, null_init): + return '0, {' + self.fields[0].get_initializer(null_init) + '}' + + def default_decl(self, declaration_only = False): + return None + + def tags(self): + return ''.join([f.tags() for f in self.fields]) + + def pb_field_t(self, prev_field_name): + result = ',\n'.join([f.pb_field_t(prev_field_name) for f in self.fields]) + return result + + def get_last_field_name(self): + if self.anonymous: + return self.fields[-1].name + else: + return self.name + '.' + self.fields[-1].name + + def largest_field_value(self): + largest = FieldMaxSize() + for f in self.fields: + largest.extend(f.largest_field_value()) + return largest + + def encoded_size(self, dependencies): + '''Returns the size of the largest oneof field.''' + largest = EncodedSize(0) + for f in self.fields: + size = EncodedSize(f.encoded_size(dependencies)) + if size.value is None: + return None + elif size.symbols: + return None # Cannot resolve maximum of symbols + elif size.value > largest.value: + largest = size + + return largest + +# --------------------------------------------------------------------------- +# Generation of messages (structures) +# --------------------------------------------------------------------------- + + +class Message: + def __init__(self, names, desc, message_options): + self.name = names + self.name_t = self.name + "_t" + self.fields = [] + self.oneofs = {} + no_unions = [] + + if message_options.msgid: + self.msgid = message_options.msgid + + if hasattr(desc, 'oneof_decl'): + for i, f in enumerate(desc.oneof_decl): + oneof_options = get_nanopb_suboptions(desc, message_options, self.name + f.name) + if oneof_options.no_unions: + no_unions.append(i) # No union, but add fields normally + elif oneof_options.type == nanopb_pb2.FT_IGNORE: + pass # No union and skip fields also + else: + oneof = OneOf(self.name, f) + if oneof_options.anonymous_oneof: + oneof.anonymous = True + self.oneofs[i] = oneof + self.fields.append(oneof) + + for f in desc.field: + field_options = get_nanopb_suboptions(f, message_options, self.name + f.name) + if field_options.type == nanopb_pb2.FT_IGNORE: + continue + + field = Field(self.name, f, field_options) + if (hasattr(f, 'oneof_index') and + f.HasField('oneof_index') and + f.oneof_index not in no_unions): + if f.oneof_index in self.oneofs: + self.oneofs[f.oneof_index].add_field(field) + else: + self.fields.append(field) + + if len(desc.extension_range) > 0: + field_options = get_nanopb_suboptions(desc, message_options, self.name + 'extensions') + range_start = min([r.start for r in desc.extension_range]) + if field_options.type != nanopb_pb2.FT_IGNORE: + self.fields.append(ExtensionRange(self.name, range_start, field_options)) + + self.packed = message_options.packed_struct + self.ordered_fields = self.fields[:] + self.ordered_fields.sort() + + def get_dependencies(self): + '''Get list of type names that this structure refers to.''' + deps = [] + for f in self.fields: + deps += f.get_dependencies() + return deps + + def __str__(self): + # result = 'typedef struct _%s {\n' % self.name_t + result = 'typedef struct {\n' + + if not self.ordered_fields: + # Empty structs are not allowed in C standard. + # Therefore add a dummy field if an empty message occurs. + result += ' char dummy_field;' + result += '\n'.join([str(f) for f in self.ordered_fields]) + result += '\n/* @@protoc_insertion_point(struct:%s) */' % self.name_t + result += '\n}' + + if self.packed: + result += ' pb_packed' + + result += ' %s;' % self.name_t + + if self.packed: + result = 'PB_PACKED_STRUCT_START\n' + result + result += '\nPB_PACKED_STRUCT_END' + + return result + + def types(self): + return ''.join([f.types() for f in self.fields]) + + def get_initializer(self, null_init): + if not self.ordered_fields: + return '{0}' + + parts = [] + for field in self.ordered_fields: + to_append = '' + for i in field.get_initializer(null_init).split(', '): + if 'init_default' in i or 'init_zero' in i: + to_append += i.upper() + else: + to_append += i + to_append += ", " + + to_append = to_append[:-2] + + parts.append(to_append) + return '{' + ', '.join(parts) + '}' + + def default_decl(self, declaration_only = False): + result = "" + for field in self.fields: + default = field.default_decl(declaration_only) + if default is not None: + result += default + '\n' + return result + + def count_required_fields(self): + '''Returns number of required fields inside this message''' + count = 0 + for f in self.fields: + if not isinstance(f, OneOf): + if f.rules == 'REQUIRED': + count += 1 + return count + + def count_all_fields(self): + count = 0 + for f in self.fields: + if isinstance(f, OneOf): + count += len(f.fields) + else: + count += 1 + return count + + def fields_declaration(self): + result = 'extern const pb_field_t %s_fields[%d];' % (self.name, self.count_all_fields() + 1) + return result + + def fields_definition(self): + result = 'const pb_field_t %s_fields[%d] = {\n' % (self.name, self.count_all_fields() + 1) + + prev = None + for field in self.ordered_fields: + result += field.pb_field_t(prev) + result += ',\n' + prev = field.get_last_field_name() + + result += ' PB_LAST_FIELD\n};' + return result + + def encoded_size(self, dependencies): + '''Return the maximum size that this message can take when encoded. + If the size cannot be determined, returns None. + ''' + size = EncodedSize(0) + for field in self.fields: + fsize = field.encoded_size(dependencies) + if fsize is None: + return None + size += fsize + + return size + + +# --------------------------------------------------------------------------- +# Processing of entire .proto files +# --------------------------------------------------------------------------- + +def iterate_messages(desc, names = Names()): + '''Recursively find all messages. For each, yield name, DescriptorProto.''' + if hasattr(desc, 'message_type'): + submsgs = desc.message_type + else: + submsgs = desc.nested_type + + for submsg in submsgs: + sub_names = names + submsg.name + yield sub_names, submsg + + for x in iterate_messages(submsg, sub_names): + yield x + +def iterate_extensions(desc, names = Names()): + '''Recursively find all extensions. + For each, yield name, FieldDescriptorProto. + ''' + for extension in desc.extension: + yield names, extension + + for subname, subdesc in iterate_messages(desc, names): + for extension in subdesc.extension: + yield subname, extension + +def toposort2(data): + '''Topological sort. + From http://code.activestate.com/recipes/577413-topological-sort/ + This function is under the MIT license. + ''' + for k, v in list(data.items()): + v.discard(k) # Ignore self dependencies + extra_items_in_deps = reduce(set.union, list(data.values()), set()) - set(data.keys()) + data.update(dict([(item, set()) for item in extra_items_in_deps])) + while True: + ordered = set(item for item,dep in list(data.items()) if not dep) + if not ordered: + break + for item in sorted(ordered): + yield item + data = dict([(item, (dep - ordered)) for item,dep in list(data.items()) + if item not in ordered]) + assert not data, "A cyclic dependency exists amongst %r" % data + +def sort_dependencies(messages): + '''Sort a list of Messages based on dependencies.''' + dependencies = {} + message_by_name = {} + for message in messages: + dependencies[str(message.name)] = set(message.get_dependencies()) + message_by_name[str(message.name)] = message + + for msgname in toposort2(dependencies): + if msgname in message_by_name: + yield message_by_name[msgname] + +def make_identifier(headername): + '''Make #ifndef identifier that contains uppercase A-Z and digits 0-9''' + result = "" + for c in headername.upper(): + if c.isalnum(): + result += c + else: + result += '_' + return result + +class ProtoFile: + def __init__(self, fdesc, file_options): + '''Takes a FileDescriptorProto and parses it.''' + self.fdesc = fdesc + self.file_options = file_options + self.dependencies = {} + self.parse() + + # Some of types used in this file probably come from the file itself. + # Thus it has implicit dependency on itself. + self.add_dependency(self) + + def parse(self): + self.enums = [] + self.messages = [] + self.extensions = [] + + if self.fdesc.package: + base_name = Names(self.fdesc.package.split('.')) + else: + base_name = Names() + + for enum in self.fdesc.enum_type: + enum_options = get_nanopb_suboptions(enum, self.file_options, base_name + enum.name) + self.enums.append(Enum(base_name, enum, enum_options)) + + for names, message in iterate_messages(self.fdesc, base_name): + message_options = get_nanopb_suboptions(message, self.file_options, names) + + if message_options.skip_message: + continue + + self.messages.append(Message(names, message, message_options)) + for enum in message.enum_type: + enum_options = get_nanopb_suboptions(enum, message_options, names + enum.name) + self.enums.append(Enum(names, enum, enum_options)) + + for names, extension in iterate_extensions(self.fdesc, base_name): + field_options = get_nanopb_suboptions(extension, self.file_options, names + extension.name) + if field_options.type != nanopb_pb2.FT_IGNORE: + self.extensions.append(ExtensionField(names, extension, field_options)) + + def add_dependency(self, other): + for enum in other.enums: + self.dependencies[str(enum.names)] = enum + + for msg in other.messages: + self.dependencies[str(msg.name)] = msg + + # Fix field default values where enum short names are used. + for enum in other.enums: + if not enum.options.long_names: + for message in self.messages: + for field in message.fields: + if field.default in enum.value_longnames: + idx = enum.value_longnames.index(field.default) + field.default = enum.values[idx][0] + + # Fix field data types where enums have negative values. + for enum in other.enums: + if not enum.has_negative(): + for message in self.messages: + for field in message.fields: + if field.pbtype == 'ENUM' and field.ctype == enum.names: + field.pbtype = 'UENUM' + + def generate_header(self, includes, headername, options): + '''Generate content for a header file. + Generates strings, which should be concatenated and stored to file. + ''' + + yield '/* Automatically generated nanopb header */\n' + if options.notimestamp: + yield '/* Generated by %s */\n\n' % (nanopb_version) + else: + yield '/* Generated by %s at %s. */\n\n' % (nanopb_version, time.asctime()) + + symbol = make_identifier(headername) + yield '#ifndef PB_%s_INCLUDED\n' % symbol + yield '#define PB_%s_INCLUDED\n' % symbol + try: + yield options.libformat % ('pb.h') + except TypeError: + # no %s specified - use whatever was passed in as options.libformat + yield options.libformat + yield '\n' + + for incfile in includes: + noext = os.path.splitext(incfile)[0] + yield options.genformat % (noext + options.extension + '.h') + yield '\n' + + yield '/* @@protoc_insertion_point(includes) */\n' + + yield '#if PB_PROTO_HEADER_VERSION != 30\n' + yield '#error Regenerate this file with the current version of nanopb generator.\n' + yield '#endif\n' + yield '\n' + + yield '#ifdef __cplusplus\n' + yield 'extern "C" {\n' + yield '#endif\n\n' + + if self.enums: + yield '/* Enum definitions */\n' + for enum in self.enums: + yield str(enum) + '\n\n' + + if self.messages: + yield '/* Struct definitions */\n' + for msg in sort_dependencies(self.messages): + yield msg.types() + yield str(msg) + '\n\n' + + if self.extensions: + yield '/* Extensions */\n' + for extension in self.extensions: + yield extension.extension_decl() + yield '\n' + + if self.messages: + yield '/* Default values for struct fields */\n' + for msg in self.messages: + yield msg.default_decl(True) + yield '\n' + + yield '/* Initializer values for message structs */\n' + for msg in self.messages: + identifier = ('%s_init_default' % msg.name).upper() + yield '#define %-40s %s\n' % (identifier, msg.get_initializer(False)) + for msg in self.messages: + identifier = ('%s_init_zero' % msg.name).upper() + yield '#define %-40s %s\n' % (identifier, msg.get_initializer(True)) + yield '\n' + + yield '/* Field tags (for use in manual encoding/decoding) */\n' + for msg in sort_dependencies(self.messages): + for field in msg.fields: + yield field.tags() + for extension in self.extensions: + yield extension.tags() + yield '\n' + + yield '/* Struct field encoding specification for nanopb */\n' + for msg in self.messages: + yield msg.fields_declaration() + '\n' + yield '\n' + + yield '/* Maximum encoded size of messages (where known) */\n' + for msg in self.messages: + msize = msg.encoded_size(self.dependencies) + identifier = ('%s_size' % msg.name).upper() + if msize is not None: + yield '#define %-40s %s\n' % (identifier, str(msize).upper()) + else: + yield '/* %s depends on runtime parameters */\n' % identifier + yield '\n' + + yield '/* Message IDs (where set with "msgid" option) */\n' + + yield '#ifdef PB_MSGID\n' + for msg in self.messages: + if hasattr(msg,'msgid'): + yield '#define PB_MSG_%d %s\n' % (msg.msgid, msg.name) + yield '\n' + + symbol = make_identifier(headername.split('.')[0]) + yield '#define %s_MESSAGES \\\n' % symbol + + for msg in self.messages: + m = "-1" + msize = msg.encoded_size(self.dependencies) + if msize is not None: + m = msize + if hasattr(msg,'msgid'): + yield '\tPB_MSG(%d,%s,%s) \\\n' % (msg.msgid, m, msg.name) + yield '\n' + + for msg in self.messages: + if hasattr(msg,'msgid'): + yield '#define %s_msgid %d\n' % (msg.name, msg.msgid) + yield '\n' + + yield '#endif\n\n' + + yield '#ifdef __cplusplus\n' + yield '} /* extern "C" */\n' + yield '#endif\n' + + # End of header + yield '/* @@protoc_insertion_point(eof) */\n' + yield '\n#endif\n' + + def generate_source(self, headername, options): + '''Generate content for a source file.''' + + yield '/* Automatically generated nanopb constant definitions */\n' + if options.notimestamp: + yield '/* Generated by %s */\n\n' % (nanopb_version) + else: + yield '/* Generated by %s at %s. */\n\n' % (nanopb_version, time.asctime()) + yield options.genformat % (headername) + yield '\n' + yield '/* @@protoc_insertion_point(includes) */\n' + + yield '#if PB_PROTO_HEADER_VERSION != 30\n' + yield '#error Regenerate this file with the current version of nanopb generator.\n' + yield '#endif\n' + yield '\n' + + for msg in self.messages: + yield msg.default_decl(False) + + yield '\n\n' + + for msg in self.messages: + yield msg.fields_definition() + '\n\n' + + for ext in self.extensions: + yield ext.extension_def() + '\n' + + # Add checks for numeric limits + if self.messages: + largest_msg = max(self.messages, key = lambda m: m.count_required_fields()) + largest_count = largest_msg.count_required_fields() + if largest_count > 64: + yield '\n/* Check that missing required fields will be properly detected */\n' + yield '#if PB_MAX_REQUIRED_FIELDS < %d\n' % largest_count + yield '#error Properly detecting missing required fields in %s requires \\\n' % largest_msg.name + yield ' setting PB_MAX_REQUIRED_FIELDS to %d or more.\n' % largest_count + yield '#endif\n' + + max_field = FieldMaxSize() + checks_msgnames = [] + for msg in self.messages: + checks_msgnames.append(msg.name) + for field in msg.fields: + max_field.extend(field.largest_field_value()) + + worst = max_field.worst + worst_field = max_field.worst_field + checks = max_field.checks + + if worst > 255 or checks: + yield '\n/* Check that field information fits in pb_field_t */\n' + + if worst > 65535 or checks: + yield '#if !defined(PB_FIELD_32BIT)\n' + if worst > 65535: + yield '#error Field descriptor for %s is too large. Define PB_FIELD_32BIT to fix this.\n' % worst_field + else: + assertion = ' && '.join(str(c) + ' < 65536' for c in checks) + msgs = '_'.join(str(n) for n in checks_msgnames) + yield '/* If you get an error here, it means that you need to define PB_FIELD_32BIT\n' + yield ' * compile-time option. You can do that in pb.h or on compiler command line.\n' + yield ' * \n' + yield ' * The reason you need to do this is that some of your messages contain tag\n' + yield ' * numbers or field sizes that are larger than what can fit in 8 or 16 bit\n' + yield ' * field descriptors.\n' + yield ' */\n' + yield 'PB_STATIC_ASSERT((%s), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_%s)\n'%(assertion,msgs) + yield '#endif\n\n' + + if worst < 65536: + yield '#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)\n' + if worst > 255: + yield '#error Field descriptor for %s is too large. Define PB_FIELD_16BIT to fix this.\n' % worst_field + else: + assertion = ' && '.join(str(c) + ' < 256' for c in checks) + msgs = '_'.join(str(n) for n in checks_msgnames) + yield '/* If you get an error here, it means that you need to define PB_FIELD_16BIT\n' + yield ' * compile-time option. You can do that in pb.h or on compiler command line.\n' + yield ' * \n' + yield ' * The reason you need to do this is that some of your messages contain tag\n' + yield ' * numbers or field sizes that are larger than what can fit in the default\n' + yield ' * 8 bit descriptors.\n' + yield ' */\n' + yield 'PB_STATIC_ASSERT((%s), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_%s)\n'%(assertion,msgs) + yield '#endif\n\n' + + # Add check for sizeof(double) + has_double = False + for msg in self.messages: + for field in msg.fields: + if field.ctype == 'double': + has_double = True + + if has_double: + yield '\n' + yield '/* On some platforms (such as AVR), double is really float.\n' + yield ' * These are not directly supported by nanopb, but see example_avr_double.\n' + yield ' * To get rid of this error, remove any double fields from your .proto.\n' + yield ' */\n' + yield 'PB_STATIC_ASSERT(sizeof(double) == 8, DOUBLE_MUST_BE_8_BYTES)\n' + + yield '\n' + yield '/* @@protoc_insertion_point(eof) */\n' + +# --------------------------------------------------------------------------- +# Options parsing for the .proto files +# --------------------------------------------------------------------------- + +from fnmatch import fnmatch + +def read_options_file(infile): + '''Parse a separate options file to list: + [(namemask, options), ...] + ''' + results = [] + data = infile.read() + data = re.sub('/\*.*?\*/', '', data, flags = re.MULTILINE) + data = re.sub('//.*?$', '', data, flags = re.MULTILINE) + data = re.sub('#.*?$', '', data, flags = re.MULTILINE) + for i, line in enumerate(data.split('\n')): + line = line.strip() + if not line: + continue + + parts = line.split(None, 1) + + if len(parts) < 2: + sys.stderr.write("%s:%d: " % (infile.name, i + 1) + + "Option lines should have space between field name and options. " + + "Skipping line: '%s'\n" % line) + continue + + opts = nanopb_pb2.NanoPBOptions() + + try: + text_format.Merge(parts[1], opts) + except Exception as e: + sys.stderr.write("%s:%d: " % (infile.name, i + 1) + + "Unparseable option line: '%s'. " % line + + "Error: %s\n" % str(e)) + continue + results.append((parts[0], opts)) + + return results + +class Globals: + '''Ugly global variables, should find a good way to pass these.''' + verbose_options = False + separate_options = [] + matched_namemasks = set() + +def get_nanopb_suboptions(subdesc, options, name): + '''Get copy of options, and merge information from subdesc.''' + new_options = nanopb_pb2.NanoPBOptions() + new_options.CopyFrom(options) + + # Handle options defined in a separate file + dotname = '.'.join(name.parts) + for namemask, options in Globals.separate_options: + if fnmatch(dotname, namemask): + Globals.matched_namemasks.add(namemask) + new_options.MergeFrom(options) + + # Handle options defined in .proto + if isinstance(subdesc.options, descriptor.FieldOptions): + ext_type = nanopb_pb2.nanopb + elif isinstance(subdesc.options, descriptor.FileOptions): + ext_type = nanopb_pb2.nanopb_fileopt + elif isinstance(subdesc.options, descriptor.MessageOptions): + ext_type = nanopb_pb2.nanopb_msgopt + elif isinstance(subdesc.options, descriptor.EnumOptions): + ext_type = nanopb_pb2.nanopb_enumopt + else: + raise Exception("Unknown options type") + + if subdesc.options.HasExtension(ext_type): + ext = subdesc.options.Extensions[ext_type] + new_options.MergeFrom(ext) + + if Globals.verbose_options: + sys.stderr.write("Options for " + dotname + ": ") + sys.stderr.write(text_format.MessageToString(new_options) + "\n") + + return new_options + + +# --------------------------------------------------------------------------- +# Command line interface +# --------------------------------------------------------------------------- + +import sys +import os.path +from optparse import OptionParser + +optparser = OptionParser( + usage = "Usage: nanopb_generator.py [options] file.pb ...", + epilog = "Compile file.pb from file.proto by: 'protoc -ofile.pb file.proto'. " + + "Output will be written to file.pb.h and file.pb.c.") +optparser.add_option("-x", dest="exclude", metavar="FILE", action="append", default=[], + help="Exclude file from generated #include list.") +optparser.add_option("-e", "--extension", dest="extension", metavar="EXTENSION", default=".pb", + help="Set extension to use instead of '.pb' for generated files. [default: %default]") +optparser.add_option("-f", "--options-file", dest="options_file", metavar="FILE", default="%s.options", + help="Set name of a separate generator options file.") +optparser.add_option("-I", "--options-path", dest="options_path", metavar="DIR", + action="append", default = [], + help="Search for .options files additionally in this path") +optparser.add_option("-D", "--output-dir", dest="output_dir", + metavar="OUTPUTDIR", default=None, + help="Output directory of .pb.h and .pb.c files") +optparser.add_option("-Q", "--generated-include-format", dest="genformat", + metavar="FORMAT", default='#include "%s"\n', + help="Set format string to use for including other .pb.h files. [default: %default]") +optparser.add_option("-L", "--library-include-format", dest="libformat", + metavar="FORMAT", default='#include <%s>\n', + help="Set format string to use for including the nanopb pb.h header. [default: %default]") +optparser.add_option("-T", "--no-timestamp", dest="notimestamp", action="store_true", default=False, + help="Don't add timestamp to .pb.h and .pb.c preambles") +optparser.add_option("-q", "--quiet", dest="quiet", action="store_true", default=False, + help="Don't print anything except errors.") +optparser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False, + help="Print more information.") +optparser.add_option("-s", dest="settings", metavar="OPTION:VALUE", action="append", default=[], + help="Set generator option (max_size, max_count etc.).") + +def parse_file(filename, fdesc, options): + '''Parse a single file. Returns a ProtoFile instance.''' + toplevel_options = nanopb_pb2.NanoPBOptions() + for s in options.settings: + text_format.Merge(s, toplevel_options) + + if not fdesc: + data = open(filename, 'rb').read() + fdesc = descriptor.FileDescriptorSet.FromString(data).file[0] + + # Check if there is a separate .options file + had_abspath = False + try: + optfilename = options.options_file % os.path.splitext(filename)[0] + except TypeError: + # No %s specified, use the filename as-is + optfilename = options.options_file + had_abspath = True + + paths = ['.'] + options.options_path + for p in paths: + if os.path.isfile(os.path.join(p, optfilename)): + optfilename = os.path.join(p, optfilename) + if options.verbose: + sys.stderr.write('Reading options from ' + optfilename + '\n') + Globals.separate_options = read_options_file(open(optfilename, "rU")) + break + else: + # If we are given a full filename and it does not exist, give an error. + # However, don't give error when we automatically look for .options file + # with the same name as .proto. + if options.verbose or had_abspath: + sys.stderr.write('Options file not found: ' + optfilename + '\n') + Globals.separate_options = [] + + Globals.matched_namemasks = set() + + # Parse the file + file_options = get_nanopb_suboptions(fdesc, toplevel_options, Names([filename])) + f = ProtoFile(fdesc, file_options) + f.optfilename = optfilename + + return f + +def process_file(filename, fdesc, options, other_files = {}): + '''Process a single file. + filename: The full path to the .proto or .pb source file, as string. + fdesc: The loaded FileDescriptorSet, or None to read from the input file. + options: Command line options as they come from OptionsParser. + + Returns a dict: + {'headername': Name of header file, + 'headerdata': Data for the .h header file, + 'sourcename': Name of the source code file, + 'sourcedata': Data for the .c source code file + } + ''' + f = parse_file(filename, fdesc, options) + + # Provide dependencies if available + for dep in f.fdesc.dependency: + if dep in other_files: + f.add_dependency(other_files[dep]) + + # Decide the file names + noext = os.path.splitext(filename)[0] + headername = noext + options.extension + '.h' + sourcename = noext + options.extension + '.c' + headerbasename = os.path.basename(headername) + + # List of .proto files that should not be included in the C header file + # even if they are mentioned in the source .proto. + excludes = ['nanopb.proto', 'google/protobuf/descriptor.proto'] + options.exclude + includes = [d for d in f.fdesc.dependency if d not in excludes] + + headerdata = ''.join(f.generate_header(includes, headerbasename, options)) + sourcedata = ''.join(f.generate_source(headerbasename, options)) + + # Check if there were any lines in .options that did not match a member + unmatched = [n for n,o in Globals.separate_options if n not in Globals.matched_namemasks] + if unmatched and not options.quiet: + sys.stderr.write("Following patterns in " + f.optfilename + " did not match any fields: " + + ', '.join(unmatched) + "\n") + if not Globals.verbose_options: + sys.stderr.write("Use protoc --nanopb-out=-v:. to see a list of the field names.\n") + + return {'headername': headername, 'headerdata': headerdata, + 'sourcename': sourcename, 'sourcedata': sourcedata} + +def main_cli(): + '''Main function when invoked directly from the command line.''' + + options, filenames = optparser.parse_args() + + if not filenames: + optparser.print_help() + sys.exit(1) + + if options.quiet: + options.verbose = False + + if options.output_dir and not os.path.exists(options.output_dir): + optparser.print_help() + sys.stderr.write("\noutput_dir does not exist: %s\n" % options.output_dir) + sys.exit(1) + + + Globals.verbose_options = options.verbose + for filename in filenames: + results = process_file(filename, None, options) + + base_dir = options.output_dir or '' + to_write = [ + (os.path.join(base_dir, results['headername']), results['headerdata']), + (os.path.join(base_dir, results['sourcename']), results['sourcedata']), + ] + + if not options.quiet: + paths = " and ".join([x[0] for x in to_write]) + sys.stderr.write("Writing to %s\n" % paths) + + for path, data in to_write: + with open(path, 'w') as f: + f.write(data) + +def main_plugin(): + '''Main function when invoked as a protoc plugin.''' + + import io, sys + if sys.platform == "win32": + import os, msvcrt + # Set stdin and stdout to binary mode + msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) + msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) + + data = io.open(sys.stdin.fileno(), "rb").read() + + request = plugin_pb2.CodeGeneratorRequest.FromString(data) + + try: + # Versions of Python prior to 2.7.3 do not support unicode + # input to shlex.split(). Try to convert to str if possible. + params = str(request.parameter) + except UnicodeEncodeError: + params = request.parameter + + import shlex + args = shlex.split(params) + options, dummy = optparser.parse_args(args) + + Globals.verbose_options = options.verbose + + response = plugin_pb2.CodeGeneratorResponse() + + # Google's protoc does not currently indicate the full path of proto files. + # Instead always add the main file path to the search dirs, that works for + # the common case. + import os.path + options.options_path.append(os.path.dirname(request.file_to_generate[0])) + + # Process any include files first, in order to have them + # available as dependencies + other_files = {} + for fdesc in request.proto_file: + other_files[fdesc.name] = parse_file(fdesc.name, fdesc, options) + + for filename in request.file_to_generate: + for fdesc in request.proto_file: + if fdesc.name == filename: + results = process_file(filename, fdesc, options, other_files) + + f = response.file.add() + f.name = results['headername'] + f.content = results['headerdata'] + + f = response.file.add() + f.name = results['sourcename'] + f.content = results['sourcedata'] + + io.open(sys.stdout.fileno(), "wb").write(response.SerializeToString()) + +if __name__ == '__main__': + # Check if we are running as a plugin under protoc + if 'protoc-gen-' in sys.argv[0] or '--protoc-plugin' in sys.argv: + main_plugin() + else: + main_cli() diff --git a/external/nano-pb/generator/proto/Makefile b/external/nano-pb/generator/proto/Makefile new file mode 100644 index 0000000..89bfe52 --- /dev/null +++ b/external/nano-pb/generator/proto/Makefile @@ -0,0 +1,4 @@ +all: nanopb_pb2.py plugin_pb2.py + +%_pb2.py: %.proto + protoc --python_out=. $< diff --git a/external/nano-pb/generator/proto/__init__.py b/external/nano-pb/generator/proto/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/external/nano-pb/generator/proto/google/protobuf/descriptor.proto b/external/nano-pb/generator/proto/google/protobuf/descriptor.proto new file mode 100644 index 0000000..e17c0cc --- /dev/null +++ b/external/nano-pb/generator/proto/google/protobuf/descriptor.proto @@ -0,0 +1,714 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + +syntax = "proto2"; + +package google.protobuf; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + // Indexes of the public imported files in the dependency list above. + repeated int32 public_dependency = 10; + // Indexes of the weak imported files in the dependency list. + // For Google-internal migration only. Do not use. + repeated int32 weak_dependency = 11; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field without harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; + + // The syntax of the proto file. + // The supported values are "proto2" and "proto3". + optional string syntax = 12; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + } + repeated ExtensionRange extension_range = 5; + + repeated OneofDescriptorProto oneof_decl = 8; + + optional MessageOptions options = 7; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + // negative values are likely. + TYPE_INT64 = 3; + TYPE_UINT64 = 4; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + // negative values are likely. + TYPE_INT32 = 5; + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + TYPE_GROUP = 10; // Tag-delimited aggregate. + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + }; + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + // TODO(sanjay): Should we add LABEL_MAP? + }; + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + // If set, gives the index of a oneof in the containing type's oneof_decl + // list. This field is a member of that oneof. Extensions of a oneof should + // not set this since the oneof to which they belong will be inferred based + // on the extension range containing the extension's field number. + optional int32 oneof_index = 9; + + optional FieldOptions options = 8; +} + +// Describes a oneof. +message OneofDescriptorProto { + optional string name = 1; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; + + // Identifies if client streams multiple client messages + optional bool client_streaming = 5 [default=false]; + // Identifies if server streams multiple server messages + optional bool server_streaming = 6 [default=false]; +} + + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail protobuf-global-extension-registry@google.com +// to reserve extension numbers. Simply provide your project name (e.g. +// Object-C plugin) and your porject website (if available) -- there's no need +// to explain how you intend to use them. Usually you only need one extension +// number. You can declare multiple options with only one extension number by +// putting them in a sub-message. See the Custom Options section of the docs +// for examples: +// https://developers.google.com/protocol-buffers/docs/proto#options +// If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default=false]; + + // If set true, then the Java code generator will generate equals() and + // hashCode() methods for all messages defined in the .proto file. + // - In the full runtime, this is purely a speed optimization, as the + // AbstractMessage base class includes reflection-based implementations of + // these methods. + //- In the lite runtime, setting this option changes the semantics of + // equals() and hashCode() to more closely match those of the full runtime; + // the generated methods compute their results based on field values rather + // than object identity. (Implementations should not assume that hashcodes + // will be consistent across runtimes or versions of the protocol compiler.) + optional bool java_generate_equals_and_hash = 20 [default=false]; + + // If set true, then the Java2 code generator will generate code that + // throws an exception whenever an attempt is made to assign a non-UTF-8 + // byte sequence to a string field. + // Message reflection will do the same. + // However, an extension field still accepts non-UTF-8 byte sequences. + // This option has no effect on when used with the lite runtime. + optional bool java_string_check_utf8 = 27 [default=false]; + + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default=SPEED]; + + // Sets the Go package where structs generated from this .proto will be + // placed. If omitted, the Go package will be derived from the following: + // - The basename of the package import path, if provided. + // - Otherwise, the package statement in the .proto file, if present. + // - Otherwise, the basename of the .proto file, without extension. + optional string go_package = 11; + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of google.protobuf. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + + // Is this file deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for everything in the file, or it will be completely ignored; in the very + // least, this is a formalization for deprecating files. + optional bool deprecated = 23 [default=false]; + + + // Enables the use of arenas for the proto messages in this file. This applies + // only to generated classes for C++. + optional bool cc_enable_arenas = 31 [default=false]; + + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default=false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + optional bool deprecated = 3 [default=false]; + + // Whether the message is an automatically generated map entry type for the + // maps field. + // + // For maps fields: + // map map_field = 1; + // The parsed descriptor looks like: + // message MapFieldEntry { + // option map_entry = true; + // optional KeyType key = 1; + // optional ValueType value = 2; + // } + // repeated MapFieldEntry map_field = 1; + // + // Implementations may choose not to generate the map_entry=true message, but + // use a native map in the target language to hold the keys and values. + // The reflection APIs in such implementions still need to work as + // if the field is a repeated message field. + // + // NOTE: Do not set the option in .proto files. Always use the maps syntax + // instead. The option should only be implicitly set by the proto compiler + // parser. + optional bool map_entry = 7; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. + optional bool packed = 2; + + + + // Should this field be parsed lazily? Lazy applies only to message-type + // fields. It means that when the outer message is initially parsed, the + // inner message's contents will not be parsed but instead stored in encoded + // form. The inner message will actually be parsed when it is first accessed. + // + // This is only a hint. Implementations are free to choose whether to use + // eager or lazy parsing regardless of the value of this option. However, + // setting this option true suggests that the protocol author believes that + // using lazy parsing on this field is worth the additional bookkeeping + // overhead typically needed to implement it. + // + // This option does not affect the public interface of any generated code; + // all method signatures remain the same. Furthermore, thread-safety of the + // interface is not affected by this option; const methods remain safe to + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // + // + // Note that implementations may choose not to check required fields within + // a lazy sub-message. That is, calling IsInitialized() on the outher message + // may return true even if the inner message has missing required fields. + // This is necessary because otherwise the inner message would have to be + // parsed in order to perform the check, defeating the purpose of lazy + // parsing. An implementation which chooses not to check required fields + // must be consistent about it. That is, for any particular sub-message, the + // implementation must either *always* check its required fields, or *never* + // check its required fields, regardless of whether or not the message has + // been parsed. + optional bool lazy = 5 [default=false]; + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default=false]; + + // For Google-internal migration only. Do not use. + optional bool weak = 10 [default=false]; + + + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // Set this option to true to allow mapping different tag names to the same + // value. + optional bool allow_alias = 2; + + // Is this enum deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum, or it will be completely ignored; in the very least, this + // is a formalization for deprecating enums. + optional bool deprecated = 3 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // Is this enum value deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum value, or it will be completely ignored; in the very least, + // this is a formalization for deprecating enum values. + optional bool deprecated = 1 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this service deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the service, or it will be completely ignored; in the very least, + // this is a formalization for deprecating services. + optional bool deprecated = 33 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this method deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the method, or it will be completely ignored; in the very least, + // this is a formalization for deprecating methods. + optional bool deprecated = 33 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // If this SourceCodeInfo represents a complete declaration, these are any + // comments appearing before and after the declaration which appear to be + // attached to the declaration. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // Only the comment content is provided; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk + // will be stripped from the beginning of each line other than the first. + // Newlines are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to qux. + // // + // // Another line attached to qux. + // optional double qux = 4; + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + optional string leading_comments = 3; + optional string trailing_comments = 4; + } +} diff --git a/external/nano-pb/generator/proto/nanopb.proto b/external/nano-pb/generator/proto/nanopb.proto new file mode 100644 index 0000000..9b2f0fb --- /dev/null +++ b/external/nano-pb/generator/proto/nanopb.proto @@ -0,0 +1,97 @@ +// Custom options for defining: +// - Maximum size of string/bytes +// - Maximum number of elements in array +// +// These are used by nanopb to generate statically allocable structures +// for memory-limited environments. + +syntax = "proto2"; +import "google/protobuf/descriptor.proto"; + +option java_package = "fi.kapsi.koti.jpa.nanopb"; + +enum FieldType { + FT_DEFAULT = 0; // Automatically decide field type, generate static field if possible. + FT_CALLBACK = 1; // Always generate a callback field. + FT_POINTER = 4; // Always generate a dynamically allocated field. + FT_STATIC = 2; // Generate a static field or raise an exception if not possible. + FT_IGNORE = 3; // Ignore the field completely. +} + +enum IntSize { + IS_DEFAULT = 0; // Default, 32/64bit based on type in .proto + IS_8 = 8; + IS_16 = 16; + IS_32 = 32; + IS_64 = 64; +} + +// This is the inner options message, which basically defines options for +// a field. When it is used in message or file scope, it applies to all +// fields. +message NanoPBOptions { + // Allocated size for 'bytes' and 'string' fields. + optional int32 max_size = 1; + + // Allocated number of entries in arrays ('repeated' fields) + optional int32 max_count = 2; + + // Size of integer fields. Can save some memory if you don't need + // full 32 bits for the value. + optional IntSize int_size = 7 [default = IS_DEFAULT]; + + // Force type of field (callback or static allocation) + optional FieldType type = 3 [default = FT_DEFAULT]; + + // Use long names for enums, i.e. EnumName_EnumValue. + optional bool long_names = 4 [default = true]; + + // Add 'packed' attribute to generated structs. + // Note: this cannot be used on CPUs that break on unaligned + // accesses to variables. + optional bool packed_struct = 5 [default = false]; + + // Add 'packed' attribute to generated enums. + optional bool packed_enum = 10 [default = false]; + + // Skip this message + optional bool skip_message = 6 [default = false]; + + // Generate oneof fields as normal optional fields instead of union. + optional bool no_unions = 8 [default = false]; + + // integer type tag for a message + optional uint32 msgid = 9; + + // decode oneof as anonymous union + optional bool anonymous_oneof = 11 [default = false]; +} + +// Extensions to protoc 'Descriptor' type in order to define options +// inside a .proto file. +// +// Protocol Buffers extension number registry +// -------------------------------- +// Project: Nanopb +// Contact: Petteri Aimonen +// Web site: http://kapsi.fi/~jpa/nanopb +// Extensions: 1010 (all types) +// -------------------------------- + +extend google.protobuf.FileOptions { + optional NanoPBOptions nanopb_fileopt = 1010; +} + +extend google.protobuf.MessageOptions { + optional NanoPBOptions nanopb_msgopt = 1010; +} + +extend google.protobuf.EnumOptions { + optional NanoPBOptions nanopb_enumopt = 1010; +} + +extend google.protobuf.FieldOptions { + optional NanoPBOptions nanopb = 1010; +} + + diff --git a/external/nano-pb/generator/proto/nanopb_pb2.py b/external/nano-pb/generator/proto/nanopb_pb2.py new file mode 100644 index 0000000..b386775 --- /dev/null +++ b/external/nano-pb/generator/proto/nanopb_pb2.py @@ -0,0 +1,270 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: nanopb.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import google.protobuf.descriptor_pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='nanopb.proto', + package='', + serialized_pb=_b('\n\x0cnanopb.proto\x1a google/protobuf/descriptor.proto\"\xbc\x02\n\rNanoPBOptions\x12\x10\n\x08max_size\x18\x01 \x01(\x05\x12\x11\n\tmax_count\x18\x02 \x01(\x05\x12&\n\x08int_size\x18\x07 \x01(\x0e\x32\x08.IntSize:\nIS_DEFAULT\x12$\n\x04type\x18\x03 \x01(\x0e\x32\n.FieldType:\nFT_DEFAULT\x12\x18\n\nlong_names\x18\x04 \x01(\x08:\x04true\x12\x1c\n\rpacked_struct\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0bpacked_enum\x18\n \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0cskip_message\x18\x06 \x01(\x08:\x05\x66\x61lse\x12\x18\n\tno_unions\x18\x08 \x01(\x08:\x05\x66\x61lse\x12\r\n\x05msgid\x18\t \x01(\r\x12\x1e\n\x0f\x61nonymous_oneof\x18\x0b \x01(\x08:\x05\x66\x61lse*Z\n\tFieldType\x12\x0e\n\nFT_DEFAULT\x10\x00\x12\x0f\n\x0b\x46T_CALLBACK\x10\x01\x12\x0e\n\nFT_POINTER\x10\x04\x12\r\n\tFT_STATIC\x10\x02\x12\r\n\tFT_IGNORE\x10\x03*D\n\x07IntSize\x12\x0e\n\nIS_DEFAULT\x10\x00\x12\x08\n\x04IS_8\x10\x08\x12\t\n\x05IS_16\x10\x10\x12\t\n\x05IS_32\x10 \x12\t\n\x05IS_64\x10@:E\n\x0enanopb_fileopt\x12\x1c.google.protobuf.FileOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:G\n\rnanopb_msgopt\x12\x1f.google.protobuf.MessageOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:E\n\x0enanopb_enumopt\x12\x1c.google.protobuf.EnumOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:>\n\x06nanopb\x12\x1d.google.protobuf.FieldOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptionsB\x1a\n\x18\x66i.kapsi.koti.jpa.nanopb') + , + dependencies=[google.protobuf.descriptor_pb2.DESCRIPTOR,]) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +_FIELDTYPE = _descriptor.EnumDescriptor( + name='FieldType', + full_name='FieldType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FT_DEFAULT', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FT_CALLBACK', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FT_POINTER', index=2, number=4, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FT_STATIC', index=3, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FT_IGNORE', index=4, number=3, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=369, + serialized_end=459, +) +_sym_db.RegisterEnumDescriptor(_FIELDTYPE) + +FieldType = enum_type_wrapper.EnumTypeWrapper(_FIELDTYPE) +_INTSIZE = _descriptor.EnumDescriptor( + name='IntSize', + full_name='IntSize', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='IS_DEFAULT', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IS_8', index=1, number=8, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IS_16', index=2, number=16, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IS_32', index=3, number=32, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IS_64', index=4, number=64, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=461, + serialized_end=529, +) +_sym_db.RegisterEnumDescriptor(_INTSIZE) + +IntSize = enum_type_wrapper.EnumTypeWrapper(_INTSIZE) +FT_DEFAULT = 0 +FT_CALLBACK = 1 +FT_POINTER = 4 +FT_STATIC = 2 +FT_IGNORE = 3 +IS_DEFAULT = 0 +IS_8 = 8 +IS_16 = 16 +IS_32 = 32 +IS_64 = 64 + +NANOPB_FILEOPT_FIELD_NUMBER = 1010 +nanopb_fileopt = _descriptor.FieldDescriptor( + name='nanopb_fileopt', full_name='nanopb_fileopt', index=0, + number=1010, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + options=None) +NANOPB_MSGOPT_FIELD_NUMBER = 1010 +nanopb_msgopt = _descriptor.FieldDescriptor( + name='nanopb_msgopt', full_name='nanopb_msgopt', index=1, + number=1010, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + options=None) +NANOPB_ENUMOPT_FIELD_NUMBER = 1010 +nanopb_enumopt = _descriptor.FieldDescriptor( + name='nanopb_enumopt', full_name='nanopb_enumopt', index=2, + number=1010, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + options=None) +NANOPB_FIELD_NUMBER = 1010 +nanopb = _descriptor.FieldDescriptor( + name='nanopb', full_name='nanopb', index=3, + number=1010, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + options=None) + + +_NANOPBOPTIONS = _descriptor.Descriptor( + name='NanoPBOptions', + full_name='NanoPBOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='max_size', full_name='NanoPBOptions.max_size', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='max_count', full_name='NanoPBOptions.max_count', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='int_size', full_name='NanoPBOptions.int_size', index=2, + number=7, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='type', full_name='NanoPBOptions.type', index=3, + number=3, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='long_names', full_name='NanoPBOptions.long_names', index=4, + number=4, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=True, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='packed_struct', full_name='NanoPBOptions.packed_struct', index=5, + number=5, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='packed_enum', full_name='NanoPBOptions.packed_enum', index=6, + number=10, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='skip_message', full_name='NanoPBOptions.skip_message', index=7, + number=6, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='no_unions', full_name='NanoPBOptions.no_unions', index=8, + number=8, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='msgid', full_name='NanoPBOptions.msgid', index=9, + number=9, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='anonymous_oneof', full_name='NanoPBOptions.anonymous_oneof', index=10, + number=11, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + extension_ranges=[], + oneofs=[ + ], + serialized_start=51, + serialized_end=367, +) + +_NANOPBOPTIONS.fields_by_name['int_size'].enum_type = _INTSIZE +_NANOPBOPTIONS.fields_by_name['type'].enum_type = _FIELDTYPE +DESCRIPTOR.message_types_by_name['NanoPBOptions'] = _NANOPBOPTIONS +DESCRIPTOR.enum_types_by_name['FieldType'] = _FIELDTYPE +DESCRIPTOR.enum_types_by_name['IntSize'] = _INTSIZE +DESCRIPTOR.extensions_by_name['nanopb_fileopt'] = nanopb_fileopt +DESCRIPTOR.extensions_by_name['nanopb_msgopt'] = nanopb_msgopt +DESCRIPTOR.extensions_by_name['nanopb_enumopt'] = nanopb_enumopt +DESCRIPTOR.extensions_by_name['nanopb'] = nanopb + +NanoPBOptions = _reflection.GeneratedProtocolMessageType('NanoPBOptions', (_message.Message,), dict( + DESCRIPTOR = _NANOPBOPTIONS, + __module__ = 'nanopb_pb2' + # @@protoc_insertion_point(class_scope:NanoPBOptions) + )) +_sym_db.RegisterMessage(NanoPBOptions) + +nanopb_fileopt.message_type = _NANOPBOPTIONS +google.protobuf.descriptor_pb2.FileOptions.RegisterExtension(nanopb_fileopt) +nanopb_msgopt.message_type = _NANOPBOPTIONS +google.protobuf.descriptor_pb2.MessageOptions.RegisterExtension(nanopb_msgopt) +nanopb_enumopt.message_type = _NANOPBOPTIONS +google.protobuf.descriptor_pb2.EnumOptions.RegisterExtension(nanopb_enumopt) +nanopb.message_type = _NANOPBOPTIONS +google.protobuf.descriptor_pb2.FieldOptions.RegisterExtension(nanopb) + +DESCRIPTOR.has_options = True +DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\030fi.kapsi.koti.jpa.nanopb')) +# @@protoc_insertion_point(module_scope) diff --git a/external/nano-pb/generator/proto/plugin.proto b/external/nano-pb/generator/proto/plugin.proto new file mode 100644 index 0000000..e627289 --- /dev/null +++ b/external/nano-pb/generator/proto/plugin.proto @@ -0,0 +1,148 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// +// WARNING: The plugin interface is currently EXPERIMENTAL and is subject to +// change. +// +// protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is +// just a program that reads a CodeGeneratorRequest from stdin and writes a +// CodeGeneratorResponse to stdout. +// +// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead +// of dealing with the raw protocol defined here. +// +// A plugin executable needs only to be placed somewhere in the path. The +// plugin should be named "protoc-gen-$NAME", and will then be used when the +// flag "--${NAME}_out" is passed to protoc. + +syntax = "proto2"; +package google.protobuf.compiler; +option java_package = "com.google.protobuf.compiler"; +option java_outer_classname = "PluginProtos"; + +import "google/protobuf/descriptor.proto"; + +// An encoded CodeGeneratorRequest is written to the plugin's stdin. +message CodeGeneratorRequest { + // The .proto files that were explicitly listed on the command-line. The + // code generator should generate code only for these files. Each file's + // descriptor will be included in proto_file, below. + repeated string file_to_generate = 1; + + // The generator parameter passed on the command-line. + optional string parameter = 2; + + // FileDescriptorProtos for all files in files_to_generate and everything + // they import. The files will appear in topological order, so each file + // appears before any file that imports it. + // + // protoc guarantees that all proto_files will be written after + // the fields above, even though this is not technically guaranteed by the + // protobuf wire format. This theoretically could allow a plugin to stream + // in the FileDescriptorProtos and handle them one by one rather than read + // the entire set into memory at once. However, as of this writing, this + // is not similarly optimized on protoc's end -- it will store all fields in + // memory at once before sending them to the plugin. + repeated FileDescriptorProto proto_file = 15; +} + +// The plugin writes an encoded CodeGeneratorResponse to stdout. +message CodeGeneratorResponse { + // Error message. If non-empty, code generation failed. The plugin process + // should exit with status code zero even if it reports an error in this way. + // + // This should be used to indicate errors in .proto files which prevent the + // code generator from generating correct code. Errors which indicate a + // problem in protoc itself -- such as the input CodeGeneratorRequest being + // unparseable -- should be reported by writing a message to stderr and + // exiting with a non-zero status code. + optional string error = 1; + + // Represents a single generated file. + message File { + // The file name, relative to the output directory. The name must not + // contain "." or ".." components and must be relative, not be absolute (so, + // the file cannot lie outside the output directory). "/" must be used as + // the path separator, not "\". + // + // If the name is omitted, the content will be appended to the previous + // file. This allows the generator to break large files into small chunks, + // and allows the generated text to be streamed back to protoc so that large + // files need not reside completely in memory at one time. Note that as of + // this writing protoc does not optimize for this -- it will read the entire + // CodeGeneratorResponse before writing files to disk. + optional string name = 1; + + // If non-empty, indicates that the named file should already exist, and the + // content here is to be inserted into that file at a defined insertion + // point. This feature allows a code generator to extend the output + // produced by another code generator. The original generator may provide + // insertion points by placing special annotations in the file that look + // like: + // @@protoc_insertion_point(NAME) + // The annotation can have arbitrary text before and after it on the line, + // which allows it to be placed in a comment. NAME should be replaced with + // an identifier naming the point -- this is what other generators will use + // as the insertion_point. Code inserted at this point will be placed + // immediately above the line containing the insertion point (thus multiple + // insertions to the same point will come out in the order they were added). + // The double-@ is intended to make it unlikely that the generated code + // could contain things that look like insertion points by accident. + // + // For example, the C++ code generator places the following line in the + // .pb.h files that it generates: + // // @@protoc_insertion_point(namespace_scope) + // This line appears within the scope of the file's package namespace, but + // outside of any particular class. Another plugin can then specify the + // insertion_point "namespace_scope" to generate additional classes or + // other declarations that should be placed in this scope. + // + // Note that if the line containing the insertion point begins with + // whitespace, the same whitespace will be added to every line of the + // inserted text. This is useful for languages like Python, where + // indentation matters. In these languages, the insertion point comment + // should be indented the same amount as any inserted code will need to be + // in order to work correctly in that context. + // + // The code generator that generates the initial file and the one which + // inserts into it must both run as part of a single invocation of protoc. + // Code generators are executed in the order in which they appear on the + // command line. + // + // If |insertion_point| is present, |name| must also be present. + optional string insertion_point = 2; + + // The file contents. + optional string content = 15; + } + repeated File file = 15; +} diff --git a/external/nano-pb/generator/proto/plugin_pb2.py b/external/nano-pb/generator/proto/plugin_pb2.py new file mode 100644 index 0000000..481d0d7 --- /dev/null +++ b/external/nano-pb/generator/proto/plugin_pb2.py @@ -0,0 +1,184 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: plugin.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import google.protobuf.descriptor_pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='plugin.proto', + package='google.protobuf.compiler', + serialized_pb=_b('\n\x0cplugin.proto\x12\x18google.protobuf.compiler\x1a google/protobuf/descriptor.proto\"}\n\x14\x43odeGeneratorRequest\x12\x18\n\x10\x66ile_to_generate\x18\x01 \x03(\t\x12\x11\n\tparameter\x18\x02 \x01(\t\x12\x38\n\nproto_file\x18\x0f \x03(\x0b\x32$.google.protobuf.FileDescriptorProto\"\xaa\x01\n\x15\x43odeGeneratorResponse\x12\r\n\x05\x65rror\x18\x01 \x01(\t\x12\x42\n\x04\x66ile\x18\x0f \x03(\x0b\x32\x34.google.protobuf.compiler.CodeGeneratorResponse.File\x1a>\n\x04\x46ile\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x17\n\x0finsertion_point\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x0f \x01(\tB,\n\x1c\x63om.google.protobuf.compilerB\x0cPluginProtos') + , + dependencies=[google.protobuf.descriptor_pb2.DESCRIPTOR,]) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + + + + +_CODEGENERATORREQUEST = _descriptor.Descriptor( + name='CodeGeneratorRequest', + full_name='google.protobuf.compiler.CodeGeneratorRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='file_to_generate', full_name='google.protobuf.compiler.CodeGeneratorRequest.file_to_generate', index=0, + number=1, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='parameter', full_name='google.protobuf.compiler.CodeGeneratorRequest.parameter', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='proto_file', full_name='google.protobuf.compiler.CodeGeneratorRequest.proto_file', index=2, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + extension_ranges=[], + oneofs=[ + ], + serialized_start=76, + serialized_end=201, +) + + +_CODEGENERATORRESPONSE_FILE = _descriptor.Descriptor( + name='File', + full_name='google.protobuf.compiler.CodeGeneratorResponse.File', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='insertion_point', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='content', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.content', index=2, + number=15, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + extension_ranges=[], + oneofs=[ + ], + serialized_start=312, + serialized_end=374, +) + +_CODEGENERATORRESPONSE = _descriptor.Descriptor( + name='CodeGeneratorResponse', + full_name='google.protobuf.compiler.CodeGeneratorResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='error', full_name='google.protobuf.compiler.CodeGeneratorResponse.error', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='file', full_name='google.protobuf.compiler.CodeGeneratorResponse.file', index=1, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_CODEGENERATORRESPONSE_FILE, ], + enum_types=[ + ], + options=None, + is_extendable=False, + extension_ranges=[], + oneofs=[ + ], + serialized_start=204, + serialized_end=374, +) + +_CODEGENERATORREQUEST.fields_by_name['proto_file'].message_type = google.protobuf.descriptor_pb2._FILEDESCRIPTORPROTO +_CODEGENERATORRESPONSE_FILE.containing_type = _CODEGENERATORRESPONSE +_CODEGENERATORRESPONSE.fields_by_name['file'].message_type = _CODEGENERATORRESPONSE_FILE +DESCRIPTOR.message_types_by_name['CodeGeneratorRequest'] = _CODEGENERATORREQUEST +DESCRIPTOR.message_types_by_name['CodeGeneratorResponse'] = _CODEGENERATORRESPONSE + +CodeGeneratorRequest = _reflection.GeneratedProtocolMessageType('CodeGeneratorRequest', (_message.Message,), dict( + DESCRIPTOR = _CODEGENERATORREQUEST, + __module__ = 'plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) + )) +_sym_db.RegisterMessage(CodeGeneratorRequest) + +CodeGeneratorResponse = _reflection.GeneratedProtocolMessageType('CodeGeneratorResponse', (_message.Message,), dict( + + File = _reflection.GeneratedProtocolMessageType('File', (_message.Message,), dict( + DESCRIPTOR = _CODEGENERATORRESPONSE_FILE, + __module__ = 'plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) + )) + , + DESCRIPTOR = _CODEGENERATORRESPONSE, + __module__ = 'plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) + )) +_sym_db.RegisterMessage(CodeGeneratorResponse) +_sym_db.RegisterMessage(CodeGeneratorResponse.File) + + +DESCRIPTOR.has_options = True +DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\034com.google.protobuf.compilerB\014PluginProtos')) +# @@protoc_insertion_point(module_scope) diff --git a/external/nano-pb/generator/protoc-gen-nanopb b/external/nano-pb/generator/protoc-gen-nanopb new file mode 100644 index 0000000..358f97c --- /dev/null +++ b/external/nano-pb/generator/protoc-gen-nanopb @@ -0,0 +1,13 @@ +#!/bin/sh + +# This file is used to invoke nanopb_generator.py as a plugin +# to protoc on Linux and other *nix-style systems. +# Use it like this: +# protoc --plugin=nanopb=..../protoc-gen-nanopb --nanopb_out=dir foo.proto +# +# Note that if you use the binary package of nanopb, the protoc +# path is already set up properly and there is no need to give +# --plugin= on the command line. + +MYPATH=$(dirname "$0") +exec "$MYPATH/nanopb_generator.py" --protoc-plugin diff --git a/external/nano-pb/generator/protoc-gen-nanopb.bat b/external/nano-pb/generator/protoc-gen-nanopb.bat new file mode 100644 index 0000000..7624984 --- /dev/null +++ b/external/nano-pb/generator/protoc-gen-nanopb.bat @@ -0,0 +1,12 @@ +@echo off +:: This file is used to invoke nanopb_generator.py as a plugin +:: to protoc on Windows. +:: Use it like this: +:: protoc --plugin=nanopb=..../protoc-gen-nanopb.bat --nanopb_out=dir foo.proto +:: +:: Note that if you use the binary package of nanopb, the protoc +:: path is already set up properly and there is no need to give +:: --plugin= on the command line. + +set mydir=%~dp0 +python "%mydir%\nanopb_generator.py" --protoc-plugin diff --git a/external/nano-pb/pb.h b/external/nano-pb/pb.h new file mode 100644 index 0000000..3fd2a4e --- /dev/null +++ b/external/nano-pb/pb.h @@ -0,0 +1,556 @@ +/* Common parts of the nanopb library. Most of these are quite low-level + * stuff. For the high-level interface, see pb_encode.h and pb_decode.h. + */ + +#ifndef PB_H_INCLUDED +#define PB_H_INCLUDED + +/***************************************************************** + * Nanopb compilation time options. You can change these here by * + * uncommenting the lines, or on the compiler command line. * + *****************************************************************/ + +/* Enable support for dynamically allocated fields */ +/* #define PB_ENABLE_MALLOC 1 */ + +/* Define this if your CPU / compiler combination does not support + * unaligned memory access to packed structures. */ +#define PB_NO_PACKED_STRUCTS 1 + +/* Increase the number of required fields that are tracked. + * A compiler warning will tell if you need this. */ +/* #define PB_MAX_REQUIRED_FIELDS 256 */ + +/* Add support for tag numbers > 255 and fields larger than 255 bytes. */ +#define PB_FIELD_16BIT 1 + +/* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */ +/* #define PB_FIELD_32BIT 1 */ + +/* Disable support for error messages in order to save some code space. */ +#define PB_NO_ERRMSG 1 + +/* Disable support for custom streams (support only memory buffers). */ +/* #define PB_BUFFER_ONLY 1 */ + +/* Switch back to the old-style callback function signature. + * This was the default until nanopb-0.2.1. */ +/* #define PB_OLD_CALLBACK_STYLE */ + + +/****************************************************************** + * You usually don't need to change anything below this line. * + * Feel free to look around and use the defined macros, though. * + ******************************************************************/ + + +/* Version of the nanopb library. Just in case you want to check it in + * your own program. */ +#define NANOPB_VERSION nanopb-0.3.6-dev + +/* Include all the system headers needed by nanopb. You will need the + * definitions of the following: + * - strlen, memcpy, memset functions + * - [u]int_least8_t, uint_fast8_t, [u]int_least16_t, [u]int32_t, [u]int64_t + * - size_t + * - bool + * + * If you don't have the standard header files, you can instead provide + * a custom header that defines or includes all this. In that case, + * define PB_SYSTEM_HEADER to the path of this file. + */ +#ifdef PB_SYSTEM_HEADER +#include PB_SYSTEM_HEADER +#else +#include +#include +#include +#include + +#ifdef PB_ENABLE_MALLOC +#include +#endif +#endif + +/* Macro for defining packed structures (compiler dependent). + * This just reduces memory requirements, but is not required. + */ +#if defined(PB_NO_PACKED_STRUCTS) + /* Disable struct packing */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed +#elif defined(__GNUC__) || defined(__clang__) + /* For GCC and clang */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed __attribute__((packed)) +#elif defined(__ICCARM__) || defined(__CC_ARM) + /* For IAR ARM and Keil MDK-ARM compilers */ +# define PB_PACKED_STRUCT_START _Pragma("pack(push, 1)") +# define PB_PACKED_STRUCT_END _Pragma("pack(pop)") +# define pb_packed +#elif defined(_MSC_VER) && (_MSC_VER >= 1500) + /* For Microsoft Visual C++ */ +# define PB_PACKED_STRUCT_START __pragma(pack(push, 1)) +# define PB_PACKED_STRUCT_END __pragma(pack(pop)) +# define pb_packed +#else + /* Unknown compiler */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed +#endif + +/* Handly macro for suppressing unreferenced-parameter compiler warnings. */ +#ifndef PB_UNUSED +#define PB_UNUSED(x) (void)(x) +#endif + +/* Compile-time assertion, used for checking compatible compilation options. + * If this does not work properly on your compiler, use + * #define PB_NO_STATIC_ASSERT to disable it. + * + * But before doing that, check carefully the error message / place where it + * comes from to see if the error has a real cause. Unfortunately the error + * message is not always very clear to read, but you can see the reason better + * in the place where the PB_STATIC_ASSERT macro was called. + */ +#ifndef PB_NO_STATIC_ASSERT +#ifndef PB_STATIC_ASSERT +#define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1]; +#define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) +#define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##LINE##COUNTER +#endif +#else +#define PB_STATIC_ASSERT(COND,MSG) +#endif + +/* Number of required fields to keep track of. */ +#ifndef PB_MAX_REQUIRED_FIELDS +#define PB_MAX_REQUIRED_FIELDS 64 +#endif + +#if PB_MAX_REQUIRED_FIELDS < 64 +#error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64). +#endif + +/* List of possible field types. These are used in the autogenerated code. + * Least-significant 4 bits tell the scalar type + * Most-significant 4 bits specify repeated/required/packed etc. + */ + +typedef uint_least8_t pb_type_t; + +/**** Field data types ****/ + +/* Numeric types */ +#define PB_LTYPE_VARINT 0x00 /* int32, int64, enum, bool */ +#define PB_LTYPE_UVARINT 0x01 /* uint32, uint64 */ +#define PB_LTYPE_SVARINT 0x02 /* sint32, sint64 */ +#define PB_LTYPE_FIXED32 0x03 /* fixed32, sfixed32, float */ +#define PB_LTYPE_FIXED64 0x04 /* fixed64, sfixed64, double */ + +/* Marker for last packable field type. */ +#define PB_LTYPE_LAST_PACKABLE 0x04 + +/* Byte array with pre-allocated buffer. + * data_size is the length of the allocated PB_BYTES_ARRAY structure. */ +#define PB_LTYPE_BYTES 0x05 + +/* String with pre-allocated buffer. + * data_size is the maximum length. */ +#define PB_LTYPE_STRING 0x06 + +/* Submessage + * submsg_fields is pointer to field descriptions */ +#define PB_LTYPE_SUBMESSAGE 0x07 + +/* Extension pseudo-field + * The field contains a pointer to pb_extension_t */ +#define PB_LTYPE_EXTENSION 0x08 + +/* Number of declared LTYPES */ +#define PB_LTYPES_COUNT 9 +#define PB_LTYPE_MASK 0x0F + +/**** Field repetition rules ****/ + +#define PB_HTYPE_REQUIRED 0x00 +#define PB_HTYPE_OPTIONAL 0x10 +#define PB_HTYPE_REPEATED 0x20 +#define PB_HTYPE_ONEOF 0x30 +#define PB_HTYPE_MASK 0x30 + +/**** Field allocation types ****/ + +#define PB_ATYPE_STATIC 0x00 +#define PB_ATYPE_POINTER 0x80 +#define PB_ATYPE_CALLBACK 0x40 +#define PB_ATYPE_MASK 0xC0 + +#define PB_ATYPE(x) ((x) & PB_ATYPE_MASK) +#define PB_HTYPE(x) ((x) & PB_HTYPE_MASK) +#define PB_LTYPE(x) ((x) & PB_LTYPE_MASK) + +/* Data type used for storing sizes of struct fields + * and array counts. + */ +#if defined(PB_FIELD_32BIT) + typedef uint32_t pb_size_t; + typedef int32_t pb_ssize_t; +#elif defined(PB_FIELD_16BIT) + typedef uint_least16_t pb_size_t; + typedef int_least16_t pb_ssize_t; +#else + typedef uint_least8_t pb_size_t; + typedef int_least8_t pb_ssize_t; +#endif +#define PB_SIZE_MAX ((pb_size_t)-1) + +/* Data type for storing encoded data and other byte streams. + * This typedef exists to support platforms where uint8_t does not exist. + * You can regard it as equivalent on uint8_t on other platforms. + */ +typedef uint_least8_t pb_byte_t; + +/* This structure is used in auto-generated constants + * to specify struct fields. + * You can change field sizes if you need structures + * larger than 256 bytes or field tags larger than 256. + * The compiler should complain if your .proto has such + * structures. Fix that by defining PB_FIELD_16BIT or + * PB_FIELD_32BIT. + */ +PB_PACKED_STRUCT_START +typedef struct pb_field_s pb_field_t; +struct pb_field_s { + pb_size_t tag; + pb_type_t type; + pb_size_t data_offset; /* Offset of field data, relative to previous field. */ + pb_ssize_t size_offset; /* Offset of array size or has-boolean, relative to data */ + pb_size_t data_size; /* Data size in bytes for a single item */ + pb_size_t array_size; /* Maximum number of entries in array */ + + /* Field definitions for submessage + * OR default value for all other non-array, non-callback types + * If null, then field will zeroed. */ + const void *ptr; +} pb_packed; +PB_PACKED_STRUCT_END + +/* Make sure that the standard integer types are of the expected sizes. + * Otherwise fixed32/fixed64 fields can break. + * + * If you get errors here, it probably means that your stdint.h is not + * correct for your platform. + */ +PB_STATIC_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t), INT64_T_WRONG_SIZE) +PB_STATIC_ASSERT(sizeof(uint64_t) == 2 * sizeof(uint32_t), UINT64_T_WRONG_SIZE) + +/* This structure is used for 'bytes' arrays. + * It has the number of bytes in the beginning, and after that an array. + * Note that actual structs used will have a different length of bytes array. + */ +#define PB_BYTES_ARRAY_T(n) struct { pb_size_t size; pb_byte_t bytes[n]; } +#define PB_BYTES_ARRAY_T_ALLOCSIZE(n) ((size_t)n + offsetof(pb_bytes_array_t, bytes)) + +struct pb_bytes_array_s { + pb_size_t size; + pb_byte_t bytes[1]; +}; +typedef struct pb_bytes_array_s pb_bytes_array_t; + +/* This structure is used for giving the callback function. + * It is stored in the message structure and filled in by the method that + * calls pb_decode. + * + * The decoding callback will be given a limited-length stream + * If the wire type was string, the length is the length of the string. + * If the wire type was a varint/fixed32/fixed64, the length is the length + * of the actual value. + * The function may be called multiple times (especially for repeated types, + * but also otherwise if the message happens to contain the field multiple + * times.) + * + * The encoding callback will receive the actual output stream. + * It should write all the data in one call, including the field tag and + * wire type. It can write multiple fields. + * + * The callback can be null if you want to skip a field. + */ +typedef struct pb_istream_s pb_istream_t; +typedef struct pb_ostream_s pb_ostream_t; +typedef struct pb_callback_s pb_callback_t; +struct pb_callback_s { +#ifdef PB_OLD_CALLBACK_STYLE + /* Deprecated since nanopb-0.2.1 */ + union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void *arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, const void *arg); + } funcs; +#else + /* New function signature, which allows modifying arg contents in callback. */ + union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg); + } funcs; +#endif + + /* Free arg for use by callback */ + void *arg; +}; + +/* Wire types. Library user needs these only in encoder callbacks. */ +typedef enum { + PB_WT_VARINT = 0, + PB_WT_64BIT = 1, + PB_WT_STRING = 2, + PB_WT_32BIT = 5 +} pb_wire_type_t; + +/* Structure for defining the handling of unknown/extension fields. + * Usually the pb_extension_type_t structure is automatically generated, + * while the pb_extension_t structure is created by the user. However, + * if you want to catch all unknown fields, you can also create a custom + * pb_extension_type_t with your own callback. + */ +typedef struct pb_extension_type_s pb_extension_type_t; +typedef struct pb_extension_s pb_extension_t; +struct pb_extension_type_s { + /* Called for each unknown field in the message. + * If you handle the field, read off all of its data and return true. + * If you do not handle the field, do not read anything and return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*decode)(pb_istream_t *stream, pb_extension_t *extension, + uint32_t tag, pb_wire_type_t wire_type); + + /* Called once after all regular fields have been encoded. + * If you have something to write, do so and return true. + * If you do not have anything to write, just return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension); + + /* Free field for use by the callback. */ + const void *arg; +}; + +struct pb_extension_s { + /* Type describing the extension field. Usually you'll initialize + * this to a pointer to the automatically generated structure. */ + const pb_extension_type_t *type; + + /* Destination for the decoded data. This must match the datatype + * of the extension field. */ + void *dest; + + /* Pointer to the next extension handler, or NULL. + * If this extension does not match a field, the next handler is + * automatically called. */ + pb_extension_t *next; + + /* The decoder sets this to true if the extension was found. + * Ignored for encoding. */ + bool found; +}; + +/* Memory allocation functions to use. You can define pb_realloc and + * pb_free to custom functions if you want. */ +#ifdef PB_ENABLE_MALLOC +# ifndef pb_realloc +# define pb_realloc(ptr, size) realloc(ptr, size) +# endif +# ifndef pb_free +# define pb_free(ptr) free(ptr) +# endif +#endif + +/* This is used to inform about need to regenerate .pb.h/.pb.c files. */ +#define PB_PROTO_HEADER_VERSION 30 + +/* These macros are used to declare pb_field_t's in the constant array. */ +/* Size of a structure member, in bytes. */ +#define pb_membersize(st, m) (sizeof ((st*)0)->m) +/* Number of entries in an array. */ +#define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0])) +/* Delta from start of one member to the start of another member. */ +#define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2)) +/* Marks the end of the field list */ +#define PB_LAST_FIELD {0,(pb_type_t) 0,0,0,0,0,0} + +/* Macros for filling in the data_offset field */ +/* data_offset for first field in a message */ +#define PB_DATAOFFSET_FIRST(st, m1, m2) (offsetof(st, m1)) +/* data_offset for subsequent fields */ +#define PB_DATAOFFSET_OTHER(st, m1, m2) (offsetof(st, m1) - offsetof(st, m2) - pb_membersize(st, m2)) +/* Choose first/other based on m1 == m2 (deprecated, remains for backwards compatibility) */ +#define PB_DATAOFFSET_CHOOSE(st, m1, m2) (int)(offsetof(st, m1) == offsetof(st, m2) \ + ? PB_DATAOFFSET_FIRST(st, m1, m2) \ + : PB_DATAOFFSET_OTHER(st, m1, m2)) + +/* Required fields are the simplest. They just have delta (padding) from + * previous field end, and the size of the field. Pointer is used for + * submessages and default values. + */ +#define PB_REQUIRED_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Optional fields add the delta to the has_ variable. */ +#define PB_OPTIONAL_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + fd, \ + pb_delta(st, has_ ## m, m), \ + pb_membersize(st, m), 0, ptr} + +/* Repeated fields have a _count field and also the maximum number of entries. */ +#define PB_REPEATED_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | ltype, \ + fd, \ + pb_delta(st, m ## _count, m), \ + pb_membersize(st, m[0]), \ + pb_arraysize(st, m), ptr} + +/* Allocated fields carry the size of the actual data, not the pointer */ +#define PB_REQUIRED_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Optional fields don't need a has_ variable, as information would be redundant */ +#define PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Repeated fields have a _count field and a pointer to array of pointers */ +#define PB_REPEATED_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_REPEATED | ltype, \ + fd, pb_delta(st, m ## _count, m), \ + pb_membersize(st, m[0]), 0, ptr} + +/* Callbacks are much like required fields except with special datatype. */ +#define PB_REQUIRED_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_REPEATED_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REPEATED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Optional extensions don't have the has_ field, as that would be redundant. */ +#define PB_OPTEXT_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + 0, \ + 0, \ + pb_membersize(st, m), 0, ptr} + +#define PB_OPTEXT_POINTER(tag, st, m, fd, ltype, ptr) \ + PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) + +#define PB_OPTEXT_CALLBACK(tag, st, m, fd, ltype, ptr) \ + PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) + +/* The mapping from protobuf types to LTYPEs is done using these macros. */ +#define PB_LTYPE_MAP_BOOL PB_LTYPE_VARINT +#define PB_LTYPE_MAP_BYTES PB_LTYPE_BYTES +#define PB_LTYPE_MAP_DOUBLE PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_ENUM PB_LTYPE_VARINT +#define PB_LTYPE_MAP_UENUM PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_FIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_FIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_FLOAT PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE +#define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_STRING PB_LTYPE_STRING +#define PB_LTYPE_MAP_UINT32 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_UINT64 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION + +/* This is the actual macro used in field descriptions. + * It takes these arguments: + * - Field tag number + * - Field type: BOOL, BYTES, DOUBLE, ENUM, UENUM, FIXED32, FIXED64, + * FLOAT, INT32, INT64, MESSAGE, SFIXED32, SFIXED64 + * SINT32, SINT64, STRING, UINT32, UINT64 or EXTENSION + * - Field rules: REQUIRED, OPTIONAL or REPEATED + * - Allocation: STATIC or CALLBACK + * - Placement: FIRST or OTHER, depending on if this is the first field in structure. + * - Message name + * - Field name + * - Previous field name (or field name again for first field) + * - Pointer to default value or submsg fields. + */ + +#define PB_FIELD(tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ ## rules ## _ ## allocation(tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +/* Field description for oneof fields. This requires taking into account the + * union name also, that's why a separate set of macros is needed. + */ +#define PB_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, u.m), \ + pb_membersize(st, u.m), 0, ptr} + +#define PB_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, u.m), \ + pb_membersize(st, u.m[0]), 0, ptr} + +#define PB_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ONEOF_ ## allocation(union_name, tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, union_name.field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +#define PB_ANONYMOUS_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, m), \ + pb_membersize(st, m), 0, ptr} + +#define PB_ANONYMOUS_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, m), \ + pb_membersize(st, m[0]), 0, ptr} + +#define PB_ANONYMOUS_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ANONYMOUS_ONEOF_ ## allocation(union_name, tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +/* These macros are used for giving out error messages. + * They are mostly a debugging aid; the main error information + * is the true/false return value from functions. + * Some code space can be saved by disabling the error + * messages if not used. + * + * PB_SET_ERROR() sets the error message if none has been set yet. + * msg must be a constant string literal. + * PB_GET_ERROR() always returns a pointer to a string. + * PB_RETURN_ERROR() sets the error and returns false from current + * function. + */ +#ifdef PB_NO_ERRMSG +#define PB_SET_ERROR(stream, msg) PB_UNUSED(stream) +#define PB_GET_ERROR(stream) "(errmsg disabled)" +#else +#define PB_SET_ERROR(stream, msg) (stream->errmsg = (stream)->errmsg ? (stream)->errmsg : (msg)) +#define PB_GET_ERROR(stream) ((stream)->errmsg ? (stream)->errmsg : "(none)") +#endif + +#define PB_RETURN_ERROR(stream, msg) return PB_SET_ERROR(stream, msg), false + +#endif diff --git a/external/nano-pb/pb_common.c b/external/nano-pb/pb_common.c new file mode 100644 index 0000000..385c019 --- /dev/null +++ b/external/nano-pb/pb_common.c @@ -0,0 +1,97 @@ +/* pb_common.c: Common support functions for pb_encode.c and pb_decode.c. + * + * 2014 Petteri Aimonen + */ + +#include "pb_common.h" + +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct) +{ + iter->start = fields; + iter->pos = fields; + iter->required_field_index = 0; + iter->dest_struct = dest_struct; + iter->pData = (char*)dest_struct + iter->pos->data_offset; + iter->pSize = (char*)iter->pData + iter->pos->size_offset; + + return (iter->pos->tag != 0); +} + +bool pb_field_iter_next(pb_field_iter_t *iter) +{ + const pb_field_t *prev_field = iter->pos; + + if (prev_field->tag == 0) + { + /* Handle empty message types, where the first field is already the terminator. + * In other cases, the iter->pos never points to the terminator. */ + return false; + } + + iter->pos++; + + if (iter->pos->tag == 0) + { + /* Wrapped back to beginning, reinitialize */ + (void)pb_field_iter_begin(iter, iter->start, iter->dest_struct); + return false; + } + else + { + /* Increment the pointers based on previous field size */ + size_t prev_size = prev_field->data_size; + + if (PB_HTYPE(prev_field->type) == PB_HTYPE_ONEOF && + PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF) + { + /* Don't advance pointers inside unions */ + prev_size = 0; + iter->pData = (char*)iter->pData - prev_field->data_offset; + } + else if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC && + PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED) + { + /* In static arrays, the data_size tells the size of a single entry and + * array_size is the number of entries */ + prev_size *= prev_field->array_size; + } + else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER) + { + /* Pointer fields always have a constant size in the main structure. + * The data_size only applies to the dynamically allocated area. */ + prev_size = sizeof(void*); + } + + if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED) + { + /* Count the required fields, in order to check their presence in the + * decoder. */ + iter->required_field_index++; + } + + iter->pData = (char*)iter->pData + prev_size + iter->pos->data_offset; + iter->pSize = (char*)iter->pData + iter->pos->size_offset; + return true; + } +} + +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) +{ + const pb_field_t *start = iter->pos; + + do { + if (iter->pos->tag == tag && + PB_LTYPE(iter->pos->type) != PB_LTYPE_EXTENSION) + { + /* Found the wanted field */ + return true; + } + + (void)pb_field_iter_next(iter); + } while (iter->pos != start); + + /* Searched all the way back to start, and found nothing. */ + return false; +} + + diff --git a/external/nano-pb/pb_common.h b/external/nano-pb/pb_common.h new file mode 100644 index 0000000..60b3d37 --- /dev/null +++ b/external/nano-pb/pb_common.h @@ -0,0 +1,42 @@ +/* pb_common.h: Common support functions for pb_encode.c and pb_decode.c. + * These functions are rarely needed by applications directly. + */ + +#ifndef PB_COMMON_H_INCLUDED +#define PB_COMMON_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Iterator for pb_field_t list */ +struct pb_field_iter_s { + const pb_field_t *start; /* Start of the pb_field_t array */ + const pb_field_t *pos; /* Current position of the iterator */ + unsigned required_field_index; /* Zero-based index that counts only the required fields */ + void *dest_struct; /* Pointer to start of the structure */ + void *pData; /* Pointer to current field value */ + void *pSize; /* Pointer to count/has field */ +}; +typedef struct pb_field_iter_s pb_field_iter_t; + +/* Initialize the field iterator structure to beginning. + * Returns false if the message type is empty. */ +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct); + +/* Advance the iterator to the next field. + * Returns false when the iterator wraps back to the first field. */ +bool pb_field_iter_next(pb_field_iter_t *iter); + +/* Advance the iterator until it points at a field with the given tag. + * Returns false if no such field exists. */ +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif + diff --git a/external/nano-pb/pb_decode.c b/external/nano-pb/pb_decode.c new file mode 100644 index 0000000..ef69efe --- /dev/null +++ b/external/nano-pb/pb_decode.c @@ -0,0 +1,1340 @@ +/* pb_decode.c -- decode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +#include "pb.h" +#include "pb_decode.h" +#include "pb_common.h" + +/************************************** + * Declarations internal to this file * + **************************************/ + +typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn; + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); +static bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest); +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size); +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension); +static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type); +static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn find_extension_field(pb_field_iter_t *iter); +static void pb_field_set_to_default(pb_field_iter_t *iter); +static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct); +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_skip_varint(pb_istream_t *stream); +static bool checkreturn pb_skip_string(pb_istream_t *stream); + +#ifdef PB_ENABLE_MALLOC +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size); +static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter); +static void pb_release_single_field(const pb_field_iter_t *iter); +#endif + +/* --- Function pointers to field decoders --- + * Order in the array must match pb_action_t LTYPE numbering. + */ +static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = { + &pb_dec_varint, + &pb_dec_uvarint, + &pb_dec_svarint, + &pb_dec_fixed32, + &pb_dec_fixed64, + + &pb_dec_bytes, + &pb_dec_string, + &pb_dec_submessage, + NULL /* extensions */ +}; + +/******************************* + * pb_istream_t implementation * + *******************************/ + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ + const pb_byte_t *source = (const pb_byte_t*)stream->state; + stream->state = (pb_byte_t*)stream->state + count; + + if (buf != NULL) + { + while (count--) + *buf++ = *source++; + } + + return true; +} + +bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ +#ifndef PB_BUFFER_ONLY + if (buf == NULL && stream->callback != buf_read) + { + /* Skip input bytes */ + pb_byte_t tmp[16]; + while (count > 16) + { + if (!pb_read(stream, tmp, 16)) + return false; + + count -= 16; + } + + return pb_read(stream, tmp, count); + } +#endif + + if (stream->bytes_left < count) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!buf_read(stream, buf, count)) + return false; +#endif + + stream->bytes_left -= count; + return true; +} + +/* Read a single byte from input stream. buf may not be NULL. + * This is an optimization for the varint decoding. */ +static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf) +{ + if (stream->bytes_left == 0) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, 1)) + PB_RETURN_ERROR(stream, "io error"); +#else + *buf = *(const pb_byte_t*)stream->state; + stream->state = (pb_byte_t*)stream->state + 1; +#endif + + stream->bytes_left--; + + return true; +} + +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize) +{ + pb_istream_t stream; + /* Cast away the const from buf without a compiler error. We are + * careful to use it only in a const manner in the callbacks. + */ + union { + void *state; + const void *c_state; + } state; +#ifdef PB_BUFFER_ONLY + stream.callback = NULL; +#else + stream.callback = &buf_read; +#endif + state.c_state = buf; + stream.state = state.state; + stream.bytes_left = bufsize; + stream.decoding_callback = NULL; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +/******************** + * Helper functions * + ********************/ + +static bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) +{ + pb_byte_t byte; + uint32_t result; + + if (!pb_readbyte(stream, &byte)) + return false; + + if ((byte & 0x80) == 0) + { + /* Quick case, 1 byte value */ + result = byte; + } + else + { + /* Multibyte case */ + uint_fast8_t bitpos = 7; + result = byte & 0x7F; + + do + { + if (bitpos >= 32) + PB_RETURN_ERROR(stream, "varint overflow"); + + if (!pb_readbyte(stream, &byte)) + return false; + + result |= (uint32_t)(byte & 0x7F) << bitpos; + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + } + + *dest = result; + return true; +} + +bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest) +{ + pb_byte_t byte; + uint_fast8_t bitpos = 0; + uint64_t result = 0; + + do + { + if (bitpos >= 64) + PB_RETURN_ERROR(stream, "varint overflow"); + + if (!pb_readbyte(stream, &byte)) + return false; + + result |= (uint64_t)(byte & 0x7F) << bitpos; + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + *dest = result; + return true; +} + +bool checkreturn pb_skip_varint(pb_istream_t *stream) +{ + pb_byte_t byte; + do + { + if (!pb_read(stream, &byte, 1)) + return false; + } while (byte & 0x80); + return true; +} + +bool checkreturn pb_skip_string(pb_istream_t *stream) +{ + uint32_t length; + if (!pb_decode_varint32(stream, &length)) + return false; + + return pb_read(stream, NULL, length); +} + +bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof) +{ + uint32_t temp; + *eof = false; + *wire_type = (pb_wire_type_t) 0; + *tag = 0; + + if (!pb_decode_varint32(stream, &temp)) + { + if (stream->bytes_left == 0) + *eof = true; + + return false; + } + + if (temp == 0) + { + *eof = true; /* Special feature: allow 0-terminated messages. */ + return false; + } + + *tag = temp >> 3; + *wire_type = (pb_wire_type_t)(temp & 7); + return true; +} + +bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type) +{ + switch (wire_type) + { + case PB_WT_VARINT: return pb_skip_varint(stream); + case PB_WT_64BIT: return pb_read(stream, NULL, 8); + case PB_WT_STRING: return pb_skip_string(stream); + case PB_WT_32BIT: return pb_read(stream, NULL, 4); + default: PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Read a raw value to buffer, for the purpose of passing it to callback as + * a substream. Size is maximum size on call, and actual size on return. + */ +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size) +{ + size_t max_size = *size; + switch (wire_type) + { + case PB_WT_VARINT: + *size = 0; + do + { + (*size)++; + if (*size > max_size) return false; + if (!pb_read(stream, buf, 1)) return false; + } while (*buf++ & 0x80); + return true; + + case PB_WT_64BIT: + *size = 8; + return pb_read(stream, buf, 8); + + case PB_WT_32BIT: + *size = 4; + return pb_read(stream, buf, 4); + + default: PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Decode string length from stream and return a substream with limited length. + * Remember to close the substream using pb_close_string_substream(). + */ +bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + uint32_t size; + if (!pb_decode_varint32(stream, &size)) + return false; + + *substream = *stream; + if (substream->bytes_left < size) + PB_RETURN_ERROR(stream, "parent stream too short"); + + substream->bytes_left = size; + stream->bytes_left -= size; + return true; +} + +void pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + stream->state = substream->state; + +#ifndef PB_NO_ERRMSG + stream->errmsg = substream->errmsg; +#endif +} + +/************************* + * Decode a single field * + *************************/ + +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_type_t type; + pb_decoder_t func; + + type = iter->pos->type; + func = PB_DECODERS[PB_LTYPE(type)]; + + switch (PB_HTYPE(type)) + { + case PB_HTYPE_REQUIRED: + return func(stream, iter->pos, iter->pData); + + case PB_HTYPE_OPTIONAL: + *(bool*)iter->pSize = true; + return func(stream, iter->pos, iter->pData); + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Packed array */ + bool status = true; + pb_size_t *size = (pb_size_t*)iter->pSize; + pb_istream_t substream; + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left > 0 && *size < iter->pos->array_size) + { + void *pItem = (char*)iter->pData + iter->pos->data_size * (*size); + if (!func(&substream, iter->pos, pItem)) + { + status = false; + break; + } + (*size)++; + } + pb_close_string_substream(stream, &substream); + + if (substream.bytes_left != 0) + PB_RETURN_ERROR(stream, "array overflow"); + + return status; + } + else + { + /* Repeated field */ + pb_size_t *size = (pb_size_t*)iter->pSize; + void *pItem = (char*)iter->pData + iter->pos->data_size * (*size); + if (*size >= iter->pos->array_size) + PB_RETURN_ERROR(stream, "array overflow"); + + (*size)++; + return func(stream, iter->pos, pItem); + } + + case PB_HTYPE_ONEOF: + *(pb_size_t*)iter->pSize = iter->pos->tag; + if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) + { + /* We memset to zero so that any callbacks are set to NULL. + * Then set any default values. */ + memset(iter->pData, 0, iter->pos->data_size); + pb_message_set_to_defaults((const pb_field_t*)iter->pos->ptr, iter->pData); + } + return func(stream, iter->pos, iter->pData); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +#ifdef PB_ENABLE_MALLOC +/* Allocate storage for the field and store the pointer at iter->pData. + * array_size is the number of entries to reserve in an array. + * Zero size is not allowed, use pb_free() for releasing. + */ +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size) +{ + void *ptr = *(void**)pData; + + if (data_size == 0 || array_size == 0) + PB_RETURN_ERROR(stream, "invalid size"); + + /* Check for multiplication overflows. + * This code avoids the costly division if the sizes are small enough. + * Multiplication is safe as long as only half of bits are set + * in either multiplicand. + */ + { + const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4); + if (data_size >= check_limit || array_size >= check_limit) + { + const size_t size_max = (size_t)-1; + if (size_max / array_size < data_size) + { + PB_RETURN_ERROR(stream, "size too large"); + } + } + } + + /* Allocate new or expand previous allocation */ + /* Note: on failure the old pointer will remain in the structure, + * the message must be freed by caller also on error return. */ + ptr = pb_realloc(ptr, array_size * data_size); + if (ptr == NULL) + PB_RETURN_ERROR(stream, "realloc failed"); + + *(void**)pData = ptr; + return true; +} + +/* Clear a newly allocated item in case it contains a pointer, or is a submessage. */ +static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter) +{ + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_STRING || + PB_LTYPE(iter->pos->type) == PB_LTYPE_BYTES) + { + *(void**)pItem = NULL; + } + else if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE) + { + pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, pItem); + } +} +#endif + +static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ +#ifndef PB_ENABLE_MALLOC + PB_UNUSED(wire_type); + PB_UNUSED(iter); + PB_RETURN_ERROR(stream, "no malloc support"); +#else + pb_type_t type; + pb_decoder_t func; + + type = iter->pos->type; + func = PB_DECODERS[PB_LTYPE(type)]; + + switch (PB_HTYPE(type)) + { + case PB_HTYPE_REQUIRED: + case PB_HTYPE_OPTIONAL: + case PB_HTYPE_ONEOF: + if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE && + *(void**)iter->pData != NULL) + { + /* Duplicate field, have to release the old allocation first. */ + pb_release_single_field(iter); + } + + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + *(pb_size_t*)iter->pSize = iter->pos->tag; + } + + if (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES) + { + return func(stream, iter->pos, iter->pData); + } + else + { + if (!allocate_field(stream, iter->pData, iter->pos->data_size, 1)) + return false; + + initialize_pointer_field(*(void**)iter->pData, iter); + return func(stream, iter->pos, *(void**)iter->pData); + } + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Packed array, multiple items come in at once. */ + bool status = true; + pb_size_t *size = (pb_size_t*)iter->pSize; + size_t allocated_size = *size; + void *pItem; + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left) + { + if ((size_t)*size + 1 > allocated_size) + { + /* Allocate more storage. This tries to guess the + * number of remaining entries. Round the division + * upwards. */ + allocated_size += (substream.bytes_left - 1) / iter->pos->data_size + 1; + + if (!allocate_field(&substream, iter->pData, iter->pos->data_size, allocated_size)) + { + status = false; + break; + } + } + + /* Decode the array entry */ + pItem = *(char**)iter->pData + iter->pos->data_size * (*size); + initialize_pointer_field(pItem, iter); + if (!func(&substream, iter->pos, pItem)) + { + status = false; + break; + } + + if (*size == PB_SIZE_MAX) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = "too many array entries"; +#endif + status = false; + break; + } + + (*size)++; + } + pb_close_string_substream(stream, &substream); + + return status; + } + else + { + /* Normal repeated field, i.e. only one item at a time. */ + pb_size_t *size = (pb_size_t*)iter->pSize; + void *pItem; + + if (*size == PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "too many array entries"); + + (*size)++; + if (!allocate_field(stream, iter->pData, iter->pos->data_size, *size)) + return false; + + pItem = *(char**)iter->pData + iter->pos->data_size * (*size - 1); + initialize_pointer_field(pItem, iter); + return func(stream, iter->pos, pItem); + } + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +#endif +} + +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_callback_t *pCallback = (pb_callback_t*)iter->pData; + +#ifdef PB_OLD_CALLBACK_STYLE + void *arg = pCallback->arg; +#else + void **arg = &(pCallback->arg); +#endif + + if (pCallback->funcs.decode == NULL) + return pb_skip_field(stream, wire_type); + + if (wire_type == PB_WT_STRING) + { + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + do + { + if (!pCallback->funcs.decode(&substream, iter->pos, arg)) + PB_RETURN_ERROR(stream, "callback failed"); + } while (substream.bytes_left); + + pb_close_string_substream(stream, &substream); + return true; + } + else + { + /* Copy the single scalar value to stack. + * This is required so that we can limit the stream length, + * which in turn allows to use same callback for packed and + * not-packed fields. */ + pb_istream_t substream; + pb_byte_t buffer[10]; + size_t size = sizeof(buffer); + + if (!read_raw_value(stream, wire_type, buffer, &size)) + return false; + substream = pb_istream_from_buffer(buffer, size); + + return pCallback->funcs.decode(&substream, iter->pos, arg); + } +} + +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ +#ifdef PB_ENABLE_MALLOC + /* When decoding an oneof field, check if there is old data that must be + * released first. */ + if (PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF) + { + if (!pb_release_union_field(stream, iter)) + return false; + } +#endif + + switch (PB_ATYPE(iter->pos->type)) + { + case PB_ATYPE_STATIC: + return decode_static_field(stream, wire_type, iter); + + case PB_ATYPE_POINTER: + return decode_pointer_field(stream, wire_type, iter); + + case PB_ATYPE_CALLBACK: + return decode_callback_field(stream, wire_type, iter); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension) +{ + /* Fake a field iterator for the extension field. + * It is not actually safe to advance this iterator, but decode_field + * will not even try to. */ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + (void)pb_field_iter_begin(iter, field, extension->dest); + iter->pData = extension->dest; + iter->pSize = &extension->found; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + iter->pData = &extension->dest; + } +} + +/* Default handler for extension fields. Expects a pb_field_t structure + * in extension->type->arg. */ +static bool checkreturn default_extension_decoder(pb_istream_t *stream, + pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type) +{ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + pb_field_iter_t iter; + + if (field->tag != tag) + return true; + + iter_from_extension(&iter, extension); + extension->found = true; + return decode_field(stream, wire_type, &iter); +} + +/* Try to decode an unknown field as an extension field. Tries each extension + * decoder in turn, until one of them handles the field or loop ends. */ +static bool checkreturn decode_extension(pb_istream_t *stream, + uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_extension_t *extension = *(pb_extension_t* const *)iter->pData; + size_t pos = stream->bytes_left; + + while (extension != NULL && pos == stream->bytes_left) + { + bool status; + if (extension->type->decode) + status = extension->type->decode(stream, extension, tag, wire_type); + else + status = default_extension_decoder(stream, extension, tag, wire_type); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/* Step through the iterator until an extension field is found or until all + * entries have been checked. There can be only one extension field per + * message. Returns false if no extension field is found. */ +static bool checkreturn find_extension_field(pb_field_iter_t *iter) +{ + const pb_field_t *start = iter->pos; + + do { + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_EXTENSION) + return true; + (void)pb_field_iter_next(iter); + } while (iter->pos != start); + + return false; +} + +/* Initialize message fields to default values, recursively */ +static void pb_field_set_to_default(pb_field_iter_t *iter) +{ + pb_type_t type; + type = iter->pos->type; + + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + pb_extension_t *ext = *(pb_extension_t* const *)iter->pData; + while (ext != NULL) + { + pb_field_iter_t ext_iter; + ext->found = false; + iter_from_extension(&ext_iter, ext); + pb_field_set_to_default(&ext_iter); + ext = ext->next; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { + bool init_data = true; + if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL) + { + /* Set has_field to false. Still initialize the optional field + * itself also. */ + *(bool*)iter->pSize = false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + /* REPEATED: Set array count to 0, no need to initialize contents. + ONEOF: Set which_field to 0. */ + *(pb_size_t*)iter->pSize = 0; + init_data = false; + } + + if (init_data) + { + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE) + { + /* Initialize submessage to defaults */ + pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, iter->pData); + } + else if (iter->pos->ptr != NULL) + { + /* Initialize to default value */ + memcpy(iter->pData, iter->pos->ptr, iter->pos->data_size); + } + else + { + /* Initialize to zeros */ + memset(iter->pData, 0, iter->pos->data_size); + } + } + } + else if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + /* Initialize the pointer to NULL. */ + *(void**)iter->pData = NULL; + + /* Initialize array count to 0. */ + if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + *(pb_size_t*)iter->pSize = 0; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK) + { + /* Don't overwrite callback */ + } +} + +static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct) +{ + pb_field_iter_t iter; + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do + { + pb_field_set_to_default(&iter); + } while (pb_field_iter_next(&iter)); +} + +/********************* + * Decode all fields * + *********************/ + +bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + uint32_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 31) / 32] = {0, 0}; + const uint32_t allbits = ~(uint32_t)0; + uint32_t extension_range_start = 0; + pb_field_iter_t iter; + + /* Return value ignored, as empty message types will be correctly handled by + * pb_field_iter_find() anyway. */ + (void)pb_field_iter_begin(&iter, fields, dest_struct); + + while (stream->bytes_left) + { + uint32_t tag; + pb_wire_type_t wire_type; + bool eof; + + if (!pb_decode_tag(stream, &wire_type, &tag, &eof)) + { + if (eof) + break; + else + return false; + } + + if (!pb_field_iter_find(&iter, tag)) + { + /* No match found, check if it matches an extension. */ + if (tag >= extension_range_start) + { + if (!find_extension_field(&iter)) + extension_range_start = (uint32_t)-1; + else + extension_range_start = iter.pos->tag; + + if (tag >= extension_range_start) + { + size_t pos = stream->bytes_left; + + if (!decode_extension(stream, tag, wire_type, &iter)) + return false; + + if (pos != stream->bytes_left) + { + /* The field was handled */ + continue; + } + } + } + + /* No match found, skip data */ + if (!pb_skip_field(stream, wire_type)) + return false; + continue; + } + + if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REQUIRED + && iter.required_field_index < PB_MAX_REQUIRED_FIELDS) + { + uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31)); + fields_seen[iter.required_field_index >> 5] |= tmp; + } + + if(stream->decoding_callback) + { + stream->decoding_callback(stream, tag, wire_type, &iter); + } + + if (!decode_field(stream, wire_type, &iter)) + return false; + } + + /* Check that all required fields were present. */ + { + /* First figure out the number of required fields by + * seeking to the end of the field array. Usually we + * are already close to end after decoding. + */ + unsigned req_field_count; + pb_type_t last_type; + unsigned i; + do { + req_field_count = iter.required_field_index; + last_type = iter.pos->type; + } while (pb_field_iter_next(&iter)); + + /* Fixup if last field was also required. */ + if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag != 0) + req_field_count++; + + if (req_field_count > 0) + { + /* Check the whole words */ + for (i = 0; i < (req_field_count >> 5); i++) + { + if (fields_seen[i] != allbits) + PB_RETURN_ERROR(stream, "missing required field"); + } + + /* Check the remaining bits */ + if (fields_seen[req_field_count >> 5] != (allbits >> (32 - (req_field_count & 31)))) + PB_RETURN_ERROR(stream, "missing required field"); + } + } + + return true; +} + +bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + bool status; + pb_message_set_to_defaults(fields, dest_struct); + status = pb_decode_noinit(stream, fields, dest_struct); + +#ifdef PB_ENABLE_MALLOC + if (!status) + pb_release(fields, dest_struct); +#endif + + return status; +} + +bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + pb_istream_t substream; + bool status; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + status = pb_decode(&substream, fields, dest_struct); + pb_close_string_substream(stream, &substream); + return status; +} + +#ifdef PB_ENABLE_MALLOC +/* Given an oneof field, if there has already been a field inside this oneof, + * release it before overwriting with a different one. */ +static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter) +{ + pb_size_t old_tag = *(pb_size_t*)iter->pSize; /* Previous which_ value */ + pb_size_t new_tag = iter->pos->tag; /* New which_ value */ + + if (old_tag == 0) + return true; /* Ok, no old data in union */ + + if (old_tag == new_tag) + return true; /* Ok, old data is of same type => merge */ + + /* Release old data. The find can fail if the message struct contains + * invalid data. */ + if (!pb_field_iter_find(iter, old_tag)) + PB_RETURN_ERROR(stream, "invalid union tag"); + + pb_release_single_field(iter); + + /* Restore iterator to where it should be. + * This shouldn't fail unless the pb_field_t structure is corrupted. */ + if (!pb_field_iter_find(iter, new_tag)) + PB_RETURN_ERROR(stream, "iterator error"); + + return true; +} + +static void pb_release_single_field(const pb_field_iter_t *iter) +{ + pb_type_t type; + type = iter->pos->type; + + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + if (*(pb_size_t*)iter->pSize != iter->pos->tag) + return; /* This is not the current field in the union */ + } + + /* Release anything contained inside an extension or submsg. + * This has to be done even if the submsg itself is statically + * allocated. */ + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + /* Release fields from all extensions in the linked list */ + pb_extension_t *ext = *(pb_extension_t**)iter->pData; + while (ext != NULL) + { + pb_field_iter_t ext_iter; + iter_from_extension(&ext_iter, ext); + pb_release_single_field(&ext_iter); + ext = ext->next; + } + } + else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) + { + /* Release fields in submessage or submsg array */ + void *pItem = iter->pData; + pb_size_t count = 1; + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + pItem = *(void**)iter->pData; + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + count = *(pb_size_t*)iter->pSize; + } + + if (pItem) + { + while (count--) + { + pb_release((const pb_field_t*)iter->pos->ptr, pItem); + pItem = (char*)pItem + iter->pos->data_size; + } + } + } + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + if (PB_HTYPE(type) == PB_HTYPE_REPEATED && + (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES)) + { + /* Release entries in repeated string or bytes array */ + void **pItem = *(void***)iter->pData; + pb_size_t count = *(pb_size_t*)iter->pSize; + while (count--) + { + pb_free(*pItem); + *pItem++ = NULL; + } + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + /* We are going to release the array, so set the size to 0 */ + *(pb_size_t*)iter->pSize = 0; + } + + /* Release main item */ + pb_free(*(void**)iter->pData); + *(void**)iter->pData = NULL; + } +} + +void pb_release(const pb_field_t fields[], void *dest_struct) +{ + pb_field_iter_t iter; + + if (!dest_struct) + return; /* Ignore NULL pointers, similar to free() */ + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do + { + pb_release_single_field(&iter); + } while (pb_field_iter_next(&iter)); +} +#endif + +/* Field decoders */ + +bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest) +{ + uint64_t value; + if (!pb_decode_varint(stream, &value)) + return false; + + if (value & 1) + *dest = (int64_t)(~(value >> 1)); + else + *dest = (int64_t)(value >> 1); + + return true; +} + +bool pb_decode_fixed32(pb_istream_t *stream, void *dest) +{ + pb_byte_t bytes[4]; + + if (!pb_read(stream, bytes, 4)) + return false; + + *(uint32_t*)dest = ((uint32_t)bytes[0] << 0) | + ((uint32_t)bytes[1] << 8) | + ((uint32_t)bytes[2] << 16) | + ((uint32_t)bytes[3] << 24); + return true; +} + +bool pb_decode_fixed64(pb_istream_t *stream, void *dest) +{ + pb_byte_t bytes[8]; + + if (!pb_read(stream, bytes, 8)) + return false; + + *(uint64_t*)dest = ((uint64_t)bytes[0] << 0) | + ((uint64_t)bytes[1] << 8) | + ((uint64_t)bytes[2] << 16) | + ((uint64_t)bytes[3] << 24) | + ((uint64_t)bytes[4] << 32) | + ((uint64_t)bytes[5] << 40) | + ((uint64_t)bytes[6] << 48) | + ((uint64_t)bytes[7] << 56); + + return true; +} + +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint64_t value; + int64_t svalue; + int64_t clamped; + if (!pb_decode_varint(stream, &value)) + return false; + + /* See issue 97: Google's C++ protobuf allows negative varint values to + * be cast as int32_t, instead of the int64_t that should be used when + * encoding. Previous nanopb versions had a bug in encoding. In order to + * not break decoding of such messages, we cast <=32 bit fields to + * int32_t first to get the sign correct. + */ + if (field->data_size == sizeof(int64_t)) + svalue = (int64_t)value; + else + svalue = (int32_t)value; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(int64_t)) + clamped = *(int64_t*)dest = svalue; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)dest = (int32_t)svalue; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)dest = (int_least16_t)svalue; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)dest = (int_least8_t)svalue; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != svalue) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint64_t value, clamped; + if (!pb_decode_varint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(uint64_t)) + clamped = *(uint64_t*)dest = value; + else if (field->data_size == sizeof(uint32_t)) + clamped = *(uint32_t*)dest = (uint32_t)value; + else if (field->data_size == sizeof(uint_least16_t)) + clamped = *(uint_least16_t*)dest = (uint_least16_t)value; + else if (field->data_size == sizeof(uint_least8_t)) + clamped = *(uint_least8_t*)dest = (uint_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + int64_t value, clamped; + if (!pb_decode_svarint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(int64_t)) + clamped = *(int64_t*)dest = value; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)dest = (int32_t)value; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)dest = (int_least16_t)value; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)dest = (int_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + PB_UNUSED(field); + return pb_decode_fixed32(stream, dest); +} + +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + PB_UNUSED(field); + return pb_decode_fixed64(stream, dest); +} + +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + size_t alloc_size; + pb_bytes_array_t *bdest; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + alloc_size = PB_BYTES_ARRAY_T_ALLOCSIZE(size); + if (size > alloc_size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (!allocate_field(stream, dest, alloc_size, 1)) + return false; + bdest = *(pb_bytes_array_t**)dest; +#endif + } + else + { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "bytes overflow"); + bdest = (pb_bytes_array_t*)dest; + } + + bdest->size = (pb_size_t)size; + return pb_read(stream, bdest->bytes, size); +} + +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + size_t alloc_size; + bool status; + if (!pb_decode_varint32(stream, &size)) + return false; + + /* Space for null terminator */ + alloc_size = size + 1; + + if (alloc_size < size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (!allocate_field(stream, dest, alloc_size, 1)) + return false; + dest = *(void**)dest; +#endif + } + else + { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "string overflow"); + } + + status = pb_read(stream, (pb_byte_t*)dest, size); + *((pb_byte_t*)dest + size) = 0; + return status; +} + +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + bool status; + pb_istream_t substream; + const pb_field_t* submsg_fields = (const pb_field_t*)field->ptr; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + if (field->ptr == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + /* New array entries need to be initialized, while required and optional + * submessages have already been initialized in the top-level pb_decode. */ + if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED) + status = pb_decode(&substream, submsg_fields, dest); + else + status = pb_decode_noinit(&substream, submsg_fields, dest); + + pb_close_string_substream(stream, &substream); + return status; +} diff --git a/external/nano-pb/pb_decode.h b/external/nano-pb/pb_decode.h new file mode 100644 index 0000000..7ab8ce7 --- /dev/null +++ b/external/nano-pb/pb_decode.h @@ -0,0 +1,152 @@ +/* pb_decode.h: Functions to decode protocol buffers. Depends on pb_decode.c. + * The main function is pb_decode. You also need an input stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_DECODE_H_INCLUDED +#define PB_DECODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom input streams. You will need to provide + * a callback function to read the bytes from your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause decoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer), + * and rely on pb_read to verify that no-body reads past bytes_left. + * 3) Your callback may be used with substreams, in which case bytes_left + * is different than from the main stream. Don't use bytes_left to compute + * any pointers. + */ +struct pb_istream_s +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + */ + int *callback; +#else + bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count); +#endif + + void *state; /* Free field for use by callback implementation */ + size_t bytes_left; + + /* Informative callback for field decoding */ + void (* decoding_callback)(pb_istream_t *strem, uint32_t tag, pb_wire_type_t wire_type, void *iter); + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +/*************************** + * Main decoding functions * + ***************************/ + +/* Decode a single protocol buffers message from input stream into a C structure. + * Returns true on success, false on any failure. + * The actual struct pointed to by dest must match the description in fields. + * Callback fields of the destination structure must be initialized by caller. + * All other fields will be initialized by this function. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_istream_t stream; + * + * // ... read some data into buffer ... + * + * stream = pb_istream_from_buffer(buffer, count); + * pb_decode(&stream, MyMessage_fields, &msg); + */ +bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except does not initialize the destination structure + * to default values. This is slightly faster if you need no default values + * and just do memset(struct, 0, sizeof(struct)) yourself. + * + * This can also be used for 'merging' two messages, i.e. update only the + * fields that exist in the new message. + * + * Note: If this function returns with an error, it will not release any + * dynamically allocated fields. You will need to call pb_release() yourself. + */ +bool pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except expects the stream to start with the message size + * encoded as varint. Corresponds to parseDelimitedFrom() in Google's + * protobuf API. + */ +bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +#ifdef PB_ENABLE_MALLOC +/* Release any allocated pointer fields. If you use dynamic allocation, you should + * call this for any successfully decoded message when you are done with it. If + * pb_decode() returns with an error, the message is already released. + */ +void pb_release(const pb_field_t fields[], void *dest_struct); +#endif + + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an input stream for reading from a memory buffer. + * + * Alternatively, you can use a custom stream that reads directly from e.g. + * a file or a network socket. + */ +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize); + +/* Function to read from a pb_istream_t. You can use this if you need to + * read some custom header data, or to read data in field callbacks. + */ +bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Decode the tag for the next field in the stream. Gives the wire type and + * field tag. At end of the message, returns false and sets eof to true. */ +bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof); + +/* Skip the field payload data, given the wire type. */ +bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type); + +/* Decode an integer in the varint format. This works for bool, enum, int32, + * int64, uint32 and uint64 field types. */ +bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest); + +/* Decode an integer in the zig-zagged svarint format. This works for sint32 + * and sint64. */ +bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest); + +/* Decode a fixed32, sfixed32 or float value. You need to pass a pointer to + * a 4-byte wide C variable. */ +bool pb_decode_fixed32(pb_istream_t *stream, void *dest); + +/* Decode a fixed64, sfixed64 or double value. You need to pass a pointer to + * a 8-byte wide C variable. */ +bool pb_decode_fixed64(pb_istream_t *stream, void *dest); + +/* Make a limited-length substream for reading a PB_WT_STRING field. */ +bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream); +void pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/external/nano-pb/pb_encode.c b/external/nano-pb/pb_encode.c new file mode 100644 index 0000000..9f91c9d --- /dev/null +++ b/external/nano-pb/pb_encode.c @@ -0,0 +1,689 @@ +/* pb_encode.c -- encode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +#include "pb.h" +#include "pb_encode.h" +#include "pb_common.h" + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +/************************************** + * Declarations internal to this file * + **************************************/ +typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn; + +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func); +static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension); +static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src); + +/* --- Function pointers to field encoders --- + * Order in the array must match pb_action_t LTYPE numbering. + */ +static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = { + &pb_enc_varint, + &pb_enc_uvarint, + &pb_enc_svarint, + &pb_enc_fixed32, + &pb_enc_fixed64, + + &pb_enc_bytes, + &pb_enc_string, + &pb_enc_submessage, + NULL /* extensions */ +}; + +/******************************* + * pb_ostream_t implementation * + *******************************/ + +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + pb_byte_t *dest = (pb_byte_t*)stream->state; + stream->state = dest + count; + + while (count--) + *dest++ = *buf++; + + return true; +} + +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize) +{ + pb_ostream_t stream; +#ifdef PB_BUFFER_ONLY + stream.callback = (void*)1; /* Just a marker value */ +#else + stream.callback = &buf_write; +#endif + stream.state = buf; + stream.max_size = bufsize; + stream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + if (stream->callback != NULL) + { + if (stream->bytes_written + count > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + +#ifdef PB_BUFFER_ONLY + if (!buf_write(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#endif + } + + stream->bytes_written += count; + return true; +} + +/************************* + * Encode a single field * + *************************/ + +/* Encode a static array. Handles the size calculations and possible packing. */ +static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, + const void *pData, size_t count, pb_encoder_t func) +{ + size_t i; + const void *p; + size_t size; + + if (count == 0) + return true; + + if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) + PB_RETURN_ERROR(stream, "array max size exceeded"); + + /* We always pack arrays if the datatype allows it. */ + if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) + { + if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) + return false; + + /* Determine the total size of packed array. */ + if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) + { + size = 4 * count; + } + else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) + { + size = 8 * count; + } + else + { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + p = pData; + for (i = 0; i < count; i++) + { + if (!func(&sizestream, field, p)) + return false; + p = (const char*)p + field->data_size; + } + size = sizestream.bytes_written; + } + + if (!pb_encode_varint(stream, (uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing.. */ + + /* Write the data */ + p = pData; + for (i = 0; i < count; i++) + { + if (!func(stream, field, p)) + return false; + p = (const char*)p + field->data_size; + } + } + else + { + p = pData; + for (i = 0; i < count; i++) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + /* Normally the data is stored directly in the array entries, but + * for pointer-type string and bytes fields, the array entries are + * actually pointers themselves also. So we have to dereference once + * more to get to the actual data. */ + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER && + (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES)) + { + if (!func(stream, field, *(const void* const*)p)) + return false; + } + else + { + if (!func(stream, field, p)) + return false; + } + p = (const char*)p + field->data_size; + } + } + + return true; +} + +/* Encode a field with static or pointer allocation, i.e. one whose data + * is available to the encoder directly. */ +static bool checkreturn encode_basic_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + pb_encoder_t func; + const void *pSize; + bool implicit_has = true; + + func = PB_ENCODERS[PB_LTYPE(field->type)]; + + if (field->size_offset) + pSize = (const char*)pData + field->size_offset; + else + pSize = &implicit_has; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* pData is a pointer to the field, which contains pointer to + * the data. If the 2nd pointer is NULL, it is interpreted as if + * the has_field was false. + */ + + pData = *(const void* const*)pData; + implicit_has = (pData != NULL); + } + + switch (PB_HTYPE(field->type)) + { + case PB_HTYPE_REQUIRED: + if (!pData) + PB_RETURN_ERROR(stream, "missing required field"); + if (!pb_encode_tag_for_field(stream, field)) + return false; + if (!func(stream, field, pData)) + return false; + break; + + case PB_HTYPE_OPTIONAL: + if (*(const bool*)pSize) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + if (!func(stream, field, pData)) + return false; + } + break; + + case PB_HTYPE_REPEATED: + if (!encode_array(stream, field, pData, *(const pb_size_t*)pSize, func)) + return false; + break; + + case PB_HTYPE_ONEOF: + if (*(const pb_size_t*)pSize == field->tag) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + if (!func(stream, field, pData)) + return false; + } + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return true; +} + +/* Encode a field with callback semantics. This means that a user function is + * called to provide and encode the actual data. */ +static bool checkreturn encode_callback_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + const pb_callback_t *callback = (const pb_callback_t*)pData; + +#ifdef PB_OLD_CALLBACK_STYLE + const void *arg = callback->arg; +#else + void * const *arg = &(callback->arg); +#endif + + if (callback->funcs.encode != NULL) + { + if (!callback->funcs.encode(stream, field, arg)) + PB_RETURN_ERROR(stream, "callback error"); + } + return true; +} + +/* Encode a single field of any callback or static type. */ +static bool checkreturn encode_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + switch (PB_ATYPE(field->type)) + { + case PB_ATYPE_STATIC: + case PB_ATYPE_POINTER: + return encode_basic_field(stream, field, pData); + + case PB_ATYPE_CALLBACK: + return encode_callback_field(stream, field, pData); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +/* Default handler for extension fields. Expects to have a pb_field_t + * pointer in the extension->type->arg field. */ +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, + const pb_extension_t *extension) +{ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + return encode_field(stream, field, &extension->dest); + } + else + { + return encode_field(stream, field, extension->dest); + } +} + +/* Walk through all the registered extensions and give them a chance + * to encode themselves. */ +static bool checkreturn encode_extension_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + const pb_extension_t *extension = *(const pb_extension_t* const *)pData; + PB_UNUSED(field); + + while (extension) + { + bool status; + if (extension->type->encode) + status = extension->type->encode(stream, extension); + else + status = default_extension_encoder(stream, extension); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/********************* + * Encode all fields * + *********************/ + +static void *remove_const(const void *p) +{ + /* Note: this casts away const, in order to use the common field iterator + * logic for both encoding and decoding. */ + union { + void *p1; + const void *p2; + } t; + t.p2 = p; + return t.p1; +} + +bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + pb_field_iter_t iter; + if (!pb_field_iter_begin(&iter, fields, remove_const(src_struct))) + return true; /* Empty message type */ + + do { + if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION) + { + /* Special case for the extension field placeholder */ + if (!encode_extension_field(stream, iter.pos, iter.pData)) + return false; + } + else + { + /* Regular field */ + if (!encode_field(stream, iter.pos, iter.pData)) + return false; + } + } while (pb_field_iter_next(&iter)); + + return true; +} + +bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + return pb_encode_submessage(stream, fields, src_struct); +} + +bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct) +{ + pb_ostream_t stream = PB_OSTREAM_SIZING; + + if (!pb_encode(&stream, fields, src_struct)) + return false; + + *size = stream.bytes_written; + return true; +} + +/******************** + * Helper functions * + ********************/ +bool checkreturn pb_encode_varint(pb_ostream_t *stream, uint64_t value) +{ + pb_byte_t buffer[10]; + size_t i = 0; + + if (value <= 0x7F) + { + pb_byte_t v = (pb_byte_t)value; + return pb_write(stream, &v, 1); + } + + while (value) + { + buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); + value >>= 7; + i++; + } + buffer[i-1] &= 0x7F; /* Unset top bit on last byte */ + + return pb_write(stream, buffer, i); +} + +bool checkreturn pb_encode_svarint(pb_ostream_t *stream, int64_t value) +{ + uint64_t zigzagged; + if (value < 0) + zigzagged = ~((uint64_t)value << 1); + else + zigzagged = (uint64_t)value << 1; + + return pb_encode_varint(stream, zigzagged); +} + +bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) +{ + uint32_t val = *(const uint32_t*)value; + pb_byte_t bytes[4]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + return pb_write(stream, bytes, 4); +} + +bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) +{ + uint64_t val = *(const uint64_t*)value; + pb_byte_t bytes[8]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + bytes[4] = (pb_byte_t)((val >> 32) & 0xFF); + bytes[5] = (pb_byte_t)((val >> 40) & 0xFF); + bytes[6] = (pb_byte_t)((val >> 48) & 0xFF); + bytes[7] = (pb_byte_t)((val >> 56) & 0xFF); + return pb_write(stream, bytes, 8); +} + +bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number) +{ + uint64_t tag = ((uint64_t)field_number << 3) | wiretype; + return pb_encode_varint(stream, tag); +} + +bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field) +{ + pb_wire_type_t wiretype; + switch (PB_LTYPE(field->type)) + { + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + wiretype = PB_WT_VARINT; + break; + + case PB_LTYPE_FIXED32: + wiretype = PB_WT_32BIT; + break; + + case PB_LTYPE_FIXED64: + wiretype = PB_WT_64BIT; + break; + + case PB_LTYPE_BYTES: + case PB_LTYPE_STRING: + case PB_LTYPE_SUBMESSAGE: + wiretype = PB_WT_STRING; + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return pb_encode_tag(stream, wiretype, field->tag); +} + +bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size) +{ + if (!pb_encode_varint(stream, (uint64_t)size)) + return false; + + return pb_write(stream, buffer, size); +} + +bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + /* First calculate the message size using a non-writing substream. */ + pb_ostream_t substream = PB_OSTREAM_SIZING; + size_t size; + bool status; + + if (!pb_encode(&substream, fields, src_struct)) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + return false; + } + + size = substream.bytes_written; + + if (!pb_encode_varint(stream, (uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing */ + + if (stream->bytes_written + size > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + + /* Use a substream to verify that a callback doesn't write more than + * what it did the first time. */ + substream.callback = stream->callback; + substream.state = stream->state; + substream.max_size = size; + substream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + substream.errmsg = NULL; +#endif + + status = pb_encode(&substream, fields, src_struct); + + stream->bytes_written += substream.bytes_written; + stream->state = substream.state; +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + + if (substream.bytes_written != size) + PB_RETURN_ERROR(stream, "submsg size changed"); + + return status; +} + +/* Field encoders */ + +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t*)src; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t*)src; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t*)src; + else if (field->data_size == sizeof(int64_t)) + value = *(const int64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_varint(stream, (uint64_t)value); +} + +static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + uint64_t value = 0; + + if (field->data_size == sizeof(uint_least8_t)) + value = *(const uint_least8_t*)src; + else if (field->data_size == sizeof(uint_least16_t)) + value = *(const uint_least16_t*)src; + else if (field->data_size == sizeof(uint32_t)) + value = *(const uint32_t*)src; + else if (field->data_size == sizeof(uint64_t)) + value = *(const uint64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_varint(stream, value); +} + +static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t*)src; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t*)src; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t*)src; + else if (field->data_size == sizeof(int64_t)) + value = *(const int64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_svarint(stream, value); +} + +static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + PB_UNUSED(field); + return pb_encode_fixed64(stream, src); +} + +static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + PB_UNUSED(field); + return pb_encode_fixed32(stream, src); +} + +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)src; + + if (src == NULL) + { + /* Threat null pointer as an empty bytes field */ + return pb_encode_string(stream, NULL, 0); + } + + if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && + PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size) + { + PB_RETURN_ERROR(stream, "bytes size exceeded"); + } + + return pb_encode_string(stream, bytes->bytes, bytes->size); +} + +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + size_t size = 0; + size_t max_size = field->data_size; + const char *p = (const char*)src; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + max_size = (size_t)-1; + + if (src == NULL) + { + size = 0; /* Threat null pointer as an empty string */ + } + else + { + /* strnlen() is not always available, so just use a loop */ + while (size < max_size && *p != '\0') + { + size++; + p++; + } + } + + return pb_encode_string(stream, (const pb_byte_t*)src, size); +} + +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + if (field->ptr == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src); +} + diff --git a/external/nano-pb/pb_encode.h b/external/nano-pb/pb_encode.h new file mode 100644 index 0000000..d9909fb --- /dev/null +++ b/external/nano-pb/pb_encode.h @@ -0,0 +1,154 @@ +/* pb_encode.h: Functions to encode protocol buffers. Depends on pb_encode.c. + * The main function is pb_encode. You also need an output stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_ENCODE_H_INCLUDED +#define PB_ENCODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom output streams. You will need to provide + * a callback function to write the bytes to your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause encoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer). + * 3) pb_write will update bytes_written after your callback runs. + * 4) Substreams will modify max_size and bytes_written. Don't use them + * to calculate any pointers. + */ +struct pb_ostream_s +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + * Also, NULL pointer marks a 'sizing stream' that does not + * write anything. + */ + int *callback; +#else + bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +#endif + void *state; /* Free field for use by callback implementation. */ + size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */ + size_t bytes_written; /* Number of bytes written so far. */ + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +/*************************** + * Main encoding functions * + ***************************/ + +/* Encode a single protocol buffers message from C structure into a stream. + * Returns true on success, false on any failure. + * The actual struct pointed to by src_struct must match the description in fields. + * All required fields in the struct are assumed to have been filled in. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_ostream_t stream; + * + * msg.field1 = 42; + * stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + * pb_encode(&stream, MyMessage_fields, &msg); + */ +bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Same as pb_encode, but prepends the length of the message as a varint. + * Corresponds to writeDelimitedTo() in Google's protobuf API. + */ +bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Encode the message to get the size of the encoded data, but do not store + * the data. */ +bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct); + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an output stream for writing into a memory buffer. + * The number of bytes written can be found in stream.bytes_written after + * encoding the message. + * + * Alternatively, you can use a custom stream that writes directly to e.g. + * a file or a network socket. + */ +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize); + +/* Pseudo-stream for measuring the size of a message without actually storing + * the encoded data. + * + * Example usage: + * MyMessage msg = {}; + * pb_ostream_t stream = PB_OSTREAM_SIZING; + * pb_encode(&stream, MyMessage_fields, &msg); + * printf("Message size is %d\n", stream.bytes_written); + */ +#ifndef PB_NO_ERRMSG +#define PB_OSTREAM_SIZING {0,0,0,0,0} +#else +#define PB_OSTREAM_SIZING {0,0,0,0} +#endif + +/* Function to write into a pb_ostream_t stream. You can use this if you need + * to append or prepend some custom headers to the message. + */ +bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Encode field header based on type and field number defined in the field + * structure. Call this from the callback before writing out field contents. */ +bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field); + +/* Encode field header by manually specifing wire type. You need to use this + * if you want to write out packed arrays from a callback field. */ +bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number); + +/* Encode an integer in the varint format. + * This works for bool, enum, int32, int64, uint32 and uint64 field types. */ +bool pb_encode_varint(pb_ostream_t *stream, uint64_t value); + +/* Encode an integer in the zig-zagged svarint format. + * This works for sint32 and sint64. */ +bool pb_encode_svarint(pb_ostream_t *stream, int64_t value); + +/* Encode a string or bytes type field. For strings, pass strlen(s) as size. */ +bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size); + +/* Encode a fixed32, sfixed32 or float value. + * You need to pass a pointer to a 4-byte wide C variable. */ +bool pb_encode_fixed32(pb_ostream_t *stream, const void *value); + +/* Encode a fixed64, sfixed64 or double value. + * You need to pass a pointer to a 8-byte wide C variable. */ +bool pb_encode_fixed64(pb_ostream_t *stream, const void *value); + +/* Encode a submessage field. + * You need to pass the pb_field_t array and pointer to struct, just like + * with pb_encode(). This internally encodes the submessage twice, first to + * calculate message size and then to actually write it out. + */ +bool pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/external/nrf_cc310/Doxyfile b/external/nrf_cc310/Doxyfile new file mode 100644 index 0000000..e471d39 --- /dev/null +++ b/external/nrf_cc310/Doxyfile @@ -0,0 +1,11 @@ +@INCLUDE_PATH = /build/HUSS-CBT4-JOB1/ext/arm_cc310/arm-sw-cc310-1.2.0.1294/doxygen/ +@INCLUDE = doxygen_cc310.conf + +PROJECT_NAME = "ARM TrustZone CryptoCell 310 TEE API Documentation" +PROJECT_LOGO = "/build/HUSS-CBT4-JOB1/ext/arm_cc310/arm-sw-cc310-1.2.0.1294/doxygen/doxywrapper/ARM_Logo.png" +HTML_HEADER = "/build/HUSS-CBT4-JOB1/ext/arm_cc310/arm-sw-cc310-1.2.0.1294/doxygen/doxywrapper/header.html" +HTML_FOOTER = "/build/HUSS-CBT4-JOB1/ext/arm_cc310/arm-sw-cc310-1.2.0.1294/doxygen/doxywrapper/footer.html" +HTML_STYLESHEET = "/build/HUSS-CBT4-JOB1/ext/arm_cc310/arm-sw-cc310-1.2.0.1294/doxygen/doxywrapper/sasi_doxygen.css" + +INPUT = /build/HUSS-CBT4-JOB1/build/release/runtime/include +OUTPUT_DIRECTORY = runtime/docs/external/ diff --git a/external/nrf_cc310/Doxyfile.internal b/external/nrf_cc310/Doxyfile.internal new file mode 100644 index 0000000..69a8c28 --- /dev/null +++ b/external/nrf_cc310/Doxyfile.internal @@ -0,0 +1,25 @@ +@INCLUDE_PATH = /build/HUSS-CBT4-JOB1/ext/arm_cc310/arm-sw-cc310-1.2.0.1294/doxygen/ +@INCLUDE = doxygen_cc310.conf + +PROJECT_NAME = "ARM TrustZone CryptoCell 310 TEE API Documentation - INTERNAL" +PROJECT_LOGO = "/build/HUSS-CBT4-JOB1/ext/arm_cc310/arm-sw-cc310-1.2.0.1294/doxygen/doxywrapper/ARM_Logo.png" +HTML_HEADER = "/build/HUSS-CBT4-JOB1/ext/arm_cc310/arm-sw-cc310-1.2.0.1294/doxygen/doxywrapper/header.html" +HTML_FOOTER = "/build/HUSS-CBT4-JOB1/ext/arm_cc310/arm-sw-cc310-1.2.0.1294/doxygen/doxywrapper/footer.html" +HTML_STYLESHEET = "/build/HUSS-CBT4-JOB1/ext/arm_cc310/arm-sw-cc310-1.2.0.1294/doxygen/doxywrapper/sasi_doxygen.css" + +INPUT = /build/HUSS-CBT4-JOB1/ext/arm_cc310/arm-sw-cc310-1.2.0.1294/ +RECURSIVE = YES +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_PACKAGE = YES +EXTRACT_STATIC = YES +INTERNAL_DOCS = YES +HAVE_DOT = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = YES +CALLER_GRAPH = YES +DIRECTORY_GRAPH = YES +GENERATE_ECLIPSEHELP = YES +ECLIPSE_DOC_ID = com.nordic.cc310 +OUTPUT_DIRECTORY = runtime/docs/internal diff --git a/external/nrf_cc310/common/integration_test_plat_defs.h b/external/nrf_cc310/common/integration_test_plat_defs.h new file mode 100644 index 0000000..0963e08 --- /dev/null +++ b/external/nrf_cc310/common/integration_test_plat_defs.h @@ -0,0 +1,73 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + +#include +#include "SEGGER_RTT.h" +#include "ssi_pal_types_plat.h" + +#if DX_LINUX_PLATFORM +extern uint32_t g_free_mem_addr; +extern uint32_t *g_test_stack_base_addr; +extern uint32_t g_rom_base_addr; +extern uint32_t g_env_rom_base_addr; +#endif + + +SaSiError_t mapEnvMemory(void); +void unmapMemory(void); +SaSiError_t integration_tests_setup(void); +void integration_tests_clear(void); + + +#define REG_BASE_ADR DX_BASE_CC +#define REG_AREA_LEN 0x20000 +#define ENV_REG_BASE_ADR DX_BASE_ENV_REGS +#define ENV_REG_AREA_LEN 0x20000 +#define SRAM_BASE_ADR 0 +#define TEST_DATA_START_ADDRESS sizeof(CRYS_RND_State_t)+sizeof(CRYS_RND_WorkBuff_t) + +/* Zynq EVBs have 1GB and we reserve the memory at offset 768M */ +#define FREE_MEM_BASE_ADR 0x20020000 +#define CONTIG_FREE_MEM 0x8000 +/* Free memory is dedicated for SW image storage */ +#define BOOT_FREE_MEM_BASE_ADR FREE_MEM_BASE_ADR +#define BOOT_FREE_MEM_LEN 0x500000 + +/* user space follows the free memory, and uses for stack and workspace memory */ +#define PTHREAD_STACK_BASE_ADR (FREE_MEM_BASE_ADR + CONTIG_FREE_MEM) +#define PTHREAD_STACK_SIZE 16*1024 + +#define WORKSPACE_BASE_ADDR (PTHREAD_STACK_BASE_ADR + PTHREAD_STACK_SIZE) + +#define INTEG_TEST_PRINT(...) SEGGER_RTT_printf(0, __VA_ARGS__) diff --git a/external/nrf_cc310/common/integration_test_plat_utils.c b/external/nrf_cc310/common/integration_test_plat_utils.c new file mode 100644 index 0000000..0d979f1 --- /dev/null +++ b/external/nrf_cc310/common/integration_test_plat_utils.c @@ -0,0 +1,120 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ +#ifdef DX_LINUX_PLATFORM +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#include "ssi_pal_types.h" + +#include "integration_test_plat_defs.h" +#include "crys_rnd.h" + +#include "nrf.h" +#include "SEGGER_RTT.h" + +/*Globals*/ +uint32_t g_free_mem_addr; +uint32_t *g_test_stack_base_addr; +uint32_t g_rom_base_addr; +uint32_t g_env_rom_base_addr; + + +CRYS_RND_WorkBuff_t* rndWorkBuff_ptr; +CRYS_RND_State_t* rndState_ptr; + +#if defined(__CC_ARM) +CRYS_RND_State_t rndState = {0}; +CRYS_RND_WorkBuff_t rndWorkBuff = {0}; +#else +CRYS_RND_State_t rndState; +CRYS_RND_WorkBuff_t rndWorkBuff; +#endif + +uint32_t* UserSpace = 0; + + +//initializatoins that need to be done prior to running the integration tests. +SaSiError_t integration_tests_setup(void) +{ + SaSiError_t ret = 0; + rndState_ptr = &rndState; + rndWorkBuff_ptr = &rndWorkBuff; + + // Initialize Segger RTT logging + + (void)SEGGER_RTT_Init(); + + INTEG_TEST_PRINT("==================== TEST START ====================\r\n"); + + //NVIC_EnableIRQ(CRYPTOCELL_IRQn); + + //NRF_CRYPTOCELL->ENABLE = 1; + + return ret; +} + + +void integration_tests_clear(void) +{ + INTEG_TEST_PRINT("==================== TEST END ====================\r\n"); + while(1) + { + __WFI(); + } +} + + +void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) +{ + (void)id; + (void)pc; + (void)info; + while(1); +} + + +void SaSi_PalAbort(const char *msg) +{ + // This function overrides SaSi_PalAbort implemented in the library. + // The library version does a NVIC_SystemReset() and has no logging. + INTEG_TEST_PRINT("CC310 abort called: %s\r\n", msg); + while(1); +} diff --git a/external/nrf_cc310/common/integration_test_ssi_data.h b/external/nrf_cc310/common/integration_test_ssi_data.h new file mode 100644 index 0000000..cafaa38 --- /dev/null +++ b/external/nrf_cc310/common/integration_test_ssi_data.h @@ -0,0 +1,304 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + +#include "ssi_pal_types.h" + +#ifdef AES_INTEGTEST +#include "ssi_aes.h" +#include "crys_aesccm.h" +#endif + +#ifdef ECC_INTEGTEST +#include "crys_ecpki_types.h" +#endif + +#ifdef HASH_INTEGTEST +#include "crys_hash.h" +#endif + +#ifdef HMAC_INTEGTEST +#include "crys_hash.h" +#include "crys_hmac.h" +#endif + +#ifdef RSA_INTEGTEST +#include "crys_rsa_types.h" +#endif + +#ifdef CHACHA_INTEGTEST +#include "crys_chacha.h" +#include "crys_poly.h" +#endif + + +#ifdef HKDF_INTEGTEST +#include "crys_hkdf.h" +#endif + +#define MAX_TEST_DATA_SIZE 256 +#define MAX_AES_CCM_DATA_SIZE_VECTOR 0x40 +#define MAX_RND_SIZE_VECTOR 0x20 + +#ifdef AES_INTEGTEST +typedef struct aesDataStuct{ + uint8_t aesTest_name[MAX_TEST_DATA_SIZE]; + uint8_t TST_KeyData[SASI_AES_KEY_MAX_SIZE_IN_BYTES]; + uint8_t TST_KeySize; + SaSiAesIv_t aesTest_IvCounter; + uint8_t aesTest_input_data[MAX_TEST_DATA_SIZE]; + uint8_t aesTest_output_data[MAX_TEST_DATA_SIZE]; + uint8_t aesTest_Expected_output_data[MAX_TEST_DATA_SIZE]; + uint16_t aesTest_DataSize; + SaSiAesOperationMode_t aesTest_OperationMode; + SaSiAesEncryptMode_t aesTest_EncDecMode; + uint32_t aesTest_OutputDataSize; +} aesDataStuct; + +typedef struct aesCCMDataStuct{ + uint8_t aesCCMTest_name[MAX_TEST_DATA_SIZE]; + CRYS_AESCCM_Key_t aesCCMTest_Key; + CRYS_AESCCM_KeySize_t aesCCMTest_KeySize; + uint8_t aesCCMTest_NData[MAX_AES_CCM_DATA_SIZE_VECTOR]; + uint32_t aesCCMTest_NDataSize; + uint8_t aesCCMTest_AddData[MAX_AES_CCM_DATA_SIZE_VECTOR]; + uint32_t aesCCMTest_AddDataSize; + uint8_t aesCCMTest_TextData[MAX_AES_CCM_DATA_SIZE_VECTOR]; + uint32_t aesCCMTest_TextdataSize; + uint8_t aesCCMTest_Expected_output_data[MAX_AES_CCM_DATA_SIZE_VECTOR]; + uint8_t aesCCMTest_Output_data[MAX_AES_CCM_DATA_SIZE_VECTOR]; + uint32_t aesCCMTest_OutputDataSize; + uint8_t aesCCMTest_Expected_MAC_output_data[MAX_AES_CCM_DATA_SIZE_VECTOR]; + uint8_t aesCCMTest_Output_MAC_data[MAX_AES_CCM_DATA_SIZE_VECTOR]; + uint32_t aesCCMTest_Output_CCM_MACSize; +} aesCCMDataStuct; +#endif + +#ifdef ECC_INTEGTEST +typedef struct eccSignDataStuct{ + uint8_t eccTest_name[MAX_TEST_DATA_SIZE]; + CRYS_ECPKI_DomainID_t eccTest_DomainID; + CRYS_ECPKI_HASH_OpMode_t eccTest_HashMode; + uint8_t eccTest_InputData[MAX_TEST_DATA_SIZE]; + uint32_t eccTest_InputDataSize; + uint8_t eccTest_PubKey[MAX_TEST_DATA_SIZE]; + uint32_t eccTest_PubKeySize; + uint8_t eccTest_PrivKey[MAX_TEST_DATA_SIZE]; + uint32_t eccTest_PrivKeySize; + uint32_t eccTest_SignitureSize; + +} eccSignDataStuct; + +typedef struct eccDHDataStuct{ + uint8_t eccDHTest_name[MAX_TEST_DATA_SIZE]; + CRYS_ECPKI_DomainID_t eccDHTest_DomainID; + uint8_t eccDHTest_PubKey1[MAX_TEST_DATA_SIZE]; + uint32_t eccDHTest_PubKeySize1; + uint8_t eccDHTest_PrivKey1[MAX_TEST_DATA_SIZE]; + uint32_t eccDHTest_PrivKeySize1; + uint8_t eccDHTest_PubKey2[MAX_TEST_DATA_SIZE]; + uint32_t eccDHTest_PubKeySize2; + uint8_t eccDHTest_PrivKey2[MAX_TEST_DATA_SIZE]; + uint32_t eccDHTest_PrivKeySize2; + +} eccDHDataStuct; +#endif + +#ifdef CHACHA_INTEGTEST +typedef struct CHACHA_DataStruct { + uint8_t testName[MAX_TEST_DATA_SIZE]; + CRYS_CHACHA_Nonce_t pIVCounter; + CRYS_CHACHA_NonceSize_t IVSize; + CRYS_CHACHA_Key_t pKey; + uint32_t initialCounter; + CRYS_CHACHA_EncryptMode_t encryptDecryptFlag; + uint8_t pDataIn[MAX_TEST_DATA_SIZE]; + uint32_t dataInSize; + uint8_t pExpectedDataOut[MAX_TEST_DATA_SIZE]; + CRYSError_t expectedRc; +} CHACHA_DataStruct; + +#define TEST_CHACHA_POLY_DATA_SIZE_MAX 272 +typedef struct CHACHA_POLY_DataStruct { + uint8_t testName[MAX_TEST_DATA_SIZE]; + CRYS_CHACHA_EncryptMode_t encryptDecryptFlag; + CRYS_CHACHA_Key_t pKey; + uint8_t pDataIn[TEST_CHACHA_POLY_DATA_SIZE_MAX]; + uint32_t dataInSize; + CRYS_CHACHA_Nonce_t pNonce; + uint8_t pAddData[TEST_CHACHA_POLY_DATA_SIZE_MAX]; + uint32_t addDataSize; + uint8_t pExpectedDataOut[TEST_CHACHA_POLY_DATA_SIZE_MAX]; + uint8_t pExpectedMac[CRYS_POLY_MAC_SIZE_IN_BYTES]; + CRYSError_t expectedRc; +} CHACHA_POLY_DataStruct_t; +#endif + +#ifdef HASH_INTEGTEST + +typedef struct hashDataStuct{ + uint8_t hashTest_Name[MAX_TEST_DATA_SIZE]; + CRYS_HASH_OperationMode_t hashTest_TST_OperationMode; + uint8_t hashTest_InputData[MAX_TEST_DATA_SIZE]; + uint32_t hashTest_InputDataSize; + CRYS_HASH_Result_t hashTest_ExpOutData; + uint32_t hashTest_ExpOutDataSize; +} hashDataStuct; +#endif + +#ifdef HMAC_INTEGTEST +typedef struct hmacDataStuct{ + uint8_t hmacTest_Name[MAX_TEST_DATA_SIZE]; + CRYS_HASH_OperationMode_t hmacTest_TST_OperationMode; + uint8_t hmacTest_Key[CRYS_HMAC_KEY_SIZE_IN_BYTES]; + uint16_t hmacTest_KeySize; + uint8_t hmacTest_InputData[MAX_TEST_DATA_SIZE]; + uint32_t hmacTest_InputDataSize; + CRYS_HASH_Result_t hmacTest_ExpOutData; + uint32_t hmacTest_ExpOutDataSize; +} hmacDataStuct; +#endif + +#ifdef RND_INTEGTEST +typedef struct rndDataStuct{ + uint8_t hmacTest_Name[MAX_TEST_DATA_SIZE]; + uint32_t rndTest_AddInputSize; + uint8_t rndTest_AddInputData[MAX_RND_SIZE_VECTOR]; + uint32_t rndTest_RandomVectorSize; + uint8_t rndTest_RandomVectorData1[MAX_RND_SIZE_VECTOR]; + uint8_t rndTest_RandomVectorData2[MAX_RND_SIZE_VECTOR]; + uint32_t rndTest_RandomVectorInRangeSize1; + uint8_t rndTest_RandomVectorInRangeData[MAX_RND_SIZE_VECTOR]; + uint32_t rndTest_RandomVectorInRangeSize2; + uint8_t rndTest_MaxVectorInRange2[MAX_RND_SIZE_VECTOR]; + uint8_t rndTest_RandomVectorInRangeData2[MAX_RND_SIZE_VECTOR]; + +} rndDataStuct; +#endif + + +#ifdef RSA_INTEGTEST + +#define TST_MAX_PRVT_EXP_SIZE_IN_BYTES 256 +#define TST_MAX_PUB_EXP_SIZE_IN_BYTES 3 +#define TST_MAX_MOD_SIZE_IN_BYTES 256 +#define TST_MAX_ENCDEC_DATA_IN_BYTES 256 +#define TST_MAX_SIGN_VERIFY_DATA_IN_BYTES 512 +#define TST_MAX_PUB_EXP_SIZE_IN_BYTES 3 +#define TST_MAX_SINGLE_RSA_SIGN_BLOCK_SIZE_IN_BYTS 16 +#define TST_LESS_DATA_FOR_PKCS1V15_ENCRYPT 11 +#define TST_LESS_DATA_FOR_OAEP_ENCRYPT_SHA1 42 +#define TST_LESS_DATA_FOR_OAEP_ENCRYPT_SHA224 58 +#define TST_LESS_DATA_FOR_OAEP_ENCRYPT_SHA256 66 +#define TST_LESS_DATA_FOR_OAEP_ENCRYPT_SHA384 98 +#define TST_LESS_DATA_FOR_OAEP_ENCRYPT_SHA512 130 +#define TST_NO_CRT 0 +#define TST_CRT_MODE 1 +#define TST_RSA_512_KEY_SIZE_IN_BYTES 64 +#define TST_RSA_1024_KEY_SIZE_IN_BYTES 128 +#define TST_LESS_DATA_FOR_PKCS1V15_ENCRYPT 11 +#define TST_LESS_DATA_FOR_OAEP_ENCRYPT_SHA1 42 +#define TST_LESS_DATA_FOR_OAEP_ENCRYPT_SHA224 58 +#define TST_LESS_DATA_FOR_OAEP_ENCRYPT_SHA256 66 +#define TST_LESS_DATA_FOR_OAEP_ENCRYPT_SHA384 98 +#define TST_LESS_DATA_FOR_OAEP_ENCRYPT_SHA512 130 + + +typedef struct rsaEncDecDataStuct{ + uint8_t rsaEncDec_Name[MAX_TEST_DATA_SIZE]; + uint8_t rsaEncDec_PrivetExponent_D[TST_MAX_PRVT_EXP_SIZE_IN_BYTES]; + uint8_t rsaEncDec_PublicExponent_E[TST_MAX_PUB_EXP_SIZE_IN_BYTES]; + uint8_t rsaEncDec_Modulus_N[TST_MAX_MOD_SIZE_IN_BYTES]; + uint8_t rsaEncDec_P[TST_MAX_PRVT_EXP_SIZE_IN_BYTES/2]; + uint8_t rsaEncDec_Q[TST_MAX_PRVT_EXP_SIZE_IN_BYTES/2]; + uint8_t rsaEncDec_dP[TST_MAX_PRVT_EXP_SIZE_IN_BYTES/2]; + uint8_t rsaEncDec_dQ[TST_MAX_PRVT_EXP_SIZE_IN_BYTES/2]; + uint8_t rsaEncDec_Qinv[TST_MAX_PRVT_EXP_SIZE_IN_BYTES/2]; + uint16_t rsaEncDec_KeySize; + uint16_t rsaEncDec_DPSize; + uint16_t rsaEncDec_PubExponentSize; + uint8_t rsaEncDec_input_data[TST_MAX_ENCDEC_DATA_IN_BYTES]; + uint8_t rsaEncDec_output_data[TST_MAX_ENCDEC_DATA_IN_BYTES]; + uint8_t rsaEncDec_Expected_output_data[TST_MAX_ENCDEC_DATA_IN_BYTES]; +} rsaEncDecDataStuct; + + +typedef struct rsaSignVerifyDataStuct{ + char rsaSignVerify_Name[MAX_TEST_DATA_SIZE]; + uint8_t rsaSignVerify_PrivetExponent_D[TST_MAX_PRVT_EXP_SIZE_IN_BYTES]; + uint8_t rsaSignVerify_PublicExponent_E[TST_MAX_PRVT_EXP_SIZE_IN_BYTES]; + uint8_t rsaSignVerify_Modulus_N[TST_MAX_MOD_SIZE_IN_BYTES]; + uint8_t rsaSignVerify_P[TST_MAX_PRVT_EXP_SIZE_IN_BYTES/2]; + uint8_t rsaSignVerify_Q[TST_MAX_PRVT_EXP_SIZE_IN_BYTES/2]; + uint8_t rsaSignVerify_dP[TST_MAX_PRVT_EXP_SIZE_IN_BYTES/2]; + uint8_t rsaSignVerify_dQ[TST_MAX_PRVT_EXP_SIZE_IN_BYTES/2]; + uint8_t rsaSignVerify_Qinv[TST_MAX_PRVT_EXP_SIZE_IN_BYTES/2]; + uint16_t rsaSignVerify_KeySize; + uint16_t rsaSignVerify_DPSize; + uint16_t rsaSignVerify_PubExponentSize; + uint16_t rsaSignVerify_SaltLength; + uint8_t rsaSignVerify_input_data[TST_MAX_SIGN_VERIFY_DATA_IN_BYTES]; + uint16_t rsaSignVerify_input_dataSize; + uint8_t rsaSignVerify_output_signiture[TST_MAX_PRVT_EXP_SIZE_IN_BYTES]; + uint8_t rsaSignVerify_hash_SHA1[CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES]; + uint8_t rsaSignVerify_hash_SHA256[CRYS_HASH_SHA256_DIGEST_SIZE_IN_BYTES]; + uint8_t rsaSignVerify_hash_SHA512[CRYS_HASH_SHA512_DIGEST_SIZE_IN_BYTES]; + +} rsaSignVerifyDataStuct; +#endif + +#ifdef HKDF_INTEGTEST +#define TST_NAME_STRING_LEN 150 + +#define TST_HKDF_MAX_IKM_SIZE 512 +#define TST_HKDF_MAX_SALT_SIZE 512 +#define TST_HKDF_MAX_INFO_SIZE 128 +#define TST_HKDF_MAX_PRK_SIZE 2048 +#define TST_HKDF_MAX_OKM_SIZE 4096 + +typedef struct hkdfDataStuct{ + char hkdf_Name[TST_NAME_STRING_LEN]; + CRYS_HKDF_HASH_OpMode_t hkdfHashMode; + uint8_t hkdf_IKM[TST_HKDF_MAX_IKM_SIZE]; + uint32_t hkdf_IKMSize; + uint8_t hkdf_Salt[TST_HKDF_MAX_SALT_SIZE]; + uint32_t hkdf_SaltSize; + uint8_t hkdf_Info[TST_HKDF_MAX_INFO_SIZE]; + uint32_t hkdf_InfoSize; + uint8_t hkdf_ExpectedPRK[TST_HKDF_MAX_PRK_SIZE]; + uint32_t hkdf_ExpectedPRKSize; + uint8_t hkdf_ExpectOKM[TST_HKDF_MAX_OKM_SIZE]; + uint32_t hkdf_LSize; +} hkdfDataStuct; + +#endif diff --git a/external/nrf_cc310/common/integration_test_ssi_defs.h b/external/nrf_cc310/common/integration_test_ssi_defs.h new file mode 100644 index 0000000..c266b65 --- /dev/null +++ b/external/nrf_cc310/common/integration_test_ssi_defs.h @@ -0,0 +1,78 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + +#define SHARED_SECRET_MAX_LENGHT 250 +#define ECC_KEY_MAX_LENGHT 0x256 +#define AES_KEY_MAX_LENGHT_IN_BYTES 0x10 + + + +#define HASH_TESTS_NUMBER 0x3 +#define AES_TESTS_NUMBER 0x4 +#define AES_CCM_TESTS_NUMBER 0x1 +#define ECC_SIGN_TESTS_NUMBER 0x2 +#define ECC_DH_TESTS_NUMBER 0x2 +#define CHACHA_TESTS_NUMBER 0xA +#define CHACHA_POLY_TESTS_NUMBER 0x2 +#define HMAC_TESTS_NUMBER 0x2 +#define RSA_ENCDEC_OEP_TESTS_NUMBER 0x2 +#define RSA_SIGN_VERIFY_OEP_TESTS_NUMBER 0x1 +#define HKDF_TESTS_NUMBER 0x8 +#define OPERATIONS_NUMBER 0x2//Integrated/noniNtegrated + + +typedef enum OperationType_enum +{ + INTEGRATED_OPERATION , + NON_INTEGRATED_OPERATION , + OperationTypeLast= 0x7FFFFFFF, + +}OperationType_t; + +typedef enum BufferType_enum +{ + NON_INPLACE_BUFFER , + INPLACE_BUFFER , + BufferTypeLast= 0x7FFFFFFF, + +}BufferType_t; + +typedef enum RSAType_enum +{ + NON_CRT_MODE , + CRT_MODE , + RSATypeLast= 0x7FFFFFFF, + +}RSAType_enum; + diff --git a/external/nrf_cc310/include/ccsw_crys_rsa_shared_types.h b/external/nrf_cc310/include/ccsw_crys_rsa_shared_types.h new file mode 100644 index 0000000..4b1e39f --- /dev/null +++ b/external/nrf_cc310/include/ccsw_crys_rsa_shared_types.h @@ -0,0 +1,144 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef SW_CRYS_RSA_SHARED_TYPES_H +#define SW_CRYS_RSA_SHARED_TYPES_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @file + * @brief This file contains the types for the CCSW RSA module. + */ + +/************************ Defines ******************************/ + +/************************************************************************/ +/* the following definitions are only relevant for RSA code on SW */ +/************************************************************************/ +/* Define the maximal allowed width of the exponentiation sliding window +in range 2...6. This define is actual for projects on soft platform. +To minimize code size use the minimum value. To optimize performance +choose the maximum value */ + +/* The valid key size in bits */ +#define SW_CRYS_RSA_MIN_VALID_KEY_SIZE_VALUE_IN_BITS 512 + +#ifndef CRYS_NO_RSA_MAX_KEY_SIZE_4096_BIT_SUPPORT +#define SW_CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS 4096 +#define SW_CRYS_RSA_MAX_KEY_GENERATION_SIZE_BITS 4096 +#else +#ifndef CRYS_NO_RSA_MAX_KEY_SIZE_3072_BIT_SUPPORT +#define SW_CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS 3072 +#define SW_CRYS_RSA_MAX_KEY_GENERATION_SIZE_BITS 3072 +#else +#define SW_CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS 2048 +#define SW_CRYS_RSA_MAX_KEY_GENERATION_SIZE_BITS 2048 +#endif +#endif + + + + + +/* Define the size of the exponentiation temp buffer, used in LLF_PKI exponentiation and NON DEPENDED on + width of the sliding window. The size defined in units equaled to maximal RSA modulus size */ +#define PKI_EXP_CONST_TEMP_BUFF_SIZE_IN_MODULUS_UNITS 7 + +#define PKI_EXP_SLIDING_WINDOW_MAX_VALUE 2 + + /* The maximum buffer size for the 'H' value */ +#define SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS ((SW_CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS + 64UL ) / 32 ) + + +/* definition of PKI_KEY_GEN_TEMP_BUFF_SIZE_WORDS IS DEPENDED on width of the sliding window*/ +#if( PKI_EXP_SLIDING_WINDOW_MAX_VALUE > 2 ) +#define PKI_KEY_GEN_TEMP_BUFF_SIZE_WORDS \ + ((4 + (1<<(PKI_EXP_SLIDING_WINDOW_MAX_VALUE-2))) * SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS) +#else +#define PKI_KEY_GEN_TEMP_BUFF_SIZE_WORDS \ + (16 * SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS) +#endif + +#ifndef PKI_EXP_WINDOW_TEMP_BUFFER_SIZE_IN_MODULUS_UNITS +#define PKI_EXP_WINDOW_TEMP_BUFFER_SIZE_IN_MODULUS_UNITS (3 + (1 << (PKI_EXP_SLIDING_WINDOW_MAX_VALUE-1))) +#endif + + +/* Define the size of the temp buffer, used in LLF_PKI exponentiation and DEPENDED on + width of the sliding window in words */ +#if (PKI_EXP_CONST_TEMP_BUFF_SIZE_IN_MODULUS_UNITS > PKI_EXP_WINDOW_TEMP_BUFFER_SIZE_IN_MODULUS_UNITS ) +#define PKI_EXP_TEMP_BUFFER_SIZE_IN_WORDS \ + (PKI_EXP_CONST_TEMP_BUFF_SIZE_IN_MODULUS_UNITS * SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS + 2 ) +#else +#define PKI_EXP_TEMP_BUFFER_SIZE_IN_WORDS \ + (PKI_EXP_WINDOW_TEMP_BUFFER_SIZE_IN_MODULUS_UNITS * SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS + 2 ) +#endif + +/* the RSA data type */ +typedef struct SW_Shared_CRYS_RSAPrimeData_t { + /* The aligned input and output data buffers */ + uint32_t DataIn[SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + uint32_t DataOut[SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + + /* #include specific fields that are used by the low level */ + struct { + union { + struct { /* Temporary buffers used for the exponent calculation */ + uint32_t Tempbuff1[PKI_EXP_TEMP_BUFFER_SIZE_IN_WORDS]; + uint32_t Tempbuff2[SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS * 2]; + /* Temporary buffer for self-test support */ + uint32_t TempBuffer[SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + }NonCrt; + + struct { /* Temporary buffers used for the exponent calculation */ + uint32_t Tempbuff1[PKI_EXP_TEMP_BUFFER_SIZE_IN_WORDS]; + uint32_t Tempbuff2[SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS * 2]; + }Crt; + }Data; + }LLF; + +}SW_Shared_CRYS_RSAPrimeData_t; + + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/external/nrf_cc310/include/crys_aesccm.h b/external/nrf_cc310/include/crys_aesccm.h new file mode 100644 index 0000000..c6a3392 --- /dev/null +++ b/external/nrf_cc310/include/crys_aesccm.h @@ -0,0 +1,315 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_AESCCM_H +#define CRYS_AESCCM_H + +#include "ssi_pal_types.h" +#include "crys_error.h" + +#include "ssi_aes.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains all of the enums and definitions that are used for the CRYS AESCCM APIs, as well as the APIs themselves. +The API supports AES-CCM and AES-CCM* as defined in ieee-802.15.4. +@defgroup crys_aesccm CryptoCell AES-CCM APIs +@{ +@ingroup cryptocell_api + + +@note +Regarding the AES-CCM*, the API supports only AES-CCM* as defined in ieee-802.15.4-2011; With the instantiations as defined in B.3.2 and the nonce as defined in 7.3.2. +in case of AES-CCM* the flow should be as follows: +
  • AES-CCM* integrated
  • +
    • CRYS_AESCCMStar_NonceGenerate
    • +
    • CRYS_AESCCMStar
+
  • AES-CCM* non-integrated
  • +
    • CRYS_AESCCMStar_NonceGenerate
    • +
    • CRYS_AESCCMStar_Init
    • +
    • CRYS_AESCCM_BlockAdata
    • +
    • CRYS_AESCCM_BlockTextData
    • +
    • CRYS_AESCCM_Finish
+*/ + +/************************ Defines ******************************/ + +/*! AES CCM context size in words.*/ +#define CRYS_AESCCM_USER_CTX_SIZE_IN_WORDS (152/4) + +/*! AES CCM maximal key size in words. */ +#define CRYS_AESCCM_KEY_SIZE_WORDS 8 + +/* nonce and AESCCM-MAC sizes definitions */ +/*! AES CCM NONCE minimal size in bytes. */ +#define CRYS_AESCCM_NONCE_MIN_SIZE_BYTES 7 +/*! AES CCM NONCE maximal size in bytes. */ +#define CRYS_AESCCM_NONCE_MAX_SIZE_BYTES 13 +/*! AES CCM MAC minimal size in bytes..*/ +#define CRYS_AESCCM_MAC_MIN_SIZE_BYTES 4 +/*! AES CCM MAC maximal size in bytes. */ +#define CRYS_AESCCM_MAC_MAX_SIZE_BYTES 16 + +/*! AES CCM star NONCE size in bytes. */ +#define CRYS_AESCCM_STAR_NONCE_SIZE_BYTES 13 +/*! AES CCM star source address size in bytes. */ +#define CRYS_AESCCM_STAR_SOURCE_ADDRESS_SIZE_BYTES 8 + +/*! AES CCM mode - CCM. */ +#define CRYS_AESCCM_MODE_CCM 0 +/*! AES CCM mode - CCM STAR. */ +#define CRYS_AESCCM_MODE_STAR 1 + + +/************************ Typedefs ****************************/ +/*! AES CCM key sizes. */ +typedef enum { + /*! Key size 128 bits. */ + CRYS_AES_Key128BitSize = 0, + /*! Key size 192 bits. */ + CRYS_AES_Key192BitSize = 1, + /*! Key size 256 bits. */ + CRYS_AES_Key256BitSize = 2, + /*! Key size 512 bits. */ + CRYS_AES_Key512BitSize = 3, + /*! Number of optional key sizes. */ + CRYS_AES_KeySizeNumOfOptions, + /*! Reserved. */ + CRYS_AES_KeySizeLast = 0x7FFFFFFF, + +}CRYS_AESCCM_KeySize_t; + +/*! AES_CCM key buffer definition.*/ +typedef uint8_t CRYS_AESCCM_Key_t[CRYS_AESCCM_KEY_SIZE_WORDS * sizeof(uint32_t)]; +/*! AES_CCM MAC buffer definition.*/ +typedef uint8_t CRYS_AESCCM_Mac_Res_t[SASI_AES_BLOCK_SIZE_IN_BYTES]; + +/*! AES_CCM_STAR source address buffer defintion. */ +typedef uint8_t CRYS_AESCCMStar_SourceAddress_t[CRYS_AESCCM_STAR_SOURCE_ADDRESS_SIZE_BYTES]; +/*! AES_CCM_STAR Nonce buffer defintion. */ +typedef uint8_t CRYS_AESCCMStar_Nonce_t[CRYS_AESCCM_STAR_NONCE_SIZE_BYTES]; + +/******************* Context Structure ***********************/ +/*! The user's context structure - the argument type that is passed by the user to the AES CCM APIs */ +typedef struct CRYS_AESCCM_UserContext_t +{ + /*! AES CCM context buffer for internal usage. */ + uint32_t buff[CRYS_AESCCM_USER_CTX_SIZE_IN_WORDS]; +}CRYS_AESCCM_UserContext_t; + + +/************************ Public Functions **********************/ + +/*! +@brief This function initializes the AES CCM context. + +It formats of the input data, calculates AES-MAC value for the formatted B0 block containing control information and +CCM unique value (Nonce), and initializes the AES context structure including the initial CTR0 value. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CRYSError_t CC_AESCCM_Init( + CRYS_AESCCM_UserContext_t *ContextID_ptr, /*!< [in] Pointer to the AES context buffer that is allocated by the user and is used for + the AES operation. */ + SaSiAesEncryptMode_t EncrDecrMode, /*!< [in] Flag specifying whether Encrypt (::SASI_AES_ENCRYPT) or Decrypt + (::SASI_AES_DECRYPT) operation should be performed. */ + CRYS_AESCCM_Key_t CCM_Key, /*!< [in] Pointer to the AES-CCM key. */ + CRYS_AESCCM_KeySize_t KeySizeId, /*!< [in] Enumerator defining the key size (only 128 bit is valid). */ + uint32_t AdataSize, /*!< [in] Full byte length of additional (associated) data. If set to zero, + calling ::CRYS_AESCCM_BlockAdata on the same context would return an error. */ + uint32_t TextSizeQ, /*!< [in] Full length of plain text data. */ + uint8_t *N_ptr, /*!< [in] Pointer to the Nonce. */ + uint8_t SizeOfN, /*!< [in] Nonce byte size. The valid values depend on the ccm mode: +
  • CCM: valid values = [7 .. 13].
  • +
  • CCM*: valid values = [13].
*/ + uint8_t SizeOfT, /*!< [in] AES-CCM MAC (tag) byte size. The valid values depend on the ccm mode: +
  • CCM: valid values = [4, 6, 8, 10, 12, 14, 16].
  • +
  • CCM*: valid values = [0, 4, 8, 16].
*/ + uint32_t ccmMode /*!< [in] Flag specifying whether AES-CCM or AES-CCM* should be performed. */ +); + +/*! Macro defintion for CRYS_AESCCM_Init (AES CCM non-star implementation). */ +#define CRYS_AESCCM_Init(ContextID_ptr, EncrDecrMode, CCM_Key, KeySizeId, AdataSize, TextSizeQ, N_ptr, SizeOfN, SizeOfT) \ + CC_AESCCM_Init(ContextID_ptr, EncrDecrMode, CCM_Key, KeySizeId, AdataSize, TextSizeQ, N_ptr, SizeOfN, SizeOfT, CRYS_AESCCM_MODE_CCM) + +/*! Macro defintion CRYS_AESCCMStar_Init (AES CCM star implementation). */ +#define CRYS_AESCCMStar_Init(ContextID_ptr, EncrDecrMode, CCM_Key, KeySizeId, AdataSize, TextSizeQ, N_ptr, SizeOfN, SizeOfT) \ + CC_AESCCM_Init(ContextID_ptr, EncrDecrMode, CCM_Key, KeySizeId, AdataSize, TextSizeQ, N_ptr, SizeOfN, SizeOfT, CRYS_AESCCM_MODE_STAR) + +/*! +@brief This function receives a CCM context and a block of additional data, and adds it to the AES MAC +calculation. +This API can be called only once per operation context. It should not be called in case AdataSize was set to +zero in ::CC_AESCCM_Init. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CRYSError_t CRYS_AESCCM_BlockAdata( + CRYS_AESCCM_UserContext_t *ContextID_ptr, /*!< [in] Pointer to the context buffer. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the additional input data. The buffer must be contiguous. */ + uint32_t DataInSize /*!< [in] Byte size of the additional data. Must match AdataSize parameter provided to + ::CRYS_AESCCM_Init. */ +); + +/*! +@brief This function can be invoked for any block of Text data whose size is a multiple of 16 bytes, +excluding the last block that must be processed by ::CRYS_AESCCM_Finish. +
  • If encrypting: + Continues calculation of the intermediate AES_MAC value of the text data, while simultaneously encrypting the text data using AES_CTR, + starting from CTR value = CTR0+1.
  • +
  • If decrypting: + Continues decryption of the text data, while calculating the intermediate AES_MAC value of decrypted data.
+ +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CRYSError_t CRYS_AESCCM_BlockTextData( + CRYS_AESCCM_UserContext_t *ContextID_ptr, /*!< [in] Pointer to the context buffer. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the additional input data. The buffer must be contiguous. */ + uint32_t DataInSize, /*!< [in] Byte size of the text data block. Must be a multiple of 16 bytes. */ + uint8_t *DataOut_ptr /*!< [out] Pointer to the output data. The size of the output buffer must be at least DataInSize. + The buffer must be contiguous. */ +); + +/*! +@brief This function must be the last to be called on the text data. +It can either be called on the entire text data (if transferred as one block), or on the last block of the text data, +even if total size of text data is equal to 0. +It performs the same operations as ::CRYS_AESCCM_BlockTextData, but additionally: +
  • If encrypting:
  • +
    • If the size of text data is not in multiples of 16 bytes, it pads the remaining bytes with zeros to a full 16-bytes block and + processes the data using AES_MAC and AES_CTR algorithms.
    • +
    • Encrypts the AES_MAC result with AES_CTR using the CTR0 value saved in the context and places the SizeOfT bytes of MAC (tag) + at the end.
+
  • If decrypting:
  • +
    • Processes the text data, except for the last SizeOfT bytes (tag), using AES_CTR and then AES_MAC algorithms.
    • +
    • Encrypts the calculated MAC using AES_CTR based on the saved CTR0 value, and compares it with SizeOfT last bytes of input data (i.e. + tag value).
    • +
    • The function saves the validation result (Valid/Invalid) in the context.
    • +
    • Returns (as the error code) the final CCM-MAC verification result.
+ +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CEXPORT_C CRYSError_t CRYS_AESCCM_Finish( + CRYS_AESCCM_UserContext_t *ContextID_ptr, /*!< [in] Pointer to the context buffer. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the last input data. The buffer must be contiguous. */ + uint32_t DataInSize, /*!< [in] Byte size of the last text data block. Can be zero. */ + uint8_t *DataOut_ptr, /*!< [in] Pointer to the output (cipher or plain text data) data. The buffer must + be contiguous. If DataInSize = 0, output buffer is not required. */ + CRYS_AESCCM_Mac_Res_t MacRes, /*!< [in] MAC result buffer pointer. */ + uint8_t *SizeOfT /*!< [out] AES-CCM MAC byte size as defined in CRYS_AESCCM_Init. */ +); + +/****************************************************************************************************/ +/******** AESCCM FUNCTION ******/ +/****************************************************************************************************/ +/*! +@brief AES CCM combines Counter mode encryption with CBC-MAC authentication. +Input to CCM includes the following elements: +
  • Payload - text data that is both authenticated and encrypted.
  • +
  • Associated data (Adata) - data that is authenticated but not encrypted, e.g., a header.
  • +
  • Nonce - A unique value that is assigned to the payload and the associated data.
+ +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CIMPORT_C CRYSError_t CC_AESCCM( + SaSiAesEncryptMode_t EncrDecrMode, /*!< [in] A flag specifying whether an AES Encrypt (::SASI_AES_ENCRYPT) or Decrypt + (::SASI_AES_DECRYPT) operation should be performed. */ + CRYS_AESCCM_Key_t CCM_Key, /*!< [in] Pointer to AES-CCM key. */ + CRYS_AESCCM_KeySize_t KeySizeId, /*!< [in] Enumerator defining the key size (only 128 bit is valid). */ + uint8_t *N_ptr, /*!< [in] Pointer to the Nonce. */ + uint8_t SizeOfN, /*!< [in] Nonce byte size. The valid values depend on the ccm mode: +
  • CCM: valid values = [7 .. 13].
  • +
  • CCM*: valid values = [13].
*/ + uint8_t *ADataIn_ptr, /*!< [in] Pointer to the additional input data. The buffer must be contiguous. */ + uint32_t ADataInSize, /*!< [in] Byte size of the additional data. */ + uint8_t *TextDataIn_ptr, /*!< [in] Pointer to the plain-text data for encryption or cipher-text data for decryption. + The buffer must be contiguous. */ + uint32_t TextDataInSize, /*!< [in] Byte size of the full text data. */ + uint8_t *TextDataOut_ptr, /*!< [out] Pointer to the output (cipher or plain text data according to encrypt-decrypt mode) + data. The buffer must be contiguous. */ + uint8_t SizeOfT, /*!< [in] AES-CCM MAC (tag) byte size. The valid values depend on the ccm mode: +
  • CCM: valid values = [4, 6, 8, 10, 12, 14, 16].
  • +
  • CCM*: valid values = [0, 4, 8, 16].
*/ + CRYS_AESCCM_Mac_Res_t Mac_Res, /*!< [in/out] Pointer to the MAC result buffer. */ + uint32_t ccmMode /*!< [in] Flag specifying whether AES-CCM or AES-CCM* should be performed. */ +); + +/*! Macro defintion for CRYS_AESCCM (AES CCM non-star implementation). */ +#define CRYS_AESCCM(EncrDecrMode, CCM_Key, KeySizeId, N_ptr, SizeOfN, ADataIn_ptr, ADataInSize, TextDataIn_ptr, TextDataInSize, TextDataOut_ptr, SizeOfT, Mac_Res) \ + CC_AESCCM(EncrDecrMode, CCM_Key, KeySizeId, N_ptr, SizeOfN, ADataIn_ptr, ADataInSize, TextDataIn_ptr, TextDataInSize, TextDataOut_ptr, SizeOfT, Mac_Res, CRYS_AESCCM_MODE_CCM) + +/*! Macro defintion for CRYS_AESCCMStar (AES CCM star implementation). */ +#define CRYS_AESCCMStar(EncrDecrMode, CCM_Key, KeySizeId, N_ptr, SizeOfN, ADataIn_ptr, ADataInSize, TextDataIn_ptr, TextDataInSize, TextDataOut_ptr, SizeOfT, Mac_Res) \ + CC_AESCCM(EncrDecrMode, CCM_Key, KeySizeId, N_ptr, SizeOfN, ADataIn_ptr, ADataInSize, TextDataIn_ptr, TextDataInSize, TextDataOut_ptr, SizeOfT, Mac_Res, CRYS_AESCCM_MODE_STAR) + + +/*! +@brief This function receives the MAC source address, the frame counter and the MAC size +and returns the required nonce for AES-CCM* as defined in ieee-802.15.4. +This API should be called before CRYS_AESCCMStar and CRYS_AESCCMStar_Init, +and the generated nonce should be provided to these functions. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CRYSError_t CRYS_AESCCMStar_NonceGenerate( + CRYS_AESCCMStar_SourceAddress_t srcAddr, /*!< [in] The MAC address in EUI-64 format. */ + uint32_t FrameCounter, /*!< [in] The MAC frame counter. */ + uint8_t SizeOfT, /*!< [in] AES-CCM* MAC (tag) byte size. Valid values = [0,4,8,16]. */ + CRYS_AESCCMStar_Nonce_t nonce /*!< [out] The required nonce for AES-CCM*. */ +); + +#ifdef __cplusplus +} +#endif + +/** +@} + */ + +#endif /*#ifndef CRYS_AESCCM_H*/ + diff --git a/external/nrf_cc310/include/crys_aesccm_error.h b/external/nrf_cc310/include/crys_aesccm_error.h new file mode 100644 index 0000000..a2b20a0 --- /dev/null +++ b/external/nrf_cc310/include/crys_aesccm_error.h @@ -0,0 +1,134 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef CRYS_AESCCM_ERROR_H +#define CRYS_AESCCM_ERROR_H + + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the CRYS AESCCM errors. +@defgroup crys_aesccm_error CryptoCell AES-CCM specific errors +@{ +@ingroup crys_aesccm +*/ + +/************************ Defines ******************************/ + +/*! CRYS AESCCM module errors. CRYS_AESCCM_MODULE_ERROR_BASE = 0x00F01500. */ +/*! Invalid context pointer. */ +#define CRYS_AESCCM_INVALID_USER_CONTEXT_POINTER_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x00UL) +/*! Illegal key size. */ +#define CRYS_AESCCM_ILLEGAL_KEY_SIZE_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x01UL) +/*! Invalid key pointer. */ +#define CRYS_AESCCM_INVALID_KEY_POINTER_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x02UL) +/*! Invalid encryption mode. */ +#define CRYS_AESCCM_INVALID_ENCRYPT_MODE_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x03UL) +/*! Context is corrupted. */ +#define CRYS_AESCCM_USER_CONTEXT_CORRUPTED_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x04UL) +/*! Invalid data in pointer. */ +#define CRYS_AESCCM_DATA_IN_POINTER_INVALID_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x05UL) +/*! Invalid data out pointer. */ +#define CRYS_AESCCM_DATA_OUT_POINTER_INVALID_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x06UL) +/*! Illegal data in size. */ +#define CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL (CRYS_AESCCM_MODULE_ERROR_BASE + 0x07UL) +/*! Illegal data in or data out address. */ +#define CRYS_AESCCM_DATA_OUT_DATA_IN_OVERLAP_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x08UL) +/*! Illegal data out size. */ +#define CRYS_AESCCM_DATA_OUT_SIZE_INVALID_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x09UL) +/*! Illegal call to process additional data. */ +#define CRYS_AESCCM_ADDITIONAL_BLOCK_NOT_PERMITTED_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x0AUL) +/*! Illegal dma buffer type. */ +#define CRYS_AESCCM_ILLEGAL_DMA_BUFF_TYPE_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x0BUL) +/*! Illegal parameter size. */ +#define CRYS_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x0CUL) +/*! Invalid parameter pointer. */ +#define CRYS_AESCCM_ILLEGAL_PARAMETER_PTR_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x0DUL) +/*! Invalid data type. */ +#define CRYS_AESCCM_ILLEGAL_DATA_TYPE_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x0EUL) +/*! CCM MAC compare failure. */ +#define CRYS_AESCCM_CCM_MAC_INVALID_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x0FUL) +/*! Illegal operation. */ +#define CRYS_AESCCM_LAST_BLOCK_NOT_PERMITTED_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x10UL) +/*! Illegal parameter. */ +#define CRYS_AESCCM_ILLEGAL_PARAMETER_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x11UL) +/*! Additional data input size is incorrect. */ +#define CRYS_AESCCM_NOT_ALL_ADATA_WAS_PROCESSED_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x13UL) +/*! Text data input size is incorrect. */ +#define CRYS_AESCCM_NOT_ALL_DATA_WAS_PROCESSED_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x14UL) +/*! Additional data was already processed (must be processed only once). */ +#define CRYS_AESCCM_ADATA_WAS_PROCESSED_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x15UL) +/*! Illegal Nonce size. */ +#define CRYS_AESCCM_ILLEGAL_NONCE_SIZE_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x16UL) +/*! Illegal tag (MAC) size. */ +#define CRYS_AESCCM_ILLEGAL_TAG_SIZE_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x17UL) + +/*! Illegal context size. */ +#define CRYS_AESCCM_CTX_SIZES_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x28UL) +/*! Illegal parameters. */ +#define CRYS_AESCCM_ILLEGAL_PARAMS_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x29UL) +/*! AESCCM is not supported. */ +#define CRYS_AESCCM_IS_NOT_SUPPORTED (CRYS_AESCCM_MODULE_ERROR_BASE + 0xFFUL) + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs *****************************/ + +/************************ Public Variables *********************/ + +/************************ Public Functions *********************/ + +#ifdef __cplusplus +} +#endif + +/** +@} + */ + +#endif + + diff --git a/external/nrf_cc310/include/crys_chacha.h b/external/nrf_cc310/include/crys_chacha.h new file mode 100644 index 0000000..d303a38 --- /dev/null +++ b/external/nrf_cc310/include/crys_chacha.h @@ -0,0 +1,234 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains all of the enums and definitions that are used for the + CRYS CHACHA APIs, as well as the APIs themselves. +@defgroup crys_chacha CryptoCell CHACHA APIs +@{ +@ingroup cryptocell_api +*/ +#ifndef CRYS_CHACHA_H +#define CRYS_CHACHA_H + + +#include "ssi_pal_types.h" +#include "crys_error.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************ Defines ******************************/ +/*! CHACHA user's context size in words. */ +#define CRYS_CHACHA_USER_CTX_SIZE_IN_WORDS 17 + +/*! CHACHA block size in words. */ +#define CRYS_CHACHA_BLOCK_SIZE_IN_WORDS 16 +/*! CHACHA block size in bytes. */ +#define CRYS_CHACHA_BLOCK_SIZE_IN_BYTES (CRYS_CHACHA_BLOCK_SIZE_IN_WORDS * sizeof(uint32_t)) + +/*! Nonce buffer max size in words. */ +#define CRYS_CHACHA_NONCE_MAX_SIZE_IN_WORDS 3 +/*! Nonce buffer max size in bytes. */ +#define CRYS_CHACHA_NONCE_MAX_SIZE_IN_BYTES (CRYS_CHACHA_NONCE_MAX_SIZE_IN_WORDS * sizeof(uint32_t)) + +/*! CHACHA KEY maximal size in words. */ +#define CRYS_CHACHA_KEY_MAX_SIZE_IN_WORDS 8 +/*! CHACHA KEY maximal size in bytes. */ +#define CRYS_CHACHA_KEY_MAX_SIZE_IN_BYTES (CRYS_CHACHA_KEY_MAX_SIZE_IN_WORDS * sizeof(uint32_t)) + +/************************ Enums ********************************/ + +/*! Enum defining the CHACHA Encrypt or Decrypt operation mode. */ +typedef enum { + /*! CHACHA encrypt mode. */ + CRYS_CHACHA_Encrypt = 0, + /*! CHACHA decrypt mode. */ + CRYS_CHACHA_Decrypt = 1, + /*! CHACHA maximal number of operations (encrypt/decrypt). */ + CRYS_CHACHA_EncryptNumOfOptions, + + /*! Reserved. */ + CRYS_CHACHA_EncryptModeLast = 0x7FFFFFFF, + +}CRYS_CHACHA_EncryptMode_t; + +/*! Enum defining the CHACHA Nonce size in bits. */ +typedef enum { + /*! 64 bit Nonce size. */ + CRYS_CHACHA_Nonce64BitSize = 0, + /*! 96 bit Nonce size. */ + CRYS_CHACHA_Nonce96BitSize = 1, + /*! CHACHA maximal number of nonce sizes. */ + CRYS_CHACHA_NonceSizeNumOfOptions, + /*! Reserved. */ + CRYS_CHACHA_NonceSizeLast = 0x7FFFFFFF, + +}CRYS_CHACHA_NonceSize_t; + +/************************ Typedefs ****************************/ + +/*! Defines the Nonce buffer 12 bytes array. */ +typedef uint8_t CRYS_CHACHA_Nonce_t[CRYS_CHACHA_NONCE_MAX_SIZE_IN_BYTES]; + +/*! Defines the CHACHA key buffer. */ +typedef uint8_t CRYS_CHACHA_Key_t[CRYS_CHACHA_KEY_MAX_SIZE_IN_BYTES]; + + +/************************ context Structs ******************************/ + +/*! The user's context prototype - the argument type that is passed by the user + to the CHACHA API. The context saves the state of the operation and must be saved by the user + till the end of the APIs flow (for example till ::CRYS_CHACHA_Free is called). */ +typedef struct CRYS_CHACHAUserContext_t { + /* Allocated buffer must be double the size of actual context + * + 1 word for offset management */ + /*! Context buffer for internal use */ + uint32_t buff[CRYS_CHACHA_USER_CTX_SIZE_IN_WORDS]; +}CRYS_CHACHAUserContext_t; + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +/****************************************************************************************************/ + +/*! +@brief This function is used to initialize the context for CHACHA operations. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_chacha_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_CHACHA_Init( + CRYS_CHACHAUserContext_t *pContextID, /*!< [in] Pointer to the CHACHA context buffer that is allocated by the user + and is used for the CHACHA operation. */ + CRYS_CHACHA_Nonce_t pNonce, /*!< [in] A buffer containing an nonce. */ + CRYS_CHACHA_NonceSize_t nonceSize, /*!< [in] Enumerator defining the nonce size (only 64 and 96 bit are valid). */ + CRYS_CHACHA_Key_t pKey, /*!< [in] A pointer to the user's key buffer. */ + uint32_t initialCounter, /*!< [in] An initial counter. */ + CRYS_CHACHA_EncryptMode_t EncryptDecryptFlag /*!< [in] A flag specifying whether the CHACHA should perform an Encrypt operation + or a Decrypt operation. */ +); + + +/*! +@brief This function is used to process aligned blocks of CHACHA. +The data in size should be a multiple of chacha block size. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_chacha_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_CHACHA_Block( + CRYS_CHACHAUserContext_t *pContextID, /*!< [in] Pointer to the context buffer. */ + uint8_t *pDataIn, /*!< [in] A pointer to the buffer of the input data to the CHACHA. + The pointer does not need to be aligned. must not be null. */ + uint32_t dataInSize, /*!< [in] The size of the input data. + Must be a multiple of ::CRYS_CHACHA_BLOCK_SIZE_IN_BYTES bytes and must not be 0. */ + uint8_t *pDataOut /*!< [out] A pointer to the buffer of the output data from the CHACHA. + The pointer does not need to be aligned. must not be null. */ +); + + +/*! +@brief This function is used to process the remaining data of CHACHA. +The data in size should be smaller than chacha block size. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_chacha_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_CHACHA_Finish( + CRYS_CHACHAUserContext_t *pContextID, /*!< [in] Pointer to the context buffer. */ + uint8_t *pDataIn, /*!< [in] A pointer to the buffer of the input data to the CHACHA. + The pointer does not need to be aligned. If dataInSize = 0, input buffer is not required. */ + uint32_t dataInSize, /*!< [in] The size of the input data. + zero and non multiple of ::CRYS_CHACHA_BLOCK_SIZE_IN_BYTES are valid. */ + uint8_t *pDataOut /*!< [out] A pointer to the buffer of the output data from the CHACHA. + The pointer does not need to be aligned. If dataInSize = 0, output buffer is not required. */ +); + + +/*! +@brief This function is used to free the context of CHACHA operations. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_chacha_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_CHACHA_Free( + CRYS_CHACHAUserContext_t *pContextID /*!< [in] Pointer to the context buffer. */ +); + + +/*! +@brief This function is used to perform the CHACHA operation in one integrated process. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_chacha_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_CHACHA( + CRYS_CHACHA_Nonce_t pNonce, /*!< [in] A buffer containing an nonce. */ + CRYS_CHACHA_NonceSize_t nonceSize, /*!< [in] Enumerator defining the nonce size (only 64 and 96 bit are valid). */ + CRYS_CHACHA_Key_t pKey, /*!< [in] A pointer to the user's key buffer. */ + uint32_t initialCounter, /*!< [in] An initial counter. */ + CRYS_CHACHA_EncryptMode_t encryptDecryptFlag, /*!< [in] A flag specifying whether the CHACHA should perform an Encrypt operation + or a Decrypt operation. */ + uint8_t *pDataIn, /*!< [in] A pointer to the buffer of the input data to the CHACHA. + The pointer does not need to be aligned. must not be null. */ + uint32_t dataInSize, /*!< [in] The size of the input data. must not be 0. */ + uint8_t *pDataOut /*!< [out] A pointer to the buffer of the output data from the CHACHA. + The pointer does not need to be aligned. must not be null. */ +); + + +/***********************************************************************************/ + +#ifdef __cplusplus +} +#endif + +/** +@} + */ + +#endif /* #ifndef CRYS_CHACHA_H */ + + + + + diff --git a/external/nrf_cc310/include/crys_chacha_error.h b/external/nrf_cc310/include/crys_chacha_error.h new file mode 100644 index 0000000..6be2c35 --- /dev/null +++ b/external/nrf_cc310/include/crys_chacha_error.h @@ -0,0 +1,103 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_CHACHA_ERROR_H +#define CRYS_CHACHA_ERROR_H + + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the CRYS CHACHA errors. +@defgroup crys_chacha_error CryptoCell CHACHA specific errors +@{ +@ingroup crys_chacha +*/ + + + +/************************ Defines ******************************/ + +/*! The CRYS CHACHA module errors base address - 0x00F02200. */ +/*! Illegal Nonce. */ +#define CRYS_CHACHA_INVALID_NONCE_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x01UL) +/*! Illegal key size. */ +#define CRYS_CHACHA_ILLEGAL_KEY_SIZE_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x02UL) +/*! Illegal key pointer. */ +#define CRYS_CHACHA_INVALID_KEY_POINTER_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x03UL) +/*! Illegal operation mode. */ +#define CRYS_CHACHA_INVALID_ENCRYPT_MODE_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x04UL) +/*! Illegal data in pointer. */ +#define CRYS_CHACHA_DATA_IN_POINTER_INVALID_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x05UL) +/*! Illegal data out pointer. */ +#define CRYS_CHACHA_DATA_OUT_POINTER_INVALID_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x06UL) +/*! Illegal user context. */ +#define CRYS_CHACHA_INVALID_USER_CONTEXT_POINTER_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x07UL) +/*! Illegal user context size. */ +#define CRYS_CHACHA_CTX_SIZES_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x08UL) +/*! Illegal Nonce pointer. */ +#define CRYS_CHACHA_INVALID_NONCE_PTR_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x09UL) +/*! Illegal data in size. */ +#define CRYS_CHACHA_DATA_IN_SIZE_ILLEGAL (CRYS_CHACHA_MODULE_ERROR_BASE + 0x0AUL) +/*! General error. */ +#define CRYS_CHACHA_GENERAL_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x0BUL) +/*! CHACHA is not supported. */ +#define CRYS_CHACHA_IS_NOT_SUPPORTED (CRYS_CHACHA_MODULE_ERROR_BASE + 0xFFUL) + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs *****************************/ + +/************************ Public Variables *********************/ + +/************************ Public Functions *********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/crys_chacha_poly.h b/external/nrf_cc310/include/crys_chacha_poly.h new file mode 100644 index 0000000..a7f074a --- /dev/null +++ b/external/nrf_cc310/include/crys_chacha_poly.h @@ -0,0 +1,95 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains all of the enums and definitions that are used for the + CRYS CHACHA-POLY APIs, as well as the APIs themselves. +@defgroup crys_chacha_poly CryptoCell CHACHA-POLY APIs +@{ +@ingroup cryptocell_api +*/ +#ifndef CRYS_CHACHA_POLY_H +#define CRYS_CHACHA_POLY_H + + +#include "ssi_pal_types.h" +#include "crys_error.h" +#include "crys_chacha.h" +#include "crys_poly.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/*! +@brief This function is used to perform the CHACHA-POLY encryption and authentication operation. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_chacha_poly_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_CHACHA_POLY( + CRYS_CHACHA_Nonce_t pNonce, /*!< [in] A pointer to a buffer containing the nonce value. */ + CRYS_CHACHA_Key_t pKey, /*!< [in] A pointer to the user's key buffer. */ + CRYS_CHACHA_EncryptMode_t encryptDecryptFlag, /*!< [in] A flag specifying whether the CHACHA-POLY should perform an Encrypt or + Decrypt operation. */ + uint8_t *pAddData, /*!< [in] A pointer to the buffer of the additional data to the POLY. + The pointer does not need to be aligned. must not be null. */ + size_t addDataSize, /*!< [in] The size of the input data. must not be 0. */ + uint8_t *pDataIn, /*!< [in] A pointer to the buffer of the input data to the CHACHA. + The pointer does not need to be aligned. must not be null. */ + size_t dataInSize, /*!< [in] The size of the input data. must not be 0. */ + uint8_t *pDataOut, /*!< [out] A pointer to the buffer of the output data from the CHACHA. + must not be null. */ + CRYS_POLY_Mac_t macRes /*!< [in/out] Pointer to the MAC result buffer.*/ +); + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /* #ifndef CRYS_CHACHA_POLY_H */ + + + + + diff --git a/external/nrf_cc310/include/crys_chacha_poly_error.h b/external/nrf_cc310/include/crys_chacha_poly_error.h new file mode 100644 index 0000000..433d071 --- /dev/null +++ b/external/nrf_cc310/include/crys_chacha_poly_error.h @@ -0,0 +1,95 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_CHACHA_POLY_ERROR_H +#define CRYS_CHACHA_POLY_ERROR_H + + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the CRYS CHACHA POLY errors. +@defgroup crys_chacha_poly_error CryptoCell CHACHA POLY specific errors +@{ +@ingroup crys_chacha_poly +*/ + + + +/************************ Defines ******************************/ + +/*! The CRYS CHACHA POLY module errors base address - 0x00F02400. */ +/*! Invalid Additional data. */ +#define CRYS_CHACHA_POLY_ADATA_INVALID_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x01UL) +/*! Invalid input data. */ +#define CRYS_CHACHA_POLY_DATA_INVALID_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x02UL) +/*! Illegal encryption mode. */ +#define CRYS_CHACHA_POLY_ENC_MODE_INVALID_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x03UL) +/*! Illegal data size. */ +#define CRYS_CHACHA_POLY_DATA_SIZE_INVALID_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x04UL) +/*! Key generation error. */ +#define CRYS_CHACHA_POLY_GEN_KEY_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x05UL) +/*! CHACHA Key generation error. */ +#define CRYS_CHACHA_POLY_ENCRYPTION_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x06UL) +/*! Authentication error. */ +#define CRYS_CHACHA_POLY_AUTH_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x07UL) +/*! MAC comparison error. */ +#define CRYS_CHACHA_POLY_MAC_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x08UL) + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs *****************************/ + +/************************ Public Variables *********************/ + +/************************ Public Functions *********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/crys_common.h b/external/nrf_cc310/include/crys_common.h new file mode 100644 index 0000000..74c13cf --- /dev/null +++ b/external/nrf_cc310/include/crys_common.h @@ -0,0 +1,371 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef CRYS_COMMON_H +#define CRYS_COMMON_H + +#include "crys_common_error.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ + +#define CRYS_AES_SECRET_KEY_SIZE_IN_WORDS 4 + +/* the ROT13 definition - relevant only on SW low level engines compiled in the ROT mode */ +#define CRYS_COMMON_ROT_13_OFFSET 13 + + + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs *****************************/ + +/************************ Public Variables *********************/ + +/************************ Public Functions *********************/ + + + +/*********************************************************************** + ** + * @brief This function executes a reverse bytes copying from one buffer to another buffer. + * + * Overlapping of buffers is not allowed, excluding the case, when destination and source + * buffers are the same. + * Example of a 5 byte buffer: + * + * dst_ptr[4] = src_ptr[0] + * dst_ptr[3] = src_ptr[1] + * dst_ptr[2] = src_ptr[2] + * dst_ptr[1] = src_ptr[3] + * dst_ptr[0] = src_ptr[4] + * + * @param[in] dst_ptr - The pointer to destination buffer. + * @param[in] src_ptr - The pointer to source buffer. + * @param[in] size - The size in bytes. + * + */ + CRYSError_t CRYS_COMMON_ReverseMemcpy( uint8_t *dst_ptr , uint8_t *src_ptr , uint32_t size ); + + +/*********************************************************************** + ** + * @brief This function converts aligned words array to bytes array/ + * + * 1. Assumed, that input buffer is aligned to 4-bytes word and + * bytes order is set according to machine endianness. + * 2. Output buffer receives data as bytes stream from LSB to MSB. + * For increasing performance on small buffers, the output data is given + * by rounded down pointer and alignment. + * 3. This implementation is given for both Big and Little endian machines. + * + * + * @param[in] in32_ptr - The pointer to aligned input buffer. + * @param[in] out32_ptr - The 32-bits pointer to output buffer (rounded down to 4 bytes) . + * @param[in] outAlignBits - The actual output data alignment; + * @param[in] sizeWords - The size in words (sizeWords >= 1). + * + * return - no return value. + */ + void CRYS_COMMON_AlignedWordsArrayToBytes( uint32_t *in32_ptr , uint32_t *out32_ptr , + uint32_t outAlignBits, uint32_t sizeWords ); + +/***********************************************************************/ + /** + * @brief This function converts in place words byffer to bytes buffer with + * reversed endianity of output array. + * + * The function can convert: + * - big endian bytes array to words array with little endian order + * of words and backward. + * + * Note: + * 1. Endianness of each word in words buffer should be set allways + * according to processor used. + * 2. Implementation is given for both big and little endianness of + * processor. + * + * @param[in] buf_ptr - The 32-bits pointer to input/output buffer. + * @param[in] sizeWords - The size in words (sizeWords > 0). + * + * @return - no return value. + */ +void CRYS_COMMON_InPlaceConvertBytesWordsAndArrayEndianness( + uint32_t *buf_ptr, + uint32_t sizeWords); + + +/***********************************************************************/ + /** + * @brief This function converts big endianness bytes array to aligned words + * array with words order according to little endian / + * + * 1. Assumed, that input bytes order is set according + * to big endianness: MS Byte is most left, i.e. order is from + * Msb to Lsb. + * 2. Output words array should set according to + * little endianness words order: LSWord is most left, i.e. order + * is from Lsw to Msw. Order bytes in each word - according to + * 3. Implementation is given for both big and little + * endianness of processor. + * + * @param[out] out32_ptr - The 32-bits pointer to output buffer. + * @param[in] sizeOutBuffBytes - The size in bytes of output buffer, must be + * aligned to 4 bytes and not less than sizeInBytes. + * @param[in] in8_ptr - The pointer to input buffer. + * @param[in] sizeInBytes - The size in bytes of input data(sizeBytes >= 1). + * + * @return CRYSError_t - On success CRYS_OK is returned, on failure a + * value MODULE_* as defined in . + */ +CRYSError_t CRYS_COMMON_ConvertMsbLsbBytesToLswMswWords( + uint32_t *out32_ptr, + uint32_t sizeOutBuffBytes, + const uint8_t *in8_ptr, + uint32_t sizeInBytes); + + +/***********************************************************************/ + /** + * @brief This function converts LE 32bit-words array to BE bytes array. + * + * Note: The function allows output full size of the data and also output + * without leading zeros, if the user gives appropriate exact output + * size < input size. + * + * Assuming: + * 1. Output bytes order is according to big endianness: + * MS Byte is most left, i.e. order is from Msb to Lsb. + * 2. Input array words order is set according to + * little endianness words order: LSWord is most left, i.e. order + * is from Lsw to Msw. Bytes order in each word - according to + * processor endianness. + * 3. Owerlapping of buffers is not allowed, besides in + * place operation and size aligned to full words. + * 4. Implementation is given for both big and little + * endianness of processor. + * + * @param[in] out8_ptr - The bytes pointer to the output buffer. + * @param[in] sizeOutBuffBytes - The size of the data in bytes to output; must + * be not less, than sizeInBytes. + * @param[out] in32_ptr - The pointer to the input buffer. + * @param[in] sizeInpBytes - The size of the input data in bytes. The size must + * be > 0 and aligned to 4 bytes. + * + * @return CRYSError_t - On success CRYS_OK is returned, on failure a + * value MODULE_* as defined in . + */ +CRYSError_t CRYS_COMMON_ConvertLswMswWordsToMsbLsbBytes( + uint8_t *out8_ptr, + uint32_t sizeOutBytes, + uint32_t *in32_ptr, + uint32_t sizeInpBytes); + + +/***********************************************************************/ +/** + * @brief VOS_GetGlobalData get the global random key hidden inside the function + * the global data implemented for now are random key buffer and AES secret key buffer + * + * When no_rtos is declared then we allow a global data. The random key/AES secret key are hidden as static inside the function + * + * + * @param[in] Globalid select the buffer + * @param[in] GlobalDataSizeWords - the global data buffer size needed in words - this value must be a predetermined value + * @param[out] GlobalData_ptr - Pointer to the global buffer returned. The buffer must be at least GlobalDataSizeWords size + * + * @return CRYSError_t - On success CRYS_OK is returned, on failure an Error as defined in VOS_error + */ +CRYSError_t CRYS_COMMON_GetGlobalData(uint16_t Globalid, uint32_t *GlobalData_ptr, uint16_t GlobalDataSizeWords); + + +/***********************************************************************/ +/** +* @brief CRYS_COMMON_StoreGlobalData store the global random key into the global buffer hidden inside the function +* the global data implemented for now are random key buffer and AES secret key buffer +* +* +* @param[in] Globalid - random key / AES secret key +* @param[in] GlobalDataSizeWords - the global data buffer size needed in words - this value must be a predetermined value +* @param[in] GlobalData_ptr - Pointer to the global buffer to be saved. The buffer must be at least GlobalDataSizeWords size +* +* Return Value: +*/ +CRYSError_t CRYS_COMMON_StoreGlobalData(uint16_t Globalid, uint32_t *GlobalData_ptr, uint16_t GlobalDataSizeWords); + + +/***********************************************************************/ +/** + * @brief The CRYS_COMMON_CutAndSaveEndOfLliData() function saves the data from end of source + * memory, pointed by LLI table, to destination memory, and decreases the LLI table accordingly. + * + * The function executes the following major steps: + * + * 1. Starts copy bytes from last byte of last chunk of source LLI table into + * last byte of destination memory. + * 2. Continues copy bytes in reverse order while not completes copying of all amount of data. + * 3. If last chunk of source or destination data is not enough, the function crosses + * to next chunk of LLI table. + * 4. Decreases the Data size of last updated LLI entry and sets the LAST bit. + * 5. Exits with the OK code. + * + * + * @param[in] SrcLliTab_ptr - The pointer to the LLI table, containing pointers and sizes of + * chunks of source data. The table need to be aligned and placed + * in SEP SRAM. + * @param[in] SrcLliTabSize_ptr - The pointer to buffer, containing th size of the LLI table in words. + * @param[in] Dest_ptr - The destination address for copying the data. + * @param[in] DataSize - The count of bytes to copy. + * + * @return CRYSError_t - On success CRYS_OK is returned, + * - CRYS_COMMON_ERROR_IN_SAVING_LLI_DATA_ERROR + * + * NOTE: 1. Because the function is intended for internal using, it is presumed that all input parameters + * are valid. + * 2. Assumed, that copied source not may to take more than two last chunks of source memory. + */ + CRYSError_t CRYS_COMMON_CutAndSaveEndOfLliData( + uint32_t *SrcLliTab_ptr, + uint32_t *SrcLliTabSize_ptr, + uint8_t *Dst_ptr, + uint32_t DataSize); + +/***********************************************************************/ +/** + * @brief The CRYS_COMMON_CutAndSaveBeginOfLliData() function saves the data from beginning of source + * memory, pointed by LLI table, to destination memory, and decreases the LLI table accordingly. + * + * The function executes the following major steps: + * + * 1. Starts copy bytes from first byte of first chunk of source LLI table into + * destination memory. + * 2. If first chunk of source is not enough, the function crosses + * to next chunk of LLI table. + * 3. Updates LLI table pointer and size according to copied amount of data. + * 5. Exits with the OK code. + * + * @param[in/out] SrcLliTab_ptr_ptr - The pointer to pointer to the LLI table, containing pointers and + * sizes of the chunks of source data. The table need to be aligned and + * placed in SRAM. + * @param[in/out] SrcLliTabSize_ptr - The pointer to buffer, containing th size of the LLI table in words. + * @param[in] Dest_ptr - The destination address for copying the data. + * @param[in] DataSize - The count of bytes to copy. + * + * @return - no return value. + * + * NOTE: 1. Because the function is intended for internal using, it is presumed that all input parameters + * are valid. + * 2. Assumed, that copied source not may to take more than two first chunks of source memory. + */ + void CRYS_COMMON_CutAndSaveBeginOfLliData( + uint32_t **SrcLliTab_ptr_ptr, + uint32_t *SrcLliTabSize_ptr, + uint8_t *Dst_ptr, + uint32_t DataSize); + +/***********************************************************************/ + /** + * @brief This function converts 32-bit words array with little endian + * order of words to bytes array with little endian (LE) order of bytes. + * + * Assuming: no buffers overlapping, in/out pointers and sizes not equall to NULL, + the buffer size must be not less, than input data size. + * + * @param[out] out8Le - The bytes pointer to output buffer. + * @param[in] in32Le - The pointer to input 32-bit words buffer. + * @param[in] sizeInWords - The size in words of input data (sizeWords >= 0). + * + * @return CRYSError_t - On success CRYS_OK is returned, on failure a + * value MODULE_* as defined in . + */ +void CRYS_COMMON_ConvertLswMswWordsToLsbMsbBytes( + uint8_t *out8Le, + const uint32_t *in32Le, + size_t sizeInWords); + + +/***********************************************************************/ +/** + * @brief This function converts bytes array with little endian (LE) order of + * bytes to 32-bit words array with little endian order of words and bytes. + * + * Assuming: No owerlapping of buffers; in/out pointers and sizes are not equall to NULL. + * If is in-place conversion, then the size must be multiple of 4 bytes. + * @param[out] out32Le - The 32-bits pointer to output buffer. The buffer size must be + * not less, than input data size. + * @param[in] in8Le - The pointer to input buffer. + * @param[in] sizeInBytes - The size in bytes of input data(sizeBytes > 0). + * + * @return CRYSError_t - On success CRYS_OK is returned, on failure a + * value MODULE_* as defined in . + */ +void CRYS_COMMON_ConvertLsbMsbBytesToLswMswWords( + uint32_t *out32Le, + const uint8_t *in8Le, + size_t sizeInBytes); + + +/** + * The function compares value of byte vector to null. + * + * @author reuvenl (6/20/2016) + * + * @param vect - a pointer to bytes vector. + * @param sizeBytes - size of the vector. + * + * @return uint32_t - if vector's value iz zero, then returns 1, else - 0; + */ +uint32_t CRYS_COMMON_CheckIsVectorZero(uint8_t *vect, uint32_t sizeBytes); + + + + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/external/nrf_cc310/include/crys_common_error.h b/external/nrf_cc310/include/crys_common_error.h new file mode 100644 index 0000000..c8e455c --- /dev/null +++ b/external/nrf_cc310/include/crys_common_error.h @@ -0,0 +1,95 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + #ifndef CRYS_COMMON_ERROR_H +#define CRYS_COMMON_ERROR_H + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ + +/* CRYS COMMON module errors. Base address - 0x00F00D00 */ + +#define CRYS_COMMON_INIT_HW_SEM_CREATION_FAILURE (CRYS_COMMON_MODULE_ERROR_BASE + 0x0UL) +#define CRYS_COMMON_DATA_IN_POINTER_INVALID_ERROR (CRYS_COMMON_MODULE_ERROR_BASE + 0x4UL) +#define CRYS_COMMON_DATA_SIZE_ILLEGAL (CRYS_COMMON_MODULE_ERROR_BASE + 0x5UL) +#define CRYS_COMMON_DATA_OUT_DATA_IN_OVERLAP_ERROR (CRYS_COMMON_MODULE_ERROR_BASE + 0x6UL) +#define CRYS_COMMON_DATA_OUT_POINTER_INVALID_ERROR (CRYS_COMMON_MODULE_ERROR_BASE + 0x7UL) +#define CRYS_COMMON_OUTPUT_BUFF_SIZE_ILLEGAL (CRYS_COMMON_MODULE_ERROR_BASE + 0x9UL) + +#define CRYS_COMMON_TST_UTIL_CHUNK_SIZE_SMALL_ERROR (CRYS_COMMON_MODULE_ERROR_BASE + 0x10UL) +#define CRYS_COMMON_ERROR_IN_SAVING_LLI_DATA_ERROR (CRYS_COMMON_MODULE_ERROR_BASE + 0x11UL) + + +#define CRYS_COMMON_TST_UTIL_LLI_ENTRY_SIZE_TOO_SMALL_ERROR (CRYS_COMMON_MODULE_ERROR_BASE + 0x12UL) +#define CRYS_COMMON_TST_CSI_DATA_SIZE_EXCEED_ERROR (CRYS_COMMON_MODULE_ERROR_BASE + 0x13UL) +#define CRYS_COMMON_TST_CSI_MODULE_ID_OUT_OF_RANGE (CRYS_COMMON_MODULE_ERROR_BASE + 0x14UL) +#define CRYS_COMMON_TST_CSI_MEMORY_MAPPING_ERROR (CRYS_COMMON_MODULE_ERROR_BASE + 0x15UL) + +#define CRYS_COMMON_TERM_HW_SEM_DELETE_FAILURE (CRYS_COMMON_MODULE_ERROR_BASE + 0x16UL) + +#define CRYS_COMMON_TST_UTIL_NOT_INTEGER_CHAR_ERROR (CRYS_COMMON_MODULE_ERROR_BASE + 0x17UL) +#define CRYS_COMMON_TST_UTIL_BUFFER_IS_SMALL_ERROR (CRYS_COMMON_MODULE_ERROR_BASE + 0x18UL) +#define CRYS_COMMON_POINTER_NOT_ALIGNED_ERROR (CRYS_COMMON_MODULE_ERROR_BASE + 0x19UL) + + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/external/nrf_cc310/include/crys_dh.h b/external/nrf_cc310/include/crys_dh.h new file mode 100644 index 0000000..d612658 --- /dev/null +++ b/external/nrf_cc310/include/crys_dh.h @@ -0,0 +1,446 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef _CRYS_DH_H +#define _CRYS_DH_H + +#include "crys_rsa_types.h" +#include "crys_kdf.h" +#include "crys_rnd.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/*! +@file +@brief This module defines the API that supports Diffie-Hellman key exchange, as defined in [PKCS3] and in [X9.42] (key lengths 1024 and 2048 bits). +@defgroup crys_dh CryptoCell DH APIs +@{ +@ingroup cryptocell_api +*/ + + +/************************ Defines ******************************/ +/*! Defintion for DH public key.*/ +#define CRYS_DHPubKey_t CRYSRSAPubKey_t + +/*! Maximal valid key size in bits.*/ +#define CRYS_DH_MAX_VALID_KEY_SIZE_VALUE_IN_BITS CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS /*!< \internal RL restrict to 2048 */ +/*! Minimal valid key size in bits.*/ +#define CRYS_DH_MIN_VALID_KEY_SIZE_VALUE_IN_BITS 1024 /*!< Size limitation according to ANSI standard */ +/*! Maximal modulus size in bytes.*/ +#define CRYS_DH_MAX_MOD_SIZE_IN_BYTES (CRYS_DH_MAX_VALID_KEY_SIZE_VALUE_IN_BITS / SASI_BITS_IN_BYTE) +/*! Maximal modulus size in words.*/ +#define CRYS_DH_MAX_MOD_SIZE_IN_WORDS (CRYS_DH_MAX_MOD_SIZE_IN_BYTES/sizeof(uint32_t)) + +/*! Modulus buffer size in words.*/ +#define CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS (CRYS_DH_MAX_MOD_SIZE_IN_WORDS + 2) +/*! Maximal domain generation size in bits.*/ +#define CRYS_DH_DOMAIN_GENERATION_MAX_SIZE_BITS CRYS_RSA_MAX_KEY_GENERATION_SIZE_BITS /*!< \internal RL restrict to 2048 */ + +/*! Defintion for DH primitives data.*/ +#define CRYS_DHPrimeData_t CRYS_RSAPrimeData_t +/*! Defintion for DH public key.*/ +#define CRYS_DHUserPubKey_t CRYS_RSAUserPubKey_t +/*! Defintion for DH other info.*/ +#define CRYS_DH_OtherInfo_t CRYS_KDF_OtherInfo_t + +/*! Keying data size is in bytes*/ +#define CRYS_DH_MAX_SIZE_OF_KEYING_DATA CRYS_KDF_MAX_SIZE_OF_KEYING_DATA + +/************************ Enums ********************************/ + +/*! DH operations mode */ +typedef enum +{ + /*! PKCS3 operation mode. */ + CRYS_DH_PKCS3_mode = 0, + /*! ANSI X942 operation mode. */ + CRYS_DH_ANSI_X942_mode = 1, + /*! Total number of operation modes. */ + CRYS_DH_NumOfModes, + + /*! Reserved. */ + CRYS_DH_OpModeLast = 0x7FFFFFFF, + +}CRYS_DH_OpMode_t; + +/*! HASH operation modes */ +typedef enum +{ + /*! SHA1 operation mode. */ + CRYS_DH_HASH_SHA1_mode = CRYS_HASH_SHA1_mode, + /*! SHA224 operation mode. */ + CRYS_DH_HASH_SHA224_mode = CRYS_HASH_SHA224_mode, + /*! SHA256 operation mode. */ + CRYS_DH_HASH_SHA256_mode = CRYS_HASH_SHA256_mode, + /*! SHA384 operation mode. */ + CRYS_DH_HASH_SHA384_mode = CRYS_HASH_SHA384_mode, + /*! SHA512 operation mode. */ + CRYS_DH_HASH_SHA512_mode = CRYS_HASH_SHA512_mode, + /*! MD5 operation mode (not used in DH). */ + CRYS_DH_HASH_MD5_mode = CRYS_HASH_MD5_mode, /*!< \internal not used in DH */ + /*! Total number of HASH modes. */ + CRYS_DH_HASH_NumOfModes = CRYS_HASH_MD5_mode, + /*! Reserved. */ + CRYS_DH_HASH_OperationModeLast = 0x7FFFFFFF, + +}CRYS_DH_HASH_OpMode_t; + +/*! Key derivation modes. */ +typedef enum +{ + /*! ASN1 derivation mode.*/ + CRYS_DH_ASN1_Der_mode = CRYS_KDF_ASN1_DerivMode, + /*! Concatination derivation mode.*/ + CRYS_DH_Concat_Der_mode = CRYS_KDF_ConcatDerivMode, + /*! X963 derivation mode.*/ + CRYS_DH_X963_DerMode = CRYS_KDF_ConcatDerivMode, + /*! Reserved. */ + CRYS_DH_DerivationFunc_ModeLast= 0x7FFFFFFF, + +}CRYS_DH_DerivationFunc_Mode; + + +/************************ Typedefs *************************************/ +/*! Temporary buffer structure for internal usage.*/ +typedef struct +{ + /*! Temporary primitives data */ + CRYS_DHPrimeData_t PrimeData; + /*! Public key. */ + CRYS_DHPubKey_t PubKey; + /*! Temporary buffer for internal usage. */ + uint32_t TempBuff[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; +} CRYS_DH_ExpTemp_t; + +/*! Temporary buffer structure for internal usage. */ +typedef struct +{ + /*! Temporary primitives data */ + CRYS_DHPrimeData_t PrimeData; + /*! User's public key. */ + CRYS_DHUserPubKey_t UserPubKey; + /*! Temporary buffer for internal usage. */ + uint32_t TempBuff[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; +} CRYS_DH_Temp_t; + +/*! Temporary buffer structure for internal usage. */ +typedef struct +{ + /*! Temporary primitives data */ + CRYS_DHPrimeData_t PrimeData; + /*! User's public key. */ + CRYS_DHUserPubKey_t UserPubKey; + /*! Temporary buffer for internal usage. */ + uint32_t TempBuff[2*CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; +} CRYS_DH_HybrTemp_t; + +/*! Defintion of buffer used for FIPS Known Answer Tests. */ +typedef struct +{ + /*! Public key. */ + CRYS_DHUserPubKey_t pubKey; + /*! Temporary primitives data */ + CRYS_DHPrimeData_t primeData; + /*! Buffer for the secret value.*/ + uint8_t secretBuff[CRYS_DH_MIN_VALID_KEY_SIZE_VALUE_IN_BITS/SASI_BITS_IN_BYTE]; // KAT tests uses 1024 bit key +} CRYS_DH_FipsKat_t; + + +/************************ Structs **************************************/ + +/************************ Public Variables ******************************/ + +/************************ Public Functions ******************************/ + +/*******************************************************************************************/ + +/*! +@brief This function has two purposes: +
  1. Randomly generate the client private key according to the choosen version [PKCS3] or [ANSI X9.42].
  2. +
  3. Computes the client public key as follows: ClientPub = Generator^Prv mod Prime, where '^' is the symbol of exponentiation.
+This function should not be called directly. Instead, use the macros ::CRYS_DH_PKCS3_GeneratePubPrv and ::CRYS_DH_ANSI_X942_GeneratePubPrv. +\note +All buffer parameters should be in Big-Endian form. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_dh_error.h, crys_rnd_error.h or crys_rsa_error.h. + */ +CIMPORT_C CRYSError_t _DX_DH_GeneratePubPrv( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + uint8_t *Generator_ptr, /*!< [in] Pointer to the Generator octet string. */ + uint16_t GeneratorSize, /*!< [in] The size of the Generator string (in bytes). */ + uint8_t *Prime_ptr, /*!< [in] Pointer to the Prime octet string P (used as modulus in the algorithm). */ + uint16_t PrimeSize, /*!< [in] The size of the Prime string in bytes. */ + uint16_t L, /*!< [in] Exact size in bits of the Prime to be generated (relevant only for [PKCS3]): +
  • If L!=0, force the private key to be [2^(L-1) ? Prv < 2^L], where '^' + indicates exponentiation.
  • +
  • If L = 0 then [0 < Prv < P-1].
*/ + uint8_t *Q_ptr, /*!< [in] Relevant only for [ANSI X9.42] - Pointer to the Q octet string in the range: + 1 <= Prv <= Q-1 or 1 < Prv < Q-1. */ + uint16_t QSize, /*!< [in] Relevant only for [ANSI X9.42] - Size of the Q string (in bytes). */ + CRYS_DH_OpMode_t DH_mode, /*!< [in] An enumerator declaring whether this is [PKCS3] or [ANSI X9.42] mode. */ + CRYS_DHUserPubKey_t *tmpPubKey_ptr, /*!< [in] Pointer to a temporary buffer for public key structure. Used for the + exponentiation function. */ + CRYS_DHPrimeData_t *tmpPrimeData_ptr, /*!< [in] Pointer to a structure holding internal temporary buffers. */ + uint8_t *ClientPrvKey_ptr, /*!< [out] Pointer to the Private key Prv. This buffer should be at least the following + size (in bytes): +
  • If L is provided: (L+7)/8.
  • +
  • If L is NULL: \p PrimeSize.
*/ + uint16_t *ClientPrvKeySize_ptr, /*!< [in/out] Pointer to the Private key size: +
  • Input - size of the given buffer.
  • +
  • Output - actual size of the generated private key.
*/ + uint8_t *ClientPub1_ptr, /*!< [out] Pointer to the Public key. This buffer should be at least \p PrimeSize bytes. */ + uint16_t *ClientPubSize_ptr /*!< [in/out] Pointer to the Public key size: +
  • Input - size of the given buffer.
  • +
  • Output - actual size of the generated public key.
*/ +); + + +/* macro for calling the GeneratePubPrv function on PKCS#3 mode: Q is irrelevant */ +/*--------------------------------------------------------------------------------*/ +/*! +This macro is used to generate the public and private DH keys according to [PKCS3]. For a description of the parameters see ::_DX_DH_GeneratePubPrv. +*/ +#define CRYS_DH_PKCS3_GeneratePubPrv(rndState_ptr, rndGenerateVectFunc, Generator_ptr,GeneratorSize,\ + Prime_ptr,PrimeSize,\ + L,\ + tmpPubKey_ptr,tmpPrimeData_ptr,\ + ClientPrvKey_ptr,ClientPrvKeySize_ptr,\ + ClientPub_ptr,ClientPubSize_ptr)\ + _DX_DH_GeneratePubPrv(rndState_ptr, rndGenerateVectFunc, (Generator_ptr),(GeneratorSize),\ + (Prime_ptr),(PrimeSize),\ + (L),\ + (uint8_t *)NULL,(uint16_t)0,\ + CRYS_DH_PKCS3_mode,\ + (tmpPubKey_ptr),(tmpPrimeData_ptr),\ + (ClientPrvKey_ptr),(ClientPrvKeySize_ptr),\ + (ClientPub_ptr),(ClientPubSize_ptr)) + +/*! +This macro is used to generate the public and private DH keys according to [ANSI X9.42]. For a description of the parameters see ::_DX_DH_GeneratePubPrv. +*/ +#define CRYS_DH_ANSI_X942_GeneratePubPrv(rndState_ptr, rndGenerateVectFunc, Generator_ptr,GeneratorSize,Prime_ptr,PrimeSize,\ + Q_ptr,QSize,\ + tmpPubKey_ptr,tmpPrimeData_ptr,\ + ClientPrvKey_ptr,ClientPrvKeySize_ptr,\ + ClientPub_ptr,ClientPubSize_ptr)\ + _DX_DH_GeneratePubPrv(rndState_ptr, rndGenerateVectFunc, (Generator_ptr),(GeneratorSize),\ + (Prime_ptr),(PrimeSize),\ + (uint16_t)0,\ + (Q_ptr),(QSize),\ + CRYS_DH_ANSI_X942_mode,\ + (tmpPubKey_ptr),(tmpPrimeData_ptr),\ + (ClientPrvKey_ptr),(ClientPrvKeySize_ptr),\ + (ClientPub_ptr),(ClientPubSize_ptr)) + + +/*******************************************************************************************/ +/*! +@brief This function computes the shared secret key (value) accordng to [ANSI X9.42], 7.5.1: + SecretKey = ServerPubKey ^ ClientPrvKey mod Prime. +\note
  • All buffer parameters should be in Big-Endian form.
  • +
  • The user must obtain assurance of validity of the public key, using one of methods, +described in [ANSI X9.42] paragraph 7.4.
  • +
  • The actual size of the private key (in bits) must be not less than 2 and not greater than the actual +size of the Prime (modulus in bits).
+ +@return CRYS_OK on success. +@return A non-zero value on failure as defined in crys_dh_error.h or crys_rsa_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_DH_GetSecretKey( + uint8_t *ClientPrvKey_ptr, /*!< [in] Pointer to the Private key octet string Prv < Prime. */ + uint16_t ClientPrvKeySize, /*!< [in] The Private key Size (in bytes). */ + uint8_t *ServerPubKey_ptr, /*!< [in] Pointer to the Server public key octet string. */ + uint16_t ServerPubKeySize, /*!< [in] The Server Public key Size (in bytes). */ + uint8_t *Prime_ptr, /*!< [in] Pointer to the Prime octet string. */ + uint16_t PrimeSize, /*!< [in] The size of the Prime string. */ + CRYS_DHUserPubKey_t *tmpPubKey_ptr, /*!< [in] Pointer to the public key structure. Used for the exponentiation + operation function. Need not be initialized. */ + CRYS_DHPrimeData_t *tmpPrimeData_ptr, /*!< [in] Pointer to a structure containing internal temp buffers. */ + uint8_t *SecretKey_ptr, /*!< [out] Pointer to the secret key octet string. This buffer should be at + least PrimeSize bytes. */ + uint16_t *SecretKeySize_ptr /*!< [in/out] Pointer to the secret key Buffer Size. This buffer should be at + least of PrimeSize bytes: +
  • Input - size of the given buffer.
  • +
  • Output - actual size.
*/ +); + + +/******************************************************************************************/ +/*! +@brief This function extracts the shared secret keying data from the shared secret value. It should be called by using +macros ::CRYS_DH_X942_GetSecretDataAsn1 and ::CRYS_DH_X942_GetSecretDataConcat. + +\note +
  • The "other info" argument and its AlgorithmID entry are mandatory only for ASN1 key derivation, and optional for +the other derivation modes.
  • +
  • If used, all entries of the structure should be initialized with relevant data and size, prior to calling this function +(entry size of empty fields must be set to 0).
  • +
  • All buffers arguments are represented in Big-Endian form.
+ +@return CRYS_OK on success. +@return A non-zero value on failure as defined in crys_dh_error.h, crys_rsa_error.h, crys_kdf_error.h or crys_hash_error.h. +*/ + CIMPORT_C CRYSError_t CRYS_DH_X942_GetSecretData( + uint8_t *ClientPrvKey_ptr, /*!< [in] Pointer to the Private key octet string. */ + uint16_t ClientPrvKeySize, /*!< [in] The Private key size (in bytes). */ + uint8_t *ServerPubKey_ptr, /*!< [in] Pointer to the Server public key octet string. */ + uint16_t ServerPubKeySize, /*!< [in] The Server Public key size (in bytes). */ + uint8_t *Prime_ptr, /*!< [in] Pointer to the Prime octet string. */ + uint16_t PrimeSize, /*!< [in] The size of the Prime string. */ + CRYS_DH_OtherInfo_t *otherInfo_ptr, /*!< [in] Pointer to structure containing other data, shared by two entities + sharing the secret keying data. + The Maximal size of each data entry of "other info" is limited - see crys_kdf.h + for the defined value. */ + CRYS_DH_HASH_OpMode_t hashMode, /*!< [in] One of the supported SHA-x HASH modes. The supported modes are according to the supported + HASH modes for the product (and MD5 is not supported). */ + CRYS_DH_DerivationFunc_Mode DerivFunc_mode, /*!< [in] The enumerator ID of key derivation function mode. ASN1 or Concatenation + modes are supported. */ + CRYS_DH_Temp_t *tmpBuff_ptr, /*!< [in] A pointer to the DH temp buffer structure. Not initialized. */ + uint8_t *SecretKeyingData_ptr, /*!< [out] Pointer to the secret key octet string. This buffer should be at least + PrimeSize bytes. */ + uint16_t SecretKeyingDataSize /*!< [in] The required Secret Keying data size (in bytes). Must be larger than 0, + and smaller than the maximal - CRYS_DH_MAX_SIZE_OF_KEYING_DATA. */ +); + +/****************************************************************/ +/*! +This macro implements the DH [ANSI X9.42] standard. It derives a secret key using the Derivation function based on ASN.1. For a +description of the parameters see ::CRYS_DH_X942_GetSecretData.*/ +#define CRYS_DH_X942_GetSecretDataAsn1(ClientPrvKey_ptr,ClientPrvKeySize,ServerPubKey_ptr,ServerPubKeySize,Prime_ptr,PrimeSize,otherInfo_ptr,hashMode,tmpBuff_ptr,SecretKeyingData_ptr,SecretKeyingDataSize)\ + CRYS_DH_X942_GetSecretData((ClientPrvKey_ptr),(ClientPrvKeySize),(ServerPubKey_ptr),(ServerPubKeySize),(Prime_ptr),(PrimeSize),(otherInfo_ptr),(hashMode),(CRYS_DH_ASN1_Der_mode),(tmpBuff_ptr),(SecretKeyingData_ptr),(SecretKeyingDataSize)) +/*! +This macro implements the DH [ANSI X9.42] standard. It derives a secret key using the Derivation function based on concatenation of HASHed data. +For a description of the parameters see ::CRYS_DH_X942_GetSecretData.*/ +#define CRYS_DH_X942_GetSecretDataConcat(ClientPrvKey_ptr,ClientPrvKeySize,ServerPubKey_ptr,ServerPubKeySize,Prime_ptr,PrimeSize,otherInfo_ptr,hashMode,tmpBuff_ptr,SecretKeyingData_ptr,SecretKeyingDataSize)\ + CRYS_DH_X942_GetSecretData((ClientPrvKey_ptr),(ClientPrvKeySize),(ServerPubKey_ptr),(ServerPubKeySize),(Prime_ptr),(PrimeSize),(otherInfo_ptr),(hashMode),(CRYS_DH_Concat_Der_mode),(tmpBuff_ptr),(SecretKeyingData_ptr),(SecretKeyingDataSize)) + + +/****************************************************************/ +/*! +@brief The function computes shared secret data using two pairs of public and private keys: + +
  • SecretKey1 = ServerPubKey1^ClientPrvKey1 mod Prime.
  • +
  • SecretKey2 = ServerPubKey2^ClientPrvKey2 mod Prime.
+It uses the Derivation function to derive secret keying data from the two secret keys (values). +This function may be called directly, or by using macros ::CRYS_DH_X942_HybridGetSecretDataAsn1 and ::CRYS_DH_X942_HybridGetSecretDataConcat +described above. + +\note +
  • The "other info" argument and its AlgorithmID entry are mandatory only for ASN1 key derivation, and optional for the other derivation modes.
  • +If used, all entries of the structure should be initialized with relevant data and size, prior to calling this function +(entry size of empty fields must be set to 0). +
  • All buffers arguments are represented in Big-Endian form.
+ +@return CRYS_OK on success. +@return A non-zero value on failure as defined in crys_dh_error.h, crys_rsa_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_DH_X942_HybridGetSecretData( + uint8_t *ClientPrvKey_ptr1, /*!< [in] Pointer to the First Private key octet string number. */ + uint16_t ClientPrvKeySize1, /*!< [in] The First Private key Size (in bytes). */ + uint8_t *ClientPrvKey_ptr2, /*!< [in] Pointer to the Second Private key octet string. */ + uint16_t ClientPrvKeySize2, /*!< [in] The Second Private key Size (in bytes). */ + uint8_t *ServerPubKey_ptr1, /*!< [in] Pointer to the First Server public key octet string. */ + uint16_t ServerPubKeySize1, /*!< [in] The First Server Public key Size (in bytes). */ + uint8_t *ServerPubKey_ptr2, /*!< [in] Pointer to the Second Server public key octet string. */ + uint16_t ServerPubKeySize2, /*!< [in] The Second Server Public key Size (in bytes). */ + uint8_t *Prime_ptr, /*!< [in] Pointer to the Prime octet string. */ + uint16_t PrimeSize, /*!< [in] The size of the Prime string. */ + CRYS_DH_OtherInfo_t *otherInfo_ptr, /*!< [in] Pointer to structure containing optional other data, shared by two entities + sharing the secret keying data. */ + CRYS_DH_HASH_OpMode_t hashMode, /*!< [in] One of the supported SHA-x HASH modes. The supported modes are according to the supported + HASH modes for the product (and MD5 is not supported). */ + CRYS_DH_DerivationFunc_Mode DerivFunc_mode, /*!< [in] The type of function to use to derive the secret key to the key data. + ASN.1 or Concatenation modes are supported. */ + CRYS_DH_HybrTemp_t *tmpDhHybr_ptr, /*!< [in] Pointer to a CRYS_DH_Temp_t structure that contains temp buffers for + internal operations. */ + uint8_t *SecretKeyingData_ptr, /*!< [out] Pointer to the secret key octet string. This buffer should be at least + of size PrimeSize bytes. */ + uint16_t SecretKeyingDataSize /*!< [in] The required Secret Keying data size (in bytes). Must be larger than 0, + and smaller than CRYS_DH_MAX_SIZE_OF_KEYING_DATA. */ +); + + +/****************************************************************/ +/*! +This macro implements the DH [X9.42] standard deriving a hybrid secret key from two public-private pair of keys using the Derivation function based on ASN.1. +For a description of the parameters see ::CRYS_DH_X942_HybridGetSecretData.*/ +#define CRYS_DH_X942_HybridGetSecretDataAsn1(ClientPrvKey_ptr1,ClientPrvKeySize1,ClientPrvKey_ptr2,ClientPrvKeySize2,ServerPubKey_ptr1,ServerPubKeySize1,ServerPubKey_ptr2,ServerPubKeySize2,Prime_ptr,PrimeSize,otherInfo_ptr,hashFunc,tmpDhHybr_ptr,SecretKeyingData_ptr,SecretKeyingDataSize)\ + CRYS_DH_X942_HybridGetSecretData((ClientPrvKey_ptr1),(ClientPrvKeySize1),(ClientPrvKey_ptr2),(ClientPrvKeySize2),(ServerPubKey_ptr1),(ServerPubKeySize1),(ServerPubKey_ptr2),(ServerPubKeySize2),(Prime_ptr),(PrimeSize),(otherInfo_ptr),(hashFunc),CRYS_DH_ASN1_Der_mode,(tmpDhHybr_ptr),(SecretKeyingData_ptr),(SecretKeyingDataSize)) + +/*! +This macro implements the DH [X9.42] standard, deriving a hybrid secret key from two pairs of public-private keys, using the Derivation +function based on concatenation using SHA-x HASH. For a description of the parameters see ::CRYS_DH_X942_HybridGetSecretData. +*/ +#define CRYS_DH_X942_HybridGetSecretDataConcat(ClientPrvKey_ptr1,ClientPrvKeySize1,ClientPrvKey_ptr2,ClientPrvKeySize2,ServerPubKey_ptr1,ServerPubKeySize1,ServerPubKey_ptr2,ServerPubKeySize2,Prime_ptr,PrimeSize,otherInfo_ptr,hashFunc,tmpDhHybr_ptr,SecretKeyingData_ptr,SecretKeyingDataSize)\ + CRYS_DH_X942_HybridGetSecretData((ClientPrvKey_ptr1),(ClientPrvKeySize1),(ClientPrvKey_ptr2),(ClientPrvKeySize2),(ServerPubKey_ptr1),(ServerPubKeySize1),(ServerPubKey_ptr2),(ServerPubKeySize2),(Prime_ptr),(PrimeSize),(otherInfo_ptr),(hashFunc),CRYS_DH_Concat_Der_mode,(tmpDhHybr_ptr),(SecretKeyingData_ptr),(SecretKeyingDataSize)) + + +/******************************************************************************************/ +/*! +@brief The function checks the obtained DH public key according to its domain parameters [ANSI X9.42-2001] + +\note +Assuming: The DH domain parameters are valid. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined in crys_dh_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_DH_CheckPubKey( + uint8_t *modP_ptr, /*!< [in] The pointer to the modulus (prime) P. */ + uint32_t modPsizeBytes, /*!< [in] The modulus size in bytes. */ + uint8_t *orderQ_ptr, /*!< [in] The pointer to the prime order Q of generator. */ + uint32_t orderQsizeBytes, /*!< [in] The size of order of generator in bytes. */ + uint8_t *pubKey_ptr, /*!< [in] The pointer to the public key to be validated. */ + uint32_t pubKeySizeBytes, /*!< [in] The public key size in bytes. */ + CRYS_DH_Temp_t *tempBuff_ptr /*!< [in] The temp buffer for internal calculations. */ +); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/crys_dh_error.h b/external/nrf_cc310/include/crys_dh_error.h new file mode 100644 index 0000000..15258a2 --- /dev/null +++ b/external/nrf_cc310/include/crys_dh_error.h @@ -0,0 +1,158 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_DH_ERROR_H +#define CRYS_DH_ERROR_H + + +#include "crys_error.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains error codes definitions for CRYS DH module. +@defgroup crys_dh_error CryptoCell DH specific errors +@{ +@ingroup crys_dh +*/ +/************************ Defines ******************************/ +/* DH module on the CRYS layer base address - 0x00F00500 */ +/*! The CRYS DH module errors */ +/*! Illegal input pointer.*/ +#define CRYS_DH_INVALID_ARGUMENT_POINTER_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x0UL) +/*! Illegal input size.*/ +#define CRYS_DH_INVALID_ARGUMENT_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x1UL) +/*! Illegal operation mode.*/ +#define CRYS_DH_INVALID_ARGUMENT_OPERATION_MODE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x2UL) +/*! Illegal hash mode.*/ +#define CRYS_DH_INVALID_ARGUMENT_HASH_MODE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x3UL) + +/*! Illegal secret key data size. */ +#define CRYS_DH_SECRET_KEYING_DATA_SIZE_ILLEGAL_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x4UL) +/*! Illegal L input. */ +#define CRYS_DH_INVALID_L_ARGUMENT_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x5UL) +/*! Prime is smaller than generator. */ +#define CRYS_DH_ARGUMENT_PRIME_SMALLER_THAN_GENERATOR_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x6UL) +/*! Generator is smaller than zero. */ +#define CRYS_DH_ARGUMENT_GENERATOR_SMALLER_THAN_ZERO_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x7UL) +/*! Illegal private key size. */ +#define CRYS_DH_ARGUMENT_PRV_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x8UL) +/*! Illegal buffer size. */ +#define CRYS_DH_ARGUMENT_BUFFER_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x9UL) +/*! Invalid shared secret value. */ +#define CRYS_DH_INVALID_SHARED_SECRET_VALUE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0xAUL) +/*! DH is not supported. */ +#define CRYS_DH_IS_NOT_SUPPORTED (CRYS_DH_MODULE_ERROR_BASE + 0xFUL) +/*! Illegal X942 hybrid buffer size.*/ +#define CRYS_DH_X942_HYBRID_SIZE1_BUFFER_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x15UL) + +/*The requested derived secret key size is invalid*/ +/*! Illegal secret key size .*/ +#define CRYS_DH_SECRET_KEY_SIZE_NEEDED_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x16UL) +/*! Illegal output secret key size .*/ +#define CRYS_DH_SECRET_KEY_SIZE_OUTPUT_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x17UL) +/*! Illegal otherInfo size .*/ +#define CRYS_DH_OTHERINFO_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x18UL) + +/* DH domain and key generation and checking errors */ +/*! Illegal modulus size. */ +#define CRYS_DH_INVALID_MODULUS_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x20UL) +/*! Illegal order size. */ +#define CRYS_DH_INVALID_ORDER_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x21UL) +/*! Illegal seed size. */ +#define CRYS_DH_INVALID_SEED_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x22UL) +/*! Illegal J factor pointer size. */ +#define CRYS_DH_INVALID_J_FACTOR_PTR_OR_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x23UL) +/*! Illegal generator pointer or size. */ +#define CRYS_DH_INVALID_GENERATOR_PTR_OR_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x24UL) + +/*! Illegal domain primes. */ +#define CRYS_DH_CHECK_DOMAIN_PRIMES_NOT_VALID_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x25UL) +/*! Illegal domain generator. */ +#define CRYS_DH_CHECK_DOMAIN_GENERATOR_NOT_VALID_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x26UL) +/*! Illegal public key size. */ +#define CRYS_DH_INVALID_PUBLIC_KEY_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x27UL) +/*! Illegal public key. */ +#define CRYS_DH_CHECK_PUB_KEY_NOT_VALID_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x28UL) +/*! Illegal generator size or pointer. */ +#define CRYS_DH_CHECK_GENERATOR_SIZE_OR_PTR_NOT_VALID_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x29UL) +/*! Illegal seed size or pointer. */ +#define CRYS_DH_CHECK_SEED_SIZE_OR_PTR_NOT_VALID_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x2AUL) +/*! Illegal generator. */ +#define CRYS_DH_CHECK_GENERATOR_NOT_VALID_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x2BUL) +/*! Prime generation failed. */ +#define CRYS_DH_PRIME_P_GENERATION_FAILURE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x2CUL) +/*! Illegal public key. */ +#define CRYS_DH_INVALID_PUBLIC_KEY_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x2DUL) +/*! Illegal seed. */ +#define CRYS_DH_PASSED_INVALID_SEED_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x2EUL) +/*! Prime generation failed. */ +#define CRYS_DH_PRIME_Q_GENERATION_FAILURE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x2FUL) +/*! Internal PKI error */ +#define CRYS_DH_PKI_INTERNAL_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x30UL) + + + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + diff --git a/external/nrf_cc310/include/crys_dh_kg.h b/external/nrf_cc310/include/crys_dh_kg.h new file mode 100644 index 0000000..961d1a0 --- /dev/null +++ b/external/nrf_cc310/include/crys_dh_kg.h @@ -0,0 +1,203 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef _CRYS_DH_KG_H +#define _CRYS_DH_KG_H + + +#include "crys_dh.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! @file +@brief This module defines the API that supports Diffie-Hellman domain. +@defgroup crys_dh_kg CryptoCell DH Key Generation APIs +@{ +@ingroup crys_dh +*/ + +/************************ Defines ******************************/ +/*! Minimal size of DH seed in bytes. */ +#define CRYS_DH_SEED_MIN_SIZE_IN_BYTES CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES +/*! Minimal size of DH seed in bits. */ +#define CRYS_DH_SEED_MIN_SIZE_IN_BITS (CRYS_DH_SEED_MIN_SIZE_IN_BYTES * 8) + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + +/* temp buffers, used in different DH KG functions */ + +/*! Temporary data buffer structure for domain parameters generation in DH. */ +typedef struct CRYS_DHKGData_t +{ + /* The aligned input and output temp buffers */ + /*! Temporary buffer. */ + uint32_t TempBuff1[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Temporary buffer. */ + uint32_t TempBuff2[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Temporary buffer. */ + uint32_t TempBuff3[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Temporary buffer. */ + uint32_t TempBuff4[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Temporary buffer. */ + uint32_t TempBuff5[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Temporary buffer. */ + uint32_t TempBuff6[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Temporary buffer. */ + CRYS_DH_Temp_t ExpTemps; +}CRYS_DHKGData_t; + +/*! Temporary buffer structure . */ +typedef struct CRYS_DHKG_CheckTemp_t +{ + /*! Temporary buffer. */ + uint32_t CheckTempBuff[3*CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Temporary buffer. */ + CRYS_DHKGData_t DhKgBuff; +}CRYS_DHKG_CheckTemp_t; + +/*! DH Domain generation values definitions */ +/*! Minimal modulus size for X942 - 1024.*/ +#define DH_X942_PRIME_MOD_MIN_VAL 1024 +/*! Maximal modulus size for X942 - 2048.*/ +#define DH_X942_PRIME_MOD_MAX_VAL 2048 +/*! PGeneration counter for X942 - 4096.*/ +#define DH_X942_PGEN_COUNTER_CONST 4096 +/*! HASH size in bits for X942 - 160.*/ +#define DH_X942_HASH_SIZE_BITS 160 +/*! Maximal allowed ratio between modulus and generator order sizes (by implementation) */ +#define DH_MAX_RATIO_MODULO_TO_ORDER 4 + +/************************ Structs ******************************/ + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + + +/******************************************************************************************/ +/*! +@brief This function generates DH domain parameters in Galois prime field according to standard [ANS X9.42]. +It receives the required sizes (in bits) of the modulus, the generator's order, and the seed, and then generates +the prime modulus and the generator according to given sizes. +If generateSeed argument is set to 1, the function generates and outputs the random seed. Otherwise (if set to 0), +the seed has to be passed as an input argument. According to implementation the seed should be not greate, than (2^seedSizeBits - 2^32). +The seed and some additional parameters, generated by the function (factorJ, pgenCounter), are used for checking +that all domain parameters are generated according to the standard and not forged. +\note All buffer parameters should be in Big-Endian form. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_dh_error.h, crys_rnd_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_DH_CreateDomainParams( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to a random vector generation function. */ + uint32_t modPsizeBits, /*!< [in] Size of the modulus (Prime) in bits equal 256*n, where n >= 4. FIPS 186-4 + defines sizes 1024 and 2048 bit. */ + uint32_t orderQsizeBits, /*!< [in] Size of the Generator's order in bits. FIPS 186-4 defines orderQSizeBits = 160 + for modulus 1024 bit and 224 or 256 bit for modPSizeBits = 2048. We not recommend + sizes > 256 and returns an error if orderQSizeBits > modPSizeBits/4 */ + uint32_t seedSizeBits, /*!< [in] Seed size in bits. Requirements: modPSizeBits >= seedSizeBits >= orderQSizeBits + (the first is required by our implementation). */ + uint8_t *modP_ptr, /*!< [out] Pointer to the modulus (prime) buffer. The size of the buffer for output + generated value must be no less than given modulus size. */ + uint8_t *orderQ_ptr, /*!< [out] Pointer to the order Q of generator. The size of the buffer for output generated + value must be no less than the given order size. */ + uint8_t *generatorG_ptr, /*!< [out] Pointer to the generator of multiplicative subgroup in GF(P). + If the user does not need this output, then both the pointer and the buffer size + must be set to 0. */ + uint32_t *generGsizeBytes_ptr, /*!< [in/out] Pointer to the one word buffer for outputting the generator's size. + The passed size (if needed) must be not less than modulus size and the function + returns the actual size of the generator. */ + uint8_t *factorJ_ptr, /*!< [out] Pointer to the buffer for integer factor J. If NULL, the function does not output + this parameter (in this case JsizeBytes_ptr also must be set to NULL, else the function + returns an error). */ + uint32_t *JsizeBytes_ptr, /*!< [in/out] Pointer to the size of integer factor J. If NULL, the function does not output + this parameter. */ + uint8_t *seedS_ptr, /*!< [in/out] Random seed used for prime generation. The size of the buffer must be + at least the seed size. */ + int8_t generateSeed, /*!< [in] Flag, defining whether the seed should be generated randomly by the function + (1) or is passed by the user (0). */ + uint32_t *pgenCounter_ptr, /*!< [out] Pointer to counter of tries to generate the primes. If NULL, the function does not + output this parameter. */ + CRYS_DHKGData_t *DHKGbuff_ptr /*!< [out] The temp buffer of defined structure for internal calculations. */ +); + + +/******************************************************************************************/ +/*! +@brief This function receives DH domain parameters, seed and prime generation counter and then verifies +that the domain was created according to the standard [ANS X9.42]. +According to implementation, the value of the user passed seed should be not +greate, than (2^seedSizeBits - 2^32), otherwise an error is returned. +\note All buffer parameters should be in Big-Endian form. For more detailed +description of the parameters see ::CRYS_DH_CreateDomainParams. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_dh_error.h, crys_rnd_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_DH_CheckDomainParams( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in/out] Pointer to the RND Generate vector function pointer. */ + uint8_t *modP_ptr, /*!< [in] Pointer to the modulus (Prime). */ + uint32_t modPsizeBytes, /*!< [in] Size of the modulus (Prime) in bytes. */ + uint8_t *orderQ_ptr, /*!< [in] Pointer to the order Q of generator. The size of the buffer for output + generated value must be no less than the order size. */ + uint32_t orderQsizeBytes, /*!< [in] Size of the Generator's order in bytes. */ + uint8_t *generatorG_ptr, /*!< [in] Pointer to the generator of the multiplicative subgroup in GF(P). */ + uint32_t generatorSizeBytes, /*!< [in] Size of the generator in bytes. */ + uint8_t *seedS_ptr, /*!< [in] Random seed used for prime generation. */ + uint32_t seedSizeBits, /*!< [in] Seed size in bits. */ + uint32_t pgenCounter, /*!< [in] Counter of prime generation attempts. */ + CRYS_DHKG_CheckTemp_t *checkTempBuff_ptr /*!< [in] Temporary buffer for internal calculations. */ + +); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/crys_ec_edw_api.h b/external/nrf_cc310/include/crys_ec_edw_api.h new file mode 100644 index 0000000..47c7f08 --- /dev/null +++ b/external/nrf_cc310/include/crys_ec_edw_api.h @@ -0,0 +1,201 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_EC_EDW_API_H +#define CRYS_EC_EDW_API_H + +#include "ssi_pal_types.h" +#include "crys_hash.h" +#include "crys_rnd.h" +#include "crys_pka_defs_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! +@defgroup cryptocell_ec CryptoCell EC 25519 curve APIs +@{ +@ingroup cryptocell_api +@brief This group is the cryptocell EC 25519 curve root group +@} + +@file +@brief This file contains the CRYS APIs used for EC EDW (Edwards) ed25519 algorithms. +@defgroup crys_ec_edw CryptoCell EC Edwards APIs +@{ +@ingroup cryptocell_ec + +\note Algorithms of Montgomery and Edwards elliptic curves cryptography were developed by + Daniel.J.Bernstein. +*/ + +/*! EC Edwards ed25519 modulus and order sizes in bits, words and bytes. */ +/*! EC Edwards modulus size in bits. */ +#define CRYS_ECEDW_MOD_SIZE_IN_BITS 255U /*!<\internal MOD - EC Edw modulus size*/ +/*! EC Edwards order size in bits. */ +#define CRYS_ECEDW_ORD_SIZE_IN_BITS 255U /*!<\internal ORD - EC Edw generator order size*/ +/*! EC Edwards nodulus size in words. */ +#define CRYS_ECEDW_MOD_SIZE_IN_32BIT_WORDS ((CRYS_ECEDW_MOD_SIZE_IN_BITS + SASI_BITS_IN_32BIT_WORD - 1) / SASI_BITS_IN_32BIT_WORD) +/*! EC Edwards modulus size in bytes. */ +#define CRYS_ECEDW_MOD_SIZE_IN_BYTES (CRYS_ECEDW_MOD_SIZE_IN_32BIT_WORDS * SASI_32BIT_WORD_SIZE) +/*! EC Edwards order size in words. */ +#define CRYS_ECEDW_ORD_SIZE_IN_32BIT_WORDS ((CRYS_ECEDW_ORD_SIZE_IN_BITS + SASI_BITS_IN_32BIT_WORD - 1) / SASI_BITS_IN_32BIT_WORD) +/*! EC Edwards order size in bytes. */ +#define CRYS_ECEDW_ORD_SIZE_IN_BYTES (CRYS_ECEDW_ORD_SIZE_IN_32BIT_WORDS * SASI_32BIT_WORD_SIZE) + +/*! Constant sizes of special EC_MONT buffers and arrays */ +/*! EC Edwards seed size in bytes. */ +#define CRYS_ECEDW_SEED_BYTES CRYS_ECEDW_MOD_SIZE_IN_BYTES +/*! EC Edwards secret key size in bytes. */ +#define CRYS_ECEDW_SECRET_KEY_BYTES (2 * CRYS_ECEDW_MOD_SIZE_IN_BYTES) +/*! EC Edwards signatue size in bytes. */ +#define CRYS_ECEDW_SIGNATURE_BYTES (2 * CRYS_ECEDW_ORD_SIZE_IN_BYTES) +/*! EC Edwards scalar size in bytes. */ +#define CRYS_ECEDW_SCALAR_BYTES CRYS_ECEDW_ORD_SIZE_IN_BYTES +/*! EC Edwards scalar multiplication size in bytes. */ +#define CRYS_ECEDW_SCALARMULT_BYTES CRYS_ECEDW_MOD_SIZE_IN_BYTES + +/*! EC_EDW temp buffer size definition. */ +#define CRYS_ECEDW_TEMP_BUFF_SIZE_IN_32BIT_WORD (10*CRYS_EC_MONT_EDW_MODULUS_MAX_SIZE_IN_WORDS + (sizeof(CRYS_HASHUserContext_t)+SASI_32BIT_WORD_SIZE-1)/SASI_32BIT_WORD_SIZE) + +/*! EC_EDW temp buffer type definition. */ +typedef struct { + /*! Internal buffer. */ + uint32_t buff[CRYS_ECEDW_TEMP_BUFF_SIZE_IN_32BIT_WORD]; +} CRYS_ECEDW_TempBuff_t; + + +/******************************************************************************/ +/*! +@brief The function creates EC Edwards signature on the message. +\note Used detached form of signature, separated from the message. + Implemented algorithm of Bernstein D. etc. sign ed25519. + +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECEDW_Sign ( + uint8_t *pSign, /*!< [out] Pointer to the detached signature. */ + size_t *pSignSize, /*!< [in/out] Pointer to the total size of the signature ; + In - the buffer size, which (must be at least 2*EC order size); + Out - the actual size of output data. */ + const uint8_t *pMsg, /*!< [in] Pointer to the message. */ + size_t msgSize, /*!< [in] Message size in bytes: must be less, than + (CRYS_HASH_UPDATE_DATA_MAX_SIZE_IN_BYTES - 2*(EC_EDW modulus size)). */ + const uint8_t *pSignSecrKey, /*!< [in] Pointer to the signer secret key (seed || pulKey) */ + size_t secrKeySize, /*!< [in] Size of signer secret key in bytes: (must be 2*EC order size). */ + CRYS_ECEDW_TempBuff_t *pTempBuff /*!< [in] Pointer to the temp buffer. */); + + + +/******************************************************************************/ +/*! +@brief The function verifies the EC Edwards ed25519 signature on the message. +\note The input signature is in detached form, i.e. separated from the message. + +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECEDW_Verify( + const uint8_t *pSign, /*!< [in] Pointer to detached signature, i.e. the + signature is separated from the message. */ + size_t signSize, /*!< [in] Size of the signature in bytes, it must be + equal to two EC Order size in bytes. */ + const uint8_t *pSignPublKey, /*!< [in] Pointer to signer public key. */ + size_t publKeySize, /*!< [in] Size of the signer public key in bytes; must be + equal to EC modulus size. */ + uint8_t *pMsg, /*!< [in] Pointer to the message. */ + size_t msgSize, /*!< [in] Pointer to the message size in bytes. Must be less than + (CRYS_HASH_UPDATE_DATA_MAX_SIZE_IN_BYTES - 2*(EC_EDW modulus size)). */ + CRYS_ECEDW_TempBuff_t *pTempBuff /*!< [in] Pointer to the temp buffer, for internal use. */); + + +/******************************************************************************/ +/*! +@brief The function randomly generates Ec ed25519 private and public keys + using given seed. + The generation is performed using EC Edwards ed25519 algorithm. + +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECEDW_SeedKeyPair ( + const uint8_t *pSeed, /*!< [in] Pointer to the given seed. */ + size_t seedSize, /*!< [in] Size of the seed in bytes, must be equal the EC order size + in bytes. */ + uint8_t *pSecrKey, /*!< [out] Pointer to the secret key, including the seed, concatenated + with the public key. */ + size_t *pSecrKeySize, /*!< [in/out] Pointer to the size of the secret key buffer in bytes + (must be at least 2*EC order size). */ + uint8_t *pPublKey, /*!< [out] Pointer to the public key. */ + size_t *pPublKeySize, /*!< [in/out] Pointer to the size of the public key in bytes. + In - the size of buffer must be at least EC modulus size; + Out - the actual size. */ + CRYS_ECEDW_TempBuff_t *pTempBuff /*!< [in] Pointer to the temp buffer, for internal use. */); + +/*******************************************************************/ +/*! + @brief The function randomly generates the EC Edwards ed25519 private and + public keys. + The generation is performed using EC Edwards ed25519 algorithm. + +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h, crys_hash_error.h or crys_rnd_error. +*/ +CIMPORT_C CRYSError_t CRYS_ECEDW_KeyPair ( + uint8_t *pSecrKey, /*!< [out] Pointer to the secret key (including seed and public key). */ + size_t *pSecrKeySize, /*!< [in/out] Pointer to the size of the secret key in bytes, + (must be at least 2*EC order size). */ + uint8_t *pPublKey, /*!< [out] Pointer to the public key. */ + size_t *pPublKeySize, /*!< [in/out] - Pointer to the size of the public key in bytes. + In - the size of buffer must be at least EC modulus size; + Out - the actual size. */ + void *pRndState, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + CRYS_ECEDW_TempBuff_t *pTempBuff /*!< [in] Pointer to the temp buffer. */); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + + diff --git a/external/nrf_cc310/include/crys_ec_mont_api.h b/external/nrf_cc310/include/crys_ec_mont_api.h new file mode 100644 index 0000000..f9d56ca --- /dev/null +++ b/external/nrf_cc310/include/crys_ec_mont_api.h @@ -0,0 +1,213 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_ECMONT_API_H +#define CRYS_ECMONT_API_H + +#include "ssi_pal_types.h" +#include "crys_rnd.h" +#include "crys_pka_defs_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! +@file +@brief This file contains the CRYS APIs used for EC MONT (Montgomery Curve25519) algorithms. +@defgroup crys_ec_mont CryptoCell EC Montgomery APIs +@{ +@ingroup cryptocell_ec + + +\note Implemented algorithms according to Montgomery elliptic curves cryptography, + developed by Daniel J.Bernstein etc. +*/ + +/*! EC Montgomery curve25519 modulus size in bits, words and bytes */ +/*! EC Montgomery modulus size in bits. */ +#define CRYS_ECMONT_MOD_SIZE_IN_BITS 255U +/*! EC Montgomery modulus size in words. */ +#define CRYS_ECMONT_MOD_SIZE_IN_32BIT_WORDS ((CRYS_ECMONT_MOD_SIZE_IN_BITS + SASI_BITS_IN_32BIT_WORD - 1) / SASI_BITS_IN_32BIT_WORD) +/*! EC Montgomery modulus size in bytes. */ +#define CRYS_ECMONT_MOD_SIZE_IN_BYTES ((CRYS_ECMONT_MOD_SIZE_IN_BITS + SASI_BITS_IN_32BIT_WORD - 1) / sizeof(uint32_t)) + +/*! Constant sizes of special EC_MONT buffers and arrays */ +/*! EC Montgomery scalar size in bytes. */ +#define CRYS_ECMONT_SCALARBYTES (CRYS_ECMONT_MOD_SIZE_IN_32BIT_WORDS * SASI_32BIT_WORD_SIZE) +/*! EC Montgomery scalar multiplication size in bytes. */ +#define CRYS_ECMONT_SCALARMULTBYTES (CRYS_ECMONT_MOD_SIZE_IN_32BIT_WORDS * SASI_32BIT_WORD_SIZE) +/*! EC Montgomery scalar seed size in bytes. */ +#define CRYS_ECMONT_SEEDBYTES (CRYS_ECMONT_MOD_SIZE_IN_32BIT_WORDS * SASI_32BIT_WORD_SIZE) + +/*! EC Montgomery domains ID-s enumerator. */ +typedef enum { + CRYS_ECMONT_DOMAIN_CURVE_25519, /*!< EC Curve25519. */ + /*! EC Montgomery last domain. */ + CRYS_ECMONT_DOMAIN_OFF_MODE, + /*! Reserved. */ + CRYS_ECMONT_DOMAIN_LAST = 0x7FFFFFFF +}CRYS_ECMONT_DomainId_t; + + +/*! EC_MONT scalar mult temp buffer type definition */ +typedef struct { + /*! Internal temporary buffer. */ + uint32_t ecMontScalarMultTempBuff[CRYS_EC_MONT_TEMP_BUFF_SIZE_IN_32BIT_WORDS]; // set needed +} CRYS_ECMONT_ScalrMultTempBuff_t; + +/*! EC_MONT temp buffer type definition */ +typedef struct { + /* Don't change sequence order of the buffers */ + /*! Internal temporary buffer. */ + uint32_t ecMontScalar[CRYS_EC_MONT_EDW_MODULUS_MAX_SIZE_IN_WORDS]; + /*! Internal temporary buffer. */ + uint32_t ecMontResPoint[CRYS_EC_MONT_EDW_MODULUS_MAX_SIZE_IN_WORDS]; + /*! Internal temporary buffer. */ + uint32_t ecMontInPoint[CRYS_EC_MONT_EDW_MODULUS_MAX_SIZE_IN_WORDS]; + /*! Internal temporary buffer. */ + CRYS_ECMONT_ScalrMultTempBuff_t ecMontScalrMultTempBuff; // if needed +} CRYS_ECMONT_TempBuff_t; + + +/*********************************************************************/ +/*! +@brief The function performs EC Montgomery (Curve25519) scalar multiplication: + resPoint = scalar * point. + +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECMONT_Scalarmult( + uint8_t *pResPoint, /*!< [out] Pointer to the public (secret) key. */ + size_t *pResPointSize, /*!< [in/out] Pointer to the size of the public key in bytes. + In - the size of the buffer. must be at least EC modulus + size (for curve25519 - 32 bytes). + Out - the actual size. */ + const uint8_t *pScalar, /*!< [in] Pointer to the secret (private) key. */ + size_t scalarSize, /*!< [in] Pointer to the size of the secret key in bytes; + must be equal to EC order size (for curve25519 - 32 bytes). */ + const uint8_t *pInPoint, /*!< [in] Pointer to the input point (compressed). */ + size_t inPointSize, /*!< [in] Size of the point - must be equal to CRYS_ECMONT_MOD_SIZE_IN_BYTES. */ + CRYS_ECMONT_TempBuff_t *pEcMontTempBuff /*!< [in] Pointer to temp buffer, for internal use. */); + + +/*********************************************************************/ +/*! +@brief The function performs EC Montgomery (Curve25519) scalar multiplication of base point: + res = scalar * base_point. + + Note: all byte arrays have LE order of bytes, i.e. LS byte is on left most place. + +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECMONT_ScalarmultBase( + uint8_t *pResPoint, /*!< [out] Pointer to the public (secret) key. */ + size_t *pResPointSize, /*!< [in/out] Pointer to the size of the public key in bytes. + In - the size of buffer must be at least EC modulus size + (for curve25519 - 32 bytes); + Out - the actual size. */ + const uint8_t *pScalar, /*!< [in] Pointer to the secret (private) key. */ + size_t scalarSize, /*!< [in] Pointer to the size of the scalar in bytes - + must be equal to EC order size (for curve25519 - 32 bytes). */ + CRYS_ECMONT_TempBuff_t *pEcMontTempBuff /*!< [in] Pointer to temp buffer, for internal use. */); + + +/*******************************************************************/ +/*! +@brief The function randomly generates private and public keys for Montgomery + Curve25519. + + +\note
  • All byte arrays are in LE order of bytes, i.e. LS byte is on the left most place.
  • +
  • LS and MS bits of the Secret key are set according to EC Montgomery scalar mult. algorithm: + secrKey[0] &= 248; secrKey[31] &= 127; secrKey[31] |= 64;
+ +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h or crys_rnd_error.h. + +*/ +CIMPORT_C CRYSError_t CRYS_ECMONT_KeyPair ( + uint8_t *pPublKey, /*!< [out] Pointer to the public key. */ + size_t *pPublKeySize, /*!< [in/out] Pointer to the size of the public key in bytes. + In - the size of the buffer must be at least EC order size + (for curve25519 - 32 bytes); + Out - the actual size. */ + uint8_t *pSecrKey, /*!< [out] Pointer to the secret key, including. */ + size_t *pSecrKeySize, /*!< [in/out] Pointer to the size of buffer for the secret key in bytes - + must be at least EC order size (for curve25519 - 32 bytes). */ + void *pRndState, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + CRYS_ECMONT_TempBuff_t *pEcMontTempBuff /*!< [in] Pointer to the temp buffer, for internal use. */); + + +/*******************************************************************/ +/*! +@brief The function generates private and public keys for Montgomery algorithms. + + The generation performed using given seed. + + +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECMONT_SeedKeyPair ( + uint8_t *pPublKey, /*!< [out] Pointer to the public (secret) key. */ + size_t *pPublKeySize, /*!< [in/out] Pointer to the size of the public key in bytes. + In - the size of buffer must be at least EC order size + (for curve25519 - 32 bytes); + Out - the actual size. */ + uint8_t *pSecrKey, /*!< [out] Pointer to the secret (private) key. */ + size_t *pSecrKeySize, /*!< [in/out] Pointer to the size of the secret key in bytes + In - the size of buffer must be at least EC order size + (for curve25519 - 32 bytes); + Out - the actual size. */ + const uint8_t *pSeed, /*!< [in] Pointer to the given seed - 32 bytes. */ + size_t seedSize, /*!< [in/] Size of the seed in bytes (must be equal to CRYS_ECMONT_SEEDBYTES). */ + CRYS_ECMONT_TempBuff_t *pEcMontTempBuff /*!< [in] Pointer to a temp buffer, for internal use. */); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + + diff --git a/external/nrf_cc310/include/crys_ec_mont_edw_error.h b/external/nrf_cc310/include/crys_ec_mont_edw_error.h new file mode 100644 index 0000000..2251b7d --- /dev/null +++ b/external/nrf_cc310/include/crys_ec_mont_edw_error.h @@ -0,0 +1,114 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_EC_MONT_EDW_ERROR_H +#define CRYS_EC_MONT_EDW_ERROR_H + +/*! +@file +@brief This module containes the definitions of the CRYS ECC-25519 errors. +@defgroup crys_ecmontedw_error CryptoCell ECC-25519 errors +@{ +@ingroup cryptocell_ec +*/ + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ + +/********************************************************************************************************** + * CRYS EC Montgomery-Edwards MODULE ERRORS base address - 0x00F02300 * + **********************************************************************************************************/ +/*! Illegal input pointer */ +#define CRYS_ECEDW_INVALID_INPUT_POINTER_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x00UL) +/*! Illegal input size */ +#define CRYS_ECEDW_INVALID_INPUT_SIZE_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x01UL) +/*! Illegal scalar size */ +#define CRYS_ECEDW_INVALID_SCALAR_SIZE_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x02UL) +/*! Illegal scalar data */ +#define CRYS_ECEDW_INVALID_SCALAR_DATA_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x03UL) +/*! Invalid RND context pointer */ +#define CRYS_ECEDW_RND_CONTEXT_PTR_INVALID_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x04UL) +/*! Invalid RND generate vector functions pointer */ +#define CRYS_ECEDW_RND_GEN_VECTOR_FUNC_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x05UL) +/*! Signing or verification operation failed */ +#define CRYS_ECEDW_SIGN_VERIFY_FAILED_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x20UL) +/*! Illegal input pointer */ +#define CRYS_ECMONT_INVALID_INPUT_POINTER_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x30UL) +/*! Illegal input size */ +#define CRYS_ECMONT_INVALID_INPUT_SIZE_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x31UL) +/*! Illegal domain id */ +#define CRYS_ECMONT_INVALID_DOMAIN_ID_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x32UL) +/*! Internal PKI error */ +#define CRYS_ECEDW_PKI_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x33UL) +/*! Internal PKI error */ +#define CRYS_ECMONT_PKI_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x34UL) + + +/************************************************************************************************************ + * NOT SUPPORTED MODULES ERROR IDs * + ************************************************************************************************************/ +/*! EC montgomery is not supported */ +#define CRYS_ECMONT_IS_NOT_SUPPORTED (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0xFEUL) +/*! EC edwards is not supported */ +#define CRYS_ECEDW_IS_NOT_SUPPORTED (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0xFFUL) + + + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs ******************************/ + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} +*/ +#endif + + diff --git a/external/nrf_cc310/include/crys_ecpki_build.h b/external/nrf_cc310/include/crys_ecpki_build.h new file mode 100644 index 0000000..5a48e21 --- /dev/null +++ b/external/nrf_cc310/include/crys_ecpki_build.h @@ -0,0 +1,224 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_ECPKI_BUILD_H +#define CRYS_ECPKI_BUILD_H + +/*! +@defgroup cryptocell_ecpki CryptoCell ECC APIs +@{ +@ingroup cryptocell_api +@brief This group is the cryptocell ECC root group +@} + +@file +@brief This module defines functions for building key structures used in Elliptic Curves Cryptography (ECC). +@defgroup crys_ecpki_build CryptoCell key build for ECC APIs +@{ +@ingroup cryptocell_ecpki +*/ + + +#include "crys_error.h" +#include "crys_ecpki_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/********************************************************************************** + * CRYS_ECPKI_BuildPrivKey function * + **********************************************************************************/ +/*! +@brief Builds (imports) the user private key structure from an existing private key so +that this structure can be used by other EC primitives. +This function should be called before using of the private key. Input +domain structure must be initialized by EC parameters and auxiliary +values, using CRYS_ECPKI_GetDomain or CRYS_ECPKI_SetDomain functions. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECPKI_BuildPrivKey( + const CRYS_ECPKI_Domain_t *pDomain, /*!< [in] The EC domain (curve). */ + const uint8_t *pPrivKeyIn, /*!< [in] Pointer to private key data. */ + uint32_t PrivKeySizeInBytes, /*!< [in] Size of private key data (in bytes). */ + CRYS_ECPKI_UserPrivKey_t *pUserPrivKey /*!< [out] Pointer to the private key structure. + This structure is used as input to the ECPKI cryptographic primitives. */ + ); + + +/********************************************************************************** + * CRYS_ECPKI_ExportPrivKey function * + **********************************************************************************/ +/*! +@brief Converts an existing private key from internal representation to Big-Endian export representation. +\note Size of output is equal to ModSizeInBytes. +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECPKI_ExportPrivKey( + CRYS_ECPKI_UserPrivKey_t *pUserPrivKey, /*!< [in] */ + uint8_t *pExportPrivKey, /*!< [out] */ + uint32_t *pPrivKeySizeBytes /*!< [in/out] */ + ); + + +/********************************************************************************** + * _DX_ECPKI_BuildPublKey function * + **********************************************************************************/ +/*! +@brief Builds a user public key structure from an imported public key, +so it can be used by other EC primitives. +When operating the EC cryptographic algorithms with imported EC public +key, this function should be called before using of the public key. + +\note The Incoming public key PublKeyIn structure is big endian bytes array, containing +concatenation of PC||X||Y, where: +
  • PC - point control single byte, defining the type of point: 0x4 - uncompressed, +06,07 - hybrid, 2,3 - compressed.
  • +
  • X,Y - EC point coordinates of public key (y is omitted in compressed form), +size of X and Y must be equal to size of EC modulus.
+ +The user may call this function by appropriate macros, according to necessary validation level [SEC1. ECC standard: 3.2, ANS X9.62]: +
  • Checking the input pointers and sizes only - ::CRYS_ECPKI_BuildPublKey.
  • +
  • Partially checking of public key - ::CRYS_ECPKI_BuildPublKeyPartlyCheck.
  • +
  • Full checking of public key - ::CRYS_ECPKI_BuildPublKeyFullCheck.
+ +\note Full check mode takes long time and should be used when it is actually needed. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h. +*/ +/* +The function performs the following operations: +- Checks validity of incoming variables and pointers; +- Converts incoming key data from big endian into little endian; +- If public key is given in compressed form (i.e. byte[0] = 2 or 3 and + coordinate Y is omitted), then the function uncompress it; +- Performs checking of input key according to CheckMode parameter. +- Initializes variables and structures. +*/ +CIMPORT_C CRYSError_t _DX_ECPKI_BuildPublKey( + const CRYS_ECPKI_Domain_t *pDomain, /*!< [in] The EC domain (curve). */ + uint8_t *PublKeyIn_ptr, /*!< [in] Pointer to the input public key data, in compressed or + uncompressed or hybrid form: + [PC||X||Y] Big-Endian representation, structured according to + [IEEE1363], where: +
  • X and Y are the public key's EC point coordinates. + In compressed form, Y is omitted.
  • +
  • The sizes of X and Y are equal to the size of the EC modulus.
  • +
  • PC is a one-byte point control that defines the type of point + compression.
*/ + uint32_t PublKeySizeInBytes, /*!< [in] The size of public key data (in bytes). */ + EC_PublKeyCheckMode_t CheckMode, /*!< [in] The required level of public key verification + (higher verification level means longer verification time): +
  • 0 = preliminary validation.
  • +
  • 1 = partial validation.
  • +
  • 2 = full validation.
*/ + CRYS_ECPKI_UserPublKey_t *pUserPublKey, /*!< [out] Pointer to the output public key structure. + This structure is used as input to the ECPKI cryptographic primitives. */ + CRYS_ECPKI_BUILD_TempData_t *pTempBuff /*!< [in] Pointer for a temporary buffer required for the build function. */ + ); + + +/********************************************************************************** + * CRYS_ECPKI_BuildPublKey macro * + **********************************************************************************/ +/*! +@brief This macro calls _DX_ECPKI_BuildPublKey function for building the public key +while checking input pointers and sizes. For a description of the parameters see ::_DX_ECPKI_BuildPublKey. +*/ +#define CRYS_ECPKI_BuildPublKey(pDomain, PublKeyIn_ptr, PublKeySizeInBytes, pUserPublKey) \ + _DX_ECPKI_BuildPublKey((pDomain), (PublKeyIn_ptr), (PublKeySizeInBytes), CheckPointersAndSizesOnly, (pUserPublKey), NULL) + + +/********************************************************************************** + * CRYS_ECPKI_BuildPublKeyPartlyCheck macro * + **********************************************************************************/ +/*! +@brief This macro calls _DX_ECPKI_BuildPublKey function for building the public key with partial validation of the key [SEC1] - 3.2.3. +For a description of the parameters see ::_DX_ECPKI_BuildPublKey. +*/ +#define CRYS_ECPKI_BuildPublKeyPartlyCheck(pDomain, PublKeyIn_ptr, PublKeySizeInBytes, pUserPublKey, pTempBuff) \ + _DX_ECPKI_BuildPublKey((pDomain), (PublKeyIn_ptr), (PublKeySizeInBytes), ECpublKeyPartlyCheck, (pUserPublKey), (pTempBuff)) + + +/********************************************************************************** + * CRYS_ECPKI_BuildPublKeyFullCheck macro * + **********************************************************************************/ +/*! +@brief This macro calls _DX_ECPKI_BuildPublKey function for building the public key with full validation of the key [SEC1] - 3.2.2. +For a description of the parameters and return values see _DX_ECPKI_BuildPublKey. +*/ +#define CRYS_ECPKI_BuildPublKeyFullCheck(pDomain, PublKeyIn_ptr, PublKeySizeInBytes, pUserPublKey, pTempBuff) \ + _DX_ECPKI_BuildPublKey((pDomain), (PublKeyIn_ptr), (PublKeySizeInBytes), (ECpublKeyFullCheck), (pUserPublKey), (pTempBuff)) + + +/*********************************************************************************** + * CRYS_ECPKI_ExportPublKey function * + ***********************************************************************************/ +/*! +@brief Converts an existing public key from internal representation to Big-Endian export representation. +The function converts the X,Y coordinates of public key EC point to big endianness, +and sets the public key as follows: +
  • In case "Uncompressed" point: PubKey = PC||X||Y, PC = 0x4 - single byte;
  • +
  • In case of "Hybrid" key PC = 0x6.
  • +
  • In case of "Compressed" key PC = 0x2.
+\note Size of output X and Y coordinates is equal to ModSizeInBytes. +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECPKI_ExportPublKey( + CRYS_ECPKI_UserPublKey_t *pUserPublKey, /*!< [in] Pointer to the input public key structure (in Little-Endian form). */ + CRYS_ECPKI_PointCompression_t compression, /*!< [in] Compression mode: Compressed, Uncompressed or Hybrid. */ + uint8_t *pExternPublKey, /*!< [out] Pointer to the exported public key array, in compressed or uncompressed + or hybrid form: + [PC||X||Y] Big-Endian representation, structured according to [IEEE1363]. + In compressed form, Y is omitted. */ + uint32_t *pPublKeySizeBytes /*!< [in/out] Pointer used for the input of the user public key buffer size + (in bytes), and the output of the size of the converted public key in bytes. */ + ); + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/crys_ecpki_dh.h b/external/nrf_cc310/include/crys_ecpki_dh.h new file mode 100644 index 0000000..5ed48ad --- /dev/null +++ b/external/nrf_cc310/include/crys_ecpki_dh.h @@ -0,0 +1,90 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_ECPKI_DH_H +#define CRYS_ECPKI_DH_H + +/*! @file +@brief Defines the API that supports EC Diffie-Hellman shared secret value derivation primitives. +@defgroup crys_ecpki_dh CryptoCell ECC Diffie-Hellman APIs +@{ +@ingroup cryptocell_ecpki +*/ + + +#include "crys_ecpki_types.h" +#include "crys_ecpki_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*********************************************************************** + * CRYS_ECDH_SVDP_DH function * + ***********************************************************************/ +/*! +@brief Creates the shared secret value according to [IEEE1363, ANS X9.63]: + +
  1. Checks input-parameter pointers and EC Domain in public and private +keys.
  2. +
  3. Derives the partner public key and calls the EcWrstDhDeriveSharedSecret +function, which performs EC SVDP operations.
+\note The term "User" +refers to any party that calculates a shared secret value using this primitive. +The term "Partner" refers to any other party of shared secret value calculation. +Partner's public key shall be validated before using in this primitive. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECDH_SVDP_DH( + CRYS_ECPKI_UserPublKey_t *PartnerPublKey_ptr, /*!< [in] Pointer to a partner public key. */ + CRYS_ECPKI_UserPrivKey_t *UserPrivKey_ptr, /*!< [in] Pointer to a user private key. */ + uint8_t *SharedSecretValue_ptr, /*!< [out] Pointer to an output buffer that will contain the shared + secret value. */ + uint32_t *SharedSecrValSize_ptr, /*!< [in/out] Pointer to the size of user-passed buffer (in) and + actual size of output of calculated shared secret value + (out). */ + CRYS_ECDH_TempData_t *TempBuff_ptr /*!< [in] Pointer to a temporary buffer. */); + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/crys_ecpki_domain.h b/external/nrf_cc310/include/crys_ecpki_domain.h new file mode 100644 index 0000000..c8faaea --- /dev/null +++ b/external/nrf_cc310/include/crys_ecpki_domain.h @@ -0,0 +1,80 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_ECPKI_DOMAIN_H +#define CRYS_ECPKI_DOMAIN_H + + +/*! +@file +@brief Defines the ecpki build domain API. +@defgroup crys_ecpki_domain CryptoCell ECC domain APIs +@{ +@ingroup cryptocell_ecpki +*/ + + +#include "crys_error.h" +#include "crys_ecpki_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + + + +/********************************************************************************** + * CRYS_ECPKI_GetEcDomain function * + **********************************************************************************/ + +/*! + * @brief The function returns a pointer to an ECDSA saved domain (one of the supported domains). + * + * @return Domain pointer on success. + * @return NULL on failure. + */ + +const CRYS_ECPKI_Domain_t *CRYS_ECPKI_GetEcDomain(CRYS_ECPKI_DomainID_t domainId /*!< [in] Index of one of the domain Id (must be one of the supported domains). */); + +#ifdef __cplusplus +} +#endif +/** +@} +*/ +#endif diff --git a/external/nrf_cc310/include/crys_ecpki_ecdsa.h b/external/nrf_cc310/include/crys_ecpki_ecdsa.h new file mode 100644 index 0000000..13138c5 --- /dev/null +++ b/external/nrf_cc310/include/crys_ecpki_ecdsa.h @@ -0,0 +1,139 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_ECPKI_ECDSA_H +#define CRYS_ECPKI_ECDSA_H + +/*! +@file +@brief Defines the APIs that support the ECDSA functions. +@defgroup crys_ecpki_ecdsa CryptoCell ECDSA APIs +@{ +@ingroup cryptocell_ecpki +*/ + +#include "crys_error.h" +#include "crys_ecpki_types.h" +#include "crys_hash.h" +#include "crys_rnd.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + + +/************************************************************************** + * CRYS_ECDSA_Sign - integrated function + **************************************************************************/ +/*! +@brief This function performs an ECDSA sign operation in integrated form. + +\note +Using of HASH functions with HASH size greater than EC modulus size, is not recommended!. +Algorithm according [ANS X9.62] standard. + +The message data may be either a non-hashed data or a digest of a hash function. +For a non-hashed data, the message data will be hashed using the hash function indicated by ::CRYS_ECPKI_HASH_OpMode_t. +For a digest, ::CRYS_ECPKI_HASH_OpMode_t should indicate the hash function that the message data was created by, and it will not be hashed. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h, crys_hash_error.h or crys_rnd_error.h. +**/ +CIMPORT_C CRYSError_t CRYS_ECDSA_Sign( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + CRYS_ECDSA_SignUserContext_t *pSignUserContext, /*!< [in/out] Pointer to the user buffer for signing the database. */ + CRYS_ECPKI_UserPrivKey_t *pSignerPrivKey, /*!< [in] A pointer to a user private key structure. */ + CRYS_ECPKI_HASH_OpMode_t hashMode, /*!< [in] One of the supported SHA-x HASH modes, as defined in + ::CRYS_ECPKI_HASH_OpMode_t. + \note MD5 is not supported. */ + uint8_t *pMessageDataIn, /*!< [in] Pointer to the input data to be signed. + The size of the scatter/gather list representing the data buffer + is limited to 128 entries, and the size of each entry is limited + to 64KB (fragments larger than 64KB are broken into + fragments <= 64KB). */ + uint32_t messageSizeInBytes, /*!< [in] Size of message data in bytes. */ + uint8_t *pSignatureOut, /*!< [in] Pointer to a buffer for output of signature. */ + uint32_t *pSignatureOutSize /*!< [in/out] Pointer to the signature size. Used to pass the size of + the SignatureOut buffer (in), which must be >= 2 + * OrderSizeInBytes. When the API returns, + it is replaced with the size of the actual signature (out). */ + ); + + + +/************************************************************************** + * CRYS_ECDSA_Verify integrated function + **************************************************************************/ +/*! +@brief This function performs an ECDSA verify operation in integrated form. +Algorithm according [ANS X9.62] standard. + +The message data may be either a non-hashed data or a digest of a hash function. +For a non-hashed data, the message data will be hashed using the hash function indicated by ::CRYS_ECPKI_HASH_OpMode_t. +For a digest, ::CRYS_ECPKI_HASH_OpMode_t should indicate the hash function that the message data was created by, and it will not be hashed. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECDSA_Verify ( + CRYS_ECDSA_VerifyUserContext_t *pVerifyUserContext, /*!< [in] Pointer to the user buffer for signing the database. */ + CRYS_ECPKI_UserPublKey_t *pUserPublKey, /*!< [in] Pointer to a user public key structure. */ + CRYS_ECPKI_HASH_OpMode_t hashMode, /*!< [in] One of the supported SHA-x HASH modes, as defined in + ::CRYS_ECPKI_HASH_OpMode_t. + \note MD5 is not supported. */ + uint8_t *pSignatureIn, /*!< [in] Pointer to the signature to be verified. */ + uint32_t SignatureSizeBytes, /*!< [in] Size of the signature (in bytes). */ + uint8_t *pMessageDataIn, /*!< [in] Pointer to the input data that was signed (same as given to + the signing function). The size of the scatter/gather list representing + the data buffer is limited to 128 entries, and the size of each entry is + limited to 64KB (fragments larger than 64KB are broken into fragments <= 64KB). */ + uint32_t messageSizeInBytes /*!< [in] Size of the input data (in bytes). */ + ); + + +/**********************************************************************************************************/ + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/crys_ecpki_error.h b/external/nrf_cc310/include/crys_ecpki_error.h new file mode 100644 index 0000000..950dce0 --- /dev/null +++ b/external/nrf_cc310/include/crys_ecpki_error.h @@ -0,0 +1,317 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_ECPKI_ERROR_H +#define CRYS_ECPKI_ERROR_H + + +/*! +@file +@brief This module contains the definitions of the CRYS ECPKI errors. +@defgroup crys_ecpki_error CryptoCell ECC specific errors +@{ +@ingroup cryptocell_ecpki +*/ + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ + +/* CRYS_ECPKI_MODULE_ERROR_BASE = 0x00F00800 */ + +/********************************************************************************************* + * CRYS ECPKI MODULE ERRORS * + *********************************************************************************************/ +/*! Illegal domain ID. */ +#define CRYS_ECPKI_ILLEGAL_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x1UL) +/*! Illegal domain pointer. */ +#define CRYS_ECPKI_DOMAIN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x2UL) +/* The CRYS ECPKI GEN KEY PAIR module errors */ +/*! Illegal private key pointer. */ +#define CRYS_ECPKI_GEN_KEY_INVALID_PRIVATE_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x3UL) +/*! Illegal public key pointer. */ +#define CRYS_ECPKI_GEN_KEY_INVALID_PUBLIC_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x4UL) +/*! Illegal temporary buffer pointer. */ +#define CRYS_ECPKI_GEN_KEY_INVALID_TEMP_DATA_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x5UL) +/*! Illegal RND context pointer. */ +#define CRYS_ECPKI_RND_CONTEXT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x6UL) + +/************************************************************************************************************ +* The CRYS ECPKI BUILD KEYS MODULE ERRORS * +*************************************************************************************************************/ +/*! Illegal compression mode. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_COMPRESSION_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x07UL) +/*! Illegal domain ID. */ +#define CRYS_ECPKI_BUILD_KEY_ILLEGAL_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x08UL) +/*! Illegal private key pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PRIV_KEY_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x09UL) +/*! Illegal private key structure pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_USER_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0AUL) +/*! Illegal private key size. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PRIV_KEY_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0BUL) +/*! Illegal private key data. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PRIV_KEY_DATA_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0CUL) +/*! Illegal public key pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0DUL) +/*! Illegal public key structure pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_USER_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0EUL) +/*! Illegal public key size. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0FUL) +/*! Illegal public key data. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_DATA_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x10UL) +/*! Illegal EC build check mode option. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_CHECK_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x11UL) +/*! Illegal temporary buffer pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_TEMP_BUFF_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x12UL) + +/* The CRYS ECPKI EXPORT PUBLIC KEY MODULE ERRORS */ +/*! Illegal public key structure pointer. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_USER_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x14UL) +/*! Illegal public key compression mode. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_ILLEGAL_COMPRESSION_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x15UL) +/*! Illegal output public key pointer. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_EXTERN_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x16UL) +/*! Illegal output public key size pointer. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_SIZE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x17UL) +/*! Illegal output public key size. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x18UL) +/*! Illegal domain ID. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_ILLEGAL_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x19UL) +/*! Validation of public key failed. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_ILLEGAL_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x1AUL) +/*! Validation of public key failed. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_DATA_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x1BUL) + +/* The CRYS ECPKI EXPORT PRIVATE KEY MODULE ERRORS */ +/*! Illegal private key structure pointer. */ +#define CRYS_ECPKI_EXPORT_PRIV_KEY_INVALID_USER_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xC0UL) +/*! Illegal output private key pointer. */ +#define CRYS_ECPKI_EXPORT_PRIV_KEY_INVALID_EXTERN_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xC1UL) +/*! Validation of private key failed. */ +#define CRYS_ECPKI_EXPORT_PRIV_KEY_ILLEGAL_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xC2UL) +/*! Illegal output private key size pointer. */ +#define CRYS_ECPKI_EXPORT_PRIV_KEY_INVALID_PRIV_KEY_SIZE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xC3UL) +/*! Illegal output private key size. */ +#define CRYS_ECPKI_EXPORT_PRIV_KEY_INVALID_PRIV_KEY_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xC4UL) +/*! Validation of private key failed. */ +#define CRYS_ECPKI_EXPORT_PRIV_KEY_INVALID_PRIV_KEY_DATA_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xC5UL) + +/* The CRYS ECPKI BUILD ECC DOMAIN ERRORS */ +/*! Illegal domain ID. */ +#define CRYS_ECPKI_BUILD_DOMAIN_ID_IS_NOT_VALID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x20UL) +/*! Illegal domain ID pointer. */ +#define CRYS_ECPKI_BUILD_DOMAIN_DOMAIN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x21UL) +/*! Illegal domain parameter pointer. */ +#define CRYS_ECPKI_BUILD_DOMAIN_EC_PARAMETR_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x22UL) +/*! Illegal domain parameter size. */ +#define CRYS_ECPKI_BUILD_DOMAIN_EC_PARAMETR_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x23UL) +/*! Illegal domain cofactor parameters. */ +#define CRYS_ECPKI_BUILD_DOMAIN_COFACTOR_PARAMS_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x24UL) +/*! Insufficient strength. */ +#define CRYS_ECPKI_BUILD_DOMAIN_SECURITY_STRENGTH_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x25UL) +/*! SCA resistance error. */ +#define CRYS_ECPKI_BUILD_SCA_RESIST_ILLEGAL_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x26UL) + + +/*! Internal PKI error */ +#define CRYS_ECPKI_PKI_INTERNAL_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x30UL) + +/************************************************************************************************************ + * CRYS EC DIFFIE-HELLMAN MODULE ERRORS +*************************************************************************************************************/ +/* The CRYS EC SVDP_DH Function errors */ +/*! Illegal partner's public key pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_PARTNER_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x31UL) +/*! Partner's public key validation failed. */ +#define CRYS_ECDH_SVDP_DH_PARTNER_PUBL_KEY_VALID_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x32UL) +/*! Illegal user private key pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_USER_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x33UL) +/*! Private key validation failed. */ +#define CRYS_ECDH_SVDP_DH_USER_PRIV_KEY_VALID_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x34UL) +/*! Illegal shared secret pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_SHARED_SECRET_VALUE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x35UL) +/*! Illegal temporary buffer pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_TEMP_DATA_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x36UL) +/*! Illegal shared secret size pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_SHARED_SECRET_VALUE_SIZE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x37UL) +/*! Illegal shared secret size. */ +#define CRYS_ECDH_SVDP_DH_INVALID_SHARED_SECRET_VALUE_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x38UL) +/*! Illegal domain ID. */ +#define CRYS_ECDH_SVDP_DH_ILLEGAL_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x39UL) +/*! Illegal private and public domain ID are different. */ +#define CRYS_ECDH_SVDP_DH_NOT_CONCENT_PUBL_AND_PRIV_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x3AUL) + + +/************************************************************************************************************ + * CRYS ECDSA MODULE ERRORS + ************************************************************************************************************/ +/* The CRYS ECDSA Signing errors */ +/*! Illegal domain ID. */ +#define CRYS_ECDSA_SIGN_INVALID_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x50UL) +/*! Illegal context pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_USER_CONTEXT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x51UL) +/*! Illegal private key pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_USER_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x52UL) +/*! Illegal hash operation mode. */ +#define CRYS_ECDSA_SIGN_ILLEGAL_HASH_OP_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x53UL) +/*! Illegal data in pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_MESSAGE_DATA_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x54UL) +/*! Illegal data in size. */ +#define CRYS_ECDSA_SIGN_INVALID_MESSAGE_DATA_IN_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x55UL) +/*! Context validation failed. */ +#define CRYS_ECDSA_SIGN_USER_CONTEXT_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x57UL) +/*! User's private key validation failed. */ +#define CRYS_ECDSA_SIGN_USER_PRIV_KEY_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x58UL) +/*! Illegal signature pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x60UL) +/*! Illegal signature size pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_SIZE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x61UL) +/*! Illegal signature size. */ +#define CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x62UL) +/*! Ephemeral key error. */ +#define CRYS_ECDSA_SIGN_INVALID_IS_EPHEMER_KEY_INTERNAL_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x63UL) +/*! Illegal ephemeral key pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_EPHEMERAL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x64UL) +/*! Illegal RND context pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_RND_CONTEXT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x65UL) +/*! Illegal RND function pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_RND_FUNCTION_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x66UL) +/*! Signature calculation failed. */ +#define CRYS_ECDSA_SIGN_SIGNING_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x67UL) + +/* The CRYS ECDSA Verifying errors */ +/*! Illegal domain ID. */ +#define CRYS_ECDSA_VERIFY_INVALID_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x70UL) +/*! Illegal user's context pointer. */ +#define CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x71UL) +/*! Illegal public key pointer. */ +#define CRYS_ECDSA_VERIFY_INVALID_SIGNER_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x72UL) +/*! Illegal hash operation mode. */ +#define CRYS_ECDSA_VERIFY_ILLEGAL_HASH_OP_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x73UL) +/*! Illegal signature pointer. */ +#define CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x76UL) +/*! Illegal signature size. */ +#define CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x77UL) +/*! Illegal data in pointer. */ +#define CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x80UL) +/*! Illegal data in size. */ +#define CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x81UL) +/*! Context validation failed. */ +#define CRYS_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x82UL) +/*! public key validation failed. */ +#define CRYS_ECDSA_VERIFY_SIGNER_PUBL_KEY_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x83UL) +/*! Verification failed. */ +#define CRYS_ECDSA_VERIFY_INCONSISTENT_VERIFY_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x84UL) + +/*! Illegal parameters. */ +#define CRYS_ECC_ILLEGAL_PARAMS_ACCORDING_TO_PRIV_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xD3UL) +/*! Illegal hash mode. */ +#define CRYS_ECC_ILLEGAL_HASH_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE0UL) + + +/************************************************************************************************************ + * CRYS ECPKI MODULE COMMON ERRORS +*************************************************************************************************************/ +/*! Illegal RND function pointer. */ +#define CRYS_ECPKI_INVALID_RND_FUNC_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x90UL) +/*! Illegal RND context pointer. */ +#define CRYS_ECPKI_INVALID_RND_CTX_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x91UL) +/*! Illegal domain ID. */ +#define CRYS_ECPKI_INVALID_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x92UL) +/*! Private key validation failed. */ +#define CRYS_ECPKI_INVALID_PRIV_KEY_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x93UL) +/*! Public key validation failed. */ +#define CRYS_ECPKI_INVALID_PUBL_KEY_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x94UL) +/*! Illegal data in. */ +#define CRYS_ECPKI_INVALID_DATA_IN_PASSED_STRUCT_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x95UL) + +/************************************************************************************************************ + * CRYS ECIES MODULE ERRORS +*************************************************************************************************************/ +/*! Illegal public key pointer. */ +#define CRYS_ECIES_INVALID_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE0UL) +/*! Public key validation failed. */ +#define CRYS_ECIES_INVALID_PUBL_KEY_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE1UL) +/*! Illegal private key pointer. */ +#define CRYS_ECIES_INVALID_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE2UL) +/*! Private key validation failed. */ +#define CRYS_ECIES_INVALID_PRIV_KEY_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE3UL) +/*! Illegal private key value. */ +#define CRYS_ECIES_INVALID_PRIV_KEY_VALUE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE4UL) +/*! Illegal KDF derivation mode. */ +#define CRYS_ECIES_INVALID_KDF_DERIV_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE5UL) +/*! Illegal KDF hash mode. */ +#define CRYS_ECIES_INVALID_KDF_HASH_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE6UL) +/*! Illegal secret key pointer. */ +#define CRYS_ECIES_INVALID_SECRET_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE7UL) +/*! Illegal secret key size. */ +#define CRYS_ECIES_INVALID_SECRET_KEY_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE8UL) +/*! Illegal cipher data pointer. */ +#define CRYS_ECIES_INVALID_CIPHER_DATA_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE9UL) +/*! Illegal cipher data size pointer. */ +#define CRYS_ECIES_INVALID_CIPHER_DATA_SIZE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xEAUL) +/*! Illegal cipher data size. */ +#define CRYS_ECIES_INVALID_CIPHER_DATA_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xEBUL) +/*! Illegal temporary buffer pointer. */ +#define CRYS_ECIES_INVALID_TEMP_DATA_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xECUL) +/*! Illegal ephemeral key pointer */ +#define CRYS_ECIES_INVALID_EPHEM_KEY_PAIR_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xEDUL) + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs ******************************/ + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/crys_ecpki_kg.h b/external/nrf_cc310/include/crys_ecpki_kg.h new file mode 100644 index 0000000..2279c25 --- /dev/null +++ b/external/nrf_cc310/include/crys_ecpki_kg.h @@ -0,0 +1,88 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_ECPKI_KG_H +#define CRYS_ECPKI_KG_H + +/*! @file +@brief Defines the API for generation of ECC private and public keys. +@defgroup crys_ecpki_kg CryptoCell ECC Key Generation APIs +@{ +@ingroup cryptocell_ecpki +*/ + + +#include "crys_error.h" +#include "crys_rnd.h" +#include "crys_ecpki_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/***************** CRYS_ECPKI_GenKeyPair function **********************/ +/*! +@brief Generates a pair of private and public keys in internal representation according to [ANS X9.62]. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h or crys_rnd_error.h +*/ +CIMPORT_C CRYSError_t CRYS_ECPKI_GenKeyPair( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + const CRYS_ECPKI_Domain_t *pDomain, /*!< [in] Pointer to EC domain (curve). */ + CRYS_ECPKI_UserPrivKey_t *pUserPrivKey, /*!< [out] Pointer to the private key structure. This structure is used as input to the + ECPKI cryptographic primitives. */ + CRYS_ECPKI_UserPublKey_t *pUserPublKey, /*!< [out] Pointer to the public key structure. This structure is used as input to the + ECPKI cryptographic primitives. */ + CRYS_ECPKI_KG_TempData_t *pTempData, /*!< [in] Temporary buffers for internal use, defined in ::CRYS_ECPKI_KG_TempData_t. */ + CRYS_ECPKI_KG_FipsContext_t *pFipsCtx /*!< [in] Pointer to temporary buffer used in case FIPS certification if required. */ +); + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + + + diff --git a/external/nrf_cc310/include/crys_ecpki_types.h b/external/nrf_cc310/include/crys_ecpki_types.h new file mode 100644 index 0000000..f32aa77 --- /dev/null +++ b/external/nrf_cc310/include/crys_ecpki_types.h @@ -0,0 +1,478 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_ECPKI_TYPES_H +#define CRYS_ECPKI_TYPES_H + +/*! +@file +@brief Contains all of the enums and definitions that are used for the CRYS ECPKI APIs. +@defgroup crys_ecpki_types CryptoCell ECC specific types +@{ +@ingroup cryptocell_ecpki +*/ + +#include "ssi_pal_types_plat.h" +#include "crys_hash.h" +#include "crys_pka_defs_hw.h" +#include "ssi_pal_compiler.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ +/*! Internal buffer size in words. */ +#define CRYS_PKA_DOMAIN_LLF_BUFF_SIZE_IN_WORDS (10 + 3*CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS) + +/************************************************************************************** + * Enumerators + ***************************************************************************************/ + +/*------------------------------------------------------------------*/ +/*! Enumerator for the EC Domain idetifier + References: [13] - SEC 2: Recommended elliptic curve domain parameters. + Version 1.0. Certicom 2000. + [8] - WAP-261-WTLS-20010406-a, Version 06-April-2001. */ + +typedef enum +{ + /* For prime field */ + CRYS_ECPKI_DomainID_secp160k1, /*!< EC secp160r1 */ + CRYS_ECPKI_DomainID_secp160r1, /*!< EC secp160k1 */ + CRYS_ECPKI_DomainID_secp160r2, /*!< EC secp160r2 */ + CRYS_ECPKI_DomainID_secp192k1, /*!< EC secp192k1 */ + CRYS_ECPKI_DomainID_secp192r1, /*!< EC secp192r1 */ + CRYS_ECPKI_DomainID_secp224k1, /*!< EC secp224k1 */ + CRYS_ECPKI_DomainID_secp224r1, /*!< EC secp224r1 */ + CRYS_ECPKI_DomainID_secp256k1, /*!< EC secp256k1 */ + CRYS_ECPKI_DomainID_secp256r1, /*!< EC secp256r1 */ + CRYS_ECPKI_DomainID_secp384r1, /*!< EC secp384r1 */ + CRYS_ECPKI_DomainID_secp521r1, /*!< EC secp521r1 */ + + CRYS_ECPKI_DomainID_Builded, /*!< User given, not identified. */ + CRYS_ECPKI_DomainID_OffMode, /*!< Reserved.*/ + + CRYS_ECPKI_DomainIDLast = 0x7FFFFFFF, /*! Reserved.*/ + +}CRYS_ECPKI_DomainID_t; + + +/*------------------------------------------------------------------*/ +/*! Defines the enum for the HASH operation mode. + * The enumerator defines 6 HASH modes according to IEEE 1363. + * + */ +typedef enum +{ + CRYS_ECPKI_HASH_SHA1_mode = 0, /*!< The message data will be hashed with SHA1. */ + CRYS_ECPKI_HASH_SHA224_mode = 1, /*!< The message data will be hashed with SHA224. */ + CRYS_ECPKI_HASH_SHA256_mode = 2, /*!< The message data will be hashed with SHA256. */ + CRYS_ECPKI_HASH_SHA384_mode = 3, /*!< The message data will be hashed with SHA384. */ + CRYS_ECPKI_HASH_SHA512_mode = 4, /*!< The message data will be hashed with SHA512. */ + + CRYS_ECPKI_AFTER_HASH_SHA1_mode = 5, /*!< The message data is a digest of SHA1 and will not be hashed. */ + CRYS_ECPKI_AFTER_HASH_SHA224_mode = 6, /*!< The message data is a digest of SHA224 and will not be hashed. */ + CRYS_ECPKI_AFTER_HASH_SHA256_mode = 7, /*!< The message data is a digest of SHA256 and will not be hashed. */ + CRYS_ECPKI_AFTER_HASH_SHA384_mode = 8, /*!< The message data is a digest of SHA384 and will not be hashed. */ + CRYS_ECPKI_AFTER_HASH_SHA512_mode = 9, /*!< The message data is a digest of SHA512 and will not be hashed. */ + + + CRYS_ECPKI_HASH_NumOfModes, /*!< Maximal number of HASH modes. */ + CRYS_ECPKI_HASH_OpModeLast = 0x7FFFFFFF, /*!< Reserved. */ + +}CRYS_ECPKI_HASH_OpMode_t; + + +/*---------------------------------------------------*/ +/*! Enumerator for the EC point compression idetifier. */ +typedef enum +{ + CRYS_EC_PointCompressed = 2, /*!< Compressed point. */ + CRYS_EC_PointUncompressed = 4, /*!< Uncompressed point. */ + CRYS_EC_PointContWrong = 5, /*!< Wrong Point Control value. */ + CRYS_EC_PointHybrid = 6, /*!< Hybrid point. */ + + CRYS_EC_PointCompresOffMode = 8, /*!< Reserved. */ + + CRYS_ECPKI_PointCompressionLast= 0x7FFFFFFF, /*!< Reserved. */ + +}CRYS_ECPKI_PointCompression_t; + + +/*! EC key checks defintions. */ +typedef enum { + CheckPointersAndSizesOnly = 0, /*!< Only preliminary input parameters are checked. */ + ECpublKeyPartlyCheck = 1, /*!< Preliminary input parameters check and verify that EC PubKey point is on the curve. */ + ECpublKeyFullCheck = 2, /*!< All the above and in addition verifies that EC_GeneratorOrder*PubKey = O */ + + PublKeyChecingOffMode, /*! Reserved. */ + EC_PublKeyCheckModeLast = 0x7FFFFFFF, /*! Reserved. */ +}EC_PublKeyCheckMode_t; + +/*----------------------------------------------------*/ +/*! Defintion of sw SCA protection. */ +typedef enum { + SCAP_Inactive, /*! Inactive.*/ + SCAP_Active, /*! Active.*/ + SCAP_OFF_MODE, /*! Reserved. */ + SCAP_LAST = 0x7FFFFFFF /*! Reserved. */ +} CRYS_ECPKI_ScaProtection_t; + + +/************************************************************************************** + * EC Domain structure definition + ***************************************************************************************/ + +/*! The structure containing the EC domain parameters in little-endian form + EC equation: Y^2 = X^3 + A*X + B over prime fild GFp. */ +typedef struct { + + /*! EC modulus: P. */ + uint32_t ecP [CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! EC equation parameter a. */ + uint32_t ecA [CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! EC equation parameter b. */ + uint32_t ecB [CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! Order of generator. */ + uint32_t ecR [CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS + 1]; + /*! EC cofactor EC_Cofactor_K + Generator (EC base point) coordinates in projective form. */ + uint32_t ecGx [CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! EC cofactor EC_Cofactor_K + Generator (EC base point) coordinates in projective form. */ + uint32_t ecGy [CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! EC cofactor EC_Cofactor_K + Generator (EC base point) coordinates in projective form. */ + uint32_t ecH; + /*! Specific fields that are used by the low level.*/ + uint32_t llfBuff[CRYS_PKA_DOMAIN_LLF_BUFF_SIZE_IN_WORDS]; + /*! Size of fields in bits. */ + uint32_t modSizeInBits; + /*! Order size in bits. */ + uint32_t ordSizeInBits; + /*! Size of each inserted Barret tag in words; 0 - if not inserted.*/ + uint32_t barrTagSizeInWords; + /*! EC Domain identifier.*/ + CRYS_ECPKI_DomainID_t DomainID; + + /*! Internal buffer. */ + int8_t name[20]; + +} CRYS_ECPKI_Domain_t; + + + +/************************************************************************************** + * EC point structures definitions + ***************************************************************************************/ + +/*! The structure containing the EC point in affine coordinates + and little endian form. */ +typedef struct +{ + /*! Point coordinate X. */ + uint32_t x[CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! Point coordinate Y. */ + uint32_t y[CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + +}CRYS_ECPKI_PointAffine_t; + + +/************************************************************************************** + * ECPKI public and private key Structures + ***************************************************************************************/ + +/* --------------------------------------------------------------------- */ +/* .................. The public key structures definitions ............ */ +/* --------------------------------------------------------------------- */ + +/*! The structure containing the Public Key in affine coordinates.*/ +typedef struct +{ + /*! Public Key coordinate X.*/ + uint32_t x[CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! Public Key coordinate Y.*/ + uint32_t y[CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! EC Domain.*/ + CRYS_ECPKI_Domain_t domain; + /*! Point type.*/ + uint32_t pointType; +} CRYS_ECPKI_PublKey_t; + +/*! The EC public key's user structure prototype. This structure must be saved by the user, and is used as input to the ECC functions +(such as ::CRYS_ECDSA_Verify etc.). */ +typedef struct CRYS_ECPKI_UserPublKey_t +{ + /*! Validation tag.*/ + uint32_t valid_tag; + /*! Public key data. */ + uint32_t PublKeyDbBuff[(sizeof(CRYS_ECPKI_PublKey_t)+3)/4]; + +} CRYS_ECPKI_UserPublKey_t; + + +/* --------------------------------------------------------------------- */ +/* .................. The private key structures definitions ........... */ +/* --------------------------------------------------------------------- */ + +/*! Structure containing the Private key data. */ +typedef struct +{ + /*! Private Key data. */ + uint32_t PrivKey[CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS + 1]; + /*! Domain. */ + CRYS_ECPKI_Domain_t domain; + /*! SCA protection mode. */ + CRYS_ECPKI_ScaProtection_t scaProtection; + +}CRYS_ECPKI_PrivKey_t; + + +/*! The EC private key's user structure prototype. This structure must be saved by the user, and is used as input to the ECC functions +(such as ::CRYS_ECDSA_Sign etc.). */ +typedef struct CRYS_ECPKI_UserPrivKey_t +{ + /*! Validation tag. */ + uint32_t valid_tag; + /*! Private key data. */ + uint32_t PrivKeyDbBuff[(sizeof(CRYS_ECPKI_PrivKey_t)+3)/4]; + +} CRYS_ECPKI_UserPrivKey_t; + +/*! ECDH temporary data type */ +typedef struct CRYS_ECDH_TempData_t +{ + /*! Temporary buffers. */ + uint32_t crysEcdhIntBuff[CRYS_PKA_ECDH_BUFF_MAX_LENGTH_IN_WORDS]; +}CRYS_ECDH_TempData_t; + +/*! EC build temporary data. */ +typedef struct CRYS_ECPKI_BUILD_TempData_t +{ + /*! Temporary buffers. */ + uint32_t crysBuildTmpIntBuff[CRYS_PKA_ECPKI_BUILD_TMP_BUFF_MAX_LENGTH_IN_WORDS]; +}CRYS_ECPKI_BUILD_TempData_t; + + + +/************************************************************************** + * CRYS ECDSA context structures + **************************************************************************/ + +/* --------------------------------------------------------------------- */ +/* CRYS ECDSA Signing context structure */ +/* --------------------------------------------------------------------- */ +/*! Internal buffer used in the signing process. */ +typedef uint32_t CRYS_ECDSA_SignIntBuff[CRYS_PKA_ECDSA_SIGN_BUFF_MAX_LENGTH_IN_WORDS]; + +/*! Context definition for Signing operation. */ +typedef struct +{ + /*! Private Key data. */ + CRYS_ECPKI_UserPrivKey_t ECDSA_SignerPrivKey; + + /*! HASH context. */ + CRYS_HASHUserContext_t hashUserCtxBuff; + /*! HASH result buffer. */ + CRYS_HASH_Result_t hashResult; + /*! HASH result size in words. */ + uint32_t hashResultSizeWords; + /*! HASH mode. */ + CRYS_ECPKI_HASH_OpMode_t hashMode; + /*! Internal buffer. */ + CRYS_ECDSA_SignIntBuff crysEcdsaSignIntBuff; +}ECDSA_SignContext_t; + + +/* --------------------------------------------------------------------- */ +/* CRYS ECDSA Signing User context database */ +/* --------------------------------------------------------------------- */ + +/*! User's context definition for signing operation. The context saves the state of the operation and must be saved by the user + till the end of the APIs flow */ +typedef struct CRYS_ECDSA_SignUserContext_t +{ + /*! Signing process data. */ + uint32_t context_buff [(sizeof(ECDSA_SignContext_t)+3)/4]; + /*! Validation tag*/ + uint32_t valid_tag; +} CRYS_ECDSA_SignUserContext_t; + + + +/****************************************************************************/ + +/* --------------------------------------------------------------------- */ +/* CRYS ECDSA Verifying context structure */ +/* --------------------------------------------------------------------- */ +/*! Internal buffer used in the verification process. */ +typedef uint32_t CRYS_ECDSA_VerifyIntBuff[CRYS_PKA_ECDSA_VERIFY_BUFF_MAX_LENGTH_IN_WORDS]; + +/*! Context definition for verification operation. */ +typedef struct +{ + /*! Public key data. */ + CRYS_ECPKI_UserPublKey_t ECDSA_SignerPublKey; + + /*! HASH context. */ + CRYS_HASHUserContext_t hashUserCtxBuff; + /*! HASH result. */ + CRYS_HASH_Result_t hashResult; + /*! HASH result size in words. */ + uint32_t hashResultSizeWords; + /*! HASH mode. */ + CRYS_ECPKI_HASH_OpMode_t hashMode; + /*! Internal buffer. */ + CRYS_ECDSA_VerifyIntBuff crysEcdsaVerIntBuff; + +}ECDSA_VerifyContext_t; + + +/* --------------------------------------------------------------------- */ +/* CRYS ECDSA Verifying User context database */ +/* --------------------------------------------------------------------- */ +/*! User's context definition for verification operation. The context saves the state of the operation and must be saved by the user + till the end of the APIs flow */ +typedef struct CRYS_ECDSA_VerifyUserContext_t +{ + /*! Verification process data. */ + uint32_t context_buff[(sizeof(ECDSA_VerifyContext_t)+3)/4]; + /*! Validation tag. */ + uint32_t valid_tag; +}CRYS_ECDSA_VerifyUserContext_t; + + + + +/* --------------------------------------------------------------------- */ +/* .................. key generation temp buffer ........... */ +/* --------------------------------------------------------------------- */ + +/*! ECPKI KG temporary data type */ +typedef struct CRYS_ECPKI_KG_TempData_t +{ + /*! Internal buffer. */ + uint32_t crysKGIntBuff[CRYS_PKA_KG_BUFF_MAX_LENGTH_IN_WORDS]; +}CRYS_ECPKI_KG_TempData_t; + +/*! ECIES temporary data definition. */ +typedef struct CRYS_ECIES_TempData_t { + + /*! Private key data. */ + CRYS_ECPKI_UserPrivKey_t PrivKey; + /*! Public key data. */ + CRYS_ECPKI_UserPublKey_t PublKey; + /*! Internal buffer. */ + uint32_t zz[3*CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS + 1]; + /*! Internal buffers. */ + union { + CRYS_ECPKI_BUILD_TempData_t buildTempbuff; + CRYS_ECPKI_KG_TempData_t KgTempBuff; + CRYS_ECDH_TempData_t DhTempBuff; + } tmp; + +}CRYS_ECIES_TempData_t; + + +/* --------------------------------------------------------------------- */ +/* .................. defines for FIPS ........... */ +/* --------------------------------------------------------------------- */ + +/*! Order length for the FIPS ECC tests. */ +#define CRYS_ECPKI_FIPS_ORDER_LENGTH (256/SASI_BITS_IN_BYTE) // the order of secp256r1 in bytes + +/*! Context definition required for internal FIPS verification for ECPKI key generation. */ +typedef struct CRYS_ECPKI_KG_FipsContext_t +{ + /*! Signing and verification data. */ + union { + CRYS_ECDSA_SignUserContext_t signCtx; + CRYS_ECDSA_VerifyUserContext_t verifyCtx; + }operationCtx; + /*! Internal buffer. */ + uint32_t signBuff[2*CRYS_ECPKI_ORDER_MAX_LENGTH_IN_WORDS]; +}CRYS_ECPKI_KG_FipsContext_t; + + + +/*! Context defintion, required for internal FIPS verification for ECDSA KAT. * +* The ECDSA KAT tests defined for domain 256r1. */ +typedef struct CRYS_ECDSAFipsKatContext_t{ + /*! Key data. */ + union { + /*! Private key data. */ + struct { + CRYS_ECPKI_UserPrivKey_t PrivKey; + CRYS_ECDSA_SignUserContext_t signCtx; + }userSignData; + /*! Public key data. */ + struct { + CRYS_ECPKI_UserPublKey_t PublKey; + union { + CRYS_ECDSA_VerifyUserContext_t verifyCtx; + CRYS_ECPKI_BUILD_TempData_t tempData; + }buildOrVerify; + }userVerifyData; + }keyContextData; + /*! Internal buffer. */ + uint8_t signBuff[2*CRYS_ECPKI_FIPS_ORDER_LENGTH]; +}CRYS_ECDSAFipsKatContext_t; + +/*! Context definition, required for internal FIPS verification for ECDH KAT. */ +typedef struct CRYS_ECDHFipsKatContext_t{ + /*! Public key data. */ + CRYS_ECPKI_UserPublKey_t pubKey; + /*! Private key data. */ + CRYS_ECPKI_UserPrivKey_t privKey; + /*! Internal buffers. */ + union { + CRYS_ECPKI_BUILD_TempData_t ecpkiTempData; + CRYS_ECDH_TempData_t ecdhTempBuff; + }tmpData; + /*! Buffer for the secret key. */ + uint8_t secretBuff[CRYS_ECPKI_FIPS_ORDER_LENGTH]; +}CRYS_ECDHFipsKatContext_t; + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/crys_error.h b/external/nrf_cc310/include/crys_error.h new file mode 100644 index 0000000..bf5673f --- /dev/null +++ b/external/nrf_cc310/include/crys_error.h @@ -0,0 +1,273 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_ERROR_H +#define CRYS_ERROR_H + +#include "ssi_pal_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! @file +@brief This module defines the error return code types and the numbering spaces of the error codes +for each module of the layers listed below. +@defgroup crys_error CryptoCell general base error codes +@{ +@ingroup cryptocell_api +*/ + +/*! The definitions of the error number space used for the different modules */ + +/* ........... Error base numeric mapping definitions ................... */ +/* ----------------------------------------------------------------------- */ + + /*! CRYS error base number. */ +#define CRYS_ERROR_BASE 0x00F00000UL + +/*! Error range number assigned for each layer. */ +#define CRYS_ERROR_LAYER_RANGE 0x00010000UL + +/*! Error range number assigned to each module on its specified layer. */ +#define CRYS_ERROR_MODULE_RANGE 0x00000100UL + +/* Defines the layer index for the error mapping. */ +/*! CRYS error layer index. */ +#define CRYS_LAYER_ERROR_IDX 0x00UL +/*! Low level functions error layer index. */ +#define LLF_LAYER_ERROR_IDX 0x01UL +/*! Generic error layer index. */ +#define GENERIC_ERROR_IDX 0x05UL + +/* Defines the module index for error mapping */ +/*! AES error index.*/ +#define AES_ERROR_IDX 0x00UL +/*! DES error index.*/ +#define DES_ERROR_IDX 0x01UL +/*! HASH error index.*/ +#define HASH_ERROR_IDX 0x02UL +/*! HMAC error index.*/ +#define HMAC_ERROR_IDX 0x03UL +/*! RSA error index.*/ +#define RSA_ERROR_IDX 0x04UL +/*! DH error index.*/ +#define DH_ERROR_IDX 0x05UL + +/*! ECPKI error index.*/ +#define ECPKI_ERROR_IDX 0x08UL +/*! RND error index.*/ +#define RND_ERROR_IDX 0x0CUL +/*! Common error index.*/ +#define COMMON_ERROR_IDX 0x0DUL +/*! KDF error index.*/ +#define KDF_ERROR_IDX 0x11UL +/*! HKDF error index.*/ +#define HKDF_ERROR_IDX 0x12UL +/*! AESCCM error index.*/ +#define AESCCM_ERROR_IDX 0x15UL +/*! FIPS error index.*/ +#define FIPS_ERROR_IDX 0x17UL + +/*! PKA error index.*/ +#define PKA_MODULE_ERROR_IDX 0x21UL +/*! CHACHA error index.*/ +#define CHACHA_ERROR_IDX 0x22UL +/*! EC montgomery and edwards error index.*/ +#define EC_MONT_EDW_ERROR_IDX 0x23UL +/*! CHACHA POLY error index.*/ +#define CHACHA_POLY_ERROR_IDX 0x24UL +/*! POLY error index.*/ +#define POLY_ERROR_IDX 0x25UL +/*! SRP error index.*/ +#define SRP_ERROR_IDX 0x26UL + + + +/* .......... defining the error spaces for each module on each layer ........... */ +/* ------------------------------------------------------------------------------ */ + +/*! AES module error base address - 0x00F00000. */ +#define CRYS_AES_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * AES_ERROR_IDX ) ) + +/*! DES module error base address - 0x00F00100. */ +#define CRYS_DES_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * DES_ERROR_IDX ) ) + +/*! HASH module error base address - 0x00F00200. */ +#define CRYS_HASH_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * HASH_ERROR_IDX ) ) + +/*! HMAC module error base address - 0x00F00300. */ +#define CRYS_HMAC_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * HMAC_ERROR_IDX ) ) + +/*! RSA module error base address - 0x00F00400. */ +#define CRYS_RSA_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * RSA_ERROR_IDX ) ) + +/*! DH module error base address - 0x00F00500. */ +#define CRYS_DH_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * DH_ERROR_IDX ) ) + +/*! ECPKI module error base address - 0x00F00800. */ +#define CRYS_ECPKI_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * ECPKI_ERROR_IDX ) ) + +/*! Low level ECPKI module error base address - 0x00F10800. */ +#define LLF_ECPKI_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * LLF_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * ECPKI_ERROR_IDX ) ) + +/*! RND module error base address - 0x00F00C00. */ +#define CRYS_RND_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * RND_ERROR_IDX ) ) + +/*! Low level RND module error base address - 0x00F10C00. */ +#define LLF_RND_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * LLF_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * RND_ERROR_IDX ) ) + +/*! COMMMON module error base address - 0x00F00D00. */ +#define CRYS_COMMON_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * COMMON_ERROR_IDX ) ) + +/*! KDF module error base address - 0x00F01100. */ +#define CRYS_KDF_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * KDF_ERROR_IDX ) ) + +/*! HKDF module error base address - 0x00F01100. */ +#define CRYS_HKDF_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * HKDF_ERROR_IDX ) ) + +/*! AESCCM module error base address - 0x00F01500. */ +#define CRYS_AESCCM_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * AESCCM_ERROR_IDX ) ) + +/*! FIPS module error base address - 0x00F01700. */ +#define CRYS_FIPS_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * FIPS_ERROR_IDX ) ) + +/*! PKA module error base address - 0x00F02100. */ +#define PKA_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * PKA_MODULE_ERROR_IDX ) ) + +/*! CHACHA module error base address - 0x00F02200. */ +#define CRYS_CHACHA_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * CHACHA_ERROR_IDX ) ) +/*! CHACHA POLY module error base address - 0x00F02400. */ +#define CRYS_CHACHA_POLY_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * CHACHA_POLY_ERROR_IDX ) ) +/*! POLY module error base address - 0x00F02500. */ +#define CRYS_POLY_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * POLY_ERROR_IDX ) ) + +/*! SRP module error base address - 0x00F02600. */ +#define CRYS_SRP_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * SRP_ERROR_IDX ) ) + + +/*! EC MONT_EDW module error base address - 0x00F02300. */ +#define CRYS_EC_MONT_EDW_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * EC_MONT_EDW_ERROR_IDX ) ) + + +/*! User generic error base address - 0x00F50000 */ +#define GENERIC_ERROR_BASE ( CRYS_ERROR_BASE + (CRYS_ERROR_LAYER_RANGE * GENERIC_ERROR_IDX) ) +/*! CRYS fatal error. */ +#define CRYS_FATAL_ERROR (GENERIC_ERROR_BASE + 0x00UL) +/*! CRYS out of resources error. */ +#define CRYS_OUT_OF_RESOURCE_ERROR (GENERIC_ERROR_BASE + 0x01UL) +/*! CRYS illegal resource value error. */ +#define CRYS_ILLEGAL_RESOURCE_VAL_ERROR (GENERIC_ERROR_BASE + 0x02UL) + + + +/* ............ The OK (success) definition ....................... */ +/*! Success defintion. */ +#define CRYS_OK 0 + +/*! MACRO that defines crys return value. */ +#define SASI_CRYS_RETURN_ERROR(retCode, retcodeInfo, funcHandler) \ + ((retCode) == 0 ? CRYS_OK : funcHandler(retCode, retcodeInfo)) + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + +/*! The typedef definition of all of the error codes that are returned from the CRYS functions */ +typedef uint32_t CRYSError_t; + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + + + diff --git a/external/nrf_cc310/include/crys_hash.h b/external/nrf_cc310/include/crys_hash.h new file mode 100644 index 0000000..dede2a0 --- /dev/null +++ b/external/nrf_cc310/include/crys_hash.h @@ -0,0 +1,285 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains all of the enums and definitions +that are used for the CRYS HASH APIs, as well as the APIs themselves. +@defgroup crys_hash CryptoCell HASH APIs +@{ +@ingroup cryptocell_api + + +This product supports the following HASH algorithms (or modes, according to product): +
  • CRYS_HASH_MD5 (producing 16 byte output).
  • +
  • CRYS_HASH_SHA1 (producing 20 byte output).
  • +
  • CRYS_HASH_SHA224 (producing 28 byte output).
  • +
  • CRYS_HASH_SHA256 (producing 32 byte output).
  • +
  • CRYS_HASH_SHA384 (producing 48 byte output).
  • +
  • CRYS_HASH_SHA512 (producing 64 byte output).
+ +HASH calculation can be performed in either of the following two modes of operation: +
  • Integrated operation - Processes all data in a single function call. This flow is applicable when all data is available prior to the + cryptographic operation.
  • +
  • Block operation - Processes a subset of the data buffers, and is called multiple times in a sequence. This flow is applicable when the + next data buffer becomes available only during/after processing of the current data buffer.
+ +The following is a typical HASH Block operation flow: +
  1. ::CRYS_HASH_Init - this function initializes the HASH machine on the CRYS level by setting the context pointer that is used on the entire + HASH operation.
  2. +
  3. ::CRYS_HASH_Update - this function runs a HASH operation on a block of data allocated by the user. This function may be called as many times + as required.
  4. +
  5. ::CRYS_HASH_Finish - this function ends the HASH operation. It returns the digest result and clears the context.
+*/ + +#ifndef CRYS_HASH_H +#define CRYS_HASH_H + + +#include "ssi_pal_types.h" +#include "crys_error.h" +#include "crys_hash_defs.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ +/* The hash result in words +#define CRYS_HASH_RESULT_SIZE_IN_WORDS 5*/ +/*! The maximal hash result is 512 bits for SHA512. */ +#define CRYS_HASH_RESULT_SIZE_IN_WORDS 16 + +/*! MD5 digest result size in bytes. */ +#define CRYS_HASH_MD5_DIGEST_SIZE_IN_BYTES 16 + +/*! MD5 digest result size in words. */ +#define CRYS_HASH_MD5_DIGEST_SIZE_IN_WORDS 4 + +/*! SHA-1 digest result size in bytes. */ +#define CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES 20 + +/*! SHA-1 digest result size in words. */ +#define CRYS_HASH_SHA1_DIGEST_SIZE_IN_WORDS 5 + +/*! SHA-256 digest result size in words. */ +#define CRYS_HASH_SHA224_DIGEST_SIZE_IN_WORDS 7 + +/*! SHA-256 digest result size in words. */ +#define CRYS_HASH_SHA256_DIGEST_SIZE_IN_WORDS 8 + +/*! SHA-384 digest result size in words. */ +#define CRYS_HASH_SHA384_DIGEST_SIZE_IN_WORDS 12 + +/*! SHA-512 digest result size in words. */ +#define CRYS_HASH_SHA512_DIGEST_SIZE_IN_WORDS 16 + +/*! SHA-256 digest result size in bytes */ +#define CRYS_HASH_SHA224_DIGEST_SIZE_IN_BYTES 28 + +/*! SHA-256 digest result size in bytes */ +#define CRYS_HASH_SHA256_DIGEST_SIZE_IN_BYTES 32 + +/*! SHA-384 digest result size in bytes */ +#define CRYS_HASH_SHA384_DIGEST_SIZE_IN_BYTES 48 + +/*! SHA-512 digest result size in bytes */ +#define CRYS_HASH_SHA512_DIGEST_SIZE_IN_BYTES 64 + +/*! SHA1 hash block size in words */ +#define CRYS_HASH_BLOCK_SIZE_IN_WORDS 16 + +/*! SHA1 hash block size in bytes */ +#define CRYS_HASH_BLOCK_SIZE_IN_BYTES 64 + +/*! SHA2 hash block size in words */ +#define CRYS_HASH_SHA512_BLOCK_SIZE_IN_WORDS 32 + +/*! SHA2 hash block size in bytes */ +#define CRYS_HASH_SHA512_BLOCK_SIZE_IN_BYTES 128 + +/*! Maximal data size for update operation. */ +#define CRYS_HASH_UPDATE_DATA_MAX_SIZE_IN_BYTES (1 << 29) + + +/************************ Enums ********************************/ + +/*! +HASH operation mode +*/ +typedef enum { + CRYS_HASH_SHA1_mode = 0, /*!< SHA1. */ + CRYS_HASH_SHA224_mode = 1, /*!< SHA224. */ + CRYS_HASH_SHA256_mode = 2, /*!< SHA256. */ + CRYS_HASH_SHA384_mode = 3, /*!< SHA384. */ + CRYS_HASH_SHA512_mode = 4, /*!< SHA512. */ + CRYS_HASH_MD5_mode = 5, /*!< MD5. */ + /*! Number of hash modes. */ + CRYS_HASH_NumOfModes, + /*! Reserved. */ + CRYS_HASH_OperationModeLast= 0x7FFFFFFF, + +}CRYS_HASH_OperationMode_t; + +/************************ Typedefs *****************************/ + +/*! HASH result buffer. */ +typedef uint32_t CRYS_HASH_Result_t[CRYS_HASH_RESULT_SIZE_IN_WORDS]; + +/************************ Structs ******************************/ +/*! The user's context prototype - the argument type that is passed by the user + to the HASH APIs. The context saves the state of the operation and must be saved by the user + till the end of the APIs flow. */ +typedef struct CRYS_HASHUserContext_t { + /*! Internal buffer */ + uint32_t buff[CRYS_HASH_USER_CTX_SIZE_IN_WORDS]; +}CRYS_HASHUserContext_t; + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + + +/************************************************************************************************/ +/*! +@brief This function initializes the HASH machine and the HASH Context. + +It receives as input a pointer to store the context handle to the HASH Context, +and initializes the HASH Context with the cryptographic attributes that are needed for the HASH block operation (initializes H's value for the HASH algorithm). + +@return CRYS_OK on success. +@return A non-zero value from crys_hash_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_HASH_Init( + CRYS_HASHUserContext_t *ContextID_ptr, /*!< [in] Pointer to the HASH context buffer allocated by the user that is used + for the HASH machine operation. */ + CRYS_HASH_OperationMode_t OperationMode /*!< [in] One of the supported HASH modes, as defined in CRYS_HASH_OperationMode_t. */ +); + +/************************************************************************************************/ +/*! +@brief This function processes a block of data to be HASHed. + +It updates a HASH Context that was previously initialized by CRYS_HASH_Init or updated by a previous call to CRYS_HASH_Update. + +@return CRYS_OK on success. +@return A non-zero value from crys_hash_error.h on failure. +*/ + +CIMPORT_C CRYSError_t CRYS_HASH_Update( + CRYS_HASHUserContext_t *ContextID_ptr, /*!< [in] Pointer to the HASH context buffer allocated by the user, which is used for the + HASH machine operation. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the input data to be HASHed. + it is a one contiguous memory block. */ + size_t DataInSize /*!< [in] Byte size of the input data. Must be > 0. + If not a multiple of the HASH block size (64 for MD5, SHA-1 and SHA-224/256, + 128 for SHA-384/512), no further calls + to CRYS_HASH_Update are allowed in this context, and only CRYS_HASH_Finish + can be called to complete the computation. */ +); + +/************************************************************************************************/ +/*! +@brief This function finalizes the hashing process of data block. + +It receives a handle to the HASH Context, which was previously initialized by CRYS_HASH_Init or by CRYS_HASH_Update. +It "adds" a header to the data block according to the relevant HASH standard, and computes the final message digest. + +@return CRYS_OK on success. +@return A non-zero value from crys_hash_error.h on failure. +*/ + +CIMPORT_C CRYSError_t CRYS_HASH_Finish( + CRYS_HASHUserContext_t *ContextID_ptr, /*!< [in] Pointer to the HASH context buffer allocated by the user that is used for + the HASH machine operation. */ + CRYS_HASH_Result_t HashResultBuff /*!< [in] Pointer to the word-aligned 64 byte buffer. The actual size of the HASH + result depends on CRYS_HASH_OperationMode_t. */ +); + + +/************************************************************************************************/ +/*! +@brief This function is a utility function that frees the context if the operation has failed. + +The function executes the following major steps: +
  1. Checks the validity of all of the inputs of the function.
  2. +
  3. Clears the user's context.
  4. +
  5. Exits the handler with the OK code.
+ +@return CRYS_OK on success. +@return A non-zero value from crys_hash_error.h on failure. +*/ + +CIMPORT_C CRYSError_t CRYS_HASH_Free( + CRYS_HASHUserContext_t *ContextID_ptr /*!< [in] Pointer to the HASH context buffer allocated by the user that is used for + the HASH machine operation. */ +); + + +/************************************************************************************************/ +/*! +@brief This function processes a single buffer of data. + +The function allocates an internal HASH Context, and initializes it with the cryptographic attributes +that are needed for the HASH block operation (initialize H's value for the HASH algorithm). +Then it processes the data block, calculating the HASH. Finally, it returns the data buffer's message digest. + +@return CRYS_OK on success. +@return A non-zero value from crys_hash_error.h on failure. + */ + +CIMPORT_C CRYSError_t CRYS_HASH ( + CRYS_HASH_OperationMode_t OperationMode, /*!< [in] One of the supported HASH modes, as defined in CRYS_HASH_OperationMode_t. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the input data to be HASHed. + The size of the scatter/gather list representing the data buffer is limited + to 128 entries, and the size of each entry is limited to 64KB + (fragments larger than 64KB are broken into fragments <= 64KB). */ + size_t DataSize, /*!< [in] The size of the data to be hashed in bytes. */ + CRYS_HASH_Result_t HashResultBuff /*!< [out] Pointer to a word-aligned 64 byte buffer. The actual size of the HASH + result depends on CRYS_HASH_OperationMode_t. */ +); + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/crys_hash_defs.h b/external/nrf_cc310/include/crys_hash_defs.h new file mode 100644 index 0000000..701f78a --- /dev/null +++ b/external/nrf_cc310/include/crys_hash_defs.h @@ -0,0 +1,66 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_HASH_DEFS_H +#define CRYS_HASH_DEFS_H + +/*! +@file +@brief This file contains HASH definitions. +@defgroup crys_hash_defs CryptoCell Hash definitions +@{ +@ingroup crys_hash +*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ + +/*! The size of user's context prototype (see ::CRYS_HASHUserContext_t) in words. */ +#define CRYS_HASH_USER_CTX_SIZE_IN_WORDS 60 + + +#ifdef __cplusplus +} +#endif + +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/crys_hash_error.h b/external/nrf_cc310/include/crys_hash_error.h new file mode 100644 index 0000000..c1d304e --- /dev/null +++ b/external/nrf_cc310/include/crys_hash_error.h @@ -0,0 +1,108 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef CRYS_HASH_ERROR_H +#define CRYS_HASH_ERROR_H + + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the CRYS HASH errors. +@defgroup crys_hash_error CryptoCell HASH specific errors +@{ +@ingroup crys_hash +*/ + + + + +/************************ Defines ******************************/ +/*! HASH module on the CRYS layer base address - 0x00F00200*/ +/* The CRYS HASH module errors */ +/*! Illegal context pointer. */ +#define CRYS_HASH_INVALID_USER_CONTEXT_POINTER_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x0UL) +/*! Illegal operation mode. */ +#define CRYS_HASH_ILLEGAL_OPERATION_MODE_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x1UL) +/*! Context is corrupted. */ +#define CRYS_HASH_USER_CONTEXT_CORRUPTED_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x2UL) +/*! Illegal data in pointer. */ +#define CRYS_HASH_DATA_IN_POINTER_INVALID_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x3UL) +/*! Illegal data in size. */ +#define CRYS_HASH_DATA_SIZE_ILLEGAL (CRYS_HASH_MODULE_ERROR_BASE + 0x4UL) +/*! Illegal result buffer pointer. */ +#define CRYS_HASH_INVALID_RESULT_BUFFER_POINTER_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x5UL) +/*! Last block was already processed (may happen if previous block was not a multiple of block size). */ +#define CRYS_HASH_LAST_BLOCK_ALREADY_PROCESSED_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0xCUL) +/*! Illegal parameter. */ +#define CRYS_HASH_ILLEGAL_PARAMS_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0xDUL) +/*! Illegal context size. */ +#define CRYS_HASH_CTX_SIZES_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0xEUL) +/*! HASH is not supported. */ +#define CRYS_HASH_IS_NOT_SUPPORTED (CRYS_HASH_MODULE_ERROR_BASE + 0xFUL) + + + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/crys_hkdf.h b/external/nrf_cc310/include/crys_hkdf.h new file mode 100644 index 0000000..2d9b948 --- /dev/null +++ b/external/nrf_cc310/include/crys_hkdf.h @@ -0,0 +1,124 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_HKDF_H +#define CRYS_HKDF_H + +#include "crys_hash.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module defines the API that supports HMAC Key derivation function as defined by RFC5869. +@defgroup crys_hkdf CryptoCell HMAC Key Derivation APIs +@{ +@ingroup cryptocell_api +*/ + +/*! HKDF maximal key size in words. */ +#define CRYS_HKDF_MAX_HASH_KEY_SIZE_IN_BYTES 512 + +/*! HKDF maximal HASH digest size in bytes. */ +#define CRYS_HKDF_MAX_HASH_DIGEST_SIZE_IN_BYTES CRYS_HASH_SHA512_DIGEST_SIZE_IN_BYTES + +/************************ Defines ******************************/ + +/************************ Enums ********************************/ + +/*! Enum defining HKDF HASH available modes. */ +typedef enum +{ + /*! SHA1 mode. */ + CRYS_HKDF_HASH_SHA1_mode = 0, + /*! SHA224 mode. */ + CRYS_HKDF_HASH_SHA224_mode = 1, + /*! SHA256 mode. */ + CRYS_HKDF_HASH_SHA256_mode = 2, + /*! SHA384 mode. */ + CRYS_HKDF_HASH_SHA384_mode = 3, + /*! SHA512 mode. */ + CRYS_HKDF_HASH_SHA512_mode = 4, + + /*! Maximal number of HASH modes. */ + CRYS_HKDF_HASH_NumOfModes, + + /*! Reserved */ + CRYS_HKDF_HASH_OpModeLast = 0x7FFFFFFF, + +}CRYS_HKDF_HASH_OpMode_t; + +/************************ Typedefs ****************************/ + +/************************ Structs ******************************/ + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + +/****************************************************************/ + + +/*********************************************************************************************************/ +/*! +@brief CRYS_HKDF_KeyDerivFunc performs the HMAC-based key derivation, according to RFC5869 + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_kdf_error.h, crys_hash_error or crys_hmac_error.h +*/ +CEXPORT_C CRYSError_t CRYS_HKDF_KeyDerivFunc( + CRYS_HKDF_HASH_OpMode_t HKDFhashMode, /*!< [in] The HKDF identifier of hash function to be used. */ + uint8_t* Salt_ptr, /*!< [in] A pointer to a non secret random value. can be NULL. */ + size_t SaltLen, /*!< [in] The size of the salt_ptr. */ + uint8_t* Ikm_ptr, /*!< [in] A pointer to a input key message. */ + uint32_t IkmLen, /*!< [in] The size of the input key message */ + uint8_t* Info, /*!< [in] A pointer to an optional context and application specific information. can be NULL */ + uint32_t InfoLen, /*!< [in] The size of the info. */ + uint8_t* Okm, /*!< [in] A pointer to a output key material. */ + uint32_t OkmLen, /*!< [in] The size of the output key material. */ + SaSiBool IsStrongKey /*!< [in] if TRUE , then no need to perform the extraction phase. */ + ); + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + diff --git a/external/nrf_cc310/include/crys_hkdf_error.h b/external/nrf_cc310/include/crys_hkdf_error.h new file mode 100644 index 0000000..36ddaee --- /dev/null +++ b/external/nrf_cc310/include/crys_hkdf_error.h @@ -0,0 +1,91 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_HKDF_ERROR_H +#define CRYS_HKDF_ERROR_H + +#include "crys_error.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the CRYS HKDF errors. +@defgroup crys_hkdf_error HMAC Key Derivation specific errors +@{ +@ingroup crys_hkdf + */ + + +/************************ Defines *******************************/ + +/*! CryptoCell HKDF module errors / base address - 0x00F01100. */ +/*! Invalid argument. */ +#define CRYS_HKDF_INVALID_ARGUMENT_POINTER_ERROR (CRYS_HKDF_MODULE_ERROR_BASE + 0x0UL) +/*! Invalid argument size. */ +#define CRYS_HKDF_INVALID_ARGUMENT_SIZE_ERROR (CRYS_HKDF_MODULE_ERROR_BASE + 0x1UL) +/*! Illegal hash mode. */ +#define CRYS_HKDF_INVALID_ARGUMENT_HASH_MODE_ERROR (CRYS_HKDF_MODULE_ERROR_BASE + 0x3UL) +/*! HKDF not supported. */ +#define CRYS_HKDF_IS_NOT_SUPPORTED (CRYS_HKDF_MODULE_ERROR_BASE + 0xFFUL) + +/************************ Enums *********************************/ + +/************************ Typedefs *****************************/ + +/************************ Structs ******************************/ + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + + + diff --git a/external/nrf_cc310/include/crys_hmac.h b/external/nrf_cc310/include/crys_hmac.h new file mode 100644 index 0000000..1ba7659 --- /dev/null +++ b/external/nrf_cc310/include/crys_hmac.h @@ -0,0 +1,214 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains all of the enums and definitions +that are used for the CRYS HMAC APIs, as well as the APIs themselves. +@defgroup crys_hmac CryptoCell HMAC APIs +@{ +@ingroup cryptocell_api + + +HMAC is a wrapping algorithm that uses a HASH function (one of the supported HASH algorithms, as specified in the HASH chapter) and a key, +to generate a unique authentication code over the input data. +HMAC calculation can be performed in either of the following two modes of operation: +
  • Integrated operation - Processes all data in a single function call. This flow is applicable when all data is available prior to +the cryptographic operation.
  • +
  • Block operation - Processes a subset of the data buffers, and is called multiple times in a sequence. This flow is applicable when +the next data buffer becomes available only during/after processing of the current data buffer.
+ +The following is a typical HMAC Block operation flow: +
  1. ::CRYS_HMAC_Init: This function initializes the HMAC machine on the CRYS level by setting the context pointer that is + used on the entire HMAC operation.
  2. +
  3. ::CRYS_HMAC_Update: This function runs an HMAC operation on a block of data allocated by the user. This function may be called as + many times as required.
  4. +
  5. ::CRYS_HMAC_Finish: This function ends the HMAC operation. It returns the digest result and clears the context.
+*/ + +#ifndef CRYS_HMAC_H +#define CRYS_HMAC_H + + +#include "ssi_pal_types.h" +#include "crys_error.h" + +#include "crys_hash.h" +#include "crys_hmac_defs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ + +/*! HMAC key size after padding for MD5, SHA1, SHA256. */ +#define CRYS_HMAC_KEY_SIZE_IN_BYTES 64 + +/*! HMAC key size after padding for SHA384, SHA512 */ +#define CRYS_HMAC_SHA2_1024BIT_KEY_SIZE_IN_BYTES 128 + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/*********************** Structures ****************************/ + + +/*! User's context prototype - the argument type that is passed by the user + to the HMAC APIs. The context saves the state of the operation and must be saved by the user + till the end of the APIs flow */ +typedef struct CRYS_HMACUserContext_t { + /*! Context buffer for internal use */ + uint32_t buff[CRYS_HMAC_USER_CTX_SIZE_IN_WORDS]; + +}CRYS_HMACUserContext_t; + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +/*! +@brief This function initializes the HMAC machine. + +It allocates and initializes the HMAC Context. It initiates a HASH session and processes a HASH update on the Key XOR ipad, +then stores it in the context + +@return CRYS_OK on success. +@return A non-zero value from crys_hmac_error.h or crys_hash_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_HMAC_Init( + CRYS_HMACUserContext_t *ContextID_ptr, /*!< [in] Pointer to the HMAC context buffer allocated by the user, which is used + for the HMAC machine operation. */ + CRYS_HASH_OperationMode_t OperationMode, /*!< [in] One of the supported HASH modes, as defined in CRYS_HASH_OperationMode_t. */ + uint8_t *key_ptr, /*!< [in] The pointer to the user's key buffer. */ + uint16_t keySize /*!< [in] The key size in bytes. If the key size is bigger than the HASH block, the key will be hashed. + The limitations on the key size are the same as the limitations on MAX hash size. */ +); + + +/*! +@brief This function processes a block of data to be HASHed. + +It receives a handle to the HMAC Context, and updates the HASH value with the new data. + +@return CRYS_OK on success. +@return A non-zero value from crys_hmac_error.h or crys_hash_error.h on failure. +*/ + +CIMPORT_C CRYSError_t CRYS_HMAC_Update( + CRYS_HMACUserContext_t *ContextID_ptr, /*!< [in] Pointer to the HMAC context buffer allocated by the user + that is used for the HMAC machine operation. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the input data to be HASHed. + The size of the scatter/gather list representing the data buffer is limited to + 128 entries, and the size of each entry is limited to 64KB + (fragments larger than 64KB are broken into fragments <= 64KB). */ + size_t DataInSize /*!< [in] Byte size of the input data. Must be > 0. + If not a multiple of the HASH block size (64 for SHA-1 and SHA-224/256, + 128 for SHA-384/512), no further calls to ::CRYS_HMAC_Update are allowed in + this context, and only ::CRYS_HMAC_Finish can be called to complete the + computation. */ +); + + +/*! +@brief This function finalizes the HMAC processing of a data block. + +It receives a handle to the HMAC context that was previously initialized by ::CRYS_HMAC_Init, or by ::CRYS_HMAC_Update. +It completes the HASH calculation on the ipad and text, and then executes a new HASH operation with the key XOR opad and the previous +HASH operation result. + +@return CRYS_OK on success. +@return A non-zero value from crys_hmac_error.h or crys_hash_error.h on failure. +*/ + +CIMPORT_C CRYSError_t CRYS_HMAC_Finish( + CRYS_HMACUserContext_t *ContextID_ptr, /*!< [in] Pointer to the HMAC context buffer allocated by the user, which is used + for the HMAC machine operation. */ + CRYS_HASH_Result_t HmacResultBuff /*!< [out] Pointer to the word-aligned 64 byte buffer. The actual size of the + HASH result depends on CRYS_HASH_OperationMode_t. */ +); + + +/*! +@brief This function is a service function that frees the context if the operation has failed. + +The function executes the following major steps: +
  1. Checks the validity of all of the inputs of the function.
  2. +
  3. Clears the user's context.
  4. +
  5. Exits the handler with the OK code.
+ +@return CRYS_OK on success. +@return a non-zero value from crys_hmac_error.h on failure. +*/ + +CIMPORT_C CRYSError_t CRYS_HMAC_Free( + CRYS_HMACUserContext_t *ContextID_ptr /*!< [in] Pointer to the HMAC context buffer allocated by the user, which is used for + the HMAC machine operation. */ +); + + +/*! +@brief This function processes a single buffer of data, and returns the data buffer's message digest. + +@return CRYS_OK on success. +@return A non-zero value from crys_hmac_error.h or crys_hash_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_HMAC ( + CRYS_HASH_OperationMode_t OperationMode, /*!< [in] One of the supported HASH modes, as defined in CRYS_HASH_OperationMode_t. */ + uint8_t *key_ptr, /*!< [in] The pointer to the user's key buffer. */ + uint16_t keySize, /*!< [in] The key size in bytes. If the key size is bigger than the HASH block, the key will be hashed. + The limitations on the key size are the same as the limitations on MAX hash size.*/ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the input data to be HASHed. + The size of the scatter/gather list representing the data buffer is limited to 128 + entries, and the size of each entry is limited to 64KB (fragments larger than + 64KB are broken into fragments <= 64KB). */ + size_t DataSize, /*!< [in] The size of the data to be hashed (in bytes). */ + CRYS_HASH_Result_t HmacResultBuff /*!< [out] Pointer to the word-aligned 64 byte buffer. The actual size of the + HMAC result depends on CRYS_HASH_OperationMode_t. */ +); +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/crys_hmac_defs.h b/external/nrf_cc310/include/crys_hmac_defs.h new file mode 100644 index 0000000..6e76d71 --- /dev/null +++ b/external/nrf_cc310/include/crys_hmac_defs.h @@ -0,0 +1,64 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_HMAC_DEFS_H +#define CRYS_HMAC_DEFS_H + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains HMAC definitions. +@defgroup crys_hmac_defs CryptoCell Hmac definitions +@{ +@ingroup crys_hmac +*/ + +/************************ Defines ******************************/ +/*! The size of user's context prototype (see ::CRYS_HMACUserContext_t) in words. */ +#define CRYS_HMAC_USER_CTX_SIZE_IN_WORDS 94 + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/crys_hmac_error.h b/external/nrf_cc310/include/crys_hmac_error.h new file mode 100644 index 0000000..9530ab8 --- /dev/null +++ b/external/nrf_cc310/include/crys_hmac_error.h @@ -0,0 +1,108 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_HMAC_ERROR_H +#define CRYS_HMAC_ERROR_H + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! @file +@brief This module contains the definitions of the CRYS HMAC errors. +@defgroup crys_hmac_error CryptoCell HMAC specific errors +@{ +@ingroup crys_hmac +*/ + + + +/************************ Defines ******************************/ + +/*! The CRYS HMAC module errors */ +/*! Illegal context pointer. */ +#define CRYS_HMAC_INVALID_USER_CONTEXT_POINTER_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0x0UL) +/*! Illegal operation mode. */ +#define CRYS_HMAC_ILLEGAL_OPERATION_MODE_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0x1UL) +/*! Context is corrupted. */ +#define CRYS_HMAC_USER_CONTEXT_CORRUPTED_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0x2UL) +/*! Illegal data in pointer. */ +#define CRYS_HMAC_DATA_IN_POINTER_INVALID_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0x3UL) +/*! Illegal data in size. */ +#define CRYS_HMAC_DATA_SIZE_ILLEGAL (CRYS_HMAC_MODULE_ERROR_BASE + 0x4UL) +/*! Illegal result buffer pointer. */ +#define CRYS_HMAC_INVALID_RESULT_BUFFER_POINTER_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0x5UL) +/*! Illegal key buffer pointer. */ +#define CRYS_HMAC_INVALID_KEY_POINTER_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0x6UL) +/*! Illegal key size. */ +#define CRYS_HMAC_UNVALID_KEY_SIZE_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0x7UL) +/*! Last block was already processed (may happen if previous block was not a multiple of block size). */ +#define CRYS_HMAC_LAST_BLOCK_ALREADY_PROCESSED_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0xBUL) +/*! Illegal parameters. */ +#define CRYS_HMAC_ILLEGAL_PARAMS_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0xCUL) +/*! Illegal context size. */ +#define CRYS_HMAC_CTX_SIZES_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0xEUL) +/*! HMAC is not supported. */ +#define CRYS_HMAC_IS_NOT_SUPPORTED (CRYS_HMAC_MODULE_ERROR_BASE + 0xFUL) + + + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/crys_kdf.h b/external/nrf_cc310/include/crys_kdf.h new file mode 100644 index 0000000..78cde00 --- /dev/null +++ b/external/nrf_cc310/include/crys_kdf.h @@ -0,0 +1,211 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_KDF_H +#define CRYS_KDF_H + + +#include "crys_hash.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module defines the API that supports Key derivation function in modes +as defined in PKCS#3, ANSI X9.42-2001, and ANSI X9.63-1999. +@defgroup crys_kdf CryptoCell Key Derivation APIs +@{ +@ingroup cryptocell_api +*/ + +#include "crys_hash.h" + +/************************ Defines ******************************/ + +/*! Shared secret value max size in bytes */ +#define CRYS_KDF_MAX_SIZE_OF_SHARED_SECRET_VALUE 1024 + +/* Count and max. sizeof OtherInfo entries (pointers to data buffers) */ +/*! Number of other info entries. */ +#define CRYS_KDF_COUNT_OF_OTHER_INFO_ENTRIES 5 +/*! Maximal size of other info entry. */ +#define CRYS_KDF_MAX_SIZE_OF_OTHER_INFO_ENTRY 64 /*!< Size is in bytes*/ +/*! Maximal size of keying data in bytes. */ +#define CRYS_KDF_MAX_SIZE_OF_KEYING_DATA 2048 + +/************************ Enums ********************************/ +/*! HASH operation modes */ +typedef enum +{ + /*! SHA1 mode.*/ + CRYS_KDF_HASH_SHA1_mode = 0, + /*! SHA224 mode.*/ + CRYS_KDF_HASH_SHA224_mode = 1, + /*! SHA256 mode.*/ + CRYS_KDF_HASH_SHA256_mode = 2, + /*! SHA384 mode.*/ + CRYS_KDF_HASH_SHA384_mode = 3, + /*! SHA512 mode.*/ + CRYS_KDF_HASH_SHA512_mode = 4, + /*! Maximal number of HASH modes. */ + CRYS_KDF_HASH_NumOfModes, + /*! Reserved.*/ + CRYS_KDF_HASH_OpModeLast = 0x7FFFFFFF, + +}CRYS_KDF_HASH_OpMode_t; + +/*! Key derivation modes. */ +typedef enum +{ + /*! ASN1 key derivation mode.*/ + CRYS_KDF_ASN1_DerivMode = 0, + /*! Concatination key derivation mode.*/ + CRYS_KDF_ConcatDerivMode = 1, + /*! X963 key derivation mode.*/ + CRYS_KDF_X963_DerivMode = CRYS_KDF_ConcatDerivMode, + /*! ISO 18033 KDF1 key derivation mode.*/ + CRYS_KDF_ISO18033_KDF1_DerivMode = 3, + /*! ISO 18033 KDF2 key derivation mode.*/ + CRYS_KDF_ISO18033_KDF2_DerivMode = 4, + /*! Maximal number of key derivation modes. */ + CRYS_KDF_DerivFunc_NumOfModes = 5, + /*! Reserved.*/ + CRYS_KDF_DerivFuncModeLast= 0x7FFFFFFF, + +}CRYS_KDF_DerivFuncMode_t; + +/************************ Typedefs ****************************/ + +/*! Structure, containing the optional data (other info) for KDF, + if any data is not needed, then the pointer value and + the size must be set to NULL */ +typedef struct +{ + /*! A unique object identifier (OID), indicating algorithm(s) + for which the keying data is used. */ + uint8_t AlgorithmID[CRYS_KDF_MAX_SIZE_OF_OTHER_INFO_ENTRY]; + uint32_t SizeOfAlgorithmID; /*!< Size of algorithm ID.*/ + /*! Public information contributed by the initiator. */ + uint8_t PartyUInfo[CRYS_KDF_MAX_SIZE_OF_OTHER_INFO_ENTRY]; + uint32_t SizeOfPartyUInfo; /*!< Size of the Public information contributed by the initiator. */ + /*! Public information contributed by the responder. */ + uint8_t PartyVInfo[CRYS_KDF_MAX_SIZE_OF_OTHER_INFO_ENTRY]; + uint32_t SizeOfPartyVInfo; /*!< Size of the responder's public information. */ + /*! Mutually-known private information, e.g. shared information + communicated throgh a separate channel. */ + uint8_t SuppPrivInfo[CRYS_KDF_MAX_SIZE_OF_OTHER_INFO_ENTRY]; + uint32_t SizeOfSuppPrivInfo; /*!< Size of the private information. */ + /*! Mutually-known public information, */ + uint8_t SuppPubInfo[CRYS_KDF_MAX_SIZE_OF_OTHER_INFO_ENTRY]; + uint32_t SizeOfSuppPubInfo; /*!< Size of the public information. */ + +}CRYS_KDF_OtherInfo_t; + +/************************ Structs ******************************/ + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + +/****************************************************************/ + + +/*********************************************************************************************************/ +/*! + @brief CRYS_KDF_KeyDerivFunc performs key derivation according to one of the modes defined in standards: + ANS X9.42-2001, ANS X9.63, ISO/IEC 18033-2. + +The present implementation of the function allows the following operation modes: +
  • CRYS_KDF_ASN1_DerivMode - mode based on ASN.1 DER encoding;
  • +
  • CRYS_KDF_ConcatDerivMode - mode based on concatenation;
  • +
  • CRYS_KDF_X963_DerivMode = CRYS_KDF_ConcatDerivMode;
  • +
  • CRYS_KDF_ISO18033_KDF1_DerivMode - specific mode according to ECIES-KEM algorithm (ISO/IEC 18033-2).
+ +The purpose of this function is to derive a keying data from the shared secret value and some +other optional shared information (SharedInfo). + +\note +
  • The length in Bytes of the hash result buffer is denoted by "hashlen".
  • +
  • All buffers arguments are represented in Big-Endian format.
  • + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_kdf_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_KDF_KeyDerivFunc( + uint8_t *ZZSecret_ptr, /*!< [in] A pointer to shared secret value octet string. */ + uint32_t ZZSecretSize, /*!< [in] The size of the shared secret value in bytes. + The maximal size is defined as: CRYS_KDF_MAX_SIZE_OF_SHARED_SECRET_VALUE. */ + CRYS_KDF_OtherInfo_t *OtherInfo_ptr, /*!< [in] The pointer to structure, containing the data, shared by two entities of + agreement and the data sizes. This argument may be optional in several modes + (if it is not needed - set NULL). + On two ISO/IEC 18033-2 modes - set NULL. + On KDF ASN1 mode the OtherInfo and its AlgorithmID entry are mandatory. */ + CRYS_KDF_HASH_OpMode_t KDFhashMode, /*!< [in] The KDF identifier of hash function to be used. The hash function output + must be at least 160 bits. */ + CRYS_KDF_DerivFuncMode_t derivation_mode, /*!< [in] Specifies one of above described derivation modes. */ + uint8_t *KeyingData_ptr, /*!< [out] A pointer to the buffer for derived keying data. */ + uint32_t KeyingDataSizeBytes /*!< [in] The size in bytes of the keying data to be derived. + The maximal size is defined as: CRYS_KDF_MAX_SIZE_OF_KEYING_DATA. */ +); + +/*********************************************************************************************************/ +/*! + CRYS_KDF_ASN1_KeyDerivFunc is A MACRO that performs key derivation according to ASN1 DER encoding method defined + in standard ANS X9.42-2001, 7.2.1. For a description of the parameters see ::CRYS_KDF_KeyDerivFunc. +*/ +#define CRYS_KDF_ASN1_KeyDerivFunc(ZZSecret_ptr,ZZSecretSize,OtherInfo_ptr,KDFhashMode,KeyingData_ptr,KeyLenInBytes)\ + CRYS_KDF_KeyDerivFunc((ZZSecret_ptr),(ZZSecretSize),(OtherInfo_ptr),(KDFhashMode),CRYS_KDF_ASN1_DerivMode,(KeyingData_ptr),(KeyLenInBytes)) + + +/*********************************************************************************************************/ +/*! + CRYS_KDF_ConcatKeyDerivFunc is a MACRO that performs key derivation according to concatenation mode defined + in standard ANS X9.42-2001, 7.2.2. For a description of the parameters see + ::CRYS_KDF_KeyDerivFunc. +*/ +#define CRYS_KDF_ConcatKeyDerivFunc(ZZSecret_ptr,ZZSecretSize,OtherInfo_ptr,KDFhashMode,KeyingData_ptr,KeyLenInBytes)\ + CRYS_KDF_KeyDerivFunc((ZZSecret_ptr),(ZZSecretSize),(OtherInfo_ptr),(KDFhashMode),CRYS_KDF_ConcatDerivMode,(KeyingData_ptr),(KeyLenInBytes)) + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + diff --git a/external/nrf_cc310/include/crys_kdf_error.h b/external/nrf_cc310/include/crys_kdf_error.h new file mode 100644 index 0000000..f550140 --- /dev/null +++ b/external/nrf_cc310/include/crys_kdf_error.h @@ -0,0 +1,105 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_KDF_ERROR_H +#define CRYS_KDF_ERROR_H + +#include "crys_error.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the CRYS KDF errors. +@defgroup crys_kdf_error CryptoCell Key Derivation specific errors +@{ +@ingroup crys_kdf + */ + + +/************************ Defines *******************************/ + +/*! The CRYS KDF module errors / base address - 0x00F01100*/ +/*! Illegal input pointer. */ +#define CRYS_KDF_INVALID_ARGUMENT_POINTER_ERROR (CRYS_KDF_MODULE_ERROR_BASE + 0x0UL) +/*! Illegal input size. */ +#define CRYS_KDF_INVALID_ARGUMENT_SIZE_ERROR (CRYS_KDF_MODULE_ERROR_BASE + 0x1UL) +/*! Illegal operation mode. */ +#define CRYS_KDF_INVALID_ARGUMENT_OPERATION_MODE_ERROR (CRYS_KDF_MODULE_ERROR_BASE + 0x2UL) +/*! Illegal hash mode. */ +#define CRYS_KDF_INVALID_ARGUMENT_HASH_MODE_ERROR (CRYS_KDF_MODULE_ERROR_BASE + 0x3UL) +/*! Illegal key derivation mode. */ +#define CRYS_KDF_INVALID_KEY_DERIVATION_MODE_ERROR (CRYS_KDF_MODULE_ERROR_BASE + 0x4UL) +/*! Illegal shared secret value size. */ +#define CRYS_KDF_INVALID_SHARED_SECRET_VALUE_SIZE_ERROR (CRYS_KDF_MODULE_ERROR_BASE + 0x5UL) +/*! Illegal otherInfo size. */ +#define CRYS_KDF_INVALID_OTHER_INFO_SIZE_ERROR (CRYS_KDF_MODULE_ERROR_BASE + 0x6UL) +/*! Illegal key data size. */ +#define CRYS_KDF_INVALID_KEYING_DATA_SIZE_ERROR (CRYS_KDF_MODULE_ERROR_BASE + 0x7UL) +/*! Illegal algorithm ID pointer. */ +#define CRYS_KDF_INVALID_ALGORITHM_ID_POINTER_ERROR (CRYS_KDF_MODULE_ERROR_BASE + 0x8UL) +/*! Illegal algorithm ID size. */ +#define CRYS_KDF_INVALID_ALGORITHM_ID_SIZE_ERROR (CRYS_KDF_MODULE_ERROR_BASE + 0x9UL) +/*! KDF is not supproted. */ +#define CRYS_KDF_IS_NOT_SUPPORTED (CRYS_KDF_MODULE_ERROR_BASE + 0xFFUL) + +/************************ Enums *********************************/ + +/************************ Typedefs *****************************/ + +/************************ Structs ******************************/ + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + + + diff --git a/external/nrf_cc310/include/crys_pka_defs_hw.h b/external/nrf_cc310/include/crys_pka_defs_hw.h new file mode 100644 index 0000000..5073ad2 --- /dev/null +++ b/external/nrf_cc310/include/crys_pka_defs_hw.h @@ -0,0 +1,128 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef _CRYS_PKA_DEFS_HW_H_ +#define _CRYS_PKA_DEFS_HW_H_ + +#include "ssi_pal_types.h" +#include "ssi_pka_hw_plat_defs.h" + +/*! +@defgroup cryptocell_pka CryptoCell PKA group +@{ +@ingroup cryptocell_api +@brief This group is the cryptocell PKA root group +@} + +@file +@brief The file contains all of the enums and definitions that are used in the PKA related code. +@defgroup crys_pka_defs_hw CryptoCell PKA specific definitions +@{ +@ingroup cryptocell_pka +*/ + + +/* The valid key sizes in bits for RSA primitives (exponentiation) */ +/*! Maximal RSA modulus size */ +#define CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS ((CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS + SASI_PKA_WORD_SIZE_IN_BITS) / SASI_BITS_IN_32BIT_WORD ) +/*! Maximal EC modulus size */ +#define CRYS_ECPKI_MODUL_MAX_LENGTH_IN_BITS 521 + +/*! size of buffers for Barrett modulus tag NP, used in PKI algorithms. */ +#define CRYS_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS 5 +/*! size of buffers for Barrett modulus tag NP, used in ECC. */ +#define CRYS_PKA_ECPKI_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS CRYS_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS +/*! Maximal PKA modulus size */ +#define CRYS_PKA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS +/*! Maximal PKA public key size in words */ +#define CRYS_PKA_PUB_KEY_BUFF_SIZE_IN_WORDS (2*CRYS_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS) +/*! Maximal PKA private key size in words */ +#define CRYS_PKA_PRIV_KEY_BUFF_SIZE_IN_WORDS (2*CRYS_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS) +/*! Maximal PKA KG buffer size in words */ +#define CRYS_PKA_KGDATA_BUFF_SIZE_IN_WORDS (3*CRYS_PKA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS) + + +/*! Maximal EC modulus size in words. */ +#define CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS 18 /*!< \internal [(CRYS_ECPKI_MODUL_MAX_LENGTH_IN_BITS + 31)/(sizeof(uint32_t)) + 1] */ +/*! Maximal EC order size in words. */ +#define CRYS_ECPKI_ORDER_MAX_LENGTH_IN_WORDS (CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS + 1) +/*! Maximal EC domain size in words. */ +#define CRYS_PKA_DOMAIN_BUFF_SIZE_IN_WORDS (2*CRYS_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS) + + +/*! ECC NAF buffer definitions */ +#define COUNT_NAF_WORDS_PER_KEY_WORD 8 /*!< \internal Change according to NAF representation (? 2)*/ +/*! Maximal ECC NAF length */ +#define CRYS_PKA_ECDSA_NAF_BUFF_MAX_LENGTH_IN_WORDS (COUNT_NAF_WORDS_PER_KEY_WORD*CRYS_ECPKI_ORDER_MAX_LENGTH_IN_WORDS + 1) + +#ifndef SSI_SUPPORT_ECC_SCA_SW_PROTECT +/* on fast SCA non protected mode required additional buffers for NAF key */ +/*! Scalar Buffer size in words */ +#define CRYS_PKA_ECPKI_SCALAR_MUL_BUFF_MAX_LENGTH_IN_WORDS (CRYS_PKA_ECDSA_NAF_BUFF_MAX_LENGTH_IN_WORDS+CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS+2) +#else +/*! Scalar Buffer size in words */ +#define CRYS_PKA_ECPKI_SCALAR_MUL_BUFF_MAX_LENGTH_IN_WORDS 1 /*(4*CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS)*/ +#endif +/*! ECC temp buffer size in words */ +#define CRYS_PKA_ECPKI_BUILD_TMP_BUFF_MAX_LENGTH_IN_WORDS (3*CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS+CRYS_PKA_ECPKI_SCALAR_MUL_BUFF_MAX_LENGTH_IN_WORDS) +/*! ECC sign temp buffer size in words */ +#define CRYS_PKA_ECDSA_SIGN_BUFF_MAX_LENGTH_IN_WORDS (6*CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS+CRYS_PKA_ECPKI_SCALAR_MUL_BUFF_MAX_LENGTH_IN_WORDS) +/*! ECC ecdh temp buffer size in words */ +#define CRYS_PKA_ECDH_BUFF_MAX_LENGTH_IN_WORDS (2*CRYS_ECPKI_ORDER_MAX_LENGTH_IN_WORDS + CRYS_PKA_ECPKI_SCALAR_MUL_BUFF_MAX_LENGTH_IN_WORDS) +/*! PKA KG temp buffer size in words */ +#define CRYS_PKA_KG_BUFF_MAX_LENGTH_IN_WORDS (2*CRYS_ECPKI_ORDER_MAX_LENGTH_IN_WORDS + CRYS_PKA_ECPKI_SCALAR_MUL_BUFF_MAX_LENGTH_IN_WORDS) +/*! ECC verify temp buffer size in words */ +#define CRYS_PKA_ECDSA_VERIFY_BUFF_MAX_LENGTH_IN_WORDS (3*CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS) + +/* *************************************************************************** */ +/*! Definitions of maximal size of modulus buffers for CRYS_EC_MONT and EC_EDW in bytes */ +#define CRYS_EC_MONT_EDW_MODULUS_MAX_SIZE_IN_BYTES 32U /*!< \internal for Curve25519 */ +/*! Definitions of maximal size of modulus buffers for CRYS_EC_MONT and EC_EDW in words */ +#define CRYS_EC_MONT_EDW_MODULUS_MAX_SIZE_IN_WORDS 8U /*!< \internal for Curve25519 */ +/*! ECC montgomery temp buffer size in words */ +#define CRYS_EC_MONT_TEMP_BUFF_SIZE_IN_32BIT_WORDS (8 * CRYS_EC_MONT_EDW_MODULUS_MAX_SIZE_IN_WORDS) +/*! ECC edwards temp buffer size in words */ +#define CRYS_EC_EDW_TEMP_BUFF_SIZE_IN_32BIT_WORD (8*CRYS_EC_MONT_EDW_MODULUS_MAX_SIZE_IN_WORDS + (sizeof(CRYS_HASHUserContext_t)+SASI_32BIT_WORD_SIZE-1)/SASI_32BIT_WORD_SIZE) + +/** +@} + */ +/** +@} + */ +#endif /*_CRYS_PKA_DEFS_HW_H_*/ + diff --git a/external/nrf_cc310/include/crys_poly.h b/external/nrf_cc310/include/crys_poly.h new file mode 100644 index 0000000..d8ad3e6 --- /dev/null +++ b/external/nrf_cc310/include/crys_poly.h @@ -0,0 +1,107 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains all of the enums and definitions that are used for the + CRYS POLY APIs, as well as the APIs themselves. +@defgroup crys_poly CryptoCell POLY APIs +@{ +@ingroup cryptocell_api + +*/ +#ifndef CRYS_POLY_H +#define CRYS_POLY_H + + +#include "ssi_pal_types.h" +#include "crys_error.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************ Defines ******************************/ +/*! POLY KEY size in words. */ +#define CRYS_POLY_KEY_SIZE_IN_WORDS 8 +/*! POLY KEY size in bytes. */ +#define CRYS_POLY_KEY_SIZE_IN_BYTES (CRYS_POLY_KEY_SIZE_IN_WORDS*SASI_32BIT_WORD_SIZE) + +/*! POLY MAC size in words. */ +#define CRYS_POLY_MAC_SIZE_IN_WORDS 4 +/*! POLY MAC size in bytes. */ +#define CRYS_POLY_MAC_SIZE_IN_BYTES (CRYS_POLY_MAC_SIZE_IN_WORDS*SASI_32BIT_WORD_SIZE) + +/************************ Typedefs ****************************/ + +/*! CHACHA MAC buffer definition. */ +typedef uint32_t CRYS_POLY_Mac_t[CRYS_POLY_MAC_SIZE_IN_WORDS]; + +/*! CHACHA key buffer definition. */ +typedef uint32_t CRYS_POLY_Key_t[CRYS_POLY_KEY_SIZE_IN_WORDS]; + +/************************ Public Functions **********************/ + +/****************************************************************************************************/ +/*! +@brief This function is used to perform the POLY MAC Calculation. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_poly_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_POLY( + CRYS_POLY_Key_t pKey, /*!< [in] A pointer to the user's key buffer. */ + uint8_t *pDataIn, /*!< [in] A pointer to the buffer of the input data to the CHACHA. + must not be null. */ + size_t dataInSize, /*!< [in] The size of the input data. must not be 0. */ + CRYS_POLY_Mac_t macRes /*!< [in/out] Pointer to the MAC result buffer.*/ +); + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /* #ifndef CRYS_POLY_H */ + + + + + diff --git a/external/nrf_cc310/include/crys_poly_error.h b/external/nrf_cc310/include/crys_poly_error.h new file mode 100644 index 0000000..0b89892 --- /dev/null +++ b/external/nrf_cc310/include/crys_poly_error.h @@ -0,0 +1,89 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_POLY_ERROR_H +#define CRYS_POLY_ERROR_H + + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the CRYS POLY errors. +@defgroup crys_poly_error CryptoCell POLY specific errors +@{ +@ingroup crys_poly +*/ + + +/************************ Defines ******************************/ + +/*! The CRYS POLY module errors base address - 0x00F02500 */ +/*! Invalid key. */ +#define CRYS_POLY_KEY_INVALID_ERROR (CRYS_POLY_MODULE_ERROR_BASE + 0x01UL) +/*! Invalid input data. */ +#define CRYS_POLY_DATA_INVALID_ERROR (CRYS_POLY_MODULE_ERROR_BASE + 0x02UL) +/*! Illegal input data size. */ +#define CRYS_POLY_DATA_SIZE_INVALID_ERROR (CRYS_POLY_MODULE_ERROR_BASE + 0x03UL) +/*! MAC calculation error. */ +#define CRYS_POLY_MAC_CALCULATION_ERROR (CRYS_POLY_MODULE_ERROR_BASE + 0x04UL) + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs *****************************/ + +/************************ Public Variables *********************/ + +/************************ Public Functions *********************/ + +#ifdef __cplusplus +} +#endif + + +/** +@} + */ + +#endif + + diff --git a/external/nrf_cc310/include/crys_rnd.h b/external/nrf_cc310/include/crys_rnd.h new file mode 100644 index 0000000..653768c --- /dev/null +++ b/external/nrf_cc310/include/crys_rnd.h @@ -0,0 +1,398 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef CRYS_RND_H +#define CRYS_RND_H + +#include "crys_error.h" +#include "ssi_aes.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains the CRYS APIs used for random number generation. +The random-number generation module implements referenced standard [SP800-90]. +@defgroup crys_rnd CryptoCell Random Generator APIs +@{ +@ingroup cryptocell_api +*/ + +/************************ Defines ******************************/ + +/*! Maximal reseed counter - indicates maximal number of +requests allowed between reseeds; according to NIST 800-90 +it is (2^48 - 1), our restriction is : (0xFFFFFFFF - 0xF).*/ +#define CRYS_RND_MAX_RESEED_COUNTER (0xFFFFFFFF - 0xF) + +/* Max size for one RNG generation (in bits) = + max_num_of_bits_per_request = 2^19 (FIPS 800-90 Tab.3) */ +/*! Maximal size of generated vector in bits. */ +#define CRYS_RND_MAX_GEN_VECTOR_SIZE_BITS 0x7FFFF +/*! Maximal size of generated vector in bytes. */ +#define CRYS_RND_MAX_GEN_VECTOR_SIZE_BYTES 0xFFFF + +/*! AES output block size in words. */ +#define CRYS_RND_AES_BLOCK_SIZE_IN_WORDS SASI_AES_BLOCK_SIZE_IN_WORDS + + +/* RND seed and additional input sizes */ +/*! Maximal size of random seed in words. */ +#define CRYS_RND_SEED_MAX_SIZE_WORDS 12 + +#ifndef CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS +/*! Maximal size of additional input data in words. */ +#define CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS CRYS_RND_SEED_MAX_SIZE_WORDS +#endif + +/* allowed sizes of AES Key, in words */ +/*! AES key size (128 bits) in words. */ +#define CRYS_RND_AES_KEY_128_SIZE_WORDS 4 +/*! AES key size (192 bits) in words. */ +#define CRYS_RND_AES_KEY_192_SIZE_WORDS 6 +/*! AES key size (256 bits) in words. */ +#define CRYS_RND_AES_KEY_256_SIZE_WORDS 8 + +/* Definitions of temp buffer for RND_DMA version of CRYS_RND */ +/*******************************************************************/ +/* Definitions of temp buffer for DMA version of CRYS_RND */ + +/*! Temporary buffer size in words. */ +#define CRYS_RND_WORK_BUFFER_SIZE_WORDS 1528 + +/*! A definition for RAM buffer to be internally used in instantiation (or reseeding) operation. */ +typedef struct +{ + /*! Internal buffer*/ + uint32_t crysRndWorkBuff[CRYS_RND_WORK_BUFFER_SIZE_WORDS]; +}CRYS_RND_WorkBuff_t; + +/*! A definition for entropy estimation data type. */ +#define CRYS_RND_EntropyEstimatData_t CRYS_RND_WorkBuff_t +/*! A definition for entropy estimation buffer. */ +#define crysRndEntrIntBuff crysRndWorkBuff + + +/* RND source buffer inner (entrpopy) offset */ +/*! An internal offset definition. */ +#define CRYS_RND_TRNG_SRC_INNER_OFFSET_WORDS 2 +/*! An internal offset definition. */ +#define CRYS_RND_TRNG_SRC_INNER_OFFSET_BYTES (CRYS_RND_TRNG_SRC_INNER_OFFSET_WORDS*sizeof(uint32_t)) + + + + +/* Size of the expected output buffer used by FIPS KAT */ +/*! FIPS Known answer test output size. */ +#define CRYS_PRNG_FIPS_KAT_OUT_DATA_SIZE 64 + +/************************ Enumerators ****************************/ + +/*! Definition of random operation modes. */ +typedef enum +{ + /*! SW entropy estimation mode. */ + CRYS_RND_Fast = 0, + /*! Full entropy mode. */ + CRYS_RND_Slow = 1, + /*! Reserved. */ + CRYS_RND_ModeLast = 0x7FFFFFFF, +} CRYS_RND_mode_t; + + + +/************************ Structs *****************************/ + + +/* The internal state of DRBG mechanism based on AES CTR and CBC-MAC + algorithms. It is set as global data defined by the following + structure */ +/*! RND state structure. Includes internal data that needs to be saved between boots by the user.*/ +typedef struct +{ + /* Seed buffer, consists from concatenated Key||V: max size 12 words */ + /*! Random Seed buffer */ + uint32_t Seed[CRYS_RND_SEED_MAX_SIZE_WORDS]; + /* Previous value for continuous test */ + /*! Previous random data (used for continuous test). */ + uint32_t PreviousRandValue[SASI_AES_BLOCK_SIZE_IN_WORDS]; + + /* AdditionalInput buffer max size = seed max size words + 4w for padding*/ + /*! Previous additional input buffer. */ + uint32_t PreviousAdditionalInput[CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS+5]; + /*! Additional input buffer. */ + uint32_t AdditionalInput[CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS+4]; + /*! Additional input size in words. */ + uint32_t AddInputSizeWords; /* size of additional data set by user, words */ + + /*! Entropy source size in words */ + uint32_t EntropySourceSizeWords; + + /*! Reseed counter (32 bits active) - indicates number of requests for entropy + since instantiation or reseeding */ + uint32_t ReseedCounter; + + /*! Key size: 4 or 8 words according to security strength 128 bits or 256 bits*/ + uint32_t KeySizeWords; + + /* State flag (see definition of StateFlag above), containing bit-fields, defining: + - b'0: instantiation steps: 0 - not done, 1 - done; + - 2b'9,8: working or testing mode: 0 - working, 1 - KAT DRBG test, 2 - + KAT TRNG test; + b'16: flag defining is Previous random valid or not: + 0 - not valid, 1 - valid */ + /*! State flag used internally in the code.*/ + uint32_t StateFlag; + + /* Trng processing flag - indicates which ROSC lengths are: + - allowed (bits 0-3); + - total started (bits 8-11); + - processed (bits 16-19); + - started, but not processed (bits24-27) */ + /*! TRNG process state used internally in the code */ + uint32_t TrngProcesState; + + /* validation tag */ + /*! Validation tag used internally in the code */ + uint32_t ValidTag; + + /*! Rnd source entropy size in bits */ + uint32_t EntropySizeBits; + +} CRYS_RND_State_t; + + +/*! The RND Generate vector function pointer type definition. + The prototype intendent for External and CRYS internal RND functions + pointers definitions. + Full description can be found in ::CRYS_RND_GenerateVector function API. */ +typedef uint32_t (*SaSiRndGenerateVectWorkFunc_t)( \ + void *rndState_ptr, /*context*/ \ + uint16_t outSizeBytes, /*in*/ \ + uint8_t *out_ptr /*out*/); + + + +/*! Data structure required for internal FIPS verification for PRNG KAT. */ +typedef struct +{ + /*! Internal working buffer. */ + CRYS_RND_WorkBuff_t rndWorkBuff; + /*! Output buffer. */ + uint8_t rndOutputBuff[CRYS_PRNG_FIPS_KAT_OUT_DATA_SIZE]; +} CRYS_PrngFipsKatCtx_t; + + +/*****************************************************************************/ +/********************** Public Functions *************************/ +/*****************************************************************************/ + +/*! +@brief This function needs to be called once. +It calls CRYS_RND_Instantiation to initialize the TRNG and the primary RND context. +An initialized RND context is required for calling RND APIs and asymmetric cryptography key generation and signatures. +The primary context returned by this function can be used as a single global context for all RND needs. +Alternatively, other contexts may be initialized and used with a more limited scope (for specific applications or specific threads). + +\note The Mutexes, if used, are initialized by this API. Therefore, unlike the other APIs in the library, +this API is not thread-safe. + +@param[in/out] rnd_ctx - Pointer to the RND state structure. +@param[in/out] rndWorkBuff_ptr - Pointer to the RND scratch buffer. +*/ +CEXPORT_C CRYSError_t CRYS_RndInit(void* rnd_ctx, /*!< [in/out] Pointer to the RND state buffer, + allocated by the user. This state must be saved and provided + as parameter to any API that uses the RND module.*/ + CRYS_RND_WorkBuff_t *rndWorkBuff_ptr /*!< [in] Scratchpad for the RND module's work. */); + +/*! +@brief This function initializes the RND context. +It must be called at least once prior to using this context with any API that requires it as a parameter (e.g., other RND APIs, asymmetric +cryptography key generation and signatures). +It is called as part of ARM TrustZone CryptoCell library initialization, which initializes and returns the primary RND context. +This primary context can be used as a single global context for all RND needs. +Alternatively, other contexts may be initialized and used with a more limited scope (for specific applications or specific threads). +The call to this function must be followed by a call to ::CRYS_RND_SetGenerateVectorFunc API to set the generate vector function. +It implements referenced standard [SP800-90] - 10.2.1.3.2 - CTR-DRBG Instantiate algorithm using AES (FIPS-PUB 197) and Derivation Function (DF). +\note Additional data can be mixed with the random seed (personalization data or nonce). If required, this data should be provided by calling ::CRYS_RND_AddAdditionalInput prior to using this API. + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RND_Instantiation( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state buffer allocated by the user, which is used to + maintain the RND state. This context state must be saved and provided as a + parameter to any API that uses the RND module. + \note the context must be cleared before sent to the function. */ + CRYS_RND_WorkBuff_t *rndWorkBuff_ptr /*!< [in/out] Scratchpad for the RND module's work. */ +); + + +/*! +@brief Clears existing RNG instantiation state. + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RND_UnInstantiation( + void *rndState_ptr /*!< [in/out] Pointer to the RND context state buffer. */ +); + + +/*! +@brief This function is used for reseeding the RNG with additional entropy and additional user-provided input. +(additional data should be provided by calling ::CRYS_RND_AddAdditionalInput prior to using this API). +It implements referenced standard [SP800-90] - 10.2.1.4.2 - CTR-DRBG Reseeding algorithm, using AES (FIPS-PUB 197) and Derivation Function (DF). + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RND_Reseeding( + void *rndState_ptr, /*!< [in/out] Pointer to the RND context buffer. */ + CRYS_RND_WorkBuff_t *rndWorkBuff_ptr /*!< [in/out] Scratchpad for the RND module's work. */ +); + + +/****************************************************************************************/ +/*! +@brief Generates a random vector according to the algorithm defined in referenced standard [SP800-90] - 10.2.1.5.2 - CTR-DRBG. +The generation algorithm uses AES (FIPS-PUB 197) and Derivation Function (DF). + +\note +
    • The RND module must be instantiated prior to invocation of this API.
    • +
    • In the following cases, Reseeding operation must be performed prior to vector generation:
    • +
      • Prediction resistance is required.
      • +
      • The function returns CRYS_RND_RESEED_COUNTER_OVERFLOW_ERROR, stating that the Reseed Counter has passed its upper-limit (2^32-2).
    + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RND_GenerateVector( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure, which is part of the RND context structure. + Use rndContext->rndState field of the context for this parameter. */ + uint16_t outSizeBytes, /*!< [in] The size in bytes of the random vector required. The maximal size is 2^16 -1 bytes. */ + uint8_t *out_ptr /*!< [out] The pointer to output buffer. */ +); + + + +/**********************************************************************************************************/ +/*! +@brief Generates a random vector with specific limitations by testing candidates (described and used in FIPS 186-4: B.1.2, B.4.2 etc.). + +This function draws a random vector, compare it to the range limits, and if within range - return it in rndVect_ptr. +If outside the range, the function continues retrying until a conforming vector is found, or the maximal retries limit is exceeded. +If maxVect_ptr is provided, rndSizeInBits specifies its size, and the output vector must conform to the range [1 < rndVect < maxVect]. +If maxVect_ptr is NULL, rndSizeInBits specifies the exact required vector size, and the output vector must be the exact same +bit size (with its most significant bit = 1). +\note +The RND module must be instantiated prior to invocation of this API. + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RND_GenerateVectorInRange( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + uint32_t rndSizeInBits, /*!< [in] The size in bits of the random vector required. The allowed size in range 2 <= rndSizeInBits < 2^19-1, bits. */ + uint8_t *maxVect_ptr, /*!< [in] Pointer to the vector defining the upper limit for the random vector output, Given as little-endian byte array. + If not NULL, its actual size is treated as [(rndSizeInBits+7)/8] bytes and its value must be in range (3, 2^19) */ + uint8_t *rndVect_ptr /*!< [in/out] Pointer to the output buffer for the random vector. Must be at least [(rndSizeInBits+7)/8] bytes. + Treated as little-endian byte array. */ +); + + +/*************************************************************************************/ +/*! +@brief Used for adding additional input/personalization data provided by the user, +to be later used by the ::CRYS_RND_Instantiation/::CRYS_RND_Reseeding/::CRYS_RND_GenerateVector functions. + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RND_AddAdditionalInput( + void *rndState_ptr, /*!< [in/out] Pointer to the RND context state buffer. */ + uint8_t *additonalInput_ptr, /*!< [in] The Additional Input buffer. */ + uint16_t additonalInputSize /*!< [in] The size of the Additional Input buffer. It must + be <= CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS and a multiple of 4. */ +); + +/*! +@brief The CRYS_RND_EnterKatMode function sets KAT mode bit into StateFlag of global CRYS_RND_WorkingState structure. + +The user must call this function before calling functions performing KAT tests. + +\note Total size of entropy and nonce must be not great than 126 words (maximal size of entropy and nonce). + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RND_EnterKatMode( + void *rndState_ptr, /*!< [in/out] Pointer to the RND context state buffer. */ + uint8_t *entrData_ptr, /*!< [in] Entropy data. */ + uint32_t entrSize, /*!< [in] Entropy size in bytes. */ + uint8_t *nonce_ptr, /*!< [in] Nonce. */ + uint32_t nonceSize, /*!< [in] Entropy size in bytes. */ + CRYS_RND_WorkBuff_t *workBuff_ptr /*!< [out] RND working buffer, must be the same buffer, which should be passed into + Instantiation/Reseeding functions. */ +); + +/**********************************************************************************************************/ +/*! +@brief The CRYS_RND_DisableKatMode function disables KAT mode bit into StateFlag of global CRYS_RND_State_t structure. + +The user must call this function after KAT tests before actual using RND module (Instantiation etc.). + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C void CRYS_RND_DisableKatMode( + void *rndState_ptr /*!< [in/out] Pointer to the RND state buffer. */ +); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /* #ifndef CRYS_RND_H */ + diff --git a/external/nrf_cc310/include/crys_rnd_error.h b/external/nrf_cc310/include/crys_rnd_error.h new file mode 100644 index 0000000..417eaff --- /dev/null +++ b/external/nrf_cc310/include/crys_rnd_error.h @@ -0,0 +1,160 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef CRYS_RND_ERROR_H +#define CRYS_RND_ERROR_H + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/*! +@file +@brief This module contains the definitions of the CRYS RND errors. +@defgroup crys_rnd_error CryptoCell RND specific errors +@{ +@ingroup crys_rnd +*/ + + + +/************************ Defines ******************************/ +/*! RND module on the CRYS layer base address - 0x00F00C00 */ + +/*! Illegal output pointer.*/ +#define CRYS_RND_DATA_OUT_POINTER_INVALID_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x0UL) +/*! Random generation in range failed .*/ +#define CRYS_RND_CAN_NOT_GENERATE_RAND_IN_RANGE (CRYS_RND_MODULE_ERROR_BASE + 0x1UL) +/*! CPRNGT test failed.*/ +#define CRYS_RND_CPRNG_TEST_FAIL_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x2UL) +/*! Illegal additional data buffer. */ +#define CRYS_RND_ADDITIONAL_INPUT_BUFFER_NULL (CRYS_RND_MODULE_ERROR_BASE + 0x3UL) +/*! Illegal additional data size. */ +#define CRYS_RND_ADDITIONAL_INPUT_SIZE_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x4UL) +/*! Data size overflow. */ +#define CRYS_RND_DATA_SIZE_OVERFLOW_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x5UL) +/*! Illegal vector size. */ +#define CRYS_RND_VECTOR_SIZE_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x6UL) +/*! Reseed counter overflow - in case this error was returned instantiation or reseeding operation must be called. */ +#define CRYS_RND_RESEED_COUNTER_OVERFLOW_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x7UL) +/*! Instantiation was not yet called. */ +#define CRYS_RND_INSTANTIATION_NOT_DONE_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x8UL) +/*! TRNG loss of samples. */ +#define CRYS_RND_TRNG_LOSS_SAMPLES_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x9UL) +/*! TRNG Time exceeded limitations. */ +#define CRYS_RND_TRNG_TIME_EXCEED_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0xAUL) +/*! TRNG loss of samples and time exceeded limitations. */ +#define CRYS_RND_TRNG_LOSS_SAMPLES_AND_TIME_EXCEED_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0xBUL) +/*! RND is in Known Answer Test mode. */ +#define CRYS_RND_IS_KAT_MODE_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0xCUL) +/*! RND operation not supported. */ +#define CRYS_RND_OPERATION_IS_NOT_SUPPORTED_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0xDUL) +/*! RND validity check failed. */ +#define CRYS_RND_STATE_VALIDATION_TAG_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0xEUL) +/*! RND is not supported. */ +#define CRYS_RND_IS_NOT_SUPPORTED (CRYS_RND_MODULE_ERROR_BASE + 0xFUL) +/*! RND Init failed. */ +#define CRYS_RND_INIT_FAILED (CRYS_RND_MODULE_ERROR_BASE + 0x10UL) +/*! RND Init failed. */ +#define CRYS_RND_STARTUP_FAILED (CRYS_RND_MODULE_ERROR_BASE + 0x11UL) +/*! Instantiation Failed. */ +#define CRYS_RND_INSTANTIATION_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x12L) + + +/*! Illegal generate vector function pointer. */ +#define CRYS_RND_GEN_VECTOR_FUNC_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x14UL) + +/*! Illegal work buffer pointer. */ +#define CRYS_RND_WORK_BUFFER_PTR_INVALID_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x20UL) +/*! Illegal AES key size. */ +#define CRYS_RND_ILLEGAL_AES_KEY_SIZE_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x21UL) +/*! Illegal data pointer. */ +#define CRYS_RND_ILLEGAL_DATA_PTR_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x22UL) +/*! Illegal data size. */ +#define CRYS_RND_ILLEGAL_DATA_SIZE_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x23UL) +/*! Illegal parameter. */ +#define CRYS_RND_ILLEGAL_PARAMETER_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x24UL) +/*! Illegal RND state pointer. */ +#define CRYS_RND_STATE_PTR_INVALID_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x25UL) +/*! TRNG errors. */ +#define CRYS_RND_TRNG_ERRORS_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x26UL) +/*! Illegal context pointer. */ +#define CRYS_RND_CONTEXT_PTR_INVALID_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x27UL) + +/*! Illegal output vector pointer. */ +#define CRYS_RND_VECTOR_OUT_PTR_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x30UL) +/*! Illegal output vector size. */ +#define CRYS_RND_VECTOR_OUT_SIZE_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x31UL) +/*! Maximal vector size is too small. */ +#define CRYS_RND_MAX_VECTOR_IS_TOO_SMALL_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x32UL) +/*! Illegal Known Answer Tests parameters. */ +#define CRYS_RND_KAT_DATA_PARAMS_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x33UL) +/*! TRNG Known Answer Test not supported. */ +#define CRYS_RND_TRNG_KAT_NOT_SUPPORTED_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x34UL) +/*! SRAM memory is not defined. */ +#define CRYS_RND_SRAM_NOT_SUPPORTED_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x35UL) +/*! AES operation failure. */ +#define CRYS_RND_AES_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x36UL) + + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/crys_rsa_build.h b/external/nrf_cc310/include/crys_rsa_build.h new file mode 100644 index 0000000..a48e46f --- /dev/null +++ b/external/nrf_cc310/include/crys_rsa_build.h @@ -0,0 +1,152 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_RSA_BUILD_H +#define CRYS_RSA_BUILD_H + + +#include "crys_error.h" +#include "crys_rsa_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@defgroup crys_rsa CryptoCell RSA APIs +@{ +@ingroup cryptocell_api +@brief This group is the cryptocell ECC root group +@} + +@file +@brief This module defines some utility functions for working with RSA cryptography. +@defgroup crys_rsa_build CryptoCell RSA Utility APIs +@{ +@ingroup crys_rsa +*/ + +/******************************************************************************************/ +/*! +@brief Builds a ::CRYSRSAPubKey_t public key structure with the provided modulus and exponent. + +@return CRYS_OK on success. +@return A non-zero value from crys_rsa_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RSA_Build_PubKey( + CRYS_RSAUserPubKey_t *UserPubKey_ptr, /*!< [out] Pointer to the public key structure. */ + uint8_t *Exponent_ptr, /*!< [in] Pointer to the exponent stream of bytes (Big-Endian format). */ + uint16_t ExponentSize, /*!< [in] The size of the exponent (in bytes). */ + uint8_t *Modulus_ptr, /*!< [in] Pointer to the modulus stream of bytes (Big-Endian format). + The most significant bit (MSB) must be set to '1'. */ + uint16_t ModulusSize /*!< [in] The modulus size in bytes. Supported sizes are 64, 128, 256, 384 and 512. */ +); + + +/******************************************************************************************/ +/*! +@brief Builds a ::CRYSRSAPrivKey_t private key structure with the provided modulus and exponent, marking the key as a non-CRT key. + +@return CRYS_OK on success. +@return A non-zero value from crys_rsa_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RSA_Build_PrivKey( + CRYS_RSAUserPrivKey_t *UserPrivKey_ptr, /*!< [out] Pointer to the public key structure.*/ + uint8_t *PrivExponent_ptr, /*!< [in] Pointer to the private exponent stream of bytes (Big-Endian format). */ + uint16_t PrivExponentSize, /*!< [in] The size of the private exponent (in bytes). */ + uint8_t *PubExponent_ptr, /*!< [in] Pointer to the public exponent stream of bytes (Big-Endian format). */ + uint16_t PubExponentSize, /*!< [in] The size of the public exponent (in bytes). */ + uint8_t *Modulus_ptr, /*!< [in] Pointer to the modulus stream of bytes (Big-Endian format). + The most significant bit must be set to '1'. */ + uint16_t ModulusSize /*!< [in] The modulus size in bytes. Supported sizes are 64, 128, 256, 384 and 512. */ +); + +/******************************************************************************************/ +/*! +@brief Builds a ::CRYSRSAPrivKey_t private key structure with the provided parameters, marking the key as a CRT key. + +@return CRYS_OK on success. +@return A non-zero value from crys_rsa_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RSA_Build_PrivKeyCRT( + CRYS_RSAUserPrivKey_t *UserPrivKey_ptr, /*!< [out] Pointer to the public key structure. */ + uint8_t *P_ptr, /*!< [in] Pointer to the first factor stream of bytes (Big-Endian format). */ + uint16_t PSize, /*!< [in] The size of the first factor (in bytes). */ + uint8_t *Q_ptr, /*!< [in] Pointer to the second factor stream of bytes (Big-Endian format). */ + uint16_t QSize, /*!< [in] The size of the second factor (in bytes). */ + uint8_t *dP_ptr, /*!< [in] Pointer to the first factor's CRT exponent stream of bytes + (Big-Endian format). */ + uint16_t dPSize, /*!< [in] The size of the first factor's CRT exponent (in bytes). */ + uint8_t *dQ_ptr, /*!< [in] Pointer to the second factor's CRT exponent stream of bytes + (Big-Endian format). */ + uint16_t dQSize, /*!< [in] The size of the second factor's CRT exponent (in bytes). */ + uint8_t *qInv_ptr, /*!< [in] Pointer to the first CRT coefficient stream of bytes (Big-Endian format). */ + uint16_t qInvSize /*!< [in] The size of the first CRT coefficient (in bytes). */ +); + + +/******************************************************************************************/ +/*! +@brief The function gets the e,n public key parameters from the input +CRYS_RSAUserPubKey_t structure. The function can also be used to retrieve the +modulus and exponent sizes only (Exponent_ptr AND Modulus_ptr must be set to +NULL). + +\note All members of input UserPubKey_ptr structure must be initialized. + +@return CRYS_OK on success. +@return A non-zero value from crys_rsa_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RSA_Get_PubKey( + CRYS_RSAUserPubKey_t *UserPubKey_ptr, /*!< [in] A pointer to the public key structure. */ + uint8_t *Exponent_ptr, /*!< [out] A pointer to the exponent stream of bytes (Big-Endian format). */ + uint16_t *ExponentSize_ptr, /*!< [in/out] the size of the exponent buffer in bytes, + it is updated to the actual size of the exponent, in bytes. */ + uint8_t *Modulus_ptr, /*!< [out] A pointer to the modulus stream of bytes (Big-Endian format). + The MS (most significant) bit must be set to '1'. */ + uint16_t *ModulusSize_ptr /*!< [in/out] the size of the modulus buffer in bytes, it is updated to the actual + size of the modulus, in bytes. */ +); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/crys_rsa_error.h b/external/nrf_cc310/include/crys_rsa_error.h new file mode 100644 index 0000000..0f8f8d9 --- /dev/null +++ b/external/nrf_cc310/include/crys_rsa_error.h @@ -0,0 +1,277 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + #ifndef CRYS_RSA_ERROR_H +#define CRYS_RSA_ERROR_H + + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! @file +@brief This module contains the definitions of the CRYS RSA errors. +@defgroup crys_rsa_error CryptoCell RSA specific errors +@{ +@ingroup crys_rsa +*/ + +/************************ Defines ******************************/ + +/*! CRYS RSA module on the CRYS layer base address - 0x00F00400 */ + +/*! The CRYS RSA module errors */ +/*! Illegal modulus size. */ +#define CRYS_RSA_INVALID_MODULUS_SIZE (CRYS_RSA_MODULE_ERROR_BASE + 0x0UL) +/*! Illegal modulus pointer. */ +#define CRYS_RSA_INVALID_MODULUS_POINTER_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x1UL) +/*! Illegal exponent pointer. */ +#define CRYS_RSA_INVALID_EXPONENT_POINTER_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x2UL) +/*! Illegal public key structure pointer. */ +#define CRYS_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x3UL) +/*! Illegal private key structure pointer. */ +#define CRYS_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x4UL) +/*! Illegal exponent value. */ +#define CRYS_RSA_INVALID_EXPONENT_VAL (CRYS_RSA_MODULE_ERROR_BASE + 0x5UL) +/*! Illegal exponent size. */ +#define CRYS_RSA_INVALID_EXPONENT_SIZE (CRYS_RSA_MODULE_ERROR_BASE + 0x6UL) +/*! Illegal CRT first factor pointer (P_ptr) . */ +#define CRYS_RSA_INVALID_CRT_FIRST_FACTOR_POINTER_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x7UL) +/*! Illegal CRT second factor pointer (Q_ptr) . */ +#define CRYS_RSA_INVALID_CRT_SECOND_FACTOR_POINTER_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x8UL) +/*! Illegal CRT first exponent factor pointer (dP_ptr) . */ +#define CRYS_RSA_INVALID_CRT_FIRST_FACTOR_EXP_PTR_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x9UL) +/*! Illegal CRT second exponent factor pointer (dQ_ptr) . */ +#define CRYS_RSA_INVALID_CRT_SECOND_FACTOR_EXP_PTR_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0xAUL) +/*! Illegal CRT coefficient pointer (qInv_ptr) . */ +#define CRYS_RSA_INVALID_CRT_COEFFICIENT_PTR_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0xBUL) +/*! Illegal CRT first factor size (Psize). */ +#define CRYS_RSA_INVALID_CRT_FIRST_FACTOR_SIZE (CRYS_RSA_MODULE_ERROR_BASE + 0xCUL) +/*! Illegal CRT second factor size (Qsize). */ +#define CRYS_RSA_INVALID_CRT_SECOND_FACTOR_SIZE (CRYS_RSA_MODULE_ERROR_BASE + 0xDUL) +/*! Illegal CRT first and second factor size (Psize + Qsize). */ +#define CRYS_RSA_INVALID_CRT_FIRST_AND_SECOND_FACTOR_SIZE (CRYS_RSA_MODULE_ERROR_BASE + 0xEUL) +/*! Illegal CRT first factor exponent value (dP). */ +#define CRYS_RSA_INVALID_CRT_FIRST_FACTOR_EXPONENT_VAL (CRYS_RSA_MODULE_ERROR_BASE + 0xFUL) +/*! Illegal CRT first factor exponent value (dQ). */ +#define CRYS_RSA_INVALID_CRT_SECOND_FACTOR_EXPONENT_VAL (CRYS_RSA_MODULE_ERROR_BASE + 0x10UL) +/*! Illegal CRT coefficient value (qInv). */ +#define CRYS_RSA_INVALID_CRT_COEFF_VAL (CRYS_RSA_MODULE_ERROR_BASE + 0x11UL) +/*! Illegal data in. */ +#define CRYS_RSA_DATA_POINTER_INVALID_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x12UL) +/*! Illegal message data size. */ +#define CRYS_RSA_INVALID_MESSAGE_DATA_SIZE (CRYS_RSA_MODULE_ERROR_BASE + 0x13UL) +/*! Illegal message value. */ +#define CRYS_RSA_INVALID_MESSAGE_VAL (CRYS_RSA_MODULE_ERROR_BASE + 0x14UL) + +/*! Modulus even error. */ +#define CRYS_RSA_MODULUS_EVEN_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x15UL) +/*! Illegal context pointer. */ +#define CRYS_RSA_INVALID_USER_CONTEXT_POINTER_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x16UL) +/*! Illegal hash operation mode. */ +#define CRYS_RSA_HASH_ILLEGAL_OPERATION_MODE_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x17UL) +/*! Illegal MGF value. */ +#define CRYS_RSA_MGF_ILLEGAL_ARG_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x18UL) +/*! Illegal PKCS1 version. */ +#define CRYS_RSA_PKCS1_VER_ARG_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x19UL) + +/*! Invalid private key. */ +#define CRYS_RSA_PRIV_KEY_VALIDATION_TAG_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x1AUL) +/*! Invalid public key. */ +#define CRYS_RSA_PUB_KEY_VALIDATION_TAG_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x1BUL) +/*! Invalid context. */ +#define CRYS_RSA_USER_CONTEXT_VALIDATION_TAG_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x1CUL) +/*! Illegal output pointer. */ +#define CRYS_RSA_INVALID_OUTPUT_POINTER_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x1DUL) +/*! Illegal output size pointer. */ +#define CRYS_RSA_INVALID_OUTPUT_SIZE_POINTER_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x1FUL) +/*! Illegal temporary buffer pointer. */ +#define CRYS_RSA_CONV_TO_CRT_INVALID_TEMP_BUFF_POINTER_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x20UL) + +/*! OAEP encode parameter string is too long. */ +#define CRYS_RSA_BASE_OAEP_ENCODE_PARAMETER_STRING_TOO_LONG (CRYS_RSA_MODULE_ERROR_BASE + 0x22UL) +/*! OAEP decode parameter string is too long. */ +#define CRYS_RSA_BASE_OAEP_DECODE_PARAMETER_STRING_TOO_LONG (CRYS_RSA_MODULE_ERROR_BASE + 0x23UL) +/*! OAEP encode message is too long. */ +#define CRYS_RSA_BASE_OAEP_ENCODE_MESSAGE_TOO_LONG (CRYS_RSA_MODULE_ERROR_BASE + 0x24UL) +/*! OAEP decode message is too long. */ +#define CRYS_RSA_BASE_OAEP_DECODE_MESSAGE_TOO_LONG (CRYS_RSA_MODULE_ERROR_BASE + 0x25UL) +/*! Illegal key generation data struct pointer. */ +#define CRYS_RSA_KEY_GEN_DATA_STRUCT_POINTER_INVALID (CRYS_RSA_MODULE_ERROR_BASE + 0x26UL) +/*! Illegal PRIM data struct pointer. */ +#define CRYS_RSA_PRIM_DATA_STRUCT_POINTER_INVALID (CRYS_RSA_MODULE_ERROR_BASE + 0x27UL) +/*! Illegal message buffer size. */ +#define CRYS_RSA_INVALID_MESSAGE_BUFFER_SIZE (CRYS_RSA_MODULE_ERROR_BASE + 0x28UL) +/*! Illegal signature buffer size. */ +#define CRYS_RSA_INVALID_SIGNATURE_BUFFER_SIZE (CRYS_RSA_MODULE_ERROR_BASE + 0x29UL) +/*! Illegal modulus size pointer. */ +#define CRYS_RSA_INVALID_MOD_BUFFER_SIZE_POINTER (CRYS_RSA_MODULE_ERROR_BASE + 0x2AUL) +/*! Illegal exponent size pointer. */ +#define CRYS_RSA_INVALID_EXP_BUFFER_SIZE_POINTER (CRYS_RSA_MODULE_ERROR_BASE + 0x2BUL) +/*! Illegal signature pointer. */ +#define CRYS_RSA_INVALID_SIGNATURE_BUFFER_POINTER (CRYS_RSA_MODULE_ERROR_BASE + 0x2CUL) +/*! Wrong private key type. */ +#define CRYS_RSA_WRONG_PRIVATE_KEY_TYPE (CRYS_RSA_MODULE_ERROR_BASE + 0x2DUL) + +/*! Illegal CRT first factor size pointer (Psize) . */ +#define CRYS_RSA_INVALID_CRT_FIRST_FACTOR_SIZE_POINTER_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x2EUL) +/*! Illegal CRT second factor size pointer (Qsize) . */ +#define CRYS_RSA_INVALID_CRT_SECOND_FACTOR_SIZE_POINTER_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x2FUL) +/*! Illegal CRT first factor exponent size pointer (dPsize) . */ +#define CRYS_RSA_INVALID_CRT_FIRST_FACTOR_EXP_SIZE_PTR_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x30UL) +/*! Illegal CRT second factor exponent size pointer (dQsize) . */ +#define CRYS_RSA_INVALID_CRT_SECOND_FACTOR_EXP_SIZE_PTR_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x31UL) +/*! Illegal CRT coefficient size pointer (qInvsize) . */ +#define CRYS_RSA_INVALID_CRT_COEFFICIENT_SIZE_PTR_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x32UL) + +/*! Illegal CRT first factor size (Psize) . */ +#define CRYS_RSA_INVALID_CRT_FIRST_FACTOR_SIZE_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x33UL) +/*! Illegal CRT second factor size (Qsize) . */ +#define CRYS_RSA_INVALID_CRT_SECOND_FACTOR_SIZE_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x34UL) +/*! Illegal CRT first factor exponent size (dPsize) . */ +#define CRYS_RSA_INVALID_CRT_FIRST_FACTOR_EXP_SIZE_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x35UL) +/*! Illegal CRT second factor exponent size (dQsize) . */ +#define CRYS_RSA_INVALID_CRT_SECOND_FACTOR_EXP_SIZE_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x36UL) +/*! Illegal CRT coefficient size (qInvsize) . */ +#define CRYS_RSA_INVALID_CRT_COEFFICIENT_SIZE_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x37UL) +/*! Key generation conditional test failed. */ +#define CRYS_RSA_KEY_GEN_CONDITIONAL_TEST_FAIL_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x38UL) + +/*! Random generation in range failed. */ +#define CRYS_RSA_CAN_NOT_GENERATE_RAND_IN_RANGE (CRYS_RSA_MODULE_ERROR_BASE + 0x39UL) +/*! Illegal CRT parameter size. */ +#define CRYS_RSA_INVALID_CRT_PARAMETR_SIZE_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x3AUL) + +/*! Illegal modulus. */ +#define CRYS_RSA_INVALID_MODULUS_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x40UL) +/*! Illegal pointer. */ +#define CRYS_RSA_INVALID_PTR_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x41UL) +/*! Illegal decryption mode. */ +#define CRYS_RSA_INVALID_DECRYPRION_MODE_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x42UL) + +/*! Illegal generated private key. */ +#define CRYS_RSA_GENERATED_PRIV_KEY_IS_TOO_LOW (CRYS_RSA_MODULE_ERROR_BASE + 0x43UL) +/*! Key generation error. */ +#define CRYS_RSA_KEY_GENERATION_FAILURE_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x44UL) +/*! Internal error. */ +#define CRYS_RSA_INTERNAL_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x45UL) + + +/**************************************************************************************** + * PKCS#1 VERSION 1.5 ERRORS + ****************************************************************************************/ +/*! BER encoding passed. */ +#define CRYS_RSA_BER_ENCODING_OK CRYS_OK +/*! Error in BER parsing. */ +#define CRYS_RSA_ERROR_BER_PARSING (CRYS_RSA_MODULE_ERROR_BASE+0x51UL) +/*! Error in PKCS15 message. */ +#define CRYS_RSA_ENCODE_15_MSG_OUT_OF_RANGE (CRYS_RSA_MODULE_ERROR_BASE+0x52UL) +/*! Error in PKCS15 PS. */ +#define CRYS_RSA_ENCODE_15_PS_TOO_SHORT (CRYS_RSA_MODULE_ERROR_BASE+0x53UL) +/*! PKCS15 block type is not supported. */ +#define CRYS_RSA_PKCS1_15_BLOCK_TYPE_NOT_SUPPORTED (CRYS_RSA_MODULE_ERROR_BASE+0x54UL) +/*! Error in PKCS15 decrypted block parsing. */ +#define CRYS_RSA_15_ERROR_IN_DECRYPTED_BLOCK_PARSING (CRYS_RSA_MODULE_ERROR_BASE+0x55UL) +/*! Error in random operation. */ +#define CRYS_RSA_ERROR_IN_RANDOM_OPERATION_FOR_ENCODE (CRYS_RSA_MODULE_ERROR_BASE+0x56UL) +/*! PKCS15 verification failed. */ +#define CRYS_RSA_ERROR_VER15_INCONSISTENT_VERIFY (CRYS_RSA_MODULE_ERROR_BASE+0x57UL) +/*! Illegal message size (in no hash operation case). */ +#define CRYS_RSA_INVALID_MESSAGE_DATA_SIZE_IN_NO_HASH_CASE (CRYS_RSA_MODULE_ERROR_BASE+0x58UL) +/*! Illegal message size. */ +#define CRYS_RSA_INVALID_MESSAGE_DATA_SIZE_IN_SSL_CASE (CRYS_RSA_MODULE_ERROR_BASE+0x59UL) +/*! PKCS#1 Ver 1.5 verify hash input inconsistent with hash mode derived from signature. */ +#define CRYS_RSA_PKCS15_VERIFY_BER_ENCODING_HASH_TYPE (CRYS_RSA_MODULE_ERROR_BASE+0x60UL) +/*! Illegal DER hash mode */ +#define CRYS_RSA_GET_DER_HASH_MODE_ILLEGAL (CRYS_RSA_MODULE_ERROR_BASE+0x61UL) + +/**************************************************************************************** + * PKCS#1 VERSION 2.1 ERRORS + ****************************************************************************************/ +/*! Illegal salt length. */ +#define CRYS_RSA_PSS_ENCODING_MODULUS_HASH_SALT_LENGTHS_ERROR (CRYS_RSA_MODULE_ERROR_BASE+0x80UL) +/*! Illegal MGF mask. */ +#define CRYS_RSA_BASE_MGF_MASK_TOO_LONG (CRYS_RSA_MODULE_ERROR_BASE+0x81UL) +/*! PSS verification failed. */ +#define CRYS_RSA_ERROR_PSS_INCONSISTENT_VERIFY (CRYS_RSA_MODULE_ERROR_BASE+0x82UL) +/*! OAEP message too long. */ +#define CRYS_RSA_OAEP_VER21_MESSAGE_TOO_LONG (CRYS_RSA_MODULE_ERROR_BASE+0x83UL) +/*! OAEP error in decrypted block parsing. */ +#define CRYS_RSA_ERROR_IN_DECRYPTED_BLOCK_PARSING (CRYS_RSA_MODULE_ERROR_BASE+0x84UL) +/*! OAEP decoding error. */ +#define CRYS_RSA_OAEP_DECODE_ERROR (CRYS_RSA_MODULE_ERROR_BASE+0x85UL) +/*! Error in decrypted data size. */ +#define CRYS_RSA_15_ERROR_IN_DECRYPTED_DATA_SIZE (CRYS_RSA_MODULE_ERROR_BASE+0x86UL) +/*! Error in decrypted data. */ +#define CRYS_RSA_15_ERROR_IN_DECRYPTED_DATA (CRYS_RSA_MODULE_ERROR_BASE+0x87UL) +/*! Illegal L pointer. */ +#define CRYS_RSA_OAEP_L_POINTER_ERROR (CRYS_RSA_MODULE_ERROR_BASE+0x88UL) +/*! Illegal output size. */ +#define CRYS_RSA_DECRYPT_INVALID_OUTPUT_SIZE (CRYS_RSA_MODULE_ERROR_BASE+0x89UL) +/*! Illegal output size pointer. */ +#define CRYS_RSA_DECRYPT_OUTPUT_SIZE_POINTER_ERROR (CRYS_RSA_MODULE_ERROR_BASE+0x8AUL) +/*! Illegal parameters. */ +#define CRYS_RSA_ILLEGAL_PARAMS_ACCORDING_TO_PRIV_ERROR (CRYS_RSA_MODULE_ERROR_BASE + 0x93UL) +/*! RSA is not supported. */ +#define CRYS_RSA_IS_NOT_SUPPORTED (CRYS_RSA_MODULE_ERROR_BASE+0xFFUL) + + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/crys_rsa_kg.h b/external/nrf_cc310/include/crys_rsa_kg.h new file mode 100644 index 0000000..2ea2e47 --- /dev/null +++ b/external/nrf_cc310/include/crys_rsa_kg.h @@ -0,0 +1,129 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef CRYS_RSA_KG_H +#define CRYS_RSA_KG_H + +#include "crys_rsa_types.h" +#include "crys_rnd.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief Generates a RSA pair of public and private keys. +@defgroup crys_rsa_kg CryptoCell RSA key generation APIs +@{ +@ingroup crys_rsa +*/ + +/************************ Defines ******************************/ + +/* Max allowed size and values of public exponent for key generation in CRYS */ +/*! Maximal public exponent size in bits. */ +#define CRYS_RSA_KG_PUB_EXP_MAX_SIZE_BITS 17 +/*! Definition of public exponent value. */ +#define CRYS_RSA_KG_PUB_EXP_ALLOW_VAL_1 0x000003 +/*! Definition of public exponent value. */ +#define CRYS_RSA_KG_PUB_EXP_ALLOW_VAL_2 0x000011 +/*! Definition of public exponent value. */ +#define CRYS_RSA_KG_PUB_EXP_ALLOW_VAL_3 0x010001 + + + + +/***********************************************************************************************/ + +/*! +@brief CRYS_RSA_KG_GenerateKeyPair generates a Pair of public and private keys on non CRT mode according to [ANS X9.31]. + +\note To be FIPS 186-4 [5.1] compliant use only the following key sizes (in bits): 1024, 2048 and 3072. + +@return CRYS_OK on success. +@return A non-zero value from crys_rsa_error.h or crys_rnd_error.h on failure. + +*/ + +CIMPORT_C CRYSError_t CRYS_RSA_KG_GenerateKeyPair( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + uint8_t *pubExp_ptr, /*!< [in] The pointer to the public exponent (public key). */ + uint16_t pubExpSizeInBytes, /*!< [in] The public exponent size in bytes. */ + uint32_t keySize, /*!< [in] The size of the key, in bits. Supported sizes are + 512, 1024, 2048, 3072 and 4096 bit. */ + CRYS_RSAUserPrivKey_t *userPrivKey_ptr, /*!< [out] Pointer to the private key structure. */ + CRYS_RSAUserPubKey_t *userPubKey_ptr, /*!< [out] Pointer to the public key structure. */ + CRYS_RSAKGData_t *keyGenData_ptr, /*!< [in] Pointer to a temporary structure required for the KeyGen operation. */ + CRYS_RSAKGFipsContext_t *pFipsCtx /*!< [in] Pointer to temporary buffer used in case FIPS certification if required. */ +); + +/***********************************************************************************************/ +/*! +@brief Generates a pair of public and private keys on CRT mode according to [ANS X9.31]. + +\note To be FIPS 186-4 [5.1] compliant use only the following key sizes (in bits): 1024, 2048 and 3072. + +@return CRYS_OK on success. +@return A non-zero value from crys_rsa_error.h or crys_rnd_error.h on failure. +*/ + +CIMPORT_C CRYSError_t CRYS_RSA_KG_GenerateKeyPairCRT( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + uint8_t *pubExp_ptr, /*!< [in] The pointer to the public exponent (public key). */ + uint16_t pubExpSizeInBytes, /*!< [in] The public exponent size in bytes. */ + uint32_t keySize, /*!< [in] The size of the key, in bits. Supported sizes are + 512, 1024, 2048, 3072 and 4096 bit. */ + CRYS_RSAUserPrivKey_t *userPrivKey_ptr, /*!< [out] Pointer to the private key structure. */ + CRYS_RSAUserPubKey_t *userPubKey_ptr, /*!< [out] Pointer to the public key structure. */ + CRYS_RSAKGData_t *keyGenData_ptr, /*!< [in] Pointer to a temporary structure required for the KeyGen operation. */ + CRYS_RSAKGFipsContext_t *pFipsCtx /*!< [in] Pointer to temporary buffer used in case FIPS certification if required. */ +); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/crys_rsa_prim.h b/external/nrf_cc310/include/crys_rsa_prim.h new file mode 100644 index 0000000..6712086 --- /dev/null +++ b/external/nrf_cc310/include/crys_rsa_prim.h @@ -0,0 +1,125 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_RSA_PRIM_H +#define CRYS_RSA_PRIM_H + +#include "crys_rsa_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module defines the API that implements the [PKCS1_2.1] primitive functions. +@defgroup crys_rsa_prim CryptoCell RSA primitive APIs +@{ +@ingroup crys_rsa + + +\note Direct use of primitive functions, rather than schemes to protect data, is strongly discouraged as primitive functions are +susceptible to well-known attacks. +*/ + + + +/**********************************************************************************/ +/*! +@brief Implements the RSAEP algorithm, as defined in [PKCS1_2.1] - 6.1.1. + +@return CRYS_OK on success. +@return A non-zero value from crys_rsa_error.h on failure. + */ +CIMPORT_C CRYSError_t CRYS_RSA_PRIM_Encrypt( + CRYS_RSAUserPubKey_t *UserPubKey_ptr, /*!< [in] Pointer to the public key data structure. */ + CRYS_RSAPrimeData_t *PrimeData_ptr, /*!< [in] Pointer to a temporary structure containing internal buffers. */ + uint8_t *Data_ptr, /*!< [in] Pointer to the data to encrypt. */ + uint16_t DataSize, /*!< [in] The size (in bytes) of input data must be ≤ modulus size. If is smaller, + then the function padds it by zeros on left side up to the modulus size + and therefore, after further decrypt operation, its result will contain + zero-padding also. If the function is used for recovering the plain data + from result of inverse function (CRYS_RSA_PRIM_Decrypt), the input size + must be equal to modulus size exactly. */ + uint8_t *Output_ptr /*!< [out] Pointer to the encrypted data. The buffer size must be ≥ the modulus size. */ +); + + +/**********************************************************************************/ +/*! +@brief Implements the RSADP algorithm, as defined in [PKCS1_2.1] - 6.1.2. + +@return CRYS_OK on success. +@return A non-zero value from crys_rsa_error.h on failure. + +*/ +CIMPORT_C CRYSError_t CRYS_RSA_PRIM_Decrypt( + CRYS_RSAUserPrivKey_t *UserPrivKey_ptr, /*!< [in] Pointer to the private key data structure. + The key representation (pair or quintuple) and hence the RSA algorithm + (CRT or not-CRT) is determined by enum value in the structure + ::CRYS_RSA_Build_PrivKey or ::CRYS_RSA_Build_PrivKeyCRT. */ + CRYS_RSAPrimeData_t *PrimeData_ptr, /*!< [in] Pointer to a temporary structure containing internal buffers required for + the RSA operation. */ + uint8_t *Data_ptr, /*!< [in] Pointer to the data to be decrypted. */ + uint16_t DataSize, /*!< [in] The size (in bytes) of input data must be ≤ modulus size. + If the size is smaller (not recommendet), then the data will be zero-padded + by the function on left side up to the modulus size and therefore, after further + decrypt operation,its result will contain zero-padding also. If the function is used + for recovering the plain data from result of inverse function (CRYS_RSA_PRIM_Encrypt), + the input size must be equal to modulus size exactly. */ + uint8_t *Output_ptr /*!< [out] Pointer to the decrypted data. The buffer size must be ≤ the modulus size. */ +); + + +/*! +@brief Implements the RSASP1 algorithm, as defined in [PKCS1_2.1] - 6.2.1, as a call to ::CRYS_RSA_PRIM_Decrypt, +since the signature primitive is identical to the decryption primitive. +*/ +#define CRYS_RSA_PRIM_Sign CRYS_RSA_PRIM_Decrypt + +/*! +@brief Implements the RSAVP1 algorithm, as defined in [PKCS1_2.1] - 6.2.2, as a call to ::CRYS_RSA_PRIM_Encrypt. +*/ +#define CRYS_RSA_PRIM_Verify CRYS_RSA_PRIM_Encrypt + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/crys_rsa_schemes.h b/external/nrf_cc310/include/crys_rsa_schemes.h new file mode 100644 index 0000000..be26af2 --- /dev/null +++ b/external/nrf_cc310/include/crys_rsa_schemes.h @@ -0,0 +1,521 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_RSA_SCHEMES_H +#define CRYS_RSA_SCHEMES_H + + +#include "crys_error.h" +#include "crys_rsa_types.h" +#include "crys_rnd.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module defines APIs that support [PKCS1_1.5] and [PKCS1_2.1] encryption and signature schemes. +@defgroup crys_rsa_schemes CryptoCell RSA encryption and signature schemes +@{ +@ingroup crys_rsa +*/ + +/**********************************************************************************************************/ +/*! +@brief This function implements the Encrypt algorithm, as defined in [PKCS1_2.1] and [PKCS1_1.5]. + +It should not be called directly. Instead, use macros ::CRYS_RSA_OAEP_Encrypt or ::CRYS_RSA_PKCS1v15_Encrypt. + +@return CRYS_OK on success. +@return A non-zero value from crys_rsa_error.h, crys_rnd_error.h or crys_hash_error.h on failure. +*/ +CIMPORT_C CRYSError_t SaSi_RsaSchemesEncrypt( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + CRYS_RSAUserPubKey_t *UserPubKey_ptr, /*!< [in] Pointer to the public key data structure. */ + CRYS_RSAPrimeData_t *PrimeData_ptr, /*!< [in] Pointer to a temporary structure that is internally used as workspace for the + Encryption operation. */ + CRYS_RSA_HASH_OpMode_t hashFunc, /*!< [in] The HASH function to be used. One of the supported SHA-x HASH modes, as defined + in ::CRYS_RSA_HASH_OpMode_t (MD5 is not supported).*/ + uint8_t *L, /*!< [in] The label input pointer. Relevant for [PKCS1_2.1] only. NULL by default. + NULL for [PKCS1_1.5]. */ + uint16_t Llen, /*!< [in] The label length. Relevant for [PKCS1_2.1] only. Zero by default. + Must be <=2048. Zero for [PKCS1_1.5]. */ + CRYS_PKCS1_MGF_t MGF, /*!< [in] The mask generation function. [PKCS1_2.1] defines MGF1, so the only value + allowed here is CRYS_PKCS1_MGF1. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the data to encrypt. */ + uint16_t DataInSize, /*!< [in] The size (in bytes) of the data to encrypt. The data size must be: + - For [PKCS1_2.1], DataSize <= modulus size - 2*HashLen - 2. + - For [PKCS1_1.5], DataSize <= modulus size - 11. */ + uint8_t *Output_ptr, /*!< [out] Pointer to the encrypted data. The buffer must be at least modulus size bytes long. */ + CRYS_PKCS1_version PKCS1_ver /*!< [in] [PKCS1_1.5] or [PKCS1_2.1], according to the functionality required. */ +); + +/*! + @brief + CRYS_RSA_OAEP_PSS21_Encrypt implements the RSAES-OAEP algorithm + as defined in PKCS#1 v2.1 8.1. + + \note It is not recommended to use hash MD5 in OAEP PKCS1 ver 2.1, therefore + it is not supported. + + This function combines the RSA encryption primitive and the + EME-OAEP encoding method, to provide an RSA-based encryption + method that is semantically secure against adaptive + chosen-ciphertext attacks. For additional details, please refer to + the PKCS#1 standard. +*/ +#define CRYS_RSA_OAEP_Encrypt(rndState_ptr, rndGenerateVectFunc, UserPubKey_ptr,PrimeData_ptr,HashMode,L,Llen,MGF,Data_ptr,DataSize,Output_ptr)\ + SaSi_RsaSchemesEncrypt(rndState_ptr, rndGenerateVectFunc, UserPubKey_ptr,PrimeData_ptr,HashMode,L,Llen,MGF,Data_ptr,DataSize,Output_ptr,CRYS_PKCS1_VER21) + +/*! + @brief + CRYS_RSA_PKCS1v15_Encrypt implements the RSAES-PKCS1v15 algorithm + as defined in PKCS#1 v2.1 8.2. +*/ +#define CRYS_RSA_PKCS1v15_Encrypt(rndState_ptr, rndGenerateVectFunc, UserPubKey_ptr,PrimeData_ptr,DataIn_ptr,DataInSize,Output_ptr)\ + SaSi_RsaSchemesEncrypt(rndState_ptr, rndGenerateVectFunc, UserPubKey_ptr,PrimeData_ptr,CRYS_RSA_HASH_NO_HASH_mode,NULL,0,CRYS_PKCS1_NO_MGF,DataIn_ptr, \ + DataInSize, Output_ptr,CRYS_PKCS1_VER15) + + +/**********************************************************************************************************/ +/*! +@brief This function implements the Decrypt algorithm, as defined in [PKCS1_2.1] and [PKCS1_1.5]. + +It should not be called directly. Instead, use macros ::CRYS_RSA_OAEP_Decrypt or ::CRYS_RSA_PKCS1v15_Decrypt. + +@return CRYS_OK on success. +@return A non-zero value from crys_rsa_error.h or crys_hash_error.h on failure. +*/ +CIMPORT_C CRYSError_t SaSi_RsaSchemesDecrypt( + CRYS_RSAUserPrivKey_t *UserPrivKey_ptr, /*!< [in] Pointer to the private key data structure of the user. */ + CRYS_RSAPrimeData_t *PrimeData_ptr, /*!< [in] Pointer to a temporary structure that is internally used as workspace + for the decryption operation. */ + CRYS_RSA_HASH_OpMode_t hashFunc, /*!< [in] The HASH function to be used. One of the supported SHA-x HASH modes, + as defined in ::CRYS_RSA_HASH_OpMode_t (MD5 is not supported). */ + uint8_t *L, /*!< [in] The label input pointer. Relevant for [PKCS1_2.1] only. NULL by default. + NULL for [PKCS1_1.5]. */ + uint16_t Llen, /*!< [in] The label length. Relevant for [PKCS1_2.1] only. Zero by default. + Zero for [PKCS1_1.5]. */ + CRYS_PKCS1_MGF_t MGF, /*!< [in] The mask generation function. [PKCS1_2.1] defines MGF1, so the only + value allowed here is CRYS_PKCS1_MGF1. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the data to decrypt. */ + uint16_t DataInSize, /*!< [in] The size (in bytes) of the data to decrypt. DataSize must be ≤ + the modulus size. */ + uint8_t *Output_ptr, /*!< [in] Pointer to the decrypted data. The buffer must be at least + PrivKey_ptr->N.len bytes long (i.e. the modulus size in bytes). */ + uint16_t *OutputSize_ptr, /*!< [in] Pointer to the byte size of the buffer pointed to by Output_buffer. + The size must be: +
    • For PKCS #1 v2.1: Modulus size > OutputSize >= + (modulus size - 2*HashLen - 2).
    • +
    • For PKCS #1 v1.5: Modulus size > OutputSize >= (modulus size - 11). + The value pointed by OutputSize_ptr is updated after decryption with + the actual number of bytes that are loaded to Output_ptr.
    */ + CRYS_PKCS1_version PKCS1_ver /*!< [in] [PKCS1_1.5] or [PKCS1_2.1], according to the functionality required. */ +); + +/**********************************************************************************************************/ +/** + @brief + CRYS_RSA_OAEP_Decrypt implements the RSAES-OAEP algorithm + as defined in PKCS#1 v2.1 8.1. + + \note It is not recommended to use hash MD5 in OAEP PKCS1 ver 2.1, therefore + it is not supported. + + This function combines the RSA decryption primitive and the + EME-OAEP encoding method, to provide an RSA-based decryption + method that is semantically secure against adaptive + chosen-ciphertext attacks. For more details, please refer to + the PKCS#1 standard. + +*/ +#define CRYS_RSA_OAEP_Decrypt(UserPrivKey_ptr,PrimeData_ptr,HashMode,L,Llen,MGF,Data_ptr,DataSize,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSchemesDecrypt(UserPrivKey_ptr,PrimeData_ptr,HashMode,L,Llen,MGF,Data_ptr,DataSize,Output_ptr,OutputSize_ptr,CRYS_PKCS1_VER21) + + +/** + @brief + CRYS_RSA_PKCS1v15_Decrypt implements the RSAES-PKCS1v15 algorithm as defined + in PKCS#1 v2.1 8.2. +*/ +#define CRYS_RSA_PKCS1v15_Decrypt(UserPrivKey_ptr,PrimeData_ptr,DataIn_ptr,DataInSize,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSchemesDecrypt(UserPrivKey_ptr,PrimeData_ptr,CRYS_RSA_HASH_NO_HASH_mode,NULL,0,CRYS_PKCS1_NO_MGF,DataIn_ptr,DataInSize,Output_ptr,OutputSize_ptr,CRYS_PKCS1_VER15) + + +/**********************************************************************************************************/ +/*! +@brief Implements the Signing algorithm, as defined in [PKCS1_1.5] or [PKCS1_2.1], using a single function. + +The input data may be either a non-hashed data or a digest of a hash function. +For a non-hashed data, the input data will be hashed using the hash function indicated by ::CRYS_RSA_HASH_OpMode_t. +For a digest, ::CRYS_RSA_HASH_OpMode_t should indicate the hash function that the input data was created by, and it will not be hashed. + +@return CRYS_OK on success. +@return A non-zero value from crys_rsa_error.h, crys_rnd_error.h or crys_hash_error.h on failure. +*/ +CIMPORT_C CRYSError_t SaSi_RsaSign( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in/out] Pointer to the RND Generate vector function pointer. */ + CRYS_RSAPrivUserContext_t *UserContext_ptr, /*!< [in] Pointer to a temporary context for internal use. */ + CRYS_RSAUserPrivKey_t *UserPrivKey_ptr, /*!< [in] Pointer to the private key data structure of the user. + The representation (pair or quintuple) and hence the algorithm (CRT or not CRT) + is determined by the Private Key build function - + ::CRYS_RSA_Build_PrivKey or ::CRYS_RSA_Build_PrivKeyCRT. */ + CRYS_RSA_HASH_OpMode_t rsaHashMode, /*!< [in] One of the supported SHA-x HASH modes, as defined in ::CRYS_RSA_HASH_OpMode_t. + (MD5 is not supported). */ + CRYS_PKCS1_MGF_t MGF, /*!< [in] The mask generation function. [PKCS1_2.1] defines only MGF1, so the only value + allowed for [PKCS1_2.1] is CRYS_PKCS1_MGF1. */ + uint16_t SaltLen, /*!< [in] The Length of the Salt buffer (relevant for PKCS#1 Ver 2.1 only, typically lengths is 0 or hash Len). + FIPS 186-4 requires, that SaltLen <= hash len. If SaltLen > KeySize - hash Len - 2, the function + returns an error. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the input data to be signed. + The size of the scatter/gather list representing the data buffer is limited to 128 + entries, and the size of each entry is limited to 64KB (fragments larger than + 64KB are broken into fragments <= 64KB). */ + uint32_t DataInSize, /*!< [in] The size (in bytes) of the data to sign. */ + uint8_t *Output_ptr, /*!< [out] Pointer to the signature. The buffer must be at least PrivKey_ptr->N.len bytes + long (i.e. the modulus size in bytes). */ + uint16_t *OutputSize_ptr, /*!< [in/out] Pointer to the signature size value - the input value is the signature + buffer size allocated, the output value is the signature size used. + he buffer must be equal to PrivKey_ptr->N.len bytes long + (i.e. the modulus size in bytes). */ + CRYS_PKCS1_version PKCS1_ver /*!< [in] [PKCS1_1.5] or [PKCS1_2.1], according to the functionality required. */ +); + + +/*! +@brief CRYS_RSA_PKCS1v15_Sign implements the RSASSA-PKCS1v15 algorithm as defined in PKCS#1 v1.5. + +This function combines the RSASP1 signature primitive and the EMSA-PKCS1v15 encoding method, to provide an RSA-based signature scheme. +For more details, please refer to the PKCS#1 standard. + */ + +#define CRYS_RSA_PKCS1v15_Sign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,hashFunc,DataIn_ptr,DataInSize,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSign(rndState_ptr, rndGenerateVectFunc, (UserContext_ptr),(UserPrivKey_ptr),(hashFunc),(CRYS_PKCS1_NO_MGF),0,(DataIn_ptr),(DataInSize),(Output_ptr),(OutputSize_ptr),CRYS_PKCS1_VER15) + + +/*! +@brief CRYS_RSA_PKCS1v15_SHA1_Sign implements the RSASSA-PKCS1v15 algorithm as defined in PKCS#1 v1.5, but without performing a HASH function - +it assumes that the data in has already been hashed using SHA-1. + +\note The data_in size is already known after the Hash. +*/ +#define CRYS_RSA_PKCS1v15_SHA1_Sign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,DataIn_ptr,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSign(rndState_ptr, rndGenerateVectFunc, (UserContext_ptr),(UserPrivKey_ptr),(CRYS_RSA_After_SHA1_mode),(CRYS_PKCS1_NO_MGF),0,(DataIn_ptr),CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES,(Output_ptr),(OutputSize_ptr),CRYS_PKCS1_VER15) + +/*! +@brief CRYS_RSA_PKCS1v15_MD5_Sign implements the RSASSA-PKCS1v15 algorithm as defined in PKCS#1 v1.5, but without performing a HASH function - +it assumes that the data in has already been hashed using MD5. + +\note The data_in size is already known after the Hash. +*/ + +#define CRYS_RSA_PKCS1v15_MD5_Sign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,DataIn_ptr,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSign(rndState_ptr, rndGenerateVectFunc, (UserContext_ptr),(UserPrivKey_ptr),CRYS_RSA_After_MD5_mode,CRYS_PKCS1_NO_MGF,0,(DataIn_ptr),CRYS_HASH_MD5_DIGEST_SIZE_IN_BYTES,(Output_ptr),(OutputSize_ptr),CRYS_PKCS1_VER15) + + +/*! +@brief CRYS_RSA_PKCS1v15_SHA224_Sign implements the RSASSA-PKCS1v15 algorithm as defined in PKCS#1 v1.5, but without performing a HASH function - +it assumes that the data in has already been hashed using SHA-224. + +\note The data_in size is already known after the Hash. +*/ +#define CRYS_RSA_PKCS1v15_SHA224_Sign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,DataIn_ptr,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSign(rndState_ptr, rndGenerateVectFunc, (UserContext_ptr),(UserPrivKey_ptr),(CRYS_RSA_After_SHA224_mode),(CRYS_PKCS1_NO_MGF),0,(DataIn_ptr),CRYS_HASH_SHA224_DIGEST_SIZE_IN_BYTES,(Output_ptr),(OutputSize_ptr),CRYS_PKCS1_VER15) + + +/*! +@brief CRYS_RSA_PKCS1v15_SHA256_Sign implements the RSASSA-PKCS1v15 algorithm as defined in PKCS#1 v1.5, but without performing a HASH function - +it assumes that the data in has already been hashed using SHA-256. + +\note The data_in size is already known after the Hash. +*/ +#define CRYS_RSA_PKCS1v15_SHA256_Sign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,DataIn_ptr,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSign(rndState_ptr, rndGenerateVectFunc, (UserContext_ptr),(UserPrivKey_ptr),(CRYS_RSA_After_SHA256_mode),(CRYS_PKCS1_NO_MGF),0,(DataIn_ptr),CRYS_HASH_SHA256_DIGEST_SIZE_IN_BYTES,(Output_ptr),(OutputSize_ptr),CRYS_PKCS1_VER15) + +/*! +@brief CRYS_RSA_PKCS1v15_SHA1_Sign implements the RSASSA-PKCS1v15 algorithm as defined in PKCS#1 v1.5, but without performing a HASH function - +it assumes that the data in has already been hashed using SHA-384. + +\note The data_in size is already known after the Hash. +*/ +#define CRYS_RSA_PKCS1v15_SHA384_Sign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,DataIn_ptr,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSign(rndState_ptr, rndGenerateVectFunc, (UserContext_ptr),(UserPrivKey_ptr),(CRYS_RSA_After_SHA384_mode),(CRYS_PKCS1_NO_MGF),0,(DataIn_ptr),CRYS_HASH_SHA384_DIGEST_SIZE_IN_BYTES,(Output_ptr),(OutputSize_ptr),CRYS_PKCS1_VER15) + + +/*! +@brief CRYS_RSA_PKCS1v15_SHA512_Sign implements the RSASSA-PKCS1v15 algorithm as defined in PKCS#1 v1.5, but without performing a HASH function - +it assumes that the data in has already been hashed using SHA-512. + +\note The data_in size is already known after the Hash. +*/ +#define CRYS_RSA_PKCS1v15_SHA512_Sign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,DataIn_ptr,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSign(rndState_ptr, rndGenerateVectFunc, (UserContext_ptr),(UserPrivKey_ptr),(CRYS_RSA_After_SHA512_mode),(CRYS_PKCS1_NO_MGF),0,(DataIn_ptr),CRYS_HASH_SHA512_DIGEST_SIZE_IN_BYTES,(Output_ptr),(OutputSize_ptr),CRYS_PKCS1_VER15) + + + +/*! +@brief CRYS_RSA_PSS_Sign implements the RSASSA-PSS algorithm as defined in PKCS#1 v2.1 9.1, in a single function call. + +\note According to the PKCS#1 ver2.1 it is not recommended to use MD5 Hash, therefore it is not supported. + +The actual macro that is used by the user is ::CRYS_RSA_PSS_Sign. +*/ + +#define CRYS_RSA_PSS_Sign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,hashFunc,MGF,SaltLen,DataIn_ptr,DataInSize,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,hashFunc,MGF,SaltLen,DataIn_ptr,DataInSize,Output_ptr,OutputSize_ptr,CRYS_PKCS1_VER21) + + +/*! +@brief CRYS_RSA_PSS_SHA1_Sign implements the RSASSA-PSS algorithm as defined in PKCS#1 v2.1 9.1 in a single function call, but without performing a HASH function - +it assumes that the data in has already been hashed using SHA-1. + +\note The data_in size is already known after the Hash. + +The actual macro that is used by the users is ::CRYS_RSA_PSS_SHA1_Sign. +*/ + +#define CRYS_RSA_PSS_SHA1_Sign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,MGF,SaltLen,DataIn_ptr,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,CRYS_RSA_After_SHA1_mode,MGF,SaltLen,DataIn_ptr,CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES,Output_ptr,OutputSize_ptr,CRYS_PKCS1_VER21) + + +/*! +@brief CRYS_RSA_PSS_SHA224_Sign implements the RSASSA-PSS algorithm as defined in PKCS#1 v2.1 9.1 in a single function call, but without performing a HASH function - +it assumes that the data in has already been hashed using SHA-224. + +\note The data_in size is already known after the Hash. + +The actual macro that is used by the users is ::CRYS_RSA_PSS_SHA224_Sign. +*/ + +#define CRYS_RSA_PSS_SHA224_Sign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,MGF,SaltLen,DataIn_ptr,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,CRYS_RSA_After_SHA224_mode,MGF,SaltLen,DataIn_ptr,CRYS_HASH_SHA224_DIGEST_SIZE_IN_BYTES,Output_ptr,OutputSize_ptr,CRYS_PKCS1_VER21) + + +/*! +@brief CRYS_RSA_PSS_SHA256_Sign implements the RSASSA-PSS algorithm as defined in PKCS#1 v2.1 9.1 in a single function call, but without performing a HASH function - +it assumes that the data in has already been hashed using SHA-256. + +\note The data_in size is already known after the Hash. + +The actual macro that is used by the users is ::CRYS_RSA_PSS_SHA256_Sign. +*/ + +#define CRYS_RSA_PSS_SHA256_Sign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,MGF,SaltLen,DataIn_ptr,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,CRYS_RSA_After_SHA256_mode,MGF,SaltLen,DataIn_ptr,CRYS_HASH_SHA256_DIGEST_SIZE_IN_BYTES,Output_ptr,OutputSize_ptr,CRYS_PKCS1_VER21) + + +/*! +@brief CRYS_RSA_PSS_SHA384_Sign implements the RSASSA-PSS algorithm as defined in PKCS#1 v2.1 9.1 in a single function call, but without performing a HASH function - +it assumes that the data in has already been hashed using SHA-384. + +\note The data_in size is already known after the Hash. + +The actual macro that is used by the users is ::CRYS_RSA_PSS_SHA384_Sign. +*/ + +#define CRYS_RSA_PSS_SHA384_Sign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,MGF,SaltLen,DataIn_ptr,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,CRYS_RSA_After_SHA384_mode,MGF,SaltLen,DataIn_ptr,CRYS_HASH_SHA384_DIGEST_SIZE_IN_BYTES,Output_ptr,OutputSize_ptr,CRYS_PKCS1_VER21) + + +/*! +@brief CRYS_RSA_PSS_SHA512_Sign implements the RSASSA-PSS algorithm as defined in PKCS#1 v2.1 9.1 in a single function call, but without performing a HASH function - +it assumes that the data in has already been hashed using SHA-512. + +\note The data_in size is already known after the Hash. + +The actual macro that is used by the users is ::CRYS_RSA_PSS_SHA512_Sign. +*/ + +#define CRYS_RSA_PSS_SHA512_Sign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,MGF,SaltLen,DataIn_ptr,Output_ptr,OutputSize_ptr)\ + SaSi_RsaSign(rndState_ptr, rndGenerateVectFunc, UserContext_ptr,UserPrivKey_ptr,CRYS_RSA_After_SHA512_mode,MGF,SaltLen,DataIn_ptr,CRYS_HASH_SHA512_DIGEST_SIZE_IN_BYTES,Output_ptr,OutputSize_ptr,CRYS_PKCS1_VER21) + + +/**********************************************************************************************************/ +/*! +@brief Implements the RSA signature verification algorithms, in a single function call, as defined in referenced standards [PKCS1_1.5] +and [PKCS1_2.1]. + +The input data may be either a non-hashed data or a digest of a hash function. +For a non-hashed data, the input data will be hashed using the hash function indicated by ::CRYS_RSA_HASH_OpMode_t. +For a digest, ::CRYS_RSA_HASH_OpMode_t should indicate the hash function that the input data was created by, and it will not be hashed. + +@return CRYS_OK on success. +@return A non-zero value from crys_rsa_error.h or crys_hash_error.h on failure. +*/ + +CIMPORT_C CRYSError_t SaSi_RsaVerify( + CRYS_RSAPubUserContext_t *UserContext_ptr, /*!< [in] Pointer to a temporary context for internal use. */ + CRYS_RSAUserPubKey_t *UserPubKey_ptr, /*!< [in] Pointer to the public key data structure of the user. */ + CRYS_RSA_HASH_OpMode_t rsaHashMode, /*!< [in] One of the supported SHA-x HASH modes, as defined in ::CRYS_RSA_HASH_OpMode_t. + (MD5 is not supported). */ + CRYS_PKCS1_MGF_t MGF, /*!< [in] The mask generation function. [PKCS1_2.1] defines only MGF1, so the only + value allowed for [PKCS_2.1] is CRYS_PKCS1_MGF1. */ + uint16_t SaltLen, /*!< [in] The Length of the Salt buffer. Relevant only for [PKCS1_2.1]. + Typical lengths are 0 or hash Len (20 for SHA-1). + The maximum length allowed is [modulus size - hash Len - 2]. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the input data to be verified. + The size of the scatter/gather list representing the data buffer is + limited to 128 entries, and the size of each entry is limited to 64KB + (fragments larger than 64KB are broken into fragments <= 64KB). */ + uint32_t DataInSize, /*!< [in] The size (in bytes) of the data whose signature is to be verified. */ + uint8_t *Sig_ptr, /*!< [in] Pointer to the signature to be verified. + The length of the signature is PubKey_ptr->N.len bytes + (i.e. the modulus size in bytes). */ + CRYS_PKCS1_version PKCS1_ver /*!< [in] [PKCS1_1.5] or [PKCS1_2.1], according to the functionality required. */ +); + +/*! +@brief CRYS_RSA_PKCS1v15_Verify implements the RSASSA-PKCS1v15 Verify algorithm as defined in PKCS#1 v1.5. +*/ +#define CRYS_RSA_PKCS1v15_Verify(UserContext_ptr,UserPubKey_ptr,hashFunc,DataIn_ptr,DataInSize,Sig_ptr)\ + SaSi_RsaVerify(UserContext_ptr,UserPubKey_ptr,hashFunc,CRYS_PKCS1_NO_MGF,0,DataIn_ptr,DataInSize,Sig_ptr,CRYS_PKCS1_VER15) + + +/*! +@brief CRYS_RSA_PKCS1v15_MD5_Verify implements the RSASSA-PKCS1v15 Verify algorithm as defined in PKCS#1 v1.5, but without operating the HASH function - +it assumes the DataIn_ptr data has already been hashed using MD5. +*/ +#define CRYS_RSA_PKCS1v15_MD5_Verify(UserContext_ptr,UserPubKey_ptr,DataIn_ptr,Sig_ptr)\ + SaSi_RsaVerify(UserContext_ptr,UserPubKey_ptr,CRYS_RSA_After_MD5_mode,CRYS_PKCS1_NO_MGF,0,DataIn_ptr,CRYS_HASH_MD5_DIGEST_SIZE_IN_BYTES,Sig_ptr,CRYS_PKCS1_VER15) + + +/*! +@brief CRYS_RSA_PKCS1v15_SHA1_Verify implements the RSASSA-PKCS1v15 Verify algorithm as defined in PKCS#1 v1.5, but without operating the HASH function - +it assumes that the DataIn_ptr data has already been hashed using SHA1. + +*/ +#define CRYS_RSA_PKCS1v15_SHA1_Verify(UserContext_ptr,UserPubKey_ptr,DataIn_ptr,Sig_ptr)\ + SaSi_RsaVerify(UserContext_ptr,UserPubKey_ptr,CRYS_RSA_After_SHA1_mode,CRYS_PKCS1_NO_MGF,0,DataIn_ptr,CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES,Sig_ptr,CRYS_PKCS1_VER15) + +/*! +@brief CRYS_RSA_PKCS1v15_SHA224_Verify implements the RSASSA-PKCS1v15 Verify algorithm as defined in PKCS#1 v1.5, but without operating the HASH function - +it assumes that the DataIn_ptr data has already been hashed using SHA224. + +*/ +#define CRYS_RSA_PKCS1v15_SHA224_Verify(UserContext_ptr,UserPubKey_ptr,DataIn_ptr,Sig_ptr)\ + SaSi_RsaVerify(UserContext_ptr,UserPubKey_ptr,CRYS_RSA_After_SHA224_mode,CRYS_PKCS1_NO_MGF,0,DataIn_ptr,CRYS_HASH_SHA224_DIGEST_SIZE_IN_BYTES,Sig_ptr,CRYS_PKCS1_VER15) + +/*! +@brief CRYS_RSA_PKCS1v15_SHA256_Verify implements the RSASSA-PKCS1v15 Verify algorithm as defined in PKCS#1 v1.5, but without operating the HASH function - +it assumes that the DataIn_ptr data has already been hashed using SHA256. + +*/ +#define CRYS_RSA_PKCS1v15_SHA256_Verify(UserContext_ptr,UserPubKey_ptr,DataIn_ptr,Sig_ptr)\ + SaSi_RsaVerify(UserContext_ptr,UserPubKey_ptr,CRYS_RSA_After_SHA256_mode,CRYS_PKCS1_NO_MGF,0,DataIn_ptr,CRYS_HASH_SHA256_DIGEST_SIZE_IN_BYTES,Sig_ptr,CRYS_PKCS1_VER15) + +/*! +@brief CRYS_RSA_PKCS1v15_SHA384_Verify implements the RSASSA-PKCS1v15 Verify algorithm as defined in PKCS#1 v1.5, but without operating the HASH function - +it assumes that the DataIn_ptr data has already been hashed using SHA384. + +*/ +#define CRYS_RSA_PKCS1v15_SHA384_Verify(UserContext_ptr,UserPubKey_ptr,DataIn_ptr,Sig_ptr)\ + SaSi_RsaVerify(UserContext_ptr,UserPubKey_ptr,CRYS_RSA_After_SHA384_mode,CRYS_PKCS1_NO_MGF,0,DataIn_ptr,CRYS_HASH_SHA384_DIGEST_SIZE_IN_BYTES,Sig_ptr,CRYS_PKCS1_VER15) + +/*! +@brief CRYS_RSA_PKCS1v15_SHA512_Verify implements the RSASSA-PKCS1v15 Verify algorithm as defined in PKCS#1 v1.5, but without operating the HASH function - +it assumes that the DataIn_ptr data has already been hashed using SHA512. + +*/ +#define CRYS_RSA_PKCS1v15_SHA512_Verify(UserContext_ptr,UserPubKey_ptr,DataIn_ptr,Sig_ptr)\ + SaSi_RsaVerify(UserContext_ptr,UserPubKey_ptr,CRYS_RSA_After_SHA512_mode,CRYS_PKCS1_NO_MGF,0,DataIn_ptr,CRYS_HASH_SHA512_DIGEST_SIZE_IN_BYTES,Sig_ptr,CRYS_PKCS1_VER15) + +/*! +@brief CRYS_RSA_PSS_Verify implements the RSASSA-PKCS1v21 Verify algorithm as defined in PKCS#1 v2.1. +*/ + +#define CRYS_RSA_PSS_Verify(UserContext_ptr,UserPubKey_ptr,hashFunc,MGF,SaltLen,DataIn_ptr,DataInSize,Sig_ptr)\ + SaSi_RsaVerify(UserContext_ptr,UserPubKey_ptr,hashFunc,MGF,SaltLen,DataIn_ptr,DataInSize,Sig_ptr,CRYS_PKCS1_VER21) + + /*! +@brief CRYS_RSA_PSS_SHA1_Verify implements the PKCS1v21 Verify algorithm as defined in PKCS#1 v2.1, but without operating the HASH function - +it assumes the DataIn_ptr has already been hashed using SHA1. + +*/ + +#define CRYS_RSA_PSS_SHA1_Verify(UserContext_ptr,UserPubKey_ptr,MGF,SaltLen,DataIn_ptr,Sig_ptr)\ + SaSi_RsaVerify(UserContext_ptr,UserPubKey_ptr,CRYS_RSA_After_SHA1_mode,MGF,SaltLen,DataIn_ptr,CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES,Sig_ptr,CRYS_PKCS1_VER21) + + +/*! +@brief CRYS_RSA_PSS_SHA224_Verify implements the PKCS1v21 Verify algorithm as defined in PKCS#1 v2.1, but without operating the HASH function - +it assumes the DataIn_ptr has already been hashed using SHA224. +*/ + +#define CRYS_RSA_PSS_SHA224_Verify(UserContext_ptr,UserPubKey_ptr,MGF,SaltLen,DataIn_ptr,Sig_ptr)\ + SaSi_RsaVerify(UserContext_ptr,UserPubKey_ptr,CRYS_RSA_After_SHA224_mode,MGF,SaltLen,DataIn_ptr,CRYS_HASH_SHA224_DIGEST_SIZE_IN_BYTES,Sig_ptr,CRYS_PKCS1_VER21) + +/*! +@brief CRYS_RSA_PSS_SHA256_Verify implements the PKCS1v21 Verify algorithm as defined in PKCS#1 v2.1, but without operating the HASH function - +it assumes the DataIn_ptr has already been hashed using SHA256. + +*/ + +#define CRYS_RSA_PSS_SHA256_Verify(UserContext_ptr,UserPubKey_ptr,MGF,SaltLen,DataIn_ptr,Sig_ptr)\ + SaSi_RsaVerify(UserContext_ptr,UserPubKey_ptr,CRYS_RSA_After_SHA256_mode,MGF,SaltLen,DataIn_ptr,CRYS_HASH_SHA256_DIGEST_SIZE_IN_BYTES,Sig_ptr,CRYS_PKCS1_VER21) + + +/*! +@brief CRYS_RSA_PSS_SHA384_Verify implements the PKCS1v21 Verify algorithm as defined in PKCS#1 v2.1, but without operating the HASH function - +it assumes the DataIn_ptr has already been hashed using SHA384. + +*/ + +#define CRYS_RSA_PSS_SHA384_Verify(UserContext_ptr,UserPubKey_ptr,MGF,SaltLen,DataIn_ptr,Sig_ptr)\ + SaSi_RsaVerify(UserContext_ptr,UserPubKey_ptr,CRYS_RSA_After_SHA384_mode,MGF,SaltLen,DataIn_ptr,CRYS_HASH_SHA384_DIGEST_SIZE_IN_BYTES,Sig_ptr,CRYS_PKCS1_VER21) + + +/*! +@brief CRYS_RSA_PSS_SHA512_Verify implements the PKCS1v21 Verify algorithm as defined in PKCS#1 v2.1, but without operating the HASH function - +it assumes the DataIn_ptr has already been hashed using SHA512. +*/ + +#define CRYS_RSA_PSS_SHA512_Verify(UserContext_ptr,UserPubKey_ptr,MGF,SaltLen,DataIn_ptr,Sig_ptr)\ + SaSi_RsaVerify(UserContext_ptr,UserPubKey_ptr,CRYS_RSA_After_SHA512_mode,MGF,SaltLen,DataIn_ptr,CRYS_HASH_SHA512_DIGEST_SIZE_IN_BYTES,Sig_ptr,CRYS_PKCS1_VER21) + +/**********************************************************************************************************/ + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/crys_rsa_types.h b/external/nrf_cc310/include/crys_rsa_types.h new file mode 100644 index 0000000..a0acc52 --- /dev/null +++ b/external/nrf_cc310/include/crys_rsa_types.h @@ -0,0 +1,616 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_RSA_TYPES_H +#define CRYS_RSA_TYPES_H + +#include "crys_hash.h" +#include "crys_pka_defs_hw.h" +#include "ssi_pal_types.h" +#include "ssi_pal_compiler.h" + +#ifdef DX_SOFT_KEYGEN +#include "ccsw_crys_rsa_shared_types.h" +#endif + + +#ifdef __cplusplus +extern "C" +{ +#endif +/*! +@file +@brief This file contains all of the enums and definitions that are used for the CRYS RSA APIs. +@defgroup crys_rsa_types CryptoCell RSA used definitions and enums +@{ +@ingroup crys_rsa +*/ + +/************************ Defines ******************************/ + +/*! Definition of HASH context size. */ +#define CRYS_PKA_RSA_HASH_CTX_SIZE_IN_WORDS CRYS_HASH_USER_CTX_SIZE_IN_WORDS + +/*! Maximal key size in bytes. */ +#define CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BYTES (CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS / SASI_BITS_IN_BYTE) + +/*! Minimal key size in bits. */ +#define CRYS_RSA_MIN_VALID_KEY_SIZE_VALUE_IN_BITS 512 +/*! Valid key size multiplications in RSA. */ +#define CRYS_RSA_VALID_KEY_SIZE_MULTIPLE_VALUE_IN_BITS 256 + +/*! Maximal RSA generated key size in bits. */ +#define CRYS_RSA_MAX_KEY_GENERATION_SIZE_BITS CRYS_RSA_MAX_KEY_GENERATION_HW_SIZE_BITS + +/* FIPS 184-4 definitions for allowed RSA and FFC DH key sizes */ +/*! FIPS 184-4 allowed key size - 1024 bits. */ +#define CRYS_RSA_FIPS_KEY_SIZE_1024_BITS 1024 +/*! FIPS 184-4 allowed key size - 2048 bits. */ +#define CRYS_RSA_FIPS_KEY_SIZE_2048_BITS 2048 +/*! FIPS 184-4 allowed key size - 3072 bits. */ +#define CRYS_RSA_FIPS_KEY_SIZE_3072_BITS 3072 +/*! FIPS 184-4 allowed modulus size in bits. */ +#define CRYS_RSA_FIPS_MODULUS_SIZE_BITS CRYS_RSA_FIPS_KEY_SIZE_2048_BITS + +/*! FIPS 184-4 DH key size - 1024 bits. */ +#define CRYS_DH_FIPS_KEY_SIZE_1024_BITS 1024 +/*! FIPS 184-4 DH key size - 2048 bits. */ +#define CRYS_DH_FIPS_KEY_SIZE_2048_BITS 2048 + + +/*! Salt length definition - if the salt length is not available in verify operation, the user can use this define and the algorithm will + calculate the salt length alone*/ +/*!\note Security wise: it is not recommended to use this flag.*/ +#define CRYS_RSA_VERIFY_SALT_LENGTH_UNKNOWN 0xFFFF + +/*! Minimal public exponent value */ +#define CRYS_RSA_MIN_PUB_EXP_VALUE 3 +/*! Minimal private exponent value */ +#define CRYS_RSA_MIN_PRIV_EXP_VALUE 1 + +/* The maximum buffer size for the 'H' value */ +/*! Temporary buffer size definition.*/ +#define CRYS_RSA_TMP_BUFF_SIZE (CRYS_RSA_OAEP_ENCODE_MAX_MASKDB_SIZE + CRYS_RSA_OAEP_ENCODE_MAX_SEEDMASK_SIZE + CRYS_PKA_RSA_HASH_CTX_SIZE_IN_WORDS*sizeof(uint32_t) + sizeof(CRYS_HASH_Result_t)) + +/*! Hash structure definition.*/ +#define CRYS_PKCS1_HashFunc_t CRYS_HASH_OperationMode_t + +/*! OAEP maximal H length.*/ +#define CRYS_RSA_OAEP_MAX_HLEN CRYS_HASH_SHA512_DIGEST_SIZE_IN_BYTES + +/*! MGF1 definitions */ +#define CRYS_RSA_MGF_2_POWER_32 65535 /*!< \internal 0xFFFF This is the 2^32 of the 2^32*hLen boundary check */ +/*! MGF1 definitions */ +#define CRYS_RSA_SIZE_OF_T_STRING_BYTES (CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS*sizeof(uint32_t)) + +/*********************************************************** + * + * RSA PKCS#1 v2.1 DEFINES + * + ***********************************************************/ +/*! Size of OEAP seed. */ +#define CRYS_RSA_OAEP_ENCODE_MAX_SEEDMASK_SIZE CRYS_RSA_OAEP_MAX_HLEN +/*! Maximal PSS salt size. */ +#define CRYS_RSA_PSS_SALT_LENGTH CRYS_RSA_OAEP_MAX_HLEN +/*! PSS padding length. */ +#define CRYS_RSA_PSS_PAD1_LEN 8 + +/*! OAEP encode mask size. */ +#define CRYS_RSA_OAEP_ENCODE_MAX_MASKDB_SIZE (CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS*sizeof(uint32_t)) /*!< \internal For OAEP Encode; the max size is emLen */ +/*! OAEP decode mask size. */ +#define CRYS_RSA_OAEP_DECODE_MAX_DBMASK_SIZE (CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS*sizeof(uint32_t)) /*!< \internal For OAEP Decode; the max size is emLen */ + +/************************ Enums ********************************/ + +/*! Defines the enum for the HASH operation mode. */ +typedef enum +{ + CRYS_RSA_HASH_MD5_mode = 0, /*!< For PKCS1 v1.5 only. The input data will be hashed with MD5 */ + CRYS_RSA_HASH_SHA1_mode = 1, /*!< The input data will be hashed with SHA1. */ + CRYS_RSA_HASH_SHA224_mode = 2, /*!< The input data will be hashed with SHA224. */ + CRYS_RSA_HASH_SHA256_mode = 3, /*!< The input data will be hashed with SHA256. */ + CRYS_RSA_HASH_SHA384_mode = 4, /*!< The input data will be hashed with SHA384. */ + CRYS_RSA_HASH_SHA512_mode = 5, /*!< The input data will be hashed with SHA512. */ + CRYS_RSA_After_MD5_mode = 6, /*!< For PKCS1 v1.5 only. The input data is a digest of MD5 and will not be hashed. */ + CRYS_RSA_After_SHA1_mode = 7, /*!< The input data is a digest of SHA1 and will not be hashed. */ + CRYS_RSA_After_SHA224_mode = 8, /*!< The input data is a digest of SHA224 and will not be hashed. */ + CRYS_RSA_After_SHA256_mode = 9, /*!< The input data is a digest of SHA256 and will not be hashed. */ + CRYS_RSA_After_SHA384_mode = 10, /*!< The input data is a digest of SHA384 and will not be hashed. */ + CRYS_RSA_After_SHA512_mode = 11, /*!< The input data is a digest of SHA512 and will not be hashed. */ + CRYS_RSA_After_HASH_NOT_KNOWN_mode = 12, /*!< \internal used only for PKCS#1 Ver 1.5 - possible to perform verify operation without hash mode input, + the hash mode is derived from the signature.*/ + CRYS_RSA_HASH_NO_HASH_mode = 13, /*!< Used for PKCS1 v1.5 Encrypt and Decrypt.*/ + CRYS_RSA_HASH_NumOfModes, /*!< Maximal number of hash operations modes. */ + + CRYS_RSA_HASH_OpModeLast = 0x7FFFFFFF, /*! Reserved.*/ + +}CRYS_RSA_HASH_OpMode_t; + + +/*! Defines the enum of the RSA decryption mode. */ +typedef enum +{ + CRYS_RSA_NoCrt = 10, /*!< Decryption no CRT mode.*/ + CRYS_RSA_Crt = 11, /*!< Decryption CRT mode.*/ + + CRYS_RSADecryptionNumOfOptions, /*! Reserved.*/ + + CRYS_RSA_DecryptionModeLast= 0x7FFFFFFF, /*! Reserved.*/ + +}CRYS_RSA_DecryptionMode_t; + +/*! RSA Key source definition. */ +typedef enum +{ + CRYS_RSA_ExternalKey = 1, /*!< External key.*/ + CRYS_RSA_InternalKey = 2, /*!< Internal key.*/ + + CRYS_RSA_KeySourceLast= 0x7FFFFFFF, /*!< Reserved. */ + +}CRYS_RSA_KeySource_t; + +/*! MGF values. */ +typedef enum +{ + CRYS_PKCS1_MGF1 = 0, /*! MGF1. */ + CRYS_PKCS1_NO_MGF = 1, /*! No MGF. */ + CRYS_RSA_NumOfMGFFunctions, /*! Maximal number of MGF options. */ + + CRYS_PKCS1_MGFLast= 0x7FFFFFFF, /*! Reserved.*/ + +}CRYS_PKCS1_MGF_t; + +/*! Defines the enum of the various PKCS1 versions. */ +typedef enum +{ + CRYS_PKCS1_VER15 = 0, /*! PKCS1 version 15. */ + CRYS_PKCS1_VER21 = 1, /*! PKCS1 version 21. */ + + CRYS_RSA_NumOf_PKCS1_versions, /*! Maximal number of PKCS versions. */ + + CRYS_PKCS1_versionLast= 0x7FFFFFFF, /*! Reserved.*/ + +}CRYS_PKCS1_version; + + +/*! Enum defining primality testing mode in Rabin-Miller + and Lucas-Lehmer tests (internal tests). */ +typedef enum +{ + /* P and Q primes */ + CRYS_RSA_PRIME_TEST_MODE = 0, /*!< PRIME test. */ + /* FFC (DH, DSA) primes */ + CRYS_DH_PRIME_TEST_MODE = 1, /*!< DH Prime test. */ + + CRYS_RSA_DH_PRIME_TEST_OFF_MODE /*!< Reserved.*/ + +}CRYS_RSA_DH_PrimeTestMode_t; + +/************************ Public and private key database Structs ******************************/ + +/* .................. The public key definitions ...................... */ +/* --------------------------------------------------------------------- */ + +/*! Public key data structure (used internally). */ +typedef struct +{ + /*! RSA modulus buffer. */ + uint32_t n[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + /*! RSA modulus size in bits. */ + uint32_t nSizeInBits; + + /*! RSA public exponent buffer. */ + uint32_t e[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + /*! RSA public exponent buffer. */ + uint32_t eSizeInBits; + + /*! Buffer for internal usage.*/ + uint32_t crysRSAIntBuff[CRYS_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS]; + +}CRYSRSAPubKey_t; + +/*! The public key's user structure prototype. This structure must be saved by the user, and is used as input to the RSA functions +(such as ::SaSi_RsaSchemesEncrypt etc.) */ +typedef struct CRYS_RSAUserPubKey_t +{ + /*! Validation tag. */ + uint32_t valid_tag; + /*! Public key data. */ + uint32_t PublicKeyDbBuff[ sizeof(CRYSRSAPubKey_t)/sizeof(uint32_t) + 1 ]; + + +}CRYS_RSAUserPubKey_t; + +/* .................. The private key definitions ...................... */ +/* --------------------------------------------------------------------- */ + +/*! Private key on non-CRT mode data structure (used internally). */ +typedef struct +{ + /*! RSA private exponent buffer. */ + uint32_t d[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + /*! RSA private exponent size in bits. */ + uint32_t dSizeInBits; + + /*! RSA public exponent buffer. */ + uint32_t e[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + /*! RSA public exponent size in bits. */ + uint32_t eSizeInBits; + +}CRYSRSAPrivNonCRTKey_t; + +/*! Private key on CRT mode data structure (used internally). */ +#ifndef CRYS_NO_RSA_SMALL_CRT_BUFFERS_SUPPORT +/* use small CRT buffers */ +typedef struct +{ + /*! First factor buffer. */ + uint32_t P[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS/2]; + /*! First factor size in bits. */ + uint32_t PSizeInBits; + + /*! Second factor buffer. */ + uint32_t Q[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS/2]; + /*! Second factor size in bits. */ + uint32_t QSizeInBits; + + /*! First CRT exponent buffer. */ + uint32_t dP[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS/2]; + /*! First CRT exponent size in bits. */ + uint32_t dPSizeInBits; + + /*! Second CRT exponent buffer. */ + uint32_t dQ[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS/2]; + /*! Second CRT exponent size in bits. */ + uint32_t dQSizeInBits; + + /*! First CRT coefficient buffer. */ + uint32_t qInv[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS/2]; + /*! First CRT coefficient size in bits. */ + uint32_t qInvSizeInBits; + +}CRYSRSAPrivCRTKey_t; + +/*! Size of CRYSRSAPrivCRTKey_t structure in words (used for temp buffers allocation). */ +#define CRYS_RSA_SIZE_IN_WORDS_OF_CRYSRSAPrivCRTKey_t (CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS*7/2 + 5) + +#else /* use large CRT buffers */ +typedef struct +{ + /* The first factor buffer and size in bits */ + uint32_t P[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + uint32_t PSizeInBits; + + /* The second factor buffer and its size in bits */ + uint32_t Q[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + uint32_t QSizeInBits; + + /* The first CRT exponent buffer and its size in bits */ + uint32_t dP[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + uint32_t dPSizeInBits; + + /* The second CRT exponent buffer and its size in bits */ + uint32_t dQ[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + uint32_t dQSizeInBits; + + /* The first CRT coefficient buffer and its size in bits */ + uint32_t qInv[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + uint32_t qInvSizeInBits; + +}CRYSRSAPrivCRTKey_t; + +/* size of CRYSRSAPrivCRTKey_t structure in words (used for temp buffers allocation) */ +#define CRYS_RSA_SIZE_IN_WORDS_OF_CRYSRSAPrivCRTKey_t (CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS*5 + 5) + +#endif + +/*! Private key data structure (used internally). */ +typedef struct +{ + /*! RSA modulus buffer. */ + uint32_t n[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + /*! RSA modulus size in bits. */ + uint32_t nSizeInBits; + + /*! Decryption operation mode. */ + CRYS_RSA_DecryptionMode_t OperationMode; + + /*! Key source ( internal or external ). */ + CRYS_RSA_KeySource_t KeySource; + + + /*! Union between the CRT and non-CRT data structures. */ + union + { + CRYSRSAPrivNonCRTKey_t NonCrt; /*!< Non CRT data structure. */ + CRYSRSAPrivCRTKey_t Crt; /*!< CRT data structure. */ + }PriveKeyDb; + + /*! Internal buffer. */ + uint32_t crysRSAPrivKeyIntBuff[CRYS_PKA_PRIV_KEY_BUFF_SIZE_IN_WORDS]; + +}CRYSRSAPrivKey_t; + +/*! The private key's user structure prototype. This structure must be saved by the user, and is used as input to the RSA functions +(such as ::SaSi_RsaSchemesDecrypt etc.). */ +typedef struct CRYS_RSAUserPrivKey_t +{ + /*! Validation tag.*/ + uint32_t valid_tag; + /*! Private key data. */ + uint32_t PrivateKeyDbBuff[ sizeof(CRYSRSAPrivKey_t)/sizeof(uint32_t) + 1 ] ; + +}CRYS_RSAUserPrivKey_t; + +/*! Temporary buffers for RSA usage. */ +typedef struct CRYS_RSAPrimeData_t +{ + /* The aligned input and output data buffers */ + uint32_t DataIn[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; /*!< Temporary buffer for data in.*/ + uint32_t DataOut[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; /*!< Temporary buffer for data out.*/ + /*! Temporary buffer for internal data.*/ + SASI_PAL_COMPILER_ALIGN(4) uint8_t InternalBuff[CRYS_RSA_TMP_BUFF_SIZE]; + +}CRYS_RSAPrimeData_t; + +/*! KG data type. */ +typedef union CRYS_RSAKGData_t +{ + /*! RSA Key Generation buffers definitions. */ + struct + { + /* The aligned input and output data buffers */ + /*! First factor buffer. */ + uint32_t p[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS / 2]; + /*! Second factor buffer. */ + uint32_t q[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS / 2]; + union { + /*! Internal buffer. */ + uint32_t crysRSAKGDataIntBuff[CRYS_PKA_KGDATA_BUFF_SIZE_IN_WORDS]; + #ifdef DX_SOFT_KEYGEN + /* # added for compatibility with size of KGData SW type */ + uint32_t TempbuffExp[PKI_KEY_GEN_TEMP_BUFF_SIZE_WORDS]; + #endif + }kg_buf; + }KGData; + + /*! Buffers for internal usage. */ + union { + /*! Internally used buffer.*/ + struct { + CRYS_RSAPrimeData_t PrimData; + }primExt; + #ifdef DX_SOFT_KEYGEN + /* # added for compatibility with size of SW CRYSRSAPrivKey_t type */ + SW_Shared_CRYS_RSAPrimeData_t SW_Shared_PrimData; + #endif + }prim; +}CRYS_RSAKGData_t; + + /************* + * RSA contexts + **************/ +/************************ CRYS RSA struct for Private Key ******************************/ + +/*! Context definition for operations that use the RSA private key. */ +typedef struct +{ + + /*! Private key data. */ + CRYS_RSAUserPrivKey_t PrivUserKey; + + /*! RSA PKCS#1 Version 1.5 or 2.1 */ + uint8_t PKCS1_Version; + + /*! MGF to be used for the PKCS1 Ver 2.1 sign or verify operations. */ + uint8_t MGF_2use; + + /*! Salt random length for PKCS#1 PSS Ver 2.1*/ + uint16_t SaltLen; + + /*! Internal buffer. */ + CRYS_RSAPrimeData_t PrimeData; + + /*! HASH context buffer. */ + uint32_t CRYSPKAHashCtxBuff[CRYS_PKA_RSA_HASH_CTX_SIZE_IN_WORDS]; + /*! HASH result buffer. */ + CRYS_HASH_Result_t HASH_Result; + /*! HASH result size in words. */ + uint16_t HASH_Result_Size; /*in words*/ + /*! RSA HASH operation mode (all modes RSA supports).*/ + CRYS_RSA_HASH_OpMode_t RsaHashOperationMode; /*RSA HASH enum. */ + /*! HASH operation mode.*/ + CRYS_HASH_OperationMode_t HashOperationMode; /*CRYS HASH enum. */ + /*! HASH block size (in words).*/ + uint16_t HashBlockSize; /*in words*/ + /*! HASH flag. */ + bool doHash; + + /* Used for sensitive data manipulation in the context space, which is safer and which saves stack space */ + /*! Internal buffer.*/ + uint32_t EBD[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Internal bufffer used size in bits. */ + uint32_t EBDSizeInBits; + + /* Used for sensitive data manipulation in the context space, which is safer and which saves stack space */ + /*! Internal buffer.*/ + uint8_t T_Buf[CRYS_RSA_SIZE_OF_T_STRING_BYTES]; + /*! Internal buffer used size.*/ + uint16_t T_BufSize; + + /*! Buffer for the use of the Ber encoder in the case of PKCS#1 Ver 1.5. */ + uint32_t BER[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Ber encoder buffer size.*/ + uint16_t BERSize; + + /*! Internal buffer.*/ + uint8_t DummyBufAESBlockSize[16]; + +}RSAPrivContext_t; + +/*! The user's context prototype - the argument type that is passed by the user + to the RSA APIs. The context saves the state of the operation and must be saved by the user + till the end of the APIs flow . */ +typedef struct CRYS_RSAPrivUserContext_t +{ + /*! Validation tag. */ + uint32_t valid_tag; + /*! Internally used value.*/ + uint32_t AES_iv; + /*! Private data context buffer. */ + SASI_PAL_COMPILER_ALIGN(4) uint8_t context_buff[ sizeof(RSAPrivContext_t) + sizeof(uint32_t)]; /* must be aligned to 4 */ + +}CRYS_RSAPrivUserContext_t; + + +/************************ CRYS RSA struct for Public Key ******************************/ + +/*! Context definition for operations that use the RSA public key. */ +typedef struct +{ + + /*! RSA public key structure. */ + CRYS_RSAUserPubKey_t PubUserKey; + + /*! Public key size in bytes */ + uint32_t nSizeInBytes; + + /*! RSA PKCS#1 Version 1.5 or 2.1 */ + uint8_t PKCS1_Version; + + /*! MGF to be used for the PKCS1 Ver 2.1 Sign or Verify operations */ + uint8_t MGF_2use; + + /*! Salt random length for PKCS#1 PSS Ver 2.1*/ + uint16_t SaltLen; + + /*! Internal buffer. */ + CRYS_RSAPrimeData_t PrimeData; + + /*! HASH context. */ + uint32_t CRYSPKAHashCtxBuff[CRYS_PKA_RSA_HASH_CTX_SIZE_IN_WORDS]; + /*! HASH result buffer. */ + CRYS_HASH_Result_t HASH_Result; + /*! HASH result size. */ + uint16_t HASH_Result_Size; /* denotes the length, in words, of the hash function output */ + /*! RSA HASH operation mode (all modes RSA supports). */ + CRYS_RSA_HASH_OpMode_t RsaHashOperationMode; /*RSA HASH enum. */ + /*! HASH operation mode. */ + CRYS_HASH_OperationMode_t HashOperationMode; /*CRYS HASH enum. */ + /*! HASH block size. */ + uint16_t HashBlockSize; /*in words*/ + /*! HASH flag.*/ + bool doHash; + + /* Used for sensitive data manipulation in the context space, which is safer and which saves stack space */ + /*! Internal buffer.*/ + uint32_t EBD[CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Internal bufffer used size in bits. */ + uint32_t EBDSizeInBits; + + /* Used for sensitive data manipulation in the context space, which is safer and which saves stack space */ + /*! Internal buffer.*/ + uint8_t T_Buf[CRYS_RSA_SIZE_OF_T_STRING_BYTES]; + /*! Internal buffer used size.*/ + uint16_t T_BufSize; + + /*! Internal buffer.*/ + uint8_t DummyBufAESBlockSize[16]; + +}RSAPubContext_t; + +/*! Temporary buffers for the RSA usage. */ +typedef struct CRYS_RSAPubUserContext_t +{ + /*! Validation tag. */ + uint32_t valid_tag; + /*! Internally used value.*/ + uint32_t AES_iv; /* For the use of the AES CBC mode of Encryption and Decryption of the context in CCM */ + /*! Public data context buffer. */ + uint32_t context_buff[ sizeof(RSAPubContext_t)/sizeof(uint32_t) + 1] ; + +}CRYS_RSAPubUserContext_t; + + + +/*! Required for internal FIPS verification for RSA key generation. */ +typedef struct CRYS_RSAKGFipsContext_t{ + /*! Internal buffer. */ + CRYS_RSAPrimeData_t primData; + /*! Buffer used for decryption. */ + uint8_t decBuff[((CRYS_RSA_MIN_VALID_KEY_SIZE_VALUE_IN_BITS/SASI_BITS_IN_BYTE) - 2*(CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES) -2)]; + /*! Buffer used for encryption. */ + uint8_t encBuff[CRYS_RSA_FIPS_MODULUS_SIZE_BITS/SASI_BITS_IN_BYTE]; +}CRYS_RSAKGFipsContext_t; + +/*! Required for internal FIPS verification for RSA KAT. The RSA KAT tests defined for scheme 2.1 with modulus key size of 2048. */ +typedef struct CRYS_RSAFipsKatContext_t{ + /*! RSA user's key (either public or private).*/ + union { + /*! RSA user's public key. */ + CRYS_RSAUserPubKey_t userPubKey; // used for RsaEnc and RsaVerify + /*! RSA user's private key. */ + CRYS_RSAUserPrivKey_t userPrivKey; // used for RsaDec and RsaSign + }userKey; + /*! RSA user's context (either public or private).*/ + union { + /*! RSA user's private context. */ + CRYS_RSAPrivUserContext_t userPrivContext; // used for RsaSign + /*! RSA public user's context. */ + CRYS_RSAPubUserContext_t userPubContext; // used for RsaVerify + /*! Internal buffers. */ + CRYS_RSAPrimeData_t primData; // used for RsaEnc and RsaDec + }userContext; + /*! RSA user's data. */ + union { + struct { // used for RsaEnc and RsaDec + /*! Buffer for encrypted data. */ + uint8_t encBuff[CRYS_RSA_FIPS_MODULUS_SIZE_BITS/SASI_BITS_IN_BYTE]; + /*! Buffer for decrypted data. */ + uint8_t decBuff[((CRYS_RSA_FIPS_MODULUS_SIZE_BITS/SASI_BITS_IN_BYTE) - 2*(CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES) -2)]; + }userOaepData; + /*! Buffer for Signed data. */ + uint8_t signBuff[CRYS_RSA_FIPS_MODULUS_SIZE_BITS/SASI_BITS_IN_BYTE]; // used for RsaSign and RsaVerify + }userData; +}CRYS_RSAFipsKatContext_t; + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/crys_srp.h b/external/nrf_cc310/include/crys_srp.h new file mode 100644 index 0000000..ed23098 --- /dev/null +++ b/external/nrf_cc310/include/crys_srp.h @@ -0,0 +1,375 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains all of the enums and definitions that are used for the + CRYS SRP APIs, as well as the APIs themselves. +@defgroup crys_srp CryptoCell SRP APIs +@{ +@ingroup cryptocell_api + +*/ +#ifndef CRYS_SRP_H +#define CRYS_SRP_H + + +#include "ssi_pal_types.h" +#include "crys_error.h" +#include "crys_pka_defs_hw.h" +#include "crys_hash.h" +#include "crys_rnd.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*!\internal The following describes the SRP APIs usage for the Device and the Accessory :* + + Device (User) Accessory (Host) +* -------------- ----------------- + + 1. CRYS_SRP_HK_INIT(CRYS_SRP_USER, .......) CRYS_SRP_HK_INIT(CRYS_SRP_HOST, .....) + + 2. CRYS_SRP_PwdVerCreate(..) + + 3. CRYS_SRP_UserPubKeyCreate(..) CRYS_SRP_HostPubKeyCreate(..) + + 4. CRYS_SRP_UserProofCalc(..) + + 5. CRYS_SRP_HostProofVerifyAndCalc(..) + + 6. CRYS_SRP_UserProofVerify(..) + + 7. CRYS_SRP_Clear(..) CRYS_SRP_Clear(..) + + */ + +/************************ Defines ******************************/ +/*! The SRP modulus sizes. */ +/*! 1024 bits modulus size. */ +#define CRYS_SRP_MODULUS_SIZE_1024_BITS 1024 +/*! 1536 bits modulus size. */ +#define CRYS_SRP_MODULUS_SIZE_1536_BITS 1536 +/*! 2048 bits modulus size. */ +#define CRYS_SRP_MODULUS_SIZE_2048_BITS 2048 +/*! 3072 bits modulus size. */ +#define CRYS_SRP_MODULUS_SIZE_3072_BITS 3072 + +/*! Maximal modulus size in bits. */ +#define CRYS_SRP_MAX_MODULUS_IN_BITS CRYS_SRP_MODULUS_SIZE_3072_BITS +/*! Maximal modulus size in bytes. */ +#define CRYS_SRP_MAX_MODULUS (CRYS_SRP_MAX_MODULUS_IN_BITS/SASI_BITS_IN_BYTE) +/*! Maximal modulus size in words. */ +#define CRYS_SRP_MAX_MODULUS_IN_WORDS (CRYS_SRP_MAX_MODULUS_IN_BITS/SASI_BITS_IN_32BIT_WORD) + +/*! The SRP private number size range. */ +/*! Minimal private number size in bits. */ +#define CRYS_SRP_PRIV_NUM_MIN_SIZE_IN_BITS (256) +/*! Minimal private number size in bytes. */ +#define CRYS_SRP_PRIV_NUM_MIN_SIZE (CRYS_SRP_PRIV_NUM_MIN_SIZE_IN_BITS/SASI_BITS_IN_BYTE) +/*! Minimal private number size in words. */ +#define CRYS_SRP_PRIV_NUM_MIN_SIZE_IN_WORDS (CRYS_SRP_PRIV_NUM_MIN_SIZE_IN_BITS/SASI_BITS_IN_32BIT_WORD) +/*! Maximal private number size in bits. */ +#define CRYS_SRP_PRIV_NUM_MAX_SIZE_IN_BITS (CRYS_SRP_MAX_MODULUS_IN_BITS) +/*! Maximal private number size in bytes. */ +#define CRYS_SRP_PRIV_NUM_MAX_SIZE (CRYS_SRP_PRIV_NUM_MAX_SIZE_IN_BITS/SASI_BITS_IN_BYTE) +/*! Maximal private number size in words. */ +#define CRYS_SRP_PRIV_NUM_MAX_SIZE_IN_WORDS (CRYS_SRP_PRIV_NUM_MAX_SIZE_IN_BITS/SASI_BITS_IN_32BIT_WORD) + +/*! Maximal SRP HASH digest size in words. */ +#define CRYS_SRP_MAX_DIGEST_IN_WORDS CRYS_HASH_RESULT_SIZE_IN_WORDS +/*! Maximal SRP HASH digest size in bytes. */ +#define CRYS_SRP_MAX_DIGEST (CRYS_SRP_MAX_DIGEST_IN_WORDS*SASI_32BIT_WORD_SIZE) + +/*! Minimal salt size in bytes. */ +#define CRYS_SRP_MIN_SALT_SIZE (8) +/*! Minimal salt size in words. */ +#define CRYS_SRP_MIN_SALT_SIZE_IN_WORDS (CRYS_SRP_MIN_SALT_SIZE/SASI_32BIT_WORD_SIZE) +/*! Maximal salt size in bytes. */ +#define CRYS_SRP_MAX_SALT_SIZE (64) +/*! Maximal salt size in words. */ +#define CRYS_SRP_MAX_SALT_SIZE_IN_WORDS (CRYS_SRP_MAX_SALT_SIZE/SASI_32BIT_WORD_SIZE) + +/************************ Typedefs ****************************/ +/*! SRP modulus buffer definition. */ +typedef uint8_t CRYS_SRP_Modulus_t[CRYS_SRP_MAX_MODULUS]; + +/*! SRP digest buffer definition. */ +typedef uint8_t CRYS_SRP_Digest_t[CRYS_SRP_MAX_DIGEST]; + +/*! SRP secret buffer definition. */ +typedef uint8_t CRYS_SRP_Secret_t[2*CRYS_SRP_MAX_DIGEST]; + +/************************ Enums ********************************/ + +/*! +SRP supported versions +*/ +typedef enum { + CRYS_SRP_VER_3 = 0, /*!< VER 3. */ + CRYS_SRP_VER_6 = 1, /*!< VER 6. */ + CRYS_SRP_VER_6A = 2, /*!< VER 6A. */ + CRYS_SRP_VER_HK = 3, /*!< VER 6A. */ + /*! Maximal number of supported versions.*/ + CRYS_SRP_NumOfVersions, + /*! Reserved.*/ + CRYS_SRP_VersionLast= 0x7FFFFFFF, + +}CRYS_SRP_Version_t; + +/*! +SRP entity type +*/ +typedef enum { + CRYS_SRP_HOST = 1, /*!< Host entity, called also server, verifier, or Accessory in Home-Kit */ + CRYS_SRP_USER = 2, /*!< User entity, called also client, or Device in Home-Kit */ + /*! Maximal number of entities types.*/ + CRYS_SRP_NumOfEntityType, + /*! Reserved.*/ + CRYS_SRP_EntityLast= 0x7FFFFFFF, + +}CRYS_SRP_Entity_t; + +/************************ Structs ******************************/ + +/*! Group parameters for the SRP - defines the modulus and the generator used */ +typedef struct CRYS_SRP_GroupParam_t { + /*! SRP modulus.*/ + CRYS_SRP_Modulus_t modulus; + /*! SRP generator.*/ + uint8_t gen; + /*! SRP modulus size in bits .*/ + size_t modSizeInBits; + /*! SRP valid Np.*/ + uint32_t validNp; + /*! SRP Np buffer.*/ + uint32_t Np[CRYS_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS]; +}CRYS_SRP_GroupParam_t; + +/************************ context Structs ******************************/ +/*! The SRP context prototype */ +typedef struct CRYS_SRP_Context_t { + /*! SRP entitiy type.*/ + CRYS_SRP_Entity_t srpType; + /*! SRP version.*/ + CRYS_SRP_Version_t srpVer; + /*! Group parameter including the modulus information.*/ + CRYS_SRP_GroupParam_t groupParam; // N, g, Np + /*! Hash mode.*/ + CRYS_HASH_OperationMode_t hashMode; + /*! Hash digest size.*/ + size_t hashDigestSize; + /*! Pointer to RND state.*/ + CRYS_RND_State_t *pRndState; + /*! Pointer to random vector generation function.*/ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc; + /*! Modulus.*/ + CRYS_SRP_Modulus_t ephemPriv; // a or b + /*! Modulus size.*/ + size_t ephemPrivSize; + /*! User name digest.*/ + CRYS_SRP_Digest_t userNameDigest; // M + /*! Cred digest.*/ + CRYS_SRP_Digest_t credDigest; // p + /*! SRP K multiplier. */ // + CRYS_SRP_Digest_t kMult; // k multiplier +}CRYS_SRP_Context_t; + + +/************************ SRP common Functions **********************/ +/****************************************************************************************************/ +/*! +@brief This function initiates the SRP context. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_srp_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_SRP_Init( + CRYS_SRP_Entity_t srpType, /*!< [in] SRP entity type. */ + CRYS_SRP_Version_t srpVer, /*!< [in] SRP version. */ + CRYS_SRP_Modulus_t srpModulus, /*!< [in] A pointer to the SRP modulus, BE byte buffer. */ + uint8_t srpGen, /*!< [in] The SRP generator param. */ + size_t modSizeInBits, /*!< [in] The SRP modulus size in bits:1024, 1536, 2048 & 3072 */ + CRYS_HASH_OperationMode_t hashMode, /*!< [in] Enumerator defining the HASH mode. */ + uint8_t *pUserName, /*!< [in] A Pointer to user name. */ + size_t userNameSize, /*!< [in] The user name buffer size > 0. */ + uint8_t *pPwd, /*!< [in] A Pointer to user password. */ + size_t pwdSize, /*!< [in] The user password buffer size > 0 if pPwd is valid. */ + void *pRndState, /*!< [in] A Pointer to RND context.*/ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to random vector generation function.*/ + CRYS_SRP_Context_t *pCtx /*!< [out] A Pointer to the SRP host context.*/ +); + +/*! MACRO definition for a specific SRP initialization function.*/ +#define CRYS_SRP_HK_INIT(srpType, srpModulus, srpGen, modSizeInBits, pUserName, userNameSize, pPwd, pwdSize, pRndState, rndGenerateVectFunc, pCtx) \ + CRYS_SRP_Init(srpType, CRYS_SRP_VER_HK, srpModulus, srpGen, modSizeInBits, CRYS_HASH_SHA512_mode, pUserName, userNameSize, pPwd, pwdSize, pRndState, rndGenerateVectFunc, pCtx) + + +/****************************************************************************************************/ +/*! +@brief This function calculates pSalt & password verifier + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_srp_error.h, crys_rnd_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_SRP_PwdVerCreate( + size_t saltSize, /*!< [in] The size of the random salt to generate, + The range is between CRYS_SRP_MIN_SALT_SIZE + to CRYS_SRP_MAX_SALT_SIZE. */ + uint8_t *pSalt, /*!< [out] A Pointer to the pSalt number (s).*/ + CRYS_SRP_Modulus_t pwdVerifier, /*!< [out] A Pointer to the password verifier (v). */ + CRYS_SRP_Context_t *pCtx /*!< [out] A Pointer to the SRP context.*/ +); + + +/****************************************************************************************************/ +/*! +@brief Clears the SRP context. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_srp_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_SRP_Clear( + CRYS_SRP_Context_t *pCtx /*!< [in/out] A Pointer to the SRP context.*/ +); + + +/************************ SRP Host Functions **********************/ +/****************************************************************************************************/ +/*! +@brief This function generates host public & private ephemeral key, known as B & b in RFC + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_srp_error.h or crys_rnd_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_SRP_HostPubKeyCreate( + size_t ephemPrivSize, /*!< [in] The size of the generated ephemeral private key (b). + The range is between CRYS_SRP_PRIV_NUM_MIN_SIZE to + CRYS_SRP_PRIV_NUM_MAX_SIZE */ + CRYS_SRP_Modulus_t pwdVerifier, /*!< [in] A Pointer to the verifier (v). */ + CRYS_SRP_Modulus_t hostPubKeyB, /*!< [out] A Pointer to the host ephemeral public key (B). */ + CRYS_SRP_Context_t *pCtx /*!< [in/out] A Pointer to the SRP context.*/ +); + + +/*! +@brief Verifies the user Proof and calculates the Host message proof. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_srp_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_SRP_HostProofVerifyAndCalc( + size_t saltSize, /*!< [in] The size of the random salt, + The range is between CRYS_SRP_MIN_SALT_SIZE + to CRYS_SRP_MAX_SALT_SIZE. */ + uint8_t *pSalt, /*!< [in] A Pointer to the pSalt number.*/ + CRYS_SRP_Modulus_t pwdVerifier, /*!< [in] A Pointer to the password verifier (v). */ + CRYS_SRP_Modulus_t userPubKeyA, /*!< [in] A Pointer to the user ephemeral public key (A). */ + CRYS_SRP_Modulus_t hostPubKeyB, /*!< [in] A Pointer to the host ephemeral public key (B). */ + CRYS_SRP_Digest_t userProof, /*!< [in] A Pointer to the SRP user proof buffer (M1).*/ + CRYS_SRP_Digest_t hostProof, /*!< [out] A Pointer to the SRP host proof buffer (M2).*/ + CRYS_SRP_Secret_t sharedSecret, /*!< [out] A Pointer to the SRP shared secret (K).*/ + CRYS_SRP_Context_t *pCtx /*!< [in] A Pointer to the SRP context.*/ +); + + + +/************************ SRP User Functions **********************/ +/****************************************************************************************************/ +/*! +@brief This function generates user public & private ephemeral key, known as A & a in RFC + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_srp_error.h or crys_rnd_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_SRP_UserPubKeyCreate( + size_t ephemPrivSize, /*!< [in] The size of the generated ephemeral private key (a). + The range is between CRYS_SRP_PRIV_NUM_MIN_SIZE to + CRYS_SRP_PRIV_NUM_MAX_SIZE */ + CRYS_SRP_Modulus_t userPubKeyA, /*!< [out] A Pointer to the user ephemeral public key (A). */ + CRYS_SRP_Context_t *pCtx /*!< [in/out] A Pointer to the SRP context.*/ +); + + +/****************************************************************************************************/ +/*! +@brief This function calculates the user proof. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_srp_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_SRP_UserProofCalc( + size_t saltSize, /*!< [in] The size of the random salt, + The range is between CRYS_SRP_MIN_SALT_SIZE + to CRYS_SRP_MAX_SALT_SIZE. */ + uint8_t *pSalt, /*!< [in] A Pointer to the pSalt number.*/ + CRYS_SRP_Modulus_t userPubKeyA, /*!< [in] A Pointer to the user public ephmeral key (A).*/ + CRYS_SRP_Modulus_t hostPubKeyB, /*!< [in] A Pointer to the host public ephmeral key (B).*/ + CRYS_SRP_Digest_t userProof, /*!< [out] A Pointer to the SRP user proof buffer (M1).*/ + CRYS_SRP_Secret_t sharedSecret, /*!< [out] A Pointer to the SRP shared secret (K).*/ + CRYS_SRP_Context_t *pCtx /*!< [out] A Pointer to the SRP context.*/ +); + +/****************************************************************************************************/ +/*! +@brief This function verifies the host proof + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_srp_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_SRP_UserProofVerify( + CRYS_SRP_Secret_t sharedSecret, /*!< [in] A Pointer to the SRP shared secret (K).*/ + CRYS_SRP_Modulus_t userPubKeyA, /*!< [in] A Pointer to the user public ephmeral key (A).*/ + CRYS_SRP_Digest_t userProof, /*!< [in] A Pointer to the SRP user proof buffer (M1).*/ + CRYS_SRP_Digest_t hostProof, /*!< [in] A Pointer to the SRP host proof buffer (M2).*/ + CRYS_SRP_Context_t *pCtx /*!< [out] A Pointer to the SRP user context.*/ +); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /* #ifndef CRYS_SRP_H */ + + + + + diff --git a/external/nrf_cc310/include/crys_srp_error.h b/external/nrf_cc310/include/crys_srp_error.h new file mode 100644 index 0000000..085b03b --- /dev/null +++ b/external/nrf_cc310/include/crys_srp_error.h @@ -0,0 +1,91 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_SRP_ERROR_H +#define CRYS_SRP_ERROR_H + + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the CRYS SRP errors. +@defgroup crys_srp_error CryptoCell SRP specific errors +@{ +@ingroup crys_srp +*/ + + + +/************************ Defines ******************************/ + +/*! The CRYS SRP module errors base address - 0x00F02600. */ +/*! Illegal parameter. */ +#define CRYS_SRP_PARAM_INVALID_ERROR (CRYS_SRP_MODULE_ERROR_BASE + 0x01UL) +/*! Illegal modulus size . */ +#define CRYS_SRP_MOD_SIZE_INVALID_ERROR (CRYS_SRP_MODULE_ERROR_BASE + 0x02UL) +/*! Illegal state (uninitialized) . */ +#define CRYS_SRP_STATE_UNINITIALIZED_ERROR (CRYS_SRP_MODULE_ERROR_BASE + 0x03UL) +/*! Result validation error. */ +#define CRYS_SRP_RESULT_ERROR (CRYS_SRP_MODULE_ERROR_BASE + 0x04UL) +/*! Invalid parameter. */ +#define CRYS_SRP_PARAM_ERROR (CRYS_SRP_MODULE_ERROR_BASE + 0x05UL) +/*! Internal PKI error */ +#define CRYS_SRP_PKI_INTERNAL_ERROR (CRYS_SRP_MODULE_ERROR_BASE + 0x06UL) + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs *****************************/ + +/************************ Public Variables *********************/ + +/************************ Public Functions *********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/dx_reg_base_host.h b/external/nrf_cc310/include/dx_reg_base_host.h new file mode 100644 index 0000000..8c60ff3 --- /dev/null +++ b/external/nrf_cc310/include/dx_reg_base_host.h @@ -0,0 +1,60 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + +#ifndef __DX_REG_BASE_HOST_H__ +#define __DX_REG_BASE_HOST_H__ + +/* Identify platform: Xilinx Zynq7000 ZC706 */ +#define DX_PLAT_ZYNQ7000 1 +#define DX_PLAT_ZYNQ7000_ZC706 1 + +/* SEP core clock frequency in MHz */ +#define DX_SEP_FREQ_MHZ 64 +#if defined(CRYPTOCELL_ARCH_BASE_ADDRESS) +#define DX_BASE_CC CRYPTOCELL_ARCH_BASE_ADDRESS +#else +#error Please set CRYPTOCELL_ARCH_BASE_ADDRESS to a non-negative number +#endif + +#define DX_BASE_ENV_REGS 0x40008000 +#define DX_BASE_ENV_CC_MEMORIES 0x40008000 +#define DX_BASE_ENV_FLASH 0x40008700 +#define DX_BASE_ENV_PERF_RAM 0x40009000 + +#define DX_BASE_HOST_RGF 0x0UL +#define DX_BASE_CRY_KERNEL 0x0UL +#define DX_BASE_ROM 0x40000000 + +#define DX_BASE_RNG 0x0000UL +#endif /*__DX_REG_BASE_HOST_H__*/ diff --git a/external/nrf_cc310/include/sns_silib.h b/external/nrf_cc310/include/sns_silib.h new file mode 100644 index 0000000..5760501 --- /dev/null +++ b/external/nrf_cc310/include/sns_silib.h @@ -0,0 +1,101 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains all of the enums and definitions that are used for the + CryptoCell Lib init and finish APIs, as well as the APIs themselves. +@defgroup sns_silib CryptoCell library basic APIs +@{ +@ingroup cryptocell_api + +*/ + +#ifndef __SNS_SILIB_H__ +#define __SNS_SILIB_H__ + +#include "ssi_pal_types.h" +#include "crys_rnd.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! Definitions for error returns from SaSi_LibInit or SaSi_LibFini functions. */ +typedef enum { + SA_SILIB_RET_OK = 0, /*!< Success defintion.*/ + SA_SILIB_RET_EINVAL_CTX_PTR, /*!< Illegal context pointer.*/ + SA_SILIB_RET_EINVAL_WORK_BUF_PTR, /*!< Illegal work buffer pointer.*/ + SA_SILIB_RET_HAL, /*!< Error returned from HAL layer.*/ + SA_SILIB_RET_PAL, /*!< Error returned from PAL layer.*/ + SA_SILIB_RET_EINVAL_HW_VERSION, /*!< Invalid HW version. */ + SA_SILIB_RET_EINVAL_HW_SIGNATURE, /*!< Invalid HW signature. */ + SA_SILIB_RESERVE32B = 0x7FFFFFFFL /*!< Reserved.*/ +} SA_SilibRetCode_t; + + +/*! Internal defintion for the product register. */ +#define DX_VERSION_PRODUCT_BIT_SHIFT 0x18UL +/*! Internal defintion for the product register size. */ +#define DX_VERSION_PRODUCT_BIT_SIZE 0x8UL + + + +/*! +@brief This function Perform global initialization of the ARM CryptoCell 3xx runtime library; +it must be called once per ARM CryptoCell for 3xx cold boot cycle. + +\note The Mutexes, if used, are initialized by this API. Therefore, unlike the other APIs in the library, +this API is not thread-safe. +@return SA_SILIB_RET_OK on success. +@return A non-zero value in case of failure. +*/ +SA_SilibRetCode_t SaSi_LibInit(void); + +/*! +@brief This function finalize the library operations. It frees the associated resources (mutexes) and call hal and pal terminate functions. +in case of active instansiation - one must call CRYS_RND_UnInstantiation to clean the rnd state. +*/ +void SaSi_LibFini(void); + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /*__DX_CCLIB_H__*/ + diff --git a/external/nrf_cc310/include/ssi_aes.h b/external/nrf_cc310/include/ssi_aes.h new file mode 100644 index 0000000..a42b65f --- /dev/null +++ b/external/nrf_cc310/include/ssi_aes.h @@ -0,0 +1,325 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! @file +@brief This file contains all of the enums and definitions that are used for the +CryptoCell AES APIs, as well as the APIs themselves. +@defgroup ssi_aes CryptoCell AES APIs +@{ +@ingroup cryptocell_api +*/ + +#ifndef SSI_AES_H +#define SSI_AES_H + +#include "ssi_pal_types.h" +#include "ssi_aes_error.h" +#include "ssi_aes_defs.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************ Defines ******************************/ + + +/************************ Enums ********************************/ + +/*! +Encrypt or Decrypt operation mode. +*/ +typedef enum { + /*! Encrypt operation. */ + SASI_AES_ENCRYPT = 0, + /*! Decrypt operation. */ + SASI_AES_DECRYPT = 1, + /*! Maximal number of operations. */ + SASI_AES_NUM_OF_ENCRYPT_MODES, + /*! Reserved. */ + SASI_AES_ENCRYPT_MODE_LAST = 0x7FFFFFFF +}SaSiAesEncryptMode_t; + +/*! +AES operation mode. +*/ +typedef enum { + SASI_AES_MODE_ECB = 0, /*!< ECB mode. */ + SASI_AES_MODE_CBC = 1, /*!< CBC mode. */ + SASI_AES_MODE_CBC_MAC = 2, /*!< CBC-MAC mode. */ + SASI_AES_MODE_CTR = 3, /*!< CTR mode. */ + SASI_AES_MODE_XCBC_MAC = 4, /*!< XCBC-MAC mode. */ + SASI_AES_MODE_CMAC = 5, /*!< CMAC mode. */ + SASI_AES_MODE_XTS = 6, /*!< XTS mode. */ + SASI_AES_MODE_CBC_CTS = 7, /*!< CBC-CTS mode. */ + SASI_AES_MODE_OFB = 8, /*!< OFB mode. */ + + /*! Maximal number of AES modes */ + SASI_AES_NUM_OF_OPERATION_MODES, + /*! Reserved. */ + SASI_AES_OPERATION_MODE_LAST = 0x7FFFFFFF +}SaSiAesOperationMode_t; + +/*! +AES padding type. +*/ +typedef enum { + SASI_AES_PADDING_NONE = 0, /*!< No padding. */ + SASI_AES_PADDING_PKCS7 = 1, /*!< PKCS7 padding. */ + + /*! Maximal number of AES padding modes */ + SASI_AES_NUM_OF_PADDING_TYPES, + /*! Reserved. */ + SASI_AES_PADDING_TYPE_LAST = 0x7FFFFFFF +}SaSiAesPaddingType_t; + +/*! +AES key type. +*/ +typedef enum { + SASI_AES_USER_KEY = 0, /*!< user key. */ + SASI_AES_PLATFORM_KEY = 1, /*!< Kplt hardware key. */ + SASI_AES_CUSTOMER_KEY = 2, /*!< Kcst hardware key. */ + + /*! Maximal number of AES key types */ + SASI_AES_NUM_OF_KEY_TYPES, + /*! Reserved. */ + SASI_AES_KEY_TYPE_LAST = 0x7FFFFFFF +}SaSiAesKeyType_t; + +/************************ Typedefs ****************************/ + +/*! Defines the IV buffer - 16 bytes array. */ +typedef uint8_t SaSiAesIv_t[SASI_AES_IV_SIZE_IN_BYTES]; + +/*! Defines the AES key data buffer. */ +typedef uint8_t SaSiAesKeyBuffer_t[SASI_AES_KEY_MAX_SIZE_IN_BYTES]; + +/************************ Structs ******************************/ + +/*! The user's context prototype - the argument type that is passed by the user + to the AES APIs. The context saves the state of the operation and must be saved by the user + till the end of the APIs flow*/ +typedef struct SaSiAesUserContext_t { + /*! Context buffer for internal usage. */ + uint32_t buff[SASI_AES_USER_CTX_SIZE_IN_WORDS]; +}SaSiAesUserContext_t; + + +/*! AES User Key Data. */ +typedef struct SaSiAesUserKeyData_t { + uint8_t * pKey; /*!< Pointer to the key. */ + size_t keySize; /*!< The key size in bytes. Valid values: +
    • For XTS mode - 32 or 64 byte, indicating the full size of the double key (2x128 or 2x256 bit).
    • +
    • For XCBC-MAC mode - 16 byte (limited by the standard).
    • +
    • For all other modes - 16, 24 or 32 byte.
    */ +}SaSiAesUserKeyData_t; + +/*! AES HW Key Data - this structure is likely to be changed when we'll start using it. */ +typedef struct SaSiAesHwKeyData_t { + size_t slotNumber; /*!< Slot number. */ +}SaSiAesHwKeyData_t; + + +/************************ Functions *****************************/ + +/*! +@brief This function is used to initialize an AES operation context. + To operate the AES machine, this must be the first API called. + +@return SASI_OK on success, +@return A non-zero value from ssi_aes_error.h on failure. +*/ +CIMPORT_C SaSiError_t SaSi_AesInit( + SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context buffer that is allocated by the caller and initialized by this API. + Should be used in all subsequent calls that are part of the same operation. */ + SaSiAesEncryptMode_t encryptDecryptFlag, /*!< [in] A flag specifying whether an AES Encrypt (SASI_AES_Encrypt) or Decrypt (SASI_AES_Decrypt) operation should be performed. + Must be set to CRYS_AES_Encrypt in CBC-MAC, XCBC-MAC and CMAC modes. */ + SaSiAesOperationMode_t operationMode, /*!< [in] The operation cipher/mode. */ + SaSiAesPaddingType_t paddingType /*!< [in] The padding type for AES operation: +
    • NONE - supported for all operation modes.
    • +
    • PKCS7 - supported for ECB, CBC, CBC-MAC operation modes.
    */ +); + + +/*! +@brief This function sets the key information for the AES operation, in the context that was initialized by SaSi_AesInit. +\note When FIPS certification mode is set to ON, and the mode is AES-XTS, weak keys are not allowed (128/256 lsb bits must be +different than 128/256 msb bits, according to the key size). +@return SASI_OK on success, +@return A non-zero value from ssi_aes_error.h on failure. +*/ +CIMPORT_C SaSiError_t SaSi_AesSetKey( + SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context, after it was initialized by SaSi_AesInit. */ + SaSiAesKeyType_t keyType, /*!< [in] The type of key to be used for the AES operation. + Currently only SASI_AES_USER_KEY is supported - the key is plaintext and provided in the pKeyData parameter. */ + void * pKeyData, /*!< [in] Pointer to the key data structure (to be casted to the relevant struct type). */ + size_t keyDataSize /*!< [in] The size of data passed in pKeyData in bytes. */ +); + + +/*! +@brief This function sets the IV, counter or tweak data for the following AES operation on the same context. + The context must be first initialized by SaSi_AesInit. + It must be called at least once prior to the first SaSi_AesBlock operation on the same context - for those ciphers that require it. + If needed, it can also be called to override the IV in the middle of a sequence of SaSi_AesBlock operations. + +@return SASI_OK on success, +@return A non-zero value from ssi_aes_error.h on failure. +*/ +CIMPORT_C SaSiError_t SaSi_AesSetIv( + SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context. */ + SaSiAesIv_t pIV /*!< [in] Pointer to the buffer of the IV, counter or tweak. +
    • For CBC, CBC-CTS, OFB and CBC-MAC modes - the IV value.
    • +
    • For CTR mode - the counter.
    • +
    • For XTS mode - the tweak value.
    • +
    • For all other modes - N/A.
    */ +); + + +/*! +@brief This function retrieves the current IV, counter or tweak from the AES context. + +@return SASI_OK on success, +@return A non-zero value from ssi_aes_error.h on failure. +*/ +CIMPORT_C SaSiError_t SaSi_AesGetIv( + SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context. */ + SaSiAesIv_t pIV /*!< [out] Pointer to the buffer of the IV, counter or tweak. +
    • For CBC, CBC-CTS, OFB and CBC-MAC modes - the IV value.
    • +
    • For CTR mode - the counter.
    • +
    • For XTS mode - the tweak value.
    • +
    • For all other modes - N/A.
    */ +); + + +/*! +@brief This function performs an AES operation on an input data buffer, according to the configuration defined in the context parameter. + It can be called as many times as needed, until all the input data is processed. + SaSi_AesInit, SaSi_AesSetKey, and for some ciphers SaSi_AesSetIv, must be called before + the first call to this API with the same context. + +@return SASI_OK on success, +@return A non-zero value from ssi_aes_error.h on failure. +*/ +CIMPORT_C SaSiError_t SaSi_AesBlock( + SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context. */ + uint8_t * pDataIn, /*!< [in] Pointer to the buffer of the input data to the AES. The pointer does not need to be aligned. + For TZ, the size of the scatter/gather list representing the data buffer is limited to 128 entries, + and the size of each entry is limited to 64KB (fragments larger than 64KB are broken into fragments <= 64KB). + For ARM CryptoCell 3xx, The buffer must be contiguous and limited to 64KB. */ + size_t dataInSize, /*!< [in] Size of the input data in bytes. +
    • For all modes except XTS, must be multiple of 16 bytes.
    • +
    • For XTS mode, only the following data sizes are supported: 64, 512, 520, 521, 1024 and 4096 bytes. + The data passed in a single SaSi_AesBlock call is considered to be a single XTS unit. + All subsequent calls to this API with the same context must use the same data size.
    */ + uint8_t * pDataOut /*!< [out] Pointer to the output buffer. The pointer does not need to be aligned. + For CBC-MAC, XCBC-MAC, CMAC modes it may be NULL. + For TZ, the size of the scatter/gather list representing the data buffer is limited to 128 entries, + and the size of each entry is limited to 64KB (fragments larger than 64KB are broken into fragments <= 64KB). + For ARM CryptoCell 3xx, The buffer must be contiguous and limited to 64KB. */ +); + + +/*! +@brief This function is used to finish AES operation. + + It processes the last data block if needed, finalizes the AES operation (cipher-specific), + and produces operation results (for MAC operations). + \note In case AES padding is used (PKCS#7) Din and Dout user's buffers must include extra space for + the padding scheme. + +@return SASI_OK on success, +@return A non-zero value from ssi_aes_error.h on failure. +*/ +CIMPORT_C SaSiError_t SaSi_AesFinish( + SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context. */ + size_t dataSize, /*!< [in] The size of the input data in bytes. +
    • For CBC-CTS mode, must be > 16. Can be <=16 only if this is the only data (no previous calls were + made to SaSi_AesBlock with the same context).
    • +
    • For XTS mode, the data size must conform to the dataInSize rules as listed for XTS under the + SaSi_AesBlock API, and match the data size passed in the previous calls to SaSi_AesBlock with the + same context.
    • +
    • For all other modes, zero is a valid size.
    • +
    • For ECB, CBC, CBC-MAC modes:
    • +
      • Must be >= 0, if direction is SASI_AES_ENCRYPT and padding type is SASI_AES_PADDING_PKCS7.
      • +
      • Must be >= 16 and a multiple of 16 bytes, if direction is SASI_AES_DECRYPT and padding type + is SASI_AES_PADDING_PKCS7.
      • +
      • Must be a multiple of 16 bytes, otherwise.
    */ + uint8_t * pDataIn, /*!< [in] Pointer of the input data buffer. + For TZ, the size of the scatter/gather list representing the data buffer is limited to 128 entries, + and the size of each entry is limited to 64KB (fragments larger than 64KB are broken into fragments <= 64KB). + For ARM CryptoCell 3xx, The buffer must be contiguous and limited to 64KB. */ + size_t dataInBuffSize, /*!< [in] Size of pDataIn buffer in bytes. +
    • Must be >= dataSize.
    • +
    • According to padding type, must be >= dataSize + padding. For PKCS7, padding size is + maximum SASI_AES_BLOCK_SIZE_IN_BYTES.
    */ + uint8_t * pDataOut, /*!< [out] Pointer to the output buffer. + For TZ, the size of the scatter/gather list representing the data buffer is limited to 128 entries, + and the size of each entry is limited to 64KB (fragments larger than 64KB are broken into fragments <= 64KB). + For ARM CryptoCell 3xx, The buffer must be contiguous and limited to 64KB. */ + size_t * dataOutBuffSize /*!< [in,out] In - Size of pDataOut buffer in bytes. + The output buffer size must be no less than: +
    • For CBC-MAC, XCBC-MAC, CMAC modes - 16 bytes (for MAC result).
    • +
    • For non-MAC modes - dataInBuffSize.
    + Out - The size in bytes of the actual output data: +
    • If direction is SASI_AES_ENCRYPT and padding type is SASI_AES_PADDING_PKCS7, it is the actual size + with the padding.
    • +
    • If direction is SASI_AES_DECRYPT and padding type is SASI_AES_PADDING_PKCS7, it is the size without + the padding.
    • +
    • For CBC-MAC, XCBC-MAC, CMAC modes - always 16 bytes.
    */ +); + + +/*! +@brief This function releases and crears resources after AES operations. + +@return SASI_OK on success, +@return A non-zero value from ssi_aes_error.h on failure. +*/ +CIMPORT_C SaSiError_t SaSi_AesFree( + SaSiAesUserContext_t * pContext /*!< [in] Pointer to the AES context. */ +); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /* #ifndef SSI_AES_H */ + diff --git a/external/nrf_cc310/include/ssi_aes_defs.h b/external/nrf_cc310/include/ssi_aes_defs.h new file mode 100644 index 0000000..02789d0 --- /dev/null +++ b/external/nrf_cc310/include/ssi_aes_defs.h @@ -0,0 +1,83 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains definitions that are used for the ARM CryptoCell 3xx version of the CryptoCell AES APIs. +@defgroup ssi_aes_defs CryptoCell AES definitions +@{ +@ingroup ssi_aes + +*/ + +#ifndef SSI_AES_DEFS_H +#define SSI_AES_DEFS_H + +#include "ssi_pal_types.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************ Defines ******************************/ + +/*! The size of the user's context prototype (see ::SaSiAesUserContext_t) in words. */ +#define SASI_AES_USER_CTX_SIZE_IN_WORDS (4+4+7+4) + +/*! The AES block size in words. */ +#define SASI_AES_BLOCK_SIZE_IN_WORDS 4 +/*! The AES block size in bytes. */ +#define SASI_AES_BLOCK_SIZE_IN_BYTES (SASI_AES_BLOCK_SIZE_IN_WORDS * sizeof(uint32_t)) + +/*! The size of the IV buffer in words. */ +#define SASI_AES_IV_SIZE_IN_WORDS SASI_AES_BLOCK_SIZE_IN_WORDS +/*! The size of the IV buffer in bytes. */ +#define SASI_AES_IV_SIZE_IN_BYTES (SASI_AES_IV_SIZE_IN_WORDS * sizeof(uint32_t)) + +/*! The maximum size of the AES KEY in words. */ +#define SASI_AES_KEY_MAX_SIZE_IN_WORDS 4 +/*! The maximum size of the AES KEY in bytes. */ +#define SASI_AES_KEY_MAX_SIZE_IN_BYTES (SASI_AES_KEY_MAX_SIZE_IN_WORDS * sizeof(uint32_t)) + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /* #ifndef SSI_AES_DEFS_H */ diff --git a/external/nrf_cc310/include/ssi_aes_error.h b/external/nrf_cc310/include/ssi_aes_error.h new file mode 100644 index 0000000..11c6927 --- /dev/null +++ b/external/nrf_cc310/include/ssi_aes_error.h @@ -0,0 +1,133 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains the definitions of the CryptoCell AES errors. +@defgroup ssi_aes_error CryptoCell AES specific errors +@{ +@ingroup ssi_aes +*/ + +#ifndef SSI_AES_ERROR_H +#define SSI_AES_ERROR_H + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************ Defines ******************************/ + +/* generic errors */ +/*! General fatal error. */ +#define SASI_FATAL_ERROR CRYS_FATAL_ERROR +/*! General out of resources error. */ +#define SASI_OUT_OF_RESOURCE_ERROR CRYS_OUT_OF_RESOURCE_ERROR +/*! General Illegal resource value error. */ +#define SASI_ILLEGAL_RESOURCE_VAL_ERROR CRYS_ILLEGAL_RESOURCE_VAL_ERROR + +/*! CRYS_AES_MODULE_ERROR_BASE - 0x00F00000. */ +/*! Illegal user context. */ +#define SASI_AES_INVALID_USER_CONTEXT_POINTER_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x00UL) +/*! Illegal IV or tweak pointer. */ +#define SASI_AES_INVALID_IV_OR_TWEAK_PTR_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x01UL) +/*! Illegal operation. */ +#define SASI_AES_ILLEGAL_OPERATION_MODE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x02UL) +/*! Illegal key size. */ +#define SASI_AES_ILLEGAL_KEY_SIZE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x03UL) +/*! Illegal key pointer. */ +#define SASI_AES_INVALID_KEY_POINTER_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x04UL) +/*! Unsupported key type. */ +#define SASI_AES_KEY_TYPE_NOT_SUPPORTED_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x05UL) +/*! Illegal operation. */ +#define SASI_AES_INVALID_ENCRYPT_MODE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x06UL) +/*! User context corrupted. */ +#define SASI_AES_USER_CONTEXT_CORRUPTED_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x07UL) +/*! Illegal data in pointer. */ +#define SASI_AES_DATA_IN_POINTER_INVALID_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x08UL) +/*! Illegal data out pointer. */ +#define SASI_AES_DATA_OUT_POINTER_INVALID_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x09UL) +/*! Illegal data in size. */ +#define SASI_AES_DATA_IN_SIZE_ILLEGAL (CRYS_AES_MODULE_ERROR_BASE + 0x0AUL) +/*! Illegal data out address. */ +#define SASI_AES_DATA_OUT_DATA_IN_OVERLAP_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0BUL) +/*! Illegal data in buffer size. */ +#define SASI_AES_DATA_IN_BUFFER_SIZE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0CUL) +/*! Illegal data out buffer size. */ +#define SASI_AES_DATA_OUT_BUFFER_SIZE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0DUL) +/*! Illegal padding type. */ +#define SASI_AES_ILLEGAL_PADDING_TYPE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0EUL) +/*! Incorrect padding. */ +#define SASI_AES_INCORRECT_PADDING_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0FUL) +/*! Output is corrupted. */ +#define SASI_AES_CORRUPTED_OUTPUT_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x10UL) +/*! Illegal output size. */ +#define SASI_AES_DATA_OUT_SIZE_POINTER_INVALID_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x11UL) +/*! Decryption operation is not permitted in this mode. */ +#define SASI_AES_DECRYPTION_NOT_ALLOWED_ON_THIS_MODE (CRYS_AES_MODULE_ERROR_BASE + 0x12UL) +/*! Additional block operation is not permitted. */ +#define SASI_AES_ADDITIONAL_BLOCK_NOT_PERMITTED_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x15UL) +/*! Illegal context size. */ +#define SASI_AES_CTX_SIZES_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x16UL) + +/*! Illegal parameters. */ +#define SASI_AES_ILLEGAL_PARAMS_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x60UL) +/*! Illegal CTR block offset. */ +#define SASI_AES_CTR_ILLEGAL_BLOCK_OFFSET_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x70UL) +/*! Illegal counter (in CTR mode). */ +#define SASI_AES_CTR_ILLEGAL_COUNTER_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x71UL) +/*! AES is not supported. */ +#define SASI_AES_IS_NOT_SUPPORTED (CRYS_AES_MODULE_ERROR_BASE + 0xFFUL) + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs *****************************/ + +/************************ Public Variables *********************/ + +/************************ Public Functions *********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /* #ifndef SSI_AES_ERROR_H */ diff --git a/external/nrf_cc310/include/ssi_bitops.h b/external/nrf_cc310/include/ssi_bitops.h new file mode 100644 index 0000000..56c85ee --- /dev/null +++ b/external/nrf_cc310/include/ssi_bitops.h @@ -0,0 +1,81 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! + * \file ssi_bitops.h + * Bit fields operations macros. + */ +#ifndef _SSI_BITOPS_H_ +#define _SSI_BITOPS_H_ + +#define BITMASK(mask_size) (((mask_size) < 32) ? \ + ((1UL << (mask_size)) - 1) : 0xFFFFFFFFUL) +#define BITMASK_AT(mask_size, mask_offset) (BITMASK(mask_size) << (mask_offset)) + +#define BITFIELD_GET(word, bit_offset, bit_size) \ + (((word) >> (bit_offset)) & BITMASK(bit_size)) +#define BITFIELD_SET(word, bit_offset, bit_size, new_val) do { \ + word = ((word) & ~BITMASK_AT(bit_size, bit_offset)) | \ + (((new_val) & BITMASK(bit_size)) << (bit_offset)); \ +} while (0) + +/* Is val aligned to "align" ("align" must be power of 2) */ +#ifndef IS_ALIGNED +#define IS_ALIGNED(val, align) \ + (((uint32_t)(val) & ((align) - 1)) == 0) +#endif + +#define SWAP_ENDIAN(word) \ + (((word) >> 24) | (((word) & 0x00FF0000) >> 8) | \ + (((word) & 0x0000FF00) << 8) | (((word) & 0x000000FF) << 24)) + +#ifdef BIG__ENDIAN +#define SWAP_TO_LE(word) SWAP_ENDIAN(word) +#define SWAP_TO_BE(word) word +#else +#define SWAP_TO_LE(word) word +#define SWAP_TO_BE(word) SWAP_ENDIAN(word) +#endif + + + +/* Is val a multiple of "mult" ("mult" must be power of 2) */ +#define IS_MULT(val, mult) \ + (((val) & ((mult) - 1)) == 0) + +#define IS_NULL_ADDR(adr) \ + (!(adr)) + +#endif /*_SSI_BITOPS_H_*/ diff --git a/external/nrf_cc310/include/ssi_pal_abort.h b/external/nrf_cc310/include/ssi_pal_abort.h new file mode 100644 index 0000000..8d7035b --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_abort.h @@ -0,0 +1,80 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef _SSI_PAL_ABORT_H +#define _SSI_PAL_ABORT_H + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/*! +@defgroup ssi_pal CryptoCell PAL APIs +@{ +@ingroup cryptocell_api +@brief This group is the PAL root group +@} + +@file +@brief This file contains definitions for PAL Abort API. +@defgroup ssi_pal_abort CryptoCell PAL abort APIs +@{ +@ingroup ssi_pal + +*/ + +/*! +This function performs the "Abort" operation, should be implemented according to platform and OS. +*/ + +void SaSi_PalAbort(const char *msg); +/** +@} + */ + + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_barrier.h b/external/nrf_cc310/include/ssi_pal_barrier.h new file mode 100644 index 0000000..1188026 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_barrier.h @@ -0,0 +1,71 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef _SSI_PAL_BARRIER_H +#define _SSI_PAL_BARRIER_H + +/*! +@file +@brief This file contains the definitions and APIs for memory barrier implementation. + This is a place holder for platform specific memory barrier implementation + The secure core driver should include a memory barrier before and after the last word of the descriptor + to allow correct order between the words and different descriptors. +@defgroup ssi_pal_barrier CryptoCell PAL memory Barrier APIs +@{ +@ingroup ssi_pal + +*/ + +/*! + * This MACRO is responsible to put the memory barrier after the write operation. + * + * @return None + */ + +void SaSi_PalWmb(void); + +/*! + * This MACRO is responsible to put the memory barrier before the read operation. + * + * @return None + */ +void SaSi_PalRmb(void); + +/** +@} + */ +#endif + diff --git a/external/nrf_cc310/include/ssi_pal_compiler.h b/external/nrf_cc310/include/ssi_pal_compiler.h new file mode 100644 index 0000000..081ce72 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_compiler.h @@ -0,0 +1,186 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef __SSI_PAL_COMPILER_H__ +#define __SSI_PAL_COMPILER_H__ + +/*! +@file +@brief This file contains compiler related definitions. +@defgroup ssi_pal_compiler CryptoCell PAL platform dependant compiler specific definitions +@{ +@ingroup ssi_pal + +*/ + +#ifdef __GNUC__ + +/************************ Defines ******************************/ + +/*! Associate a symbol with a link section. */ +#define SASI_PAL_COMPILER_SECTION(sectionName) __attribute__((section(sectionName))) + +/*! Mark symbol as used, i.e., prevent garbage collector from dropping it. */ +#define SASI_PAL_COMPILER_KEEP_SYMBOL __attribute__((used)) + +/*! Make given data item aligned (alignment in bytes). */ +#define SASI_PAL_COMPILER_ALIGN(alignement) __attribute__((aligned(alignement))) + +/*! Mark function that never returns. */ +#define SASI_PAL_COMPILER_FUNC_NEVER_RETURNS __attribute__((noreturn)) + +/*! Prevent function from being inlined */ +#define SASI_PAL_COMPILER_FUNC_DONT_INLINE __attribute__((noinline)) + +/*! Given data type may cast (alias) another data type pointer. */ +/* (this is used for "superclass" struct casting) */ +#define SASI_PAL_COMPILER_TYPE_MAY_ALIAS __attribute__((__may_alias__)) + +/*! Get sizeof for a structure type member. */ +#define SASI_PAL_COMPILER_SIZEOF_STRUCT_MEMBER(type_name, member_name) \ + sizeof(((type_name *)0)->member_name) + +/*! Assertion. */ +#define SASI_ASSERT_CONCAT_(a, b) a##b +#define SASI_ASSERT_CONCAT(a, b) SASI_ASSERT_CONCAT_(a, b) +#define SASI_PAL_COMPILER_ASSERT(cond, message) \ + enum { SASI_ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(cond)) } + +#elif defined(__ARM_DSM__) || defined(__CC_ARM) +#define inline +/*! Associate a symbol with a link section. */ +#define SASI_PAL_COMPILER_SECTION(sectionName) __attribute__((section(sectionName))) + +/*! Mark symbol as used, i.e., prevent garbage collector from dropping it. */ +#define SASI_PAL_COMPILER_KEEP_SYMBOL __attribute__((used)) + +/*! Make given data item aligned (alignment in bytes). */ +#define SASI_PAL_COMPILER_ALIGN(alignement) __attribute__((aligned(alignement))) + +/*! Mark function that never returns. */ +#define SASI_PAL_COMPILER_FUNC_NEVER_RETURNS __attribute__((noreturn)) + +/*! Prevent function from being inlined. */ +#define SASI_PAL_COMPILER_FUNC_DONT_INLINE __attribute__((noinline)) + +/*! Given data type may cast (alias) another data type pointer. */ +/* (this is used for "superclass" struct casting) */ +#define SASI_PAL_COMPILER_TYPE_MAY_ALIAS __attribute__((__may_alias__)) + +/*! Get sizeof for a structure type member. */ +#define SASI_PAL_COMPILER_SIZEOF_STRUCT_MEMBER(type_name, member_name) \ + sizeof(((type_name *)0)->member_name) + +/*! Assertion. */ +#define SASI_ASSERT_CONCAT_(a, b) a##b +#define SASI_ASSERT_CONCAT(a, b) SASI_ASSERT_CONCAT_(a, b) +#define SASI_PAL_COMPILER_ASSERT(cond, message) \ + enum { SASI_ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(cond)) } + +#elif defined(__ARM_DS__) +#define inline +/*! Associate a symbol with a link section. */ +#define SASI_PAL_COMPILER_SECTION(sectionName) __attribute__((section(sectionName))) + +/*! Mark symbol as used, i.e., prevent garbage collector from dropping it. */ +#define SASI_PAL_COMPILER_KEEP_SYMBOL __attribute__((used)) + +/*! Make given data item aligned (alignment in bytes). */ +#define SASI_PAL_COMPILER_ALIGN(alignement) __attribute__((aligned(alignement))) + +/*! Mark function that never returns. */ +#define SASI_PAL_COMPILER_FUNC_NEVER_RETURNS __attribute__((noreturn)) + +/*! Prevent function from being inlined. */ +#define SASI_PAL_COMPILER_FUNC_DONT_INLINE __attribute__((noinline)) + +/*! Given data type may cast (alias) another data type pointer. */ +/* (this is used for "superclass" struct casting) */ +#define SASI_PAL_COMPILER_TYPE_MAY_ALIAS + +/*! Get sizeof for a structure type member. */ +#define SASI_PAL_COMPILER_SIZEOF_STRUCT_MEMBER(type_name, member_name) \ + sizeof(((type_name *)0)->member_name) + +/*! Assertion. */ +#define SASI_ASSERT_CONCAT_(a, b) a##b +#define SASI_ASSERT_CONCAT(a, b) SASI_ASSERT_CONCAT_(a, b) +#define SASI_PAL_COMPILER_ASSERT(cond, message) \ + enum { SASI_ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(cond)) } + +#elif defined(__ICCARM__) + +/************************ Defines ******************************/ + +/*! Associate a symbol with a link section. */ +#define SASI_PAL_COMPILER_SECTION(sectionName) __attribute__((section(sectionName))) + +/*! Mark symbol as used, i.e., prevent garbage collector from dropping it. */ +#define SASI_PAL_COMPILER_KEEP_SYMBOL __attribute__((used)) + +/*! Make given data item aligned (alignment in bytes). */ +#define STRING_PRAGMA(x) _Pragma(#x) +//#define SASI_PAL_COMPILER_ALIGN(n) STRING_PRAGMA(data_alignment = n) +#define SASI_PAL_COMPILER_ALIGN(n) + +/*! Mark function that never returns. Not implemented */ +#define SASI_PAL_COMPILER_FUNC_NEVER_RETURNS + +/* Prevent function from being inlined */ +#define SASI_PAL_COMPILER_FUNC_DONT_INLINE STRING_PRAGMA(optimize = no_inline) + +/*! Given data type may cast (alias) another data type pointer. */ +/* (this is used for "superclass" struct casting). Not implemented */ +#define SASI_PAL_COMPILER_TYPE_MAY_ALIAS + +/*! Get sizeof for a structure type member. */ +#define SASI_PAL_COMPILER_SIZEOF_STRUCT_MEMBER(type_name, member_name) \ + sizeof(((type_name *)0)->member_name) + +/*! Assertion. */ +#define SASI_ASSERT_CONCAT_(a, b) a##b +#define SASI_ASSERT_CONCAT(a, b) SASI_ASSERT_CONCAT_(a, b) + +#define SASI_PAL_COMPILER_ASSERT(cond, message) \ + enum { SASI_ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(cond)) } + + +#else +#error Unsupported compiler. +#endif +/** +@} + */ +#endif /*__SSI_PAL_COMPILER_H__*/ diff --git a/external/nrf_cc310/include/ssi_pal_dma.h b/external/nrf_cc310/include/ssi_pal_dma.h new file mode 100644 index 0000000..2a89846 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_dma.h @@ -0,0 +1,175 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef _SSI_PAL_DMA_H +#define _SSI_PAL_DMA_H + +/*! +@file +@brief This file contains definitions that are used for the DMA related APIs. The implementation of these functions +need to be replaced according to Platform and OS. +@defgroup ssi_pal_dma CryptoCell PAL DMA related APIs +@{ +@ingroup ssi_pal + +*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ssi_pal_types.h" +#include "ssi_pal_dma_plat.h" +#include "ssi_pal_dma_defs.h" + +/*! User buffer scatter information. */ +typedef struct { + SaSiDmaAddr_t blockPhysAddr; /*!< Physical address.*/ + uint32_t blockSize; /*!< Block size.*/ +}SaSi_PalDmaBlockInfo_t; + +#ifdef BIG__ENDIAN +/*! Defintion for big to little endian. */ +#define SET_WORD_LE(val) cpu_to_le32(val) +#else +/*! Defintion for big to little endian. */ +#define SET_WORD_LE +#endif + +/** + * @brief This function is called by the ARM TrustZone CryptoCell TEE runtime library before the HW is used. + * It maps a given data buffer (virtual address) for ARM TrustZone CryptoCell TEE HW DMA use (physical address), and returns the list of + * one or more DMA-able (physical) blocks. It may lock the buffer for ARM TrustZone CryptoCell TEE HW use. Once it is called, + * only ARM TrustZone CryptoCell TEE HW access to the buffer is allowed, until it is unmapped. + * If the data buffer was already mapped by the Secure OS prior to calling the ARM TrustZone CryptoCell TEE runtime library, + * this API does not have to perform any actual mapping operation, but only return the list of DMA-able blocks. + * + * @return A non-zero value in case of failure. + */ +uint32_t SaSi_PalDmaBufferMap(uint8_t *pDataBuffer, /*!< [in] Address of the buffer to map. */ + uint32_t buffSize, /*!< [in] Buffer size in bytes. */ + SaSi_PalDmaBufferDirection_t copyDirection, /*!< [in] Copy direction of the buffer, according to ::SaSi_PalDmaBufferDirection_t, +
    • TO_DEVICE - the original buffer is the input to the operation, + and this function should copy it to the temp buffer, + prior to the activating the HW on the temp buffer.
    • +
    • FROM_DEVICE - not relevant for this API.
    • +
    • BI_DIRECTION - used when the crypto operation is "in-place", meaning + the result of encryption or decryption is written over the original data + at the same address. Should be treated by this API same as + TO_DEVICE.
    */ + uint32_t *pNumOfBlocks, /*!< [in/out] Maximum numOfBlocks to fill, as output the actual number. */ + SaSi_PalDmaBlockInfo_t *pDmaBlockList, /*!< [out] List of DMA-able blocks that the buffer maps to. */ + SaSi_PalDmaBufferHandle *dmaBuffHandle /*!< [out] A handle to the mapped buffer private resources.*/ ); + + +/** + * @brief This function is called by the ARM TrustZone CryptoCell TEE runtime library after the HW is used. + * It unmaps a given buffer, and frees its associated resources, if needed. It may unlock the buffer and flush it for CPU use. + * Once it is called, ARM TrustZone CryptoCell TEE HW does not require access to this buffer anymore. + * If the data buffer was already mapped by the Secure OS prior to calling the ARM TrustZone CryptoCell TEE runtime library, this API does + * not have to perform any un-mapping operation, and the actual un-mapping can be done by the Secure OS outside the context + * of the ARM TrustZone CryptoCell TEE runtime library. + * @return A non-zero value in case of failure. + */ +uint32_t SaSi_PalDmaBufferUnmap(uint8_t *pDataBuffer, /*!< [in] Address of the buffer to unmap. */ + uint32_t buffSize, /*!< [in] Buffer size in bytes. */ + SaSi_PalDmaBufferDirection_t copyDirection, /*!< [in] Copy direction of the buffer, according to ::SaSi_PalDmaBufferDirection_t +
    • TO_DEVICE - not relevant for this API.
    • +
    • FROM_DEVICE - the temp buffer holds the output of the HW, and this + API should copy it to the actual output buffer.
    • +
    • BI_DIRECTION - used when the crypto operation is "in-place", meaning + the result of encryption or decryption is written over the original data + at the same address. Should be treated by this API same as + FROM_DEVICE.
    */ + uint32_t numOfBlocks, /*!< [in] Number of DMA-able blocks that the buffer maps to. */ + SaSi_PalDmaBlockInfo_t *pDmaBlockList, /*!< [in] List of DMA-able blocks that the buffer maps to. */ + SaSi_PalDmaBufferHandle dmaBuffHandle /*!< [in] A handle to the mapped buffer private resources. */); + + +/** + * @brief Allocates a DMA-contiguous buffer for CPU use, and returns its virtual address. + * Before passing the buffer to the ARM TrustZone CryptoCell TEE HW, ::SaSi_PalDmaBufferMap should be called. + * \note The returned address must be aligned to 32 bits. + * + * + * @return A non-zero value in case of failure. + */ +uint32_t SaSi_PalDmaContigBufferAllocate(uint32_t buffSize, /*!< [in] Buffer size in bytes.*/ + uint8_t **ppVirtBuffAddr /*!< [out] Virtual address of the allocated buffer.*/); + + + +/** + * @brief Frees resources previously allocated by ::SaSi_PalDmaContigBufferAllocate. + * + * + * @return A non-zero value in case of failure. + */ +uint32_t SaSi_PalDmaContigBufferFree(uint32_t buffSize, /*!< [in] Buffer size in Bytes. */ + uint8_t *pVirtBuffAddr /*!< [in] Virtual address of the buffer to free. */); + + + +/** + * @brief Checks whether the buffer is guaranteed to be a single contiguous DMA block. + * + * + * @return Returns TRUE if the buffer is guaranteed to be a single contiguous DMA block, and FALSE otherwise. + */ +uint32_t SaSi_PalIsDmaBufferContiguous(uint8_t *pDataBuffer, /*!< [in] User buffer address. */ + uint32_t buffSize /*!< [in] User buffer size. */); + + +/** + * @brief Maps virtual address to physical address. + * + * + * @return Physical address. + */ +SaSiDmaAddr_t SaSi_PalMapVirtualToPhysical(uint8_t *pVirtualAddr /*!< [in] Pointer to virtual address. */); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_dma_defs.h b/external/nrf_cc310/include/ssi_pal_dma_defs.h new file mode 100644 index 0000000..ce74c10 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_dma_defs.h @@ -0,0 +1,77 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +/*! +@file +@brief This file contains the platform dependent DMA definitions. +@defgroup ssi_pal_dma_defs CryptoCell PAL DMA specific definitions +@{ +@ingroup ssi_pal +*/ + +#ifndef _SSI_PAL_DMA_DEFS_H +#define _SSI_PAL_DMA_DEFS_H + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! Definition for DMA buffer handle.*/ +typedef void * SaSi_PalDmaBufferHandle; + +/*! DMA directions configuration */ +typedef enum { + SASI_PAL_DMA_DIR_NONE = 0, /*!< No direction. */ + SASI_PAL_DMA_DIR_TO_DEVICE = 1, /*!< The original buffer is the input to the operation, and should be copied/mapped to a temp buffer, + prior to activating the HW on the temp buffer. */ + SASI_PAL_DMA_DIR_FROM_DEVICE = 2, /*!< The temp buffer holds the output of the HW, and this API should copy/map it to the original output buffer.*/ + SASI_PAL_DMA_DIR_BI_DIRECTION = 3, /*!< Used when the result is written over the original data at the same address. should be treated as 1 & 2.*/ + SASI_PAL_DMA_DIR_MAX, /*!< Maximal DMA directions options. */ + SASI_PAL_DMA_DIR_RESERVE32 = 0x7FFFFFFF /*!< Reserved.*/ +}SaSi_PalDmaBufferDirection_t; + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_dma_plat.h b/external/nrf_cc310/include/ssi_pal_dma_plat.h new file mode 100644 index 0000000..e296977 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_dma_plat.h @@ -0,0 +1,72 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef _SSI_PAL_DMA_PLAT_H +#define _SSI_PAL_DMA_PLAT_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief stub function, the function should initialize the DMA mapping of the platform (if needed) + * + * @param[in] buffSize - buffer size in Bytes + * @param[in] physBuffAddr - physical start address of the memory to map + * + * @return Virtual start address of contiguous memory + */ +extern uint32_t SaSi_PalDmaInit(uint32_t buffSize, + uint32_t physBuffAddr); + +/** + * @brief free system resources created in PD_PAL_DmaInit() + * + * + * @return void + */ +extern void SaSi_PalDmaTerminate(void); +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_error.h b/external/nrf_cc310/include/ssi_pal_error.h new file mode 100644 index 0000000..9210acd --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_error.h @@ -0,0 +1,84 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef _SSI_PAL_ERROR_H +#define _SSI_PAL_ERROR_H + +/*! +@file +@brief This file contains the platform dependent error definitions. +@defgroup ssi_pal_error CryptoCell PAL specific errors +@{ +@ingroup ssi_pal + +*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! PAL error base.*/ +#define SASI_PAL_BASE_ERROR 0x0F000000 + +/* Memory error returns */ +/*! Buffer 1 is greater than buffer 2 error.*/ +#define SASI_PAL_MEM_BUF1_GREATER SASI_PAL_BASE_ERROR + 0x01UL +/*! Buffer 2 is greater than buffer 1 error.*/ +#define SASI_PAL_MEM_BUF2_GREATER SASI_PAL_BASE_ERROR + 0x02UL + +/* Semaphore error returns */ +/*! Semaphor creation failed.*/ +#define SASI_PAL_SEM_CREATE_FAILED SASI_PAL_BASE_ERROR + 0x03UL +/*! Semaphor deletion failed.*/ +#define SASI_PAL_SEM_DELETE_FAILED SASI_PAL_BASE_ERROR + 0x04UL +/*! Semaphor reached timeout.*/ +#define SASI_PAL_SEM_WAIT_TIMEOUT SASI_PAL_BASE_ERROR + 0x05UL +/*! Semaphor wait failed.*/ +#define SASI_PAL_SEM_WAIT_FAILED SASI_PAL_BASE_ERROR + 0x06UL +/*! Semaphor release failed.*/ +#define SASI_PAL_SEM_RELEASE_FAILED SASI_PAL_BASE_ERROR + 0x07UL +/*! PAL illegal address.*/ +#define SASI_PAL_ILLEGAL_ADDRESS SASI_PAL_BASE_ERROR + 0x08UL + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_file.h b/external/nrf_cc310/include/ssi_pal_file.h new file mode 100644 index 0000000..a39875d --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_file.h @@ -0,0 +1,225 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef _SSI_PAL_FILE_H +#define _SSI_PAL_FILE_H + + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ssi_pal_types.h" +#include "ssi_pal_file_plat.h" +/** +* @brief File Description: +* This file contains functions for file related operations. The functions implementations +* are generally just wrappers to different operating system calls. +* None of the described functions will check the input parameters so the behavior +* of the APIs in illegal parameters case is dependent on the operating system behavior. +* +*/ + +/**** ----- Files General Definitions ----- ****/ +typedef enum +{ + SASI_PAL_Read = 0, /* "r", read only */ + SASI_PAL_ReadAndWrite = 1, /* "r+", read and write */ + SASI_PAL_Write = 2, /* "w", write only */ + SASI_PAL_WriteAndRead = 3, /* "w+", write and read */ + SASI_PAL_Append = 4, /* "a", append to the end of file */ + SASI_PAL_AppendAndRead = 5, /* "a+", append (to the end of file) and read */ + SASI_PAL_ReadBinary = 6, /* "rb", read binary */ + SASI_PAL_ReadAndWriteBinary = 7, /* "r+b" read and write binary */ + SASI_PAL_WriteBinary = 8, /* "wb" write binary */ + SASI_PAL_WriteAndReadBinary = 9, /* "w+b" write and read binary */ + SASI_PAL_AppendBinary = 10, /* "ab" append binary */ + SASI_PAL_AppendAndReadBinary = 11, /* "a+b" append and read binary */ + + SASI_PAL_DummyMode = 0x7FFFFFFF + +}SaSi_PalFileMode_t; + +/* Definitions for SEEK positions */ + +#define SASI_PAL_SEEK_START 0 /* Seek from start of file */ +#define SASI_PAL_SEEK_CUR 1 /* Seek from current position */ +#define SASI_PAL_SEEK_END 2 /* Seek from end of file */ + +/* Definition for DxFile */ +typedef struct _SaSiFile_t* SaSiFile_t; +/**** ------------------------------------- ****/ + + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/** + * @brief This function purpose is to create a new file. The function will delete a file + * If it is already exist. + * + * + * @param[in] aFileName - The file name to create + * + * @return The function returns a FILE handle to the opened file, in case of failure + * the function will return NULL + */ +SaSiFile_t SaSi_PalFileCreate( char *aFileName ); + +/* Definition for SaSi_PalFileCreate */ +#define SaSi_PalFileCreate(aFileName) _SaSi_PalFileCreate(aFileName) +/** + * @brief This function purpose is to create a new file. The function will delete a file + * If it is already exist. + * + * + * @param[in] aFileName - The file name to open + * @param[in] aFileMode - The mode to open the file + * + * @return The function returns a FILE handle to the opened file, in case of failure + * the function will return NULL + */ +SaSiFile_t SaSi_PalFOpen( char *aFileName, SaSi_PalFileMode_t aFileMode ); + +/* Definition for fopen */ +#define SaSi_PalFOpen(aFileName, aFileMode) _SaSi_PalFOpen(aFileName, aFileMode) +/** + * @brief This function purpose is to close a file (pointed by aFileHandle), The function + * will dissociate the file from the handle. + * + * + * @param[in] aFileHandle - The file name to create + * + * @return The return values is according to operating system return values. + */ +SaSiError_t SaSi_PalFClose( SaSiFile_t aFileHandle ); + +/* Definition for fclose */ +#define SaSi_PalFClose(aFileHandle) _SaSi_PalFClose(aFileHandle) + +/** + * @brief This function purpose is to change the file pointer position according to aOffset + * + * + * @param[in] aFileHandle - The file handle + * @param[in] aOffset - offset to move the file pointer inside the file + * @param[in] aSeekOrigin - seek origin (current, end or start) to move aOffset from + * + * @return The return values is according to operating system return values. + */ +SaSiError_t SaSi_PalFSeek( SaSiFile_t aFileHandle, int32_t aOffset, uint8_t aSeekOrigin ); + +/* Definition for fseek */ +#define SaSi_PalFSeek(aFileHandle ,aOffset, aSeekOrigin) _SaSi_PalFSeek(aFileHandle, aOffset, aSeekOrigin) + +/** + * @brief This function purpose is to return the file pointer position + * + * + * @param[in] aFileHandle - The file handle + * + * @return The file pointer position + */ +uint32_t SaSi_PalFTell( SaSiFile_t aFileHandle ); + +/* definition for SaSi_PalFTell */ +#define SaSi_PalFTell(aFileHandle) _SaSi_PalFTell(aFileHandle) + +/** + * @brief This function purpose is to read aSize of bytes from the file and write it + * to aBuffer. In case EOF reached before aSize is read the returned size is smaller + * than aSize. + * + * + * @param[in] aFileHandle - The file handle + * @param[in] aBuffer - Pointer to buffer to read the data into + * @param[in] aSize - Number of bytes to read from file + * + * @return The number of bytes read from the file + */ +uint32_t SaSi_PalFRead(SaSiFile_t aFileHandle, void *aBuffer, uint32_t aSize ); + +/* Definition for fread */ +#define SaSi_PalFRead(aFileHandle, aBuffer, aSize) _SaSi_PalFRead(aFileHandle, aBuffer, aSize) +/** + * @brief This function purpose is to write aSize bytes from aBuffer to the file pointed + * by aFileHandle. + * + * + * @param[in] aFileHandle - The file handle + * @param[in] aBuffer - Pointer to buffer to read the data into + * @param[in] aSize - Number of bytes to read from file + * + * @return The number of bytes written to the file + */ +uint32_t SaSi_PalFWrite( SaSiFile_t aFileHandle, const void *aBuffer, uint32_t aSize ); + +#define SaSi_PalFWrite(aFileHandle, aBuffer, aSize) _SaSi_PalFWrite(aFileHandle, aBuffer, aSize) +/** + * @brief This function purpose is to save all buffered data to disk + * + * + * @param[in] aFileHandle - The file handle + * + * @return The return values is according to operating system return values. + */ +SaSiError_t SaSi_PalFFlush( SaSiFile_t aFileHandle ); + +/* Definition for fflush */ +#define SaSi_PalFFlush(aFileHandle) _SaSi_PalFFlush(aFileHandle) + +/** + * @brief This function purpose is to return the file size + * + * + * @param[in] aFileHandle - The file handle + * @param[out] aFileSize - The returned file size + * + * @return The function will return SASI_SUCCESS in case of success, else errors from + * ssi_pal_error.h is returned. + */ +SaSiError_t SaSi_PalFGetFileSize( SaSiFile_t aFileHandle, uint32_t *aFileSize ); + + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_file_plat.h b/external/nrf_cc310/include/ssi_pal_file_plat.h new file mode 100644 index 0000000..1d99c52 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_file_plat.h @@ -0,0 +1,128 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef _SSI_PAL_FILE_INT_H +#define _SSI_PAL_FILE_INT_H + + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "stdio.h" + +/** +* @brief File Description: +* This file contains wrapper functions for file related operations. +*/ + +/**** ----- Files General Definitions ----- ****/ + +/* Definitions for file modes */ +#define SASI_PAL_MAX_SIZE_MODE 4 +#define SASI_PAL_NUM_OF_SUPPORT_MODES 12 + +typedef char SaSiPalFileModeStr_t[SASI_PAL_MAX_SIZE_MODE]; + +typedef SaSiPalFileModeStr_t SaSiPalFileModesTable_t[SASI_PAL_NUM_OF_SUPPORT_MODES]; + +extern const SaSiPalFileModeStr_t SaSiPalFileModeTable[]; +/**** ------------------------------------- ****/ + +//#define _SaSiFile_t FILE + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ +/** +* @brief A wrapper for fopen functionality (to create a new file, the file is opened for read and +* write). +* +*/ +#define _SaSi_PalFileCreate(aFileName) SaSi_PalFOpen(aFileName, SASI_PAL_WriteAndRead) + +/** +* @brief A wrapper for fopen functionality. SaSiPalFileModeTable contains all possible modes +* for fopen +* +*/ +#define _SaSi_PalFOpen(aFileName, aFileMode) ((SaSiFile_t)fopen(aFileName, SaSiPalFileModeTable[aFileMode])) + +/** + * @brief A wrapper for fclose functionality. + * + */ +#define _SaSi_PalFClose(aFileHandle) fclose((FILE*)aFileHandle) + +/** + * @brief A wrapper for fseek functionality + * + */ +#define _SaSi_PalFSeek(aFileHandle, aOffset, aSeekOrigin) fseek((FILE*)aFileHandle, aOffset, aSeekOrigin) + +/** + * @brief A wrapper for ftell functionality + * + */ +#define _SaSi_PalFTell(aFileHandle) ftell((FILE*)aFileHandle) + +/** +* @brief A wrapper for fread functionality +* +*/ +#define _SaSi_PalFRead(aFileHandle, aBuffer, aSize) fread(aBuffer, 1, aSize, (FILE*)aFileHandle) + +/** +* @brief A wrapper for fwrite functionality +* +*/ +#define _SaSi_PalFWrite(aFileHandle, aBuffer, aSize) fwrite(aBuffer, 1, aSize, (FILE*)aFileHandle) +/** + * @brief A wrapper for fflush functionality + * + */ +#define _SaSi_PalFFlush(aFileHandle) fflush((FILE*)aFileHandle) + + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_fips.h b/external/nrf_cc310/include/ssi_pal_fips.h new file mode 100644 index 0000000..5fba32e --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_fips.h @@ -0,0 +1,119 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef _SSI_PAL_FIPS_H +#define _SSI_PAL_FIPS_H + +/*! +@file +@brief This file contains definitions that are used by the FIPS related APIs. The implementation of these functions +need to be replaced according to Platform and OS. +*/ + +#include "ssi_pal_types_plat.h" +#include "crys_fips.h" +#include "crys_fips_defs.h" + +/** + * @brief This function purpose is to get the FIPS state. + * + * + * @return Zero on success. + * @return A non-zero value on failure. + */ +SaSiError_t SaSi_PalFipsGetState(CC_FipsState_t *pFipsState); + + +/** + * @brief This function purpose is to get the FIPS Error. + * + * + * @return Zero on success. + * @return A non-zero value on failure. + */ +SaSiError_t SaSi_PalFipsGetError(CC_FipsError_t *pFipsError); + + +/** + * @brief This function purpose is to get the FIPS trace. + * + * + * @return Zero on success. + * @return A non-zero value on failure. + */ +SaSiError_t SaSi_PalFipsGetTrace(CC_FipsTrace_t *pFipsTrace); + + +/** + * @brief This function purpose is to set the FIPS state. + * + * + * @return Zero on success. + * @return A non-zero value on failure. + */ +SaSiError_t SaSi_PalFipsSetState(CC_FipsState_t fipsState); + + +/** + * @brief This function purpose is to set the FIPS error. + * + * + * @return Zero on success. + * @return A non-zero value on failure. + */ +SaSiError_t SaSi_PalFipsSetError(CC_FipsError_t fipsError); + + +/** + * @brief This function purpose is to set the FIPS trace. + * + * + * @return Zero on success. + * @return A non-zero value on failure. + */ +SaSiError_t SaSi_PalFipsSetTrace(CC_FipsTrace_t fipsTrace); + + +/** + * @brief This function should push the FIPS TEE library error towards the REE library, + * the FIPS error can occur while running KAT tests at library init or while running + * conditional or continues tests + * + * @return Zero on success. + * @return A non-zero value on failure. + */ +SaSiError_t SaSi_PalFipsNotifyUponTeeError(void); + +#endif // _SSI_PAL_FIPS_H \ No newline at end of file diff --git a/external/nrf_cc310/include/ssi_pal_init.h b/external/nrf_cc310/include/ssi_pal_init.h new file mode 100644 index 0000000..a607547 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_init.h @@ -0,0 +1,85 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef _SSI_PAL_INIT_H +#define _SSI_PAL_INIT_H + +#include "ssi_pal_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains the PAL layer entry point, it includes the definitions and APIs for PAL initialization and termination. +@defgroup ssi_pal_init CryptoCell PAL entry\exit point APIs +@{ +@ingroup ssi_pal + +*/ + +/** + * @brief This function Performs all initializations that may be required by the customer's PAL implementation, specifically by the DMA-able buffer + * scheme. The existing implementation allocates a contiguous memory pool that is later used by the ARM TrustZone CryptoCell TEE implementation. + * In case no initializations are needed in the customer's environment, the function can be minimized to return OK. + * It is called by ::SaSi_LibInit. + * + * @return A non-zero value in case of failure. + */ +int SaSi_PalInit(void); + + + +/** + * @brief This function is used to terminate the PAL implementation and free the resources that were taken by ::SaSi_PalInit. + * + * @return Void. + */ +void SaSi_PalTerminate(void); + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_list.h b/external/nrf_cc310/include/ssi_pal_list.h new file mode 100644 index 0000000..eda599b --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_list.h @@ -0,0 +1,118 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef _SSI_PAL_LIST_H +#define _SSI_PAL_LIST_H + + +typedef struct SaSi_PalListItem { + struct SaSi_PalListItem *prev; + struct SaSi_PalListItem *next; +} SaSi_PalListItem_s; + +/*! + * Initializes a list. Prev/Next points to the same head object. + * + * \param head The head of the list. + */ +static inline void SaSi_PalListInit(SaSi_PalListItem_s *head) +{ + head->prev = head; + head->next = head; +} + +/*! + * Add a new list item after head of list. + * + * \param new New entry to be added + * \param head List head to add it after + */ +static inline void SaSi_PalListAdd(SaSi_PalListItem_s *new, SaSi_PalListItem_s *head) +{ + SaSi_PalListItem_s *next = head->next; + + next->prev = new; + new->next = next; + new->prev = head; + head->next = new; +} + +/*! + * Add a new list item after head of list. + * + * \param new New entry to be added + * \param head List head to add it after + */ +static inline void SaSi_PalListAddTail(SaSi_PalListItem_s *new, SaSi_PalListItem_s *head) +{ + SaSi_PalListItem_s *prev = head->prev; + + prev->next = new; + new->next = head; + new->prev = prev; + head->prev = new; +} + +/*! + * Deletes entry from list. + * + * \param item The item to delete from the list. + */ +static inline void SaSi_PalListDel(SaSi_PalListItem_s *item) +{ + SaSi_PalListItem_s *prev = item->prev; + SaSi_PalListItem_s *next = item->next; + + prev->next = next; + next->prev = prev; + + item->next = item; + item->prev = item; +} + +/*! + * Checks whether a list is empty. + * + * \param head The list's head + * + * \return int True if empty list, False otherwise. + */ +static inline int SaSi_PalIsListEmpty(const SaSi_PalListItem_s *head) +{ + return (head->next == head); +} + +#endif + diff --git a/external/nrf_cc310/include/ssi_pal_log.h b/external/nrf_cc310/include/ssi_pal_log.h new file mode 100644 index 0000000..fd97069 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_log.h @@ -0,0 +1,216 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef _SSI_PAL_LOG_H_ +#define _SSI_PAL_LOG_H_ + +#include "ssi_pal_types.h" + + +/*! +@file +@brief This file contains the PAL layer log definitions, by default the log is disabled. +@defgroup ssi_pal_log CryptoCell PAL logging APIs and definitions +@{ +@ingroup ssi_pal + +*/ + +/* PAL log levels (to be used in SASI_PAL_logLevel) */ +/*! PAL log level - disabled. */ +#define SASI_PAL_LOG_LEVEL_NULL -1 /*!< \internal Disable logging */ +/*! PAL log level - error. */ +#define SASI_PAL_LOG_LEVEL_ERR 0 +/*! PAL log level - warning. */ +#define SASI_PAL_LOG_LEVEL_WARN 1 +/*! PAL log level - info. */ +#define SASI_PAL_LOG_LEVEL_INFO 2 +/*! PAL log level - debug. */ +#define SASI_PAL_LOG_LEVEL_DEBUG 3 +/*! PAL log level - trace. */ +#define SASI_PAL_LOG_LEVEL_TRACE 4 +/*! PAL log level - data. */ +#define SASI_PAL_LOG_LEVEL_DATA 5 + +#ifndef SASI_PAL_LOG_CUR_COMPONENT +/* Setting default component mask in case caller did not define */ +/* (a mask that is always on for every log mask value but full masking) */ +/*! Default log debugged component.*/ +#define SASI_PAL_LOG_CUR_COMPONENT 0xFFFFFFFF +#endif +#ifndef SASI_PAL_LOG_CUR_COMPONENT_NAME +/*! Default log component name.*/ +#define SASI_PAL_LOG_CUR_COMPONENT_NAME "Dx" +#endif + +/* Select compile time log level (default if not explicitly specified by caller) */ +#ifndef SASI_PAL_MAX_LOG_LEVEL /* Can be overriden by external definition of this constant */ +#ifdef DEBUG +/*! Default debug log level (when debug is set to on).*/ +#define SASI_PAL_MAX_LOG_LEVEL SASI_PAL_LOG_LEVEL_ERR /*SASI_PAL_LOG_LEVEL_DEBUG*/ +#else /* Disable logging */ +/*! Default debug log level (when debug is set to off).*/ +#define SASI_PAL_MAX_LOG_LEVEL SASI_PAL_LOG_LEVEL_NULL +#endif +#endif /*SASI_PAL_MAX_LOG_LEVEL*/ +/*! Evaluate SASI_PAL_MAX_LOG_LEVEL in case provided by caller */ +#define __SASI_PAL_LOG_LEVEL_EVAL(level) level +/*! Maximal log level defintion.*/ +#define _SASI_PAL_MAX_LOG_LEVEL __SASI_PAL_LOG_LEVEL_EVAL(SASI_PAL_MAX_LOG_LEVEL) + +#ifdef ARM_DSM //not support ARM DSM log feature +/*! Log init function. */ +#define SaSi_PalLogInit() do {} while (0) +/*! Log set level function - sets the level of logging in case of debug. */ +#define SaSi_PalLogLevelSet(setLevel) do {} while (0) +/*! Log set mask function - sets the component masking in case of debug. */ +#define SaSi_PalLogMaskSet(setMask) do {} while (0) +/*! Log log funtion based on various platform */ +#define SaSi_PalLogPlatsampan(level, msg) do {} while (0) + +#else +#if _SASI_PAL_MAX_LOG_LEVEL > SASI_PAL_LOG_LEVEL_NULL +/*! Log init function. */ +void SaSi_PalLogInit(void); +/*! Log set level function - sets the level of logging in case of debug. */ +void SaSi_PalLogLevelSet(int setLevel); +/*! Log set mask function - sets the component masking in case of debug. */ +void SaSi_PalLogMaskSet(uint32_t setMask); +/*! Log log funtion based on various platform */ +void SaSi_PalLogPlat(uint32_t level, const char *msg); + +/*! Global variable for log level */ +extern int SaSi_PAL_logLevel; +/*! Global variable for log mask */ +extern uint32_t SaSi_PAL_logMask; +#else /* No log */ +/*! Log init function. */ +#define SaSi_PalLogInit() do {} while (0) +/*! Log set level function - sets the level of logging in case of debug. */ +#define SaSi_PalLogLevelSet(setLevel) do {} while (0) +/*! Log set mask function - sets the component masking in case of debug. */ +#define SaSi_PalLogMaskSet(setMask) do {} while (0) +/*! Log log funtion based on various platform */ +#define SaSi_PalLogPlat(level, msg) do {} while (0) + +#endif +#endif + +/*! Filter logging based on logMask and dispatch to platform specific logging mechanism */ +#define _SASI_PAL_LOG(level, msg) \ + if (SaSi_PAL_logMask & SASI_PAL_LOG_CUR_COMPONENT) \ + SaSi_PalLogPlat(SASI_PAL_LOG_LEVEL_ ## level, msg ) + +#if (_SASI_PAL_MAX_LOG_LEVEL >= SASI_PAL_LOG_LEVEL_ERR) + +/*! Log messages according to log level.*/ +#define SASI_PAL_LOG_ERR(msg) \ + _SASI_PAL_LOG(ERR, msg) +#else +/*! Log messages according to log level.*/ +#define SASI_PAL_LOG_ERR( ... ) do {} while (0) +#endif + +#if (_SASI_PAL_MAX_LOG_LEVEL >= SASI_PAL_LOG_LEVEL_WARN) +/*! Log messages according to log level.*/ +#define SASI_PAL_LOG_WARN(msg) \ + if (SaSi_PAL_logLevel >= SASI_PAL_LOG_LEVEL_WARN) \ + _SASI_PAL_LOG(WARN, msg) +#else +/*! Log messages according to log level.*/ +#define SASI_PAL_LOG_WARN( ... ) do {} while (0) +#endif + +#if (_SASI_PAL_MAX_LOG_LEVEL >= SASI_PAL_LOG_LEVEL_INFO) +/*! Log messages according to log level.*/ +#define SASI_PAL_LOG_INFO(msg) \ + if (SaSi_PAL_logLevel >= SASI_PAL_LOG_LEVEL_INFO) \ + _SASI_PAL_LOG(INFO, msg) +#else +/*! Log messages according to log level.*/ +#define SASI_PAL_LOG_INFO( ... ) do {} while (0) +#endif + +#if (_SASI_PAL_MAX_LOG_LEVEL >= SASI_PAL_LOG_LEVEL_DEBUG) +/*! Log messages according to log level.*/ +#define SASI_PAL_LOG_DEBUG(msg) \ + if (SaSi_PAL_logLevel >= SASI_PAL_LOG_LEVEL_DEBUG) \ + _SASI_PAL_LOG(DEBUG, msg) + +/*! Log message buffer.*/ +#define SASI_PAL_LOG_DUMP_BUF(msg, buf, size) \ + do { \ + int i; \ + uint8_t *pData = (uint8_t*)buf; \ + \ + PRINTF("%s (%d):\n", msg, size); \ + for (i = 0; i < size; i++) { \ + PRINTF("0x%02X ", pData[i]); \ + if ((i & 0xF) == 0xF) { \ + PRINTF("\n"); \ + } \ + } \ + PRINTF("\n"); \ + } while (0) +#else +/*! Log debug messages.*/ +#define SASI_PAL_LOG_DEBUG( ... ) do {} while (0) +/*! Log debug buffer.*/ +#define SASI_PAL_LOG_DUMP_BUF(msg, buf, size) do {} while (0) +#endif + +#if (_SASI_PAL_MAX_LOG_LEVEL >= SASI_PAL_LOG_LEVEL_TRACE) +/*! Log debug trace.*/ +#define SASI_PAL_LOG_TRACE(msg) \ + if (SaSi_PAL_logLevel >= SASI_PAL_LOG_LEVEL_TRACE) \ + _SASI_PAL_LOG(TRACE, format, msg) +#else +/*! Log debug trace.*/ +#define SASI_PAL_LOG_TRACE(...) do {} while (0) +#endif + +#if (_SASI_PAL_MAX_LOG_LEVEL >= SASI_PAL_LOG_LEVEL_TRACE) +/*! Log debug data.*/ +#define SASI_PAL_LOG_DATA(msg) \ + if (SaSi_PAL_logLevel >= SASI_PAL_LOG_LEVEL_TRACE) \ + _SASI_PAL_LOG(DATA, format, msg) +#else +/*! Log debug data.*/ +#define SASI_PAL_LOG_DATA( ...) do {} while (0) +#endif +/** +@} + */ +#endif /*_SSI_PAL_LOG_H_*/ diff --git a/external/nrf_cc310/include/ssi_pal_mem.h b/external/nrf_cc310/include/ssi_pal_mem.h new file mode 100644 index 0000000..b261537 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_mem.h @@ -0,0 +1,161 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef _SSI_PAL_MEM_H +#define _SSI_PAL_MEM_H + + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ssi_pal_types.h" + +/*! +@file +@brief This file contains functions for memory operations. The functions implementations + are generally just wrappers to different operating system calls. + None of the described functions will check the input parameters so the behavior + of the APIs in illegal parameters case is dependent on the operating system behavior. +@defgroup ssi_pal_mem CryptoCell PAL memory operations +@{ +@ingroup ssi_pal +*/ + + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/**** ----- Memory Operations APIs ----- ****/ + +/*! +* @brief This function purpose is to compare between two given buffers according to given size. +* +* @return The return values is according to operating system return values. +*/ + + +int32_t SaSi_PalMemCmp( const void* aTarget, /*!< [in] The target buffer to compare. */ + const void* aSource, /*!< [in] The Source buffer to compare to. */ + uint32_t aSize /*!< [in] Number of bytes to compare. */); + +/*! + * @brief This function purpose is to perform secured memory comparison between two given + * buffers according to given size. The function will compare each byte till aSize + * number of bytes was compared even if the bytes are different. + * The function should be used to avoid security timing attacks. + * + * @return True if same, otherwise false + */ +bool SaSi_PalSecMemCmp( const void* aTarget, /*!< [in] The target buffer to compare. */ + const void* aSource, /*!< [in] The Source buffer to compare to. */ + uint32_t aSize /*!< [in] Number of bytes to compare. */); + +/*! + * @brief This function purpose is to copy aSize bytes from source buffer to destination buffer. + * + * @return void. + */ +void SaSi_PalMemCopy( void* aDestination, /*!< [out] The destination buffer to copy bytes to. */ + const void* aSource, /*!< [in] The Source buffer to copy from. */ + uint32_t aSize /*!< [in] Number of bytes to copy. */ ); + +/*! + * @brief This function purpose is to copy aSize bytes from source buffer to destination buffer. + * This function Supports overlapped buffers. + * + * @return void. + */ +void SaSi_PalMemMove( void* aDestination, /*!< [out] The destination buffer to copy bytes to. */ + const void* aSource, /*!< [in] The Source buffer to copy from. */ + uint32_t aSize /*!< [in] Number of bytes to copy. */); + +/*! + * @brief This function purpose is to set aSize bytes in the given buffer with aChar. + * + * @return void. + */ +void SaSi_PalMemSet( void* aTarget, /*!< [out] The target buffer to set. */ + const uint8_t aChar, /*!< [in] The char to set into aTarget. */ + uint32_t aSize /*!< [in] Number of bytes to set. */); + +/*! + * @brief This function purpose is to set aSize bytes in the given buffer with zeroes. + * + * @return void. + */ +void SaSi_PalMemSetZero( void* aTarget, /*!< [out] The target buffer to set. */ + uint32_t aSize /*!< [in] Number of bytes to set. */); + +/**** ----- Memory Allocation APIs ----- ****/ + +/*! + * @brief This function purpose is to allocate a memory buffer according to aSize. + * + * + * @return The function will return a pointer to allocated buffer or NULL if allocation failed. + */ +void* SaSi_PalMemMalloc(uint32_t aSize /*!< [in] Number of bytes to allocate. */); + +/*! + * @brief This function purpose is to reallocate a memory buffer according to aNewSize. + * The content of the old buffer is moved to the new location. + * + * @return The function will return a pointer to the newly allocated buffer or NULL if allocation failed. + */ +void* SaSi_PalMemRealloc( void* aBuffer, /*!< [in] Pointer to allocated buffer. */ + uint32_t aNewSize /*!< [in] Number of bytes to reallocate. */); + +/*! + * @brief This function purpose is to free allocated buffer. + * + * + * @return void. + */ +void SaSi_PalMemFree(void* aBuffer /*!< [in] Pointer to allocated buffer.*/); + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_memmap.h b/external/nrf_cc310/include/ssi_pal_memmap.h new file mode 100644 index 0000000..b0d70bb --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_memmap.h @@ -0,0 +1,95 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef _SSI_PAL_MEMMAP_H +#define _SSI_PAL_MEMMAP_H + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +#include "ssi_pal_types.h" +/*! +@file +@brief This file contains functions for memory mapping + None of the described functions will check the input parameters so the behavior + of the APIs in illegal parameters case is dependent on the operating system behavior. +@defgroup ssi_pal_memmap CryptoCell PAL memory mapping APIs +@{ +@ingroup ssi_pal + +*/ + + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/** + * @brief This function purpose is to return the base virtual address that maps the + * base physical address + * + * @return Zero on success. + * @return A non-zero value in case of failure. + */ +uint32_t SaSi_PalMemMap(uint32_t physicalAddress, /*!< [in] Start physical address of the I/O range to be mapped. */ + uint32_t mapSize, /*!< [in] Number of bytes that were mapped. */ + uint32_t **ppVirtBuffAddr /*!< [out] Pointer to the base virtual address to which the physical pages were mapped. */ ); + + +/** + * @brief This function purpose is to Unmap a specified address range previously mapped + * by SaSi_PalMemMap. + * + * @return Zero on success. + * @return A non-zero value in case of failure. + */ +uint32_t SaSi_PalMemUnMap(uint32_t *pVirtBuffAddr, /*!< [in] Pointer to the base virtual address to which the physical pages were mapped. */ + uint32_t mapSize /*!< [in] Number of bytes that were mapped. */); + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_mutex.h b/external/nrf_cc310/include/ssi_pal_mutex.h new file mode 100644 index 0000000..e2e03f9 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_mutex.h @@ -0,0 +1,148 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef _SSI_PAL_MUTEX_H +#define _SSI_PAL_MUTEX_H + +#include "ssi_pal_types.h" +#include "ssi_pal_mutex_plat.h" +#include "ssi_pal_types_plat.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains functions for resource management (mutex operations). + The functions implementations are generally just wrappers to different operating system calls. + None of the described functions will check the input parameters so the behavior + of the APIs in illegal parameters case is dependent on the operating system behavior. +@defgroup ssi_pal_mutex CryptoCell PAL mutex APIs +@{ +@ingroup ssi_pal +*/ + + + + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/** + * @brief This function purpose is to create a mutex. + * + * + * @return Zero on success. + * @return A non-zero value on failure. + */ +//SaSiError_t SaSi_PalMutexCreate(SaSi_PalMutex *pMutexId /*!< [out] Pointer to created mutex handle. */); +#define SaSi_PalMutexCreate(a) (0) + + +/** + * @brief This function purpose is to destroy a mutex. + * + * + * @return Zero on success. + * @return A non-zero value on failure. + */ +//SaSiError_t SaSi_PalMutexDestroy(SaSi_PalMutex *pMutexId /*!< [in] Pointer to mutex handle. */); +#define SaSi_PalMutexDestroy(a) (0) + + +/** + * @brief This function purpose is to Wait for Mutex with aTimeOut. aTimeOut is + * specified in milliseconds (SASI_INFINITE is blocking). + * + * @return Zero on success. + * @return A non-zero value on failure. + */ +#define SaSi_PalMutexLock(a, b) (0) +//SaSiError_t SaSi_PalMutexLock (SaSi_PalMutex *pMutexId, /*!< [in] Pointer to Mutex handle. */ +// uint32_t aTimeOut /*!< [in] Timeout in mSec, or SASI_INFINITE. */); + + +/** + * @brief This function purpose is to release the mutex. + * + * @return Zero on success. + * @return A non-zero value on failure. + */ +#define SaSi_PalMutexUnlock(a) (0) +//SaSiError_t SaSi_PalMutexUnlock (SaSi_PalMutex *pMutexId/*!< [in] Pointer to Mutex handle. */); + + +/** + * @brief This function gets the number of users of CC-hardware + * + * @return Number of users + */ +int32_t SaSi_PalPowerModeStatus(void); + + +/** + * @brief This function enables/disables power level + * + * @return 0 on success, otherwise false + */ +uint32_t SaSi_PalPowerSaveModeSelect(bool isPowerSaveMode); + +#define CC_SUCCESS SASI_SUCCESS +#define CC_FALSE SASI_FALSE +#define CC_TRUE SASI_TRUE + +/*! Get ARM Cerberus status. Return number of active registered CC operations */ +#define CC_STATUS_GET SaSi_PalPowerSaveModeStatus() + +/*! Notify ARM Cerberus is active. */ +#define CC_IS_WAKE SaSi_PalPowerSaveModeSelect(CC_FALSE) + +/*! Notify ARM Cerberus is idle. */ +#define CC_IS_IDLE SaSi_PalPowerSaveModeSelect(CC_TRUE) + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_mutex_plat.h b/external/nrf_cc310/include/ssi_pal_mutex_plat.h new file mode 100644 index 0000000..9141c8b --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_mutex_plat.h @@ -0,0 +1,71 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef _SSI_PAL_MUTEX_PLAT_H +#define _SSI_PAL_MUTEX_PLAT_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif +/** +* @brief File Description: +* This file contains functions for resource management (semaphor operations). +* The functions implementations are generally just wrappers to different operating system calls. +* None of the described functions will check the input parameters so the behavior +* of the APIs in illegal parameters case is dependent on the operating system behavior. +* +*/ + +typedef uint32_t SaSi_PalMutex; + + + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_perf.h b/external/nrf_cc310/include/ssi_pal_perf.h new file mode 100644 index 0000000..8bad274 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_perf.h @@ -0,0 +1,143 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef _SSI_PAL_PERF_H_ +#define _SSI_PAL_PERF_H_ + +#ifdef LIB_PERF +#include "ssi_pal_perf_plat.h" +#endif + +typedef enum { + PERF_TEST_TYPE_CRYS_AES_INTGR = 0x1, + PERF_TEST_TYPE_CRYS_AES_INIT = 0x2, + PERF_TEST_TYPE_CRYS_AES_BLOCK = 0x3, + PERF_TEST_TYPE_CRYS_AES_FIN = 0x4, + PERF_TEST_TYPE_HW_CMPLT = 0x5, + PERF_TEST_TYPE_PAL_MAP = 0x6, + PERF_TEST_TYPE_PAL_UNMAP = 0x7, + PERF_TEST_TYPE_MLLI_BUILD = 0x8, + PERF_TEST_TYPE_SYM_DRV_INIT = 0x9, + PERF_TEST_TYPE_SYM_DRV_PROC = 0xA, + PERF_TEST_TYPE_SYM_DRV_FIN = 0xB, + PERF_TEST_TYPE_CRYS_HASH_INIT = 0xC, + PERF_TEST_TYPE_CRYS_HASH_UPDATE=0xD, + PERF_TEST_TYPE_CRYS_HASH_FIN = 0xE, + PERF_TEST_TYPE_CRYS_HMAC_INIT = 0xF, + PERF_TEST_TYPE_CRYS_HMAC_UPDATE=0x10, + PERF_TEST_TYPE_CRYS_HMAC_FIN = 0x11, + PERF_TEST_TYPE_CMPLT_SLEEP = 0x12, + PERF_TEST_TYPE_CRYS_AES_SET_KEY = 0x13, + PERF_TEST_TYPE_PKA_ModExp = 0x30, + PERF_TEST_TYPE_TEST_BASE = 0x100, + PERF_TEST_TYPE_MAX, + PERF_TEST_TYPE_RESERVE32 = 0x7FFFFFFF +}SaSiPalPerfType_t; + + +#ifdef LIB_PERF +#define SASI_PAL_PERF_INIT SaSi_PalPerfInit +#define SASI_PAL_PERF_OPEN_NEW_ENTRY(num, type) \ + num = SaSi_PalPerfOpenNewEntry(type) + +#define SASI_PAL_PERF_CLOSE_ENTRY(num, type) \ + SaSi_PalPerfCloseEntry(num, type) +#define SASI_PAL_PERF_DUMP SaSi_PalPerfDump +#define SASI_PAL_PERF_FIN SaSi_PalPerfFin + +/** + * @brief initialize performance test mechanism + * + * @param[in] + * * + * @return None + */ +void SaSi_PalPerfInit(void); + + +/** + * @brief opens new entry in perf buffer to record new entry + * + * @param[in] entryType - entry type (defined in ssi_pal_perf.h) to be recorded in buffer + * + * @return A non-zero value in case of failure. + */ +SaSi_PalPerfData_t SaSi_PalPerfOpenNewEntry(SaSiPalPerfType_t entryType); + + +/** + * @brief closes entry in perf buffer previously opened by SaSi_PalPerfOpenNewEntry + * + * @param[in] idx - index of the entry to be closed, the return value of SaSi_PalPerfOpenNewEntry + * @param[in] entryType - entry type (defined in ssi_pal_perf.h) to be recorded in buffer + * + * @return A non-zero value in case of failure. + */ +void SaSi_PalPerfCloseEntry(SaSi_PalPerfData_t idx, SaSiPalPerfType_t entryType); + + +/** + * @brief dumps the performance buffer + * + * @param[in] None + * + * @return None + */ +void SaSi_PalPerfDump(void); + + +/** + * @brief terminates resources used for performance tests + * + * @param[in] + * * + * @return None + */ +void SaSi_PalPerfFin(void); + +#else //LIB_PERF +#define SASI_PAL_PERF_INIT() +#define SASI_PAL_PERF_OPEN_NEW_ENTRY(num, type) (num=num) +#define SASI_PAL_PERF_CLOSE_ENTRY(num, type) +#define SASI_PAL_PERF_DUMP() +#define SASI_PAL_PERF_FIN() + + +typedef uint32_t SaSi_PalPerfData_t; + +#endif //LIB_PERF + + +#endif /*_SSI_PAL_PERF_H__*/ diff --git a/external/nrf_cc310/include/ssi_pal_perf_plat.h b/external/nrf_cc310/include/ssi_pal_perf_plat.h new file mode 100644 index 0000000..04972de --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_perf_plat.h @@ -0,0 +1,55 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef _SSI_PAL_PERF_PLAT_H__ +#define _SSI_PAL_PERF_PLAT_H__ + + + + +typedef unsigned int SaSi_PalPerfData_t; + +/** + * @brief DSM environment bug - sometimes very long write operation. + * to overcome this bug we added while to make sure write opeartion is completed + * + * @param[in] + * * + * @return None + */ +void SaSi_PalDsmWorkarround(void); + + +#endif /*_SSI_PAL_PERF_PLAT_H__*/ diff --git a/external/nrf_cc310/include/ssi_pal_sem.h b/external/nrf_cc310/include/ssi_pal_sem.h new file mode 100644 index 0000000..c371143 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_sem.h @@ -0,0 +1,123 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef _SSI_PAL_SEM_H +#define _SSI_PAL_SEM_H + +#include "ssi_pal_sem_plat.h" + +#define SASI_PAL_SEM_NO_WAIT 0 +#define SASI_PAL_SEM_FREE 1 +#define SASI_PAL_SEM_LOCKED 0 + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** +* @brief File Description: +* This file contains functions for resource management (semaphor operations). +* The functions implementations are generally just wrappers to different operating system calls. +* None of the described functions will check the input parameters so the behavior +* of the APIs in illegal parameters case is dependent on the operating system behavior. +* +*/ + + + + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/** + * @brief This function purpose is to create a semaphore. + * + * + * @param[out] aSemId - Pointer to created semaphor handle + * @param[in] aInitialVal - Initial semaphore value + * + * @return The return values is according to operating system return values. + */ +//SaSiError_t SaSi_PalSemCreate( DX_PAL_SEM *aSemId, uint32_t aInitialVal ); +#define SaSi_PalSemCreate _SaSi_PalSemCreate +/** + * @brief This function purpose is to delete a semaphore + * + * + * @param[in] aSemId - Semaphore handle + * + * @return The return values is according to operating system return values. + */ +//SaSiError_t SaSi_PalSemDelete( DX_PAL_SEM *aSemId ); +#define SaSi_PalSemDelete _SaSi_PalSemDelete +/** + * @brief This function purpose is to Wait for semaphore with aTimeOut. aTimeOut is + * specified in milliseconds. + * + * + * @param[in] aSemId - Semaphore handle + * @param[in] aTimeOut - timeout in mSec, or SASI_INFINITE + * + * @return The return values is according to operating system return values. + */ +//SaSiError_t SaSi_PalSemWait(DX_PAL_SEM aSemId, uint32_t aTimeOut); +#define SaSi_PalSemWait _SaSi_PalSemWait +/** + * @brief This function purpose is to signal the semaphore. + * + * + * @param[in] aSemId - Semaphore handle + * + * @return The return values is according to operating system return values. + */ +//SaSiError_t SaSi_PalSemGive(DX_PAL_SEM aSemId); + +#define SaSi_PalSemGive _SaSi_PalSemGive + + + + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_sem_plat.h b/external/nrf_cc310/include/ssi_pal_sem_plat.h new file mode 100644 index 0000000..8e65ce2 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_sem_plat.h @@ -0,0 +1,120 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef _SSI_PAL_SEM_INT__H +#define _SSI_PAL_SEM_INT__H + + + +#ifdef __cplusplus +extern "C" +{ +#endif +#include "ssi_pal_types.h" +/** +* @brief File Description: +* This file contains functions for resource management (semaphor operations). +* The functions implementations are generally just wrappers to different operating system calls. +* None of the described functions will check the input parameters so the behavior +* of the APIs in illegal parameters case is dependent on the operating system behavior. +* +*/ + +typedef int DX_PAL_SEM; + + + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/** + * @brief This function purpose is to create a semaphore. + * + * + * @param[out] aSemId - Pointer to created semaphor handle + * @param[in] aInitialVal - Initial semaphore value + * + * @return The return values is according to operating system return values. + */ +SaSiError_t _SaSi_PalSemCreate( DX_PAL_SEM *aSemId, uint32_t aInitialVal ); + +#define _SaSi_PalSemCreate(aSemId,aInitialVal) SASI_SUCCESS +/** + * @brief This function purpose is to delete a semaphore + * + * + * @param[in] aSemId - Semaphore handle + * + * @return The return values is according to operating system return values. + */ +SaSiError_t _SaSi_PalSemDelete( DX_PAL_SEM *aSemId ); + +#define _SaSi_PalSemDelete( aSemId ) SASI_SUCCESS +/** + * @brief This function purpose is to Wait for semaphore with aTimeOut. aTimeOut is + * specified in milliseconds. + * + * + * @param[in] aSemId - Semaphore handle + * @param[in] aTimeOut - timeout in mSec, or SASI_INFINITE + * + * @return The return values is according to operating system return values. + */ +SaSiError_t _SaSi_PalSemWait(DX_PAL_SEM aSemId, uint32_t aTimeOut); + +#define _SaSi_PalSemWait(aSemId, aTimeOut) SASI_SUCCESS +/** + * @brief This function purpose is to signal the semaphore. + * + * + * @param[in] aSemId - Semaphore handle + * + * @return The return values is according to operating system return values. + */ +SaSiError_t _SaSi_PalSemGive(DX_PAL_SEM aSemId); + +#define _SaSi_PalSemGive(aSemId) SASI_SUCCESS + + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_trng.h b/external/nrf_cc310/include/ssi_pal_trng.h new file mode 100644 index 0000000..029bb0a --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_trng.h @@ -0,0 +1,66 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef _SSI_PAL_TRNG_H +#define _SSI_PAL_TRNG_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/** + * @brief This function purpose is to get TRNG characterization parameters. + * + * + * @return Zero on success. + * @return A non-zero value on failure. + */ +SaSiError_t SaSi_PalTrngParameterGet(uint32_t *SubSamplingRatio /*!< [out] TRNG characterization parameters, array size = 4. */); + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310/include/ssi_pal_types.h b/external/nrf_cc310/include/ssi_pal_types.h new file mode 100644 index 0000000..ed9c333 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_types.h @@ -0,0 +1,115 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains the platform dependent definitions and types. +@defgroup ssi_pal_types CryptoCell PAL platform dependant types +@{ +@ingroup ssi_pal +*/ + +#ifndef SSI_PAL_TYPES_H +#define SSI_PAL_TYPES_H + +#include "ssi_pal_types_plat.h" + +/*! Boolean definition.*/ +typedef enum { + /*! Boolean false definition.*/ + SASI_FALSE = 0, + /*! Boolean true definition.*/ + SASI_TRUE = 1 +} SaSiBool; + +/*! Success definition. */ +#define SASI_SUCCESS 0UL +/*! Failure definition. */ +#define SASI_FAIL 1UL + +/*! Defintion of 1KB in bytes. */ +#define SASI_1K_SIZE_IN_BYTES 1024 +/*! Defintion of number of bits in a byte. */ +#define SASI_BITS_IN_BYTE 8 +/*! Defintion of number of bits in a 32bits word. */ +#define SASI_BITS_IN_32BIT_WORD 32 +/*! Defintion of number of bytes in a 32bits word. */ +#define SASI_32BIT_WORD_SIZE (sizeof(uint32_t)) + +/*! Success (OK) defintion. */ +#define SASI_OK SASI_SUCCESS + +/*! Macro that handles unused parameters in the code (to avoid compilation warnings). */ +#define SASI_UNUSED_PARAM(prm) ((void)prm) + +/*! Maximal uint32 value.*/ +#define SASI_MAX_UINT32_VAL (0xFFFFFFFF) + + +/* Minimum and Maximum macros */ +#ifdef min +/*! Definition for minimum. */ +#define CRYS_MIN(a,b) min( a , b ) +#else +/*! Definition for minimum. */ +#define CRYS_MIN( a , b ) ( ( (a) < (b) ) ? (a) : (b) ) +#endif + +#ifdef max +/*! Definition for maximum. */ +#define CRYS_MAX(a,b) max( a , b ) +#else +/*! Definition for maximum. */ +#define CRYS_MAX( a , b ) ( ( (a) > (b) ) ? (a) : (b) ) +#endif + +/*! Macro that calculates number of full bytes from bits (i.e. 7 bits are 1 byte). */ +#define CALC_FULL_BYTES(numBits) (((numBits) + (SASI_BITS_IN_BYTE -1))/SASI_BITS_IN_BYTE) +/*! Macro that calculates number of full 32bits words from bits (i.e. 31 bits are 1 word). */ +#define CALC_FULL_32BIT_WORDS(numBits) (((numBits) + (SASI_BITS_IN_32BIT_WORD -1))/SASI_BITS_IN_32BIT_WORD) +/*! Macro that calculates number of full 32bits words from bytes (i.e. 3 bytes are 1 word). */ +#define CALC_32BIT_WORDS_FROM_BYTES(sizeBytes) (((sizeBytes) + SASI_32BIT_WORD_SIZE - 1) / SASI_32BIT_WORD_SIZE) +/*! Macro that round up bits to 32bits words. */ +#define ROUNDUP_BITS_TO_32BIT_WORD(numBits) (CALC_FULL_32BIT_WORDS(numBits)*SASI_BITS_IN_32BIT_WORD) +/*! Macro that round up bits to bytes. */ +#define ROUNDUP_BITS_TO_BYTES(numBits) (CALC_FULL_BYTES(numBits)*SASI_BITS_IN_BYTE) +/*! Macro that round up bytes to 32bits words. */ +#define ROUNDUP_BYTES_TO_32BIT_WORD(numBytes) (SASI_32BIT_WORD_SIZE*(((numBytes)+SASI_32BIT_WORD_SIZE-1)/SASI_32BIT_WORD_SIZE)) + + +/** +@} + */ +#endif diff --git a/external/nrf_cc310/include/ssi_pal_types_plat.h b/external/nrf_cc310/include/ssi_pal_types_plat.h new file mode 100644 index 0000000..50e7e40 --- /dev/null +++ b/external/nrf_cc310/include/ssi_pal_types_plat.h @@ -0,0 +1,57 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! @file +@brief This file contains basic type definitions that are platform dependent. +*/ +#ifndef SSI_PAL_TYPES_PLAT_H +#define SSI_PAL_TYPES_PLAT_H +/* Host specific types for standard (ISO-C99) compilant platforms */ + +#include +#include +#include + +typedef uintptr_t SaSiVirtAddr_t; +typedef uint32_t SaSiBool_t; +typedef uint32_t SaSiStatus; + +#define SaSiError_t SaSiStatus +#define SASI_INFINITE 0xFFFFFFFF + +#define CEXPORT_C +#define CIMPORT_C + +#endif /*SSI_PAL_TYPES_PLAT_H*/ diff --git a/external/nrf_cc310/include/ssi_pka_hw_plat_defs.h b/external/nrf_cc310/include/ssi_pka_hw_plat_defs.h new file mode 100644 index 0000000..1ea406c --- /dev/null +++ b/external/nrf_cc310/include/ssi_pka_hw_plat_defs.h @@ -0,0 +1,77 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef PKA_HW_PLAT_DEFS_H +#define PKA_HW_PLAT_DEFS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief Contains the enums and definitions that are used in the PKA code (definitions that are platform dependent). +@defgroup ssi_pka_hw_plat_defs CryptoCell PKA specific types and definitions +@{ +@ingroup cryptocell_pka + +*/ + +/*! Size of PKA engine word.*/ +#define SASI_PKA_WORD_SIZE_IN_BITS 64 +/*! Maximal supported modulus size in bits. */ +#define CRYS_SRP_MAX_MODULUS_SIZE_IN_BITS 3072 +/*! Maximal supported modulus size in RSA in bits. */ +#define CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS 2048 +/*! Maximal supported key generation size in RSA in bits. */ +#define CRYS_RSA_MAX_KEY_GENERATION_HW_SIZE_BITS 2048 + +/*! PKA operations maximal count of extra bits. */ +#define PKA_EXTRA_BITS 8 +/*! PKA operations number of memory registers. */ +#define PKA_MAX_COUNT_OF_PHYS_MEM_REGS 32 + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif //PKA_HW_PLAT_DEFS_H + + diff --git a/external/nrf_cc310/include/ssi_regs.h b/external/nrf_cc310/include/ssi_regs.h new file mode 100644 index 0000000..82290ba --- /dev/null +++ b/external/nrf_cc310/include/ssi_regs.h @@ -0,0 +1,166 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +/*! + * @file + * @brief Macro definitions for accessing ARM TrustZone CryptoCell register space. + */ + +#ifndef _SSI_REGS_H_ +#define _SSI_REGS_H_ + +#include "ssi_bitops.h" + +/* Register Offset macro */ +#define SASI_REG_OFFSET(unit_name, reg_name) \ + (DX_BASE_ ## unit_name + DX_ ## reg_name ## _REG_OFFSET) + +#define SASI_REG_BIT_SHIFT(reg_name, field_name) \ + (DX_ ## reg_name ## _ ## field_name ## _BIT_SHIFT) + +/* Register Offset macros (from registers base address in host) */ +#if defined(DX_CC_REE) || defined(DX_CC_TEE) || defined(DX_CONFIG_IOT_SUPPORTED) + +#include "dx_reg_base_host.h" + +/* Indexed GPR offset macros - note the (not original) preprocessor tricks...*/ +/* (Using the macro without the "_" prefix is allowed with another macro * + * as the gpr_idx) */ +#define _SEP_HOST_GPR_REG_OFFSET(gpr_idx) \ + SASI_REG_OFFSET(HOST_RGF, HOST_SEP_HOST_GPR ## gpr_idx) +#define SEP_HOST_GPR_REG_OFFSET(gpr_idx) _SEP_HOST_GPR_REG_OFFSET(gpr_idx) +#define _HOST_SEP_GPR_REG_OFFSET(gpr_idx) \ + SASI_REG_OFFSET(HOST_RGF, HOST_HOST_SEP_GPR ## gpr_idx) +#define HOST_SEP_GPR_REG_OFFSET(gpr_idx) _HOST_SEP_GPR_REG_OFFSET(gpr_idx) + +/* GPR IRQ bit shift/mask by GPR index */ +#define _SEP_HOST_GPR_IRQ_SHIFT(gpr_idx) \ + DX_HOST_IRR_SEP_HOST_GPR ## gpr_idx ## _INT_BIT_SHIFT +#define SEP_HOST_GPR_IRQ_SHIFT(gpr_idx) \ + _SEP_HOST_GPR_IRQ_SHIFT(gpr_idx) +#define SEP_HOST_GPR_IRQ_MASK(gpr_idx) \ + (1 << SEP_HOST_GPR_IRQ_CAUSE_SHIFT(gpr_idx)) + +/* Read-Modify-Write a field of a register */ +#define MODIFY_REGISTER_FLD(unitName, regName, fldName, fldVal) \ +do { \ + uint32_t regVal; \ + regVal = READ_REGISTER(SASI_REG_ADDR(unitName, regName)); \ + SASI_REG_FLD_SET(unitName, regName, fldName, regVal, fldVal); \ + WRITE_REGISTER(SASI_REG_ADDR(unitName, regName), regVal); \ +} while (0) + +#elif defined(DX_CC_SEP) + +#include "dx_reg_base_sep.h" + +/* We only provide this macro for SEP code because other platforms require usage + of (mapping base + offset), i.e., use of SASI_REG_OFFSET */ +/* PLEASE AVOID USING THIS MACRO FOR NEW SEP CODE. USE THE OFFSET MACROS. */ +#define SASI_REG_ADDR(unit_name, reg_name) \ + (DX_BASE_CC_PERIF + DX_BASE_ ## unit_name + \ + DX_ ## reg_name ## _REG_OFFSET) + +/* Indexed GPR address macros - note the (not original) preprocessor tricks...*/ +/* (Using the macro without the "_" prefix is allowed with another macro * + * as the gpr_idx) */ +#define _SEP_HOST_GPR_REG_ADDR(gpr_idx) \ + SASI_REG_ADDR(SEP_RGF, SEP_SEP_HOST_GPR ## gpr_idx) +#define SEP_HOST_GPR_REG_ADDR(gpr_idx) _SEP_HOST_GPR_REG_ADDR(gpr_idx) +#define _HOST_SEP_GPR_REG_ADDR(gpr_idx) \ + SASI_REG_ADDR(SEP_RGF, SEP_HOST_SEP_GPR ## gpr_idx) +#define HOST_SEP_GPR_REG_ADDR(gpr_idx) _HOST_SEP_GPR_REG_ADDR(gpr_idx) + +#else +#error Execution domain is not DX_CC_SEP/DX_CC_REE/DX_CC_TEE/DX_CONFIG_IOT_SUPPORTED +#endif + +/* Registers address macros for ENV registers (development FPGA only) */ +#ifdef DX_BASE_ENV_REGS + +#ifndef DX_CC_SEP /* Irrelevant for SeP code */ +/* This offset should be added to mapping address of DX_BASE_ENV_REGS */ +#define SASI_ENV_REG_OFFSET(reg_name) (DX_ENV_ ## reg_name ## _REG_OFFSET) +#endif + +#endif /*DX_BASE_ENV_REGS*/ + +/* Bit fields access */ +#define SASI_REG_FLD_GET(unit_name, reg_name, fld_name, reg_val) \ + (DX_ ## reg_name ## _ ## fld_name ## _BIT_SIZE == 0x20 ? \ + reg_val /*!< \internal Optimization for 32b fields */ : \ + BITFIELD_GET(reg_val, DX_ ## reg_name ## _ ## fld_name ## _BIT_SHIFT, \ + DX_ ## reg_name ## _ ## fld_name ## _BIT_SIZE)) + +/* Bit fields access */ +#define SASI2_REG_FLD_GET(unit_name, reg_name, fld_name, reg_val) \ + (SASI_ ## reg_name ## _ ## fld_name ## _BIT_SIZE == 0x20 ? \ + reg_val /*!< \internal Optimization for 32b fields */ : \ + BITFIELD_GET(reg_val, SASI_ ## reg_name ## _ ## fld_name ## _BIT_SHIFT, \ + SASI_ ## reg_name ## _ ## fld_name ## _BIT_SIZE)) + +#define SASI_REG_FLD_SET( \ + unit_name, reg_name, fld_name, reg_shadow_var, new_fld_val) \ +do { \ + if (DX_ ## reg_name ## _ ## fld_name ## _BIT_SIZE == 0x20) \ + reg_shadow_var = new_fld_val; /*!< \internal Optimization for 32b fields */\ + else \ + BITFIELD_SET(reg_shadow_var, \ + DX_ ## reg_name ## _ ## fld_name ## _BIT_SHIFT, \ + DX_ ## reg_name ## _ ## fld_name ## _BIT_SIZE, \ + new_fld_val); \ +} while (0) + +#define SASI2_REG_FLD_SET( \ + unit_name, reg_name, fld_name, reg_shadow_var, new_fld_val) \ +do { \ + if (SASI_ ## reg_name ## _ ## fld_name ## _BIT_SIZE == 0x20) \ + reg_shadow_var = new_fld_val; /*!< \internal Optimization for 32b fields */\ + else \ + BITFIELD_SET(reg_shadow_var, \ + SASI_ ## reg_name ## _ ## fld_name ## _BIT_SHIFT, \ + SASI_ ## reg_name ## _ ## fld_name ## _BIT_SIZE, \ + new_fld_val); \ +} while (0) + +/* Usage example: + uint32_t reg_shadow = READ_REGISTER(SASI_REG_ADDR(CRY_KERNEL,AES_CONTROL)); + SASI_REG_FLD_SET(CRY_KERNEL,AES_CONTROL,NK_KEY0,reg_shadow, 3); + SASI_REG_FLD_SET(CRY_KERNEL,AES_CONTROL,NK_KEY1,reg_shadow, 1); + WRITE_REGISTER(SASI_REG_ADDR(CRY_KERNEL,AES_CONTROL), reg_shadow); + */ + +#endif /*_SSI_REGS_H_*/ diff --git a/external/nrf_cc310/include/ssi_sram_map.h b/external/nrf_cc310/include/ssi_sram_map.h new file mode 100644 index 0000000..b409598 --- /dev/null +++ b/external/nrf_cc310/include/ssi_sram_map.h @@ -0,0 +1,71 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef _SSI_SRAM_MAP_H_ +#define _SSI_SRAM_MAP_H_ + +/*! +@file +@brief This file contains internal SRAM mapping definitions. +@defgroup ssi_sram_map CryptoCell SRAM mapping APIs +@{ +@ingroup cryptocell_api + +*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! PKA base address in the PKA SRAM. */ +#define SASI_SRAM_PKA_BASE_ADDRESS 0x0 +/*! PKA SRAM size in KB. */ +#define SASI_PKA_SRAM_SIZE_IN_KBYTES 4 + +/*! RND SRAM address. */ +#define SASI_SRAM_RND_HW_DMA_ADDRESS 0x0 +/*! Addresses 0K-2KB in SRAM reserved for RND operations. */ +#define SASI_SRAM_RND_MAX_SIZE 0x800 +/*! SRAM maximal size. */ +#define SASI_SRAM_MAX_SIZE 0x1000 + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /*_SSI_SRAM_MAP_H_*/ diff --git a/external/nrf_cc310/include/ssi_util_defs.h b/external/nrf_cc310/include/ssi_util_defs.h new file mode 100644 index 0000000..f6e7746 --- /dev/null +++ b/external/nrf_cc310/include/ssi_util_defs.h @@ -0,0 +1,93 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef _SSI_UTIL_DEFS_H +#define _SSI_UTIL_DEFS_H + +/*! +@defgroup ssi_utils CryptoCell utility APIs +@{ +@ingroup cryptocell_api +@brief This group is the utility apis group +@} + +@file +@brief This file contains CryptoCell Util general definitions. +@defgroup ssi_utils_defs CryptoCell utils general definitions +@{ +@ingroup ssi_utils + +*/ + + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ssi_pal_types_plat.h" +#include "ssi_util_key_derivation_defs.h" + + +/****************************************************************************** +* DEFINITIONS +******************************************************************************/ +/*! Supported AES key size in bits. */ +#define SASI_UTIL_AES_128BIT_SIZE 16 // same as SEP_AES_128_BIT_KEY_SIZE +/*****************************************/ +/* CMAC derive key definitions*/ +/*****************************************/ +/*! Minimal data size for CMAC derivation operation. */ +#define SASI_UTIL_CMAC_DERV_MIN_DATA_IN_SIZE SASI_UTIL_FIX_DATA_MIN_SIZE_IN_BYTES+2 +/*! Maximal data size for CMAC derivation operation. */ +#define SASI_UTIL_CMAC_DERV_MAX_DATA_IN_SIZE SASI_UTIL_MAX_KDF_SIZE_IN_BYTES +/*! AES CMAC result size in bytes. */ +#define SASI_UTIL_AES_CMAC_RESULT_SIZE_IN_BYTES 0x10UL +/*! AES CMAC result size in words. */ +#define SASI_UTIL_AES_CMAC_RESULT_SIZE_IN_WORDS (SASI_UTIL_AES_CMAC_RESULT_SIZE_IN_BYTES/4) + +/*! Util Error type. */ +typedef uint32_t SaSiUtilError_t; +/*! Defines the CMAC result buffer. */ +typedef uint8_t SaSiUtilAesCmacResult_t[SASI_UTIL_AES_CMAC_RESULT_SIZE_IN_BYTES]; + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /*_SSI_UTIL_DEFS_H*/ diff --git a/external/nrf_cc310/include/ssi_util_error.h b/external/nrf_cc310/include/ssi_util_error.h new file mode 100644 index 0000000..e932a52 --- /dev/null +++ b/external/nrf_cc310/include/ssi_util_error.h @@ -0,0 +1,97 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef _SSI_UTIL_ERROR_H +#define _SSI_UTIL_ERROR_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the UTIL module errors. +@defgroup ssi_utils_errors CryptoCell utils error definitions +@{ +@ingroup ssi_utils + +*/ + +/***********************/ +/* Util return codes */ +/***********************/ + +/*! Success definition. */ +#define SASI_UTIL_OK 0x00UL +/*! Error base number definition. */ +#define SASI_UTIL_MODULE_ERROR_BASE 0x80000000 + +/*! Illegal key type. */ +#define SASI_UTIL_INVALID_KEY_TYPE (SASI_UTIL_MODULE_ERROR_BASE + 0x00UL) +/*! Illegal data in pointer. */ +#define SASI_UTIL_DATA_IN_POINTER_INVALID_ERROR (SASI_UTIL_MODULE_ERROR_BASE + 0x01UL) +/*! Illegal data in size. */ +#define SASI_UTIL_DATA_IN_SIZE_INVALID_ERROR (SASI_UTIL_MODULE_ERROR_BASE + 0x02UL) +/*! Illegal data out pointer. */ +#define SASI_UTIL_DATA_OUT_POINTER_INVALID_ERROR (SASI_UTIL_MODULE_ERROR_BASE + 0x03UL) +/*! Illegal data out size. */ +#define SASI_UTIL_DATA_OUT_SIZE_INVALID_ERROR (SASI_UTIL_MODULE_ERROR_BASE + 0x04UL) +/*! Fatal error. */ +#define SASI_UTIL_FATAL_ERROR (SASI_UTIL_MODULE_ERROR_BASE + 0x05UL) +/*! Illegal parameters. */ +#define SASI_UTIL_ILLEGAL_PARAMS_ERROR (SASI_UTIL_MODULE_ERROR_BASE + 0x06UL) +/*! Invalid address given. */ +#define SASI_UTIL_BAD_ADDR_ERROR (SASI_UTIL_MODULE_ERROR_BASE + 0x07UL) +/*! Illegal domain for endorsement key. */ +#define SASI_UTIL_EK_DOMAIN_INVALID_ERROR (SASI_UTIL_MODULE_ERROR_BASE + 0x08UL) +/*! Kdr is not valid. */ +#define SASI_UTIL_KDR_INVALID_ERROR (SASI_UTIL_MODULE_ERROR_BASE + 0x09UL) +/*! LCS is not valid. */ +#define SASI_UTIL_LCS_INVALID_ERROR (SASI_UTIL_MODULE_ERROR_BASE + 0x0AUL) +/*! session key is not valid. */ +#define SASI_UTIL_SESSION_KEY_ERROR (SASI_UTIL_MODULE_ERROR_BASE + 0x0BUL) +/*! Illegal user key size. */ +#define SASI_UTIL_INVALID_USER_KEY_SIZE (SASI_UTIL_MODULE_ERROR_BASE + 0x0DUL) +/*! Illegal LCS for the required operation. */ +#define SASI_UTIL_ILLEGAL_LCS_FOR_OPERATION_ERR (SASI_UTIL_MODULE_ERROR_BASE + 0x0EUL) + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /*_SSI_UTIL_ERROR_H*/ diff --git a/external/nrf_cc310/include/ssi_util_key_derivation.h b/external/nrf_cc310/include/ssi_util_key_derivation.h new file mode 100644 index 0000000..ac39184 --- /dev/null +++ b/external/nrf_cc310/include/ssi_util_key_derivation.h @@ -0,0 +1,107 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef _SSI_UTIL_KEY_DERIVATION_H +#define _SSI_UTIL_KEY_DERIVATION_H + +/*! +@file +@brief This module defines the API that supports Key derivation function as specified + in [SP800-108] in section "KDF in Counter Mode". +@defgroup ssi_utils_key_derivation CryptoCell utility key derivation APIs +@{ +@ingroup ssi_utils + +*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ssi_util_defs.h" +#include "ssi_util_key_derivation_defs.h" +#include "ssi_aes.h" + +/****************************************************************************** +* DEFINITIONS +******************************************************************************/ + +/*! Input key derivation type. */ +typedef enum { + /*! User's key.*/ + SASI_UTIL_USER_KEY = 0, + /*! Root key (Kdr).*/ + SASI_UTIL_ROOT_KEY = 1, + /*! Reserved.*/ + SASI_UTIL_END_OF_KEY_TYPE = 0x7FFFFFFF +}SaSiUtilKeyType_t; + + +/*! +@brief The key derivation function is as specified in [SP800-108] in section "KDF in Counter Mode". + The derivation is based on length l, label L, context C and derivation key Ki. + AES-CMAC is used as the pseudorandom function (PRF). + +@return SASI_UTIL_OK on success. +@return A non-zero value from ssi_util_error.h on failure. +*/ + +/* A key derivation functions can iterates n times until l bits of keying material are generated. + For each of the iteration of the PRF, i=1 to n, do: + result(0) = 0; + K(i) = PRF (Ki, [i] || Label || 0x00 || Context || length); + results(i) = result(i-1) || K(i); + + concisely, result(i) = K(i) || k(i-1) || .... || k(0)*/ +SaSiUtilError_t SaSi_UtilKeyDerivation( + SaSiUtilKeyType_t keyType, /*!< [in] The key type that is used as an input to a key derivation function. + Can be one of: SASI_UTIL_USER_KEY or SASI_UTIL_ROOT_KEY. */ + SaSiAesUserKeyData_t *pUserKey, /*!< [in] A pointer to the user's key buffer (in case of SASI_UTIL_USER_KEY). */ + const uint8_t *pLabel, /*!< [in] A string that identifies the purpose for the derived keying material.*/ + size_t labelSize, /*!< [in] The label size should be in range of 1 to 64 bytes length. */ + const uint8_t *pContextData, /*!< [in] A binary string containing the information related to the derived keying material. */ + size_t contextSize, /*!< [in] The context size should be in range of 1 to 64 bytes length. */ + uint8_t *pDerivedKey, /*!< [out] Keying material output (MUST be atleast the size of derivedKeySize). */ + size_t derivedKeySize /*!< [in] Size of the derived keying material in bytes (limited to 4080 bytes). */ + ); + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /*_SSI_UTIL_KEY_DERIVATION_H*/ diff --git a/external/nrf_cc310/include/ssi_util_key_derivation_defs.h b/external/nrf_cc310/include/ssi_util_key_derivation_defs.h new file mode 100644 index 0000000..10a8869 --- /dev/null +++ b/external/nrf_cc310/include/ssi_util_key_derivation_defs.h @@ -0,0 +1,81 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef _SSI_UTIL_KEY_DERIVATION_DEFS_H +#define _SSI_UTIL_KEY_DERIVATION_DEFS_H + +/*! +@file +@brief This file contains the definitions for the key derivation API. +@defgroup ssi_utils_key_defs CryptoCell utils general key definitions +@{ +@ingroup ssi_utils + +*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************************************** +* DEFINITIONS +******************************************************************************/ + +/*! Maximal label length in bytes. */ +#define SASI_UTIL_MAX_LABEL_LENGTH_IN_BYTES 64 +/*! Maximal context length in bytes. */ +#define SASI_UTIL_MAX_CONTEXT_LENGTH_IN_BYTES 64 + +/*! Minimal fixed data size in bytes. */ +#define SASI_UTIL_FIX_DATA_MIN_SIZE_IN_BYTES 3 /*!< \internal counter, 0x00, lengt(-0xff) */ +/*! Maximal fixed data size in bytes. */ +#define SASI_UTIL_FIX_DATA_MAX_SIZE_IN_BYTES 4 /*!< \internal counter, 0x00, lengt(0x100-0xff0) */ + +/*! Maximal derived key material size in bytes. */ +#define SASI_UTIL_MAX_KDF_SIZE_IN_BYTES (SASI_UTIL_MAX_LABEL_LENGTH_IN_BYTES+ \ + SASI_UTIL_MAX_CONTEXT_LENGTH_IN_BYTES+SASI_UTIL_FIX_DATA_MAX_SIZE_IN_BYTES) + +/*! Maximal derived key size in bytes. */ +#define SASI_UTIL_MAX_DERIVED_KEY_SIZE_IN_BYTES 4080 + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /*_SSI_UTIL_KEY_DERIVATION_DEFS_H*/ + diff --git a/external/nrf_cc310/lib/cortex-m4/hard-float/libnrf_cc310_0.9.13.a b/external/nrf_cc310/lib/cortex-m4/hard-float/libnrf_cc310_0.9.13.a new file mode 100644 index 0000000..6bf8d14 Binary files /dev/null and b/external/nrf_cc310/lib/cortex-m4/hard-float/libnrf_cc310_0.9.13.a differ diff --git a/external/nrf_cc310/lib/cortex-m4/hard-float/no-interrupts/libnrf_cc310_0.9.13.a b/external/nrf_cc310/lib/cortex-m4/hard-float/no-interrupts/libnrf_cc310_0.9.13.a new file mode 100644 index 0000000..13e6f5e Binary files /dev/null and b/external/nrf_cc310/lib/cortex-m4/hard-float/no-interrupts/libnrf_cc310_0.9.13.a differ diff --git a/external/nrf_cc310/lib/cortex-m4/hard-float/short-wchar/libnrf_cc310_0.9.13.a b/external/nrf_cc310/lib/cortex-m4/hard-float/short-wchar/libnrf_cc310_0.9.13.a new file mode 100644 index 0000000..fa86709 Binary files /dev/null and b/external/nrf_cc310/lib/cortex-m4/hard-float/short-wchar/libnrf_cc310_0.9.13.a differ diff --git a/external/nrf_cc310/lib/cortex-m4/hard-float/short-wchar/no-interrupts/libnrf_cc310_0.9.13.a b/external/nrf_cc310/lib/cortex-m4/hard-float/short-wchar/no-interrupts/libnrf_cc310_0.9.13.a new file mode 100644 index 0000000..ddb7521 Binary files /dev/null and b/external/nrf_cc310/lib/cortex-m4/hard-float/short-wchar/no-interrupts/libnrf_cc310_0.9.13.a differ diff --git a/external/nrf_cc310/lib/cortex-m4/hard-float/short-wchar/no-interrupts/nrf_cc310_0.9.13.lib b/external/nrf_cc310/lib/cortex-m4/hard-float/short-wchar/no-interrupts/nrf_cc310_0.9.13.lib new file mode 100644 index 0000000..ddb7521 Binary files /dev/null and b/external/nrf_cc310/lib/cortex-m4/hard-float/short-wchar/no-interrupts/nrf_cc310_0.9.13.lib differ diff --git a/external/nrf_cc310/lib/cortex-m4/hard-float/short-wchar/nrf_cc310_0.9.13.lib b/external/nrf_cc310/lib/cortex-m4/hard-float/short-wchar/nrf_cc310_0.9.13.lib new file mode 100644 index 0000000..fa86709 Binary files /dev/null and b/external/nrf_cc310/lib/cortex-m4/hard-float/short-wchar/nrf_cc310_0.9.13.lib differ diff --git a/external/nrf_cc310/lib/cortex-m4/soft-float/libnrf_cc310_0.9.13.a b/external/nrf_cc310/lib/cortex-m4/soft-float/libnrf_cc310_0.9.13.a new file mode 100644 index 0000000..35b1783 Binary files /dev/null and b/external/nrf_cc310/lib/cortex-m4/soft-float/libnrf_cc310_0.9.13.a differ diff --git a/external/nrf_cc310/lib/cortex-m4/soft-float/no-interrupts/libnrf_cc310_0.9.13.a b/external/nrf_cc310/lib/cortex-m4/soft-float/no-interrupts/libnrf_cc310_0.9.13.a new file mode 100644 index 0000000..82385ba Binary files /dev/null and b/external/nrf_cc310/lib/cortex-m4/soft-float/no-interrupts/libnrf_cc310_0.9.13.a differ diff --git a/external/nrf_cc310/lib/cortex-m4/soft-float/short-wchar/libnrf_cc310_0.9.13.a b/external/nrf_cc310/lib/cortex-m4/soft-float/short-wchar/libnrf_cc310_0.9.13.a new file mode 100644 index 0000000..1eff1be Binary files /dev/null and b/external/nrf_cc310/lib/cortex-m4/soft-float/short-wchar/libnrf_cc310_0.9.13.a differ diff --git a/external/nrf_cc310/lib/cortex-m4/soft-float/short-wchar/no-interrupts/libnrf_cc310_0.9.13.a b/external/nrf_cc310/lib/cortex-m4/soft-float/short-wchar/no-interrupts/libnrf_cc310_0.9.13.a new file mode 100644 index 0000000..0c0af4b Binary files /dev/null and b/external/nrf_cc310/lib/cortex-m4/soft-float/short-wchar/no-interrupts/libnrf_cc310_0.9.13.a differ diff --git a/external/nrf_cc310/lib/cortex-m4/soft-float/short-wchar/no-interrupts/nrf_cc310_0.9.13.lib b/external/nrf_cc310/lib/cortex-m4/soft-float/short-wchar/no-interrupts/nrf_cc310_0.9.13.lib new file mode 100644 index 0000000..0c0af4b Binary files /dev/null and b/external/nrf_cc310/lib/cortex-m4/soft-float/short-wchar/no-interrupts/nrf_cc310_0.9.13.lib differ diff --git a/external/nrf_cc310/lib/cortex-m4/soft-float/short-wchar/nrf_cc310_0.9.13.lib b/external/nrf_cc310/lib/cortex-m4/soft-float/short-wchar/nrf_cc310_0.9.13.lib new file mode 100644 index 0000000..1eff1be Binary files /dev/null and b/external/nrf_cc310/lib/cortex-m4/soft-float/short-wchar/nrf_cc310_0.9.13.lib differ diff --git a/external/nrf_cc310/lib/license.txt b/external/nrf_cc310/lib/license.txt new file mode 100644 index 0000000..d45aeb3 --- /dev/null +++ b/external/nrf_cc310/lib/license.txt @@ -0,0 +1,28 @@ +ARM Object Code and Header Files License +Version 1.0 + +Redistribution. + +Redistribution and use of object code, header files, and +documentation, without modification, are permitted provided that the following +conditions are met: +1) Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. +2) Unless to the extent explicitly permitted by law, no reverse + engineering, decompilation, or disassembly of is permitted. +3) Redistribution and use is permitted solely for the purpose of + developing or executing applications that are targeted for use + on an ARM-based product. + + DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/external/nrf_cc310/license.txt b/external/nrf_cc310/license.txt new file mode 100644 index 0000000..d45aeb3 --- /dev/null +++ b/external/nrf_cc310/license.txt @@ -0,0 +1,28 @@ +ARM Object Code and Header Files License +Version 1.0 + +Redistribution. + +Redistribution and use of object code, header files, and +documentation, without modification, are permitted provided that the following +conditions are met: +1) Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. +2) Unless to the extent explicitly permitted by law, no reverse + engineering, decompilation, or disassembly of is permitted. +3) Redistribution and use is permitted solely for the purpose of + developing or executing applications that are targeted for use + on an ARM-based product. + + DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/external/nrf_cc310_bl/include/crys_aesccm.h b/external/nrf_cc310_bl/include/crys_aesccm.h new file mode 100644 index 0000000..c6a3392 --- /dev/null +++ b/external/nrf_cc310_bl/include/crys_aesccm.h @@ -0,0 +1,315 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_AESCCM_H +#define CRYS_AESCCM_H + +#include "ssi_pal_types.h" +#include "crys_error.h" + +#include "ssi_aes.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains all of the enums and definitions that are used for the CRYS AESCCM APIs, as well as the APIs themselves. +The API supports AES-CCM and AES-CCM* as defined in ieee-802.15.4. +@defgroup crys_aesccm CryptoCell AES-CCM APIs +@{ +@ingroup cryptocell_api + + +@note +Regarding the AES-CCM*, the API supports only AES-CCM* as defined in ieee-802.15.4-2011; With the instantiations as defined in B.3.2 and the nonce as defined in 7.3.2. +in case of AES-CCM* the flow should be as follows: +
    • AES-CCM* integrated
    • +
      • CRYS_AESCCMStar_NonceGenerate
      • +
      • CRYS_AESCCMStar
    +
    • AES-CCM* non-integrated
    • +
      • CRYS_AESCCMStar_NonceGenerate
      • +
      • CRYS_AESCCMStar_Init
      • +
      • CRYS_AESCCM_BlockAdata
      • +
      • CRYS_AESCCM_BlockTextData
      • +
      • CRYS_AESCCM_Finish
    +*/ + +/************************ Defines ******************************/ + +/*! AES CCM context size in words.*/ +#define CRYS_AESCCM_USER_CTX_SIZE_IN_WORDS (152/4) + +/*! AES CCM maximal key size in words. */ +#define CRYS_AESCCM_KEY_SIZE_WORDS 8 + +/* nonce and AESCCM-MAC sizes definitions */ +/*! AES CCM NONCE minimal size in bytes. */ +#define CRYS_AESCCM_NONCE_MIN_SIZE_BYTES 7 +/*! AES CCM NONCE maximal size in bytes. */ +#define CRYS_AESCCM_NONCE_MAX_SIZE_BYTES 13 +/*! AES CCM MAC minimal size in bytes..*/ +#define CRYS_AESCCM_MAC_MIN_SIZE_BYTES 4 +/*! AES CCM MAC maximal size in bytes. */ +#define CRYS_AESCCM_MAC_MAX_SIZE_BYTES 16 + +/*! AES CCM star NONCE size in bytes. */ +#define CRYS_AESCCM_STAR_NONCE_SIZE_BYTES 13 +/*! AES CCM star source address size in bytes. */ +#define CRYS_AESCCM_STAR_SOURCE_ADDRESS_SIZE_BYTES 8 + +/*! AES CCM mode - CCM. */ +#define CRYS_AESCCM_MODE_CCM 0 +/*! AES CCM mode - CCM STAR. */ +#define CRYS_AESCCM_MODE_STAR 1 + + +/************************ Typedefs ****************************/ +/*! AES CCM key sizes. */ +typedef enum { + /*! Key size 128 bits. */ + CRYS_AES_Key128BitSize = 0, + /*! Key size 192 bits. */ + CRYS_AES_Key192BitSize = 1, + /*! Key size 256 bits. */ + CRYS_AES_Key256BitSize = 2, + /*! Key size 512 bits. */ + CRYS_AES_Key512BitSize = 3, + /*! Number of optional key sizes. */ + CRYS_AES_KeySizeNumOfOptions, + /*! Reserved. */ + CRYS_AES_KeySizeLast = 0x7FFFFFFF, + +}CRYS_AESCCM_KeySize_t; + +/*! AES_CCM key buffer definition.*/ +typedef uint8_t CRYS_AESCCM_Key_t[CRYS_AESCCM_KEY_SIZE_WORDS * sizeof(uint32_t)]; +/*! AES_CCM MAC buffer definition.*/ +typedef uint8_t CRYS_AESCCM_Mac_Res_t[SASI_AES_BLOCK_SIZE_IN_BYTES]; + +/*! AES_CCM_STAR source address buffer defintion. */ +typedef uint8_t CRYS_AESCCMStar_SourceAddress_t[CRYS_AESCCM_STAR_SOURCE_ADDRESS_SIZE_BYTES]; +/*! AES_CCM_STAR Nonce buffer defintion. */ +typedef uint8_t CRYS_AESCCMStar_Nonce_t[CRYS_AESCCM_STAR_NONCE_SIZE_BYTES]; + +/******************* Context Structure ***********************/ +/*! The user's context structure - the argument type that is passed by the user to the AES CCM APIs */ +typedef struct CRYS_AESCCM_UserContext_t +{ + /*! AES CCM context buffer for internal usage. */ + uint32_t buff[CRYS_AESCCM_USER_CTX_SIZE_IN_WORDS]; +}CRYS_AESCCM_UserContext_t; + + +/************************ Public Functions **********************/ + +/*! +@brief This function initializes the AES CCM context. + +It formats of the input data, calculates AES-MAC value for the formatted B0 block containing control information and +CCM unique value (Nonce), and initializes the AES context structure including the initial CTR0 value. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CRYSError_t CC_AESCCM_Init( + CRYS_AESCCM_UserContext_t *ContextID_ptr, /*!< [in] Pointer to the AES context buffer that is allocated by the user and is used for + the AES operation. */ + SaSiAesEncryptMode_t EncrDecrMode, /*!< [in] Flag specifying whether Encrypt (::SASI_AES_ENCRYPT) or Decrypt + (::SASI_AES_DECRYPT) operation should be performed. */ + CRYS_AESCCM_Key_t CCM_Key, /*!< [in] Pointer to the AES-CCM key. */ + CRYS_AESCCM_KeySize_t KeySizeId, /*!< [in] Enumerator defining the key size (only 128 bit is valid). */ + uint32_t AdataSize, /*!< [in] Full byte length of additional (associated) data. If set to zero, + calling ::CRYS_AESCCM_BlockAdata on the same context would return an error. */ + uint32_t TextSizeQ, /*!< [in] Full length of plain text data. */ + uint8_t *N_ptr, /*!< [in] Pointer to the Nonce. */ + uint8_t SizeOfN, /*!< [in] Nonce byte size. The valid values depend on the ccm mode: +
    • CCM: valid values = [7 .. 13].
    • +
    • CCM*: valid values = [13].
    */ + uint8_t SizeOfT, /*!< [in] AES-CCM MAC (tag) byte size. The valid values depend on the ccm mode: +
    • CCM: valid values = [4, 6, 8, 10, 12, 14, 16].
    • +
    • CCM*: valid values = [0, 4, 8, 16].
    */ + uint32_t ccmMode /*!< [in] Flag specifying whether AES-CCM or AES-CCM* should be performed. */ +); + +/*! Macro defintion for CRYS_AESCCM_Init (AES CCM non-star implementation). */ +#define CRYS_AESCCM_Init(ContextID_ptr, EncrDecrMode, CCM_Key, KeySizeId, AdataSize, TextSizeQ, N_ptr, SizeOfN, SizeOfT) \ + CC_AESCCM_Init(ContextID_ptr, EncrDecrMode, CCM_Key, KeySizeId, AdataSize, TextSizeQ, N_ptr, SizeOfN, SizeOfT, CRYS_AESCCM_MODE_CCM) + +/*! Macro defintion CRYS_AESCCMStar_Init (AES CCM star implementation). */ +#define CRYS_AESCCMStar_Init(ContextID_ptr, EncrDecrMode, CCM_Key, KeySizeId, AdataSize, TextSizeQ, N_ptr, SizeOfN, SizeOfT) \ + CC_AESCCM_Init(ContextID_ptr, EncrDecrMode, CCM_Key, KeySizeId, AdataSize, TextSizeQ, N_ptr, SizeOfN, SizeOfT, CRYS_AESCCM_MODE_STAR) + +/*! +@brief This function receives a CCM context and a block of additional data, and adds it to the AES MAC +calculation. +This API can be called only once per operation context. It should not be called in case AdataSize was set to +zero in ::CC_AESCCM_Init. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CRYSError_t CRYS_AESCCM_BlockAdata( + CRYS_AESCCM_UserContext_t *ContextID_ptr, /*!< [in] Pointer to the context buffer. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the additional input data. The buffer must be contiguous. */ + uint32_t DataInSize /*!< [in] Byte size of the additional data. Must match AdataSize parameter provided to + ::CRYS_AESCCM_Init. */ +); + +/*! +@brief This function can be invoked for any block of Text data whose size is a multiple of 16 bytes, +excluding the last block that must be processed by ::CRYS_AESCCM_Finish. +
    • If encrypting: + Continues calculation of the intermediate AES_MAC value of the text data, while simultaneously encrypting the text data using AES_CTR, + starting from CTR value = CTR0+1.
    • +
    • If decrypting: + Continues decryption of the text data, while calculating the intermediate AES_MAC value of decrypted data.
    + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CRYSError_t CRYS_AESCCM_BlockTextData( + CRYS_AESCCM_UserContext_t *ContextID_ptr, /*!< [in] Pointer to the context buffer. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the additional input data. The buffer must be contiguous. */ + uint32_t DataInSize, /*!< [in] Byte size of the text data block. Must be a multiple of 16 bytes. */ + uint8_t *DataOut_ptr /*!< [out] Pointer to the output data. The size of the output buffer must be at least DataInSize. + The buffer must be contiguous. */ +); + +/*! +@brief This function must be the last to be called on the text data. +It can either be called on the entire text data (if transferred as one block), or on the last block of the text data, +even if total size of text data is equal to 0. +It performs the same operations as ::CRYS_AESCCM_BlockTextData, but additionally: +
    • If encrypting:
    • +
      • If the size of text data is not in multiples of 16 bytes, it pads the remaining bytes with zeros to a full 16-bytes block and + processes the data using AES_MAC and AES_CTR algorithms.
      • +
      • Encrypts the AES_MAC result with AES_CTR using the CTR0 value saved in the context and places the SizeOfT bytes of MAC (tag) + at the end.
    +
    • If decrypting:
    • +
      • Processes the text data, except for the last SizeOfT bytes (tag), using AES_CTR and then AES_MAC algorithms.
      • +
      • Encrypts the calculated MAC using AES_CTR based on the saved CTR0 value, and compares it with SizeOfT last bytes of input data (i.e. + tag value).
      • +
      • The function saves the validation result (Valid/Invalid) in the context.
      • +
      • Returns (as the error code) the final CCM-MAC verification result.
    + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CEXPORT_C CRYSError_t CRYS_AESCCM_Finish( + CRYS_AESCCM_UserContext_t *ContextID_ptr, /*!< [in] Pointer to the context buffer. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the last input data. The buffer must be contiguous. */ + uint32_t DataInSize, /*!< [in] Byte size of the last text data block. Can be zero. */ + uint8_t *DataOut_ptr, /*!< [in] Pointer to the output (cipher or plain text data) data. The buffer must + be contiguous. If DataInSize = 0, output buffer is not required. */ + CRYS_AESCCM_Mac_Res_t MacRes, /*!< [in] MAC result buffer pointer. */ + uint8_t *SizeOfT /*!< [out] AES-CCM MAC byte size as defined in CRYS_AESCCM_Init. */ +); + +/****************************************************************************************************/ +/******** AESCCM FUNCTION ******/ +/****************************************************************************************************/ +/*! +@brief AES CCM combines Counter mode encryption with CBC-MAC authentication. +Input to CCM includes the following elements: +
    • Payload - text data that is both authenticated and encrypted.
    • +
    • Associated data (Adata) - data that is authenticated but not encrypted, e.g., a header.
    • +
    • Nonce - A unique value that is assigned to the payload and the associated data.
    + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CIMPORT_C CRYSError_t CC_AESCCM( + SaSiAesEncryptMode_t EncrDecrMode, /*!< [in] A flag specifying whether an AES Encrypt (::SASI_AES_ENCRYPT) or Decrypt + (::SASI_AES_DECRYPT) operation should be performed. */ + CRYS_AESCCM_Key_t CCM_Key, /*!< [in] Pointer to AES-CCM key. */ + CRYS_AESCCM_KeySize_t KeySizeId, /*!< [in] Enumerator defining the key size (only 128 bit is valid). */ + uint8_t *N_ptr, /*!< [in] Pointer to the Nonce. */ + uint8_t SizeOfN, /*!< [in] Nonce byte size. The valid values depend on the ccm mode: +
    • CCM: valid values = [7 .. 13].
    • +
    • CCM*: valid values = [13].
    */ + uint8_t *ADataIn_ptr, /*!< [in] Pointer to the additional input data. The buffer must be contiguous. */ + uint32_t ADataInSize, /*!< [in] Byte size of the additional data. */ + uint8_t *TextDataIn_ptr, /*!< [in] Pointer to the plain-text data for encryption or cipher-text data for decryption. + The buffer must be contiguous. */ + uint32_t TextDataInSize, /*!< [in] Byte size of the full text data. */ + uint8_t *TextDataOut_ptr, /*!< [out] Pointer to the output (cipher or plain text data according to encrypt-decrypt mode) + data. The buffer must be contiguous. */ + uint8_t SizeOfT, /*!< [in] AES-CCM MAC (tag) byte size. The valid values depend on the ccm mode: +
    • CCM: valid values = [4, 6, 8, 10, 12, 14, 16].
    • +
    • CCM*: valid values = [0, 4, 8, 16].
    */ + CRYS_AESCCM_Mac_Res_t Mac_Res, /*!< [in/out] Pointer to the MAC result buffer. */ + uint32_t ccmMode /*!< [in] Flag specifying whether AES-CCM or AES-CCM* should be performed. */ +); + +/*! Macro defintion for CRYS_AESCCM (AES CCM non-star implementation). */ +#define CRYS_AESCCM(EncrDecrMode, CCM_Key, KeySizeId, N_ptr, SizeOfN, ADataIn_ptr, ADataInSize, TextDataIn_ptr, TextDataInSize, TextDataOut_ptr, SizeOfT, Mac_Res) \ + CC_AESCCM(EncrDecrMode, CCM_Key, KeySizeId, N_ptr, SizeOfN, ADataIn_ptr, ADataInSize, TextDataIn_ptr, TextDataInSize, TextDataOut_ptr, SizeOfT, Mac_Res, CRYS_AESCCM_MODE_CCM) + +/*! Macro defintion for CRYS_AESCCMStar (AES CCM star implementation). */ +#define CRYS_AESCCMStar(EncrDecrMode, CCM_Key, KeySizeId, N_ptr, SizeOfN, ADataIn_ptr, ADataInSize, TextDataIn_ptr, TextDataInSize, TextDataOut_ptr, SizeOfT, Mac_Res) \ + CC_AESCCM(EncrDecrMode, CCM_Key, KeySizeId, N_ptr, SizeOfN, ADataIn_ptr, ADataInSize, TextDataIn_ptr, TextDataInSize, TextDataOut_ptr, SizeOfT, Mac_Res, CRYS_AESCCM_MODE_STAR) + + +/*! +@brief This function receives the MAC source address, the frame counter and the MAC size +and returns the required nonce for AES-CCM* as defined in ieee-802.15.4. +This API should be called before CRYS_AESCCMStar and CRYS_AESCCMStar_Init, +and the generated nonce should be provided to these functions. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CRYSError_t CRYS_AESCCMStar_NonceGenerate( + CRYS_AESCCMStar_SourceAddress_t srcAddr, /*!< [in] The MAC address in EUI-64 format. */ + uint32_t FrameCounter, /*!< [in] The MAC frame counter. */ + uint8_t SizeOfT, /*!< [in] AES-CCM* MAC (tag) byte size. Valid values = [0,4,8,16]. */ + CRYS_AESCCMStar_Nonce_t nonce /*!< [out] The required nonce for AES-CCM*. */ +); + +#ifdef __cplusplus +} +#endif + +/** +@} + */ + +#endif /*#ifndef CRYS_AESCCM_H*/ + diff --git a/external/nrf_cc310_bl/include/crys_ecpki_error.h b/external/nrf_cc310_bl/include/crys_ecpki_error.h new file mode 100644 index 0000000..950dce0 --- /dev/null +++ b/external/nrf_cc310_bl/include/crys_ecpki_error.h @@ -0,0 +1,317 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_ECPKI_ERROR_H +#define CRYS_ECPKI_ERROR_H + + +/*! +@file +@brief This module contains the definitions of the CRYS ECPKI errors. +@defgroup crys_ecpki_error CryptoCell ECC specific errors +@{ +@ingroup cryptocell_ecpki +*/ + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ + +/* CRYS_ECPKI_MODULE_ERROR_BASE = 0x00F00800 */ + +/********************************************************************************************* + * CRYS ECPKI MODULE ERRORS * + *********************************************************************************************/ +/*! Illegal domain ID. */ +#define CRYS_ECPKI_ILLEGAL_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x1UL) +/*! Illegal domain pointer. */ +#define CRYS_ECPKI_DOMAIN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x2UL) +/* The CRYS ECPKI GEN KEY PAIR module errors */ +/*! Illegal private key pointer. */ +#define CRYS_ECPKI_GEN_KEY_INVALID_PRIVATE_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x3UL) +/*! Illegal public key pointer. */ +#define CRYS_ECPKI_GEN_KEY_INVALID_PUBLIC_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x4UL) +/*! Illegal temporary buffer pointer. */ +#define CRYS_ECPKI_GEN_KEY_INVALID_TEMP_DATA_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x5UL) +/*! Illegal RND context pointer. */ +#define CRYS_ECPKI_RND_CONTEXT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x6UL) + +/************************************************************************************************************ +* The CRYS ECPKI BUILD KEYS MODULE ERRORS * +*************************************************************************************************************/ +/*! Illegal compression mode. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_COMPRESSION_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x07UL) +/*! Illegal domain ID. */ +#define CRYS_ECPKI_BUILD_KEY_ILLEGAL_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x08UL) +/*! Illegal private key pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PRIV_KEY_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x09UL) +/*! Illegal private key structure pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_USER_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0AUL) +/*! Illegal private key size. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PRIV_KEY_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0BUL) +/*! Illegal private key data. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PRIV_KEY_DATA_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0CUL) +/*! Illegal public key pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0DUL) +/*! Illegal public key structure pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_USER_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0EUL) +/*! Illegal public key size. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0FUL) +/*! Illegal public key data. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_DATA_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x10UL) +/*! Illegal EC build check mode option. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_CHECK_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x11UL) +/*! Illegal temporary buffer pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_TEMP_BUFF_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x12UL) + +/* The CRYS ECPKI EXPORT PUBLIC KEY MODULE ERRORS */ +/*! Illegal public key structure pointer. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_USER_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x14UL) +/*! Illegal public key compression mode. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_ILLEGAL_COMPRESSION_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x15UL) +/*! Illegal output public key pointer. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_EXTERN_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x16UL) +/*! Illegal output public key size pointer. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_SIZE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x17UL) +/*! Illegal output public key size. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x18UL) +/*! Illegal domain ID. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_ILLEGAL_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x19UL) +/*! Validation of public key failed. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_ILLEGAL_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x1AUL) +/*! Validation of public key failed. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_DATA_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x1BUL) + +/* The CRYS ECPKI EXPORT PRIVATE KEY MODULE ERRORS */ +/*! Illegal private key structure pointer. */ +#define CRYS_ECPKI_EXPORT_PRIV_KEY_INVALID_USER_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xC0UL) +/*! Illegal output private key pointer. */ +#define CRYS_ECPKI_EXPORT_PRIV_KEY_INVALID_EXTERN_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xC1UL) +/*! Validation of private key failed. */ +#define CRYS_ECPKI_EXPORT_PRIV_KEY_ILLEGAL_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xC2UL) +/*! Illegal output private key size pointer. */ +#define CRYS_ECPKI_EXPORT_PRIV_KEY_INVALID_PRIV_KEY_SIZE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xC3UL) +/*! Illegal output private key size. */ +#define CRYS_ECPKI_EXPORT_PRIV_KEY_INVALID_PRIV_KEY_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xC4UL) +/*! Validation of private key failed. */ +#define CRYS_ECPKI_EXPORT_PRIV_KEY_INVALID_PRIV_KEY_DATA_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xC5UL) + +/* The CRYS ECPKI BUILD ECC DOMAIN ERRORS */ +/*! Illegal domain ID. */ +#define CRYS_ECPKI_BUILD_DOMAIN_ID_IS_NOT_VALID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x20UL) +/*! Illegal domain ID pointer. */ +#define CRYS_ECPKI_BUILD_DOMAIN_DOMAIN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x21UL) +/*! Illegal domain parameter pointer. */ +#define CRYS_ECPKI_BUILD_DOMAIN_EC_PARAMETR_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x22UL) +/*! Illegal domain parameter size. */ +#define CRYS_ECPKI_BUILD_DOMAIN_EC_PARAMETR_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x23UL) +/*! Illegal domain cofactor parameters. */ +#define CRYS_ECPKI_BUILD_DOMAIN_COFACTOR_PARAMS_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x24UL) +/*! Insufficient strength. */ +#define CRYS_ECPKI_BUILD_DOMAIN_SECURITY_STRENGTH_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x25UL) +/*! SCA resistance error. */ +#define CRYS_ECPKI_BUILD_SCA_RESIST_ILLEGAL_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x26UL) + + +/*! Internal PKI error */ +#define CRYS_ECPKI_PKI_INTERNAL_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x30UL) + +/************************************************************************************************************ + * CRYS EC DIFFIE-HELLMAN MODULE ERRORS +*************************************************************************************************************/ +/* The CRYS EC SVDP_DH Function errors */ +/*! Illegal partner's public key pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_PARTNER_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x31UL) +/*! Partner's public key validation failed. */ +#define CRYS_ECDH_SVDP_DH_PARTNER_PUBL_KEY_VALID_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x32UL) +/*! Illegal user private key pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_USER_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x33UL) +/*! Private key validation failed. */ +#define CRYS_ECDH_SVDP_DH_USER_PRIV_KEY_VALID_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x34UL) +/*! Illegal shared secret pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_SHARED_SECRET_VALUE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x35UL) +/*! Illegal temporary buffer pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_TEMP_DATA_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x36UL) +/*! Illegal shared secret size pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_SHARED_SECRET_VALUE_SIZE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x37UL) +/*! Illegal shared secret size. */ +#define CRYS_ECDH_SVDP_DH_INVALID_SHARED_SECRET_VALUE_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x38UL) +/*! Illegal domain ID. */ +#define CRYS_ECDH_SVDP_DH_ILLEGAL_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x39UL) +/*! Illegal private and public domain ID are different. */ +#define CRYS_ECDH_SVDP_DH_NOT_CONCENT_PUBL_AND_PRIV_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x3AUL) + + +/************************************************************************************************************ + * CRYS ECDSA MODULE ERRORS + ************************************************************************************************************/ +/* The CRYS ECDSA Signing errors */ +/*! Illegal domain ID. */ +#define CRYS_ECDSA_SIGN_INVALID_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x50UL) +/*! Illegal context pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_USER_CONTEXT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x51UL) +/*! Illegal private key pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_USER_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x52UL) +/*! Illegal hash operation mode. */ +#define CRYS_ECDSA_SIGN_ILLEGAL_HASH_OP_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x53UL) +/*! Illegal data in pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_MESSAGE_DATA_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x54UL) +/*! Illegal data in size. */ +#define CRYS_ECDSA_SIGN_INVALID_MESSAGE_DATA_IN_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x55UL) +/*! Context validation failed. */ +#define CRYS_ECDSA_SIGN_USER_CONTEXT_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x57UL) +/*! User's private key validation failed. */ +#define CRYS_ECDSA_SIGN_USER_PRIV_KEY_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x58UL) +/*! Illegal signature pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x60UL) +/*! Illegal signature size pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_SIZE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x61UL) +/*! Illegal signature size. */ +#define CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x62UL) +/*! Ephemeral key error. */ +#define CRYS_ECDSA_SIGN_INVALID_IS_EPHEMER_KEY_INTERNAL_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x63UL) +/*! Illegal ephemeral key pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_EPHEMERAL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x64UL) +/*! Illegal RND context pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_RND_CONTEXT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x65UL) +/*! Illegal RND function pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_RND_FUNCTION_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x66UL) +/*! Signature calculation failed. */ +#define CRYS_ECDSA_SIGN_SIGNING_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x67UL) + +/* The CRYS ECDSA Verifying errors */ +/*! Illegal domain ID. */ +#define CRYS_ECDSA_VERIFY_INVALID_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x70UL) +/*! Illegal user's context pointer. */ +#define CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x71UL) +/*! Illegal public key pointer. */ +#define CRYS_ECDSA_VERIFY_INVALID_SIGNER_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x72UL) +/*! Illegal hash operation mode. */ +#define CRYS_ECDSA_VERIFY_ILLEGAL_HASH_OP_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x73UL) +/*! Illegal signature pointer. */ +#define CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x76UL) +/*! Illegal signature size. */ +#define CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x77UL) +/*! Illegal data in pointer. */ +#define CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x80UL) +/*! Illegal data in size. */ +#define CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x81UL) +/*! Context validation failed. */ +#define CRYS_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x82UL) +/*! public key validation failed. */ +#define CRYS_ECDSA_VERIFY_SIGNER_PUBL_KEY_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x83UL) +/*! Verification failed. */ +#define CRYS_ECDSA_VERIFY_INCONSISTENT_VERIFY_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x84UL) + +/*! Illegal parameters. */ +#define CRYS_ECC_ILLEGAL_PARAMS_ACCORDING_TO_PRIV_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xD3UL) +/*! Illegal hash mode. */ +#define CRYS_ECC_ILLEGAL_HASH_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE0UL) + + +/************************************************************************************************************ + * CRYS ECPKI MODULE COMMON ERRORS +*************************************************************************************************************/ +/*! Illegal RND function pointer. */ +#define CRYS_ECPKI_INVALID_RND_FUNC_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x90UL) +/*! Illegal RND context pointer. */ +#define CRYS_ECPKI_INVALID_RND_CTX_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x91UL) +/*! Illegal domain ID. */ +#define CRYS_ECPKI_INVALID_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x92UL) +/*! Private key validation failed. */ +#define CRYS_ECPKI_INVALID_PRIV_KEY_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x93UL) +/*! Public key validation failed. */ +#define CRYS_ECPKI_INVALID_PUBL_KEY_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x94UL) +/*! Illegal data in. */ +#define CRYS_ECPKI_INVALID_DATA_IN_PASSED_STRUCT_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x95UL) + +/************************************************************************************************************ + * CRYS ECIES MODULE ERRORS +*************************************************************************************************************/ +/*! Illegal public key pointer. */ +#define CRYS_ECIES_INVALID_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE0UL) +/*! Public key validation failed. */ +#define CRYS_ECIES_INVALID_PUBL_KEY_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE1UL) +/*! Illegal private key pointer. */ +#define CRYS_ECIES_INVALID_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE2UL) +/*! Private key validation failed. */ +#define CRYS_ECIES_INVALID_PRIV_KEY_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE3UL) +/*! Illegal private key value. */ +#define CRYS_ECIES_INVALID_PRIV_KEY_VALUE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE4UL) +/*! Illegal KDF derivation mode. */ +#define CRYS_ECIES_INVALID_KDF_DERIV_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE5UL) +/*! Illegal KDF hash mode. */ +#define CRYS_ECIES_INVALID_KDF_HASH_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE6UL) +/*! Illegal secret key pointer. */ +#define CRYS_ECIES_INVALID_SECRET_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE7UL) +/*! Illegal secret key size. */ +#define CRYS_ECIES_INVALID_SECRET_KEY_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE8UL) +/*! Illegal cipher data pointer. */ +#define CRYS_ECIES_INVALID_CIPHER_DATA_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE9UL) +/*! Illegal cipher data size pointer. */ +#define CRYS_ECIES_INVALID_CIPHER_DATA_SIZE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xEAUL) +/*! Illegal cipher data size. */ +#define CRYS_ECIES_INVALID_CIPHER_DATA_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xEBUL) +/*! Illegal temporary buffer pointer. */ +#define CRYS_ECIES_INVALID_TEMP_DATA_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xECUL) +/*! Illegal ephemeral key pointer */ +#define CRYS_ECIES_INVALID_EPHEM_KEY_PAIR_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xEDUL) + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs ******************************/ + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310_bl/include/crys_error.h b/external/nrf_cc310_bl/include/crys_error.h new file mode 100644 index 0000000..bf5673f --- /dev/null +++ b/external/nrf_cc310_bl/include/crys_error.h @@ -0,0 +1,273 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_ERROR_H +#define CRYS_ERROR_H + +#include "ssi_pal_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! @file +@brief This module defines the error return code types and the numbering spaces of the error codes +for each module of the layers listed below. +@defgroup crys_error CryptoCell general base error codes +@{ +@ingroup cryptocell_api +*/ + +/*! The definitions of the error number space used for the different modules */ + +/* ........... Error base numeric mapping definitions ................... */ +/* ----------------------------------------------------------------------- */ + + /*! CRYS error base number. */ +#define CRYS_ERROR_BASE 0x00F00000UL + +/*! Error range number assigned for each layer. */ +#define CRYS_ERROR_LAYER_RANGE 0x00010000UL + +/*! Error range number assigned to each module on its specified layer. */ +#define CRYS_ERROR_MODULE_RANGE 0x00000100UL + +/* Defines the layer index for the error mapping. */ +/*! CRYS error layer index. */ +#define CRYS_LAYER_ERROR_IDX 0x00UL +/*! Low level functions error layer index. */ +#define LLF_LAYER_ERROR_IDX 0x01UL +/*! Generic error layer index. */ +#define GENERIC_ERROR_IDX 0x05UL + +/* Defines the module index for error mapping */ +/*! AES error index.*/ +#define AES_ERROR_IDX 0x00UL +/*! DES error index.*/ +#define DES_ERROR_IDX 0x01UL +/*! HASH error index.*/ +#define HASH_ERROR_IDX 0x02UL +/*! HMAC error index.*/ +#define HMAC_ERROR_IDX 0x03UL +/*! RSA error index.*/ +#define RSA_ERROR_IDX 0x04UL +/*! DH error index.*/ +#define DH_ERROR_IDX 0x05UL + +/*! ECPKI error index.*/ +#define ECPKI_ERROR_IDX 0x08UL +/*! RND error index.*/ +#define RND_ERROR_IDX 0x0CUL +/*! Common error index.*/ +#define COMMON_ERROR_IDX 0x0DUL +/*! KDF error index.*/ +#define KDF_ERROR_IDX 0x11UL +/*! HKDF error index.*/ +#define HKDF_ERROR_IDX 0x12UL +/*! AESCCM error index.*/ +#define AESCCM_ERROR_IDX 0x15UL +/*! FIPS error index.*/ +#define FIPS_ERROR_IDX 0x17UL + +/*! PKA error index.*/ +#define PKA_MODULE_ERROR_IDX 0x21UL +/*! CHACHA error index.*/ +#define CHACHA_ERROR_IDX 0x22UL +/*! EC montgomery and edwards error index.*/ +#define EC_MONT_EDW_ERROR_IDX 0x23UL +/*! CHACHA POLY error index.*/ +#define CHACHA_POLY_ERROR_IDX 0x24UL +/*! POLY error index.*/ +#define POLY_ERROR_IDX 0x25UL +/*! SRP error index.*/ +#define SRP_ERROR_IDX 0x26UL + + + +/* .......... defining the error spaces for each module on each layer ........... */ +/* ------------------------------------------------------------------------------ */ + +/*! AES module error base address - 0x00F00000. */ +#define CRYS_AES_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * AES_ERROR_IDX ) ) + +/*! DES module error base address - 0x00F00100. */ +#define CRYS_DES_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * DES_ERROR_IDX ) ) + +/*! HASH module error base address - 0x00F00200. */ +#define CRYS_HASH_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * HASH_ERROR_IDX ) ) + +/*! HMAC module error base address - 0x00F00300. */ +#define CRYS_HMAC_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * HMAC_ERROR_IDX ) ) + +/*! RSA module error base address - 0x00F00400. */ +#define CRYS_RSA_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * RSA_ERROR_IDX ) ) + +/*! DH module error base address - 0x00F00500. */ +#define CRYS_DH_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * DH_ERROR_IDX ) ) + +/*! ECPKI module error base address - 0x00F00800. */ +#define CRYS_ECPKI_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * ECPKI_ERROR_IDX ) ) + +/*! Low level ECPKI module error base address - 0x00F10800. */ +#define LLF_ECPKI_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * LLF_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * ECPKI_ERROR_IDX ) ) + +/*! RND module error base address - 0x00F00C00. */ +#define CRYS_RND_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * RND_ERROR_IDX ) ) + +/*! Low level RND module error base address - 0x00F10C00. */ +#define LLF_RND_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * LLF_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * RND_ERROR_IDX ) ) + +/*! COMMMON module error base address - 0x00F00D00. */ +#define CRYS_COMMON_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * COMMON_ERROR_IDX ) ) + +/*! KDF module error base address - 0x00F01100. */ +#define CRYS_KDF_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * KDF_ERROR_IDX ) ) + +/*! HKDF module error base address - 0x00F01100. */ +#define CRYS_HKDF_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * HKDF_ERROR_IDX ) ) + +/*! AESCCM module error base address - 0x00F01500. */ +#define CRYS_AESCCM_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * AESCCM_ERROR_IDX ) ) + +/*! FIPS module error base address - 0x00F01700. */ +#define CRYS_FIPS_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * FIPS_ERROR_IDX ) ) + +/*! PKA module error base address - 0x00F02100. */ +#define PKA_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * PKA_MODULE_ERROR_IDX ) ) + +/*! CHACHA module error base address - 0x00F02200. */ +#define CRYS_CHACHA_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * CHACHA_ERROR_IDX ) ) +/*! CHACHA POLY module error base address - 0x00F02400. */ +#define CRYS_CHACHA_POLY_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * CHACHA_POLY_ERROR_IDX ) ) +/*! POLY module error base address - 0x00F02500. */ +#define CRYS_POLY_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * POLY_ERROR_IDX ) ) + +/*! SRP module error base address - 0x00F02600. */ +#define CRYS_SRP_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * SRP_ERROR_IDX ) ) + + +/*! EC MONT_EDW module error base address - 0x00F02300. */ +#define CRYS_EC_MONT_EDW_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * EC_MONT_EDW_ERROR_IDX ) ) + + +/*! User generic error base address - 0x00F50000 */ +#define GENERIC_ERROR_BASE ( CRYS_ERROR_BASE + (CRYS_ERROR_LAYER_RANGE * GENERIC_ERROR_IDX) ) +/*! CRYS fatal error. */ +#define CRYS_FATAL_ERROR (GENERIC_ERROR_BASE + 0x00UL) +/*! CRYS out of resources error. */ +#define CRYS_OUT_OF_RESOURCE_ERROR (GENERIC_ERROR_BASE + 0x01UL) +/*! CRYS illegal resource value error. */ +#define CRYS_ILLEGAL_RESOURCE_VAL_ERROR (GENERIC_ERROR_BASE + 0x02UL) + + + +/* ............ The OK (success) definition ....................... */ +/*! Success defintion. */ +#define CRYS_OK 0 + +/*! MACRO that defines crys return value. */ +#define SASI_CRYS_RETURN_ERROR(retCode, retcodeInfo, funcHandler) \ + ((retCode) == 0 ? CRYS_OK : funcHandler(retCode, retcodeInfo)) + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + +/*! The typedef definition of all of the error codes that are returned from the CRYS functions */ +typedef uint32_t CRYSError_t; + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + + + diff --git a/external/nrf_cc310_bl/include/crys_hash_error.h b/external/nrf_cc310_bl/include/crys_hash_error.h new file mode 100644 index 0000000..c1d304e --- /dev/null +++ b/external/nrf_cc310_bl/include/crys_hash_error.h @@ -0,0 +1,108 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef CRYS_HASH_ERROR_H +#define CRYS_HASH_ERROR_H + + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the CRYS HASH errors. +@defgroup crys_hash_error CryptoCell HASH specific errors +@{ +@ingroup crys_hash +*/ + + + + +/************************ Defines ******************************/ +/*! HASH module on the CRYS layer base address - 0x00F00200*/ +/* The CRYS HASH module errors */ +/*! Illegal context pointer. */ +#define CRYS_HASH_INVALID_USER_CONTEXT_POINTER_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x0UL) +/*! Illegal operation mode. */ +#define CRYS_HASH_ILLEGAL_OPERATION_MODE_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x1UL) +/*! Context is corrupted. */ +#define CRYS_HASH_USER_CONTEXT_CORRUPTED_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x2UL) +/*! Illegal data in pointer. */ +#define CRYS_HASH_DATA_IN_POINTER_INVALID_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x3UL) +/*! Illegal data in size. */ +#define CRYS_HASH_DATA_SIZE_ILLEGAL (CRYS_HASH_MODULE_ERROR_BASE + 0x4UL) +/*! Illegal result buffer pointer. */ +#define CRYS_HASH_INVALID_RESULT_BUFFER_POINTER_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x5UL) +/*! Last block was already processed (may happen if previous block was not a multiple of block size). */ +#define CRYS_HASH_LAST_BLOCK_ALREADY_PROCESSED_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0xCUL) +/*! Illegal parameter. */ +#define CRYS_HASH_ILLEGAL_PARAMS_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0xDUL) +/*! Illegal context size. */ +#define CRYS_HASH_CTX_SIZES_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0xEUL) +/*! HASH is not supported. */ +#define CRYS_HASH_IS_NOT_SUPPORTED (CRYS_HASH_MODULE_ERROR_BASE + 0xFUL) + + + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310_bl/include/crys_rnd.h b/external/nrf_cc310_bl/include/crys_rnd.h new file mode 100644 index 0000000..653768c --- /dev/null +++ b/external/nrf_cc310_bl/include/crys_rnd.h @@ -0,0 +1,398 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef CRYS_RND_H +#define CRYS_RND_H + +#include "crys_error.h" +#include "ssi_aes.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains the CRYS APIs used for random number generation. +The random-number generation module implements referenced standard [SP800-90]. +@defgroup crys_rnd CryptoCell Random Generator APIs +@{ +@ingroup cryptocell_api +*/ + +/************************ Defines ******************************/ + +/*! Maximal reseed counter - indicates maximal number of +requests allowed between reseeds; according to NIST 800-90 +it is (2^48 - 1), our restriction is : (0xFFFFFFFF - 0xF).*/ +#define CRYS_RND_MAX_RESEED_COUNTER (0xFFFFFFFF - 0xF) + +/* Max size for one RNG generation (in bits) = + max_num_of_bits_per_request = 2^19 (FIPS 800-90 Tab.3) */ +/*! Maximal size of generated vector in bits. */ +#define CRYS_RND_MAX_GEN_VECTOR_SIZE_BITS 0x7FFFF +/*! Maximal size of generated vector in bytes. */ +#define CRYS_RND_MAX_GEN_VECTOR_SIZE_BYTES 0xFFFF + +/*! AES output block size in words. */ +#define CRYS_RND_AES_BLOCK_SIZE_IN_WORDS SASI_AES_BLOCK_SIZE_IN_WORDS + + +/* RND seed and additional input sizes */ +/*! Maximal size of random seed in words. */ +#define CRYS_RND_SEED_MAX_SIZE_WORDS 12 + +#ifndef CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS +/*! Maximal size of additional input data in words. */ +#define CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS CRYS_RND_SEED_MAX_SIZE_WORDS +#endif + +/* allowed sizes of AES Key, in words */ +/*! AES key size (128 bits) in words. */ +#define CRYS_RND_AES_KEY_128_SIZE_WORDS 4 +/*! AES key size (192 bits) in words. */ +#define CRYS_RND_AES_KEY_192_SIZE_WORDS 6 +/*! AES key size (256 bits) in words. */ +#define CRYS_RND_AES_KEY_256_SIZE_WORDS 8 + +/* Definitions of temp buffer for RND_DMA version of CRYS_RND */ +/*******************************************************************/ +/* Definitions of temp buffer for DMA version of CRYS_RND */ + +/*! Temporary buffer size in words. */ +#define CRYS_RND_WORK_BUFFER_SIZE_WORDS 1528 + +/*! A definition for RAM buffer to be internally used in instantiation (or reseeding) operation. */ +typedef struct +{ + /*! Internal buffer*/ + uint32_t crysRndWorkBuff[CRYS_RND_WORK_BUFFER_SIZE_WORDS]; +}CRYS_RND_WorkBuff_t; + +/*! A definition for entropy estimation data type. */ +#define CRYS_RND_EntropyEstimatData_t CRYS_RND_WorkBuff_t +/*! A definition for entropy estimation buffer. */ +#define crysRndEntrIntBuff crysRndWorkBuff + + +/* RND source buffer inner (entrpopy) offset */ +/*! An internal offset definition. */ +#define CRYS_RND_TRNG_SRC_INNER_OFFSET_WORDS 2 +/*! An internal offset definition. */ +#define CRYS_RND_TRNG_SRC_INNER_OFFSET_BYTES (CRYS_RND_TRNG_SRC_INNER_OFFSET_WORDS*sizeof(uint32_t)) + + + + +/* Size of the expected output buffer used by FIPS KAT */ +/*! FIPS Known answer test output size. */ +#define CRYS_PRNG_FIPS_KAT_OUT_DATA_SIZE 64 + +/************************ Enumerators ****************************/ + +/*! Definition of random operation modes. */ +typedef enum +{ + /*! SW entropy estimation mode. */ + CRYS_RND_Fast = 0, + /*! Full entropy mode. */ + CRYS_RND_Slow = 1, + /*! Reserved. */ + CRYS_RND_ModeLast = 0x7FFFFFFF, +} CRYS_RND_mode_t; + + + +/************************ Structs *****************************/ + + +/* The internal state of DRBG mechanism based on AES CTR and CBC-MAC + algorithms. It is set as global data defined by the following + structure */ +/*! RND state structure. Includes internal data that needs to be saved between boots by the user.*/ +typedef struct +{ + /* Seed buffer, consists from concatenated Key||V: max size 12 words */ + /*! Random Seed buffer */ + uint32_t Seed[CRYS_RND_SEED_MAX_SIZE_WORDS]; + /* Previous value for continuous test */ + /*! Previous random data (used for continuous test). */ + uint32_t PreviousRandValue[SASI_AES_BLOCK_SIZE_IN_WORDS]; + + /* AdditionalInput buffer max size = seed max size words + 4w for padding*/ + /*! Previous additional input buffer. */ + uint32_t PreviousAdditionalInput[CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS+5]; + /*! Additional input buffer. */ + uint32_t AdditionalInput[CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS+4]; + /*! Additional input size in words. */ + uint32_t AddInputSizeWords; /* size of additional data set by user, words */ + + /*! Entropy source size in words */ + uint32_t EntropySourceSizeWords; + + /*! Reseed counter (32 bits active) - indicates number of requests for entropy + since instantiation or reseeding */ + uint32_t ReseedCounter; + + /*! Key size: 4 or 8 words according to security strength 128 bits or 256 bits*/ + uint32_t KeySizeWords; + + /* State flag (see definition of StateFlag above), containing bit-fields, defining: + - b'0: instantiation steps: 0 - not done, 1 - done; + - 2b'9,8: working or testing mode: 0 - working, 1 - KAT DRBG test, 2 - + KAT TRNG test; + b'16: flag defining is Previous random valid or not: + 0 - not valid, 1 - valid */ + /*! State flag used internally in the code.*/ + uint32_t StateFlag; + + /* Trng processing flag - indicates which ROSC lengths are: + - allowed (bits 0-3); + - total started (bits 8-11); + - processed (bits 16-19); + - started, but not processed (bits24-27) */ + /*! TRNG process state used internally in the code */ + uint32_t TrngProcesState; + + /* validation tag */ + /*! Validation tag used internally in the code */ + uint32_t ValidTag; + + /*! Rnd source entropy size in bits */ + uint32_t EntropySizeBits; + +} CRYS_RND_State_t; + + +/*! The RND Generate vector function pointer type definition. + The prototype intendent for External and CRYS internal RND functions + pointers definitions. + Full description can be found in ::CRYS_RND_GenerateVector function API. */ +typedef uint32_t (*SaSiRndGenerateVectWorkFunc_t)( \ + void *rndState_ptr, /*context*/ \ + uint16_t outSizeBytes, /*in*/ \ + uint8_t *out_ptr /*out*/); + + + +/*! Data structure required for internal FIPS verification for PRNG KAT. */ +typedef struct +{ + /*! Internal working buffer. */ + CRYS_RND_WorkBuff_t rndWorkBuff; + /*! Output buffer. */ + uint8_t rndOutputBuff[CRYS_PRNG_FIPS_KAT_OUT_DATA_SIZE]; +} CRYS_PrngFipsKatCtx_t; + + +/*****************************************************************************/ +/********************** Public Functions *************************/ +/*****************************************************************************/ + +/*! +@brief This function needs to be called once. +It calls CRYS_RND_Instantiation to initialize the TRNG and the primary RND context. +An initialized RND context is required for calling RND APIs and asymmetric cryptography key generation and signatures. +The primary context returned by this function can be used as a single global context for all RND needs. +Alternatively, other contexts may be initialized and used with a more limited scope (for specific applications or specific threads). + +\note The Mutexes, if used, are initialized by this API. Therefore, unlike the other APIs in the library, +this API is not thread-safe. + +@param[in/out] rnd_ctx - Pointer to the RND state structure. +@param[in/out] rndWorkBuff_ptr - Pointer to the RND scratch buffer. +*/ +CEXPORT_C CRYSError_t CRYS_RndInit(void* rnd_ctx, /*!< [in/out] Pointer to the RND state buffer, + allocated by the user. This state must be saved and provided + as parameter to any API that uses the RND module.*/ + CRYS_RND_WorkBuff_t *rndWorkBuff_ptr /*!< [in] Scratchpad for the RND module's work. */); + +/*! +@brief This function initializes the RND context. +It must be called at least once prior to using this context with any API that requires it as a parameter (e.g., other RND APIs, asymmetric +cryptography key generation and signatures). +It is called as part of ARM TrustZone CryptoCell library initialization, which initializes and returns the primary RND context. +This primary context can be used as a single global context for all RND needs. +Alternatively, other contexts may be initialized and used with a more limited scope (for specific applications or specific threads). +The call to this function must be followed by a call to ::CRYS_RND_SetGenerateVectorFunc API to set the generate vector function. +It implements referenced standard [SP800-90] - 10.2.1.3.2 - CTR-DRBG Instantiate algorithm using AES (FIPS-PUB 197) and Derivation Function (DF). +\note Additional data can be mixed with the random seed (personalization data or nonce). If required, this data should be provided by calling ::CRYS_RND_AddAdditionalInput prior to using this API. + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RND_Instantiation( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state buffer allocated by the user, which is used to + maintain the RND state. This context state must be saved and provided as a + parameter to any API that uses the RND module. + \note the context must be cleared before sent to the function. */ + CRYS_RND_WorkBuff_t *rndWorkBuff_ptr /*!< [in/out] Scratchpad for the RND module's work. */ +); + + +/*! +@brief Clears existing RNG instantiation state. + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RND_UnInstantiation( + void *rndState_ptr /*!< [in/out] Pointer to the RND context state buffer. */ +); + + +/*! +@brief This function is used for reseeding the RNG with additional entropy and additional user-provided input. +(additional data should be provided by calling ::CRYS_RND_AddAdditionalInput prior to using this API). +It implements referenced standard [SP800-90] - 10.2.1.4.2 - CTR-DRBG Reseeding algorithm, using AES (FIPS-PUB 197) and Derivation Function (DF). + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RND_Reseeding( + void *rndState_ptr, /*!< [in/out] Pointer to the RND context buffer. */ + CRYS_RND_WorkBuff_t *rndWorkBuff_ptr /*!< [in/out] Scratchpad for the RND module's work. */ +); + + +/****************************************************************************************/ +/*! +@brief Generates a random vector according to the algorithm defined in referenced standard [SP800-90] - 10.2.1.5.2 - CTR-DRBG. +The generation algorithm uses AES (FIPS-PUB 197) and Derivation Function (DF). + +\note +
    • The RND module must be instantiated prior to invocation of this API.
    • +
    • In the following cases, Reseeding operation must be performed prior to vector generation:
    • +
      • Prediction resistance is required.
      • +
      • The function returns CRYS_RND_RESEED_COUNTER_OVERFLOW_ERROR, stating that the Reseed Counter has passed its upper-limit (2^32-2).
    + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RND_GenerateVector( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure, which is part of the RND context structure. + Use rndContext->rndState field of the context for this parameter. */ + uint16_t outSizeBytes, /*!< [in] The size in bytes of the random vector required. The maximal size is 2^16 -1 bytes. */ + uint8_t *out_ptr /*!< [out] The pointer to output buffer. */ +); + + + +/**********************************************************************************************************/ +/*! +@brief Generates a random vector with specific limitations by testing candidates (described and used in FIPS 186-4: B.1.2, B.4.2 etc.). + +This function draws a random vector, compare it to the range limits, and if within range - return it in rndVect_ptr. +If outside the range, the function continues retrying until a conforming vector is found, or the maximal retries limit is exceeded. +If maxVect_ptr is provided, rndSizeInBits specifies its size, and the output vector must conform to the range [1 < rndVect < maxVect]. +If maxVect_ptr is NULL, rndSizeInBits specifies the exact required vector size, and the output vector must be the exact same +bit size (with its most significant bit = 1). +\note +The RND module must be instantiated prior to invocation of this API. + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RND_GenerateVectorInRange( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + uint32_t rndSizeInBits, /*!< [in] The size in bits of the random vector required. The allowed size in range 2 <= rndSizeInBits < 2^19-1, bits. */ + uint8_t *maxVect_ptr, /*!< [in] Pointer to the vector defining the upper limit for the random vector output, Given as little-endian byte array. + If not NULL, its actual size is treated as [(rndSizeInBits+7)/8] bytes and its value must be in range (3, 2^19) */ + uint8_t *rndVect_ptr /*!< [in/out] Pointer to the output buffer for the random vector. Must be at least [(rndSizeInBits+7)/8] bytes. + Treated as little-endian byte array. */ +); + + +/*************************************************************************************/ +/*! +@brief Used for adding additional input/personalization data provided by the user, +to be later used by the ::CRYS_RND_Instantiation/::CRYS_RND_Reseeding/::CRYS_RND_GenerateVector functions. + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RND_AddAdditionalInput( + void *rndState_ptr, /*!< [in/out] Pointer to the RND context state buffer. */ + uint8_t *additonalInput_ptr, /*!< [in] The Additional Input buffer. */ + uint16_t additonalInputSize /*!< [in] The size of the Additional Input buffer. It must + be <= CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS and a multiple of 4. */ +); + +/*! +@brief The CRYS_RND_EnterKatMode function sets KAT mode bit into StateFlag of global CRYS_RND_WorkingState structure. + +The user must call this function before calling functions performing KAT tests. + +\note Total size of entropy and nonce must be not great than 126 words (maximal size of entropy and nonce). + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_RND_EnterKatMode( + void *rndState_ptr, /*!< [in/out] Pointer to the RND context state buffer. */ + uint8_t *entrData_ptr, /*!< [in] Entropy data. */ + uint32_t entrSize, /*!< [in] Entropy size in bytes. */ + uint8_t *nonce_ptr, /*!< [in] Nonce. */ + uint32_t nonceSize, /*!< [in] Entropy size in bytes. */ + CRYS_RND_WorkBuff_t *workBuff_ptr /*!< [out] RND working buffer, must be the same buffer, which should be passed into + Instantiation/Reseeding functions. */ +); + +/**********************************************************************************************************/ +/*! +@brief The CRYS_RND_DisableKatMode function disables KAT mode bit into StateFlag of global CRYS_RND_State_t structure. + +The user must call this function after KAT tests before actual using RND module (Instantiation etc.). + +@return CRYS_OK on success. +@return A non-zero value from crys_rnd_error.h on failure. +*/ +CIMPORT_C void CRYS_RND_DisableKatMode( + void *rndState_ptr /*!< [in/out] Pointer to the RND state buffer. */ +); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /* #ifndef CRYS_RND_H */ + diff --git a/external/nrf_cc310_bl/include/crys_rnd_error.h b/external/nrf_cc310_bl/include/crys_rnd_error.h new file mode 100644 index 0000000..417eaff --- /dev/null +++ b/external/nrf_cc310_bl/include/crys_rnd_error.h @@ -0,0 +1,160 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef CRYS_RND_ERROR_H +#define CRYS_RND_ERROR_H + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/*! +@file +@brief This module contains the definitions of the CRYS RND errors. +@defgroup crys_rnd_error CryptoCell RND specific errors +@{ +@ingroup crys_rnd +*/ + + + +/************************ Defines ******************************/ +/*! RND module on the CRYS layer base address - 0x00F00C00 */ + +/*! Illegal output pointer.*/ +#define CRYS_RND_DATA_OUT_POINTER_INVALID_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x0UL) +/*! Random generation in range failed .*/ +#define CRYS_RND_CAN_NOT_GENERATE_RAND_IN_RANGE (CRYS_RND_MODULE_ERROR_BASE + 0x1UL) +/*! CPRNGT test failed.*/ +#define CRYS_RND_CPRNG_TEST_FAIL_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x2UL) +/*! Illegal additional data buffer. */ +#define CRYS_RND_ADDITIONAL_INPUT_BUFFER_NULL (CRYS_RND_MODULE_ERROR_BASE + 0x3UL) +/*! Illegal additional data size. */ +#define CRYS_RND_ADDITIONAL_INPUT_SIZE_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x4UL) +/*! Data size overflow. */ +#define CRYS_RND_DATA_SIZE_OVERFLOW_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x5UL) +/*! Illegal vector size. */ +#define CRYS_RND_VECTOR_SIZE_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x6UL) +/*! Reseed counter overflow - in case this error was returned instantiation or reseeding operation must be called. */ +#define CRYS_RND_RESEED_COUNTER_OVERFLOW_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x7UL) +/*! Instantiation was not yet called. */ +#define CRYS_RND_INSTANTIATION_NOT_DONE_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x8UL) +/*! TRNG loss of samples. */ +#define CRYS_RND_TRNG_LOSS_SAMPLES_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x9UL) +/*! TRNG Time exceeded limitations. */ +#define CRYS_RND_TRNG_TIME_EXCEED_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0xAUL) +/*! TRNG loss of samples and time exceeded limitations. */ +#define CRYS_RND_TRNG_LOSS_SAMPLES_AND_TIME_EXCEED_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0xBUL) +/*! RND is in Known Answer Test mode. */ +#define CRYS_RND_IS_KAT_MODE_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0xCUL) +/*! RND operation not supported. */ +#define CRYS_RND_OPERATION_IS_NOT_SUPPORTED_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0xDUL) +/*! RND validity check failed. */ +#define CRYS_RND_STATE_VALIDATION_TAG_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0xEUL) +/*! RND is not supported. */ +#define CRYS_RND_IS_NOT_SUPPORTED (CRYS_RND_MODULE_ERROR_BASE + 0xFUL) +/*! RND Init failed. */ +#define CRYS_RND_INIT_FAILED (CRYS_RND_MODULE_ERROR_BASE + 0x10UL) +/*! RND Init failed. */ +#define CRYS_RND_STARTUP_FAILED (CRYS_RND_MODULE_ERROR_BASE + 0x11UL) +/*! Instantiation Failed. */ +#define CRYS_RND_INSTANTIATION_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x12L) + + +/*! Illegal generate vector function pointer. */ +#define CRYS_RND_GEN_VECTOR_FUNC_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x14UL) + +/*! Illegal work buffer pointer. */ +#define CRYS_RND_WORK_BUFFER_PTR_INVALID_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x20UL) +/*! Illegal AES key size. */ +#define CRYS_RND_ILLEGAL_AES_KEY_SIZE_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x21UL) +/*! Illegal data pointer. */ +#define CRYS_RND_ILLEGAL_DATA_PTR_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x22UL) +/*! Illegal data size. */ +#define CRYS_RND_ILLEGAL_DATA_SIZE_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x23UL) +/*! Illegal parameter. */ +#define CRYS_RND_ILLEGAL_PARAMETER_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x24UL) +/*! Illegal RND state pointer. */ +#define CRYS_RND_STATE_PTR_INVALID_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x25UL) +/*! TRNG errors. */ +#define CRYS_RND_TRNG_ERRORS_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x26UL) +/*! Illegal context pointer. */ +#define CRYS_RND_CONTEXT_PTR_INVALID_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x27UL) + +/*! Illegal output vector pointer. */ +#define CRYS_RND_VECTOR_OUT_PTR_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x30UL) +/*! Illegal output vector size. */ +#define CRYS_RND_VECTOR_OUT_SIZE_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x31UL) +/*! Maximal vector size is too small. */ +#define CRYS_RND_MAX_VECTOR_IS_TOO_SMALL_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x32UL) +/*! Illegal Known Answer Tests parameters. */ +#define CRYS_RND_KAT_DATA_PARAMS_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x33UL) +/*! TRNG Known Answer Test not supported. */ +#define CRYS_RND_TRNG_KAT_NOT_SUPPORTED_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x34UL) +/*! SRAM memory is not defined. */ +#define CRYS_RND_SRAM_NOT_SUPPORTED_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x35UL) +/*! AES operation failure. */ +#define CRYS_RND_AES_ERROR (CRYS_RND_MODULE_ERROR_BASE + 0x36UL) + + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/external/nrf_cc310_bl/include/nrf_cc310_bl.h b/external/nrf_cc310_bl/include/nrf_cc310_bl.h new file mode 100644 index 0000000..b9fc491 --- /dev/null +++ b/external/nrf_cc310_bl/include/nrf_cc310_bl.h @@ -0,0 +1,52 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ +#ifndef NRF_CC310_BL_H__ +#define NRF_CC310_BL_H__ + +/**@file + * + * @defgroup nrf_cc310_bl CC310 bootloader API (nrf_cc310_bl) + * @brief This is a customized version of the CC310 API tailored to work with the + * @ref lib_bootloader. + * @{ + */ + +#include "nrf_cc310_bl_init.h" +#include "nrf_cc310_bl_hash_sha256.h" +#include "nrf_cc310_bl_ecdsa_verify_secp224r1.h" +#include "nrf_cc310_bl_ecdsa_verify_secp256r1.h" + +/** @} */ + +#endif //NRF_CC310_BL_H__ diff --git a/external/nrf_cc310_bl/include/nrf_cc310_bl_ecdsa_verify_common.h b/external/nrf_cc310_bl/include/nrf_cc310_bl_ecdsa_verify_common.h new file mode 100644 index 0000000..9ad6d02 --- /dev/null +++ b/external/nrf_cc310_bl/include/nrf_cc310_bl_ecdsa_verify_common.h @@ -0,0 +1,61 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ +#ifndef NRF_CC310_BL_ECDSA_VERIFY_COMMON_H__ +#define NRF_CC310_BL_ECDSA_VERIFY_COMMON_H__ + +/**@file + * + * @defgroup nrf_cc310_bl_ecdsa_verify_common nrf_cc310_bl ECDSA verify common declarations + * @ingroup nrf_cc310_bl + * @brief Common declarations for nrf_cc310_bl ECDSA verify APIs. + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_CC310_BL_ECDSA_CONTEXT_INITIALIZED (0xBBAA55DD) + +#define NRF_CC310_BL_ECDSA_VERIFY_CONTEXT_SIZE_SECP224R1 (140) //!< Macro for the size of the ECDSA Verify context. +#define NRF_CC310_BL_ECDSA_VERIFY_CONTEXT_SIZE_SECP256R1 (160) //!< Macro for the size of the ECDSA Verify context. + +#ifdef __cplusplus +} +#endif + +/** @} */ + + +#endif // NRF_CC310_BL_ECDSA_VERIFY_COMMON_H__ diff --git a/external/nrf_cc310_bl/include/nrf_cc310_bl_ecdsa_verify_secp224r1.h b/external/nrf_cc310_bl/include/nrf_cc310_bl_ecdsa_verify_secp224r1.h new file mode 100644 index 0000000..8068c72 --- /dev/null +++ b/external/nrf_cc310_bl/include/nrf_cc310_bl_ecdsa_verify_secp224r1.h @@ -0,0 +1,167 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ +#ifndef NRF_CC310_BL_ECDSA_VERIFY_SECP224R1_H__ +#define NRF_CC310_BL_ECDSA_VERIFY_SECP224R1_H__ + +/**@file + * + * @defgroup nrf_cc310_bl_ecdsa_verify_secp224r1 nrf_cc310_bl ECDSA verify secp224r1 types + * @ingroup nrf_cc310_bl + * @brief Type definitions and APIs for nrf_cc310_bl ECDSA verify using curve secp224r1. + * @{ + */ + +#include +#include "crys_error.h" +#include "nrf_cc310_bl_ecdsa_verify_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Structure holding the secp224r1 public key represented by X,Y coordinates (uncompressed). +*/ +typedef struct +{ + uint8_t x[28]; //!< Public key X coordinate in big-endian format. + uint8_t y[28]; //!< Public key Y coordinate in big-endian format. + +} nrf_cc310_bl_ecc_public_key_secp224r1_t; + + +/**@brief Structure holding secp224r1 signature represented by R,S. +*/ +typedef struct +{ + uint8_t r[28]; //!< Signature R part in big-endian format. + uint8_t s[28]; //!< Signature S part in big-endian format. + +} nrf_cc310_bl_ecc_signature_secp224r1_t; + + +/**@brief Type definition for a context structure for running an ECDSA verify operation using + * curve secp224r1. + */ +typedef struct +{ + uint32_t init_val; //!< Value indicating the initialized state of the context structure. + uint8_t context_buffer[NRF_CC310_BL_ECDSA_VERIFY_CONTEXT_SIZE_SECP224R1]; //!< Buffer containing the required memory for running the ECDSA verify operation. + +} nrf_cc310_bl_ecdsa_verify_context_secp224r1_t; + + +/**@brief Function for initializing the context information for an ECDSA verify operation + * using curve secp224r1. + * + * @note The memory that holds the context object must be allocated prior to this call. + * + * @param[in,out] p_context Pointer to the structure holding context information + * * for the ECDSA verify operation. + * @param[in] p_public_key Pointer to the structure holding the public key for the + * ECDSA verify operation. + * + * @retval CRYS_OK Context initialized succesfully. + * @retval CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR p_context was NULL. + * @retval CRYS_ECDSA_VERIFY_SIGNER_PUBL_KEY_VALIDATION_TAG_ERROR p_public_key was NULL. + */ +CRYSError_t nrf_cc310_bl_ecdsa_verify_init_secp224r1( + nrf_cc310_bl_ecdsa_verify_context_secp224r1_t * const p_context, + nrf_cc310_bl_ecc_public_key_secp224r1_t const * const p_public_key); + + +/**@brief Function for executing an ECDSA verify on secp224r1 with hash input. + * + * @note The ECDSA verify context structure must be initialized prior to this call + * using @ref nrf_cc310_bl_ecdsa_verify_init_secp224r1. + * + * @param[in,out] p_context Pointer to the structure holding context information for + * the ECDSA verify operation. + * @param[in] p_signature Pointer to the structure holding the signature to use for the +* ECDSA verify operation. + * @param[in] p_hash Pointer to the hash to use in the ECDSA verify operation. + * @param[in] hash_len Length of the hash to verify. + * + * @retval CRYS_OK Signature was successfully verified. + * @retval CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR p_context was NULL. + * @retval CRYS_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR p_context was not initialized. + * @retval CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_IN_PTR_ERROR p_signature was NULL. + * @retval CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_PTR_ERROR p_hash was NULL. + * @retval CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_SIZE_ERROR hash_len was invalid. + * @retval CRYS_ECDSA_VERIFY_INCONSISTENT_VERIFY_ERROR Signature verification failed. + */ +CRYSError_t nrf_cc310_bl_ecdsa_verify_hash_secp224r1( + nrf_cc310_bl_ecdsa_verify_context_secp224r1_t * const p_context, + nrf_cc310_bl_ecc_signature_secp224r1_t const * const p_signature, + uint8_t const * const p_hash, + uint32_t hash_len); + + +/**@brief Function for executing an ECDSA verify on secp224r1 with hash input in integrated form. + * + * @note This will run initialization of ECDSA context and run ECDSA verify in + * a single integrated step. + * + * @param[in,out] p_context Pointer to the structure holding context information + * for the ECDSA verify operation. + * @param[in] p_public_key Pointer to the structure holding the public key for + * the ECDSA verify operation. + * @param[in] p_signature Pointer to the structure holding the signature to use + * for the ECDSA verify operation. + * @param[in] p_hash Pointer to the hash to use in the ECDSA verify operation. + * @param[in] hash_len Length of the hash to verify. + * + * @retval CRYS_OK Signature was successfully verified. + * @retval CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR p_context was NULL. + * @retval CRYS_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR p_context was not initialized. + * @retval CRYS_ECDSA_VERIFY_SIGNER_PUBL_KEY_VALIDATION_TAG_ERROR + * p_public_key was NULL. + * @retval CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_IN_PTR_ERROR p_signature was NULL. + * @retval CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_PTR_ERROR p_hash was NULL. + * @retval CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_SIZE_ERROR hash_len was invalid. + * @retval CRYS_ECDSA_VERIFY_INCONSISTENT_VERIFY_ERROR Signature verification failed. + */ +CRYSError_t nrf_cc310_bl_ecdsa_verify_secp224r1( + nrf_cc310_bl_ecdsa_verify_context_secp224r1_t * const p_context, + nrf_cc310_bl_ecc_public_key_secp224r1_t const * const p_public_key, + nrf_cc310_bl_ecc_signature_secp224r1_t const * const p_signature, + uint8_t const * const p_hash, + uint32_t hash_len); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif // NRF_CC310_BL_ECDSA_VERIFY_SECP224R1_H__ diff --git a/external/nrf_cc310_bl/include/nrf_cc310_bl_ecdsa_verify_secp256r1.h b/external/nrf_cc310_bl/include/nrf_cc310_bl_ecdsa_verify_secp256r1.h new file mode 100644 index 0000000..cc89c41 --- /dev/null +++ b/external/nrf_cc310_bl/include/nrf_cc310_bl_ecdsa_verify_secp256r1.h @@ -0,0 +1,161 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ +#ifndef NRF_CC310_BL_ECDSA_VERIFY_SECP256R1_H__ +#define NRF_CC310_BL_ECDSA_VERIFY_SECP256R1_H__ + +/**@file + * + * @defgroup nrf_cc310_bl_ecdsa_verify_secp256r1 nrf_cc310_bl ECDSA verify secp256r1 types + * @ingroup nrf_cc310_bl + * @brief Type definitions and APIs for nrf_cc310_bl ECDSA verify using curve secp256r1. + * @{ + */ + +#include +#include "crys_error.h" +#include "nrf_cc310_bl_ecdsa_verify_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Structure holding the secp256r1 public key represented by X,Y coordinates. +*/ +typedef struct +{ + uint8_t x[32]; //!< Public key X coordinate in big-endian format. + uint8_t y[32]; //!< Public key Y coordinate in big-endian format. +} nrf_cc310_bl_ecc_public_key_secp256r1_t; + + +/**@brief Structure holding the secp256r1 signature represented by R,S values. +*/ +typedef struct +{ + uint8_t r[32]; //!< Signature R part in big-endian format. + uint8_t s[32]; //!< Signature S part in big-endian format. +} nrf_cc310_bl_ecc_signature_secp256r1_t; + + +/**@brief Structure holding memory required for allocation of CC310 ECDSA verify context + * using curve secp256r1. + */ +typedef struct +{ + uint32_t init_val; + uint8_t context_buffer[NRF_CC310_BL_ECDSA_VERIFY_CONTEXT_SIZE_SECP256R1]; +} nrf_cc310_bl_ecdsa_verify_context_secp256r1_t; + + +/**@brief Function for initializing the context information for an ECDSA verify operation. + * + * @note The memory that holds the context object must be allocated prior to this call. + * + * @param[in,out] p_context Pointer to the structure holding context information + * for the ECDSA verify operation. + * @param[in] p_public_key Pointer to the structure holding the public key for + * the ECDSA verify operation. + * + * @retval CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR p_context was NULL. + * @retval CRYS_ECDSA_VERIFY_SIGNER_PUBL_KEY_VALIDATION_TAG_ERROR p_public_key was NULL. + */ +CRYSError_t nrf_cc310_bl_ecdsa_verify_init_secp256r1( + nrf_cc310_bl_ecdsa_verify_context_secp256r1_t * const p_context, + nrf_cc310_bl_ecc_public_key_secp256r1_t const * const p_public_key); + + +/**@brief Function for executing an ECDSA verify operation using secp256r1 with hash input. + * + * @note The ECDSA verify context structure must be initialized prior to this call using + * @ref nrf_cc310_bl_ecdsa_verify_init_secp256r1. + * + * @param[in,out] p_context Pointer to the structure holding context information + * for the ECDSA verify operation. + * @param[in] p_signature Pointer to the structure holding the signature to use for + * the ECDSA verify operation. + * @param[in] p_hash Pointer to the hash to use in the ECDSA verify operation. + * @param[in] hash_len Length of the hash to verify. + * + * @retval CRYS_OK Signature was successfully verified. + * @retval CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR p_context was NULL. + * @retval CRYS_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR p_context was not initialized. + * @retval CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_IN_PTR_ERROR p_signature was NULL. + * @retval CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_PTR_ERROR p_hash was NULL. + * @retval CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_SIZE_ERROR hash_len was invalid. + * @retval CRYS_ECDSA_VERIFY_INCONSISTENT_VERIFY_ERROR Signature verification failed. + */ +CRYSError_t nrf_cc310_bl_ecdsa_verify_hash_secp256r1( + nrf_cc310_bl_ecdsa_verify_context_secp256r1_t * const p_context, + nrf_cc310_bl_ecc_signature_secp256r1_t const * const p_signature, + uint8_t const * const p_hash, + uint32_t hash_len); + +/**@brief Function for executing an ECDSA verify operation using secp256r1 with + * hash input in integrated form. + * + * @note This will run initialization of ECDSA context and run ECDSA verify in a single step. + * + * @param[in,out] p_context Pointer to the structure holding context information for + * the ECDSA verify operation. + * @param[in] p_public_key Pointer to the structure holding the public key for + * the ECDSA verify operation. + * @param[in] p_signature Pointer to the structure holding the signature to use + * for the ECDSA verify operation. + * @param[in] p_hash Pointer to the hash to use in the ECDSA verify operation. + * @param[in] hash_len Length of the hash to verify. + * + * @retval CRYS_OK Signature was successfully verified. + * @retval CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR p_context was NULL. + * @retval CRYS_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR p_context was not initialized. + * @retval CRYS_ECDSA_VERIFY_SIGNER_PUBL_KEY_VALIDATION_TAG_ERROR + * p_public_key was NULL. + * @retval CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_IN_PTR_ERROR p_signature was NULL. + * @retval CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_PTR_ERROR p_hash was NULL. + * @retval CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_SIZE_ERROR hash_len was invalid. + * @retval CRYS_ECDSA_VERIFY_INCONSISTENT_VERIFY_ERROR Signature verification failed. + */ +CRYSError_t nrf_cc310_bl_ecdsa_verify_secp256r1( + nrf_cc310_bl_ecdsa_verify_context_secp256r1_t * const p_context, + nrf_cc310_bl_ecc_public_key_secp256r1_t const * const p_public_key, + nrf_cc310_bl_ecc_signature_secp256r1_t const * const p_signature, + uint8_t const * const p_hash, + uint32_t hash_len); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif // NRF_CC310_BL_ECDSA_VERIFY_SECP256R1_H__ diff --git a/external/nrf_cc310_bl/include/nrf_cc310_bl_hash_common.h b/external/nrf_cc310_bl/include/nrf_cc310_bl_hash_common.h new file mode 100644 index 0000000..3fa9dda --- /dev/null +++ b/external/nrf_cc310_bl/include/nrf_cc310_bl_hash_common.h @@ -0,0 +1,60 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ +#ifndef NRF_CC310_BL_HASH_COMMON_H__ +#define NRF_CC310_BL_HASH_COMMON_H__ + +/**@file + * + * @defgroup nrf_cc310_bl_hash_common nrf_crypto_bl Hash common declarations + * @ingroup nrf_cc310_bl + * @brief Shared declarations used by nrf_cc310_bl for hash APIs. + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_CC310_BL_HASH_CONTEXT_INITIALIZED (0xBBAA55DD) //!< Value indicating that the hash context is initialized. +#define NRF_CC310_BL_HASH_CONTEXT_BUFFER_SIZE_SHA256 (112) //!< Size of internal representation of SHA-256 hash context. +#define NRF_CC310_BL_SHA256_DIGEST_SIZE_IN_WORDS (8) //!< Size of SHA-256 hash digest in words. +#define NRF_CC310_BL_SHA256_DIGEST_SIZE_IN_BYTES (32) //!< Size of SHA-256 hash digest in bytes. + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif // NRF_CC310_BL_HASH_COMMON_H__ diff --git a/external/nrf_cc310_bl/include/nrf_cc310_bl_hash_sha256.h b/external/nrf_cc310_bl/include/nrf_cc310_bl_hash_sha256.h new file mode 100644 index 0000000..199911b --- /dev/null +++ b/external/nrf_cc310_bl/include/nrf_cc310_bl_hash_sha256.h @@ -0,0 +1,120 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ +#ifndef NRF_CC310_BL_HASH_SHA256_H__ +#define NRF_CC310_BL_HASH_SHA256_H__ + +/**@file + * + * @defgroup nrf_cc310_bl_hash_sha256 nrf_cc310_bl Hash SHA-256 API + * @ingroup nrf_cc310_bl + * @brief Type definitions and public APIs for nrf_cc310_bl HASH using SHA-256. + * @{ + */ + +#include +#include "nrf_cc310_bl_hash_common.h" +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Structure to hold SHA-256 context information. + */ +typedef struct +{ + uint32_t init_val; + uint8_t context_buffer[NRF_CC310_BL_HASH_CONTEXT_BUFFER_SIZE_SHA256]; +} nrf_cc310_bl_hash_context_sha256_t; + + +/**@brief Array to hold SHA-256 hash digest. + */ +typedef uint8_t nrf_cc310_bl_hash_digest_sha256_t[NRF_CC310_BL_SHA256_DIGEST_SIZE_IN_BYTES]; + + +/**@brief Function for initializing the SHA-256 context. + * + * @note Memory pointed to in hash context must be allocated prior to this call. + * + * @param[in,out] p_hash_context Structure holding context information for + * the SHA-256 operation. + * + * @retval CRYS_OK If call was successful. + * @retval CRYS_HASH_INVALID_USER_CONTEXT_POINTER_ERROR p_hash_context was NULL. + */ +CRYSError_t nrf_cc310_bl_hash_sha256_init( + nrf_cc310_bl_hash_context_sha256_t * const p_hash_context); + + +/** @brief Function for running an update to the SHA-256 hash calculation. + * + * @param[in,out] p_hash_context Structure holding context information + * for the SHA-256 operation. + * + * @retval CRYS_OK If call was successful. + * @retval CRYS_HASH_INVALID_USER_CONTEXT_POINTER_ERROR p_hash_context was NULL. + * @retval CRYS_HASH_USER_CONTEXT_CORRUPTED_ERROR p_hash_context not initialized. + * @retval CRYS_HASH_LAST_BLOCK_ALREADY_PROCESSED_ERROR p_hash_context already finalized. + */ +CRYSError_t nrf_cc310_bl_hash_sha256_update( + nrf_cc310_bl_hash_context_sha256_t * const p_hash_context, + uint8_t const * p_src, + uint32_t len); + + +/** @brief Function for finalizing the hash calculation. + * + * @note Memory pointed to in hash digest must be allocated prior to this call. + * + * @param[in,out] p_hash_context Structure holding context information for + * the SHA-256 operation. + * @param[in,out] p_hash_digest Pointer to the structure holding SHA-256 + * hash digest. Data pointed to must be 32 bytes long. + * + * @retval CRYS_HASH_INVALID_USER_CONTEXT_POINTER_ERROR p_hash_context was NULL. + * @retval CRYS_HASH_USER_CONTEXT_CORRUPTED_ERROR p_hash_context was corrupted. + * @retval CRYS_HASH_INVALID_RESULT_BUFFER_POINTER_ERROR p_digest was NULL. + */ +CRYSError_t nrf_cc310_bl_hash_sha256_finalize( + nrf_cc310_bl_hash_context_sha256_t * const p_hash_context, + nrf_cc310_bl_hash_digest_sha256_t * const p_digest); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif // NRF_CC310_BL_HASH_SHA256_H__ diff --git a/external/nrf_cc310_bl/include/nrf_cc310_bl_init.h b/external/nrf_cc310_bl/include/nrf_cc310_bl_init.h new file mode 100644 index 0000000..e8ae3bc --- /dev/null +++ b/external/nrf_cc310_bl/include/nrf_cc310_bl_init.h @@ -0,0 +1,62 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ +#ifndef NRF_CC310_BL_INIT_H__ +#define NRF_CC310_BL_INIT_H__ + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@file + * + * @addtogroup nrf_cc310_bl + * @{ + * @brief Function for initializing the CC310 hardware and runtime library. + * + * @note Running this initialization is intended for cases where there + * is no direct requirement for the RNG subsystem (all operations are deterministic). + * + * @retval CRYS_OK Initialization was successful. + */ +CRYSError_t nrf_cc310_bl_init(void); + +#ifdef __cplusplus +} +#endif + +/** @} */ + + #endif // NRF_CC310_BL_INIT_H__ diff --git a/external/nrf_cc310_bl/include/sns_silib.h b/external/nrf_cc310_bl/include/sns_silib.h new file mode 100644 index 0000000..5760501 --- /dev/null +++ b/external/nrf_cc310_bl/include/sns_silib.h @@ -0,0 +1,101 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains all of the enums and definitions that are used for the + CryptoCell Lib init and finish APIs, as well as the APIs themselves. +@defgroup sns_silib CryptoCell library basic APIs +@{ +@ingroup cryptocell_api + +*/ + +#ifndef __SNS_SILIB_H__ +#define __SNS_SILIB_H__ + +#include "ssi_pal_types.h" +#include "crys_rnd.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! Definitions for error returns from SaSi_LibInit or SaSi_LibFini functions. */ +typedef enum { + SA_SILIB_RET_OK = 0, /*!< Success defintion.*/ + SA_SILIB_RET_EINVAL_CTX_PTR, /*!< Illegal context pointer.*/ + SA_SILIB_RET_EINVAL_WORK_BUF_PTR, /*!< Illegal work buffer pointer.*/ + SA_SILIB_RET_HAL, /*!< Error returned from HAL layer.*/ + SA_SILIB_RET_PAL, /*!< Error returned from PAL layer.*/ + SA_SILIB_RET_EINVAL_HW_VERSION, /*!< Invalid HW version. */ + SA_SILIB_RET_EINVAL_HW_SIGNATURE, /*!< Invalid HW signature. */ + SA_SILIB_RESERVE32B = 0x7FFFFFFFL /*!< Reserved.*/ +} SA_SilibRetCode_t; + + +/*! Internal defintion for the product register. */ +#define DX_VERSION_PRODUCT_BIT_SHIFT 0x18UL +/*! Internal defintion for the product register size. */ +#define DX_VERSION_PRODUCT_BIT_SIZE 0x8UL + + + +/*! +@brief This function Perform global initialization of the ARM CryptoCell 3xx runtime library; +it must be called once per ARM CryptoCell for 3xx cold boot cycle. + +\note The Mutexes, if used, are initialized by this API. Therefore, unlike the other APIs in the library, +this API is not thread-safe. +@return SA_SILIB_RET_OK on success. +@return A non-zero value in case of failure. +*/ +SA_SilibRetCode_t SaSi_LibInit(void); + +/*! +@brief This function finalize the library operations. It frees the associated resources (mutexes) and call hal and pal terminate functions. +in case of active instansiation - one must call CRYS_RND_UnInstantiation to clean the rnd state. +*/ +void SaSi_LibFini(void); + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /*__DX_CCLIB_H__*/ + diff --git a/external/nrf_cc310_bl/include/ssi_aes.h b/external/nrf_cc310_bl/include/ssi_aes.h new file mode 100644 index 0000000..a42b65f --- /dev/null +++ b/external/nrf_cc310_bl/include/ssi_aes.h @@ -0,0 +1,325 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! @file +@brief This file contains all of the enums and definitions that are used for the +CryptoCell AES APIs, as well as the APIs themselves. +@defgroup ssi_aes CryptoCell AES APIs +@{ +@ingroup cryptocell_api +*/ + +#ifndef SSI_AES_H +#define SSI_AES_H + +#include "ssi_pal_types.h" +#include "ssi_aes_error.h" +#include "ssi_aes_defs.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************ Defines ******************************/ + + +/************************ Enums ********************************/ + +/*! +Encrypt or Decrypt operation mode. +*/ +typedef enum { + /*! Encrypt operation. */ + SASI_AES_ENCRYPT = 0, + /*! Decrypt operation. */ + SASI_AES_DECRYPT = 1, + /*! Maximal number of operations. */ + SASI_AES_NUM_OF_ENCRYPT_MODES, + /*! Reserved. */ + SASI_AES_ENCRYPT_MODE_LAST = 0x7FFFFFFF +}SaSiAesEncryptMode_t; + +/*! +AES operation mode. +*/ +typedef enum { + SASI_AES_MODE_ECB = 0, /*!< ECB mode. */ + SASI_AES_MODE_CBC = 1, /*!< CBC mode. */ + SASI_AES_MODE_CBC_MAC = 2, /*!< CBC-MAC mode. */ + SASI_AES_MODE_CTR = 3, /*!< CTR mode. */ + SASI_AES_MODE_XCBC_MAC = 4, /*!< XCBC-MAC mode. */ + SASI_AES_MODE_CMAC = 5, /*!< CMAC mode. */ + SASI_AES_MODE_XTS = 6, /*!< XTS mode. */ + SASI_AES_MODE_CBC_CTS = 7, /*!< CBC-CTS mode. */ + SASI_AES_MODE_OFB = 8, /*!< OFB mode. */ + + /*! Maximal number of AES modes */ + SASI_AES_NUM_OF_OPERATION_MODES, + /*! Reserved. */ + SASI_AES_OPERATION_MODE_LAST = 0x7FFFFFFF +}SaSiAesOperationMode_t; + +/*! +AES padding type. +*/ +typedef enum { + SASI_AES_PADDING_NONE = 0, /*!< No padding. */ + SASI_AES_PADDING_PKCS7 = 1, /*!< PKCS7 padding. */ + + /*! Maximal number of AES padding modes */ + SASI_AES_NUM_OF_PADDING_TYPES, + /*! Reserved. */ + SASI_AES_PADDING_TYPE_LAST = 0x7FFFFFFF +}SaSiAesPaddingType_t; + +/*! +AES key type. +*/ +typedef enum { + SASI_AES_USER_KEY = 0, /*!< user key. */ + SASI_AES_PLATFORM_KEY = 1, /*!< Kplt hardware key. */ + SASI_AES_CUSTOMER_KEY = 2, /*!< Kcst hardware key. */ + + /*! Maximal number of AES key types */ + SASI_AES_NUM_OF_KEY_TYPES, + /*! Reserved. */ + SASI_AES_KEY_TYPE_LAST = 0x7FFFFFFF +}SaSiAesKeyType_t; + +/************************ Typedefs ****************************/ + +/*! Defines the IV buffer - 16 bytes array. */ +typedef uint8_t SaSiAesIv_t[SASI_AES_IV_SIZE_IN_BYTES]; + +/*! Defines the AES key data buffer. */ +typedef uint8_t SaSiAesKeyBuffer_t[SASI_AES_KEY_MAX_SIZE_IN_BYTES]; + +/************************ Structs ******************************/ + +/*! The user's context prototype - the argument type that is passed by the user + to the AES APIs. The context saves the state of the operation and must be saved by the user + till the end of the APIs flow*/ +typedef struct SaSiAesUserContext_t { + /*! Context buffer for internal usage. */ + uint32_t buff[SASI_AES_USER_CTX_SIZE_IN_WORDS]; +}SaSiAesUserContext_t; + + +/*! AES User Key Data. */ +typedef struct SaSiAesUserKeyData_t { + uint8_t * pKey; /*!< Pointer to the key. */ + size_t keySize; /*!< The key size in bytes. Valid values: +
    • For XTS mode - 32 or 64 byte, indicating the full size of the double key (2x128 or 2x256 bit).
    • +
    • For XCBC-MAC mode - 16 byte (limited by the standard).
    • +
    • For all other modes - 16, 24 or 32 byte.
    */ +}SaSiAesUserKeyData_t; + +/*! AES HW Key Data - this structure is likely to be changed when we'll start using it. */ +typedef struct SaSiAesHwKeyData_t { + size_t slotNumber; /*!< Slot number. */ +}SaSiAesHwKeyData_t; + + +/************************ Functions *****************************/ + +/*! +@brief This function is used to initialize an AES operation context. + To operate the AES machine, this must be the first API called. + +@return SASI_OK on success, +@return A non-zero value from ssi_aes_error.h on failure. +*/ +CIMPORT_C SaSiError_t SaSi_AesInit( + SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context buffer that is allocated by the caller and initialized by this API. + Should be used in all subsequent calls that are part of the same operation. */ + SaSiAesEncryptMode_t encryptDecryptFlag, /*!< [in] A flag specifying whether an AES Encrypt (SASI_AES_Encrypt) or Decrypt (SASI_AES_Decrypt) operation should be performed. + Must be set to CRYS_AES_Encrypt in CBC-MAC, XCBC-MAC and CMAC modes. */ + SaSiAesOperationMode_t operationMode, /*!< [in] The operation cipher/mode. */ + SaSiAesPaddingType_t paddingType /*!< [in] The padding type for AES operation: +
    • NONE - supported for all operation modes.
    • +
    • PKCS7 - supported for ECB, CBC, CBC-MAC operation modes.
    */ +); + + +/*! +@brief This function sets the key information for the AES operation, in the context that was initialized by SaSi_AesInit. +\note When FIPS certification mode is set to ON, and the mode is AES-XTS, weak keys are not allowed (128/256 lsb bits must be +different than 128/256 msb bits, according to the key size). +@return SASI_OK on success, +@return A non-zero value from ssi_aes_error.h on failure. +*/ +CIMPORT_C SaSiError_t SaSi_AesSetKey( + SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context, after it was initialized by SaSi_AesInit. */ + SaSiAesKeyType_t keyType, /*!< [in] The type of key to be used for the AES operation. + Currently only SASI_AES_USER_KEY is supported - the key is plaintext and provided in the pKeyData parameter. */ + void * pKeyData, /*!< [in] Pointer to the key data structure (to be casted to the relevant struct type). */ + size_t keyDataSize /*!< [in] The size of data passed in pKeyData in bytes. */ +); + + +/*! +@brief This function sets the IV, counter or tweak data for the following AES operation on the same context. + The context must be first initialized by SaSi_AesInit. + It must be called at least once prior to the first SaSi_AesBlock operation on the same context - for those ciphers that require it. + If needed, it can also be called to override the IV in the middle of a sequence of SaSi_AesBlock operations. + +@return SASI_OK on success, +@return A non-zero value from ssi_aes_error.h on failure. +*/ +CIMPORT_C SaSiError_t SaSi_AesSetIv( + SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context. */ + SaSiAesIv_t pIV /*!< [in] Pointer to the buffer of the IV, counter or tweak. +
    • For CBC, CBC-CTS, OFB and CBC-MAC modes - the IV value.
    • +
    • For CTR mode - the counter.
    • +
    • For XTS mode - the tweak value.
    • +
    • For all other modes - N/A.
    */ +); + + +/*! +@brief This function retrieves the current IV, counter or tweak from the AES context. + +@return SASI_OK on success, +@return A non-zero value from ssi_aes_error.h on failure. +*/ +CIMPORT_C SaSiError_t SaSi_AesGetIv( + SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context. */ + SaSiAesIv_t pIV /*!< [out] Pointer to the buffer of the IV, counter or tweak. +
    • For CBC, CBC-CTS, OFB and CBC-MAC modes - the IV value.
    • +
    • For CTR mode - the counter.
    • +
    • For XTS mode - the tweak value.
    • +
    • For all other modes - N/A.
    */ +); + + +/*! +@brief This function performs an AES operation on an input data buffer, according to the configuration defined in the context parameter. + It can be called as many times as needed, until all the input data is processed. + SaSi_AesInit, SaSi_AesSetKey, and for some ciphers SaSi_AesSetIv, must be called before + the first call to this API with the same context. + +@return SASI_OK on success, +@return A non-zero value from ssi_aes_error.h on failure. +*/ +CIMPORT_C SaSiError_t SaSi_AesBlock( + SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context. */ + uint8_t * pDataIn, /*!< [in] Pointer to the buffer of the input data to the AES. The pointer does not need to be aligned. + For TZ, the size of the scatter/gather list representing the data buffer is limited to 128 entries, + and the size of each entry is limited to 64KB (fragments larger than 64KB are broken into fragments <= 64KB). + For ARM CryptoCell 3xx, The buffer must be contiguous and limited to 64KB. */ + size_t dataInSize, /*!< [in] Size of the input data in bytes. +
    • For all modes except XTS, must be multiple of 16 bytes.
    • +
    • For XTS mode, only the following data sizes are supported: 64, 512, 520, 521, 1024 and 4096 bytes. + The data passed in a single SaSi_AesBlock call is considered to be a single XTS unit. + All subsequent calls to this API with the same context must use the same data size.
    */ + uint8_t * pDataOut /*!< [out] Pointer to the output buffer. The pointer does not need to be aligned. + For CBC-MAC, XCBC-MAC, CMAC modes it may be NULL. + For TZ, the size of the scatter/gather list representing the data buffer is limited to 128 entries, + and the size of each entry is limited to 64KB (fragments larger than 64KB are broken into fragments <= 64KB). + For ARM CryptoCell 3xx, The buffer must be contiguous and limited to 64KB. */ +); + + +/*! +@brief This function is used to finish AES operation. + + It processes the last data block if needed, finalizes the AES operation (cipher-specific), + and produces operation results (for MAC operations). + \note In case AES padding is used (PKCS#7) Din and Dout user's buffers must include extra space for + the padding scheme. + +@return SASI_OK on success, +@return A non-zero value from ssi_aes_error.h on failure. +*/ +CIMPORT_C SaSiError_t SaSi_AesFinish( + SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context. */ + size_t dataSize, /*!< [in] The size of the input data in bytes. +
    • For CBC-CTS mode, must be > 16. Can be <=16 only if this is the only data (no previous calls were + made to SaSi_AesBlock with the same context).
    • +
    • For XTS mode, the data size must conform to the dataInSize rules as listed for XTS under the + SaSi_AesBlock API, and match the data size passed in the previous calls to SaSi_AesBlock with the + same context.
    • +
    • For all other modes, zero is a valid size.
    • +
    • For ECB, CBC, CBC-MAC modes:
    • +
      • Must be >= 0, if direction is SASI_AES_ENCRYPT and padding type is SASI_AES_PADDING_PKCS7.
      • +
      • Must be >= 16 and a multiple of 16 bytes, if direction is SASI_AES_DECRYPT and padding type + is SASI_AES_PADDING_PKCS7.
      • +
      • Must be a multiple of 16 bytes, otherwise.
    */ + uint8_t * pDataIn, /*!< [in] Pointer of the input data buffer. + For TZ, the size of the scatter/gather list representing the data buffer is limited to 128 entries, + and the size of each entry is limited to 64KB (fragments larger than 64KB are broken into fragments <= 64KB). + For ARM CryptoCell 3xx, The buffer must be contiguous and limited to 64KB. */ + size_t dataInBuffSize, /*!< [in] Size of pDataIn buffer in bytes. +
    • Must be >= dataSize.
    • +
    • According to padding type, must be >= dataSize + padding. For PKCS7, padding size is + maximum SASI_AES_BLOCK_SIZE_IN_BYTES.
    */ + uint8_t * pDataOut, /*!< [out] Pointer to the output buffer. + For TZ, the size of the scatter/gather list representing the data buffer is limited to 128 entries, + and the size of each entry is limited to 64KB (fragments larger than 64KB are broken into fragments <= 64KB). + For ARM CryptoCell 3xx, The buffer must be contiguous and limited to 64KB. */ + size_t * dataOutBuffSize /*!< [in,out] In - Size of pDataOut buffer in bytes. + The output buffer size must be no less than: +
    • For CBC-MAC, XCBC-MAC, CMAC modes - 16 bytes (for MAC result).
    • +
    • For non-MAC modes - dataInBuffSize.
    + Out - The size in bytes of the actual output data: +
    • If direction is SASI_AES_ENCRYPT and padding type is SASI_AES_PADDING_PKCS7, it is the actual size + with the padding.
    • +
    • If direction is SASI_AES_DECRYPT and padding type is SASI_AES_PADDING_PKCS7, it is the size without + the padding.
    • +
    • For CBC-MAC, XCBC-MAC, CMAC modes - always 16 bytes.
    */ +); + + +/*! +@brief This function releases and crears resources after AES operations. + +@return SASI_OK on success, +@return A non-zero value from ssi_aes_error.h on failure. +*/ +CIMPORT_C SaSiError_t SaSi_AesFree( + SaSiAesUserContext_t * pContext /*!< [in] Pointer to the AES context. */ +); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /* #ifndef SSI_AES_H */ + diff --git a/external/nrf_cc310_bl/include/ssi_aes_defs.h b/external/nrf_cc310_bl/include/ssi_aes_defs.h new file mode 100644 index 0000000..02789d0 --- /dev/null +++ b/external/nrf_cc310_bl/include/ssi_aes_defs.h @@ -0,0 +1,83 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains definitions that are used for the ARM CryptoCell 3xx version of the CryptoCell AES APIs. +@defgroup ssi_aes_defs CryptoCell AES definitions +@{ +@ingroup ssi_aes + +*/ + +#ifndef SSI_AES_DEFS_H +#define SSI_AES_DEFS_H + +#include "ssi_pal_types.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************ Defines ******************************/ + +/*! The size of the user's context prototype (see ::SaSiAesUserContext_t) in words. */ +#define SASI_AES_USER_CTX_SIZE_IN_WORDS (4+4+7+4) + +/*! The AES block size in words. */ +#define SASI_AES_BLOCK_SIZE_IN_WORDS 4 +/*! The AES block size in bytes. */ +#define SASI_AES_BLOCK_SIZE_IN_BYTES (SASI_AES_BLOCK_SIZE_IN_WORDS * sizeof(uint32_t)) + +/*! The size of the IV buffer in words. */ +#define SASI_AES_IV_SIZE_IN_WORDS SASI_AES_BLOCK_SIZE_IN_WORDS +/*! The size of the IV buffer in bytes. */ +#define SASI_AES_IV_SIZE_IN_BYTES (SASI_AES_IV_SIZE_IN_WORDS * sizeof(uint32_t)) + +/*! The maximum size of the AES KEY in words. */ +#define SASI_AES_KEY_MAX_SIZE_IN_WORDS 4 +/*! The maximum size of the AES KEY in bytes. */ +#define SASI_AES_KEY_MAX_SIZE_IN_BYTES (SASI_AES_KEY_MAX_SIZE_IN_WORDS * sizeof(uint32_t)) + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /* #ifndef SSI_AES_DEFS_H */ diff --git a/external/nrf_cc310_bl/include/ssi_aes_error.h b/external/nrf_cc310_bl/include/ssi_aes_error.h new file mode 100644 index 0000000..11c6927 --- /dev/null +++ b/external/nrf_cc310_bl/include/ssi_aes_error.h @@ -0,0 +1,133 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains the definitions of the CryptoCell AES errors. +@defgroup ssi_aes_error CryptoCell AES specific errors +@{ +@ingroup ssi_aes +*/ + +#ifndef SSI_AES_ERROR_H +#define SSI_AES_ERROR_H + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************ Defines ******************************/ + +/* generic errors */ +/*! General fatal error. */ +#define SASI_FATAL_ERROR CRYS_FATAL_ERROR +/*! General out of resources error. */ +#define SASI_OUT_OF_RESOURCE_ERROR CRYS_OUT_OF_RESOURCE_ERROR +/*! General Illegal resource value error. */ +#define SASI_ILLEGAL_RESOURCE_VAL_ERROR CRYS_ILLEGAL_RESOURCE_VAL_ERROR + +/*! CRYS_AES_MODULE_ERROR_BASE - 0x00F00000. */ +/*! Illegal user context. */ +#define SASI_AES_INVALID_USER_CONTEXT_POINTER_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x00UL) +/*! Illegal IV or tweak pointer. */ +#define SASI_AES_INVALID_IV_OR_TWEAK_PTR_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x01UL) +/*! Illegal operation. */ +#define SASI_AES_ILLEGAL_OPERATION_MODE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x02UL) +/*! Illegal key size. */ +#define SASI_AES_ILLEGAL_KEY_SIZE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x03UL) +/*! Illegal key pointer. */ +#define SASI_AES_INVALID_KEY_POINTER_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x04UL) +/*! Unsupported key type. */ +#define SASI_AES_KEY_TYPE_NOT_SUPPORTED_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x05UL) +/*! Illegal operation. */ +#define SASI_AES_INVALID_ENCRYPT_MODE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x06UL) +/*! User context corrupted. */ +#define SASI_AES_USER_CONTEXT_CORRUPTED_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x07UL) +/*! Illegal data in pointer. */ +#define SASI_AES_DATA_IN_POINTER_INVALID_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x08UL) +/*! Illegal data out pointer. */ +#define SASI_AES_DATA_OUT_POINTER_INVALID_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x09UL) +/*! Illegal data in size. */ +#define SASI_AES_DATA_IN_SIZE_ILLEGAL (CRYS_AES_MODULE_ERROR_BASE + 0x0AUL) +/*! Illegal data out address. */ +#define SASI_AES_DATA_OUT_DATA_IN_OVERLAP_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0BUL) +/*! Illegal data in buffer size. */ +#define SASI_AES_DATA_IN_BUFFER_SIZE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0CUL) +/*! Illegal data out buffer size. */ +#define SASI_AES_DATA_OUT_BUFFER_SIZE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0DUL) +/*! Illegal padding type. */ +#define SASI_AES_ILLEGAL_PADDING_TYPE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0EUL) +/*! Incorrect padding. */ +#define SASI_AES_INCORRECT_PADDING_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0FUL) +/*! Output is corrupted. */ +#define SASI_AES_CORRUPTED_OUTPUT_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x10UL) +/*! Illegal output size. */ +#define SASI_AES_DATA_OUT_SIZE_POINTER_INVALID_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x11UL) +/*! Decryption operation is not permitted in this mode. */ +#define SASI_AES_DECRYPTION_NOT_ALLOWED_ON_THIS_MODE (CRYS_AES_MODULE_ERROR_BASE + 0x12UL) +/*! Additional block operation is not permitted. */ +#define SASI_AES_ADDITIONAL_BLOCK_NOT_PERMITTED_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x15UL) +/*! Illegal context size. */ +#define SASI_AES_CTX_SIZES_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x16UL) + +/*! Illegal parameters. */ +#define SASI_AES_ILLEGAL_PARAMS_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x60UL) +/*! Illegal CTR block offset. */ +#define SASI_AES_CTR_ILLEGAL_BLOCK_OFFSET_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x70UL) +/*! Illegal counter (in CTR mode). */ +#define SASI_AES_CTR_ILLEGAL_COUNTER_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x71UL) +/*! AES is not supported. */ +#define SASI_AES_IS_NOT_SUPPORTED (CRYS_AES_MODULE_ERROR_BASE + 0xFFUL) + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs *****************************/ + +/************************ Public Variables *********************/ + +/************************ Public Functions *********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /* #ifndef SSI_AES_ERROR_H */ diff --git a/external/nrf_cc310_bl/include/ssi_pal_types.h b/external/nrf_cc310_bl/include/ssi_pal_types.h new file mode 100644 index 0000000..ed9c333 --- /dev/null +++ b/external/nrf_cc310_bl/include/ssi_pal_types.h @@ -0,0 +1,115 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains the platform dependent definitions and types. +@defgroup ssi_pal_types CryptoCell PAL platform dependant types +@{ +@ingroup ssi_pal +*/ + +#ifndef SSI_PAL_TYPES_H +#define SSI_PAL_TYPES_H + +#include "ssi_pal_types_plat.h" + +/*! Boolean definition.*/ +typedef enum { + /*! Boolean false definition.*/ + SASI_FALSE = 0, + /*! Boolean true definition.*/ + SASI_TRUE = 1 +} SaSiBool; + +/*! Success definition. */ +#define SASI_SUCCESS 0UL +/*! Failure definition. */ +#define SASI_FAIL 1UL + +/*! Defintion of 1KB in bytes. */ +#define SASI_1K_SIZE_IN_BYTES 1024 +/*! Defintion of number of bits in a byte. */ +#define SASI_BITS_IN_BYTE 8 +/*! Defintion of number of bits in a 32bits word. */ +#define SASI_BITS_IN_32BIT_WORD 32 +/*! Defintion of number of bytes in a 32bits word. */ +#define SASI_32BIT_WORD_SIZE (sizeof(uint32_t)) + +/*! Success (OK) defintion. */ +#define SASI_OK SASI_SUCCESS + +/*! Macro that handles unused parameters in the code (to avoid compilation warnings). */ +#define SASI_UNUSED_PARAM(prm) ((void)prm) + +/*! Maximal uint32 value.*/ +#define SASI_MAX_UINT32_VAL (0xFFFFFFFF) + + +/* Minimum and Maximum macros */ +#ifdef min +/*! Definition for minimum. */ +#define CRYS_MIN(a,b) min( a , b ) +#else +/*! Definition for minimum. */ +#define CRYS_MIN( a , b ) ( ( (a) < (b) ) ? (a) : (b) ) +#endif + +#ifdef max +/*! Definition for maximum. */ +#define CRYS_MAX(a,b) max( a , b ) +#else +/*! Definition for maximum. */ +#define CRYS_MAX( a , b ) ( ( (a) > (b) ) ? (a) : (b) ) +#endif + +/*! Macro that calculates number of full bytes from bits (i.e. 7 bits are 1 byte). */ +#define CALC_FULL_BYTES(numBits) (((numBits) + (SASI_BITS_IN_BYTE -1))/SASI_BITS_IN_BYTE) +/*! Macro that calculates number of full 32bits words from bits (i.e. 31 bits are 1 word). */ +#define CALC_FULL_32BIT_WORDS(numBits) (((numBits) + (SASI_BITS_IN_32BIT_WORD -1))/SASI_BITS_IN_32BIT_WORD) +/*! Macro that calculates number of full 32bits words from bytes (i.e. 3 bytes are 1 word). */ +#define CALC_32BIT_WORDS_FROM_BYTES(sizeBytes) (((sizeBytes) + SASI_32BIT_WORD_SIZE - 1) / SASI_32BIT_WORD_SIZE) +/*! Macro that round up bits to 32bits words. */ +#define ROUNDUP_BITS_TO_32BIT_WORD(numBits) (CALC_FULL_32BIT_WORDS(numBits)*SASI_BITS_IN_32BIT_WORD) +/*! Macro that round up bits to bytes. */ +#define ROUNDUP_BITS_TO_BYTES(numBits) (CALC_FULL_BYTES(numBits)*SASI_BITS_IN_BYTE) +/*! Macro that round up bytes to 32bits words. */ +#define ROUNDUP_BYTES_TO_32BIT_WORD(numBytes) (SASI_32BIT_WORD_SIZE*(((numBytes)+SASI_32BIT_WORD_SIZE-1)/SASI_32BIT_WORD_SIZE)) + + +/** +@} + */ +#endif diff --git a/external/nrf_cc310_bl/include/ssi_pal_types_plat.h b/external/nrf_cc310_bl/include/ssi_pal_types_plat.h new file mode 100644 index 0000000..50e7e40 --- /dev/null +++ b/external/nrf_cc310_bl/include/ssi_pal_types_plat.h @@ -0,0 +1,57 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! @file +@brief This file contains basic type definitions that are platform dependent. +*/ +#ifndef SSI_PAL_TYPES_PLAT_H +#define SSI_PAL_TYPES_PLAT_H +/* Host specific types for standard (ISO-C99) compilant platforms */ + +#include +#include +#include + +typedef uintptr_t SaSiVirtAddr_t; +typedef uint32_t SaSiBool_t; +typedef uint32_t SaSiStatus; + +#define SaSiError_t SaSiStatus +#define SASI_INFINITE 0xFFFFFFFF + +#define CEXPORT_C +#define CIMPORT_C + +#endif /*SSI_PAL_TYPES_PLAT_H*/ diff --git a/external/nrf_cc310_bl/lib/cortex-m4/hard-float/libnrf_cc310_bl_0.9.13.a b/external/nrf_cc310_bl/lib/cortex-m4/hard-float/libnrf_cc310_bl_0.9.13.a new file mode 100644 index 0000000..089832e Binary files /dev/null and b/external/nrf_cc310_bl/lib/cortex-m4/hard-float/libnrf_cc310_bl_0.9.13.a differ diff --git a/external/nrf_cc310_bl/lib/cortex-m4/hard-float/no-interrupts/libnrf_cc310_bl_0.9.13.a b/external/nrf_cc310_bl/lib/cortex-m4/hard-float/no-interrupts/libnrf_cc310_bl_0.9.13.a new file mode 100644 index 0000000..2f40717 Binary files /dev/null and b/external/nrf_cc310_bl/lib/cortex-m4/hard-float/no-interrupts/libnrf_cc310_bl_0.9.13.a differ diff --git a/external/nrf_cc310_bl/lib/cortex-m4/hard-float/short-wchar/libnrf_cc310_bl_0.9.13.a b/external/nrf_cc310_bl/lib/cortex-m4/hard-float/short-wchar/libnrf_cc310_bl_0.9.13.a new file mode 100644 index 0000000..2f15a08 Binary files /dev/null and b/external/nrf_cc310_bl/lib/cortex-m4/hard-float/short-wchar/libnrf_cc310_bl_0.9.13.a differ diff --git a/external/nrf_cc310_bl/lib/cortex-m4/hard-float/short-wchar/no-interrupts/libnrf_cc310_bl_0.9.13.a b/external/nrf_cc310_bl/lib/cortex-m4/hard-float/short-wchar/no-interrupts/libnrf_cc310_bl_0.9.13.a new file mode 100644 index 0000000..d7cd0a1 Binary files /dev/null and b/external/nrf_cc310_bl/lib/cortex-m4/hard-float/short-wchar/no-interrupts/libnrf_cc310_bl_0.9.13.a differ diff --git a/external/nrf_cc310_bl/lib/cortex-m4/hard-float/short-wchar/no-interrupts/nrf_cc310_bl_0.9.13.lib b/external/nrf_cc310_bl/lib/cortex-m4/hard-float/short-wchar/no-interrupts/nrf_cc310_bl_0.9.13.lib new file mode 100644 index 0000000..d7cd0a1 Binary files /dev/null and b/external/nrf_cc310_bl/lib/cortex-m4/hard-float/short-wchar/no-interrupts/nrf_cc310_bl_0.9.13.lib differ diff --git a/external/nrf_cc310_bl/lib/cortex-m4/hard-float/short-wchar/nrf_cc310_bl_0.9.13.lib b/external/nrf_cc310_bl/lib/cortex-m4/hard-float/short-wchar/nrf_cc310_bl_0.9.13.lib new file mode 100644 index 0000000..2f15a08 Binary files /dev/null and b/external/nrf_cc310_bl/lib/cortex-m4/hard-float/short-wchar/nrf_cc310_bl_0.9.13.lib differ diff --git a/external/nrf_cc310_bl/lib/cortex-m4/soft-float/libnrf_cc310_bl_0.9.13.a b/external/nrf_cc310_bl/lib/cortex-m4/soft-float/libnrf_cc310_bl_0.9.13.a new file mode 100644 index 0000000..8126449 Binary files /dev/null and b/external/nrf_cc310_bl/lib/cortex-m4/soft-float/libnrf_cc310_bl_0.9.13.a differ diff --git a/external/nrf_cc310_bl/lib/cortex-m4/soft-float/no-interrupts/libnrf_cc310_bl_0.9.13.a b/external/nrf_cc310_bl/lib/cortex-m4/soft-float/no-interrupts/libnrf_cc310_bl_0.9.13.a new file mode 100644 index 0000000..5e71c7e Binary files /dev/null and b/external/nrf_cc310_bl/lib/cortex-m4/soft-float/no-interrupts/libnrf_cc310_bl_0.9.13.a differ diff --git a/external/nrf_cc310_bl/lib/cortex-m4/soft-float/short-wchar/libnrf_cc310_bl_0.9.13.a b/external/nrf_cc310_bl/lib/cortex-m4/soft-float/short-wchar/libnrf_cc310_bl_0.9.13.a new file mode 100644 index 0000000..2149fae Binary files /dev/null and b/external/nrf_cc310_bl/lib/cortex-m4/soft-float/short-wchar/libnrf_cc310_bl_0.9.13.a differ diff --git a/external/nrf_cc310_bl/lib/cortex-m4/soft-float/short-wchar/no-interrupts/libnrf_cc310_bl_0.9.13.a b/external/nrf_cc310_bl/lib/cortex-m4/soft-float/short-wchar/no-interrupts/libnrf_cc310_bl_0.9.13.a new file mode 100644 index 0000000..5bf3377 Binary files /dev/null and b/external/nrf_cc310_bl/lib/cortex-m4/soft-float/short-wchar/no-interrupts/libnrf_cc310_bl_0.9.13.a differ diff --git a/external/nrf_cc310_bl/lib/cortex-m4/soft-float/short-wchar/no-interrupts/nrf_cc310_bl_0.9.13.lib b/external/nrf_cc310_bl/lib/cortex-m4/soft-float/short-wchar/no-interrupts/nrf_cc310_bl_0.9.13.lib new file mode 100644 index 0000000..5bf3377 Binary files /dev/null and b/external/nrf_cc310_bl/lib/cortex-m4/soft-float/short-wchar/no-interrupts/nrf_cc310_bl_0.9.13.lib differ diff --git a/external/nrf_cc310_bl/lib/cortex-m4/soft-float/short-wchar/nrf_cc310_bl_0.9.13.lib b/external/nrf_cc310_bl/lib/cortex-m4/soft-float/short-wchar/nrf_cc310_bl_0.9.13.lib new file mode 100644 index 0000000..2149fae Binary files /dev/null and b/external/nrf_cc310_bl/lib/cortex-m4/soft-float/short-wchar/nrf_cc310_bl_0.9.13.lib differ diff --git a/external/nrf_cc310_bl/lib/license.txt b/external/nrf_cc310_bl/lib/license.txt new file mode 100644 index 0000000..d45aeb3 --- /dev/null +++ b/external/nrf_cc310_bl/lib/license.txt @@ -0,0 +1,28 @@ +ARM Object Code and Header Files License +Version 1.0 + +Redistribution. + +Redistribution and use of object code, header files, and +documentation, without modification, are permitted provided that the following +conditions are met: +1) Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. +2) Unless to the extent explicitly permitted by law, no reverse + engineering, decompilation, or disassembly of is permitted. +3) Redistribution and use is permitted solely for the purpose of + developing or executing applications that are targeted for use + on an ARM-based product. + + DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/external/nrf_cc310_bl/license.txt b/external/nrf_cc310_bl/license.txt new file mode 100644 index 0000000..d45aeb3 --- /dev/null +++ b/external/nrf_cc310_bl/license.txt @@ -0,0 +1,28 @@ +ARM Object Code and Header Files License +Version 1.0 + +Redistribution. + +Redistribution and use of object code, header files, and +documentation, without modification, are permitted provided that the following +conditions are met: +1) Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. +2) Unless to the extent explicitly permitted by law, no reverse + engineering, decompilation, or disassembly of is permitted. +3) Redistribution and use is permitted solely for the purpose of + developing or executing applications that are targeted for use + on an ARM-based product. + + DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/external/nrf_oberon/include/mbedtls/chacha20_alt.h b/external/nrf_oberon/include/mbedtls/chacha20_alt.h new file mode 100644 index 0000000..2ce419d --- /dev/null +++ b/external/nrf_oberon/include/mbedtls/chacha20_alt.h @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CHACHA20_ALT_H +#define CHACHA20_ALT_H + +#include "mbedtls/config.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct mbedtls_chacha20_context +{ + uint8_t key[32]; + uint8_t nonce[12]; + uint32_t count; + uint8_t cipher[64]; + size_t bytes; +} +mbedtls_chacha20_context; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/nrf_oberon/include/mbedtls/ecjpake_alt.h b/external/nrf_oberon/include/mbedtls/ecjpake_alt.h new file mode 100644 index 0000000..20c5da5 --- /dev/null +++ b/external/nrf_oberon/include/mbedtls/ecjpake_alt.h @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_mbed_tls_ecjpake Oberon Mbed ECJPAKE APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations for an alternate implementation of EC-JPAKE for mbed TLS. + */ + +#ifndef ECJPAKE_ALT_H +#define ECJPAKE_ALT_H + +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#else +#include "mbedtls/config.h" +#endif + +#include "mbedtls/ecp.h" +#include "mbedtls/md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define OBERON_ECJPAKE_P256_SECRET_KEY_SIZE (32) //!< ECJPAKE P-256 secret key size in bytes. +#define OBERON_ECJPAKE_P256_PUBLIC_KEY_SIZE (64) //!< ECJPAKE P-256 public key size in bytes. + +/* @brief Oberon replacement ECJPAKE context */ +typedef struct mbedtls_ecjpake_context { + mbedtls_ecjpake_role role; //!< Role, either client or server. + int point_format; //!< Point format + unsigned char secret[OBERON_ECJPAKE_P256_SECRET_KEY_SIZE]; //!< Secret. + unsigned char s_key2[OBERON_ECJPAKE_P256_SECRET_KEY_SIZE]; //!< Secret key 2. + unsigned char p_key1[OBERON_ECJPAKE_P256_PUBLIC_KEY_SIZE]; //!< Public key 1. + unsigned char p_key2[OBERON_ECJPAKE_P256_PUBLIC_KEY_SIZE]; //!< Public key 2. + unsigned char r_key1[OBERON_ECJPAKE_P256_PUBLIC_KEY_SIZE]; //!< Remote key 1. + unsigned char r_key2[OBERON_ECJPAKE_P256_PUBLIC_KEY_SIZE]; //!< Remote key 2. + unsigned char r_key3[OBERON_ECJPAKE_P256_PUBLIC_KEY_SIZE]; //!< Remote key 3. +} mbedtls_ecjpake_context; + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef ECJPAKE_ALT_H */ + +/** @} */ diff --git a/external/nrf_oberon/include/mbedtls/poly1305_alt.h b/external/nrf_oberon/include/mbedtls/poly1305_alt.h new file mode 100644 index 0000000..dc12a4e --- /dev/null +++ b/external/nrf_oberon/include/mbedtls/poly1305_alt.h @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef POLY1305_ALT_H +#define POLY1305_ALT_H + +#include "mbedtls/config.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct mbedtls_poly1305_context +{ + uint32_t state[5]; + uint8_t key[32]; + uint8_t data[16]; + size_t bytes; +} mbedtls_poly1305_context; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/nrf_oberon/include/mbedtls/sha1_alt.h b/external/nrf_oberon/include/mbedtls/sha1_alt.h new file mode 100644 index 0000000..fa81764 --- /dev/null +++ b/external/nrf_oberon/include/mbedtls/sha1_alt.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2020 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_mbed_tls_sha1 Oberon Mbed TLS SHA-1 type declarations + * @ingroup nrf_oberon + * @{ + * @brief Type declarations for an alternate implementation of SHA-1 for mbed TLS. + */ + + +#ifndef SHA1_ALT_H +#define SHA1_ALT_H + +#include + +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#else +#include "mbedtls/config.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define OBERON_SHA1_CONTEXT_SIZE_WORDS (24) //!< SHA-1 context size in words. + +/* @brief Oberon replacement SHA-1 context */ +typedef struct mbedtls_sha1_context { + uint32_t data[OBERON_SHA1_CONTEXT_SIZE_WORDS]; //!< Opaque SHA-1 context. +} mbedtls_sha1_context; + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef SHA1_ALT_H */ + +/** @} */ diff --git a/external/nrf_oberon/include/mbedtls/sha256_alt.h b/external/nrf_oberon/include/mbedtls/sha256_alt.h new file mode 100644 index 0000000..0737d07 --- /dev/null +++ b/external/nrf_oberon/include/mbedtls/sha256_alt.h @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_mbed_tls_sha256 Oberon Mbed TLS SHA-256 type declarations + * @ingroup nrf_oberon + * @{ + * @brief Type declarations for an alternate implementation of SHA-256 for Mbed TLS. + */ + +#ifndef SHA256_ALT_H +#define SHA256_ALT_H + +#include + +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#else +#include "mbedtls/config.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define OCRYPTO_SHA256_CONTEXT_SIZE_WORDS (27) //!< SHA-256 context size in words. + +/* @brief Oberon replacement SHA-256 context */ +typedef struct mbedtls_sha256_context { + uint32_t data[OCRYPTO_SHA256_CONTEXT_SIZE_WORDS]; //!< Opaque SHA-256 context. + int is224; +} mbedtls_sha256_context; + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef SHA256_ALT_H */ + +/** @} */ diff --git a/external/nrf_oberon/include/ocrypto_aes_cbc.h b/external/nrf_oberon/include/ocrypto_aes_cbc.h new file mode 100644 index 0000000..c04d012 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_aes_cbc.h @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_aes_cbc AES CBC APIs + * @ingroup nrf_oberon_aes + * @{ + * @brief Type definitions and APIS for AES CBC (AES Cipher Block Chaining) + * + * AES (advanced encryption standard) is a symmetric encryption algorithm standardized by NIST. + * AES transfers a 128-bit block of data into an encrypted block of the same size. + * + * AES-CBC (AES Cipher Block Chaining) is an AES block cipher mode which avoids the problems of the + * ECB mode by xoring each plaintext block with the previous ciphertext block before being encrypted. + */ + +#ifndef OCRYPTO_AES_CBC_H +#define OCRYPTO_AES_CBC_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * AES-CBC encryption. + * + * @param[out] ct Cyphertext. + * @param pt Plaintext. + * @param pt_len Plaintext length. + * @param key AES key. + * @param size Key size (16, 24, or 32). + * @param iv Initial vector. + * + * @remark @p ct may be same as @p pt. + */ +void ocrypto_aes_cbc_encrypt ( + uint8_t* ct, const uint8_t* pt, size_t pt_len, const uint8_t *key, size_t size, const uint8_t iv[16]); + +/** + * AES-CBC decryption. + * + * @param[out] pt Plaintext. + * @param ct Cyphertext. + * @param ct_len Cyphertext length. + * @param key AES key. + * @param size Key size (16, 24, or 32). + * @param iv Initial vector. + * + * @remark @p ct may be same as @p pt. + */ +void ocrypto_aes_cbc_decrypt ( + uint8_t* pt, const uint8_t* ct, size_t ct_len, const uint8_t *key, size_t size, const uint8_t iv[16]); + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_AES_CBC_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_aes_ccm.h b/external/nrf_oberon/include/ocrypto_aes_ccm.h new file mode 100644 index 0000000..84049ae --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_aes_ccm.h @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_aes_ccm AES CCM APIs + * @ingroup nrf_oberon_aes + * @{ + * @brief Type definitions and APIS for AES CCM (AES counter mode with CBC-MAC) + * + * AES (advanced encryption standard) is a symmetric encryption algorithm standardized by NIST. + * AES transfers a 128-bit block of data into an encrypted block of the same size. + * + * AES-CCM (AES counter mode with CBC-MAC) is an AES mode which effectively turns the block + * cipher into a stream cipher. The AES block cipher primitive is used in CTR mode for + * encryption and decryption. In addition an AES CBC-MAC is used for authentication. + */ + +#ifndef OCRYPTO_AES_CCM_H +#define OCRYPTO_AES_CCM_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * AES-CCM encryption. + * + * @param[out] ct Cyphertext. + * @param[out] tag Authentication tag. + * @param tag_len Tag length (4, 6, 8, 10, 12, 14, or 16). + * @param pt Plaintext. + * @param pt_len Plaintext length, 0 <= @p pt_len < 2^(8*(15-n_len)). + * @param key AES key. + * @param size Key size (16, 24, or 32). + * @param nonce Nonce. + * @param n_len Nonce length, 7 <= @p n_len <= 13. + * @param aa Additional authentication data. + * @param aa_len Additional authentication data length. + * + * @remark @p ct may be same as @p pt. + */ +void ocrypto_aes_ccm_encrypt ( + uint8_t *ct, + uint8_t *tag, size_t tag_len, + const uint8_t *pt, size_t pt_len, + const uint8_t *key, size_t size, + const uint8_t *nonce, size_t n_len, + const uint8_t *aa, size_t aa_len); + +/** + * AES-CCM decryption. + * + * @param[out] pt Plaintext. + * @param tag Authentication tag. + * @param tag_len Tag length (4, 6, 8, 10, 12, 14, or 16). + * @param ct Cyphertext. + * @param ct_len Cyphertext length, 0 <= @p ct_len < 2^(8*(15-n_len)). + * @param key AES key. + * @param size Key size (16, 24, or 32). + * @param nonce Nonce. + * @param n_len Nonce length, 7 <= @p n_len <= 13. + * @param aa Additional authentication data. + * @param aa_len Additional authentication data length. + * + * @retval 0 If @p tag is valid. + * @retval -1 Otherwise. + * + * @remark @p ct may be same as @p pt. + */ +int ocrypto_aes_ccm_decrypt ( + uint8_t *pt, + const uint8_t *tag, size_t tag_len, + const uint8_t *ct, size_t ct_len, + const uint8_t *key, size_t size, + const uint8_t *nonce, size_t n_len, + const uint8_t *aa, size_t aa_len); + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_AES_CCM_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_aes_cmac.h b/external/nrf_oberon/include/ocrypto_aes_cmac.h new file mode 100644 index 0000000..5d1632e --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_aes_cmac.h @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_aes_cmac AES CMAC APIs + * @ingroup nrf_oberon_aes + * @{ + * @brief Type definitions and APIS for AES CMAC (AES Cipher-based Message Authentication Code) + * + * AES (advanced encryption standard) is a symmetric encryption algorithm standardized by NIST. + * AES transfers a 128-bit block of data into an encrypted block of the same size. + * + * AES-CMAC (AES Cipher-based Message Authentication Code) is a block cipher-based message + * authentication code algorithm. The AES block cipher primitive is used in variant of the + * CBC mode to get the authentication tag. + */ + +#ifndef OCRYPTO_AES_CMAC_H +#define OCRYPTO_AES_CMAC_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Length of the pseudo random function. + */ +#define ocrypto_aes_cmac_prf128_BYTES (16) + +/** + * AES-CMAC authentication algorithm. + * + * @param[out] tag Resulting tag. + * @param tag_len Tag length, 0 < @p tag_len <= 16. + * @param msg Message to authenticate. + * @param msg_len Message length. + * @param key AES key. + * @param size Key size (16, 24, or 32). + */ +void ocrypto_aes_cmac_authenticate ( + uint8_t *tag, size_t tag_len, + const uint8_t *msg, size_t msg_len, + const uint8_t *key, size_t size); + +/** + * AES-CMAC-PRF-128 pseudo random function algorithm. + * + * @param[out] prf 16 byte PRF output. + * @param msg Message input. + * @param msg_len Message length. + * @param key Key. + * @param key_len Key length. + */ +void ocrypto_aes_cmac_prf128 ( + uint8_t prf[ocrypto_aes_cmac_prf128_BYTES], + const uint8_t *msg, size_t msg_len, + const uint8_t *key, size_t key_len); + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_AES_CMAC_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_aes_ctr.h b/external/nrf_oberon/include/ocrypto_aes_ctr.h new file mode 100644 index 0000000..8b996a0 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_aes_ctr.h @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_aes AES - Advanced Encryption Standard APIs + * @ingroup nrf_oberon + * @{ + * @brief AES (advanced encryption standard) is a symmetric encryption algorithm standardized by NIST. + * AES transfers a 128-bit block of data into an encrypted block of the same size. + * @} + * + * @defgroup nrf_oberon_aes_ctr AES-CTR - AES Counter Mode + * @ingroup nrf_oberon_aes + * @{ + * @brief Type definitions and APIs for AES-CTR (AES Counter mode). + * + * AES (advanced encryption standard) is a symmetric encryption algorithm standardized by NIST. + * AES transfers a 128-bit block of data into an encrypted block of the same size. + * + * AES-CTR (AES counter mode) is an AES mode which effectively turns the block cipher into a stream + * cipher. The AES block encryption is used on a value which is incremented for each new block. + * The resulting cypher stream is then xor combined with the plaintext to get the ciphertext. + * In contrast to AES itself, encryption and decryption operations are identical for AES-CTR. + */ + +#ifndef OCRYPTO_AES_CTR_H +#define OCRYPTO_AES_CTR_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@cond */ +typedef struct { + uint32_t xkey[60]; + uint8_t counter[16]; + uint8_t cypher[16]; + uint8_t size; // Key size (16, 24, or 32 bytes). + uint32_t valid; // Valid bytes in cypher. +} ocrypto_aes_ctr_ctx; +/**@endcond */ + + +/**@name Incremental AES-CTR encryption/decryption. + * + * This group of functions can be used to incrementally compute the + * AES-CTR encryption/decryption for a given message. + */ +/**@{*/ + +/** + * AES-CTR initialization. + * + * The context @p ctx is initialized using the given key @p key and initial vector @p iv. + * + * @param[out] ctx Context. + * @param key AES key. + * @param size Key size (16, 24, or 32 bytes). + * @param iv Initial vector. + */ +void ocrypto_aes_ctr_init(ocrypto_aes_ctr_ctx *ctx, const uint8_t *key, size_t size, const uint8_t iv[16]); + +/** + * AES-CTR incremental encryption. + * + * The plaintext @p pt is encrypted to the ciphertext @p ct using the context @p ctx. + * + * This function can be called repeatedly until the whole message is processed. + * + * @param ctx Context. + * @param[out] ct Ciphertext. + * @param pt Plaintext. + * @param pt_len Length of @p pt and @p ct. + * + * @remark @p ct and @p pt can point to the same address. + * @remark Initialization of the context @p ctx through + * @c ocrypto_aes_ctr_init is required before this function can be called. + */ +void ocrypto_aes_ctr_encrypt(ocrypto_aes_ctr_ctx *ctx, uint8_t* ct, const uint8_t* pt, size_t pt_len); + +/** + * AES-CTR incremental decryption. + * + * The ciphertext @p ct is decrypted to the plaintext @p pt using the context @p ctx. + * + * This function can be called repeatedly until the whole message is processed. + * + * @param ctx Context. + * @param[out] pt Plaintext. + * @param ct Ciphertext. + * @param ct_len Length of @p ct and @p pt. + * + * @remark @p ct and @p pt can point to the same address. + * @remark Initialization of the context @p ctx through + * @c ocrypto_aes_ctr_init is required before this function can be called. + */ +void ocrypto_aes_ctr_decrypt(ocrypto_aes_ctr_ctx *ctx, uint8_t* pt, const uint8_t* ct, size_t ct_len); +/**@}*/ + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_AES_CTR_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_aes_eax.h b/external/nrf_oberon/include/ocrypto_aes_eax.h new file mode 100644 index 0000000..d63d981 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_aes_eax.h @@ -0,0 +1,118 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_aes_eax AES EAX APIs + * @ingroup nrf_oberon_aes + * @{ + * @brief Type definitions and APIS for AES EAX (Encrypt-then-authenticate-then-translate) + * + * AES (advanced encryption standard) is a symmetric encryption algorithm standardized by NIST. + * AES transfers a 128-bit block of data into an encrypted block of the same size. + * + * AES-EAX (encrypt-then-authenticate-then-translate) is an AES mode which effectively turns the + * block cipher into a stream cipher. The AES block cipher primitive is used in CTR mode for + * encryption and as OMAC for authentication over each block. + */ + +#ifndef OCRYPTO_AES_EAX_H +#define OCRYPTO_AES_EAX_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * AES-EAX encryption. + * + * @param[out] ct Cyphertext. + * @param[out] tag Authentication tag. + * @param pt Plaintext. + * @param pt_len Plaintext length. + * @param key AES key. + * @param size Key size (16, 24, or 32 bytes). + * @param iv Initial vector. + * @param iv_len Initial vector length. + * @param aa Additional authentication data. + * @param aa_len Additional authentication data length. + * + * @remark @p ct and @p pt can point to the same address. + */ +void ocrypto_aes_eax_encrypt ( + uint8_t* ct, uint8_t tag[16], const uint8_t* pt, size_t pt_len, const uint8_t *key, size_t size, + const uint8_t* iv, size_t iv_len, const uint8_t *aa, size_t aa_len); + +/** + * AES-EAX decryption. + * + * @param[out] pt Plaintext. + * @param tag Authentication tag. + * @param ct Cyphertext. + * @param ct_len Cyphertext length. + * @param key AES key. + * @param size Key size (16, 24, or 32 bytes). + * @param iv Initial vector. + * @param iv_len Initial vector length. + * @param aa Additional authentication data. + * @param aa_len Additional authentication data length. + * + * @remark @p ct and @p pt can point to the same address. + * + * @retval 0 If @p tag is valid. + * @retval -1 Otherwise. + */ +int ocrypto_aes_eax_decrypt ( + uint8_t* pt, const uint8_t tag[16], const uint8_t* ct, size_t ct_len, const uint8_t *key, size_t size, + const uint8_t* iv, size_t iv_len, const uint8_t *aa, size_t aa_len); + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_AES_EAX_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_aes_gcm.h b/external/nrf_oberon/include/ocrypto_aes_gcm.h new file mode 100644 index 0000000..1e9551e --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_aes_gcm.h @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_aes_gcm AES GCM - AES Galois/Counter Mode APIs + * @ingroup nrf_oberon_aes + * @{ + * @brief Type definitions and APIs for AES-GCM (AES Galois/Counter Mode). + * + * AES (advanced encryption standard) is a symmetric encryption algorithm standardized by NIST. + * AES transfers a 128-bit block of data into an encrypted block of the same size. + * + * AES-GCM (AES Galois/Counter Mode) is an AES mode which effectively turns the block cipher into + * a stream cipher. The AES block cipher primitive is used in CTR mode for encryption and decryption. + * In addition, 128-bit Galois Field multiplication is used for authentication. + */ + +#ifndef OCRYPTO_AES_GCM_H +#define OCRYPTO_AES_GCM_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * AES-GCM encryption. + * + * @param[out] ct Cyphertext. + * @param[out] tag Authentication tag. + * @param pt Plaintext. + * @param pt_len Plaintext length. + * @param key AES key. + * @param size Key size (16, 24, or 32 bytes). + * @param iv Initial vector. + * @param aa Additional authentication data. + * @param aa_len Additional authentication data length. + * + * @remark @p ct and @p pt can point to the same address. + */ +void ocrypto_aes_gcm_encrypt ( + uint8_t* ct, uint8_t tag[16], const uint8_t* pt, size_t pt_len, + const uint8_t *key, size_t size, const uint8_t iv[12], const uint8_t *aa, size_t aa_len); + +/** + * AES-GCM decryption. + * + * @param[out] pt Plaintext. + * @param tag Authentication tag. + * @param ct Cyphertext. + * @param ct_len Cyphertext length. + * @param key AES key. + * @param size Key size (16, 24, or 32 bytes). + * @param iv Initial vector. + * @param aa Additional authentication data. + * @param aa_len Additional authentication data length. + * + * @remark @p ct and @p pt can point to the same address. + * + * @retval 0 If @p tag is valid. + * @retval -1 Otherwise. + */ +int ocrypto_aes_gcm_decrypt ( + uint8_t* pt, const uint8_t tag[16], const uint8_t* ct, size_t ct_len, + const uint8_t *key, size_t size, const uint8_t iv[12], const uint8_t *aa, size_t aa_len); + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_AES_GCM_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_aes_key.h b/external/nrf_oberon/include/ocrypto_aes_key.h new file mode 100644 index 0000000..af04bef --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_aes_key.h @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_aes_key AES key sizes + * @ingroup nrf_oberon_aes + * @{ + * @brief Type definition of AES key sizes. + * + * AES (advanced encryption standard) is a symmetric encryption algorithm standardized by NIST. + * AES transfers a 128-bit block of data into an encrypted block of the same size. + */ + +#ifndef OCRYPTO_AES_KEY_H +#define OCRYPTO_AES_KEY_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +#define ocrypto_aes128_KEY_BYTES ((size_t) 16) //!< AES-128 key size in bytes +#define ocrypto_aes192_KEY_BYTES ((size_t) 24) //!< AES-192 key size in bytes +#define ocrypto_aes256_KEY_BYTES ((size_t) 32) //!< AES-256 key size in bytes + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_AES_KEY_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_chacha20.h b/external/nrf_oberon/include/ocrypto_chacha20.h new file mode 100644 index 0000000..431ec68 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_chacha20.h @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_chacha ChaCha20 APIs + * @ingroup nrf_oberon_chacha_poly + * @{ + * @brief Type declaration and APIs for the Chacha20 stream cipher algorithm. + * + * ChaCha20 is a stream cipher developed by Daniel J. Bernstein based on the 20-round cipher + * Salsa20/20. + * + * A 256-bit key is expanded into 2^64 randomly accessible streams, each + * containing 2^64 randomly accessible 64-byte (512-bit) blocks. + * + * The changes from Salsa20/20 to ChaCha20 are designed to improve diffusion per + * round, conjecturally increasing resistance to cryptanalysis, while + * preserving - and often improving - time per round. + * + * @see [RFC 7539 - ChaCha20 and Poly1305 for IETF Protocols](http://tools.ietf.org/html/rfc7539) + * @see [The ChaCha family of stream ciphers](http://cr.yp.to/chacha.html) + */ + +#ifndef OCRYPTO_CHACHA20_H +#define OCRYPTO_CHACHA20_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Length of the encryption key. + */ +#define ocrypto_chacha20_KEY_BYTES (32) + +/** + * Maximum length of the nonce. + */ +#define ocrypto_chacha20_NONCE_BYTES_MAX (12) + + +/** + * ChaCha20 cipher stream generator. + * + * The encryption key @p k, the nonce @p n, and the initial block counter + * @p count are used to generate a pseudo random cipher stream. + * + * Possible applications include key generation and random number generation. + * + * @param[out] c Generated cipher stream. + * @param c_len Length of @p c. + * @param n Nonce. + * @param n_len Nonce length. 0 <= @p n_len <= @c ocrypto_chacha20_NONCE_BYTES_MAX. + * @param k Encryption key. + * @param count Initial block counter. + * + * @remark When reusing an encryption key @p k, a different nonce @p n or + * initial block counter @p count must be used. + * + * @remark This function is equivalent to @c chacha20_stream_xor with a + * message @p m consisting of @p c_len zeroes. + */ +void ocrypto_chacha20_stream( + uint8_t *c, size_t c_len, + const uint8_t *n, size_t n_len, + const uint8_t k[ocrypto_chacha20_KEY_BYTES], + uint32_t count); + +/** + * ChaCha20 cipher stream encoder. + * + * The message @p m is encrypted by applying the XOR operation with a pseudo + * random cipher stream derived from the encryption key @p k, the nonce @p n, and + * the initial block counter @p count. + * + * Calling the function a second time with the generated ciphertext as input + * message @p m decrypts it back to the original message. + * + * @param[out] c Generated ciphertext. Same length as input message. + * @param m Input message. + * @param m_len Length of @p c and @p m. + * @param n Nonce. + * @param n_len Nonce length. 0 <= @p n_len <= @c ocrypto_chacha20_NONCE_BYTES_MAX. + * @param k Encryption key. + * @param count Initial block counter. + * + * @remark @p c and @p m can point to the same address. + * + * @remark When reusing an encryption key @p k for a different message @p m, a + * different nonce @p n or initial block counter @p count must be used. + */ +void ocrypto_chacha20_stream_xor( + uint8_t *c, + const uint8_t *m, size_t m_len, + const uint8_t *n, size_t n_len, + const uint8_t k[ocrypto_chacha20_KEY_BYTES], + uint32_t count); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_CHACHA20_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_chacha20_poly1305.h b/external/nrf_oberon/include/ocrypto_chacha20_poly1305.h new file mode 100644 index 0000000..e6f3bea --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_chacha20_poly1305.h @@ -0,0 +1,227 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_chacha_poly ChaCha20-Poly1305 + * @ingroup nrf_oberon + * @{ + * @brief ChaCha20-Poly1305 is an authenticated encryption algorithm with optional + * additional authenticated data developed by Daniel J.Bernstein. + * @} + * + * @defgroup nrf_oberon_chacha_poly_apis ChaCha20-Poly1305 APIs + * @ingroup nrf_oberon_chacha_poly + * @{ + * @brief Type declaration and APIs for authenticated encryption and additional data using + * the ChaCha20-Poly1305 algorithm. + * + * ChaCha20-Poly1305 is an authenticated encryption algorithm with optional + * additional authenticated data developed by Daniel J.Bernstein. + * + * The ChaCha20 stream cipher is combined with the Poly1305 authenticator. + * + * @see [RFC 7539 - ChaCha20 and Poly1305 for IETF Protocols](http://tools.ietf.org/html/rfc7539) + */ + +#ifndef OCRYPTO_CHACHA20_POLY1305_H +#define OCRYPTO_CHACHA20_POLY1305_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Length of the encryption key. + */ +#define ocrypto_chacha20_poly1305_KEY_BYTES (32) + +/** + * Maximum length of the nonce. + */ +#define ocrypto_chacha20_poly1305_NONCE_BYTES_MAX (12) + +/** + * Length of the authentication tag. + */ +#define ocrypto_chacha20_poly1305_TAG_BYTES (16) + + +/**@{*/ +/** + * AEAD ChaCha20-Poly1305 encrypt. + * + * The message @p m is encrypted using a ChaCha20 cipher stream derived from the + * encryption key @p k and the nonce @p n. The resulting ciphertext has the same + * length @p m_len as the input message @p m and is put into @p c. + * + * Additionally, the ciphertext @p c is authenticated with a tag that is + * generated with Poly1305 using a unique subkey derived from @p k and @p n, and + * then put into @p tag. + * + * @param[out] tag Generated authentication tag. + * @param[out] c Generated ciphertext. Same length as input message. + * @param m Input message. + * @param m_len Length of @p m and @p c. + * @param n Nonce. + * @param n_len Length of @p n. 0 <= @p n_len <= @c ocrypto_chacha20_poly1305_NONCE_BYTES_MAX. + * @param k Encryption key. + * + * @remark @p c and @p m can point to the same address. + * + * @remark When reusing an encryption key @p k for a different message @p m, a + * different nonce @p n must be used. + */ +void ocrypto_chacha20_poly1305_encrypt( + uint8_t tag[ocrypto_chacha20_poly1305_TAG_BYTES], + uint8_t *c, + const uint8_t *m, size_t m_len, + const uint8_t *n, size_t n_len, + const uint8_t k[ocrypto_chacha20_poly1305_KEY_BYTES]); + +/** + * AEAD ChaCha20-Poly1305 encrypt with AAD. + * + * The message @p m is encrypted using a ChaCha20 cipher stream derived from the + * encryption key @p k and the nonce @p n. The resulting ciphertext has the same + * length @p m_len as the input message @p m and is put into @p c. + * + * Additionally, the ciphertext @p c, as well as the additional authenticated + * data @p a, is authenticated with a tag that is generated with Poly1305 using a + * unique subkey derived from @p k and @p n, and then put into @p tag. + * + * @param[out] tag Generated authentication tag. + * @param[out] c Generated ciphertext. Same length as input message. + * @param m Input message. + * @param m_len Length of @p m and @p c. + * @param a Additional authenticated data. + * @param a_len Length of @p a. + * @param n Nonce. + * @param n_len Length of @p n. 0 <= @p n_len <= @c ocrypto_chacha20_poly1305_NONCE_BYTES_MAX. + * @param k Encryption key. + * + * @remark @p c and @p m can point to the same address. + * + * @remark When reusing an encryption key @p k for a different message @p m or + * different additional authenticated data @p a, a different nonce @p n + * must be used. + */ +void ocrypto_chacha20_poly1305_encrypt_aad( + uint8_t tag[ocrypto_chacha20_poly1305_TAG_BYTES], + uint8_t *c, + const uint8_t *m, size_t m_len, + const uint8_t *a, size_t a_len, + const uint8_t *n, size_t n_len, + const uint8_t k[ocrypto_chacha20_poly1305_KEY_BYTES]); +/**@}*/ + +/**@{*/ +/** + * AEAD ChaCha20-Poly1305 decrypt. + * + * If the authentication tag @p tag is valid for the ciphertext @p c, the + * encryption key @p k and the nonce @p n, the ciphertext is decrypted and put + * into @p m. The decrypted message @p m has the same length @p c_len as the + * original ciphertext. + * + * @param tag Received authentication tag. + * @param[out] m Decoded message. Same length as received ciphertext. + * @param c Received ciphertext. + * @param c_len Length of @p c and @p m. + * @param n Nonce. + * @param n_len Length of @p n. 0 <= @p n_len <= @c ocrypto_chacha20_poly1305_NONCE_BYTES_MAX. + * @param k Encryption key. + * + * @retval 0 If @p tag is valid. + * @retval -1 Otherwise. + * + * @remark @p m and @p c can point to the same address. + */ +int ocrypto_chacha20_poly1305_decrypt( + const uint8_t tag[ocrypto_chacha20_poly1305_TAG_BYTES], + uint8_t *m, + const uint8_t *c, size_t c_len, + const uint8_t *n, size_t n_len, + const uint8_t k[ocrypto_chacha20_poly1305_KEY_BYTES]); + +/** + * AEAD ChaCha20-Poly1305 decrypt with AAD. + * + * If the authentication tag @p tag is valid for the ciphertext @p c, the + * additional authenticated data @p a, the encryption key @p k and the nonce + * @p n, the ciphertext is decrypted and put into @p m. The decrypted message + * @p m has the same length @p c_len as the original ciphertext. + * + * @param tag Received authentication tag. + * @param[out] m Decoded message. Same length as received ciphertext. + * @param c Received ciphertext. + * @param c_len Length of @p c and @p m. + * @param a Received additional authenticated data. + * @param a_len Length of @p a. + * @param n Nonce. + * @param n_len Length of @p n. 0 <= @p n_len <= @c ocrypto_chacha20_poly1305_NONCE_BYTES_MAX. + * @param k Encryption key. + * + * @retval 0 If @p tag is valid. + * @retval -1 Otherwise. + * + * @remark @p m and @p c can point to the same address. + */ +int ocrypto_chacha20_poly1305_decrypt_aad( + const uint8_t tag[ocrypto_chacha20_poly1305_TAG_BYTES], + uint8_t *m, + const uint8_t *c, size_t c_len, + const uint8_t *a, size_t a_len, + const uint8_t *n, size_t n_len, + const uint8_t k[ocrypto_chacha20_poly1305_KEY_BYTES]); +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_CHACHA20_POLY1305_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_chacha20_poly1305_inc.h b/external/nrf_oberon/include/ocrypto_chacha20_poly1305_inc.h new file mode 100644 index 0000000..84b9852 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_chacha20_poly1305_inc.h @@ -0,0 +1,247 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_chacha_poly_inc ChaCha20-Poly1305 incremental APIs + * @ingroup nrf_oberon_chacha_poly + * @{ + * @brief Type declaration and APIs for authenticated encryption and additional data using + * the ChaCha20-Poly1305 algorithm in incremental steps. + * + * ChaCha20-Poly1305 is an authenticated encryption algorithm with optional + * additional authenticated data developed by Daniel J.Bernstein. + * + * The ChaCha20 stream cipher is combined with the Poly1305 authenticator. + * + * @see [RFC 7539 - ChaCha20 and Poly1305 for IETF Protocols](http://tools.ietf.org/html/rfc7539) + */ + +#ifndef OCRYPTO_CHACHA20_POLY1305_INC_H +#define OCRYPTO_CHACHA20_POLY1305_INC_H + +#include +#include +#include "ocrypto_chacha20_poly1305.h" +#include "ocrypto_poly1305.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@cond */ +typedef struct { + ocrypto_poly1305_ctx auth_ctx; + uint8_t subkey[32]; + uint8_t buffer[16]; + uint32_t buffer_len; + uint8_t cypher[64]; + uint32_t cypher_idx; + uint32_t count; + size_t msg_len; + size_t aad_len; +} ocrypto_chacha20_poly1305_ctx; +/**@endcond */ + + +/**@name Incremental ChaCha20-Poly1305 generator. + * + * This group of functions can be used to incrementally encode and decode using the ChaCha20-Poly1305 stream cypher. + * + * Use pattern: + * + * Encoding: + * @code + * ocrypto_chacha20_poly1305_init(ctx, nonce, nonce_len, key); + * ocrypto_chacha20_poly1305_update_aad(ctx, aad, aad_len, nonce, nonce_len, key); + * ... + * ocrypto_chacha20_poly1305_update_aad(ctx, aad, aad_len, nonce, nonce_len, key); + * ocrypto_chacha20_poly1305_update_enc(ctx, ct, pt, pt_len, nonce, nonce_len, key); + * ... + * ocrypto_chacha20_poly1305_update_enc(ctx, ct, pt, pt_len, nonce, nonce_len, key); + * ocrypto_chacha20_poly1305_final_enc(ctx, tag); + * @endcode + * Decoding: + * @code + * ocrypto_chacha20_poly1305_init(ctx, nonce, nonce_len, key); + * ocrypto_chacha20_poly1305_update_aad(ctx, aad, aad_len, nonce, nonce_len, key); + * ... + * ocrypto_chacha20_poly1305_update_aad(ctx, aad, aad_len, nonce, nonce_len, key); + * ocrypto_chacha20_poly1305_update_dec(ctx, pt, ct, ct_len, nonce, nonce_len, key); + * ... + * ocrypto_chacha20_poly1305_update_dec(ctx, pt, ct, ct_len, nonce, nonce_len, key); + * res = ocrypto_chacha20_poly1305_final_dec(ctx, tag); + * @endcode + */ +/**@{*/ + +/** + * ChaCha20-Poly1305 initialization. + * + * The generator state @p ctx is initialized by this function. + * + * @param[out] ctx Generator state. + * @param n Nonce. + * @param n_len Length of @p n. 0 <= @p n_len <= @c ocrypto_chacha20_poly1305_NONCE_BYTES_MAX. + * @param k Encryption key. + */ +void ocrypto_chacha20_poly1305_init( + ocrypto_chacha20_poly1305_ctx *ctx, + const uint8_t *n, size_t n_len, + const uint8_t k[ocrypto_chacha20_poly1305_KEY_BYTES]); + +/** + * SHA-ChaCha20-Poly1305 incremental aad input. + * + * The generator state @p ctx is updated to include a data chunk @p a. + * + * This function can be called repeatedly until the whole data is processed. + * + * @param ctx Generator state. + * @param a Additional authenticated data. + * @param a_len Length of @p a. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_chacha20_poly1305_init is required before this function can be called. + * + * @remark @c ocrypto_chacha20_poly1305_update_aad must be called before any call to + * @c ocrypto_chacha20_poly1305_update_enc or @c ocrypto_chacha20_poly1305_update_dec. + */ +void ocrypto_chacha20_poly1305_update_aad( + ocrypto_chacha20_poly1305_ctx *ctx, + const uint8_t *a, size_t a_len); + +/** + * SHA-ChaCha20-Poly1305 incremental encoder input. + * + * The generator state @p ctx is updated to include a message chunk @p m. + * + * This function can be called repeatedly until the whole message is processed. + * + * @param ctx Generator state. + * @param[out] c Generated ciphertext. Same length as input message. + * @param m Message chunk. + * @param m_len Length of @p m. + * @param n Nonce. + * @param n_len Length of @p n. 0 <= @p n_len <= @c ocrypto_chacha20_poly1305_NONCE_BYTES_MAX. + * @param k Encryption key. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_chacha20_poly1305_init is required before this function can be called. + * + * @remark @c ocrypto_chacha20_poly1305_update_enc must be called after any call to + * @c ocrypto_chacha20_poly1305_update_aad. + * + * @remark @p c and @p m can point to the same address. + */ +void ocrypto_chacha20_poly1305_update_enc( + ocrypto_chacha20_poly1305_ctx *ctx, + uint8_t *c, + const uint8_t *m, size_t m_len, + const uint8_t *n, size_t n_len, + const uint8_t k[ocrypto_chacha20_poly1305_KEY_BYTES]); + +/** + * SHA-ChaCha20-Poly1305 incremental decoder input. + * + * The generator state @p ctx is updated to include a cyphertext chunk @p c. + * + * This function can be called repeatedly until the whole cyphertext is processed. + * + * @param ctx Generator state. + * @param[out] m Decoded message. Same length as received ciphertext. + * @param c Cyphertext chunk. + * @param c_len Length of @p c. + * @param n Nonce. + * @param n_len Length of @p n. 0 <= @p n_len <= @c ocrypto_chacha20_poly1305_NONCE_BYTES_MAX. + * @param k Encryption key. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_chacha20_poly1305_init is required before this function can be called. + * + * @remark @c ocrypto_chacha20_poly1305_update_dec must be called after any call to + * @c ocrypto_chacha20_poly1305_update_aad. + * + * @remark @p m and @p c can point to the same address. + */ +void ocrypto_chacha20_poly1305_update_dec( + ocrypto_chacha20_poly1305_ctx *ctx, + uint8_t *m, + const uint8_t *c, size_t c_len, + const uint8_t *n, size_t n_len, + const uint8_t k[ocrypto_chacha20_poly1305_KEY_BYTES]); + +/** + * SHA-ChaCha20-Poly1305 final encoder step. + * + * The generator state @p ctx is used to finalize the encryption and generate the tag. + * + * @param ctx Generator state. + * @param[out] tag Generated authentication tag. + */ +void ocrypto_chacha20_poly1305_final_enc( + ocrypto_chacha20_poly1305_ctx *ctx, + uint8_t tag[ocrypto_chacha20_poly1305_TAG_BYTES]); + +/** + * SHA-ChaCha20-Poly1305 final decoder step. + * + * The generator state @p ctx is used to finalize the decryption and check the tag. + * + * @param ctx Generator state. + * @param tag Received authentication tag. + * + * @retval 0 If @p tag is valid. + * @retval -1 Otherwise. + */ +int ocrypto_chacha20_poly1305_final_dec( + ocrypto_chacha20_poly1305_ctx *ctx, + const uint8_t tag[ocrypto_chacha20_poly1305_TAG_BYTES]); +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_CHACHA20_POLY1305_INC_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_constant_time.h b/external/nrf_oberon/include/ocrypto_constant_time.h new file mode 100644 index 0000000..ff0e804 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_constant_time.h @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon Oberon cryptographic library + * @{ + * @brief Highly optimized cryptographic algorithm implementation for Cortex-M0, Cortex-M4, + * and Cortex-M33. Created by Oberon, under distribution license with Nordic Semiconductor ASA. + * @} + * + * @defgroup nrf_oberon_constant_time Constant time APIs + * @ingroup nrf_oberon + * @{ + * @brief Timing-invariant functions to use with cryptography. + * + * Collection of timing-invariant implementations of basic functions. + */ + +#ifndef OCRYPTO_CONSTANT_TIME_H +#define OCRYPTO_CONSTANT_TIME_H + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Variable length comparison. + * + * @param x Memory region to compare with @p y. + * @param y Memory region to compare with @p x. + * @param length Number of bytes to compare, @p length > 0. + * + * @retval 1 If @p x and @p y point to equal memory regions. + * @retval 0 Otherwise. + */ +int ocrypto_constant_time_equal(const void *x, const void *y, size_t length); + +/** + * Variable length compare to zero. + * + * @param x Pointer to memory region that will be compared. + * @param length Number of bytes to compare, @p length > 0. + * + * @retval 1 If @p x is equal to a zero memory region. + * @retval 0 Otherwise. + */ +int ocrypto_constant_time_is_zero(const void *x, size_t length); + +/** + * Variable length copy. + * + * @param x Pointer to memory region to copy @p y to. + * @param y Pointer to memory region to copy to @p x. + * @param length Number of bytes to copy, @p length > 0. + */ +void ocrypto_constant_time_copy(void *x, const void *y, size_t length); + +/** + * Variable length fill with zero. + * + * @param x Pointer to memory region to be filled with zero. + * @param length Number of bytes to fill, @p length > 0. + */ +void ocrypto_constant_time_fill_zero(void *x, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_CONSTANT_TIME_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_curve25519.h b/external/nrf_oberon/include/ocrypto_curve25519.h new file mode 100644 index 0000000..bee397e --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_curve25519.h @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_curve25519 ECC Curve25519 low-level APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations and APIs for low-level elliptic curve point operations + * based on Curve25519. + * + * Curve25519 is an elliptic curve offering 128 bits of security. It is designed + * for use in the Elliptic Curve Diffie-Hellman (ECDH) key agreement scheme. + * + * @see [RFC 7748 - Elliptic Curves for Security](https://tools.ietf.org/html/rfc7748) + * @see [Curve25519: high-speed elliptic-curve cryptography](http://cr.yp.to/ecdh.html) + */ + +#ifndef OCRYPTO_CURVE25519_H +#define OCRYPTO_CURVE25519_H + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Length of a scalar. + */ +#define ocrypto_curve25519_SCALAR_BYTES (32) + +/** + * Length of a curve point. + */ +#define ocrypto_curve25519_BYTES (32) + + +/** + * Curve25519 scalar multiplication `r = n * basePoint`. + * + * Given a secret key @p n, the corresponding Curve25519 public key is computed + * and put into @p r. + * + * The inverse of this function is difficult to compute. + * + * @param[out] r Resulting curve point. + * @param[in] n Scalar factor. + * + * @remark @p r and @p n can point to the same address. + */ +void ocrypto_curve25519_scalarmult_base( + uint8_t r[ocrypto_curve25519_BYTES], + const uint8_t n[ocrypto_curve25519_SCALAR_BYTES]); + +/** + * Curve25519 scalar multiplication `r = n * p`. + * + * A shared secret is computed from the local secret key @p n and another + * party's public key @p p and put into @p r. The same shared secret is + * generated when the other party combines its private key with the local public + * key. + * + * @param[out] r Resulting curve point. + * @param[in] n Scalar factor. + * @param[in] p Point factor. + * + * @remark @p r and @p n can point to the same address. + */ +void ocrypto_curve25519_scalarmult( + uint8_t r[ocrypto_curve25519_BYTES], + const uint8_t n[ocrypto_curve25519_SCALAR_BYTES], + const uint8_t p[ocrypto_curve25519_BYTES]); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_CURVE25519_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_curve_p224.h b/external/nrf_oberon/include/ocrypto_curve_p224.h new file mode 100644 index 0000000..b488fda --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_curve_p224.h @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_p224 ECC secp224r1 low-level APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations and APIs for low-level elliptic curve point operations + * based on the NIST secp224r1 curve. + */ + +#ifndef OCRYPTO_CURVE_P224_H +#define OCRYPTO_CURVE_P224_H + +#include "ocrypto_sc_p224.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// (x,y) only jacobian coordinates +/**@cond */ +typedef struct { + ocrypto_mod_p224 x; + ocrypto_mod_p224 y; +} ocrypto_cp_p224; +/**@endcond */ + + +/** Load r.x from bytes, keep r.y. + * + * @param[out] r Point with r.x loaded, r.y kept. + * @param p x as as array of bytes. + * + * @retval 0 If @p r is a valid curve point. + * @retval -1 Otherwise. + */ +int ocrypto_curve_p224_from28bytes(ocrypto_cp_p224 *r, const uint8_t p[28]); + +/** Load point from bytes. + * + * @param[out] r Loaded point. + * @param p Point as array of bytes. + * + * @retval 0 If @p r is a valid curve point. + * @retval -1 Otherwise. + */ +int ocrypto_curve_p224_from56bytes(ocrypto_cp_p224 *r, const uint8_t p[56]); + +/** Store p.x to bytes. + * + * @param[out] r x stored as array. + * @param p Point with x to be stored. + */ +void ocrypto_curve_p224_to28bytes(uint8_t r[28], ocrypto_cp_p224 *p); + +/** Store p.x to bytes. + * + * @param[out] r Point stored as array. + * @param p Point to be stored. + */ +void ocrypto_curve_p224_to56bytes(uint8_t r[56], ocrypto_cp_p224 *p); + +/** P224 scalar multiplication. + * + * r = p * s + * r = [0,0] if p = [0,0] or s mod q = 0 + * + * @param[out] r Output point. + * @param p Input point. + * @param s Scalar. + * + * @retval -1 If r = [0,0]. + * @retval 0 If 0 < s < q. + * @retval 1 If s > q. + */ +int ocrypto_curve_p224_scalarmult(ocrypto_cp_p224 *r, const ocrypto_cp_p224 *p, const ocrypto_sc_p224 *s); + +/** P224 scalar base multiplication. + * + * r = basePoint * s + * r = [0,0] if s mod q = 0 + * + * @param[out] r Output point. + * @param s Scalar. + * + * @retval -1 If r = [0,0]. + * @retval 0 If 0 < s < q. + * @retval 1 If s > q. + */ +int ocrypto_curve_p224_scalarmult_base(ocrypto_cp_p224 *r, const ocrypto_sc_p224 *s); + +/** P224 add and double + * + * r = p + q + * p == [0,0] -> r = q + * q == [0,0] -> r = p + * p == -q -> r = [0,0] + * + * @param[out] r Resulting point + * @param p Input point. + * @param q input point. + * + * @retval -1 if r = [0,0]. + * @etval 0 if successfull. + */ +int ocrypto_curve_p224_add(ocrypto_cp_p224 *r, const ocrypto_cp_p224 *p, const ocrypto_cp_p224 *q); + + +#ifdef __cplusplus +} +#endif /* #ifndef OCRYPTO_CURVE_P224_H */ + +#endif diff --git a/external/nrf_oberon/include/ocrypto_curve_p256.h b/external/nrf_oberon/include/ocrypto_curve_p256.h new file mode 100644 index 0000000..71b9c5c --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_curve_p256.h @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_p256 ECC secp256r1 low-level APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations and APIs for low-level elliptic curve point operations + * based on the NIST secp256r1 curve. + */ + +#ifndef OCRYPTO_CURVE_P256_H +#define OCRYPTO_CURVE_P256_H + +#include "ocrypto_sc_p256.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@cond */ + +// (x,y) only jacobian coordinates +typedef struct { + ocrypto_mod_p256 x; + ocrypto_mod_p256 y; +} ocrypto_cp_p256; + +// P-256 invert context +typedef struct { + ocrypto_mod_p256 x, x3, xn, t; + int step; +} ocrypto_p256_invert_context; + + +typedef struct { + ocrypto_cp_p256 p, q0, q1; + uint32_t e[8]; // bits 0-255 of extended scalar, bit 256 = ~bit 255 + ocrypto_p256_invert_context inv; + int ret, prev, dec, step; +} ocrypto_p256_mult_context; +/**@endcond */ + + +/** Load r.x from bytes, keep r.y. + * + * @param[out] r Point with r.x loaded, r.y kept. + * @param p x as as array of bytes. + * + * @retval 0 If @p r is a valid curve point. + * @retval -1 Otherwise. + */ +int ocrypto_curve_p256_from32bytes(ocrypto_cp_p256 *r, const uint8_t p[32]); + + +/** Load point from bytes. + * + * @param[out] r Loaded point. + * @param p Point as array of bytes. + * + * @retval 0 If @p r is a valid curve point. + * @retval -1 Otherwise. + */ +int ocrypto_curve_p256_from64bytes(ocrypto_cp_p256 *r, const uint8_t p[64]); + +/** Store p.x to bytes. + * + * @param[out] r x stored as array. + * @param p Point with x to be stored. + */ +void ocrypto_curve_p256_to32bytes(uint8_t r[32], ocrypto_cp_p256 *p); + +/** Store p.x to bytes. + * + * @param[out] r Point stored as array. + * @param p Point to be stored. + */ +void ocrypto_curve_p256_to64bytes(uint8_t r[64], ocrypto_cp_p256 *p); + +/** P256 scalar multiplication. + * + * r = p * s + * r = [0,0] if p = [0,0] or s mod q = 0 + * + * @param[out] r Output point. + * @param p Input point. + * @param s Scalar. + * + * @retval -1 If r = [0,0]. + * @retval 0 If 0 < s < q. + * @retval 1 If s > q. + */ +int ocrypto_curve_p256_scalarmult(ocrypto_cp_p256 *r, const ocrypto_cp_p256 *p, const ocrypto_sc_p256 *s); + +/** P256 scalar base multiplication. + * + * r = basePoint * s + * r = [0,0] if s mod q = 0 + * + * @param[out] r Output point. + * @param s Scalar. + * + * @retval -1 If r = [0,0]. + * @retval 0 If 0 < s < q. + * @retval 1 If s > q. + */ +int ocrypto_curve_p256_scalarmult_base(ocrypto_cp_p256 *r, const ocrypto_sc_p256 *s); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_CURVE_P256_H */ + +/** @} */ diff --git a/external/nrf_oberon/include/ocrypto_ecdh_p224.h b/external/nrf_oberon/include/ocrypto_ecdh_p224.h new file mode 100644 index 0000000..7eaa540 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_ecdh_p224.h @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_ecdh_p224 ECDH P224 APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations and APIs for low-level elliptic curve point operations + * to do Elliptic Curve Diffie-Hellman based on the NIST secp224r1 curve. + */ + +#ifndef OCRYPTO_ECDH_P224_H +#define OCRYPTO_ECDH_P224_H + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * ECDH P-224 public key generation `r = n * p`. + * + * Given a secret key @p s the corresponding public key is computed and put + * into @p r. + * + * @param[out] r Generated public key. + * @param s Secret key. Must be pre-filled with random data. + * + * @retval 0 If @p s is a valid secret key. + * @retval -1 Otherwise. + * + * @remark @p r may be same as @p s. + */ +int ocrypto_ecdh_p224_public_key(uint8_t r[56], const uint8_t s[28]); + +/** + * ECDH P-224 common secret. + * + * The common secret is computed from both the client's public key @p p + * and the server's secret key @p s and put into @p r. + * + * @param[out] r Generated common secret. + * @param s Server private key. + * @param p Client public key. + * + * @retval 0 If @p s is a valid secret key and @p p is a valid public key. + * @retval -1 Otherwise. + * + * @remark @p r may be same as @p s or @p p. + */ +int ocrypto_ecdh_p224_common_secret(uint8_t r[28], const uint8_t s[28], const uint8_t p[56]); + + +#ifdef __cplusplus +} +#endif + +#endif + +/** @} */ diff --git a/external/nrf_oberon/include/ocrypto_ecdh_p256.h b/external/nrf_oberon/include/ocrypto_ecdh_p256.h new file mode 100644 index 0000000..0c949c7 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_ecdh_p256.h @@ -0,0 +1,203 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_ecdh_p256 ECDH APIs + * @ingroup nrf_oberon + * @{ + * @brief APIs to do Elliptic Curve Diffie-Hellman using the NIST secp256r1 curve. + */ + +#ifndef OCRYPTO_ECDH_P256_H +#define OCRYPTO_ECDH_P256_H + +#include +#include "ocrypto_curve_p256.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/**@cond */ +typedef struct { + ocrypto_p256_mult_context mul; + int ret; +} ocrypto_ecdh_p256_context; +/**@endcond */ + + +/** + * ECDH P-256 public key generation `r = n * p`. + * + * Given a secret key @p s the corresponding public key is computed and put + * into @p r. + * + * @param[out] r Generated public key. + * @param s Secret key. Must be pre-filled with random data. + * + * @retval 0 If @p s is a valid secret key. + * @retval -1 Otherwise. + * + * @remark @p r may be same as @p s. + */ +int ocrypto_ecdh_p256_public_key(uint8_t r[64], const uint8_t s[32]); + +/** + * ECDH P-256 common secret. + * + * The common secret is computed from both the client's public key @p p + * and the server's secret key @p s and put into @p r. + * + * @param[out] r Generated common secret. + * @param s Server private key. + * @param p Client public key. + * + * @retval 0 If @p s is a valid secret key and @p p is a valid public key. + * @retval -1 Otherwise. + * + * @remark @p r may be same as @p s or @p p. + */ +int ocrypto_ecdh_p256_common_secret(uint8_t r[32], const uint8_t s[32], const uint8_t p[64]); + + +/**@name Incremental ECDH P-256 calculation. + * + * This group of functions can be used to incrementally calculate + * the ECDH P-256 public key and common secret. + * Each call completes in less than 25ms on a 16MHz Cortex-M0. + * + * Use pattern: + * + * Public Key: + * @code + * ocrypto_ecdh_p256_public_key_init(ctx, sKey); + * while (ocrypto_ecdh_p256_public_key_iterate(ctx)); + * res = ocrypto_ecdh_p256_public_key_final(ctx, pKey); + * @endcode + * Common Secret: + * @code + * ocrypto_ecdh_p256_common_secret_init(ctx, sKey, pKey); + * while (ocrypto_ecdh_p256_common_secret_iterate(ctx)); + * res = ocrypto_ecdh_p256_common_secret_final(ctx, secet); + * @endcode + */ +/**@{*/ + +/** + * Incremental ECDH P-256 public key generation start. + * + * Key generation is started and the context @p ctx is initialized by this function. + * + * @param[out] ctx Context. + * @param s Secret key. Must be pre-filled with random data. + */ +void ocrypto_ecdh_p256_public_key_init(ocrypto_ecdh_p256_context *ctx, const uint8_t s[32]); + +/** + * Incremental ECDH P-256 public key generation step. + * + * The key calculation is advanced and the context @p ctx is updated by this function. + * + * @param ctx Context. + * + * @retval 1 If another call to @c ocrypto_ecdh_p256_public_key_init is needed. + * @retval 0 If key generation should be completed by a call to @c ocrypto_ecdh_p256_public_key_final. + */ +int ocrypto_ecdh_p256_public_key_iterate(ocrypto_ecdh_p256_context *ctx); + +/** + * Incremental ECDH P-256 public key generation final step. + * + * Key generation is finalized and the context @p ctx is used to generate the key. + * + * @param ctx Context. + * @param[out] r Generated public key. + * + * @retval 0 If @p s is a valid secret key. + * @retval -1 Otherwise. + */ +int ocrypto_ecdh_p256_public_key_final(ocrypto_ecdh_p256_context *ctx, uint8_t r[64]); + +/** + * Incremental ECDH P-256 common secret generation start. + * + * Common secret calculation is started and the context @p ctx is initialized by this function. + * + * @param[out] ctx Context. + * @param s Server private key. + * @param p Client public key. + */ +void ocrypto_ecdh_p256_common_secret_init(ocrypto_ecdh_p256_context *ctx, const uint8_t s[32], const uint8_t p[64]); + +/** + * Incremental ECDH P-256 common secret generation step. + * + * Common secret calculation is advanced and the context @p ctx is updated by this function. + * + * @param ctx Context. + * + * @retval 1 If another call to @c ocrypto_ecdh_p256_common_secret_iterate is needed. + * @retval 0 If key generation should be completed by a call to @c ocrypto_ecdh_p256_common_secret_final. + */ +int ocrypto_ecdh_p256_common_secret_iterate(ocrypto_ecdh_p256_context *ctx); + +/** + * Incremental ECDH P-256 common secret generation final step. + * + * Common secret calculation is finalized and the context @p ctx is used to generate the secret. + * + * @param ctx Context. + * @param[out] r Generated common secret. + * + * @retval 0 If @p s is a valid secret key and @p p is a valid public key. + * @retval -1 Otherwise. + */ +int ocrypto_ecdh_p256_common_secret_final(ocrypto_ecdh_p256_context *ctx, uint8_t r[32]); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_ECDH_P256_H */ + +/** @} */ diff --git a/external/nrf_oberon/include/ocrypto_ecdsa_p224.h b/external/nrf_oberon/include/ocrypto_ecdsa_p224.h new file mode 100644 index 0000000..647d20a --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_ecdsa_p224.h @@ -0,0 +1,164 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_ecdsa_p224 ECDSA secp224r1 low-level APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations and APIs to do Elliptic Curve Digital Signature Algorith using the + * NIST secp224r1 curve. + * + * ECDSA P-224 is a specific implementation of a digital signature scheme. + */ + +#ifndef OCRYPTO_ECDSA_P224_H +#define OCRYPTO_ECDSA_P224_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * ECDSA P-224 public key generation. + * + * Given a secret key @p sk the corresponding public key is computed and put + * into @p pk. + * + * @param[out] pk Generated public key. + * @param sk Secret key. Must be pre-filled with random data. + * + * @retval 0 If @p sk is a valid secret key. + * @retval -1 Otherwise. + */ +int ocrypto_ecdsa_p224_public_key( + uint8_t pk[56], + const uint8_t sk[28]); + +/** + * ECDSA P-224 signature generation. + * + * The message @p m is signed using the secret key @p sk and the ephemeral + * session key @p ek. The signature is put into @p sig. + * + * @param[out] sig Generated signature. + * @param m Input message. + * @param mlen Length of @p m. + * @param sk Secret key. + * @param ek Session key. + * + * @retval 0 If @p ek is a valid session key. + * @retval -1 Otherwise. + */ +int ocrypto_ecdsa_p224_sign( + uint8_t sig[56], + const uint8_t *m, size_t mlen, + const uint8_t sk[28], + const uint8_t ek[28]); + +/** + * ECDSA P-224 signature generation from SHA224 hash. + * + * The message hash @p hash is signed using the secret key @p sk and the ephemeral + * session key @p ek. The signature is put into @p sig. + * + * @param[out] sig Generated signature. + * @param hash Input hash. + * @param sk Secret key. + * @param ek Session key. + * + * @retval 0 If @p ek is a valid session key. + * @retval -1 Otherwise. + */ +int ocrypto_ecdsa_p224_sign_hash( + uint8_t sig[56], + const uint8_t hash[28], + const uint8_t sk[28], + const uint8_t ek[28]); + +/** + * ECDSA P-224 signature verification. + * + * The signature @p sig of the input message @p m is verified using the signer's + * public key @p pk. + * + * @param sig Input signature. + * @param m Input message. + * @param mlen Length of @p m. + * @param pk Signer's public key. + * + * @retval 0 If the signature is valid. + * @retval -1 Otherwise. + */ +int ocrypto_ecdsa_p224_verify( + const uint8_t sig[56], + const uint8_t *m, size_t mlen, + const uint8_t pk[56]); + +/** + * ECDSA P-224 signature verification from SHA224 hash. + * + * The signature @p sig of the message hash @p hash is verified using the signer's + * public key @p pk. + * + * @param sig Input signature. + * @param hash Input hash. + * @param pk Signer's public key. + * + * @retval 0 If the signature is valid. + * @retval -1 Otherwise. + */ +int ocrypto_ecdsa_p224_verify_hash( + const uint8_t sig[56], + const uint8_t hash[28], + const uint8_t pk[56]); + + +#ifdef __cplusplus +} +#endif + +#endif + +/** @} */ diff --git a/external/nrf_oberon/include/ocrypto_ecdsa_p256.h b/external/nrf_oberon/include/ocrypto_ecdsa_p256.h new file mode 100644 index 0000000..f365dec --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_ecdsa_p256.h @@ -0,0 +1,157 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * @defgroup nrf_oberon_ecdsa_p256 ECDSA APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations and APIs to do Elliptic Curve Digital Signature Algorith using the + * NIST secp256r1 curve. + */ +#ifndef OCRYPTO_ECDSA_P256_H +#define OCRYPTO_ECDSA_P256_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * ECDSA P-256 public key generation. + * + * Given a secret key @p sk the corresponding public key is computed and put + * into @p pk. + * + * @param[out] pk Generated public key. + * @param sk Secret key. Must be pre-filled with random data. + * + * @retval 0 If @p sk is a valid secret key. + * @retval -1 Otherwise. + */ +int ocrypto_ecdsa_p256_public_key( + uint8_t pk[64], + const uint8_t sk[32]); + +/** + * ECDSA P-256 signature generation. + * + * The message @p m is signed using the secret key @p sk and the ephemeral + * session key @p ek. The signature is put into @p sig. + * + * @param[out] sig Generated signature. + * @param m Input message. + * @param mlen Length of @p m. + * @param sk Secret key. + * @param ek Ephemeral session key. + * + * @retval 0 If @p ek is a valid session key. + * @retval -1 Otherwise. + */ +int ocrypto_ecdsa_p256_sign( + uint8_t sig[64], + const uint8_t *m, size_t mlen, + const uint8_t sk[32], + const uint8_t ek[32]); + +/** + * ECDSA P-256 signature generation from SHA256 hash. + * + * The message hash @p hash is signed using the secret key @p sk and the ephemeral + * session key @p ek. The signature is put into @p sig. + * + * @param[out] sig Generated signature. + * @param hash Input hash. + * @param sk Secret key. + * @param ek Ephemeral session key. + * + * @retval 0 If @p ek is a valid session key. + * @retval -1 Otherwise. + */ +int ocrypto_ecdsa_p256_sign_hash( + uint8_t sig[64], + const uint8_t hash[32], + const uint8_t sk[32], + const uint8_t ek[32]); + +/** + * ECDSA P-256 signature verification. + * + * The signature @p sig of the input message @p m is verified using the signer's + * public key @p pk. + * + * @param sig Input signature. + * @param m Input message. + * @param mlen Length of @p m. + * @param pk Signer's public key. + * + * @retval 0 If the signature is valid. + * @retval -1 Otherwise. + */ +int ocrypto_ecdsa_p256_verify( + const uint8_t sig[64], + const uint8_t *m, size_t mlen, + const uint8_t pk[64]); + +/** + * ECDSA P-256 signature verification from SHA256 hash. + * + * The signature @p sig of the message hash @p hash is verified using the signer's + * public key @p pk. + * + * @param sig Input signature. + * @param hash Input hash. + * @param pk Signer's public key. + * + * @retval 0 If the signature is valid. + * @retval -1 Otherwise. + */ +int ocrypto_ecdsa_p256_verify_hash( + const uint8_t sig[64], + const uint8_t hash[32], + const uint8_t pk[64]); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_ECDSA_P256_H */ + +/** @} */ diff --git a/external/nrf_oberon/include/ocrypto_ecjpake_p256.h b/external/nrf_oberon/include/ocrypto_ecjpake_p256.h new file mode 100644 index 0000000..d940d6c --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_ecjpake_p256.h @@ -0,0 +1,173 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_ecjpake EC-JPAKE + * @ingroup nrf_oberon + * @{ + * @brief Type declaration and APIs for EC-JPAKE. + * + */ +#ifndef OCRYPTO_ECJPAKE_P256_H +#define OCRYPTO_ECJPAKE_P256_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * EC-JPAKE-P256 public key and zero knowledge proof generation. + * + * @param[out] X Public key. + * @param[out] V ZKP ephemeral public key. + * @param[out] r ZKP signature. + * @param G Generator. May be NULL to use the default generator. + * @param x Secret key. 0 < x < group order. + * @param v ZKP ephemeral secret key. 0 < v < group order. + * @param id Identity of originator. + * @param id_len Identity length. + * + * @retval 0 If inputs are valid. + * @retval -1 Otherwise. + */ +int ocrypto_ecjpake_get_key( + uint8_t X[64], + uint8_t V[64], + uint8_t r[32], + const uint8_t G[64], + const uint8_t x[32], + const uint8_t v[32], + const char *id, size_t id_len); + +/** + * EC-JPAKE-P256 zero knowledge proof verification. + * + * @param G Generator. May be NULL to use the default generator. + * @param X Public key. + * @param V ZKP ephemeral public key. + * @param r ZKP signature. + * @param id Identity of originator. + * @param id_len Identity length. + * + * @retval 0 If proof is valid. + * @retval -1 Otherwise. + */ +int ocrypto_ecjpake_verify_key( + const uint8_t G[64], + const uint8_t X[64], + const uint8_t V[64], + const uint8_t r[32], + const char *id, size_t id_len); + + +/** + * EC-JPAKE-P256 generator derivation. + * + * @param[out] G Generator. + * @param X1 Public key 1. + * @param X2 Public key 2. + * @param X3 Public key 3. + * + * @retval 0 If the generator is valid. + * @retval -1 Otherwise. + */ +int ocrypto_ecjpake_get_generator( + uint8_t G[64], + const uint8_t X1[64], + const uint8_t X2[64], + const uint8_t X3[64]); + +/** + * EC-JPAKE-P256 read shared secret. + * + * @param[out] rs Reduced shared secret. + * @param secret Shared secret. + * @param secret_len Secret length. + */ +void ocrypto_ecjpake_read_shared_secret( + uint8_t rs[32], + const uint8_t *secret, size_t secret_len); + +/** + * EC-JPAKE-P256 shared secret handling. + * + * @param[out] xs Client/server secret key. + * @param x2 Secret key 2. + * @param rs Reduced shared secret. + * + * @retval 0 If the derived secret key is valid. + * @retval -1 Otherwise. + */ +int ocrypto_ecjpake_process_shared_secret( + uint8_t xs[32], + const uint8_t x2[32], + const uint8_t rs[32]); + +/** + * EC-JPAKE-P256 secret key generation. + * + * @param[out] secret Resulting premaster secret. + * @param Xr Remote client/server public key. + * @param X2 Remote public key 2. + * @param xs Client/server secret key. + * @param x2 Secret key 2. + * + * @retval 0 If the key is valid. + * @retval -1 Otherwise. + */ +int ocrypto_ecjpake_get_secret_key( + uint8_t secret[32], + const uint8_t Xr[64], + const uint8_t X2[64], + const uint8_t xs[32], + const uint8_t x2[32]); + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_ECJPAKE_P256_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_ed25519.h b/external/nrf_oberon/include/ocrypto_ed25519.h new file mode 100644 index 0000000..dad7434 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_ed25519.h @@ -0,0 +1,138 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_ed25519 Ed25519 APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations and APIs for the Ed25519 algorithm. + * + * Ed25519 is a specific implementation of EdDSA, a digital signature scheme. + * EdDSA is based on Twisted Edwards curves and is designed to be faster than + * existing digital signature schemes without sacrificing security. It was + * developed by Daniel J. Bernstein, et al. Ed25519 is intended to provide + * attack resistance comparable to quality 128-bit symmetric ciphers. + * + * @see [Ed25519: high-speed high-security signatures](https://ed25519.cr.yp.to) + */ + +#ifndef OCRYPTO_ED25519_H +#define OCRYPTO_ED25519_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Length of a public key. + */ +#define ocrypto_ed25519_PUBLIC_KEY_BYTES (32) + +/** + * Length of a secret key. + */ +#define ocrypto_ed25519_SECRET_KEY_BYTES (32) + +/** + * Length of a signature. + */ +#define ocrypto_ed25519_BYTES (64) + + +/** + * Ed25519 signature key pair generation. + * + * Given a secret key @p sk, the corresponding public key is computed and put + * into @p pk. The key pair can then be used to sign and verify message signatures. + * + * @param[out] pk Generated public key. + * @param sk Secret key. Must be pre-filled with random data. + */ +void ocrypto_ed25519_public_key(uint8_t pk[ocrypto_ed25519_PUBLIC_KEY_BYTES], + const uint8_t sk[ocrypto_ed25519_SECRET_KEY_BYTES]); + +/** + * Ed25519 signature generate. + * + * The message @p m is signed using the secret key @p sk and the corresponding + * public key @p pk. The signature is put into @p sig. + * + * @param[out] sig Generated signature. + * @param m Input message. + * @param m_len Length of @p m. + * @param sk Secret key. + * @param pk Public key. + */ +void ocrypto_ed25519_sign(uint8_t sig[ocrypto_ed25519_BYTES], + const uint8_t *m, size_t m_len, + const uint8_t sk[ocrypto_ed25519_SECRET_KEY_BYTES], + const uint8_t pk[ocrypto_ed25519_PUBLIC_KEY_BYTES]); + +/** + * Ed25519 signature verification. + * + * The signature @p sig of the input message @p m is verified using the signer's + * public key @p pk. + * + * @param sig Input signature. + * @param m Input message. + * @param m_len Length of @p m. + * @param pk Signer's public key. + * + * @retval 0 If the signature is valid. + * @retval -1 Otherwise. + */ +int ocrypto_ed25519_verify(const uint8_t sig[ocrypto_ed25519_BYTES], + const uint8_t *m, size_t m_len, + const uint8_t pk[ocrypto_ed25519_PUBLIC_KEY_BYTES]); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_ED25519_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_hkdf_sha1.h b/external/nrf_oberon/include/ocrypto_hkdf_sha1.h new file mode 100644 index 0000000..efe134f --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_hkdf_sha1.h @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_hkdf_1 HKDF APIs using SHA-1 + * @ingroup nrf_oberon_hkdf + * @{ + * @brief Type declaration and APIs for the HKDF-SHA1 algorithm. + * + * HKDF-SHA1 is a key derivation function based on HMAC-SHA1. + * + * @see [RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF)](http://tools.ietf.org/html/rfc5869) + */ + +#ifndef OCRYPTO_HKDF_SHA1_H +#define OCRYPTO_HKDF_SHA1_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Maximum length of a derived key. + */ +#define ocrypto_hkdf_sha1_LENGTH_MAX (20) + +/** + * Maximum salt length. + */ +#define ocrypto_hkdf_sha1_SALT_LENGTH_MAX (40) + + +/** + * HKDF-SHA1 algorithm. + * + * A new pseudo-random key of length @p r_len is derived from an input key + * @p key, a salt @p salt and additional information @p info. The new key is put + * into @p r. + * + * @param[out] r Output key. + * @param r_len Length of @p r, 0 < @p r_len <= @c ocrypto_hkdf_sha1_LENGTH_MAX. + * @param key Input key. + * @param key_len Length of @p key. + * @param salt Salt. + * @param salt_len Length of salt @p salt. 0 <= @p salt_len <= @c ocrypto_hkdf_sha1_SALT_LENGTH_MAX. + * @param info Additional information. + * @param info_len Length of @p info. + */ +void ocrypto_hkdf_sha1( + uint8_t* r, size_t r_len, + const uint8_t* key, size_t key_len, + const uint8_t* salt, size_t salt_len, + const uint8_t* info, size_t info_len); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_HKDF_SHA1_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_hkdf_sha256.h b/external/nrf_oberon/include/ocrypto_hkdf_sha256.h new file mode 100644 index 0000000..62500d4 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_hkdf_sha256.h @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_hkdf HKDF - HMAC based Key Derivation Function + * @ingroup nrf_oberon + * @{ + * @brief HKDF is a key derivation function based on HMAC Extract-and-Expand + * @} + * + * @defgroup nrf_oberon_hkdf_256 HKDF APIs using SHA-256 + * @ingroup nrf_oberon_hkdf + * @{ + * @brief Type declarations and APIs for the HKDF-SHA256 algorithm. + * + * HKDF-SHA256 is a key derivation function based on HMAC-SHA256. + * + * @see [RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF)](http://tools.ietf.org/html/rfc5869) + */ + +#ifndef OCRYPTO_HKDF_SHA256_H +#define OCRYPTO_HKDF_SHA256_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Maximum length of a derived key. + */ +#define ocrypto_hkdf_sha256_LENGTH_MAX (32) + +/** + * Maximum salt length. + */ +#define ocrypto_hkdf_sha256_SALT_LENGTH_MAX (64) + + +/** + * HKDF-SHA256 algorithm. + * + * A new pseudo-random key of length @p r_len is derived from an input key + * @p key, a salt @p salt and additional information @p info. The new key is put + * into @p r. + * + * @param[out] r Output key. + * @param r_len Length of @p r, 0 < @p r_len <= @c ocrypto_hkdf_sha256_LENGTH_MAX. + * @param key Input key. + * @param key_len Length of @p key. + * @param salt Salt. + * @param salt_len Length of salt @p salt. 0 <= @p salt_len <= @c ocrypto_hkdf_sha256_SALT_LENGTH_MAX. + * @param info Additional information. + * @param info_len Length of @p info. + */ +void ocrypto_hkdf_sha256( + uint8_t* r, size_t r_len, + const uint8_t* key, size_t key_len, + const uint8_t* salt, size_t salt_len, + const uint8_t* info, size_t info_len); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_HKDF_SHA256_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_hkdf_sha512.h b/external/nrf_oberon/include/ocrypto_hkdf_sha512.h new file mode 100644 index 0000000..45f7f89 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_hkdf_sha512.h @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_hkdf_512 HKDF APIs using SHA-512 + * @ingroup nrf_oberon_hkdf + * @{ + * @brief Type declaration and APIs for the HKDF-SHA512 algorithm. + * + * HKDF-SHA512 is a key derivation function based on HMAC-SHA512. + * + * @see [RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF)](http://tools.ietf.org/html/rfc5869) + */ + +#ifndef OCRYPTO_HKDF_SHA512_H +#define OCRYPTO_HKDF_SHA512_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Maximum length of a derived key. + */ +#define ocrypto_hkdf_sha512_LENGTH_MAX (64) + +/** + * Maximum salt length. + */ +#define ocrypto_hkdf_sha512_SALT_LENGTH_MAX (128) + + +/** + * HKDF-SHA512 algorithm. + * + * A new pseudo-random key of length @p r_len is derived from an input key + * @p key, a salt @p salt and additional information @p info. The new key is put + * into @p r. + * + * @param[out] r Output key. + * @param r_len Length of @p r, 0 < @p r_len <= @c ocrypto_hkdf_sha512_LENGTH_MAX. + * @param key Input key. + * @param key_len Length of @p key. + * @param salt Salt. + * @param salt_len Length of salt @p salt. 0 <= @p salt_len <= @c ocrypto_hkdf_sha512_SALT_LENGTH_MAX. + * @param info Additional information. + * @param info_len Length of @p info. + */ +void ocrypto_hkdf_sha512( + uint8_t* r, size_t r_len, + const uint8_t* key, size_t key_len, + const uint8_t* salt, size_t salt_len, + const uint8_t* info, size_t info_len); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_HKDF_SHA512_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_hmac_sha1.h b/external/nrf_oberon/include/ocrypto_hmac_sha1.h new file mode 100644 index 0000000..37f180e --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_hmac_sha1.h @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_hmac_1 HMAC APIs using SHA-1 + * @ingroup nrf_oberon_hmac + * @{ + * @brief Type declarations and APIs for the HMAC-SHA1 algorithm. + * + * HMAC-SHA1 is an algorithm for message authentication using the + * cryptographic hash function SHA-1 and a reusable secret key. Users in + * possession of the key can verify the integrity and authenticity of the + * message. + * + * @see [RFC 2104 - HMAC: Keyed-Hashing for Message Authentication](http://tools.ietf.org/html/rfc2104) + */ + +#ifndef OCRYPTO_HMAC_SHA1_H +#define OCRYPTO_HMAC_SHA1_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Maximum key length. + */ +#define ocrypto_hmac_sha1_KEY_BYTES_MAX (64) + +/** + * Length of the authenticator. + */ +#define ocrypto_hmac_sha1_BYTES (20) + + +/** + * HMAC-SHA1 algorithm. + * + * The input message @p in is authenticated using the key @p k. The computed + * authenticator is put into @p r. To verify the authenticator, the recipient + * needs to recompute the HMAC authenticator and can then compare it with the + * received authenticator. + * + * @param[out] r HMAC output. + * @param key HMAC key. + * @param key_len Length of @p key. 0 <= @p key_len <= @c ocrypto_hmac_sha1_KEY_BYTES_MAX. + * @param in Input data. + * @param in_len Length of @p in. + */ +void ocrypto_hmac_sha1( + uint8_t r[ocrypto_hmac_sha1_BYTES], + const uint8_t* key, size_t key_len, + const uint8_t* in, size_t in_len); + +/** + * HMAC-SHA1 algorithm with AAD. + * + * @param[out] r HMAC output + * @param key HMAC key. + * @param key_len Length of @p key. 0 <= @p key_len <= @c ocrypto_hmac_sha1_KEY_BYTES_MAX. + * @param in Input data. + * @param in_len Length of @p in. + * @param aad Additional authentication data. May be NULL. + * @param aad_len Length of @p aad. + */ +void ocrypto_hmac_sha1_aad( + uint8_t r[20], + const uint8_t* key, size_t key_len, + const uint8_t* in, size_t in_len, + const uint8_t* aad, size_t aad_len); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_HMAC_SHA1_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_hmac_sha256.h b/external/nrf_oberon/include/ocrypto_hmac_sha256.h new file mode 100644 index 0000000..f402aee --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_hmac_sha256.h @@ -0,0 +1,193 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_hmac HMAC - Hash-based Aessage Authentication Code + * @ingroup nrf_oberon + * @{ + * @brief HMAC is a hash-based Message Authentication Code utilizing a secure hash function. + * @} + * @defgroup nrf_oberon_hmac_256 HMAC APIs using SHA-256 + * @ingroup nrf_oberon_hmac + * @{ + * @brief Type declarations and APIs for the HMAC-SHA256 algorithm. + * + * HMAC-SHA256 is an algorithm for message authentication using the + * cryptographic hash function SHA256 and a reusable secret key. Users in + * possession of the key can verify the integrity and authenticity of the + * message. + * + * @see [RFC 2104 - HMAC: Keyed-Hashing for Message Authentication](http://tools.ietf.org/html/rfc2104) + */ + +#ifndef OCRYPTO_HMAC_SHA256_H +#define OCRYPTO_HMAC_SHA256_H + +#include +#include +#include "ocrypto_sha256.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Maximum key length. + */ +#define ocrypto_hmac_sha256_KEY_BYTES_MAX (64) + +/** + * Length of the authenticator. + */ +#define ocrypto_hmac_sha256_BYTES (32) + +/**@cond */ +typedef struct +{ + ocrypto_sha256_ctx hash_ctx; + uint8_t ikey[ocrypto_hmac_sha256_KEY_BYTES_MAX]; + uint8_t okey[ocrypto_hmac_sha256_KEY_BYTES_MAX]; + uint8_t key[ocrypto_hmac_sha256_KEY_BYTES_MAX]; +} ocrypto_hmac_sha256_ctx; +/**@endcond */ + + +/**@name Incremental HMAC-SHA256 generator. + * + * This group of functions can be used to incrementally compute HMAC-SHA256 + * for a given message. + */ +/**@{*/ + +/** + * HMAC-SHA256 initialization. + * + * The generator state @p ctx is initialized by this function. + * + * @param[out] ctx Generator state. + * @param key HMAC key. + * @param key_len Length of @p key. + */ +void ocrypto_hmac_sha256_init(ocrypto_hmac_sha256_ctx * ctx, + const uint8_t* key, size_t key_len); + +/** + * HMAC-SHA256 incremental data input. + * + * The generator state @p ctx is updated to hash a message chunk @p in. + * + * This function can be called repeatedly until the whole message is processed. + * + * @param[in,out] ctx Generator state. + * @param in Input data. + * @param in_len Length of @p in. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_hmac_sha256_init is required before this function can be called. + */ +void ocrypto_hmac_sha256_update(ocrypto_hmac_sha256_ctx * ctx, + const uint8_t* in, size_t in_len); + +/** + * HMAC-SHA256 output. + * + * The generator state @p ctx is updated to finalize the HMAC calculation. + * The HMAC digest is put into @p r. + * + * @param[in,out] ctx Generator state. + * @param[out] r Generated HMAC digest. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_hmac_sha256_init is required before this function can be called. + * + * @remark After return, the generator state @p ctx must no longer be used with + * @c ocrypto_hmac_sha256_update and @c ocrypto_hmac_sha256_final unless it is + * reinitialized using @c ocrypto_hmac_sha256_init. + */ +void ocrypto_hmac_sha256_final(ocrypto_hmac_sha256_ctx * ctx, + uint8_t r[ocrypto_hmac_sha256_BYTES]); +/**@}*/ + + +/** + * HMAC-SHA256 algorithm. + * + * The input message @p in is authenticated using the key @p k. The computed + * authenticator is put into @p r. To verify the authenticator, the recipient + * needs to recompute the HMAC authenticator and can then compare it with the + * received authenticator. + * + * @param[out] r HMAC output. + * @param key HMAC key. + * @param key_len Length of @p key. 0 <= @p key_len <= @c ocrypto_hmac_sha256_KEY_BYTES_MAX. + * @param in Input data. + * @param in_len Length of @p in. + */ +void ocrypto_hmac_sha256( + uint8_t r[ocrypto_hmac_sha256_BYTES], + const uint8_t* key, size_t key_len, + const uint8_t* in, size_t in_len); + +/** + * HMAC-SHA256 algorithm with AAD. + * + * @param[out] r HMAC output + * @param key HMAC key. + * @param key_len Length of @p key. 0 <= @p key_len <= @c ocrypto_hmac_sha256_KEY_BYTES_MAX. + * @param in Input data. + * @param in_len Length of @p in. + * @param aad Additional authentication data. May be NULL. + * @param aad_len Length of @p aad. + */ +void ocrypto_hmac_sha256_aad( + uint8_t r[ocrypto_hmac_sha256_BYTES], + const uint8_t* key, size_t key_len, + const uint8_t* in, size_t in_len, + const uint8_t* aad, size_t aad_len); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_HMAC_SHA256_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_hmac_sha512.h b/external/nrf_oberon/include/ocrypto_hmac_sha512.h new file mode 100644 index 0000000..c4380ed --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_hmac_sha512.h @@ -0,0 +1,171 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_hmac_512 HMAC APIs using SHA-512 + * @ingroup nrf_oberon_hmac + * @{ + * @brief Type declarations and APIs for the HMAC-SHA512 algorithm. + * + * HMAC-SHA512 is an algorithm for message authentication using the + * cryptographic hash function SHA512 and a reusable secret key. Users in + * possession of the key can verify the integrity and authenticity of the + * message. + * + * @see [RFC 2104 - HMAC: Keyed-Hashing for Message Authentication](http://tools.ietf.org/html/rfc2104) + */ + +#ifndef OCRYPTO_HMAC_SHA512_H +#define OCRYPTO_HMAC_SHA512_H + +#include +#include +#include "ocrypto_sha512.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Maximum key length. + */ +#define ocrypto_hmac_sha512_KEY_BYTES_MAX (128) + +/** + * Length of the authenticator. + */ +#define ocrypto_hmac_sha512_BYTES (64) + +/**@cond */ +typedef struct +{ + ocrypto_sha512_ctx hash_ctx; + uint8_t ikey[ocrypto_hmac_sha512_KEY_BYTES_MAX]; + uint8_t okey[ocrypto_hmac_sha512_KEY_BYTES_MAX]; + uint8_t key[ocrypto_hmac_sha512_KEY_BYTES_MAX]; +} ocrypto_hmac_sha512_ctx; +/**@endcond */ + + +/**@name Incremental HMAC-SHA512 generator. + * + * This group of functions can be used to incrementally compute HMAC-SHA512 + * for a given message. + */ +/**@{*/ + +/** + * HMAC-SHA512 initialization. + * + * The generator state @p ctx is initialized by this function. + * + * @param[out] ctx Generator state. + * @param key HMAC key. + * @param key_len Length of @p key. + */ +void ocrypto_hmac_sha512_init(ocrypto_hmac_sha512_ctx * ctx, + const uint8_t* key, size_t key_len); + +/** + * HMAC-SHA512 incremental data input. + * + * The generator state @p ctx is updated to hash a message chunk @p in. + * + * This function can be called repeatedly until the whole message is processed. + * + * @param[in,out] ctx Generator state. + * @param in Input data. + * @param in_len Length of @p in. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_hmac_sha512_init is required before this function can be called. + */ +void ocrypto_hmac_sha512_update(ocrypto_hmac_sha512_ctx * ctx, + const uint8_t* in, size_t in_len); + +/** + * HMAC-SHA512 output. + * + * The generator state @p ctx is updated to finalize the HMAC calculation. + * The HMAC digest is put into @p r. + * + * @param[in,out] ctx Generator state. + * @param[out] r Generated HMAC digest. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_hmac_sha512_init is required before this function can be called. + * + * @remark After return, the generator state @p ctx must no longer be used with + * @c ocrypto_hmac_sha512_update and @c ocrypto_hmac_sha512_final unless it is + * reinitialized using @c ocrypto_hmac_sha512_init. + */ +void ocrypto_hmac_sha512_final(ocrypto_hmac_sha512_ctx * ctx, + uint8_t r[ocrypto_hmac_sha512_BYTES]); + +/**@}*/ + +/** + * HMAC-SHA512 algorithm. + * + * The input message @p in is authenticated using the key @p k. The computed + * authenticator is put into @p r. To verify the authenticator, the recipient + * needs to recompute the HMAC authenticator and can then compare it with the + * received authenticator. + * + * @param[out] r HMAC output. + * @param key HMAC key. + * @param key_len Length of @p key. 0 <= @p key_len <= @c ocrypto_hmac_sha512_KEY_BYTES_MAX. + * @param in Input data. + * @param in_len Length of @p in. + */ +void ocrypto_hmac_sha512( + uint8_t r[ocrypto_hmac_sha512_BYTES], + const uint8_t* key, size_t key_len, + const uint8_t* in, size_t in_len); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_HMAC_SHA512_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_poly1305.h b/external/nrf_oberon/include/ocrypto_poly1305.h new file mode 100644 index 0000000..5b0f786 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_poly1305.h @@ -0,0 +1,178 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_poly1305 Poly1305 APIs + * @ingroup nrf_oberon_chacha_poly + @{ + * @brief Type declaration and APIs for the Poly1035 algorithm. + * + * Poly1305 is a message authentication code created by Daniel J. + * Bernstein. It can be used to verify the data integrity and the + * authenticity of a message. + * + * Poly1305 takes a one-time key to produce an authentication tag for a message. + * Since a key can only be used to authenticate a single message, a new key + * needs to be derived for each message. + * + * @see [RFC 7539 - ChaCha20 and Poly1305 for IETF Protocols](http://tools.ietf.org/html/rfc7539) + * @see [Poly1305-AES: a state-of-the-art message-authentication code](http://cr.yp.to/mac.html) + */ + +#ifndef OCRYPTO_POLY1305_H +#define OCRYPTO_POLY1305_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Key length. + */ +#define ocrypto_poly1305_KEY_BYTES (32) + +/** + * Authenticator length. + */ +#define ocrypto_poly1305_BYTES (16) + + +/**@cond */ +typedef struct { + uint32_t h[5]; +} ocrypto_poly1305_ctx; +/**@endcond */ + + +/**@name Incremental Poly1305 generator. + * + * This group of functions can be used to incrementally compute the Poly1305 + * authenticator for a given message and key. + */ +/**@{*/ +/** + * Poly1305 generator initialize. + * + * The generator state @p ctx is initialized by this function. + * + * @param[out] ctx Generator state. + */ +void ocrypto_poly1305_init(ocrypto_poly1305_ctx *ctx); + +/** + * Poly1305 generator. + * + * The generator state @p ctx is updated to authenticate a message chunk @p in + * with a key @p k. + * + * This function can be called repeatedly until the whole message has been + * processed. + * + * @param ctx Generator state. + * @param in Input data. + * @param in_len Length of @p in. + * @param k Encryption key. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_poly1305_init is required before this function can be called. + * + * @remark The same key @p k needs to be supplied for all message chunks. + */ +void ocrypto_poly1305_update( + ocrypto_poly1305_ctx *ctx, + const uint8_t *in, size_t in_len, + const uint8_t k[ocrypto_poly1305_KEY_BYTES]); + +/** + * Poly1305 generator output. + * + * The generator state @p ctx is updated to finalize the authenticator for the + * previously processed message chunks with key @p k. The authentication tag is + * put into @p r. + * + * @param ctx Generator state. + * @param[out] r Generated authentication tag. + * @param k Encryption key. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_poly1305_init is required before this function can be called. + * + * @remark The same key @p k needs to be supplied that was used in previous + * @c ocrypto_poly1305_update invocations. + * + * @remark After return, the generator state @p ctx must no longer be used with + * @c ocrypto_poly1305_update and @c ocrypto_poly1305_final unless it is + * reinitialized using @c ocrypto_poly1305_init. + */ +void ocrypto_poly1305_final( + ocrypto_poly1305_ctx *ctx, + uint8_t r[ocrypto_poly1305_BYTES], + const uint8_t k[ocrypto_poly1305_KEY_BYTES]); +/**@}*/ + +/** + * Poly1305 message authentication tag. + * + * The Poly1305 authentication of a given input message @p in is computed and + * put into @p r. + * + * @param[out] r Generated authentication tag. + * @param in Input data. + * @param in_len Length of @p in. + * @param k Encryption key. + */ +void ocrypto_poly1305( + uint8_t r[ocrypto_poly1305_BYTES], + const uint8_t *in, size_t in_len, + const uint8_t k[ocrypto_poly1305_KEY_BYTES]); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_POLY1305_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_rsa.h b/external/nrf_oberon/include/ocrypto_rsa.h new file mode 100644 index 0000000..559a230 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_rsa.h @@ -0,0 +1,645 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_rsa RSA - Rivest-Shamir-Adleman algorithm + * @ingroup nrf_oberon + * @{ + * @brief RSA is a number theoretic public-key encryption and signature algorithm. + * @} + * @defgroup nrf_oberon_rsa_api RSA APIs + * @ingroup nrf_oberon_rsa + * @{ + * @brief APIs to for RSA encryption/decryption and sign/verify using PKCS1 v1.5, OEAP and PSS. + * + * These functions support RSA encryption and signatures with 1024 and 2048-bit + * modulo and PKCS1 V1.5 padding. + */ + +#ifndef OCRYPTO_RSA_H +#define OCRYPTO_RSA_H + +#include +#include + +#include "ocrypto_rsa_key.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@name 1024-bit RSA Functions. + * + * This group of functions is used for 1024-bit RSA. + */ +/**@{*/ +/** + * 1024 bit RSA PKCS1 V1.5 encryption. + * + * The message @p m is encrypted to a ciphertext returned in @p c. + * + * @param[out] c The generated 128-byte ciphertext. + * @param m The message to be encrypted. + * @param mlen Length of @p m. 0 <= mlen <= 117. + * @param seed The random seed to be used for the padding. + * @param slen Length of @p seed. @p slen >= 125 - @p mlen. + * @param pk A valid 1024-bit RSA public key. + * + * @retval -1 If the message is too long (mlen > 117). + * @retval -2 If the seed is too short (slen < 125 - mlen). + * @retval 0 Otherwise. + * + * @remark The key @p pk should be initialized with @c ocrypto_rsa1024_init_pub_key. + * @remark The @p seed should consist of non-zero random bytes. + * @remark @p c and @p m can point to the same address. + */ +int ocrypto_rsa1024_pkcs1_v15_encrypt( + uint8_t c[128], + const uint8_t *m, size_t mlen, + const uint8_t *seed, size_t slen, + const ocrypto_rsa1024_pub_key *pk); + +/** + * 1024-bit RSA PKCS1 V1.5 decryption. + * + * The ciphertext @p c is decrypted to the message returned in @p m. + * + * @param[out] m The decrypted message. The buffer must be long enough to hold the message. + * @param mlen Length of @p m. + * @param c The 128-byte ciphertext to decrypt. + * @param k A valid 1024-bit RSA secret key. + * + * @retval -1 If decryption failed. + * @retval -2 If the output buffer is too short (mlen < length of message). + * @retval n If a message of length n was successfully decrypted. + * + * @remark The key @p k should be initialized with @c ocrypto_rsa1024_init_key. + * @remark @p m and @p c can point to the same address. + */ +int ocrypto_rsa1024_pkcs1_v15_decrypt( + uint8_t *m, size_t mlen, + const uint8_t c[128], + const ocrypto_rsa1024_key *k); + +/** + * 1024-bit RSA PKCS1 V1.5 decryption with CRT acceleration. + * + * The ciphertext @p c is decrypted to the message returned in @p m. + * + * @param[out] m The decrypted message. The buffer must be long enough to hold the message. + * @param mlen Length of @p m. + * @param c The 128-byte ciphertext to decrypt. + * @param k A valid 1024-bit RSA secret key with CRT coefficients. + * + * @retval -1 If decryption failed. + * @retval -2 If the output buffer is too short (mlen < length of message). + * @retval n If a message of length n was successfully decrypted. + * + * @remark The key @p k should be initialized with @c ocrypto_rsa1024_init_crt_key. + * @remark @p m and @p c can point to the same address. + */ +int ocrypto_rsa1024_pkcs1_v15_crt_decrypt( + uint8_t *m, size_t mlen, + const uint8_t c[128], + const ocrypto_rsa1024_crt_key *k); + +/** + * 1024-bit RSA OAEP SHA256 encryption. + * + * The message @p m is encrypted to a ciphertext returned in @p c. + * + * @param[out] c The generated 128-byte ciphertext. + * @param m The message to be encrypted. + * @param mlen Length of @p m. 0 <= mlen <= 62. + * @param label The label associated with the message. + * @param llen Length of @p label. May be 0. + * @param seed 32-byte random seed. + * @param pk A valid 1024-bit RSA public key. + * + * @retval -1 If the message is too long (mlen > 62). + * @retval 0 Otherwise. + * + * @remark The key @p pk should be initialized with @c ocrypto_rsa1024_init_pub_key. + * @remark @p c and @p m can point to the same address. + */ +int ocrypto_rsa1024_oaep_sha256_encrypt( + uint8_t c[128], + const uint8_t *m, size_t mlen, + const uint8_t *label, size_t llen, + const uint8_t seed[32], + const ocrypto_rsa1024_pub_key *pk); + +/** + * 1024-bit RSA OAEP SHA256 decryption. + * + * The ciphertext @p c is decrypted to the message returned in @p m. + * + * @param[out] m The decrypted message. The buffer must be long enough to hold the message. + * @param mlen Length of @p m. + * @param c The 128-byte ciphertext to decrypt. + * @param label The label associated with the message. + * @param llen Length of @p label. May be 0. + * @param k A valid 1024-bit RSA secret key. + * + * @retval -1 If decryption failed. + * @retval -2 If the output buffer is too short (mlen < length of message). + * @retval n If a message of length n was successfully decrypted. + * + * @remark The key @p k should be initialized with @c ocrypto_rsa1024_init_key. + * @remark @p m and @p c can point to the same address. + */ +int ocrypto_rsa1024_oaep_sha256_decrypt( + uint8_t *m, size_t mlen, + const uint8_t c[128], + const uint8_t *label, size_t llen, + const ocrypto_rsa1024_key *k); + +/** + * 1024-bit RSA OAEP SHA256 decryption with CRT acceleration. + * + * The ciphertext @p c is decrypted to the message returned in @p m. + * + * @param[out] m The decrypted message. The buffer must be long enough to hold the message. + * @param mlen Length of @p m. + * @param c The 128-byte ciphertext to decrypt. + * @param label The label associated with the message. + * @param llen Length of @p label. May be 0. + * @param k A valid 1024-bit RSA secret key with CRT coefficients. + * + * @retval -1 If decryption failed. + * @retval -2 If the output buffer is too short (mlen < length of message). + * @retval n If a message of length n was successfully decrypted. + * + * @remark The key @p k should be initialized with @c ocrypto_rsa1024_init_crt_key. + * @remark @p m and @p c can point to the same address. + */ +int ocrypto_rsa1024_oaep_sha256_crt_decrypt( + uint8_t *m, size_t mlen, + const uint8_t c[128], + const uint8_t *label, size_t llen, + const ocrypto_rsa1024_crt_key *k); + +/** + * 1024-bit RSA PKCS1 V1.5 SHA-256 sign. + * + * The message @p m is signed and the signature returned in @p s. + * + * @param[out] s The generated 128-byte signature. + * @param m The message to be signed. + * @param mlen Length of @p m. + * @param k A valid 1024-bit RSA secret key. + * + * @return 0 + * + * @remark The key @p k should be initialized with @c ocrypto_rsa1024_init_key. + * @remark @p s and @p m can point to the same address. + */ +int ocrypto_rsa1024_pkcs1_v15_sha256_sign( + uint8_t s[128], + const uint8_t *m, size_t mlen, + const ocrypto_rsa1024_key *k); + +/** + * 1024-bit RSA PKCS1 V1.5 SHA-256 sign with CRT acceleration. + * + * The message @p m is signed and the signature returned in @p s. + * + * @param[out] s The generated 128-byte signature. + * @param m The message to be signed. + * @param mlen Length of @p m. + * @param k A valid 1024-bit RSA secret key with CRT coefficients. + * + * @return 0 + * + * @remark The key @p k should be initialized with @c ocrypto_rsa1024_init_crt_key. + * @remark @p s and @p m can point to the same address. + */ +int ocrypto_rsa1024_pkcs1_v15_sha256_crt_sign( + uint8_t s[128], + const uint8_t *m, size_t mlen, + const ocrypto_rsa1024_crt_key *k); + +/** + * 1024-bit RSA PKCS1 V1.5 SHA-256 signature verify. + * + * The signature @p s is verified for a valid signature of message @p m. + * + * @param s The 128-byte signature. + * @param m The signed message. + * @param mlen Length of @p m. + * @param pk A valid 1024-bit RSA public key. + * + * @retval 0 If the signature is valid. + * @retval -1 If verification failed. + * + * @remark The key @p pk should be initialized with @c ocrypto_rsa1024_init_pub_key. + */ +int ocrypto_rsa1024_pkcs1_v15_sha256_verify( + const uint8_t s[128], + const uint8_t *m, size_t mlen, + const ocrypto_rsa1024_pub_key *pk); + +/** + * 1024-bit RSA PSS SHA-256 sign. + * + * The message @p m is signed and the signature returned in @p s. + * + * @param[out] s The generated 128-byte signature. + * @param m The message to be signed. + * @param mlen Length of @p m. + * @param salt The salt to be used. + * @param slen Length of @p salt. + * @param k A valid 1024-bit RSA secret key. + * + * @retval -2 If the salt is too long. + * @retval 0 Otherwise. + * + * @remark The key @p k should be initialized with @c ocrypto_rsa1024_init_key. + * @remark @p s and @p m can point to the same address. + */ +int ocrypto_rsa1024_pss_sha256_sign( + uint8_t s[128], + const uint8_t *m, size_t mlen, + const uint8_t *salt, size_t slen, + const ocrypto_rsa1024_key *k); + +/** + * 1024-bit RSA PSS SHA-256 sign with CRT acceleration. + * + * The message @p m is signed and the signature returned in @p s. + * + * @param[out] s The generated 128-byte signature. + * @param m The message to be signed. + * @param mlen Length of @p m. + * @param salt The salt to be used. + * @param slen Length of @p salt. + * @param k A valid 1024-bit RSA secret key with CRT coefficients. + * + * @retval -2 If the salt is too long. + * @retval 0 Otherwise. + * + * @remark The key @p k should be initialized with @c ocrypto_rsa1024_init_crt_key. + * @remark @p s and @p m can point to the same address. + */ +int ocrypto_rsa1024_pss_sha256_crt_sign( + uint8_t s[128], + const uint8_t *m, size_t mlen, + const uint8_t *salt, size_t slen, + const ocrypto_rsa1024_crt_key *k); + +/** + * 1024-bit RSA PSS SHA-256 signature verify. + * + * The signature @p s is verified for a valid signature of message @p m. + * + * @param s The 128-byte signature. + * @param m The signed message. + * @param mlen Length of @p m. + * @param slen The length of the salt. + * @param pk A valid 1024-bit RSA public key. + * + * @retval 0 If the signature is valid. + * @retval -1 If verification failed. + * @retval -2 If the salt is too long. + * + * @remark The key @p pk should be initialized with @c ocrypto_rsa1024_init_pub_key. + */ +int ocrypto_rsa1024_pss_sha256_verify( + const uint8_t s[128], + const uint8_t *m, size_t mlen, + size_t slen, // salt length + const ocrypto_rsa1024_pub_key *pk); +/**@}*/ + + +/**@name 2048-bit RSA Functions. + * + * This group of functions is used for 2048-bit RSA. + */ +/**@{*/ +/** + * 2048-bit RSA PKCS1 V1.5 encryption. + * + * The message @p m is encrypted to a ciphertext returned in @p c. + * + * @param[out] c The generated 256-byte ciphertext. + * @param m The message to be encrypted. + * @param mlen Length of @p m. 0 <= @p mlen <= 245. + * @param seed The random seed to be used for the padding. + * @param slen Length of @p seed. @p slen >= 253 - @p mlen. + * @param pk A valid 2048-bit RSA public key. + * + * @retval -1 If the message is too long (mlen > 245). + * @retval -2 If the seed is too short (slen < 253 - mlen). + * @retval 0 Otherwise. + * + * @remark The key @p pk should be initialized with @c ocrypto_rsa2048_init_pub_key. + * @remark The @p seed should consist of non-zero random bytes. + * @remark @p c and @p m can point to the same address. + */ +int ocrypto_rsa2048_pkcs1_v15_encrypt( + uint8_t c[256], + const uint8_t *m, size_t mlen, + const uint8_t *seed, size_t slen, + const ocrypto_rsa2048_pub_key *pk); + +/** + * 2048-bit RSA PKCS1 V1.5 decryption. + * + * The ciphertext @p c is decrypted to the message returned in @p m. + * + * @param[out] m The decrypted message. The buffer must be long enough to hold the message. + * @param mlen Length of @p m. + * @param c The 256-byte ciphertext to decrypt. + * @param k A valid 2048-bit RSA secret key. + + * @retval -1 If decryption failed. + * @retval -2 If the output buffer is too short (mlen < length of message). + * @retval n If a message of length n was successfully decrypted. + * + * @remark The key @p k should be initialized with @c ocrypto_rsa2048_init_key. + * @remark @p m and @p c can point to the same address. + */ +int ocrypto_rsa2048_pkcs1_v15_decrypt( + uint8_t *m, size_t mlen, + const uint8_t c[256], + const ocrypto_rsa2048_key *k); + +/** + * 2048-bit RSA PKCS1 V1.5 decryption with CRT acceleration. + * + * The ciphertext @p c is decrypted to the message returned in @p m. + * + * @param[out] m The decrypted message. The buffer must be long enough to hold the message. + * @param mlen Length of @p m. + * @param c The 256-byte ciphertext to decrypt. + * @param k A valid 2048-bit RSA secret key with CRT coefficients. + + * @retval -1 If decryption failed. + * @retval -2 If the output buffer is too short (mlen < length of message). + * @retval n If a message of length n was successfully decrypted. + * + * @remark The key @p k should be initialized with @c ocrypto_rsa2048_init_crt_key. + * @remark @p m and @p c can point to the same address. + */ +int ocrypto_rsa2048_pkcs1_v15_crt_decrypt( + uint8_t *m, size_t mlen, + const uint8_t c[256], + const ocrypto_rsa2048_crt_key *k); + +/** + * 2048-bit RSA OAEP SHA256 encryption. + * + * The message @p m is encrypted to a ciphertext returned in @p c. + * + * @param[out] c The generated 256-byte ciphertext. + * @param m The message to be encrypted. + * @param mlen Length of @p m. 0 <= mlen <= 190. + * @param label The label associated with the message. + * @param llen Length of @p label. May be 0. + * @param seed 32-byte random seed. + * @param pk A valid 2048-bit RSA public key. + * + * @retval -1 If the message is too long (mlen > 190). + * @retval 0 Otherwise. + * + * @remark The key @p pk should be initialized with @c ocrypto_rsa2048_init_pub_key. + * @remark @p c and @p m can point to the same address. + */ +int ocrypto_rsa2048_oaep_sha256_encrypt( + uint8_t c[256], + const uint8_t *m, size_t mlen, + const uint8_t *label, size_t llen, + const uint8_t seed[32], + const ocrypto_rsa2048_pub_key *pk); + +/** + * 2048-bit RSA OAEP SHA256 decryption. + * + * The ciphertext @p c is decrypted to the message returned in @p m. + * + * @param[out] m The decrypted message. The buffer must be long enough to hold the message. + * @param mlen Length of @p m. + * @param c The 256-byte ciphertext to decrypt. + * @param label The label associated with the message. + * @param llen Length of @p label. May be 0. + * @param k A valid 2048-bit RSA secret key. + * + * @retval -1 If decryption failed. + * @retval -2 If the output buffer is too short (mlen < length of message). + * @retval n If a message of length n was successfully decrypted. + * + * @remark The key @p k should be initialized with @c ocrypto_rsa2048_init_key. + * @remark @p m and @p c can point to the same address. + */ +int ocrypto_rsa2048_oaep_sha256_decrypt( + uint8_t *m, size_t mlen, + const uint8_t c[256], + const uint8_t *label, size_t llen, + const ocrypto_rsa2048_key *k); + +/** + * 2048-bit RSA OAEP SHA256 decryption with CRT acceleration. + * + * The ciphertext @p c is decrypted to the message returned in @p m. + * + * @param[out] m The decrypted message. The buffer must be long enough to hold the message. + * @param mlen Length of @p m. + * @param c The 256-byte ciphertext to decrypt. + * @param label The label associated with the message. + * @param llen Length of @p label. May be 0. + * @param k A valid 2048-bit RSA secret key with CRT coefficients. + * + * @retval -1 If decryption failed. + * @retval -2 If the output buffer is too short (mlen < length of message). + * @retval n If a message of length n was successfully decrypted. + * + * @remark The key @p k should be initialized with @c ocrypto_rsa2048_init_crt_key. + * @remark @p m and @p c can point to the same address. + */ +int ocrypto_rsa2048_oaep_sha256_crt_decrypt( + uint8_t *m, size_t mlen, + const uint8_t c[256], + const uint8_t *label, size_t llen, + const ocrypto_rsa2048_crt_key *k); + +/** + * 2048-bit RSA PKCS1 V1.5 SHA-256 sign. + * + * The message @p m is signed and the signature returned in @p s. + * + * @param[out] s The generated 256-byte signature. + * @param m The message to be signed. + * @param mlen Length of @p m. + * @param k A valid 2048-bit RSA secret key. + + * @returns 0 + * + * @remark The key @p k should be initialized with @c ocrypto_rsa2048_init_key. + * @remark @p s and @p m can point to the same address. + */ +int ocrypto_rsa2048_pkcs1_v15_sha256_sign( + uint8_t s[256], + const uint8_t *m, size_t mlen, + const ocrypto_rsa2048_key *k); + +/** + * 2048-bit RSA PKCS1 V1.5 SHA-256 sign with CRT acceleration. + * + * The message @p m is signed and the signature returned in @p s. + * + * @param[out] s The generated 256-byte signature. + * @param m The message to be signed. + * @param mlen Length of @p m. + * @param k A valid 2048-bit RSA secret key with CRT coefficients. + + * @returns 0 + * + * @remark The key @p k should be initialized with @c ocrypto_rsa2048_init_crt_key. + * @remark @p s and @p m can point to the same address. + */ +int ocrypto_rsa2048_pkcs1_v15_sha256_crt_sign( + uint8_t s[256], + const uint8_t *m, size_t mlen, + const ocrypto_rsa2048_crt_key *k); + +/** + * 2048-bit RSA PKCS1 V1.5 SHA-256 signature verify. + * + * The signature @p s is verified for a correct signature of message @p m. + * + * @param s The 256-byte signature. + * @param m The signed message. + * @param mlen Length of @p m. + * @param pk A valid 2048-bit RSA public key. + * + * @retval 0 If the signature is valid. + * @retval -1 If verification failed. + * + * @remark The key @p pk should be initialized with @c ocrypto_rsa2048_init_pub_key. + */ +int ocrypto_rsa2048_pkcs1_v15_sha256_verify( + const uint8_t s[256], + const uint8_t *m, size_t mlen, + const ocrypto_rsa2048_pub_key *pk); + +/** + * 2048-bit RSA PSS SHA-256 sign. + * + * The message @p m is signed and the signature returned in @p s. + * + * @param[out] s The generated 256-byte signature. + * @param m The message to be signed. + * @param mlen Length of @p m. + * @param salt The salt to be used. + * @param slen Length of @p salt. + * @param k A valid 2048-bit RSA secret key. + * + * @retval -2 If the salt is too long. + * @retval 0 Otherwise. + * + * @remark The key @p k should be initialized with @c ocrypto_rsa2048_init_key. + * @remark @p s and @p m can point to the same address. + */ +int ocrypto_rsa2048_pss_sha256_sign( + uint8_t s[256], + const uint8_t *m, size_t mlen, + const uint8_t *salt, size_t slen, + const ocrypto_rsa2048_key *k); + +/** + * 2048-bit RSA PSS SHA-256 sign with CRT acceleration. + * + * The message @p m is signed and the signature returned in @p s. + * + * @param[out] s The generated 256-byte signature. + * @param m The message to be signed. + * @param mlen Length of @p m. + * @param salt The salt to be used. + * @param slen Length of @p salt. + * @param k A valid 2048-bit RSA secret key with CRT coefficients. + * + * @retval -2 If the salt is too long. + * @retval 0 Otherwise. + * + * @remark The key @p k should be initialized with @c ocrypto_rsa2048_init_crt_key. + * @remark @p s and @p m can point to the same address. + */ +int ocrypto_rsa2048_pss_sha256_crt_sign( + uint8_t s[256], + const uint8_t *m, size_t mlen, + const uint8_t *salt, size_t slen, + const ocrypto_rsa2048_crt_key *k); + +/** + * 2048-bit RSA PSS SHA-256 signature verify. + * + * The signature @p s is verified for a valid signature of message @p m. + * + * @param s The 256-byte signature. + * @param m The signed message. + * @param mlen Length of @p m. + * @param slen The length of the salt. + * @param pk A valid 2048-bit RSA public key. + * + * @retval 0 If the signature is valid. + * @retval -1 If verification failed. + * @retval -2 If the salt is too long. + * + * @remark The key @p pk should be initialized with @c ocrypto_rsa2048_init_pub_key. + */ +int ocrypto_rsa2048_pss_sha256_verify( + const uint8_t s[256], + const uint8_t *m, size_t mlen, + size_t slen, // salt length + const ocrypto_rsa2048_pub_key *pk); +/**@}*/ + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_RSA_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_rsa_key.h b/external/nrf_oberon/include/ocrypto_rsa_key.h new file mode 100644 index 0000000..47ce11d --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_rsa_key.h @@ -0,0 +1,283 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_rsa_key RSA key APIs + * @ingroup nrf_oberon_rsa + * @{ + * @brief Type declarations for RSA APIs. + * + * RSA is a number theoretic public-key encryption and signature algorithm. + * + * These functions support the setup of 1024 and 2048 RSA secret and public keys. + */ + +#ifndef OCRYPTO_RSA_KEY_H +#define OCRYPTO_RSA_KEY_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * The Public RSA Exponent. + */ +#define PUB_EXP 65537 // 2^16 + 1 + + +/**@name 1024-bit RSA Keys + * + * This group of keys is used for 1024-bit RSA. + */ +/**@{*/ +/** + * 1024-bit RSA public key. + */ +typedef struct { + /**@cond */ + uint32_t n[32]; + // e = 65537 + /**@endcond */ +} ocrypto_rsa1024_pub_key; + +/** + * 1024 bit RSA secret key. + */ +typedef struct { + /**@cond */ + uint32_t n[32]; + uint32_t d[32]; // x^(e*d) mod n == x + /**@endcond */ +} ocrypto_rsa1024_key; + +/** + * 1024-bit RSA secret key with CRT coefficients. + */ +typedef struct { + /**@cond */ + uint32_t n[32]; + uint32_t p[16], q[16]; // primes, p*q = n + uint32_t dp[16], dq[16]; // d mod (p-1), d mod (q-1) + uint32_t qinv[16]; // 1/q mod p + /**@endcond */ +} ocrypto_rsa1024_crt_key; +/**@}*/ + + +/**@name 2048-bit RSA Keys + * + * This group of keys is used for 2048-bit RSA. + */ +/**@{*/ +/** + * 2048-bit RSA public key. + */ +typedef struct { + /**@cond */ + uint32_t n[64]; + // e = 65537 + /**@endcond */ +} ocrypto_rsa2048_pub_key; + +/** + * 2048-bit RSA secret key. + */ +typedef struct { + /**@cond */ + uint32_t n[64]; + uint32_t d[64]; // x^(e*d) mod n == x + /**@endcond */ +} ocrypto_rsa2048_key; + +/** + * 2048-bit RSA secret key with CRT coefficients. + */ +typedef struct { + /**@cond */ + uint32_t n[64]; + uint32_t p[32], q[32]; // primes, p*q = n + uint32_t dp[32], dq[32]; // d mod (p-1), d mod (q-1) + uint32_t qinv[32]; // 1/q mod p + /**@endcond */ +} ocrypto_rsa2048_crt_key; +/**@}*/ + +/**@name 1024-bit RSA key setup + * + * This group of functions is used for 1024-bit RSA key setup. + */ +/**@{*/ +/** + * 1024-bit RSA public key setup. + * + * @param[out] k The initialized public key. + * @param n The RSA modulus. Must be exactly 1024 bits. + * @param nlen Length of @p n. + * + * @retval -1 If the input length is invalid. + * @retval 0 Otherwise. + * + * @remark The public exponent is fixed at 65537. + */ +int ocrypto_rsa1024_init_pub_key( + ocrypto_rsa1024_pub_key *k, + const uint8_t *n, size_t nlen); + +/** + * 1024-bit RSA secret key setup. + * + * @param[out] k The initialized public key. + * @param n The RSA modulus. Must be exactly 1024 bits. + * @param nlen Length of @p n. + * @param d The secret exponent. Must be <= 1024 bits. + * @param dlen Length of @p d. + * + * @retval -1 If the input length is invalid. + * @retval 0 Otherwise. + */ +int ocrypto_rsa1024_init_key( + ocrypto_rsa1024_key *k, + const uint8_t *n, size_t nlen, + const uint8_t *d, size_t dlen); + +/** + * 1024-bit RSA secret key setup with CRT coefficients. + * + * @param[out] k The initialized secret key. + * @param p The 1. RSA prime. Must be exactly 512 bits. + * @param plen Length of @p p. + * @param q The 2. RSA prime. Must be exactly 512 bits. + * @param qlen Length of @p q. + * @param dp The 1. CRT exponent. dp = d mod (p-1). + * @param dplen Length of @p dp. + * @param dq The 2. CRT exponent. dq = d mod (q-1). + * @param dqlen Length of @p dq. + * @param qinv The CRT coefficient. qinv = 1/q mod p. + * @param qilen Length of @p qinv. + * + * @retval -1 If the input length is invalid. + * @retval 0 Otherwise. + */ +int ocrypto_rsa1024_init_crt_key( + ocrypto_rsa1024_crt_key *k, + const uint8_t *p, size_t plen, + const uint8_t *q, size_t qlen, + const uint8_t *dp, size_t dplen, + const uint8_t *dq, size_t dqlen, + const uint8_t *qinv, size_t qilen); +/**@}*/ + +/**@name 2048-bit RSA key setup + * + * This group of functions is used for 2048-bit RSA key setup. + */ +/**@{*/ +/** + * 2048-bit RSA public key setup. + * + * @param[out] k The initialized public key. + * @param n The RSA modulus. Must be exactly 2048 bits. + * @param nlen Length of @p n. + * + * @retval -1 If the input length is invalid. + * @retval 0 Otherwise. + * + * @remark The public exponent is fixed at 65537. + */ +int ocrypto_rsa2048_init_pub_key( + ocrypto_rsa2048_pub_key *k, + const uint8_t *n, size_t nlen); + +/** + * 2048-bit RSA secret key setup. + * + * @param[out] k The initialized public key. + * @param n The RSA modulus. Must be exactly 2048 bits. + * @param nlen Length of @p n. + * @param d The secret exponent. Must be <= 2048 bits. + * @param dlen Length of @p d. + * + * @retval -1 If the input length is invalid. + * @retval 0 Otherwise. + */ +int ocrypto_rsa2048_init_key(ocrypto_rsa2048_key *k, + const uint8_t *n, size_t nlen, + const uint8_t *d, size_t dlen); + +/** + * 2048-bit RSA secret key setup with CRT coefficients. + * + * @param[out] k The initialized secret key. + * @param p The 1. RSA prime. Must be exactly 1024 bits. + * @param plen Length of @p p. + * @param q The 2. RSA prime. Must be exactly 1024 bits. + * @param qlen Length of @p q. + * @param dp The 1. CRT exponent. dp = d mod (p-1). + * @param dplen Length of @p dp. + * @param dq The 2. CRT exponent. dq = d mod (q-1). + * @param dqlen Length of @p dq. + * @param qinv The CRT coefficient. qinv = 1/q mod p. + * @param qilen Length of @p qinv. + * + * @retval -1 If the input length is invalid. + * @retval 0 Otherwise. + */ +int ocrypto_rsa2048_init_crt_key( + ocrypto_rsa2048_crt_key *k, + const uint8_t *p, size_t plen, + const uint8_t *q, size_t qlen, + const uint8_t *dp, size_t dplen, + const uint8_t *dq, size_t dqlen, + const uint8_t *qinv, size_t qilen); +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_RSA_KEY_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_sc_p224.h b/external/nrf_oberon/include/ocrypto_sc_p224.h new file mode 100644 index 0000000..ab43165 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_sc_p224.h @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef OCRYPTO_SC_P224_H +#define OCRYPTO_SC_P224_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/**@cond */ + +// P-224 scalar modulo group order +typedef struct { + uint32_t w[7]; // little endian +} ocrypto_sc_p224; + + +// modulo P-224 number +typedef struct { + uint32_t w[7]; // little endian +} ocrypto_mod_p224; +/**@endcond */ + +// scalar to 28 byte value +void ocrypto_sc_p224_to28bytes(uint8_t r[28], const ocrypto_sc_p224 *x); + +// 28 byte value to scalar +// return 0 if x < group order +int ocrypto_sc_p224_from28bytes(ocrypto_sc_p224 *r, const uint8_t x[28]); + +// reduce 36 bytes to range 0 < r < group order +void ocrypto_sc_p224_from36bytes(ocrypto_sc_p224 *r, const uint8_t x[36]); + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_SC_P224_H */ diff --git a/external/nrf_oberon/include/ocrypto_sc_p256.h b/external/nrf_oberon/include/ocrypto_sc_p256.h new file mode 100644 index 0000000..7085279 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_sc_p256.h @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef OCRYPTO_SC_P256_H +#define OCRYPTO_SC_P256_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +// P-256 scalar modulo group order +/**@cond */ +typedef struct { + uint32_t w[8]; // little endian +} ocrypto_sc_p256; +/**@endcond */ + +// modulo P-256 number +/**@cond */ +typedef struct { + uint32_t w[8]; // little endian +} ocrypto_mod_p256; +/**@endcond */ + +// 32 byte value to scalar +// return 0 if x < group order +int ocrypto_sc_p256_from32bytes(ocrypto_sc_p256 *r, const uint8_t x[32]); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_SC_P256_H */ diff --git a/external/nrf_oberon/include/ocrypto_sha1.h b/external/nrf_oberon/include/ocrypto_sha1.h new file mode 100644 index 0000000..ea91604 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_sha1.h @@ -0,0 +1,159 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_sha_1 SHA-1 APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations and APIs for the SHA-1 algorithm. + * + * A fixed-sized message digest is computed from variable length input data. + * The function is practically impossible to revert, and small changes in the + * input message lead to major changes in the message digest. + * + * SHA-1 is no longer considered secure against well-funded opponents; + * replacement by SHA-2 or SHA-3 is recommended. + */ + +#ifndef OCRYPTO_SHA1_H +#define OCRYPTO_SHA1_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Length of SHA-1 hash. + */ +#define ocrypto_sha1_BYTES (20) + + +/**@cond */ +typedef struct { + uint32_t h[5]; + uint8_t padded[64]; + uint32_t length; + size_t bytes; +} ocrypto_sha1_ctx; +/**@endcond */ + + +/**@name Incremental SHA-1 generator. + * + * This group of functions can be used to incrementally compute the SHA-1 + * hash for a given message. + */ +/**@{*/ +/** + * SHA-1 initialization. + * + * The generator state @p ctx is initialized by this function. + * + * @param[out] ctx Generator state. + */ +void ocrypto_sha1_init( + ocrypto_sha1_ctx *ctx); + +/** + * SHA-1 incremental data input. + * + * The generator state @p ctx is updated to hash a message chunk @p in. + * + * This function can be called repeatedly until the whole message is processed. + * + * @param ctx Generator state. + * @param in Input data. + * @param in_len Length of @p in. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_sha1_init is required before this function can be called. + */ +void ocrypto_sha1_update( + ocrypto_sha1_ctx *ctx, + const uint8_t *in, size_t in_len); + +/** + * SHA-1 output. + * + * The generator state @p ctx is updated to finalize the hash for the previously + * processed message chunks. The hash is put into @p r. + * + * @param ctx Generator state. + * @param[out] r Generated hash value. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_sha1_init is required before this function can be called. + * + * @remark After return, the generator state @p ctx must no longer be used with + * @c ocrypto_sha1_update and @c ocrypto_sha1_final unless it is + * reinitialized using @c ocrypto_sha1_init. + */ +void ocrypto_sha1_final( + ocrypto_sha1_ctx *ctx, + uint8_t r[ocrypto_sha1_BYTES]); +/**@}*/ + + +/** + * SHA-1 hash. + * + * The SHA-1 hash of a given input message @p in is computed and put into @p r. + * + * @param[out] r Generated hash. + * @param in Input data. + * @param in_len Length of @p in. + */ +void ocrypto_sha1( + uint8_t r[ocrypto_sha1_BYTES], + const uint8_t *in, size_t in_len); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_SHA1_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_sha224.h b/external/nrf_oberon/include/ocrypto_sha224.h new file mode 100644 index 0000000..dc03a59 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_sha224.h @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_sha_224 SHA-224 APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations and APIs for the SHA-224 algorithm. + * + * SHA-224 is part of the SHA-2 family that is a set of cryptographic hash + * functions designed by the NSA. It is the successor of the SHA-1 algorithm. + * + * A fixed-sized message digest is computed from variable length input data. + * The function is practically impossible to revert, and small changes in the + * input message lead to major changes in the message digest. + */ + +#ifndef OCRYPTO_SHA224_H +#define OCRYPTO_SHA224_H + +#include +#include + +#include "ocrypto_sha256.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Length of SHA-224 hash. + */ +#define ocrypto_sha224_BYTES (28) + +/**@cond */ +typedef ocrypto_sha256_ctx ocrypto_sha224_ctx; +/**@endcond */ + + +/**@name Incremental SHA-224 generator. + * + * This group of functions can be used to incrementally compute the SHA-224 + * hash for a given message. + */ +/**@{*/ +/** + * SHA-224 initialization. + * + * The generator state @p ctx is initialized by this function. + * + * @param[out] ctx Generator state. + */ +void ocrypto_sha224_init( + ocrypto_sha224_ctx *ctx); + +/** + * SHA-224 incremental data input. + * + * The generator state @p ctx is updated to hash a message chunk @p in. + * + * This function can be called repeatedly until the whole message is processed. + * + * @param ctx Generator state. + * @param in Input data. + * @param in_len Length of @p in. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_sha224_init is required before this function can be called. + */ +void ocrypto_sha224_update( + ocrypto_sha224_ctx *ctx, + const uint8_t *in, size_t in_len); + +/** + * SHA-224 output. + * + * The generator state @p ctx is updated to finalize the hash for the previously + * processed message chunks. The hash is put into @p r. + * + * @param ctx Generator state. + * @param[out] r Generated hash value. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_sha224_init is required before this function can be called. + * + * @remark After return, the generator state @p ctx must no longer be used with + * @c ocrypto_sha224_update and @c ocrypto_sha224_final unless it is + * reinitialized using @c ocrypto_sha224_init. + */ +void ocrypto_sha224_final( + ocrypto_sha224_ctx *ctx, + uint8_t r[ocrypto_sha224_BYTES]); +/**@}*/ + +/** + * SHA-224 hash. + * + * The SHA-224 hash of a given input message @p in is computed and put into @p r. + * + * @param[out] r Generated hash. + * @param in Input data. + * @param in_len Length of @p in. + */ +void ocrypto_sha224( + uint8_t r[ocrypto_sha224_BYTES], + const uint8_t *in, size_t in_len); + +#ifdef __cplusplus +} +#endif + +#endif + +/** @} */ diff --git a/external/nrf_oberon/include/ocrypto_sha256.h b/external/nrf_oberon/include/ocrypto_sha256.h new file mode 100644 index 0000000..6e550f3 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_sha256.h @@ -0,0 +1,158 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_sha_256 SHA-256 APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations and APIs for the SHA-256 algorithm. + * + * SHA-256 is part of the SHA-2 family that is a set of cryptographic hash + * functions designed by the NSA. It is the successor of the SHA-1 algorithm. + * + * A fixed-sized message digest is computed from variable length input data. + * The function is practically impossible to revert, and small changes in the + * input message lead to major changes in the message digest. + */ + +#ifndef OCRYPTO_SHA256_H +#define OCRYPTO_SHA256_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Length of SHA-256 hash. + */ +#define ocrypto_sha256_BYTES (32) + + +/**@cond */ +typedef struct { + uint32_t h[8]; + uint8_t padded[64]; + uint32_t length; + size_t bytes; +} ocrypto_sha256_ctx; +/**@endcond */ + + +/**@name Incremental SHA-256 generator + * + * This group of functions can be used to incrementally compute the SHA-256 + * hash for a given message. + */ +/**@{*/ +/** + * SHA-256 initialization. + * + * The generator state @p ctx is initialized by this function. + * + * @param[out] ctx Generator state. + */ +void ocrypto_sha256_init( + ocrypto_sha256_ctx *ctx); + +/** + * SHA-256 incremental data input. + * + * The generator state @p ctx is updated to hash a message chunk @p in. + * + * This function can be called repeatedly until the whole message is processed. + * + * @param ctx Generator state. + * @param in Input data. + * @param in_len Length of @p in. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_sha256_init is required before this function can be called. + */ +void ocrypto_sha256_update( + ocrypto_sha256_ctx *ctx, + const uint8_t *in, size_t in_len); + +/** + * SHA-256 output. + * + * The generator state @p ctx is updated to finalize the hash for the previously + * processed message chunks. The hash is put into @p r. + * + * @param ctx Generator state. + * @param[out] r Generated hash value. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_sha256_init is required before this function can be called. + * + * @remark After return, the generator state @p ctx must no longer be used with + * @c ocrypto_sha256_update and @c ocrypto_sha256_final unless it is + * reinitialized using @c ocrypto_sha256_init. + */ +void ocrypto_sha256_final( + ocrypto_sha256_ctx *ctx, + uint8_t r[ocrypto_sha256_BYTES]); +/**@}*/ + +/** + * SHA-256 hash. + * + * The SHA-256 hash of a given input message @p in is computed and put into @p r. + * + * @param[out] r Generated hash. + * @param in Input data. + * @param in_len Length of @p in. + */ +void ocrypto_sha256( + uint8_t r[ocrypto_sha256_BYTES], + const uint8_t *in, size_t in_len); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_SHA256_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_sha384.h b/external/nrf_oberon/include/ocrypto_sha384.h new file mode 100644 index 0000000..a04162c --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_sha384.h @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_sha_384 SHA-384 APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations and APIs for the SHA-384 algorithm. + * + * SHA-384 is part of the SHA-2 family that is a set of cryptographic hash + * functions designed by the NSA. It is the successor of the SHA-1 algorithm. + * + * A fixed-sized message digest is computed from variable length input data. + * The function is practically impossible to revert, and small changes in the + * input message lead to major changes in the message digest. + */ + +#ifndef OCRYPTO_SHA384_H +#define OCRYPTO_SHA384_H + +#include "ocrypto_sha512.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Length of SHA-384 hash. + */ +#define ocrypto_sha384_BYTES (48) + +/**@cond */ +typedef ocrypto_sha512_ctx ocrypto_sha384_ctx; +/**@endcond */ + + +/**@name Incremental SHA-384 generator. + * + * This group of functions can be used to incrementally compute the SHA-384 + * hash for a given message. + */ +/**@{*/ +/** + * SHA-384 initialization. + * + * The generator state @p ctx is initialized by this function. + * + * @param[out] ctx Generator state. + */ +void ocrypto_sha384_init( + ocrypto_sha384_ctx *ctx); + +/** + * SHA-384 incremental data input. + * + * The generator state @p ctx is updated to hash a message chunk @p in. + * + * This function can be called repeatedly until the whole message is processed. + * + * @param ctx Generator state. + * @param in Input data. + * @param in_len Length of @p in. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_sha384_init is required before this function can be called. + */ +void ocrypto_sha384_update( + ocrypto_sha384_ctx *ctx, + const uint8_t *in, size_t in_len); + +/** + * SHA-384 output. + * + * The generator state @p ctx is updated to finalize the hash for the previously + * processed message chunks. The hash is put into @p r. + * + * @param ctx Generator state. + * @param[out] r Generated hash value. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_sha384_init is required before this function can be called. + * + * @remark After return, the generator state @p ctx must no longer be used with + * @c ocrypto_sha384_update and @c ocrypto_sha384_final unless it is + * reinitialized using @c ocrypto_sha384_init. + */ +void ocrypto_sha384_final( + ocrypto_sha384_ctx *ctx, + uint8_t r[ocrypto_sha384_BYTES]); +/**@}*/ + +/** + * SHA-384 hash. + * + * The SHA-384 hash of a given input message @p in is computed and put into @p r. + * + * @param[out] r Generated hash. + * @param in Input data. + * @param in_len Length of @p in. + */ +void ocrypto_sha384( + uint8_t r[ocrypto_sha384_BYTES], + const uint8_t *in, size_t in_len); + +#ifdef __cplusplus +} +#endif + +#endif + +/** @} */ diff --git a/external/nrf_oberon/include/ocrypto_sha512.h b/external/nrf_oberon/include/ocrypto_sha512.h new file mode 100644 index 0000000..714b8ec --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_sha512.h @@ -0,0 +1,158 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_sha_512 SHA-512 APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations and APIs for the SHA-512 algorithm. + * + * SHA-512 is part of the SHA-2 family that is a set of cryptographic hash + * functions designed by the NSA. It is the successor of the SHA-1 algorithm. + * + * A fixed-sized message digest is computed from variable length input data. + * The function is practically impossible to revert, and small changes in the + * input message lead to major changes in the message digest. + */ + +#ifndef OCRYPTO_SHA512_H +#define OCRYPTO_SHA512_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Length of SHA-512 hash. + */ +#define ocrypto_sha512_BYTES (64) + + +/**@cond */ +typedef struct { + uint64_t h[8]; + uint8_t padded[128]; + uint32_t length; + size_t bytes; +} ocrypto_sha512_ctx; +/**@endcond */ + + +/**@name Incremental SHA-512 generator + * + * This group of functions can be used to incrementally compute the SHA-512 + * hash for a given message. + */ +/**@{*/ +/** + * SHA-512 initialization. + * + * The generator state @p ctx is initialized by this function. + * + * @param[out] ctx Generator state. + */ +void ocrypto_sha512_init( + ocrypto_sha512_ctx *ctx); + +/** + * SHA-512 incremental data input. + * + * The generator state @p ctx is updated to hash a message chunk @p in. + * + * This function can be called repeatedly until the whole message is processed. + * + * @param ctx Generator state. + * @param in Input data. + * @param in_len Length of @p in. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_sha512_init is required before this function can be called. + */ +void ocrypto_sha512_update( + ocrypto_sha512_ctx *ctx, + const uint8_t *in, size_t in_len); + +/** + * SHA-512 output. + * + * The generator state @p ctx is updated to finalize the hash for the previously + * processed message chunks. The hash is put into @p r. + * + * @param ctx Generator state. + * @param[out] r Generated hash value. + * + * @remark Initialization of the generator state @p ctx through + * @c ocrypto_sha512_init is required before this function can be called. + * + * @remark After return, the generator state @p ctx must no longer be used with + * @c ocrypto_sha512_update and @c ocrypto_sha512_final unless it is + * reinitialized using @c ocrypto_sha512_init. + */ +void ocrypto_sha512_final( + ocrypto_sha512_ctx *ctx, + uint8_t r[ocrypto_sha512_BYTES]); +/**@}*/ + +/** + * SHA-512 hash. + * + * The SHA-512 hash of a given input message @p in is computed and put into @p r. + * + * @param[out] r Generated hash. + * @param in Input data. + * @param in_len Length of @p in. + */ +void ocrypto_sha512( + uint8_t r[ocrypto_sha512_BYTES], + const uint8_t *in, size_t in_len); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_SHA512_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_srp.h b/external/nrf_oberon/include/ocrypto_srp.h new file mode 100644 index 0000000..157cf54 --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_srp.h @@ -0,0 +1,313 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_srp SRP - Secure Remote Password APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations and APIs for the SRP key agreement protocol. + * + * SRP is an augmented password-authenticated key agreement protocol, + * specifically designed to work around existing patents. SRP allows the use of + * user names and passwords over unencrypted channels and supplies a shared + * secret at the end of the authentication sequence that can be used to generate + * encryption keys. + * + * An eavesdropper or man in the middle cannot obtain enough information to be + * able to brute force guess a password without further interactions with the + * parties for each guess. + * + * The server does not store password-equivalent data. This means that an + * attacker who steals the server data cannot masquerade as the client unless + * they first perform a brute force search for the password. + * + * The specific variant implemented here is SRP-6 3072 bit SHA-512. + * + * @see [RFC 5054 - Using the Secure Remote Password (SRP) Protocol for TLS Authentication](https://tools.ietf.org/html/rfc5054) + * @see [The Stanford SRP Homepage](http://srp.stanford.edu) + * + * **Basic protocol overview** + * + * *Setup* + * 1. Server generates a username / password combination together with a salt. + * 2. Server derives a password verifier (see #ocrypto_srp_verifier). + * 3. The username, salt and verifier are stored and required to open sessions. + * The original password is no longer needed. + * + * *Session opening* + * 1. Client sends a username and the public key of an ephemeral key pair to the + * server. + * 2. Server sends the salt and the public key of another ephemeral key pair to + * the client (see #ocrypto_srp_public_key). + * 3. Client and Server both compute the session key from this information (see + * #ocrypto_srp_scrambling_parameter, #ocrypto_srp_premaster_secret, + * #ocrypto_srp_session_key). + * 4. Client sends proof of the session key to the server. + * 5. Server validates proof (see #ocrypto_srp_proof_m1), then sends proof of the + * session key to the client (see #ocrypto_srp_proof_m2). + * 6. Client validates proof. Both parties know that they share the same private + * session key. + */ + +#ifndef OCRYPTO_SRP_H +#define OCRYPTO_SRP_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Salt length. + */ +#define ocrypto_srp_SALT_BYTES (16) + +/** + * Password verifier length. + */ +#define ocrypto_srp_VERIFIER_BYTES (384) + +/** + * Secret key length. + */ +#define ocrypto_srp_SECRET_KEY_BYTES (32) + +/** + * Public key length. + */ +#define ocrypto_srp_PUBLIC_KEY_BYTES (384) + +/** + * Scrambling parameter length. + */ +#define ocrypto_srp_SCRAMBLING_PARAMETER_BYTES (64) + +/** + * Premaster secret length. + */ +#define ocrypto_srp_PREMASTER_SECRET_BYTES (384) + +/** + * Session key length. + */ +#define ocrypto_srp_SESSION_KEY_BYTES (64) + +/** + * Proof length. + */ +#define ocrypto_srp_PROOF_BYTES (64) + + +/**@name SRP-6 Password verifier generation + * + * A password verifier is generated from a user name and a password. The + * password @p pass may be discarded, as only the verifier is used during later + * computations. + */ +/**@{*/ +/** + * SRP-6 Password Verifier. + * + * The verifier is generated for a given user name @p user, a password @p pass + * and salt @p salt. + * + * @param[out] v Generated password verifier, must be 32-bit aligned. + * @param salt Salt. + * @param user User name. + * @param user_len Length of @p user. + * @param pass Password. + * @param pass_len Length of @p pass. + */ +void ocrypto_srp_verifier( + uint8_t v[ocrypto_srp_VERIFIER_BYTES], + const uint8_t salt[ocrypto_srp_SALT_BYTES], + const uint8_t *user, size_t user_len, + const uint8_t *pass, size_t pass_len); +/**@}*/ + +/**@name SRP-6 Public key generation + * + * An ephemeral keypair can be generated based on the password verifier to be + * used when opening a new session. + */ +/**@{*/ +/** + * SRP-6 Public Key. + * + * The public key for a given private key @p priv_b is generated using the + * password verifier @p v and put into @p pub_b. + * + * @param[out] pub_b Generated public key, must be 32-bit aligned. + * @param priv_b Private key. + * @param v Password verifier. + */ +void ocrypto_srp_public_key( + uint8_t pub_b[ocrypto_srp_PUBLIC_KEY_BYTES], + const uint8_t priv_b[ocrypto_srp_SECRET_KEY_BYTES], + const uint8_t v[ocrypto_srp_VERIFIER_BYTES]); +/**@}*/ + +/**@name SRP-6 Session key generation + * + * A premaster secret can be derived from both the client's and server's public + * keys, the server's private key and the password verifier. A shared session + * key can be generated from this premaster secret. + */ +/**@{*/ +/** + * SRP-6 Scrambling Parameter. + * + * The scrambling parameter is computed from both the client's public key + * @p pub_a and the server's public key @p pub_b. The scrambling parameter + * is required to compute the premaster secret. + * + * @param[out] u Generated scrambling parameter. + * @param pub_a Client public key. + * @param pub_b Server public key. + */ +void ocrypto_srp_scrambling_parameter( + uint8_t u[ocrypto_srp_SCRAMBLING_PARAMETER_BYTES], + const uint8_t pub_a[ocrypto_srp_PUBLIC_KEY_BYTES], + const uint8_t pub_b[ocrypto_srp_PUBLIC_KEY_BYTES]); + +/** + * SRP-6 Premaster Secret. + * + * The premaster secret between the client and the server is computed using the + * client public key @p pub_a, the server private key @p priv_b, the scrambling + * parameter @p u and the password verifier @p v. If the client public key + * @p pub_a is valid, the premaster secret is then put into @p s. The premaster + * secret can be used to generate encryption keys. + * + * @param[out] s Generated premaster secret, must be 32-bit aligned. + * @param pub_a Client public key. + * @param priv_b Server private key. + * @param u Scrambling parameter; generated with @c srp_scrambling_parameter. + * @param v Password verifier. + * + * @retval 0 If @p pub_a is a valid public key. + * @retval 1 Otherwise. + */ +int ocrypto_srp_premaster_secret( + uint8_t s[ocrypto_srp_PREMASTER_SECRET_BYTES], + const uint8_t pub_a[ocrypto_srp_PUBLIC_KEY_BYTES], + const uint8_t priv_b[ocrypto_srp_SECRET_KEY_BYTES], + const uint8_t u[ocrypto_srp_SCRAMBLING_PARAMETER_BYTES], + const uint8_t v[ocrypto_srp_VERIFIER_BYTES]); + +/** + * SRP-6 SRP Session Key. + * + * Generates the shared SRP session key from the premaster secret @p s and puts + * it into @p k. + * + * @param[out] k Generated SRP session key. + * @param s Premaster secret. + */ +void ocrypto_srp_session_key( + uint8_t k[ocrypto_srp_SESSION_KEY_BYTES], + const uint8_t s[ocrypto_srp_PREMASTER_SECRET_BYTES]); +/**@}*/ + +/**@name SRP-6 Proof exchange + * + * Proofs are exchanged from client to server and vice versa to ensure that both + * parties computed the same shared session key. The proofs only match if the + * correct password is used by the client. + */ +/**@{*/ +/** + * SRP-6 Proof M1 (client to server). + * + * A proof is generated by the client and sent to the server to assert that the + * client is in possession of the shared session key @p k. The server also + * generates the proof. Only if the proofs match, the process can continue. + * The proof is based on the salt @p salt, the client public key @p pub_a, + * the server public key @p pub_b and the shared session key @p k. + * + * @param[out] m1 Generated proof. + * @param user User name. + * @param user_len Length of @p user. + * @param salt Salt. + * @param pub_a Client public key. + * @param pub_b Server public key. + * @param k Session key. + */ +void ocrypto_srp_proof_m1( + uint8_t m1[ocrypto_srp_PROOF_BYTES], + const uint8_t *user, size_t user_len, + const uint8_t salt[ocrypto_srp_SALT_BYTES], + const uint8_t pub_a[ocrypto_srp_PUBLIC_KEY_BYTES], + const uint8_t pub_b[ocrypto_srp_PUBLIC_KEY_BYTES], + const uint8_t k[ocrypto_srp_SESSION_KEY_BYTES]); + +/** + * SRP-6 Proof M2 (server to client). + * + * A second proof is generated by the server and sent back to the client to + * assert that the server is in possession of the shared session key @p k. The + * client also generates the proof. If the proofs match, both parties can assume + * that they share the same session key @p k. The second proof is based on the + * client public key @p pub_a, the first proof @p m1 and the session key @p k. + * + * @param[out] m2 Generated proof. + * @param pub_a Client public key. + * @param m1 First proof. Generated with @c srp_proof_m1. + * @param k Session key. + */ +void ocrypto_srp_proof_m2( + uint8_t m2[ocrypto_srp_PROOF_BYTES], + const uint8_t pub_a[ocrypto_srp_PUBLIC_KEY_BYTES], + const uint8_t m1[ocrypto_srp_PROOF_BYTES], + const uint8_t k[ocrypto_srp_SESSION_KEY_BYTES]); +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_SRP_H */ + +/** @} */ + diff --git a/external/nrf_oberon/include/ocrypto_srtp.h b/external/nrf_oberon/include/ocrypto_srtp.h new file mode 100644 index 0000000..b78ce7b --- /dev/null +++ b/external/nrf_oberon/include/ocrypto_srtp.h @@ -0,0 +1,210 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/**@file + * @defgroup nrf_oberon_srpt SRPT - Secure Real-Time Transport Protocol APIs + * @ingroup nrf_oberon + * @{ + * @brief Type declarations and APIs for SRTP - Secure Real-time Transport Protocol. + * + * SRTP is an extension of the RTP protocol with an enhanced security mechanism. + */ + +#ifndef OCRYPTO_SRTP_H +#define OCRYPTO_SRTP_H + +#include +#include + +#include "ocrypto_aes_key.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * SRTP Authentication Key Size. + */ +#define ocrypto_srtp_AuthKeySize (20) + +/** + * SRTP Salt Size. + */ +#define ocrypto_srtp_SaltSize (14) + +/** + * SRTP Maximum Key Size. + */ +#define ocrypto_srtp_MaxKeySize (ocrypto_aes256_KEY_BYTES) + +/** + * SRTP Context. + */ +typedef struct { + /** + * Key size [bytes]. + */ + uint32_t keySize; + + /** + * Tag size [bytes]. + */ + uint32_t tagSize; + + /** + * Session encryption key (max 256 bits). + */ + uint8_t encrKey[ocrypto_srtp_MaxKeySize]; + + /** + * Session authentication key + * 160 bits. + */ + uint8_t authKey[ocrypto_srtp_AuthKeySize]; + + /** + * Session salt + * 112 bits. + */ + uint8_t saltKey[ocrypto_srtp_SaltSize]; +} ocrypto_srtp_context; + +/** + * Setup SRTP contexts. + * + * @param[out] srtpContext SRTP context to be setup. + * @param[out] srtcpContext SRTCP context to be setup. + * @param key Master key. + * @param keySize Size of the master key (16, 24, or 32 bytes) + * @param salt Master salt. + * @param tagSize Size of the authentication tag. + * @param ssrc Synchronization source. + */ +void ocrypto_srtp_setupContext( + ocrypto_srtp_context *srtpContext, + ocrypto_srtp_context *srtcpContext, + const uint8_t *key, + uint32_t keySize, + const uint8_t *salt, + uint32_t tagSize, + uint32_t ssrc); + +/** + * Encrypt SRTP packet. + * + * The final packet consists of @p numHeaderBytes encrypted in place, followed + * by @p numDataBytes copied from @p dataBytes during encryption. + * + * @param srtpContext SRTP context. + * @param[in,out] packet Encrypted packet. + * @param dataBytes Data bytes to be encrypted. + * @param numHeaderBytes Number of header bytes. + * @param numDataBytes Number of data bytes. + * @param index Packet index. + */ +void ocrypto_srtp_encrypt( + const ocrypto_srtp_context *srtpContext, + uint8_t *packet, + const uint8_t *dataBytes, + size_t numHeaderBytes, + size_t numDataBytes, + uint32_t index); + +/** + * Decrypt SRTP packet. + * + * @param srtpContext SRTP context. + * @param[out] data Decrypted data. + * @param packetBytes Packet bytes. + * @param numPacketBytes Number of packet bytes. + * @param index Packet index. + */ +void ocrypto_srtp_decrypt( + const ocrypto_srtp_context *srtpContext, + uint8_t *data, + const uint8_t *packetBytes, + size_t numPacketBytes, + uint32_t index); + +/** + * Generate SRTP authentication tag from bytes and index. + * + * @param context SRTP context. + * @param[out] tag Authentication tag generated. + * @param bytes Byte buffer. + * @param numBytes Number of bytes in buffer. + * @param index Index. + */ +void ocrypto_srtp_authenticate( + const ocrypto_srtp_context *context, + uint8_t *tag, + const uint8_t *bytes, + size_t numBytes, + uint32_t index); + +/** + * Check SRTP authentication tag against bytes and index. + * + * @param context SRTP context. + * @param tag Tag. + * @param bytes Byte buffer. + * @param numBytes Number of bytes in buffer. + * @param index Index. + * + * @retval 1 If the tag is valid. + * @retval 0 Otherwise. + */ +int ocrypto_srtp_verifyAuthentication( + const ocrypto_srtp_context *context, + const uint8_t *tag, + const uint8_t *bytes, + size_t numBytes, + uint32_t index); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OCRYPTO_SRTP_H */ + +/** @} */ + diff --git a/external/nrf_oberon/lib/cortex-m0/soft-float/liboberon_3.0.8.a b/external/nrf_oberon/lib/cortex-m0/soft-float/liboberon_3.0.8.a new file mode 100644 index 0000000..f970b5e Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m0/soft-float/liboberon_3.0.8.a differ diff --git a/external/nrf_oberon/lib/cortex-m0/soft-float/liboberon_mbedtls_3.0.8.a b/external/nrf_oberon/lib/cortex-m0/soft-float/liboberon_mbedtls_3.0.8.a new file mode 100644 index 0000000..2b644d8 Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m0/soft-float/liboberon_mbedtls_3.0.8.a differ diff --git a/external/nrf_oberon/lib/cortex-m0/soft-float/short-wchar/liboberon_3.0.8.a b/external/nrf_oberon/lib/cortex-m0/soft-float/short-wchar/liboberon_3.0.8.a new file mode 100644 index 0000000..4dece11 Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m0/soft-float/short-wchar/liboberon_3.0.8.a differ diff --git a/external/nrf_oberon/lib/cortex-m0/soft-float/short-wchar/liboberon_mbedtls_3.0.8.a b/external/nrf_oberon/lib/cortex-m0/soft-float/short-wchar/liboberon_mbedtls_3.0.8.a new file mode 100644 index 0000000..2e26928 Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m0/soft-float/short-wchar/liboberon_mbedtls_3.0.8.a differ diff --git a/external/nrf_oberon/lib/cortex-m0/soft-float/short-wchar/oberon_3.0.8.lib b/external/nrf_oberon/lib/cortex-m0/soft-float/short-wchar/oberon_3.0.8.lib new file mode 100644 index 0000000..4dece11 Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m0/soft-float/short-wchar/oberon_3.0.8.lib differ diff --git a/external/nrf_oberon/lib/cortex-m0/soft-float/short-wchar/oberon_mbedtls_3.0.8.lib b/external/nrf_oberon/lib/cortex-m0/soft-float/short-wchar/oberon_mbedtls_3.0.8.lib new file mode 100644 index 0000000..2e26928 Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m0/soft-float/short-wchar/oberon_mbedtls_3.0.8.lib differ diff --git a/external/nrf_oberon/lib/cortex-m4/hard-float/liboberon_3.0.8.a b/external/nrf_oberon/lib/cortex-m4/hard-float/liboberon_3.0.8.a new file mode 100644 index 0000000..7d962c7 Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m4/hard-float/liboberon_3.0.8.a differ diff --git a/external/nrf_oberon/lib/cortex-m4/hard-float/liboberon_mbedtls_3.0.8.a b/external/nrf_oberon/lib/cortex-m4/hard-float/liboberon_mbedtls_3.0.8.a new file mode 100644 index 0000000..137f94a Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m4/hard-float/liboberon_mbedtls_3.0.8.a differ diff --git a/external/nrf_oberon/lib/cortex-m4/hard-float/short-wchar/liboberon_3.0.8.a b/external/nrf_oberon/lib/cortex-m4/hard-float/short-wchar/liboberon_3.0.8.a new file mode 100644 index 0000000..98b1f67 Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m4/hard-float/short-wchar/liboberon_3.0.8.a differ diff --git a/external/nrf_oberon/lib/cortex-m4/hard-float/short-wchar/liboberon_mbedtls_3.0.8.a b/external/nrf_oberon/lib/cortex-m4/hard-float/short-wchar/liboberon_mbedtls_3.0.8.a new file mode 100644 index 0000000..04c9168 Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m4/hard-float/short-wchar/liboberon_mbedtls_3.0.8.a differ diff --git a/external/nrf_oberon/lib/cortex-m4/hard-float/short-wchar/oberon_3.0.8.lib b/external/nrf_oberon/lib/cortex-m4/hard-float/short-wchar/oberon_3.0.8.lib new file mode 100644 index 0000000..98b1f67 Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m4/hard-float/short-wchar/oberon_3.0.8.lib differ diff --git a/external/nrf_oberon/lib/cortex-m4/hard-float/short-wchar/oberon_mbedtls_3.0.8.lib b/external/nrf_oberon/lib/cortex-m4/hard-float/short-wchar/oberon_mbedtls_3.0.8.lib new file mode 100644 index 0000000..04c9168 Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m4/hard-float/short-wchar/oberon_mbedtls_3.0.8.lib differ diff --git a/external/nrf_oberon/lib/cortex-m4/soft-float/liboberon_3.0.8.a b/external/nrf_oberon/lib/cortex-m4/soft-float/liboberon_3.0.8.a new file mode 100644 index 0000000..111fe03 Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m4/soft-float/liboberon_3.0.8.a differ diff --git a/external/nrf_oberon/lib/cortex-m4/soft-float/liboberon_mbedtls_3.0.8.a b/external/nrf_oberon/lib/cortex-m4/soft-float/liboberon_mbedtls_3.0.8.a new file mode 100644 index 0000000..de8facc Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m4/soft-float/liboberon_mbedtls_3.0.8.a differ diff --git a/external/nrf_oberon/lib/cortex-m4/soft-float/short-wchar/liboberon_3.0.8.a b/external/nrf_oberon/lib/cortex-m4/soft-float/short-wchar/liboberon_3.0.8.a new file mode 100644 index 0000000..36bb1da Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m4/soft-float/short-wchar/liboberon_3.0.8.a differ diff --git a/external/nrf_oberon/lib/cortex-m4/soft-float/short-wchar/liboberon_mbedtls_3.0.8.a b/external/nrf_oberon/lib/cortex-m4/soft-float/short-wchar/liboberon_mbedtls_3.0.8.a new file mode 100644 index 0000000..0e22075 Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m4/soft-float/short-wchar/liboberon_mbedtls_3.0.8.a differ diff --git a/external/nrf_oberon/lib/cortex-m4/soft-float/short-wchar/oberon_3.0.8.lib b/external/nrf_oberon/lib/cortex-m4/soft-float/short-wchar/oberon_3.0.8.lib new file mode 100644 index 0000000..36bb1da Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m4/soft-float/short-wchar/oberon_3.0.8.lib differ diff --git a/external/nrf_oberon/lib/cortex-m4/soft-float/short-wchar/oberon_mbedtls_3.0.8.lib b/external/nrf_oberon/lib/cortex-m4/soft-float/short-wchar/oberon_mbedtls_3.0.8.lib new file mode 100644 index 0000000..0e22075 Binary files /dev/null and b/external/nrf_oberon/lib/cortex-m4/soft-float/short-wchar/oberon_mbedtls_3.0.8.lib differ diff --git a/external/nrf_oberon/lib/license.txt b/external/nrf_oberon/lib/license.txt new file mode 100644 index 0000000..eeb33eb --- /dev/null +++ b/external/nrf_oberon/lib/license.txt @@ -0,0 +1,37 @@ +Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form, except as embedded into a Nordic + Semiconductor ASA integrated circuit in a product or a software update for + such product, must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +3. Neither the name of Nordic Semiconductor ASA nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +4. This software, with or without modification, must only be used with a + Nordic Semiconductor ASA integrated circuit. + +5. Any software provided in binary form under this license must not be reverse + engineered, decompiled, modified and/or disassembled. + +THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/external/nrf_oberon/license.txt b/external/nrf_oberon/license.txt new file mode 100644 index 0000000..eeb33eb --- /dev/null +++ b/external/nrf_oberon/license.txt @@ -0,0 +1,37 @@ +Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form, except as embedded into a Nordic + Semiconductor ASA integrated circuit in a product or a software update for + such product, must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +3. Neither the name of Nordic Semiconductor ASA nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +4. This software, with or without modification, must only be used with a + Nordic Semiconductor ASA integrated circuit. + +5. Any software provided in binary form under this license must not be reverse + engineered, decompiled, modified and/or disassembled. + +THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/external/nrf_tls/mbedtls/dtls/config/nrf_dtls_config.h b/external/nrf_tls/mbedtls/dtls/config/nrf_dtls_config.h new file mode 100644 index 0000000..a28a2e3 --- /dev/null +++ b/external/nrf_tls/mbedtls/dtls/config/nrf_dtls_config.h @@ -0,0 +1,3420 @@ +/** + * \file nrf_dtls_config.h + * + * \brief Configuration options (set of defines) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2015 Nordic Semiconductor ASA, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/aria.c + * library/timing.c + * include/mbedtls/bn_mul.h + * + * Required by: + * MBEDTLS_AESNI_C + * MBEDTLS_PADLOCK_C + * + * Comment to disable the use of assembly code. + */ +//#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \def MBEDTLS_NO_64BIT_MULTIPLICATION + * + * The platform lacks support for 32x32 -> 64-bit multiplication. + * + * Used in: + * library/poly1305.c + * + * Some parts of the library may use multiplication of two unsigned 32-bit + * operands with a 64-bit result in order to speed up computations. On some + * platforms, this is not available in hardware and has to be implemented in + * software, usually in a library provided by the toolchain. + * + * Sometimes it is not desirable to have to link to that library. This option + * removes the dependency of that library on platforms that lack a hardware + * 64-bit multiplier by embedding a software implementation in Mbed TLS. + * + * Note that depending on the compiler, this may decrease performance compared + * to using the library function provided by the toolchain. + */ +//#define MBEDTLS_NO_64BIT_MULTIPLICATION + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, + * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and + * MBEDTLS_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions + */ +//#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h, time(), and an implementation for + * mbedtls_platform_gmtime_r() (see below). + * The time needs to be correct (not necessarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + * + * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that + * behaves similarly to the gmtime_r() function from the C standard. Refer to + * the documentation for mbedtls_platform_gmtime_r() for more information. + * + * \note It is possible to configure an implementation for + * mbedtls_platform_gmtime_r() at compile-time by using the macro + * MBEDTLS_PLATFORM_GMTIME_R_ALT. + */ +//#define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +#define MBEDTLS_PLATFORM_MEMORY + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_EXIT_ALT + * + * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT + +/** + * \def MBEDTLS_DEPRECATED_WARNING + * + * Mark deprecated functions so that they generate a warning if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_DEPRECATED_REMOVED + * + * Remove deprecated functions so that they generate an error if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * Uncomment to get errors on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_REMOVED + +/** + * \def MBEDTLS_CHECK_PARAMS + * + * This configuration option controls whether the library validates more of + * the parameters passed to it. + * + * When this flag is not defined, the library only attempts to validate an + * input parameter if: (1) they may come from the outside world (such as the + * network, the filesystem, etc.) or (2) not validating them could result in + * internal memory errors such as overflowing a buffer controlled by the + * library. On the other hand, it doesn't attempt to validate parameters whose + * values are fully controlled by the application (such as pointers). + * + * When this flag is defined, the library additionally attempts to validate + * parameters that are fully controlled by the application, and should always + * be valid if the application code is fully correct and trusted. + * + * For example, when a function accepts as input a pointer to a buffer that may + * contain untrusted data, and its documentation mentions that this pointer + * must not be NULL: + * - The pointer is checked to be non-NULL only if this option is enabled. + * - The content of the buffer is always validated. + * + * When this flag is defined, if a library function receives a parameter that + * is invalid: + * 1. The function will invoke the macro MBEDTLS_PARAM_FAILED(). + * 2. If MBEDTLS_PARAM_FAILED() did not terminate the program, the function + * will immediately return. If the function returns an Mbed TLS error code, + * the error code in this case is MBEDTLS_ERR_xxx_BAD_INPUT_DATA. + * + * When defining this flag, you also need to arrange a definition for + * MBEDTLS_PARAM_FAILED(). You can do this by any of the following methods: + * - By default, the library defines MBEDTLS_PARAM_FAILED() to call a + * function mbedtls_param_failed(), but the library does not define this + * function. If you do not make any other arrangements, you must provide + * the function mbedtls_param_failed() in your application. + * See `platform_util.h` for its prototype. + * - If you enable the macro #MBEDTLS_CHECK_PARAMS_ASSERT, then the + * library defines #MBEDTLS_PARAM_FAILED(\c cond) to be `assert(cond)`. + * You can still supply an alternative definition of + * MBEDTLS_PARAM_FAILED(), which may call `assert`. + * - If you define a macro MBEDTLS_PARAM_FAILED() before including `config.h` + * or you uncomment the definition of MBEDTLS_PARAM_FAILED() in `config.h`, + * the library will call the macro that you defined and will not supply + * its own version. Note that if MBEDTLS_PARAM_FAILED() calls `assert`, + * you need to enable #MBEDTLS_CHECK_PARAMS_ASSERT so that library source + * files include ``. + * + * Uncomment to enable validation of application-controlled parameters. + */ +//#define MBEDTLS_CHECK_PARAMS + +/** + * \def MBEDTLS_CHECK_PARAMS_ASSERT + * + * Allow MBEDTLS_PARAM_FAILED() to call `assert`, and make it default to + * `assert`. This macro is only used if #MBEDTLS_CHECK_PARAMS is defined. + * + * If this macro is not defined, then MBEDTLS_PARAM_FAILED() defaults to + * calling a function mbedtls_param_failed(). See the documentation of + * #MBEDTLS_CHECK_PARAMS for details. + * + * Uncomment to allow MBEDTLS_PARAM_FAILED() to call `assert`. + */ +//#define MBEDTLS_CHECK_PARAMS_ASSERT + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def MBEDTLS_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS_AES_ALT + * + * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternate core implementation of a symmetric crypto, an arithmetic or hash + * module (e.g. platform specific assembly optimized implementations). Keep + * in mind that the function prototypes should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base + * function declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + * + * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their + * use constitutes a security risk. If possible, we recommend + * avoiding dependencies on them, and considering stronger message + * digests and ciphers instead. + * + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_ARIA_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CHACHA20_ALT +//#define MBEDTLS_CHACHAPOLY_ALT +//#define MBEDTLS_CMAC_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_DHM_ALT +//#define MBEDTLS_ECJPAKE_ALT +//#define MBEDTLS_GCM_ALT +//#define MBEDTLS_NIST_KW_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_RSA_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT +//#define MBEDTLS_XTEA_ALT + +/* + * When replacing the elliptic curve module, please consider, that it is + * implemented with two .c files: + * - ecp.c + * - ecp_curves.c + * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT + * macros as described above. The only difference is that you have to make sure + * that you provide functionality for both .c files. + */ +//#define MBEDTLS_ECP_ALT + +/** + * \def MBEDTLS_MD2_PROCESS_ALT + * + * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you + * alternate core implementation of symmetric crypto or hash function. Keep in + * mind that function prototypes should remain the same. + * + * This replaces only one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will + * no longer provide the mbedtls_sha1_process() function, but it will still provide + * the other function (using your mbedtls_sha1_process() function) and the definition + * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible + * with this definition. + * + * \note Because of a signature change, the core AES encryption and decryption routines are + * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, + * respectively. When setting up alternative implementations, these functions should + * be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt + * must stay untouched. + * + * \note If you use the AES_xxx_ALT macros, then is is recommended to also set + * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + * + * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use + * constitutes a security risk. If possible, we recommend avoiding + * dependencies on them, and considering stronger message digests + * and ciphers instead. + * + * \warning If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are + * enabled, then the deterministic ECDH signature functions pass the + * the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore + * alternative implementations should use the RNG only for generating + * the ephemeral key and nothing else. If this is not possible, then + * MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative + * implementation should be provided for mbedtls_ecdsa_sign_det_ext() + * (and for mbedtls_ecdsa_sign_det() too if backward compatibility is + * desirable). + * + */ +//#define MBEDTLS_MD2_PROCESS_ALT +//#define MBEDTLS_MD4_PROCESS_ALT +//#define MBEDTLS_MD5_PROCESS_ALT +//#define MBEDTLS_RIPEMD160_PROCESS_ALT +//#define MBEDTLS_SHA1_PROCESS_ALT +//#define MBEDTLS_SHA256_PROCESS_ALT +//#define MBEDTLS_SHA512_PROCESS_ALT +//#define MBEDTLS_DES_SETKEY_ALT +//#define MBEDTLS_DES_CRYPT_ECB_ALT +//#define MBEDTLS_DES3_CRYPT_ECB_ALT +//#define MBEDTLS_AES_SETKEY_ENC_ALT +//#define MBEDTLS_AES_SETKEY_DEC_ALT +//#define MBEDTLS_AES_ENCRYPT_ALT +//#define MBEDTLS_AES_DECRYPT_ALT +//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT +//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT +//#define MBEDTLS_ECDSA_VERIFY_ALT +//#define MBEDTLS_ECDSA_SIGN_ALT +//#define MBEDTLS_ECDSA_GENKEY_ALT + +/** + * \def MBEDTLS_ECP_INTERNAL_ALT + * + * Expose a part of the internal interface of the Elliptic Curve Point module. + * + * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternative core implementation of elliptic curve arithmetic. Keep in mind + * that function prototypes should remain the same. + * + * This partially replaces one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation + * is still present and it is used for group structures not supported by the + * alternative. + * + * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT + * and implementing the following functions: + * unsigned char mbedtls_internal_ecp_grp_capable( + * const mbedtls_ecp_group *grp ) + * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) + * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ) + * The mbedtls_internal_ecp_grp_capable function should return 1 if the + * replacement functions implement arithmetic for the given group and 0 + * otherwise. + * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are + * called before and after each point operation and provide an opportunity to + * implement optimized set up and tear down instructions. + * + * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and + * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac + * function, but will use your mbedtls_internal_ecp_double_jac if the group is + * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when + * receives it as an argument). If the group is not supported then the original + * implementation is used. The other functions and the definition of + * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your + * implementation of mbedtls_internal_ecp_double_jac and + * mbedtls_internal_ecp_grp_capable must be compatible with this definition. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +/* Required for all the functions in this section */ +//#define MBEDTLS_ECP_INTERNAL_ALT +/* Support for Weierstrass curves with Jacobi representation */ +//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT +//#define MBEDTLS_ECP_ADD_MIXED_ALT +//#define MBEDTLS_ECP_DOUBLE_JAC_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT +/* Support for curves with Montgomery arithmetic */ +//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT +//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT +//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT + +/** + * \def MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN + * + * Enable testing of the constant-flow nature of some sensitive functions with + * clang's MemorySanitizer. This causes some existing tests to also test + * this non-functional property of the code under test. + * + * This setting requires compiling with clang -fsanitize=memory. The test + * suites can then be run normally. + * + * \warning This macro is only used for extended testing; it is not considered + * part of the library's API, so it may change or disappear at any time. + * + * Uncomment to enable testing of the constant-flow nature of selected code. + */ +//#define MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN + +/** + * \def MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND + * + * Enable testing of the constant-flow nature of some sensitive functions with + * valgrind's memcheck tool. This causes some existing tests to also test + * this non-functional property of the code under test. + * + * This setting requires valgrind headers for building, and is only useful for + * testing if the tests suites are run with valgrind's memcheck. This can be + * done for an individual test suite with 'valgrind ./test_suite_xxx', or when + * using CMake, this can be done for all test suites with 'make memcheck'. + * + * \warning This macro is only used for extended testing; it is not considered + * part of the library's API, so it may change or disappear at any time. + * + * Uncomment to enable testing of the constant-flow nature of selected code. + */ +//#define MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND + +/** + * \def MBEDTLS_TEST_NULL_ENTROPY + * + * Enables testing and use of mbed TLS without any configured entropy sources. + * This permits use of the library on platforms before an entropy source has + * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the + * MBEDTLS_ENTROPY_NV_SEED switches). + * + * WARNING! This switch MUST be disabled in production builds, and is suitable + * only for development. + * Enabling the switch negates any security provided by the library. + * + * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + */ +//#define MBEDTLS_TEST_NULL_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * + * Uncomment to use your own hardware entropy collector. + */ +//#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Use precomputed AES tables stored in ROM. + * + * Uncomment this macro to use precomputed AES tables stored in ROM. + * Comment this macro to generate AES tables in RAM at runtime. + * + * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb + * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the + * initialization time before the first AES operation can be performed. + * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c + * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded + * performance if ROM access is slower than RAM access. + * + * This option is independent of \c MBEDTLS_AES_FEWER_TABLES. + * + */ +#define MBEDTLS_AES_ROM_TABLES + +/** + * \def MBEDTLS_AES_FEWER_TABLES + * + * Use less ROM/RAM for AES tables. + * + * Uncommenting this macro omits 75% of the AES tables from + * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES) + * by computing their values on the fly during operations + * (the tables are entry-wise rotations of one another). + * + * Tradeoff: Uncommenting this reduces the RAM / ROM footprint + * by ~6kb but at the cost of more arithmetic operations during + * runtime. Specifically, one has to compare 4 accesses within + * different tables to 4 accesses with additional arithmetic + * operations within the same table. The performance gain/loss + * depends on the system and memory details. + * + * This option is independent of \c MBEDTLS_AES_ROM_TABLES. + * + */ +//#define MBEDTLS_AES_FEWER_TABLES + +/** + * \def MBEDTLS_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define MBEDTLS_CAMELLIA_SMALL_MEMORY + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_CIPHER_MODE_OFB + * + * Enable Output Feedback mode (OFB) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_OFB + +/** + * \def MBEDTLS_CIPHER_MODE_XTS + * + * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. + */ +//#define MBEDTLS_CIPHER_MODE_XTS + +/** + * \def MBEDTLS_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define MBEDTLS_CIPHER_NULL_CIPHER + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + * + * Uncomment this macro to use a 128-bit key in the CTR_DRBG module. + * By default, CTR_DRBG uses a 256-bit key. + */ +#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + +/** + * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_3DES_CIPHERSUITES + * + * Remove 3DES ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on 3DES from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible + * to enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including + * them explicitly. + * + * A man-in-the-browser attacker can recover authentication tokens sent through + * a TLS connection using a 3DES based cipher suite (see "On the Practical + * (In-)Security of 64-bit Block Ciphers" by Karthikeyan Bhargavan and Gatan + * Leurent, see https://sweet32.info/SWEET32_CCS16.pdf). If this attack falls + * in your threat model or you are unsure, then you should keep this option + * enabled to remove 3DES based cipher suites. + * + * Comment this macro to keep 3DES in the default ciphersuite list. + */ +#define MBEDTLS_REMOVE_3DES_CIPHERSUITES + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +//#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +//#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +//#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +//#define MBEDTLS_ECP_DP_BP256R1_ENABLED +//#define MBEDTLS_ECP_DP_BP384R1_ENABLED +//#define MBEDTLS_ECP_DP_BP512R1_ENABLED +//#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +//#define MBEDTLS_ECP_DP_CURVE448_ENABLED + +/** + * \def MBEDTLS_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#define MBEDTLS_ECP_NIST_OPTIM + +/** + * \def MBEDTLS_ECP_NO_INTERNAL_RNG + * + * When this option is disabled, mbedtls_ecp_mul() will make use of an + * internal RNG when called with a NULL \c f_rng argument, in order to protect + * against some side-channel attacks. + * + * This protection introduces a dependency of the ECP module on one of the + * DRBG or SHA modules (HMAC-DRBG, CTR-DRBG, SHA-512 or SHA-256.) For very + * constrained applications that don't require this protection (for example, + * because you're only doing signature verification, so not manipulating any + * secret, or because local/physical side-channel attacks are outside your + * threat model), it might be desirable to get rid of that dependency. + * + * \warning Enabling this option makes some uses of ECP vulnerable to some + * side-channel attacks. Only enable it if you know that's not a problem for + * your use case. + * + * Uncomment this macro to disable some counter-measures in ECP. + */ +//#define MBEDTLS_ECP_NO_INTERNAL_RNG + +/** + * \def MBEDTLS_ECP_RESTARTABLE + * + * Enable "non-blocking" ECC operations that can return early and be resumed. + * + * This allows various functions to pause by returning + * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in + * order to further progress and eventually complete their operation. This is + * controlled through mbedtls_ecp_set_max_ops() which limits the maximum + * number of ECC operations a function may perform before pausing; see + * mbedtls_ecp_set_max_ops() for more information. + * + * This is useful in non-threaded environments if you want to avoid blocking + * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. + * + * Uncomment this macro to enable restartable ECC computations. + * + * \note This option only works with the default software implementation of + * elliptic curve functionality. It is incompatible with + * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT and MBEDTLS_ECDSA_XXX_ALT. + */ +//#define MBEDTLS_ECP_RESTARTABLE + +/** + * \def MBEDTLS_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: MBEDTLS_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +//#define MBEDTLS_ECDSA_DETERMINISTIC + +/** + * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + */ +//#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + * + * Enable the ECJPAKE based ciphersuite modes in SSL / TLS. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Requires: MBEDTLS_ECJPAKE_C + * MBEDTLS_SHA256_C + * MBEDTLS_ECP_DP_SECP256R1_ENABLED + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + +/** + * \def MBEDTLS_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +//#define MBEDTLS_PK_PARSE_EC_EXTENDED + +/** + * \def MBEDTLS_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when MBEDTLS_ERROR_C is disabled + * (no effect when MBEDTLS_ERROR_C is enabled). + * + * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're + * not using mbedtls_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * mbedtls_strerror() + */ +#define MBEDTLS_ERROR_STRERROR_DUMMY + +/** + * \def MBEDTLS_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: MBEDTLS_BIGNUM_C + */ +#define MBEDTLS_GENPRIME + +/** + * \def MBEDTLS_FS_IO + * + * Enable functions that use the filesystem. + */ +//#define MBEDTLS_FS_IO + +/** + * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * mbedtls_timing_hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def MBEDTLS_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +#define MBEDTLS_NO_PLATFORM_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: MBEDTLS_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both MBEDTLS_SHA256_C and + * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. + */ +#define MBEDTLS_ENTROPY_FORCE_SHA256 + +/** + * \def MBEDTLS_ENTROPY_NV_SEED + * + * Enable the non-volatile (NV) seed file-based entropy source. + * (Also enables the NV seed read/write functions in the platform layer) + * + * This is crucial (if not required) on systems that do not have a + * cryptographic entropy source (in hardware or kernel) available. + * + * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C + * + * \note The read/write functions that are used by the entropy source are + * determined in the platform layer, and can be modified at runtime and/or + * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used. + * + * \note If you use the default implementation functions that read a seedfile + * with regular fopen(), please make sure you make a seedfile with the + * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at + * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from + * and written to or you will get an entropy source error! The default + * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE + * bytes from the file. + * + * \note The entropy collector will write to the seed file before entropy is + * given to an external source, to update it. + */ +//#define MBEDTLS_ENTROPY_NV_SEED + +/** + * \def MBEDTLS_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define MBEDTLS_MEMORY_DEBUG + +/** + * \def MBEDTLS_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define MBEDTLS_MEMORY_BACKTRACE + +/** + * \def MBEDTLS_PK_RSA_ALT_SUPPORT + * + * Support external private RSA keys (eg from a HSM) in the PK layer. + * + * Comment this macro to disable support for external private RSA keys. + */ +//#define MBEDTLS_PK_RSA_ALT_SUPPORT + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +//#define MBEDTLS_PKCS1_V15 + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +//#define MBEDTLS_PKCS1_V21 + +/** + * \def MBEDTLS_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem + * for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define MBEDTLS_RSA_NO_CRT + +/** + * \def MBEDTLS_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +//#define MBEDTLS_SELF_TEST + +/** + * \def MBEDTLS_SHA256_SMALLER + * + * Enable an implementation of SHA-256 that has lower ROM footprint but also + * lower performance. + * + * The default implementation is meant to be a reasonnable compromise between + * performance and size. This version optimizes more aggressively for size at + * the expense of performance. Eg on Cortex-M4 it reduces the size of + * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about + * 30%. + * + * Uncomment to enable the smaller implementation of SHA256. + */ +//#define MBEDTLS_SHA256_SMALLER + +/** + * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define MBEDTLS_SSL_ALL_ALERT_MESSAGES + +/** + * \def MBEDTLS_SSL_ASYNC_PRIVATE + * + * Enable asynchronous external private key operations in SSL. This allows + * you to configure an SSL connection to call an external cryptographic + * module to perform private key operations instead of performing the + * operation inside the library. + * + */ +//#define MBEDTLS_SSL_ASYNC_PRIVATE + +/** + * \def MBEDTLS_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define MBEDTLS_SSL_DEBUG_ALL + +/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +#define MBEDTLS_SSL_ENCRYPT_THEN_MAC + +/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for Extended Master Secret, aka Session Hash + * (draft-ietf-tls-session-hash-02). + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET + +/** + * \def MBEDTLS_SSL_FALLBACK_SCSV + * + * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00). + * + * For servers, it is recommended to always enable this, unless you support + * only one version of TLS, or know for sure that none of your clients + * implements a fallback strategy. + * + * For clients, you only need this if you're using a fallback strategy, which + * is not recommended in the first place, unless you absolutely need it to + * interoperate with buggy (version-intolerant) servers. + * + * Comment this macro to disable support for FALLBACK_SCSV + */ +//#define MBEDTLS_SSL_FALLBACK_SCSV + +/** + * \def MBEDTLS_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define MBEDTLS_SSL_HW_RECORD_ACCEL + +/** + * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING + * + * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. + * + * This is a countermeasure to the BEAST attack, which also minimizes the risk + * of interoperability issues compared to sending 0-length records. + * + * Comment this macro to disable 1/n-1 record splitting. + */ +//#define MBEDTLS_SSL_CBC_RECORD_SPLITTING + +/** + * \def MBEDTLS_SSL_RENEGOTIATION + * + * Enable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Comment this to disable support for renegotiation. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * + */ +#define MBEDTLS_SSL_RENEGOTIATION + +/** + * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to enable support for SSLv2 Client Hello messages. + */ +//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def MBEDTLS_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +//#define MBEDTLS_SSL_PROTO_SSL3 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +//#define MBEDTLS_SSL_PROTO_TLS1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled). + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 / DTLS 1.0 + */ +//#define MBEDTLS_SSL_PROTO_TLS1_1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/** + * \def MBEDTLS_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0, + * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_1 + * or MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +#define MBEDTLS_SSL_PROTO_DTLS + +/** + * \def MBEDTLS_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +//#define MBEDTLS_SSL_ALPN + +/** + * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: MBEDTLS_SSL_TLS_C + * MBEDTLS_SSL_PROTO_DTLS + * + * \warning Disabling this is often a security risk! + * See mbedtls_ssl_conf_dtls_anti_replay() for details. + * + * Comment this to disable anti-replay in DTLS. + */ +#define MBEDTLS_SSL_DTLS_ANTI_REPLAY + +/** + * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Enable support for HelloVerifyRequest on DTLS servers. + * + * This feature is highly recommended to prevent DTLS servers being used as + * amplifiers in DoS attacks against other hosts. It should always be enabled + * unless you know for sure amplification cannot be a problem in the + * environment in which your server operates. + * + * \warning Disabling this can ba a security risk! (see above) + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY + +/** + * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + * + * Enable server-side support for clients that reconnect from the same port. + * + * Some clients unexpectedly close the connection and try to reconnect using the + * same source port. This needs special support from the server to handle the + * new connection securely, as described in section 4.2.8 of RFC 6347. This + * flag enables that support. + * + * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +//#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + +/** + * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT + * + * Enable support for a limit of records with bad MAC. + * + * See mbedtls_ssl_conf_dtls_badmac_limit(). + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + */ +#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT + +/** + * \def MBEDTLS_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * Client-side, provides full support for session tickets (maintenance of a + * session store remains the responsibility of the application, though). + * Server-side, you also need to provide callbacks for writing and parsing + * tickets, including authenticated encryption and key management. Example + * callbacks are provided by MBEDTLS_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +#define MBEDTLS_SSL_SESSION_TICKETS + +/** + * \def MBEDTLS_SSL_EXPORT_KEYS + * + * Enable support for exporting key block and master secret. + * This is required for certain users of TLS, e.g. EAP-TLS. + * + * Comment this macro to disable support for key export + */ +//#define MBEDTLS_SSL_EXPORT_KEYS + +/** + * \def MBEDTLS_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +//#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + * + * Fallback to old (pre-2.7), non-conforming implementation of the truncated + * HMAC extension which also truncates the HMAC key. Note that this option is + * only meant for a transitory upgrade period and is likely to be removed in + * a future version of the library. + * + * \warning The old implementation is non-compliant and has a security weakness + * (2^80 brute force attack on the HMAC key used for a single, + * uninterrupted connection). This should only be enabled temporarily + * when (1) the use of truncated HMAC is essential in order to save + * bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use + * the fixed implementation yet (pre-2.7). + * + * \deprecated This option is deprecated and will likely be removed in a + * future version of Mbed TLS. + * + * Uncomment to fallback to old, non-compliant truncated HMAC implementation. + * + * Requires: MBEDTLS_SSL_TRUNCATED_HMAC + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + +/** + * \def MBEDTLS_TEST_HOOKS + * + * Enable features for invasive testing such as introspection functions and + * hooks for fault injection. This enables additional unit tests. + * + * Merely enabling this feature should not change the behavior of the product. + * It only adds new code, and new branching points where the default behavior + * is the same as when this feature is disabled. + * However, this feature increases the attack surface: there is an added + * risk of vulnerabilities, and more gadgets that can make exploits easier. + * Therefore this feature must never be enabled in production. + * + * Uncomment to enable invasive tests. + */ +//#define MBEDTLS_TEST_HOOKS + +/** + * \def MBEDTLS_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define MBEDTLS_THREADING_ALT + +/** + * \def MBEDTLS_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define MBEDTLS_THREADING_PTHREAD + +/** + * \def MBEDTLS_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via mbedtls_version_check_feature(). + * + * Requires: MBEDTLS_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +#define MBEDTLS_VERSION_FEATURES + +/** + * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * \warning Depending on your PKI use, enabling this can be a security risk! + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def MBEDTLS_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +//#define MBEDTLS_X509_CHECK_KEY_USAGE + +/** + * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +//#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +//#define MBEDTLS_X509_RSASSA_PSS_SUPPORT + +/** + * \def MBEDTLS_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * \warning TLS-level compression MAY REDUCE SECURITY! See for example the + * CRIME attack. Before enabling this option, you should examine with care if + * CRIME or similar exploits may be applicable to your use case. + * + * \note Currently compression can't be used with DTLS. + * + * \deprecated This feature is deprecated and will be removed + * in the next major revision of the library. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define MBEDTLS_ZLIB_SUPPORT +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +//#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/cipher.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define MBEDTLS_AES_C + +/** + * \def MBEDTLS_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. If possible, we recommend avoidng dependencies on + * it, and considering stronger ciphers instead. + * + */ +//#define MBEDTLS_ARC4_C + +/** + * \def MBEDTLS_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +//#define MBEDTLS_ASN1_PARSE_C + +/** + * \def MBEDTLS_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +//#define MBEDTLS_ASN1_WRITE_C + +/** + * \def MBEDTLS_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +//#define MBEDTLS_BASE64_C + +/** + * \def MBEDTLS_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/rsa_internal.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define MBEDTLS_BIGNUM_C + +/** + * \def MBEDTLS_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +//#define MBEDTLS_BLOWFISH_C + +/** + * \def MBEDTLS_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +//#define MBEDTLS_CAMELLIA_C + +/** + * \def MBEDTLS_ARIA_C + * + * Enable the ARIA block cipher. + * + * Module: library/aria.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * + * MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 + */ +//#define MBEDTLS_ARIA_C + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +#define MBEDTLS_CCM_C + +/** + * \def MBEDTLS_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +//#define MBEDTLS_CERTS_C + +/** + * \def MBEDTLS_CHACHA20_C + * + * Enable the ChaCha20 stream cipher. + * + * Module: library/chacha20.c + */ +#define MBEDTLS_CHACHA20_C + +/** + * \def MBEDTLS_CHACHAPOLY_C + * + * Enable the ChaCha20-Poly1305 AEAD algorithm. + * + * Module: library/chachapoly.c + * + * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C + */ +#define MBEDTLS_CHACHAPOLY_C + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define MBEDTLS_CIPHER_C + +/** + * \def MBEDTLS_CMAC_C + * + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. + * + * Module: library/cmac.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C + * + */ +//#define MBEDTLS_CMAC_C + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-based random generator. + * The CTR_DRBG generator uses AES-256 by default. + * To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above. + * + * \note To achieve a 256-bit security strength with CTR_DRBG, + * you must use AES-256 *and* use sufficient entropy. + * See ctr_drbg.h for more details. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES random number generator. + */ +#define MBEDTLS_CTR_DRBG_C + +/** + * \def MBEDTLS_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +//#define MBEDTLS_DEBUG_C + +/** + * \def MBEDTLS_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#define MBEDTLS_DES_C + +/** + * \def MBEDTLS_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_DHM_C + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +//#define MBEDTLS_ECDH_C + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C + */ +//#define MBEDTLS_ECDSA_C + +/** + * \def MBEDTLS_ECJPAKE_C + * + * Enable the elliptic curve J-PAKE library. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Module: library/ecjpake.c + * Caller: + * + * This module is used by the following key exchanges: + * ECJPAKE + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C + */ +//#define MBEDTLS_ECJPAKE_C + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +//#define MBEDTLS_ECP_C + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +//#define MBEDTLS_ERROR_C + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#define MBEDTLS_GCM_C + +/** + * \def MBEDTLS_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: MBEDTLS_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define MBEDTLS_HAVEGE_C + +/** + * \def MBEDTLS_HKDF_C + * + * Enable the HKDF algorithm (RFC 5869). + * + * Module: library/hkdf.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the Hashed Message Authentication Code + * (HMAC)-based key derivation function (HKDF). + */ +#define MBEDTLS_HKDF_C + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +//#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_NIST_KW_C + * + * Enable the Key Wrapping mode for 128-bit block ciphers, + * as defined in NIST SP 800-38F. Only KW and KWP modes + * are supported. At the moment, only AES is approved by NIST. + * + * Module: library/nist_kw.c + * + * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_NIST_KW_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD2_C + +/** + * \def MBEDTLS_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD4_C + +/** + * \def MBEDTLS_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2 + * depending on the handshake parameters. Further, it is used for checking + * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded + * encrypted keys. + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: MBEDTLS_PLATFORM_C + * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +/** + * \def MBEDTLS_NET_C + * + * Enable the TCP and UDP over IPv6/IPv4 networking routines. + * + * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) + * and Windows. For other platforms, you'll want to disable it, and write your + * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/net_sockets.c + * + * This module provides networking routines. + */ +//#define MBEDTLS_NET_C + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +//#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +//#define MBEDTLS_PEM_PARSE_C + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +//#define MBEDTLS_PEM_WRITE_C + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +//#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. +*/ +//#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +//#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +//#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: MBEDTLS_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define MBEDTLS_PKCS11_C + +/** + * \def MBEDTLS_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * Can use: MBEDTLS_ARC4_C + * + * This module enables PKCS#12 functions. + */ +//#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_POLY1305_C + * + * Enable the Poly1305 MAC algorithm. + * + * Module: library/poly1305.c + * Caller: library/chachapoly.c + */ +#define MBEDTLS_POLY1305_C + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +//#define MBEDTLS_RIPEMD160_C + +/** + * \def MBEDTLS_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * library/rsa_internal.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +//#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS up to version 1.1, for TLS 1.2 + * depending on the handshake parameters, and for SHA1-signed certificates. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +//#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +//#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_SSL_TICKET_C + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define MBEDTLS_SSL_CLI_C + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +#define MBEDTLS_SSL_SRV_C + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +#define MBEDTLS_SSL_TLS_C + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by + * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide + * your own implementation of the whole module by setting + * \c MBEDTLS_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +//#define MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +//#define MBEDTLS_X509_USE_C + +/** + * \def MBEDTLS_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +//#define MBEDTLS_X509_CRT_PARSE_C + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +//#define MBEDTLS_X509_CRL_PARSE_C + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +//#define MBEDTLS_X509_CSR_PARSE_C + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +//#define MBEDTLS_X509_CREATE_C + +/** + * \def MBEDTLS_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +//#define MBEDTLS_X509_CRT_WRITE_C + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +//#define MBEDTLS_X509_CSR_WRITE_C + +/** + * \def MBEDTLS_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +//#define MBEDTLS_XTEA_C + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */ +//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +/*! Maximal reseed counter - indicates maximal number of +requests allowed between reseeds; according to NIST 800-90 +it is (2^48 - 1), our restriction is : (int - 0xFFFF - 0xF).*/ +#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 0xFFF0 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */ +/* HMAC_DRBG options */ +//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define MBEDTLS_ENTROPY_MAX_GATHER 144 /**< Maximum amount requested from entropy sources */ +//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ + +/* Memory buffer allocator options */ +//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ + +/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ + +/** + * \brief This macro is invoked by the library when an invalid parameter + * is detected that is only checked with #MBEDTLS_CHECK_PARAMS + * (see the documentation of that option for context). + * + * When you leave this undefined here, the library provides + * a default definition. If the macro #MBEDTLS_CHECK_PARAMS_ASSERT + * is defined, the default definition is `assert(cond)`, + * otherwise the default definition calls a function + * mbedtls_param_failed(). This function is declared in + * `platform_util.h` for the benefit of the library, but + * you need to define in your application. + * + * When you define this here, this replaces the default + * definition in platform_util.h (which no longer declares the + * function mbedtls_param_failed()) and it is your responsibility + * to make sure this macro expands to something suitable (in + * particular, that all the necessary declarations are visible + * from within the library - you can ensure that by providing + * them in this file next to the macro definition). + * If you define this macro to call `assert`, also define + * #MBEDTLS_CHECK_PARAMS_ASSERT so that library source files + * include ``. + * + * Note that you may define this macro to expand to nothing, in + * which case you don't have to worry about declarations or + * definitions. However, you will then be notified about invalid + * parameters only in non-void functions, and void function will + * just silently return early on invalid parameters, which + * partially negates the benefits of enabling + * #MBEDTLS_CHECK_PARAMS in the first place, so is discouraged. + * + * \param cond The expression that should evaluate to true, but doesn't. + */ +//#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) + +/* SSL Cache options */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ + +/** \def MBEDTLS_SSL_MAX_CONTENT_LEN + * + * Maximum length (in bytes) of incoming and outgoing plaintext fragments. + * + * This determines the size of both the incoming and outgoing TLS I/O buffers + * in such a way that both are capable of holding the specified amount of + * plaintext data, regardless of the protection mechanism used. + * + * To configure incoming and outgoing I/O buffers separately, use + * #MBEDTLS_SSL_IN_CONTENT_LEN and #MBEDTLS_SSL_OUT_CONTENT_LEN, + * which overwrite the value set by this option. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of both + * incoming and outgoing I/O buffers. + */ +#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024 + +/** \def MBEDTLS_SSL_IN_CONTENT_LEN + * + * Maximum length (in bytes) of incoming plaintext fragments. + * + * This determines the size of the incoming TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option is undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of the incoming I/O buffer + * independently of the outgoing I/O buffer. + */ +//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_OUT_CONTENT_LEN + * + * Maximum length (in bytes) of outgoing plaintext fragments. + * + * This determines the size of the outgoing TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * It is possible to save RAM by setting a smaller outward buffer, while keeping + * the default inward 16384 byte buffer to conform to the TLS specification. + * + * The minimum required outward buffer size is determined by the handshake + * protocol's usage. Handshaking will fail if the outward buffer is too small. + * The specific size requirement depends on the configured ciphers and any + * certificate data which is sent during the handshake. + * + * Uncomment to set the maximum plaintext size of the outgoing I/O buffer + * independently of the incoming I/O buffer. + */ +//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING + * + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + * + * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN + * to account for a reassembled handshake message of maximum size, + * together with its reassembly bitmap. + * + * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default) + * should be sufficient for all practical situations as it allows + * to reassembly a large handshake message (such as a certificate) + * while buffering multiple smaller handshake messages. + * + */ +//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 + +//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +#define MBEDTLS_PSK_MAX_LEN 16 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ +//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +//#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ +//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ + +/** + * Allow SHA-1 in the default TLS configuration for certificate signing. + * Without this build-time option, SHA-1 support must be activated explicitly + * through mbedtls_ssl_conf_cert_profile. Turning on this option is not + * recommended because of it is possible to generate SHA-1 collisions, however + * this may be safe for legacy infrastructure where additional controls apply. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +// #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES + +/** + * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake + * signature and ciphersuite selection. Without this build-time option, SHA-1 + * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. + * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by + * default. At the time of writing, there is no practical attack on the use + * of SHA-1 in handshake signatures, hence this option is turned on by default + * to preserve compatibility with existing peers, but the general + * warning applies nonetheless: + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +/** + * Uncomment the macro to let mbed TLS use your alternate implementation of + * mbedtls_platform_zeroize(). This replaces the default implementation in + * platform_util.c. + * + * mbedtls_platform_zeroize() is a widely used function across the library to + * zero a block of memory. The implementation is expected to be secure in the + * sense that it has been written to prevent the compiler from removing calls + * to mbedtls_platform_zeroize() as part of redundant code elimination + * optimizations. However, it is difficult to guarantee that calls to + * mbedtls_platform_zeroize() will not be optimized by the compiler as older + * versions of the C language standards do not provide a secure implementation + * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to + * configure their own implementation of mbedtls_platform_zeroize(), for + * example by using directives specific to their compiler, features from newer + * C standards (e.g using memset_s() in C11) or calling a secure memset() from + * their system (e.g explicit_bzero() in BSD). + */ +//#define MBEDTLS_PLATFORM_ZEROIZE_ALT + +/** + * Uncomment the macro to let Mbed TLS use your alternate implementation of + * mbedtls_platform_gmtime_r(). This replaces the default implementation in + * platform_util.c. + * + * gmtime() is not a thread-safe function as defined in the C standard. The + * library will try to use safer implementations of this function, such as + * gmtime_r() when available. However, if Mbed TLS cannot identify the target + * system, the implementation of mbedtls_platform_gmtime_r() will default to + * using the standard gmtime(). In this case, calls from the library to + * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex + * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the + * library are also guarded with this mutex to avoid race conditions. However, + * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will + * unconditionally use the implementation for mbedtls_platform_gmtime_r() + * supplied at compile time. + */ +//#define MBEDTLS_PLATFORM_GMTIME_R_ALT + +/* \} name SECTION: Customisation configuration options */ + +/* Target and application specific configurations + * + * Allow user to override any previous default. + * + */ +#if defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +// Adding include to stdio.h to prevent warning (not finding snprintf) +#include + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external/nrf_tls/mbedtls/nrf_crypto/config/nrf_crypto_mbedtls_config.h b/external/nrf_tls/mbedtls/nrf_crypto/config/nrf_crypto_mbedtls_config.h new file mode 100644 index 0000000..9395a46 --- /dev/null +++ b/external/nrf_tls/mbedtls/nrf_crypto/config/nrf_crypto_mbedtls_config.h @@ -0,0 +1,3422 @@ +/** + * \file nrf_crypto_mbedtls_config.h + * + * \brief Configuration options (set of defines) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2020 Nordic Semiconductor ASA, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +#include "sdk_config.h" + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/aria.c + * library/timing.c + * include/mbedtls/bn_mul.h + * + * Required by: + * MBEDTLS_AESNI_C + * MBEDTLS_PADLOCK_C + * + * Comment to disable the use of assembly code. + */ +//#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \def MBEDTLS_NO_64BIT_MULTIPLICATION + * + * The platform lacks support for 32x32 -> 64-bit multiplication. + * + * Used in: + * library/poly1305.c + * + * Some parts of the library may use multiplication of two unsigned 32-bit + * operands with a 64-bit result in order to speed up computations. On some + * platforms, this is not available in hardware and has to be implemented in + * software, usually in a library provided by the toolchain. + * + * Sometimes it is not desirable to have to link to that library. This option + * removes the dependency of that library on platforms that lack a hardware + * 64-bit multiplier by embedding a software implementation in Mbed TLS. + * + * Note that depending on the compiler, this may decrease performance compared + * to using the library function provided by the toolchain. + */ +//#define MBEDTLS_NO_64BIT_MULTIPLICATION + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, + * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and + * MBEDTLS_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions + */ +//#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h, time(), and an implementation for + * mbedtls_platform_gmtime_r() (see below). + * The time needs to be correct (not necessarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + * + * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that + * behaves similarly to the gmtime_r() function from the C standard. Refer to + * the documentation for mbedtls_platform_gmtime_r() for more information. + * + * \note It is possible to configure an implementation for + * mbedtls_platform_gmtime_r() at compile-time by using the macro + * MBEDTLS_PLATFORM_GMTIME_R_ALT. + */ +//#define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +#define MBEDTLS_PLATFORM_MEMORY + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_EXIT_ALT + * + * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT + +/** + * \def MBEDTLS_DEPRECATED_WARNING + * + * Mark deprecated functions so that they generate a warning if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_DEPRECATED_REMOVED + * + * Remove deprecated functions so that they generate an error if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * Uncomment to get errors on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_REMOVED + +/** + * \def MBEDTLS_CHECK_PARAMS + * + * This configuration option controls whether the library validates more of + * the parameters passed to it. + * + * When this flag is not defined, the library only attempts to validate an + * input parameter if: (1) they may come from the outside world (such as the + * network, the filesystem, etc.) or (2) not validating them could result in + * internal memory errors such as overflowing a buffer controlled by the + * library. On the other hand, it doesn't attempt to validate parameters whose + * values are fully controlled by the application (such as pointers). + * + * When this flag is defined, the library additionally attempts to validate + * parameters that are fully controlled by the application, and should always + * be valid if the application code is fully correct and trusted. + * + * For example, when a function accepts as input a pointer to a buffer that may + * contain untrusted data, and its documentation mentions that this pointer + * must not be NULL: + * - The pointer is checked to be non-NULL only if this option is enabled. + * - The content of the buffer is always validated. + * + * When this flag is defined, if a library function receives a parameter that + * is invalid: + * 1. The function will invoke the macro MBEDTLS_PARAM_FAILED(). + * 2. If MBEDTLS_PARAM_FAILED() did not terminate the program, the function + * will immediately return. If the function returns an Mbed TLS error code, + * the error code in this case is MBEDTLS_ERR_xxx_BAD_INPUT_DATA. + * + * When defining this flag, you also need to arrange a definition for + * MBEDTLS_PARAM_FAILED(). You can do this by any of the following methods: + * - By default, the library defines MBEDTLS_PARAM_FAILED() to call a + * function mbedtls_param_failed(), but the library does not define this + * function. If you do not make any other arrangements, you must provide + * the function mbedtls_param_failed() in your application. + * See `platform_util.h` for its prototype. + * - If you enable the macro #MBEDTLS_CHECK_PARAMS_ASSERT, then the + * library defines #MBEDTLS_PARAM_FAILED(\c cond) to be `assert(cond)`. + * You can still supply an alternative definition of + * MBEDTLS_PARAM_FAILED(), which may call `assert`. + * - If you define a macro MBEDTLS_PARAM_FAILED() before including `config.h` + * or you uncomment the definition of MBEDTLS_PARAM_FAILED() in `config.h`, + * the library will call the macro that you defined and will not supply + * its own version. Note that if MBEDTLS_PARAM_FAILED() calls `assert`, + * you need to enable #MBEDTLS_CHECK_PARAMS_ASSERT so that library source + * files include ``. + * + * Uncomment to enable validation of application-controlled parameters. + */ +//#define MBEDTLS_CHECK_PARAMS + +/** + * \def MBEDTLS_CHECK_PARAMS_ASSERT + * + * Allow MBEDTLS_PARAM_FAILED() to call `assert`, and make it default to + * `assert`. This macro is only used if #MBEDTLS_CHECK_PARAMS is defined. + * + * If this macro is not defined, then MBEDTLS_PARAM_FAILED() defaults to + * calling a function mbedtls_param_failed(). See the documentation of + * #MBEDTLS_CHECK_PARAMS for details. + * + * Uncomment to allow MBEDTLS_PARAM_FAILED() to call `assert`. + */ +//#define MBEDTLS_CHECK_PARAMS_ASSERT + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def MBEDTLS_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS_AES_ALT + * + * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternate core implementation of a symmetric crypto, an arithmetic or hash + * module (e.g. platform specific assembly optimized implementations). Keep + * in mind that the function prototypes should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base + * function declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + * + * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their + * use constitutes a security risk. If possible, we recommend + * avoiding dependencies on them, and considering stronger message + * digests and ciphers instead. + * + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_ARIA_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CHACHA20_ALT +//#define MBEDTLS_CHACHAPOLY_ALT +//#define MBEDTLS_CMAC_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_DHM_ALT +//#define MBEDTLS_ECJPAKE_ALT +//#define MBEDTLS_GCM_ALT +//#define MBEDTLS_NIST_KW_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_POLY1305_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_RSA_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT +//#define MBEDTLS_XTEA_ALT + +/* + * When replacing the elliptic curve module, please consider, that it is + * implemented with two .c files: + * - ecp.c + * - ecp_curves.c + * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT + * macros as described above. The only difference is that you have to make sure + * that you provide functionality for both .c files. + */ +//#define MBEDTLS_ECP_ALT + +/** + * \def MBEDTLS_MD2_PROCESS_ALT + * + * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you + * alternate core implementation of symmetric crypto or hash function. Keep in + * mind that function prototypes should remain the same. + * + * This replaces only one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will + * no longer provide the mbedtls_sha1_process() function, but it will still provide + * the other function (using your mbedtls_sha1_process() function) and the definition + * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible + * with this definition. + * + * \note Because of a signature change, the core AES encryption and decryption routines are + * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, + * respectively. When setting up alternative implementations, these functions should + * be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt + * must stay untouched. + * + * \note If you use the AES_xxx_ALT macros, then is is recommended to also set + * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + * + * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use + * constitutes a security risk. If possible, we recommend avoiding + * dependencies on them, and considering stronger message digests + * and ciphers instead. + * + * \warning If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are + * enabled, then the deterministic ECDH signature functions pass the + * the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore + * alternative implementations should use the RNG only for generating + * the ephemeral key and nothing else. If this is not possible, then + * MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative + * implementation should be provided for mbedtls_ecdsa_sign_det_ext() + * (and for mbedtls_ecdsa_sign_det() too if backward compatibility is + * desirable). + * + */ +//#define MBEDTLS_MD2_PROCESS_ALT +//#define MBEDTLS_MD4_PROCESS_ALT +//#define MBEDTLS_MD5_PROCESS_ALT +//#define MBEDTLS_RIPEMD160_PROCESS_ALT +//#define MBEDTLS_SHA1_PROCESS_ALT +//#define MBEDTLS_SHA256_PROCESS_ALT +//#define MBEDTLS_SHA512_PROCESS_ALT +//#define MBEDTLS_DES_SETKEY_ALT +//#define MBEDTLS_DES_CRYPT_ECB_ALT +//#define MBEDTLS_DES3_CRYPT_ECB_ALT +//#define MBEDTLS_AES_SETKEY_ENC_ALT +//#define MBEDTLS_AES_SETKEY_DEC_ALT +//#define MBEDTLS_AES_ENCRYPT_ALT +//#define MBEDTLS_AES_DECRYPT_ALT +//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT +//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT +//#define MBEDTLS_ECDSA_VERIFY_ALT +//#define MBEDTLS_ECDSA_SIGN_ALT +//#define MBEDTLS_ECDSA_GENKEY_ALT + +/** + * \def MBEDTLS_ECP_INTERNAL_ALT + * + * Expose a part of the internal interface of the Elliptic Curve Point module. + * + * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternative core implementation of elliptic curve arithmetic. Keep in mind + * that function prototypes should remain the same. + * + * This partially replaces one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation + * is still present and it is used for group structures not supported by the + * alternative. + * + * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT + * and implementing the following functions: + * unsigned char mbedtls_internal_ecp_grp_capable( + * const mbedtls_ecp_group *grp ) + * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) + * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ) + * The mbedtls_internal_ecp_grp_capable function should return 1 if the + * replacement functions implement arithmetic for the given group and 0 + * otherwise. + * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are + * called before and after each point operation and provide an opportunity to + * implement optimized set up and tear down instructions. + * + * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and + * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac + * function, but will use your mbedtls_internal_ecp_double_jac if the group is + * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when + * receives it as an argument). If the group is not supported then the original + * implementation is used. The other functions and the definition of + * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your + * implementation of mbedtls_internal_ecp_double_jac and + * mbedtls_internal_ecp_grp_capable must be compatible with this definition. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +/* Required for all the functions in this section */ +//#define MBEDTLS_ECP_INTERNAL_ALT +/* Support for Weierstrass curves with Jacobi representation */ +//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT +//#define MBEDTLS_ECP_ADD_MIXED_ALT +//#define MBEDTLS_ECP_DOUBLE_JAC_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT +/* Support for curves with Montgomery arithmetic */ +//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT +//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT +//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT + +/** + * \def MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN + * + * Enable testing of the constant-flow nature of some sensitive functions with + * clang's MemorySanitizer. This causes some existing tests to also test + * this non-functional property of the code under test. + * + * This setting requires compiling with clang -fsanitize=memory. The test + * suites can then be run normally. + * + * \warning This macro is only used for extended testing; it is not considered + * part of the library's API, so it may change or disappear at any time. + * + * Uncomment to enable testing of the constant-flow nature of selected code. + */ +//#define MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN + +/** + * \def MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND + * + * Enable testing of the constant-flow nature of some sensitive functions with + * valgrind's memcheck tool. This causes some existing tests to also test + * this non-functional property of the code under test. + * + * This setting requires valgrind headers for building, and is only useful for + * testing if the tests suites are run with valgrind's memcheck. This can be + * done for an individual test suite with 'valgrind ./test_suite_xxx', or when + * using CMake, this can be done for all test suites with 'make memcheck'. + * + * \warning This macro is only used for extended testing; it is not considered + * part of the library's API, so it may change or disappear at any time. + * + * Uncomment to enable testing of the constant-flow nature of selected code. + */ +//#define MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND + +/** + * \def MBEDTLS_TEST_NULL_ENTROPY + * + * Enables testing and use of mbed TLS without any configured entropy sources. + * This permits use of the library on platforms before an entropy source has + * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the + * MBEDTLS_ENTROPY_NV_SEED switches). + * + * WARNING! This switch MUST be disabled in production builds, and is suitable + * only for development. + * Enabling the switch negates any security provided by the library. + * + * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + */ +//#define MBEDTLS_TEST_NULL_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * + * Uncomment to use your own hardware entropy collector. + */ +//#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Use precomputed AES tables stored in ROM. + * + * Uncomment this macro to use precomputed AES tables stored in ROM. + * Comment this macro to generate AES tables in RAM at runtime. + * + * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb + * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the + * initialization time before the first AES operation can be performed. + * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c + * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded + * performance if ROM access is slower than RAM access. + * + * This option is independent of \c MBEDTLS_AES_FEWER_TABLES. + * + */ +#define MBEDTLS_AES_ROM_TABLES + +/** + * \def MBEDTLS_AES_FEWER_TABLES + * + * Use less ROM/RAM for AES tables. + * + * Uncommenting this macro omits 75% of the AES tables from + * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES) + * by computing their values on the fly during operations + * (the tables are entry-wise rotations of one another). + * + * Tradeoff: Uncommenting this reduces the RAM / ROM footprint + * by ~6kb but at the cost of more arithmetic operations during + * runtime. Specifically, one has to compare 4 accesses within + * different tables to 4 accesses with additional arithmetic + * operations within the same table. The performance gain/loss + * depends on the system and memory details. + * + * This option is independent of \c MBEDTLS_AES_ROM_TABLES. + * + */ +//#define MBEDTLS_AES_FEWER_TABLES + +/** + * \def MBEDTLS_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define MBEDTLS_CAMELLIA_SMALL_MEMORY + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_CIPHER_MODE_OFB + * + * Enable Output Feedback mode (OFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_OFB + +/** + * \def MBEDTLS_CIPHER_MODE_XTS + * + * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. + */ +#define MBEDTLS_CIPHER_MODE_XTS + +/** + * \def MBEDTLS_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define MBEDTLS_CIPHER_NULL_CIPHER + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + * + * Uncomment this macro to use a 128-bit key in the CTR_DRBG module. + * By default, CTR_DRBG uses a 256-bit key. + */ +#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + +/** + * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_3DES_CIPHERSUITES + * + * Remove 3DES ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on 3DES from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible + * to enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including + * them explicitly. + * + * A man-in-the-browser attacker can recover authentication tokens sent through + * a TLS connection using a 3DES based cipher suite (see "On the Practical + * (In-)Security of 64-bit Block Ciphers" by Karthikeyan Bhargavan and Gaëtan + * Leurent, see https://sweet32.info/SWEET32_CCS16.pdf). If this attack falls + * in your threat model or you are unsure, then you should keep this option + * enabled to remove 3DES based cipher suites. + * + * Comment this macro to keep 3DES in the default ciphersuite list. + */ +#define MBEDTLS_REMOVE_3DES_CIPHERSUITES + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_DP_CURVE448_ENABLED + +/** + * \def MBEDTLS_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#define MBEDTLS_ECP_NIST_OPTIM + +/** + * \def MBEDTLS_ECP_NO_INTERNAL_RNG + * + * When this option is disabled, mbedtls_ecp_mul() will make use of an + * internal RNG when called with a NULL \c f_rng argument, in order to protect + * against some side-channel attacks. + * + * This protection introduces a dependency of the ECP module on one of the + * DRBG or SHA modules (HMAC-DRBG, CTR-DRBG, SHA-512 or SHA-256.) For very + * constrained applications that don't require this protection (for example, + * because you're only doing signature verification, so not manipulating any + * secret, or because local/physical side-channel attacks are outside your + * threat model), it might be desirable to get rid of that dependency. + * + * \warning Enabling this option makes some uses of ECP vulnerable to some + * side-channel attacks. Only enable it if you know that's not a problem for + * your use case. + * + * Uncomment this macro to disable some counter-measures in ECP. + */ +//#define MBEDTLS_ECP_NO_INTERNAL_RNG + +/** + * \def MBEDTLS_ECP_RESTARTABLE + * + * Enable "non-blocking" ECC operations that can return early and be resumed. + * + * This allows various functions to pause by returning + * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in + * order to further progress and eventually complete their operation. This is + * controlled through mbedtls_ecp_set_max_ops() which limits the maximum + * number of ECC operations a function may perform before pausing; see + * mbedtls_ecp_set_max_ops() for more information. + * + * This is useful in non-threaded environments if you want to avoid blocking + * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. + * + * Uncomment this macro to enable restartable ECC computations. + * + * \note This option only works with the default software implementation of + * elliptic curve functionality. It is incompatible with + * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT and MBEDTLS_ECDSA_XXX_ALT. + */ +//#define MBEDTLS_ECP_RESTARTABLE + +/** + * \def MBEDTLS_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: MBEDTLS_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +//#define MBEDTLS_ECDSA_DETERMINISTIC + +/** + * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + */ +//#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + * + * Enable the ECJPAKE based ciphersuite modes in SSL / TLS. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Requires: MBEDTLS_ECJPAKE_C + * MBEDTLS_SHA256_C + * MBEDTLS_ECP_DP_SECP256R1_ENABLED + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + +/** + * \def MBEDTLS_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +//#define MBEDTLS_PK_PARSE_EC_EXTENDED + +/** + * \def MBEDTLS_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when MBEDTLS_ERROR_C is disabled + * (no effect when MBEDTLS_ERROR_C is enabled). + * + * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're + * not using mbedtls_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * mbedtls_strerror() + */ +#define MBEDTLS_ERROR_STRERROR_DUMMY + +/** + * \def MBEDTLS_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: MBEDTLS_BIGNUM_C + */ +#define MBEDTLS_GENPRIME + +/** + * \def MBEDTLS_FS_IO + * + * Enable functions that use the filesystem. + */ +//#define MBEDTLS_FS_IO + +/** + * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * mbedtls_timing_hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def MBEDTLS_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +#define MBEDTLS_NO_PLATFORM_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: MBEDTLS_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both MBEDTLS_SHA256_C and + * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. + */ +#define MBEDTLS_ENTROPY_FORCE_SHA256 + +/** + * \def MBEDTLS_ENTROPY_NV_SEED + * + * Enable the non-volatile (NV) seed file-based entropy source. + * (Also enables the NV seed read/write functions in the platform layer) + * + * This is crucial (if not required) on systems that do not have a + * cryptographic entropy source (in hardware or kernel) available. + * + * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C + * + * \note The read/write functions that are used by the entropy source are + * determined in the platform layer, and can be modified at runtime and/or + * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used. + * + * \note If you use the default implementation functions that read a seedfile + * with regular fopen(), please make sure you make a seedfile with the + * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at + * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from + * and written to or you will get an entropy source error! The default + * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE + * bytes from the file. + * + * \note The entropy collector will write to the seed file before entropy is + * given to an external source, to update it. + */ +//#define MBEDTLS_ENTROPY_NV_SEED + +/** + * \def MBEDTLS_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define MBEDTLS_MEMORY_DEBUG + +/** + * \def MBEDTLS_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define MBEDTLS_MEMORY_BACKTRACE + +/** + * \def MBEDTLS_PK_RSA_ALT_SUPPORT + * + * Support external private RSA keys (eg from a HSM) in the PK layer. + * + * Comment this macro to disable support for external private RSA keys. + */ +//#define MBEDTLS_PK_RSA_ALT_SUPPORT + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define MBEDTLS_PKCS1_V15 + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define MBEDTLS_PKCS1_V21 + +/** + * \def MBEDTLS_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem + * for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define MBEDTLS_RSA_NO_CRT + +/** + * \def MBEDTLS_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +//#define MBEDTLS_SELF_TEST + +/** + * \def MBEDTLS_SHA256_SMALLER + * + * Enable an implementation of SHA-256 that has lower ROM footprint but also + * lower performance. + * + * The default implementation is meant to be a reasonnable compromise between + * performance and size. This version optimizes more aggressively for size at + * the expense of performance. Eg on Cortex-M4 it reduces the size of + * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about + * 30%. + * + * Uncomment to enable the smaller implementation of SHA256. + */ +//#define MBEDTLS_SHA256_SMALLER + +/** + * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define MBEDTLS_SSL_ALL_ALERT_MESSAGES + +/** + * \def MBEDTLS_SSL_ASYNC_PRIVATE + * + * Enable asynchronous external private key operations in SSL. This allows + * you to configure an SSL connection to call an external cryptographic + * module to perform private key operations instead of performing the + * operation inside the library. + * + */ +//#define MBEDTLS_SSL_ASYNC_PRIVATE + +/** + * \def MBEDTLS_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define MBEDTLS_SSL_DEBUG_ALL + +/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +//#define MBEDTLS_SSL_ENCRYPT_THEN_MAC + +/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for Extended Master Secret, aka Session Hash + * (draft-ietf-tls-session-hash-02). + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +//#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET + +/** + * \def MBEDTLS_SSL_FALLBACK_SCSV + * + * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00). + * + * For servers, it is recommended to always enable this, unless you support + * only one version of TLS, or know for sure that none of your clients + * implements a fallback strategy. + * + * For clients, you only need this if you're using a fallback strategy, which + * is not recommended in the first place, unless you absolutely need it to + * interoperate with buggy (version-intolerant) servers. + * + * Comment this macro to disable support for FALLBACK_SCSV + */ +#define MBEDTLS_SSL_FALLBACK_SCSV + +/** + * \def MBEDTLS_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define MBEDTLS_SSL_HW_RECORD_ACCEL + +/** + * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING + * + * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. + * + * This is a countermeasure to the BEAST attack, which also minimizes the risk + * of interoperability issues compared to sending 0-length records. + * + * Comment this macro to disable 1/n-1 record splitting. + */ +//#define MBEDTLS_SSL_CBC_RECORD_SPLITTING + +/** + * \def MBEDTLS_SSL_RENEGOTIATION + * + * Enable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Comment this to disable support for renegotiation. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * + */ +#define MBEDTLS_SSL_RENEGOTIATION + +/** + * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to enable support for SSLv2 Client Hello messages. + */ +//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def MBEDTLS_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +//#define MBEDTLS_SSL_PROTO_SSL3 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +//#define MBEDTLS_SSL_PROTO_TLS1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled). + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 / DTLS 1.0 + */ +//#define MBEDTLS_SSL_PROTO_TLS1_1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +//#define MBEDTLS_SSL_PROTO_TLS1_2 + +/** + * \def MBEDTLS_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0, + * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_1 + * or MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +//#define MBEDTLS_SSL_PROTO_DTLS + +/** + * \def MBEDTLS_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +//#define MBEDTLS_SSL_ALPN + +/** + * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: MBEDTLS_SSL_TLS_C + * MBEDTLS_SSL_PROTO_DTLS + * + * \warning Disabling this is often a security risk! + * See mbedtls_ssl_conf_dtls_anti_replay() for details. + * + * Comment this to disable anti-replay in DTLS. + */ +//#define MBEDTLS_SSL_DTLS_ANTI_REPLAY + +/** + * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Enable support for HelloVerifyRequest on DTLS servers. + * + * This feature is highly recommended to prevent DTLS servers being used as + * amplifiers in DoS attacks against other hosts. It should always be enabled + * unless you know for sure amplification cannot be a problem in the + * environment in which your server operates. + * + * \warning Disabling this can ba a security risk! (see above) + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +//#define MBEDTLS_SSL_DTLS_HELLO_VERIFY + +/** + * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + * + * Enable server-side support for clients that reconnect from the same port. + * + * Some clients unexpectedly close the connection and try to reconnect using the + * same source port. This needs special support from the server to handle the + * new connection securely, as described in section 4.2.8 of RFC 6347. This + * flag enables that support. + * + * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +//#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + +/** + * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT + * + * Enable support for a limit of records with bad MAC. + * + * See mbedtls_ssl_conf_dtls_badmac_limit(). + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + */ +//#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT + +/** + * \def MBEDTLS_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * Client-side, provides full support for session tickets (maintenance of a + * session store remains the responsibility of the application, though). + * Server-side, you also need to provide callbacks for writing and parsing + * tickets, including authenticated encryption and key management. Example + * callbacks are provided by MBEDTLS_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +#define MBEDTLS_SSL_SESSION_TICKETS + +/** + * \def MBEDTLS_SSL_EXPORT_KEYS + * + * Enable support for exporting key block and master secret. + * This is required for certain users of TLS, e.g. EAP-TLS. + * + * Comment this macro to disable support for key export + */ +//#define MBEDTLS_SSL_EXPORT_KEYS + +/** + * \def MBEDTLS_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +//#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +#define MBEDTLS_SSL_TRUNCATED_HMAC + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + * + * Fallback to old (pre-2.7), non-conforming implementation of the truncated + * HMAC extension which also truncates the HMAC key. Note that this option is + * only meant for a transitory upgrade period and is likely to be removed in + * a future version of the library. + * + * \warning The old implementation is non-compliant and has a security weakness + * (2^80 brute force attack on the HMAC key used for a single, + * uninterrupted connection). This should only be enabled temporarily + * when (1) the use of truncated HMAC is essential in order to save + * bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use + * the fixed implementation yet (pre-2.7). + * + * \deprecated This option is deprecated and will likely be removed in a + * future version of Mbed TLS. + * + * Uncomment to fallback to old, non-compliant truncated HMAC implementation. + * + * Requires: MBEDTLS_SSL_TRUNCATED_HMAC + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + +/** + * \def MBEDTLS_TEST_HOOKS + * + * Enable features for invasive testing such as introspection functions and + * hooks for fault injection. This enables additional unit tests. + * + * Merely enabling this feature should not change the behavior of the product. + * It only adds new code, and new branching points where the default behavior + * is the same as when this feature is disabled. + * However, this feature increases the attack surface: there is an added + * risk of vulnerabilities, and more gadgets that can make exploits easier. + * Therefore this feature must never be enabled in production. + * + * Uncomment to enable invasive tests. + */ +//#define MBEDTLS_TEST_HOOKS + +/** + * \def MBEDTLS_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define MBEDTLS_THREADING_ALT + +/** + * \def MBEDTLS_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define MBEDTLS_THREADING_PTHREAD + +/** + * \def MBEDTLS_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via mbedtls_version_check_feature(). + * + * Requires: MBEDTLS_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +#define MBEDTLS_VERSION_FEATURES + +/** + * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * \warning Depending on your PKI use, enabling this can be a security risk! + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def MBEDTLS_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +#define MBEDTLS_X509_CHECK_KEY_USAGE + +/** + * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +//#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +//#define MBEDTLS_X509_RSASSA_PSS_SUPPORT + +/** + * \def MBEDTLS_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * \warning TLS-level compression MAY REDUCE SECURITY! See for example the + * CRIME attack. Before enabling this option, you should examine with care if + * CRIME or similar exploits may be applicable to your use case. + * + * \note Currently compression can't be used with DTLS. + * + * \deprecated This feature is deprecated and will be removed + * in the next major revision of the library. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define MBEDTLS_ZLIB_SUPPORT +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +//#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/cipher.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define MBEDTLS_AES_C + +/** + * \def MBEDTLS_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. If possible, we recommend avoidng dependencies on + * it, and considering stronger ciphers instead. + * + */ +//#define MBEDTLS_ARC4_C + +/** + * \def MBEDTLS_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define MBEDTLS_ASN1_PARSE_C + +/** + * \def MBEDTLS_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +#define MBEDTLS_ASN1_WRITE_C + +/** + * \def MBEDTLS_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define MBEDTLS_BASE64_C + +/** + * \def MBEDTLS_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/rsa_internal.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define MBEDTLS_BIGNUM_C + +/** + * \def MBEDTLS_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +//#define MBEDTLS_BLOWFISH_C + +/** + * \def MBEDTLS_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +#define MBEDTLS_CAMELLIA_C + +/** + * \def MBEDTLS_ARIA_C + * + * Enable the ARIA block cipher. + * + * Module: library/aria.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * + * MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 + */ +//#define MBEDTLS_ARIA_C + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +#define MBEDTLS_CCM_C + +/** + * \def MBEDTLS_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +//#define MBEDTLS_CERTS_C + +/** + * \def MBEDTLS_CHACHA20_C + * + * Enable the ChaCha20 stream cipher. + * + * Module: library/chacha20.c + */ +#define MBEDTLS_CHACHA20_C + +/** + * \def MBEDTLS_CHACHAPOLY_C + * + * Enable the ChaCha20-Poly1305 AEAD algorithm. + * + * Module: library/chachapoly.c + * + * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C + */ +#define MBEDTLS_CHACHAPOLY_C + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define MBEDTLS_CIPHER_C + +/** + * \def MBEDTLS_CMAC_C + * + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. + * + * Module: library/cmac.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C + * + */ +#define MBEDTLS_CMAC_C + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-based random generator. + * The CTR_DRBG generator uses AES-256 by default. + * To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above. + * + * \note To achieve a 256-bit security strength with CTR_DRBG, + * you must use AES-256 *and* use sufficient entropy. + * See ctr_drbg.h for more details. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES random number generator. + */ +#define MBEDTLS_CTR_DRBG_C + +/** + * \def MBEDTLS_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +//#define MBEDTLS_DEBUG_C + +/** + * \def MBEDTLS_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#define MBEDTLS_DES_C + +/** + * \def MBEDTLS_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_DHM_C + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +#define MBEDTLS_ECDH_C + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C + */ +#define MBEDTLS_ECDSA_C + +/** + * \def MBEDTLS_ECJPAKE_C + * + * Enable the elliptic curve J-PAKE library. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Module: library/ecjpake.c + * Caller: + * + * This module is used by the following key exchanges: + * ECJPAKE + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C + */ +//#define MBEDTLS_ECJPAKE_C + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +#define MBEDTLS_ECP_C + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +//#define MBEDTLS_ERROR_C + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#define MBEDTLS_GCM_C + +/** + * \def MBEDTLS_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: MBEDTLS_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define MBEDTLS_HAVEGE_C + +/** + * \def MBEDTLS_HKDF_C + * + * Enable the HKDF algorithm (RFC 5869). + * + * Module: library/hkdf.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the Hashed Message Authentication Code + * (HMAC)-based key derivation function (HKDF). + */ +#define MBEDTLS_HKDF_C + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_NIST_KW_C + * + * Enable the Key Wrapping mode for 128-bit block ciphers, + * as defined in NIST SP 800-38F. Only KW and KWP modes + * are supported. At the moment, only AES is approved by NIST. + * + * Module: library/nist_kw.c + * + * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_NIST_KW_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD2_C + +/** + * \def MBEDTLS_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD4_C + +/** + * \def MBEDTLS_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2 + * depending on the handshake parameters. Further, it is used for checking + * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded + * encrypted keys. + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: MBEDTLS_PLATFORM_C + * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +/** + * \def MBEDTLS_NET_C + * + * Enable the TCP and UDP over IPv6/IPv4 networking routines. + * + * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) + * and Windows. For other platforms, you'll want to disable it, and write your + * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/net_sockets.c + * + * This module provides networking routines. + */ +//#define MBEDTLS_NET_C + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +//#define MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +//#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +//#define MBEDTLS_PEM_PARSE_C + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +//#define MBEDTLS_PEM_WRITE_C + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +//#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +//#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +//#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +//#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: MBEDTLS_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define MBEDTLS_PKCS11_C + +/** + * \def MBEDTLS_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * Can use: MBEDTLS_ARC4_C + * + * This module enables PKCS#12 functions. + */ +//#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_POLY1305_C + * + * Enable the Poly1305 MAC algorithm. + * + * Module: library/poly1305.c + * Caller: library/chachapoly.c + */ +#define MBEDTLS_POLY1305_C + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +//#define MBEDTLS_RIPEMD160_C + +/** + * \def MBEDTLS_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * library/rsa_internal.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +//#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS up to version 1.1, for TLS 1.2 + * depending on the handshake parameters, and for SHA1-signed certificates. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +//#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +//#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_SSL_TICKET_C + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +//#define MBEDTLS_SSL_CLI_C + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +//#define MBEDTLS_SSL_SRV_C + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +//define MBEDTLS_SSL_TLS_C + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by + * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide + * your own implementation of the whole module by setting + * \c MBEDTLS_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +//#define MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +//#define MBEDTLS_X509_USE_C + +/** + * \def MBEDTLS_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/mbedtls_x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +//#define MBEDTLS_X509_CRT_PARSE_C + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +//#define MBEDTLS_X509_CRL_PARSE_C + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/mbedtls_x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +//#define MBEDTLS_X509_CSR_PARSE_C + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +//#define MBEDTLS_X509_CREATE_C + +/** + * \def MBEDTLS_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +//#define MBEDTLS_X509_CRT_WRITE_C + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +//#define MBEDTLS_X509_CSR_WRITE_C + +/** + * \def MBEDTLS_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +//#define MBEDTLS_XTEA_C + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */ +//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +/*! Maximal reseed counter - indicates maximal number of +requests allowed between reseeds; according to NIST 800-90 +it is (2^48 - 1), our restriction is : (int - 0xFFFF - 0xF).*/ +#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 0xFFF0 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */ +/* HMAC_DRBG options */ +//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define MBEDTLS_ENTROPY_MAX_GATHER 144 /**< Maximum amount requested from entropy sources */ +//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ + +/* Memory buffer allocator options */ +//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ + +/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ + +/** + * \brief This macro is invoked by the library when an invalid parameter + * is detected that is only checked with #MBEDTLS_CHECK_PARAMS + * (see the documentation of that option for context). + * + * When you leave this undefined here, the library provides + * a default definition. If the macro #MBEDTLS_CHECK_PARAMS_ASSERT + * is defined, the default definition is `assert(cond)`, + * otherwise the default definition calls a function + * mbedtls_param_failed(). This function is declared in + * `platform_util.h` for the benefit of the library, but + * you need to define in your application. + * + * When you define this here, this replaces the default + * definition in platform_util.h (which no longer declares the + * function mbedtls_param_failed()) and it is your responsibility + * to make sure this macro expands to something suitable (in + * particular, that all the necessary declarations are visible + * from within the library - you can ensure that by providing + * them in this file next to the macro definition). + * If you define this macro to call `assert`, also define + * #MBEDTLS_CHECK_PARAMS_ASSERT so that library source files + * include ``. + * + * Note that you may define this macro to expand to nothing, in + * which case you don't have to worry about declarations or + * definitions. However, you will then be notified about invalid + * parameters only in non-void functions, and void function will + * just silently return early on invalid parameters, which + * partially negates the benefits of enabling + * #MBEDTLS_CHECK_PARAMS in the first place, so is discouraged. + * + * \param cond The expression that should evaluate to true, but doesn't. + */ +//#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) + +/* SSL Cache options */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ + +/** \def MBEDTLS_SSL_MAX_CONTENT_LEN + * + * Maximum length (in bytes) of incoming and outgoing plaintext fragments. + * + * This determines the size of both the incoming and outgoing TLS I/O buffers + * in such a way that both are capable of holding the specified amount of + * plaintext data, regardless of the protection mechanism used. + * + * To configure incoming and outgoing I/O buffers separately, use + * #MBEDTLS_SSL_IN_CONTENT_LEN and #MBEDTLS_SSL_OUT_CONTENT_LEN, + * which overwrite the value set by this option. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of both + * incoming and outgoing I/O buffers. + */ +//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_IN_CONTENT_LEN + * + * Maximum length (in bytes) of incoming plaintext fragments. + * + * This determines the size of the incoming TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option is undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of the incoming I/O buffer + * independently of the outgoing I/O buffer. + */ +//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_OUT_CONTENT_LEN + * + * Maximum length (in bytes) of outgoing plaintext fragments. + * + * This determines the size of the outgoing TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * It is possible to save RAM by setting a smaller outward buffer, while keeping + * the default inward 16384 byte buffer to conform to the TLS specification. + * + * The minimum required outward buffer size is determined by the handshake + * protocol's usage. Handshaking will fail if the outward buffer is too small. + * The specific size requirement depends on the configured ciphers and any + * certificate data which is sent during the handshake. + * + * Uncomment to set the maximum plaintext size of the outgoing I/O buffer + * independently of the incoming I/O buffer. + */ +//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING + * + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + * + * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN + * to account for a reassembled handshake message of maximum size, + * together with its reassembly bitmap. + * + * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default) + * should be sufficient for all practical situations as it allows + * to reassembly a large handshake message (such as a certificate) + * while buffering multiple smaller handshake messages. + * + */ +//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 + +//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ +//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,\ + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,\ + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA,\ + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ +//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ + +/** + * Allow SHA-1 in the default TLS configuration for certificate signing. + * Without this build-time option, SHA-1 support must be activated explicitly + * through mbedtls_ssl_conf_cert_profile. Turning on this option is not + * recommended because of it is possible to generate SHA-1 collisions, however + * this may be safe for legacy infrastructure where additional controls apply. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +// #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES + +/** + * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake + * signature and ciphersuite selection. Without this build-time option, SHA-1 + * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. + * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by + * default. At the time of writing, there is no practical attack on the use + * of SHA-1 in handshake signatures, hence this option is turned on by default + * to preserve compatibility with existing peers, but the general + * warning applies nonetheless: + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +/** + * Uncomment the macro to let mbed TLS use your alternate implementation of + * mbedtls_platform_zeroize(). This replaces the default implementation in + * platform_util.c. + * + * mbedtls_platform_zeroize() is a widely used function across the library to + * zero a block of memory. The implementation is expected to be secure in the + * sense that it has been written to prevent the compiler from removing calls + * to mbedtls_platform_zeroize() as part of redundant code elimination + * optimizations. However, it is difficult to guarantee that calls to + * mbedtls_platform_zeroize() will not be optimized by the compiler as older + * versions of the C language standards do not provide a secure implementation + * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to + * configure their own implementation of mbedtls_platform_zeroize(), for + * example by using directives specific to their compiler, features from newer + * C standards (e.g using memset_s() in C11) or calling a secure memset() from + * their system (e.g explicit_bzero() in BSD). + */ +//#define MBEDTLS_PLATFORM_ZEROIZE_ALT + +/** + * Uncomment the macro to let Mbed TLS use your alternate implementation of + * mbedtls_platform_gmtime_r(). This replaces the default implementation in + * platform_util.c. + * + * gmtime() is not a thread-safe function as defined in the C standard. The + * library will try to use safer implementations of this function, such as + * gmtime_r() when available. However, if Mbed TLS cannot identify the target + * system, the implementation of mbedtls_platform_gmtime_r() will default to + * using the standard gmtime(). In this case, calls from the library to + * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex + * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the + * library are also guarded with this mutex to avoid race conditions. However, + * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will + * unconditionally use the implementation for mbedtls_platform_gmtime_r() + * supplied at compile time. + */ +//#define MBEDTLS_PLATFORM_GMTIME_R_ALT + +/* \} name SECTION: Customisation configuration options */ + +/* Target and application specific configurations + * + * Allow user to override any previous default. + * + */ +#if defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external/nrf_tls/mbedtls/tls/config/nrf_tls_config.h b/external/nrf_tls/mbedtls/tls/config/nrf_tls_config.h new file mode 100644 index 0000000..a71e7b3 --- /dev/null +++ b/external/nrf_tls/mbedtls/tls/config/nrf_tls_config.h @@ -0,0 +1,3423 @@ +/** + * \file nrf_dtls_config.h + * + * \brief Configuration options (set of defines) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2015 Nordic Semiconductor ASA, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/aria.c + * library/timing.c + * include/mbedtls/bn_mul.h + * + * Required by: + * MBEDTLS_AESNI_C + * MBEDTLS_PADLOCK_C + * + * Comment to disable the use of assembly code. + */ +//#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \def MBEDTLS_NO_64BIT_MULTIPLICATION + * + * The platform lacks support for 32x32 -> 64-bit multiplication. + * + * Used in: + * library/poly1305.c + * + * Some parts of the library may use multiplication of two unsigned 32-bit + * operands with a 64-bit result in order to speed up computations. On some + * platforms, this is not available in hardware and has to be implemented in + * software, usually in a library provided by the toolchain. + * + * Sometimes it is not desirable to have to link to that library. This option + * removes the dependency of that library on platforms that lack a hardware + * 64-bit multiplier by embedding a software implementation in Mbed TLS. + * + * Note that depending on the compiler, this may decrease performance compared + * to using the library function provided by the toolchain. + */ +//#define MBEDTLS_NO_64BIT_MULTIPLICATION + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, + * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and + * MBEDTLS_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions + */ +//#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h, time(), and an implementation for + * mbedtls_platform_gmtime_r() (see below). + * The time needs to be correct (not necessarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + * + * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that + * behaves similarly to the gmtime_r() function from the C standard. Refer to + * the documentation for mbedtls_platform_gmtime_r() for more information. + * + * \note It is possible to configure an implementation for + * mbedtls_platform_gmtime_r() at compile-time by using the macro + * MBEDTLS_PLATFORM_GMTIME_R_ALT. + */ +//#define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +#define MBEDTLS_PLATFORM_MEMORY + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_EXIT_ALT + * + * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT + +/** + * \def MBEDTLS_DEPRECATED_WARNING + * + * Mark deprecated functions so that they generate a warning if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_DEPRECATED_REMOVED + * + * Remove deprecated functions so that they generate an error if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * Uncomment to get errors on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_REMOVED + +/** + * \def MBEDTLS_CHECK_PARAMS + * + * This configuration option controls whether the library validates more of + * the parameters passed to it. + * + * When this flag is not defined, the library only attempts to validate an + * input parameter if: (1) they may come from the outside world (such as the + * network, the filesystem, etc.) or (2) not validating them could result in + * internal memory errors such as overflowing a buffer controlled by the + * library. On the other hand, it doesn't attempt to validate parameters whose + * values are fully controlled by the application (such as pointers). + * + * When this flag is defined, the library additionally attempts to validate + * parameters that are fully controlled by the application, and should always + * be valid if the application code is fully correct and trusted. + * + * For example, when a function accepts as input a pointer to a buffer that may + * contain untrusted data, and its documentation mentions that this pointer + * must not be NULL: + * - The pointer is checked to be non-NULL only if this option is enabled. + * - The content of the buffer is always validated. + * + * When this flag is defined, if a library function receives a parameter that + * is invalid: + * 1. The function will invoke the macro MBEDTLS_PARAM_FAILED(). + * 2. If MBEDTLS_PARAM_FAILED() did not terminate the program, the function + * will immediately return. If the function returns an Mbed TLS error code, + * the error code in this case is MBEDTLS_ERR_xxx_BAD_INPUT_DATA. + * + * When defining this flag, you also need to arrange a definition for + * MBEDTLS_PARAM_FAILED(). You can do this by any of the following methods: + * - By default, the library defines MBEDTLS_PARAM_FAILED() to call a + * function mbedtls_param_failed(), but the library does not define this + * function. If you do not make any other arrangements, you must provide + * the function mbedtls_param_failed() in your application. + * See `platform_util.h` for its prototype. + * - If you enable the macro #MBEDTLS_CHECK_PARAMS_ASSERT, then the + * library defines #MBEDTLS_PARAM_FAILED(\c cond) to be `assert(cond)`. + * You can still supply an alternative definition of + * MBEDTLS_PARAM_FAILED(), which may call `assert`. + * - If you define a macro MBEDTLS_PARAM_FAILED() before including `config.h` + * or you uncomment the definition of MBEDTLS_PARAM_FAILED() in `config.h`, + * the library will call the macro that you defined and will not supply + * its own version. Note that if MBEDTLS_PARAM_FAILED() calls `assert`, + * you need to enable #MBEDTLS_CHECK_PARAMS_ASSERT so that library source + * files include ``. + * + * Uncomment to enable validation of application-controlled parameters. + */ +//#define MBEDTLS_CHECK_PARAMS + +/** + * \def MBEDTLS_CHECK_PARAMS_ASSERT + * + * Allow MBEDTLS_PARAM_FAILED() to call `assert`, and make it default to + * `assert`. This macro is only used if #MBEDTLS_CHECK_PARAMS is defined. + * + * If this macro is not defined, then MBEDTLS_PARAM_FAILED() defaults to + * calling a function mbedtls_param_failed(). See the documentation of + * #MBEDTLS_CHECK_PARAMS for details. + * + * Uncomment to allow MBEDTLS_PARAM_FAILED() to call `assert`. + */ +//#define MBEDTLS_CHECK_PARAMS_ASSERT + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def MBEDTLS_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS_AES_ALT + * + * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternate core implementation of a symmetric crypto, an arithmetic or hash + * module (e.g. platform specific assembly optimized implementations). Keep + * in mind that the function prototypes should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base + * function declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + * + * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their + * use constitutes a security risk. If possible, we recommend + * avoiding dependencies on them, and considering stronger message + * digests and ciphers instead. + * + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_ARIA_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CHACHA20_ALT +//#define MBEDTLS_CHACHAPOLY_ALT +//#define MBEDTLS_CMAC_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_DHM_ALT +//#define MBEDTLS_ECJPAKE_ALT +//#define MBEDTLS_GCM_ALT +//#define MBEDTLS_NIST_KW_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_RSA_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT +//#define MBEDTLS_XTEA_ALT + +/* + * When replacing the elliptic curve module, please consider, that it is + * implemented with two .c files: + * - ecp.c + * - ecp_curves.c + * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT + * macros as described above. The only difference is that you have to make sure + * that you provide functionality for both .c files. + */ +//#define MBEDTLS_ECP_ALT + +/** + * \def MBEDTLS_MD2_PROCESS_ALT + * + * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you + * alternate core implementation of symmetric crypto or hash function. Keep in + * mind that function prototypes should remain the same. + * + * This replaces only one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will + * no longer provide the mbedtls_sha1_process() function, but it will still provide + * the other function (using your mbedtls_sha1_process() function) and the definition + * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible + * with this definition. + * + * \note Because of a signature change, the core AES encryption and decryption routines are + * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, + * respectively. When setting up alternative implementations, these functions should + * be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt + * must stay untouched. + * + * \note If you use the AES_xxx_ALT macros, then is is recommended to also set + * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + * + * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use + * constitutes a security risk. If possible, we recommend avoiding + * dependencies on them, and considering stronger message digests + * and ciphers instead. + * + * \warning If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are + * enabled, then the deterministic ECDH signature functions pass the + * the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore + * alternative implementations should use the RNG only for generating + * the ephemeral key and nothing else. If this is not possible, then + * MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative + * implementation should be provided for mbedtls_ecdsa_sign_det_ext() + * (and for mbedtls_ecdsa_sign_det() too if backward compatibility is + * desirable). + * + */ +//#define MBEDTLS_MD2_PROCESS_ALT +//#define MBEDTLS_MD4_PROCESS_ALT +//#define MBEDTLS_MD5_PROCESS_ALT +//#define MBEDTLS_RIPEMD160_PROCESS_ALT +//#define MBEDTLS_SHA1_PROCESS_ALT +//#define MBEDTLS_SHA256_PROCESS_ALT +//#define MBEDTLS_SHA512_PROCESS_ALT +//#define MBEDTLS_DES_SETKEY_ALT +//#define MBEDTLS_DES_CRYPT_ECB_ALT +//#define MBEDTLS_DES3_CRYPT_ECB_ALT +//#define MBEDTLS_AES_SETKEY_ENC_ALT +//#define MBEDTLS_AES_SETKEY_DEC_ALT +//#define MBEDTLS_AES_ENCRYPT_ALT +//#define MBEDTLS_AES_DECRYPT_ALT +//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT +//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT +//#define MBEDTLS_ECDSA_VERIFY_ALT +//#define MBEDTLS_ECDSA_SIGN_ALT +//#define MBEDTLS_ECDSA_GENKEY_ALT + +/** + * \def MBEDTLS_ECP_INTERNAL_ALT + * + * Expose a part of the internal interface of the Elliptic Curve Point module. + * + * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternative core implementation of elliptic curve arithmetic. Keep in mind + * that function prototypes should remain the same. + * + * This partially replaces one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation + * is still present and it is used for group structures not supported by the + * alternative. + * + * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT + * and implementing the following functions: + * unsigned char mbedtls_internal_ecp_grp_capable( + * const mbedtls_ecp_group *grp ) + * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) + * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ) + * The mbedtls_internal_ecp_grp_capable function should return 1 if the + * replacement functions implement arithmetic for the given group and 0 + * otherwise. + * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are + * called before and after each point operation and provide an opportunity to + * implement optimized set up and tear down instructions. + * + * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and + * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac + * function, but will use your mbedtls_internal_ecp_double_jac if the group is + * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when + * receives it as an argument). If the group is not supported then the original + * implementation is used. The other functions and the definition of + * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your + * implementation of mbedtls_internal_ecp_double_jac and + * mbedtls_internal_ecp_grp_capable must be compatible with this definition. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +/* Required for all the functions in this section */ +//#define MBEDTLS_ECP_INTERNAL_ALT +/* Support for Weierstrass curves with Jacobi representation */ +//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT +//#define MBEDTLS_ECP_ADD_MIXED_ALT +//#define MBEDTLS_ECP_DOUBLE_JAC_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT +/* Support for curves with Montgomery arithmetic */ +//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT +//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT +//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT + +/** + * \def MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN + * + * Enable testing of the constant-flow nature of some sensitive functions with + * clang's MemorySanitizer. This causes some existing tests to also test + * this non-functional property of the code under test. + * + * This setting requires compiling with clang -fsanitize=memory. The test + * suites can then be run normally. + * + * \warning This macro is only used for extended testing; it is not considered + * part of the library's API, so it may change or disappear at any time. + * + * Uncomment to enable testing of the constant-flow nature of selected code. + */ +//#define MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN + +/** + * \def MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND + * + * Enable testing of the constant-flow nature of some sensitive functions with + * valgrind's memcheck tool. This causes some existing tests to also test + * this non-functional property of the code under test. + * + * This setting requires valgrind headers for building, and is only useful for + * testing if the tests suites are run with valgrind's memcheck. This can be + * done for an individual test suite with 'valgrind ./test_suite_xxx', or when + * using CMake, this can be done for all test suites with 'make memcheck'. + * + * \warning This macro is only used for extended testing; it is not considered + * part of the library's API, so it may change or disappear at any time. + * + * Uncomment to enable testing of the constant-flow nature of selected code. + */ +//#define MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND + +/** + * \def MBEDTLS_TEST_NULL_ENTROPY + * + * Enables testing and use of mbed TLS without any configured entropy sources. + * This permits use of the library on platforms before an entropy source has + * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the + * MBEDTLS_ENTROPY_NV_SEED switches). + * + * WARNING! This switch MUST be disabled in production builds, and is suitable + * only for development. + * Enabling the switch negates any security provided by the library. + * + * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + */ +//#define MBEDTLS_TEST_NULL_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * + * Uncomment to use your own hardware entropy collector. + */ +//#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Use precomputed AES tables stored in ROM. + * + * Uncomment this macro to use precomputed AES tables stored in ROM. + * Comment this macro to generate AES tables in RAM at runtime. + * + * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb + * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the + * initialization time before the first AES operation can be performed. + * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c + * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded + * performance if ROM access is slower than RAM access. + * + * This option is independent of \c MBEDTLS_AES_FEWER_TABLES. + * + */ +#define MBEDTLS_AES_ROM_TABLES + +/** + * \def MBEDTLS_AES_FEWER_TABLES + * + * Use less ROM/RAM for AES tables. + * + * Uncommenting this macro omits 75% of the AES tables from + * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES) + * by computing their values on the fly during operations + * (the tables are entry-wise rotations of one another). + * + * Tradeoff: Uncommenting this reduces the RAM / ROM footprint + * by ~6kb but at the cost of more arithmetic operations during + * runtime. Specifically, one has to compare 4 accesses within + * different tables to 4 accesses with additional arithmetic + * operations within the same table. The performance gain/loss + * depends on the system and memory details. + * + * This option is independent of \c MBEDTLS_AES_ROM_TABLES. + * + */ +//#define MBEDTLS_AES_FEWER_TABLES + +/** + * \def MBEDTLS_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define MBEDTLS_CAMELLIA_SMALL_MEMORY + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_CIPHER_MODE_OFB + * + * Enable Output Feedback mode (OFB) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_OFB + +/** + * \def MBEDTLS_CIPHER_MODE_XTS + * + * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. + */ +//#define MBEDTLS_CIPHER_MODE_XTS + +/** + * \def MBEDTLS_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define MBEDTLS_CIPHER_NULL_CIPHER + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +//#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + * + * Uncomment this macro to use a 128-bit key in the CTR_DRBG module. + * By default, CTR_DRBG uses a 256-bit key. + */ +#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + +/** + * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_3DES_CIPHERSUITES + * + * Remove 3DES ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on 3DES from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible + * to enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including + * them explicitly. + * + * A man-in-the-browser attacker can recover authentication tokens sent through + * a TLS connection using a 3DES based cipher suite (see "On the Practical + * (In-)Security of 64-bit Block Ciphers" by Karthikeyan Bhargavan and Gaëtan + * Leurent, see https://sweet32.info/SWEET32_CCS16.pdf). If this attack falls + * in your threat model or you are unsure, then you should keep this option + * enabled to remove 3DES based cipher suites. + * + * Comment this macro to keep 3DES in the default ciphersuite list. + */ +#define MBEDTLS_REMOVE_3DES_CIPHERSUITES + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +//#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +//#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +//#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +//#define MBEDTLS_ECP_DP_BP256R1_ENABLED +//#define MBEDTLS_ECP_DP_BP384R1_ENABLED +//#define MBEDTLS_ECP_DP_BP512R1_ENABLED +//#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +//#define MBEDTLS_ECP_DP_CURVE448_ENABLED + +/** + * \def MBEDTLS_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#define MBEDTLS_ECP_NIST_OPTIM + +/** + * \def MBEDTLS_ECP_NO_INTERNAL_RNG + * + * When this option is disabled, mbedtls_ecp_mul() will make use of an + * internal RNG when called with a NULL \c f_rng argument, in order to protect + * against some side-channel attacks. + * + * This protection introduces a dependency of the ECP module on one of the + * DRBG or SHA modules (HMAC-DRBG, CTR-DRBG, SHA-512 or SHA-256.) For very + * constrained applications that don't require this protection (for example, + * because you're only doing signature verification, so not manipulating any + * secret, or because local/physical side-channel attacks are outside your + * threat model), it might be desirable to get rid of that dependency. + * + * \warning Enabling this option makes some uses of ECP vulnerable to some + * side-channel attacks. Only enable it if you know that's not a problem for + * your use case. + * + * Uncomment this macro to disable some counter-measures in ECP. + */ +//#define MBEDTLS_ECP_NO_INTERNAL_RNG + +/** + * \def MBEDTLS_ECP_RESTARTABLE + * + * Enable "non-blocking" ECC operations that can return early and be resumed. + * + * This allows various functions to pause by returning + * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in + * order to further progress and eventually complete their operation. This is + * controlled through mbedtls_ecp_set_max_ops() which limits the maximum + * number of ECC operations a function may perform before pausing; see + * mbedtls_ecp_set_max_ops() for more information. + * + * This is useful in non-threaded environments if you want to avoid blocking + * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. + * + * Uncomment this macro to enable restartable ECC computations. + * + * \note This option only works with the default software implementation of + * elliptic curve functionality. It is incompatible with + * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT and MBEDTLS_ECDSA_XXX_ALT. + */ +//#define MBEDTLS_ECP_RESTARTABLE + +/** + * \def MBEDTLS_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: MBEDTLS_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +//#define MBEDTLS_ECDSA_DETERMINISTIC + +/** + * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + */ +//#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + * + * Enable the ECJPAKE based ciphersuite modes in SSL / TLS. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Requires: MBEDTLS_ECJPAKE_C + * MBEDTLS_SHA256_C + * MBEDTLS_ECP_DP_SECP256R1_ENABLED + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + +/** + * \def MBEDTLS_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +//#define MBEDTLS_PK_PARSE_EC_EXTENDED + +/** + * \def MBEDTLS_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when MBEDTLS_ERROR_C is disabled + * (no effect when MBEDTLS_ERROR_C is enabled). + * + * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're + * not using mbedtls_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * mbedtls_strerror() + */ +#define MBEDTLS_ERROR_STRERROR_DUMMY + +/** + * \def MBEDTLS_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: MBEDTLS_BIGNUM_C + */ +#define MBEDTLS_GENPRIME + +/** + * \def MBEDTLS_FS_IO + * + * Enable functions that use the filesystem. + */ +//#define MBEDTLS_FS_IO + +/** + * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * mbedtls_timing_hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def MBEDTLS_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +#define MBEDTLS_NO_PLATFORM_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: MBEDTLS_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both MBEDTLS_SHA256_C and + * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. + */ +#define MBEDTLS_ENTROPY_FORCE_SHA256 + +/** + * \def MBEDTLS_ENTROPY_NV_SEED + * + * Enable the non-volatile (NV) seed file-based entropy source. + * (Also enables the NV seed read/write functions in the platform layer) + * + * This is crucial (if not required) on systems that do not have a + * cryptographic entropy source (in hardware or kernel) available. + * + * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C + * + * \note The read/write functions that are used by the entropy source are + * determined in the platform layer, and can be modified at runtime and/or + * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used. + * + * \note If you use the default implementation functions that read a seedfile + * with regular fopen(), please make sure you make a seedfile with the + * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at + * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from + * and written to or you will get an entropy source error! The default + * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE + * bytes from the file. + * + * \note The entropy collector will write to the seed file before entropy is + * given to an external source, to update it. + */ +//#define MBEDTLS_ENTROPY_NV_SEED + +/** + * \def MBEDTLS_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define MBEDTLS_MEMORY_DEBUG + +/** + * \def MBEDTLS_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define MBEDTLS_MEMORY_BACKTRACE + +/** + * \def MBEDTLS_PK_RSA_ALT_SUPPORT + * + * Support external private RSA keys (eg from a HSM) in the PK layer. + * + * Comment this macro to disable support for external private RSA keys. + */ +//#define MBEDTLS_PK_RSA_ALT_SUPPORT + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define MBEDTLS_PKCS1_V15 + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +//#define MBEDTLS_PKCS1_V21 + +/** + * \def MBEDTLS_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem + * for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define MBEDTLS_RSA_NO_CRT + +/** + * \def MBEDTLS_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +//#define MBEDTLS_SELF_TEST + +/** + * \def MBEDTLS_SHA256_SMALLER + * + * Enable an implementation of SHA-256 that has lower ROM footprint but also + * lower performance. + * + * The default implementation is meant to be a reasonnable compromise between + * performance and size. This version optimizes more aggressively for size at + * the expense of performance. Eg on Cortex-M4 it reduces the size of + * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about + * 30%. + * + * Uncomment to enable the smaller implementation of SHA256. + */ +//#define MBEDTLS_SHA256_SMALLER + +/** + * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define MBEDTLS_SSL_ALL_ALERT_MESSAGES + +/** + * \def MBEDTLS_SSL_ASYNC_PRIVATE + * + * Enable asynchronous external private key operations in SSL. This allows + * you to configure an SSL connection to call an external cryptographic + * module to perform private key operations instead of performing the + * operation inside the library. + * + */ +//#define MBEDTLS_SSL_ASYNC_PRIVATE + +/** + * \def MBEDTLS_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define MBEDTLS_SSL_DEBUG_ALL + +/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +#define MBEDTLS_SSL_ENCRYPT_THEN_MAC + +/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for Extended Master Secret, aka Session Hash + * (draft-ietf-tls-session-hash-02). + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET + +/** + * \def MBEDTLS_SSL_FALLBACK_SCSV + * + * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00). + * + * For servers, it is recommended to always enable this, unless you support + * only one version of TLS, or know for sure that none of your clients + * implements a fallback strategy. + * + * For clients, you only need this if you're using a fallback strategy, which + * is not recommended in the first place, unless you absolutely need it to + * interoperate with buggy (version-intolerant) servers. + * + * Comment this macro to disable support for FALLBACK_SCSV + */ +//#define MBEDTLS_SSL_FALLBACK_SCSV + +/** + * \def MBEDTLS_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define MBEDTLS_SSL_HW_RECORD_ACCEL + +/** + * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING + * + * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. + * + * This is a countermeasure to the BEAST attack, which also minimizes the risk + * of interoperability issues compared to sending 0-length records. + * + * Comment this macro to disable 1/n-1 record splitting. + */ +//#define MBEDTLS_SSL_CBC_RECORD_SPLITTING + +/** + * \def MBEDTLS_SSL_RENEGOTIATION + * + * Enable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Comment this to disable support for renegotiation. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * + */ +#define MBEDTLS_SSL_RENEGOTIATION + +/** + * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to enable support for SSLv2 Client Hello messages. + */ +//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def MBEDTLS_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +//#define MBEDTLS_SSL_PROTO_SSL3 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +//#define MBEDTLS_SSL_PROTO_TLS1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled). + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 / DTLS 1.0 + */ +//#define MBEDTLS_SSL_PROTO_TLS1_1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/** + * \def MBEDTLS_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0, + * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_1 + * or MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +//#define MBEDTLS_SSL_PROTO_DTLS + +/** + * \def MBEDTLS_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +//#define MBEDTLS_SSL_ALPN + +/** + * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: MBEDTLS_SSL_TLS_C + * MBEDTLS_SSL_PROTO_DTLS + * + * \warning Disabling this is often a security risk! + * See mbedtls_ssl_conf_dtls_anti_replay() for details. + * + * Comment this to disable anti-replay in DTLS. + */ +//#define MBEDTLS_SSL_DTLS_ANTI_REPLAY + +/** + * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Enable support for HelloVerifyRequest on DTLS servers. + * + * This feature is highly recommended to prevent DTLS servers being used as + * amplifiers in DoS attacks against other hosts. It should always be enabled + * unless you know for sure amplification cannot be a problem in the + * environment in which your server operates. + * + * \warning Disabling this can ba a security risk! (see above) + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +//#define MBEDTLS_SSL_DTLS_HELLO_VERIFY + +/** + * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + * + * Enable server-side support for clients that reconnect from the same port. + * + * Some clients unexpectedly close the connection and try to reconnect using the + * same source port. This needs special support from the server to handle the + * new connection securely, as described in section 4.2.8 of RFC 6347. This + * flag enables that support. + * + * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +//#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + +/** + * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT + * + * Enable support for a limit of records with bad MAC. + * + * See mbedtls_ssl_conf_dtls_badmac_limit(). + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + */ +//#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT + +/** + * \def MBEDTLS_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * Client-side, provides full support for session tickets (maintenance of a + * session store remains the responsibility of the application, though). + * Server-side, you also need to provide callbacks for writing and parsing + * tickets, including authenticated encryption and key management. Example + * callbacks are provided by MBEDTLS_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +//#define MBEDTLS_SSL_SESSION_TICKETS + +/** + * \def MBEDTLS_SSL_EXPORT_KEYS + * + * Enable support for exporting key block and master secret. + * This is required for certain users of TLS, e.g. EAP-TLS. + * + * Comment this macro to disable support for key export + */ +//#define MBEDTLS_SSL_EXPORT_KEYS + +/** + * \def MBEDTLS_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +//#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + * + * Fallback to old (pre-2.7), non-conforming implementation of the truncated + * HMAC extension which also truncates the HMAC key. Note that this option is + * only meant for a transitory upgrade period and is likely to be removed in + * a future version of the library. + * + * \warning The old implementation is non-compliant and has a security weakness + * (2^80 brute force attack on the HMAC key used for a single, + * uninterrupted connection). This should only be enabled temporarily + * when (1) the use of truncated HMAC is essential in order to save + * bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use + * the fixed implementation yet (pre-2.7). + * + * \deprecated This option is deprecated and will likely be removed in a + * future version of Mbed TLS. + * + * Uncomment to fallback to old, non-compliant truncated HMAC implementation. + * + * Requires: MBEDTLS_SSL_TRUNCATED_HMAC + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + +/** + * \def MBEDTLS_TEST_HOOKS + * + * Enable features for invasive testing such as introspection functions and + * hooks for fault injection. This enables additional unit tests. + * + * Merely enabling this feature should not change the behavior of the product. + * It only adds new code, and new branching points where the default behavior + * is the same as when this feature is disabled. + * However, this feature increases the attack surface: there is an added + * risk of vulnerabilities, and more gadgets that can make exploits easier. + * Therefore this feature must never be enabled in production. + * + * Uncomment to enable invasive tests. + */ +//#define MBEDTLS_TEST_HOOKS + +/** + * \def MBEDTLS_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define MBEDTLS_THREADING_ALT + +/** + * \def MBEDTLS_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define MBEDTLS_THREADING_PTHREAD + +/** + * \def MBEDTLS_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via mbedtls_version_check_feature(). + * + * Requires: MBEDTLS_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +#define MBEDTLS_VERSION_FEATURES + +/** + * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * \warning Depending on your PKI use, enabling this can be a security risk! + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def MBEDTLS_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +//#define MBEDTLS_X509_CHECK_KEY_USAGE + +/** + * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +//#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +#define MBEDTLS_X509_RSASSA_PSS_SUPPORT + +/** + * \def MBEDTLS_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * \warning TLS-level compression MAY REDUCE SECURITY! See for example the + * CRIME attack. Before enabling this option, you should examine with care if + * CRIME or similar exploits may be applicable to your use case. + * + * \note Currently compression can't be used with DTLS. + * + * \deprecated This feature is deprecated and will be removed + * in the next major revision of the library. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define MBEDTLS_ZLIB_SUPPORT +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +//#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/cipher.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define MBEDTLS_AES_C + +/** + * \def MBEDTLS_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. If possible, we recommend avoidng dependencies on + * it, and considering stronger ciphers instead. + * + */ +//#define MBEDTLS_ARC4_C + +/** + * \def MBEDTLS_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define MBEDTLS_ASN1_PARSE_C + +/** + * \def MBEDTLS_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +#define MBEDTLS_ASN1_WRITE_C + +/** + * \def MBEDTLS_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define MBEDTLS_BASE64_C + +/** + * \def MBEDTLS_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/rsa_internal.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define MBEDTLS_BIGNUM_C + +/** + * \def MBEDTLS_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +//#define MBEDTLS_BLOWFISH_C + +/** + * \def MBEDTLS_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +//#define MBEDTLS_CAMELLIA_C + +/** + * \def MBEDTLS_ARIA_C + * + * Enable the ARIA block cipher. + * + * Module: library/aria.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * + * MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 + */ +//#define MBEDTLS_ARIA_C + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +#define MBEDTLS_CCM_C + +/** + * \def MBEDTLS_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +#define MBEDTLS_CERTS_C + +/** + * \def MBEDTLS_CHACHA20_C + * + * Enable the ChaCha20 stream cipher. + * + * Module: library/chacha20.c + */ +#define MBEDTLS_CHACHA20_C + +/** + * \def MBEDTLS_CHACHAPOLY_C + * + * Enable the ChaCha20-Poly1305 AEAD algorithm. + * + * Module: library/chachapoly.c + * + * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C + */ +#define MBEDTLS_CHACHAPOLY_C + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define MBEDTLS_CIPHER_C + +/** + * \def MBEDTLS_CMAC_C + * + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. + * + * Module: library/cmac.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C + * + */ +//#define MBEDTLS_CMAC_C + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-based random generator. + * The CTR_DRBG generator uses AES-256 by default. + * To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above. + * + * \note To achieve a 256-bit security strength with CTR_DRBG, + * you must use AES-256 *and* use sufficient entropy. + * See ctr_drbg.h for more details. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES random number generator. + */ +#define MBEDTLS_CTR_DRBG_C + +/** + * \def MBEDTLS_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +//#define MBEDTLS_DEBUG_C + +/** + * \def MBEDTLS_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#define MBEDTLS_DES_C + +/** + * \def MBEDTLS_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_DHM_C + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +#define MBEDTLS_ECDH_C + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C + */ +#define MBEDTLS_ECDSA_C + +/** + * \def MBEDTLS_ECJPAKE_C + * + * Enable the elliptic curve J-PAKE library. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Module: library/ecjpake.c + * Caller: + * + * This module is used by the following key exchanges: + * ECJPAKE + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C + */ +//#define MBEDTLS_ECJPAKE_C + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +#define MBEDTLS_ECP_C + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +//#define MBEDTLS_ERROR_C + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#define MBEDTLS_GCM_C + +/** + * \def MBEDTLS_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: MBEDTLS_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define MBEDTLS_HAVEGE_C + +/** + * \def MBEDTLS_HKDF_C + * + * Enable the HKDF algorithm (RFC 5869). + * + * Module: library/hkdf.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the Hashed Message Authentication Code + * (HMAC)-based key derivation function (HKDF). + */ +#define MBEDTLS_HKDF_C + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +//#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_NIST_KW_C + * + * Enable the Key Wrapping mode for 128-bit block ciphers, + * as defined in NIST SP 800-38F. Only KW and KWP modes + * are supported. At the moment, only AES is approved by NIST. + * + * Module: library/nist_kw.c + * + * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_NIST_KW_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD2_C + +/** + * \def MBEDTLS_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD4_C + +/** + * \def MBEDTLS_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2 + * depending on the handshake parameters. Further, it is used for checking + * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded + * encrypted keys. + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: MBEDTLS_PLATFORM_C + * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +/** + * \def MBEDTLS_NET_C + * + * Enable the TCP and UDP over IPv6/IPv4 networking routines. + * + * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) + * and Windows. For other platforms, you'll want to disable it, and write your + * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/net_sockets.c + * + * This module provides networking routines. + */ +//#define MBEDTLS_NET_C + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +//#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define MBEDTLS_PEM_PARSE_C + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +//#define MBEDTLS_PEM_WRITE_C + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +//#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: MBEDTLS_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define MBEDTLS_PKCS11_C + +/** + * \def MBEDTLS_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * Can use: MBEDTLS_ARC4_C + * + * This module enables PKCS#12 functions. + */ +//#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_POLY1305_C + * + * Enable the Poly1305 MAC algorithm. + * + * Module: library/poly1305.c + * Caller: library/chachapoly.c + */ +#define MBEDTLS_POLY1305_C + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +//#define MBEDTLS_RIPEMD160_C + +/** + * \def MBEDTLS_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * library/rsa_internal.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS up to version 1.1, for TLS 1.2 + * depending on the handshake parameters, and for SHA1-signed certificates. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +//#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +//#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_SSL_TICKET_C + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define MBEDTLS_SSL_CLI_C + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +//#define MBEDTLS_SSL_SRV_C + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +#define MBEDTLS_SSL_TLS_C + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by + * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide + * your own implementation of the whole module by setting + * \c MBEDTLS_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +//#define MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define MBEDTLS_X509_USE_C + +/** + * \def MBEDTLS_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define MBEDTLS_X509_CRT_PARSE_C + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +#define MBEDTLS_X509_CRL_PARSE_C + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +#define MBEDTLS_X509_CSR_PARSE_C + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +#define MBEDTLS_X509_CREATE_C + +/** + * \def MBEDTLS_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +//#define MBEDTLS_X509_CRT_WRITE_C + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +//#define MBEDTLS_X509_CSR_WRITE_C + +/** + * \def MBEDTLS_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +//#define MBEDTLS_XTEA_C + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */ +//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +/*! Maximal reseed counter - indicates maximal number of +requests allowed between reseeds; according to NIST 800-90 +it is (2^48 - 1), our restriction is : (int - 0xFFFF - 0xF).*/ +#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 0xFFF0 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */ +/* HMAC_DRBG options */ +//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define MBEDTLS_ENTROPY_MAX_GATHER 144 /**< Maximum amount requested from entropy sources */ +//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ + +/* Memory buffer allocator options */ +//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ + +/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ + +/** + * \brief This macro is invoked by the library when an invalid parameter + * is detected that is only checked with #MBEDTLS_CHECK_PARAMS + * (see the documentation of that option for context). + * + * When you leave this undefined here, the library provides + * a default definition. If the macro #MBEDTLS_CHECK_PARAMS_ASSERT + * is defined, the default definition is `assert(cond)`, + * otherwise the default definition calls a function + * mbedtls_param_failed(). This function is declared in + * `platform_util.h` for the benefit of the library, but + * you need to define in your application. + * + * When you define this here, this replaces the default + * definition in platform_util.h (which no longer declares the + * function mbedtls_param_failed()) and it is your responsibility + * to make sure this macro expands to something suitable (in + * particular, that all the necessary declarations are visible + * from within the library - you can ensure that by providing + * them in this file next to the macro definition). + * If you define this macro to call `assert`, also define + * #MBEDTLS_CHECK_PARAMS_ASSERT so that library source files + * include ``. + * + * Note that you may define this macro to expand to nothing, in + * which case you don't have to worry about declarations or + * definitions. However, you will then be notified about invalid + * parameters only in non-void functions, and void function will + * just silently return early on invalid parameters, which + * partially negates the benefits of enabling + * #MBEDTLS_CHECK_PARAMS in the first place, so is discouraged. + * + * \param cond The expression that should evaluate to true, but doesn't. + */ +//#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) + +/* SSL Cache options */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ + +/** \def MBEDTLS_SSL_MAX_CONTENT_LEN + * + * Maximum length (in bytes) of incoming and outgoing plaintext fragments. + * + * This determines the size of both the incoming and outgoing TLS I/O buffers + * in such a way that both are capable of holding the specified amount of + * plaintext data, regardless of the protection mechanism used. + * + * To configure incoming and outgoing I/O buffers separately, use + * #MBEDTLS_SSL_IN_CONTENT_LEN and #MBEDTLS_SSL_OUT_CONTENT_LEN, + * which overwrite the value set by this option. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of both + * incoming and outgoing I/O buffers. + */ +#define MBEDTLS_SSL_MAX_CONTENT_LEN 3072 + +/** \def MBEDTLS_SSL_IN_CONTENT_LEN + * + * Maximum length (in bytes) of incoming plaintext fragments. + * + * This determines the size of the incoming TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option is undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of the incoming I/O buffer + * independently of the outgoing I/O buffer. + */ +//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_OUT_CONTENT_LEN + * + * Maximum length (in bytes) of outgoing plaintext fragments. + * + * This determines the size of the outgoing TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * It is possible to save RAM by setting a smaller outward buffer, while keeping + * the default inward 16384 byte buffer to conform to the TLS specification. + * + * The minimum required outward buffer size is determined by the handshake + * protocol's usage. Handshaking will fail if the outward buffer is too small. + * The specific size requirement depends on the configured ciphers and any + * certificate data which is sent during the handshake. + * + * Uncomment to set the maximum plaintext size of the outgoing I/O buffer + * independently of the incoming I/O buffer. + */ +//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING + * + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + * + * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN + * to account for a reassembled handshake message of maximum size, + * together with its reassembly bitmap. + * + * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default) + * should be sufficient for all practical situations as it allows + * to reassembly a large handshake message (such as a certificate) + * while buffering multiple smaller handshake messages. + * + */ +//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 + +//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +#define MBEDTLS_PSK_MAX_LEN 16 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ +//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,\ + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,\ + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA,\ + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ +//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ + +/** + * Allow SHA-1 in the default TLS configuration for certificate signing. + * Without this build-time option, SHA-1 support must be activated explicitly + * through mbedtls_ssl_conf_cert_profile. Turning on this option is not + * recommended because of it is possible to generate SHA-1 collisions, however + * this may be safe for legacy infrastructure where additional controls apply. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +// #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES + +/** + * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake + * signature and ciphersuite selection. Without this build-time option, SHA-1 + * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. + * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by + * default. At the time of writing, there is no practical attack on the use + * of SHA-1 in handshake signatures, hence this option is turned on by default + * to preserve compatibility with existing peers, but the general + * warning applies nonetheless: + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +/** + * Uncomment the macro to let mbed TLS use your alternate implementation of + * mbedtls_platform_zeroize(). This replaces the default implementation in + * platform_util.c. + * + * mbedtls_platform_zeroize() is a widely used function across the library to + * zero a block of memory. The implementation is expected to be secure in the + * sense that it has been written to prevent the compiler from removing calls + * to mbedtls_platform_zeroize() as part of redundant code elimination + * optimizations. However, it is difficult to guarantee that calls to + * mbedtls_platform_zeroize() will not be optimized by the compiler as older + * versions of the C language standards do not provide a secure implementation + * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to + * configure their own implementation of mbedtls_platform_zeroize(), for + * example by using directives specific to their compiler, features from newer + * C standards (e.g using memset_s() in C11) or calling a secure memset() from + * their system (e.g explicit_bzero() in BSD). + */ +//#define MBEDTLS_PLATFORM_ZEROIZE_ALT + +/** + * Uncomment the macro to let Mbed TLS use your alternate implementation of + * mbedtls_platform_gmtime_r(). This replaces the default implementation in + * platform_util.c. + * + * gmtime() is not a thread-safe function as defined in the C standard. The + * library will try to use safer implementations of this function, such as + * gmtime_r() when available. However, if Mbed TLS cannot identify the target + * system, the implementation of mbedtls_platform_gmtime_r() will default to + * using the standard gmtime(). In this case, calls from the library to + * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex + * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the + * library are also guarded with this mutex to avoid race conditions. However, + * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will + * unconditionally use the implementation for mbedtls_platform_gmtime_r() + * supplied at compile time. + */ +//#define MBEDTLS_PLATFORM_GMTIME_R_ALT + +/* \} name SECTION: Customisation configuration options */ + +/* Target and application specific configurations + * + * Allow user to override any previous default. + * + */ +#if defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +// Adding include to stdio.h to prevent warning (not finding snprintf) +#include + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external/nrf_tls/mbedtls/tls_interface.c b/external/nrf_tls/mbedtls/tls_interface.c new file mode 100644 index 0000000..4c4d94e --- /dev/null +++ b/external/nrf_tls/mbedtls/tls_interface.c @@ -0,0 +1,1111 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include "nrf_error.h" +#include "nrf_drv_rng.h" +#include "app_fifo.h" +#include "mem_manager.h" +#include "mbedtls/ssl.h" +#include "mbedtls/platform.h" +#include "mbedtls/sha256.h" +#include "mbedtls/debug.h" +#include "nrf_tls.h" +#include "nrf_assert.h" +#include "iot_timer.h" +#include "iot_errors.h" + +#if TLS_CONFIG_LOG_ENABLED + +#define NRF_LOG_MODULE_NAME TLS + +#define NRF_LOG_LEVEL TLS_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR TLS_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR TLS_CONFIG_DEBUG_COLOR + +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define TLS_LOG NRF_LOG_INFO /**< Used for getting trace of execution in the module. */ +#define TLS_ERR NRF_LOG_ERROR /**< Used for logging errors in the module. */ +#define TLS_DUMP NRF_LOG_HEXDUMP_DEBUG /**< Used for dumping octet information to get details of bond information etc. */ + +#define TLS_ENTRY() TLS_TRC(">> %s", __func__) +#define TLS_EXIT() TLS_TRC("<< %s", __func__) + +#else // TLS_CONFIG_LOG_ENABLED + +#define TLS_LOG(...) /**< Disables traces. */ +#define TLS_DUMP(...) /**< Disables dumping of octet streams. */ +#define TLS_ERR(...) /**< Disables error logs. */ + +#define TLS_ENTRY(...) +#define TLS_EXIT(...) + +#endif // TLS_CONFIG_LOG_ENABLED + +#define TIME_PERIOD_INVALID 0xFFFFFFFF /**< Identifier for invalid time period. Used for timer functions. */ + +#define TLS_MUTEX_LOCK() SDK_MUTEX_LOCK(m_tls_mutex) /**< Lock module using mutex */ +#define TLS_MUTEX_UNLOCK() SDK_MUTEX_UNLOCK(m_tls_mutex) /**< Unlock module using mutex */ + +/** + * @brief This macro is used for developer debugging. + * + * @note Not enabled normally as too many logs result and this level of detail is needed + * less frequently. + */ +#define TLS_TRC(...) + +/**@brief TLS interface. */ +typedef struct +{ + uint32_t transport_id; /**< Transport identifier provided by the application to map the TLS instance with associated transport. Set by the application on allocation. */ + nrf_tls_output_t output_fn; /**< Output function registered by the application to write TLS data on the transport. */ + app_fifo_t input_fifo; /**< Input FIFO used for queueing up data received from the transport. Data on the transport us*/ + app_fifo_t output_fifo; /**< Output FIFO used for queueing up decrypted data received on the TLS interface. */ + mbedtls_ssl_context context; /**< SSL context used by mBedTLS for managing the TLS instance. */ + mbedtls_ssl_config conf; /**< Pointer to the configuration paramaters used for the instance. Memory is allocated on nrf_tls_alloc. */ +#ifdef MBEDTLS_X509_CRT_PARSE_C + mbedtls_pk_context pkey; /**< Private key information. Used only when own certificate is provided. */ + mbedtls_x509_crt * p_owncert; /**< Own parsed certificate. */ + mbedtls_x509_crt * p_cacert; /**< CA's parsed certificate. */ +#endif // MBEDTLS_X509_CRT_PARSE_C + /**@brief Timer management used to provide timeouts to the TLS library. */ + uint32_t start_tick; /**< Indicator (in milliseconds) of when the timeout was requested. */ + uint32_t intrmediate_delay; /**< Period indicating intermediate timeout period in milliseconds. */ + uint32_t final_delay; /**< Final timeout period in milliseconds. */ +} interface_t; + + +#ifdef MBEDTLS_X509_CRT_PARSE_C + +/**@brief Input buffer size used for the input FIFO. + * + * @note For ECDHE-RSA, though the context length is set to a value smaller than 3072, a buffer size + * of 4k is needed for the cloud sends a certificate that does not fit the size. + * Also configuration of input FIFO is possible in powers of 2 therefore tuning this value to + * a smaller FIFO size to exactly the size of certificate size is not possible. + */ +#define INPUT_BUFFER_SIZE 4096 + +#endif // MBEDTLS_X509_CRT_PARSE_C + +/**@brief Input buffer size when certificates are not used. */ +#ifndef INPUT_BUFFER_SIZE +#define INPUT_BUFFER_SIZE MBEDTLS_SSL_MAX_CONTENT_LEN +#endif // INPUT_BUFFER_SIZE + +/**@brief Output buffer size. + * + * @note Limiting to 1024 instead of MBEDTLS_SSL_MAX_CONTENT_LEN due to RAM constraints. + */ +#define OUTPUT_BUFFER_SIZE 1024 + + +static interface_t * m_interface[NRF_TLS_MAX_INSTANCE_COUNT]; /**< Interface table to manage the interfaces. */ +static uint8_t m_input_buffer[INPUT_BUFFER_SIZE * NRF_TLS_MAX_INSTANCE_COUNT]; /**< Input buffer that is statically reserved. */ +SDK_MUTEX_DEFINE(m_tls_mutex) /**< Mutex variable. Currently unused, this declaration does not occupy any space in RAM. */ + + +/**@brief Initializes the interface. + * + * @param[in] index Identifies instance in m_interface table to be initialized. + */ +static __INLINE void interface_init(uint32_t index) +{ + m_interface[index] = NULL; +} + + +/**@brief Wrapper function to avoid GCC errors with incompatible parameters. + * + * @param[in] n Number of blocks to be allocated. + * @param[in] s Size of each block to be assigned. + * + * @retval Pointer to memory block if procedure succeeded. + * @retval NULL if procedure failed. + */ +static __INLINE void * wrapper_calloc(size_t n, size_t s) +{ + return nrf_calloc(n,s); +} + + +/**@brief Frees an allocated interface instance. + * + * @param[in] p_instance Identifies the interface instance to be freed. + */ +static void interface_free(uint32_t index) +{ + interface_t * const p_interface = m_interface[index]; + + if (p_interface != NULL) + { + nrf_free(p_interface->input_fifo.p_buf); + nrf_free(p_interface->output_fifo.p_buf); +#ifdef MBEDTLS_X509_CRT_PARSE_C + nrf_free(p_interface->p_cacert); + nrf_free(p_interface->p_owncert); +#endif // MBEDTLS_X509_CRT_PARSE_C + + mbedtls_ssl_config_free(&p_interface->conf); + mbedtls_ssl_config_init(&p_interface->conf); + + mbedtls_ssl_free(&p_interface->context); + + nrf_free(p_interface); + } + interface_init(index); +} + + +/**@brief Allocates an interface instance. + * + * @param[inout] p_instance Provides transport identifier for the TLS instance. + * And if procedure was successful, will conatin allocated TLS instance identifier. + * @param[in] p_options TLS options to be used for the instance. + * + * @retval NRF_SUCCESS if the procedure was successful, else an error code indicating reason + ( for failure. + */ +static uint32_t interface_alloc(nrf_tls_instance_t * p_instance, + nrf_tls_options_t const * p_options) +{ + uint32_t index; + uint32_t err_code = NRF_TLS_NO_FREE_INSTANCE; + interface_t * p_interface = NULL; + + TLS_ENTRY(); + + // Allocate memory for the TLS instance. + for (index = 0; index < NRF_TLS_MAX_INSTANCE_COUNT; index++) + { + if (m_interface[index] == NULL) + { + err_code = (NRF_ERROR_NO_MEM | IOT_TLS_ERR_BASE); + + // Check if we have space to book keep the instance information. + p_interface = nrf_malloc(sizeof(interface_t)); + + m_interface[index] = p_interface; + break; + } + } + + if ((index < NRF_TLS_MAX_INSTANCE_COUNT) && (p_interface != NULL)) + { + // Initialize the memory holding the structure. + memset(p_interface, 0, sizeof(interface_t)); + + p_interface->output_fn = p_options->output_fn; + + // Found free instance. Allocate memory for input and output queues. + uint8_t * p_input_memory = &m_input_buffer[INPUT_BUFFER_SIZE * index]; + uint8_t * p_output_memory = (uint8_t *)nrf_malloc(OUTPUT_BUFFER_SIZE); + + TLS_LOG("Input memory address %p", p_input_memory); + TLS_LOG("Output memory address %p", p_output_memory); + + if (p_output_memory != NULL) + { + // Initialize the instance. + err_code = app_fifo_init(&p_interface->input_fifo, + p_input_memory, + INPUT_BUFFER_SIZE); + + TLS_LOG("Input FIFO init result %08lx", err_code); + + if (err_code == NRF_SUCCESS) + { + err_code = app_fifo_init(&p_interface->output_fifo, + p_output_memory, + OUTPUT_BUFFER_SIZE); + + TLS_LOG("Output FIFO init result %08lx", err_code); + } + + if (err_code == NRF_SUCCESS) + { + // All prerequisites for using the instance met. + // Procedure was successful. + p_interface->transport_id = p_instance->transport_id; + p_instance->instance_id = index; + } + else + { + err_code = (NRF_ERROR_INTERNAL | IOT_TLS_ERR_BASE); + } + } + + if (err_code != NRF_SUCCESS) + { + TLS_ERR("Allocation failed - Initialization procedures."); + interface_free(index); + } + } + else + { + TLS_ERR("Allocation failed - Inadequate memory."); + } + + return err_code; +} + + +/**@brief Transport read function registered with the TLS library. + * + * @details Data read on the transport is fed to the interface using the nrf_tls_input function. + * The TLS library requests the data based on state of SSL connection. + * + * @param[in] p_ctx Context registered with the library on creation of the TLS instance. + * @param[out] p_buffer Buffer where read data is fetched. + * @param[in] size Size to be read. + * + * @retval size of data read if procedure was successful. + * @retval MBEDTLS_ERR_SSL_CONN_EOF indicating there is not enough data received on the transport. + */ +static int interface_transport_read(void * p_ctx, + unsigned char * p_buffer, + size_t buffer_size) +{ + uint32_t err_code; + uint32_t length = buffer_size; + interface_t * const p_interface = m_interface[(uint32_t)p_ctx]; + uint32_t available_size = 0; + + TLS_MUTEX_LOCK(); + + TLS_TRC("[%p]: interface_transport_read requested %08x", + p_interface, + buffer_size); + + // Verify how much data is available in the queue. + err_code = app_fifo_read(&p_interface->input_fifo, NULL, &available_size); + + TLS_TRC("[%p]: interface_transport_read, app_fifo_read result %ld", + p_interface, + err_code); + + // For datagram connection, read all that is available. + // For stream sockets, read only if available data is at least as much as requested. + if (( (p_interface->conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) && + (available_size > 0) )|| + ( (p_interface->conf.transport == MBEDTLS_SSL_TRANSPORT_STREAM) && + (available_size >= buffer_size)) ) + { + TLS_TRC("[%p]: interface_transport_read requested 0x%08x, available %08lx.", + p_interface, + buffer_size, + available_size); + + err_code = app_fifo_read(&p_interface->input_fifo, p_buffer, &length); + + if (err_code == NRF_SUCCESS) + { + TLS_TRC("[%p]: interface_transport_read success, length 0x%08lx.", + p_interface, + length); + + TLS_TRC("[NRF TLS]: ---------------- SSL Read data --------------"); + TLS_DUMP(p_buffer, length); + TLS_TRC("[NRF TLS]: -------------------- End ------------------"); + + TLS_MUTEX_UNLOCK(); + + return length; + } + } + else + { + TLS_TRC("[%p]: interface_transport_read requested size 0x%08x, " + "available 0x%08lx.", + p_interface, + buffer_size, + available_size); + } + + TLS_MUTEX_UNLOCK(); + + return MBEDTLS_ERR_SSL_CONN_EOF; +} + + +/**@brief Write function that the TLS library calls to write on the transport. + * + * @param[in] p_ctx Context registered with the library on creation of the TLS instance. + * @param[in] p_buf Buffer containing data to be written on the transport. + * @param[in] len Length of data to be written. + * + * @retval length of data written on the transport if the procedure was successful. + * @retval MBEDTLS_ERR_SSL_CONN_EOF in case the procedure failed. + */ +static int interface_transport_write(void * p_ctx, + const unsigned char * p_buf, + size_t len) +{ + int op_len = len; + interface_t * const p_interface = m_interface[(uint32_t)p_ctx]; + + TLS_MUTEX_LOCK(); + + const nrf_tls_instance_t handle = { + .transport_id = p_interface->transport_id, + .instance_id = (uint32_t)p_ctx + }; + + TLS_TRC("[%p]: interface_transport_write requested 0x%08x", + p_interface, len); + + TLS_MUTEX_UNLOCK(); + + uint32_t err_code = p_interface->output_fn(&handle, (uint8_t *)p_buf, len); + + TLS_MUTEX_LOCK(); + + if (err_code != NRF_SUCCESS) + { + op_len = MBEDTLS_ERR_SSL_CONN_EOF; + } + + TLS_MUTEX_UNLOCK(); + + return op_len; +} + + +/** + * @brief Random number generator registered with the TLS library to create random numbers + * when needed. + * + * @param[in] p_ctx Context registered with the library on creation of the TLS instance. + * @param[out] p_buffer Buffer where generated random vector is to be fetched. + * @param[in] size Requested size of the random vector. + * + * @retval 0 when procedure is successful. + * + * @note This loop is time critical when available is less than requested size. + */ +static int random_vector_generate(void * p_ctx, + unsigned char * p_buffer, + size_t size) +{ + uint8_t available = 0; + + ASSERT(size <= RNG_CONFIG_POOL_SIZE); + + while (available < size) + { + nrf_drv_rng_bytes_available(&available); + + TLS_TRC(">> random_vector_generate, requested 0x%08lx, available 0x%08x", + size, + available); + } + + UNUSED_RETURN_VALUE(nrf_drv_rng_rand(p_buffer, size)); + + return 0; +} + + +/**@brief Routine called periodically to advance the SSL context state. + * + * @param[in] p_instance Provides transport identifier for the TLS instance. + */ +static void interface_continue(interface_t * p_interface) +{ + uint8_t * data = nrf_malloc(OUTPUT_BUFFER_SIZE); + + if (data != NULL) + { + int len; + + TLS_MUTEX_UNLOCK(); + + len = mbedtls_ssl_read(&p_interface->context, &data[0], OUTPUT_BUFFER_SIZE); + + TLS_MUTEX_LOCK(); + + TLS_TRC("[%p]: mbedtls_ssl_read result(len) 0x%08lx", + p_interface, + len); + + if (len > 0) + { + uint32_t write_len = len; + + uint32_t err_code = app_fifo_write(&p_interface->output_fifo, data, &write_len); + if (err_code != NRF_SUCCESS) + { + TLS_LOG("Failed to write decrypted data."); + } + } + + nrf_free(data); + } +} + + +/**@brief Debug log funciton registered with the TLS library. + * + * @param[in] p_ctx Context registered with the library on creation of the TLS instance. + * @param[in] level Debug level of the log. + * @param[in] p_file File requesting the log. + * @param[in] line Line number in the file requesting the log. + * @param[in] p_str String containing the log message. + */ +static void mbedtls_log(void * p_ctx, + int level, + const char * p_file, + int line, + const char * p_str) +{ + TLS_LOG("[%s]:[%d]: %s", &p_file[strlen(p_file)-12], line, p_str); +} + + +/**@brief Function registered with TLS library to set (start/stop) timer. + * + * @param[in] p_ctx Context registered with the library on creation of the TLS instance. + * @param[in] int_ms Intermediate timeout period in milliseconds. + * @param[in] fin_ms Finaly timout period in milliseconds. + * Value of zero indicates a request to stop the timer. + */ +static void tls_set_timer(void * p_ctx, + uint32_t int_ms, + uint32_t fin_ms) +{ + TLS_MUTEX_LOCK(); + + interface_t * const p_interface = m_interface[(uint32_t)p_ctx]; + + if (fin_ms > 0) + { + TLS_TRC("[%p]: set_timer, start %d, final %d, intermediate %d", + p_interface, + p_interface->start_tick, + p_interface->final_delay, + p_interface->intrmediate_delay); + + uint32_t err_code = iot_timer_wall_clock_get(&p_interface->start_tick); + + if (err_code == NRF_SUCCESS) + { + p_interface->final_delay = fin_ms; + p_interface->intrmediate_delay = int_ms; + } + } + else + { + p_interface->start_tick = TIME_PERIOD_INVALID; + p_interface->final_delay = TIME_PERIOD_INVALID; + p_interface->intrmediate_delay = 0; + } + + TLS_MUTEX_UNLOCK(); +} + + +/**@brief Function registered with TLS library to get the status of the timer. + * + * @param[in] p_ctx Context registered with the library on creation of the TLS instance. + * + * @retval -1 if timer is cancelled + * @retval 0 if none of the delays is expired + * @retval 1 if the intermediate delay only is expired + * @retval 2 if the final delay is expired + */ +static int tls_get_timer(void * p_ctx) +{ + int retval = 0; + + TLS_MUTEX_LOCK(); + + iot_timer_time_in_ms_t elapsed_time; + interface_t * const p_interface = m_interface[(uint32_t)p_ctx]; + + uint32_t err_code = iot_timer_wall_clock_delta_get(&p_interface->start_tick, &elapsed_time); + + TLS_TRC("[%p]: get_timer, start %d, final %d, intermediate %d, elapsed %d", + p_interface, + p_interface->start_tick, + p_interface->final_delay, + p_interface->intrmediate_delay, + elapsed_time); + + if (err_code == NRF_SUCCESS) + { + if (p_interface->final_delay <= elapsed_time) + { + retval = 2; + } + else if (p_interface->intrmediate_delay <= elapsed_time) + { + retval = 1; + } + else if ((p_interface->intrmediate_delay == TIME_PERIOD_INVALID) && + (p_interface->final_delay == TIME_PERIOD_INVALID)) + { + retval = -1; + } + } + + TLS_MUTEX_UNLOCK(); + + return retval; +} + + +/**@brief Prints/displays the configuration of the interface. Used for debugging purposes. + * + * @param[in] p_interface Identifies the instance whose ssl configuration is to be printed. + */ +static void interface_conf_debug_print(interface_t * p_interface) +{ + + TLS_TRC("[%p] SSL Conf", p_interface); + + for (int i = 0; i < 4; i++) + { + TLS_TRC("\t Cipger Suites : %02d", i); + TLS_TRC("\t\t\tCiphersuite[0] = %02d", p_interface->conf.ciphersuite_list[i][0]); + TLS_TRC("\t\t\tCiphersuite[1] = %02d", p_interface->conf.ciphersuite_list[i][1]); + TLS_TRC("\t\t\tCiphersuite[2] = %02d", p_interface->conf.ciphersuite_list[i][2]); + TLS_TRC("\t\t\tCiphersuite[3] = %02d", p_interface->conf.ciphersuite_list[i][3]); + } + + TLS_TRC("\t\tf_dbg = %p", p_interface->conf.f_dbg); + TLS_TRC("\t\tp_dbg = %p", p_interface->conf.p_dbg); + + TLS_TRC("\t\tf_rng = %p", p_interface->conf.f_rng); + TLS_TRC("\t\tp_rng = %p", p_interface->conf.p_rng); + + TLS_TRC("\t\tf_get_cache = %p", p_interface->conf.f_get_cache); + TLS_TRC("\t\tf_set_cache = %p", p_interface->conf.f_set_cache); + TLS_TRC("\t\tf_set_cache = %p", p_interface->conf.p_cache); + + TLS_TRC("\t\tf_vrfy = %p", p_interface->conf.f_vrfy); + TLS_TRC("\t\tp_vrfy = %p", p_interface->conf.p_vrfy); + + TLS_TRC("\t\tcert_profile = %p", p_interface->conf.cert_profile); + TLS_TRC("\t\tkey_cert = %p", p_interface->conf.key_cert); + TLS_TRC("\t\tca_chain = %p", p_interface->conf.ca_chain); + TLS_TRC("\t\tca_crl = %p", p_interface->conf.ca_crl); + + TLS_TRC("\t\tmax_major_ver = %2d", p_interface->conf.max_major_ver); + TLS_TRC("\t\tmax_minor_ver = %2d", p_interface->conf.max_minor_ver); + TLS_TRC("\t\tmin_major_ver = %2d", p_interface->conf.min_major_ver); + TLS_TRC("\t\tmax_major_ver = %2d", p_interface->conf.max_major_ver); +} + + +/**@brief Sets up own certificate on the interface instance. + * + * @param[in] p_interface TLS interface instance for which the procedure is requested. + * @param[in] p_own Supplies own certifcate setup information. + * + * @retval NRF_SUCCESS if the procedure was successful, else an error code indicating reason for + * failure. + */ +static uint32_t own_certificate_set(interface_t * const p_interface, + nrf_tls_certificate_t const * p_own) +{ +#ifdef MBEDTLS_X509_CRT_PARSE_C + uint32_t error_code = (NRF_ERROR_NO_MEM | IOT_TLS_ERR_BASE); + + int result; + + p_interface->p_owncert = nrf_malloc(sizeof(mbedtls_x509_crt)); + + if (p_interface->p_owncert) + { + mbedtls_x509_crt_init(p_interface->p_owncert); + + result = mbedtls_x509_crt_parse(p_interface->p_owncert, + p_own->p_certificate, + p_own->certificate_len); + + if (result == 0) + { + mbedtls_pk_init(&p_interface->pkey); + + result = mbedtls_pk_parse_key(&p_interface->pkey, + p_own->p_private_key, + p_own->private_key_len, + NULL, + 0 ); + + result = mbedtls_ssl_conf_own_cert(&p_interface->conf, + p_interface->p_owncert, + &p_interface->pkey); + if (result == 0) + { + error_code = NRF_SUCCESS; + } + else + { + error_code = NRF_TLS_OWN_CERT_SETUP_FAILED; + } + } + else + { + error_code = NRF_TLS_OWN_CERT_SETUP_FAILED; + } + } + + return error_code; +#else + return NRF_SUCCESS; +#endif // MBEDTLS_X509_CRT_PARSE_C +} + + +/**@brief Sets up verification option for the interfce, + * + * @param[in] p_interface TLS interface instance for which the procedure is requested. + * @param[in] p_settings Key setting supplying CA PEM file. + * + * @retval NRF_SUCCESS if the procedure was successful, else an error code indicating reason for + * failure. + */ +static uint32_t verify_options_set(interface_t * const p_interface, + nrf_tls_key_settings_t const * p_settings) +{ + uint32_t err_code = NRF_SUCCESS; + +#ifdef MBEDTLS_X509_CRT_PARSE_C + if ((p_settings != NULL) && (p_settings->p_ca_cert_pem != NULL)) + { + mbedtls_ssl_conf_authmode(&p_interface->conf, MBEDTLS_SSL_VERIFY_REQUIRED ); + + p_interface->p_cacert = nrf_malloc(sizeof(mbedtls_x509_crt)); + + if (p_interface->p_cacert != NULL) + { + // Initialize ca certificate. + mbedtls_x509_crt_init(p_interface->p_cacert); + + int result = mbedtls_x509_crt_parse(p_interface->p_cacert, + p_settings->p_ca_cert_pem, + p_settings->ca_cert_pem_len); + if (result >= 0) + { + mbedtls_ssl_conf_ca_chain(&p_interface->conf, p_interface->p_cacert, NULL); + } + else + { + err_code = NRF_TLS_INVALID_CA_CERTIFICATE; + } + } + else + { + err_code = (NRF_ERROR_NO_MEM | IOT_TLS_ERR_BASE); + } + } + else +#endif // MBEDTLS_X509_CRT_PARSE_C + { + mbedtls_ssl_conf_authmode(&p_interface->conf, MBEDTLS_SSL_VERIFY_NONE); + } + + return err_code; +} + + +/**@brief Sets up the configuration for SSL context according to the options specificed. + * + * @param[in] instance_id Identifies the TLS instance for which the procedure is requested. + * @param[in] p_options Supplies options to be used for the configuration. + * + * @retval NRF_SUCCESS if the procedure was successful, else an error indicating reason + * for failure. + */ +static uint32_t interface_conf_setup(uint32_t instance_id, + nrf_tls_options_t const * p_options) +{ + int result; + interface_t * p_interface = m_interface[instance_id]; + uint32_t err_code = NRF_TLS_CONFIGURATION_FAILED; + + mbedtls_ssl_config_init(&p_interface->conf); + + result = mbedtls_ssl_config_defaults(&p_interface->conf, + p_options->role, + p_options->transport_type, + MBEDTLS_SSL_PRESET_DEFAULT); + + mbedtls_ssl_conf_rng(&p_interface->conf, random_vector_generate, NULL); + mbedtls_ssl_conf_dbg(&p_interface->conf, mbedtls_log, NULL); + + TLS_TRC("[%p]: mbedtls_ssl_config_defaults result %08lx", p_interface, result); + +#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + if (result == 0) + { + if ((p_options->p_key_settings != NULL) && (p_options->p_key_settings->p_psk != NULL)) + { + result = mbedtls_ssl_conf_psk(&p_interface->conf, + p_options->p_key_settings->p_psk->p_secret_key, + p_options->p_key_settings->p_psk->secret_key_len, + p_options->p_key_settings->p_psk->p_identity, + p_options->p_key_settings->p_psk->identity_len); + } + } +#endif // MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + + if (result == 0) + { + if (p_options->p_key_settings->p_own_certificate != NULL) + { + err_code = own_certificate_set(p_interface, + p_options->p_key_settings->p_own_certificate); + } + else + { + err_code = NRF_SUCCESS; + } + } + + if (err_code == NRF_SUCCESS) + { + err_code = verify_options_set(p_interface, p_options->p_key_settings); + } + +#ifdef MBEDTLS_SSL_PROTO_DTLS + if (err_code == NRF_SUCCESS) + { + if (p_interface->conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) + { + mbedtls_ssl_conf_min_version(&p_interface->conf, + MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_3); + + mbedtls_ssl_conf_max_version(&p_interface->conf, + MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_3); + + if (p_options->transport_type == MBEDTLS_SSL_TRANSPORT_DATAGRAM) + { + mbedtls_ssl_conf_handshake_timeout(&p_interface->conf, + (MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2), + (MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2)); + } + } + } +#endif // MBEDTLS_SSL_PROTO_DTLS + + interface_conf_debug_print(p_interface); + + return err_code; +} + + +/**@brief Sets up the SSL context according to the options specificed. + * + * @param[in] instance_id Identifies the TLS instance for which the procedure is requested. + * + * @retval NRF_SUCCESS if the procedure was successful, else an error indicating reason for + * failure. + * + * @note For client roles, handshake prcoedure is initiated here. + */ +static uint32_t interface_ssl_context_setup(uint32_t instance_id) +{ + int result; + interface_t * p_interface = m_interface[instance_id]; + + TLS_TRC("[%p]: Major number: 0x%08lx Minor number: 0x%08lx", + p_interface->conf, + p_interface->conf.min_major_ver, + p_interface->conf.min_minor_ver); + + mbedtls_ssl_init(&p_interface->context); + + result = mbedtls_ssl_setup(&p_interface->context, &p_interface->conf); + + TLS_LOG("mbedtls_ssl_setup result %d",result); + + if (result == 0) + { + //ssl_set_ciphersuites(&p_interface->context, default_ciphers); + mbedtls_ssl_set_bio(&p_interface->context, + (void *)instance_id, + interface_transport_write, + interface_transport_read, + NULL); + + if (p_interface->conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) + { + mbedtls_ssl_set_timer_cb(&p_interface->context, + (void *)instance_id, + tls_set_timer, + tls_get_timer); + } + + TLS_MUTEX_UNLOCK(); + + result = mbedtls_ssl_handshake(&p_interface->context); + + TLS_MUTEX_LOCK(); + + TLS_LOG("mbedtls_ssl_handshake result %d", result); + + if (result == MBEDTLS_ERR_SSL_CONN_EOF) + { + result = 0; + } + } + + return (result ? (NRF_ERROR_INTERNAL | IOT_TLS_ERR_BASE) : NRF_SUCCESS); +} + + +uint32_t nrf_tls_init(void) +{ + uint32_t index = 0; + + SDK_MUTEX_INIT(m_tls_mutex); + + for (index = 0; index < NRF_TLS_MAX_INSTANCE_COUNT; index++) + { + interface_init(index); + } + + UNUSED_RETURN_VALUE(mbedtls_platform_set_calloc_free(wrapper_calloc, nrf_free)); + +#ifdef MBEDTLS_DEBUG_C + mbedtls_debug_set_threshold(2); +#endif // MBEDTLS_DEBUG_C + + UNUSED_RETURN_VALUE(nrf_drv_rng_init(NULL)); + + return NRF_SUCCESS; +} + + +uint32_t nrf_tls_alloc(nrf_tls_instance_t * p_instance, + nrf_tls_options_t const * p_options) +{ + uint32_t err_code = (NRF_ERROR_NO_MEM | IOT_TLS_ERR_BASE); + + TLS_MUTEX_LOCK(); + + err_code = interface_alloc(p_instance, p_options); + + if (err_code == NRF_SUCCESS) + { + err_code = interface_conf_setup(p_instance->instance_id, p_options); + } + + if (err_code == NRF_SUCCESS) + { + err_code = interface_ssl_context_setup(p_instance->instance_id); + } + + if (err_code != NRF_SUCCESS) + { + interface_free(p_instance->instance_id); + } + + TLS_MUTEX_UNLOCK(); + + return err_code; +} + + +uint32_t nrf_tls_input(nrf_tls_instance_t const * p_instance, + uint8_t const * p_data, + uint32_t datalen) +{ + + uint32_t actual_size = 0; + uint32_t err_code = (NRF_ERROR_NOT_FOUND | IOT_TLS_ERR_BASE); + + TLS_MUTEX_LOCK(); + + if ((p_instance->instance_id < NRF_TLS_MAX_INSTANCE_COUNT) && + (m_interface[p_instance->instance_id] != NULL)) + { + interface_t * const p_interface = m_interface[p_instance->instance_id]; + + // Verify all data can be queued in the FIFO. + err_code = app_fifo_write(&p_interface->input_fifo, NULL, &actual_size); + if (err_code == NRF_SUCCESS) + { + // Avoid partial write. + if (datalen <= actual_size) + { + actual_size = datalen; + + err_code = app_fifo_write(&p_interface->input_fifo, p_data, &actual_size); + + TLS_TRC("[%p]: >> nrf_tls_input datalen 0x%08lx result 0x%08lx", + p_interface, + datalen, + err_code); + } + else + { + TLS_LOG("[%p]: Failed to queue input. " + "Available 0x%08lx, requested 0x%08lx", + p_interface, + actual_size, + datalen); + } + + interface_continue(p_interface); + } + else + { + // Not enough room in the FIFO, indicate error. + err_code = (NRF_ERROR_NO_MEM | IOT_TLS_ERR_BASE); + } + } + + TLS_MUTEX_UNLOCK(); + + return err_code; +} + + +uint32_t nrf_tls_read(nrf_tls_instance_t const * p_instance, + uint8_t * p_data, + uint32_t * p_datalen) +{ + uint32_t err_code = (NRF_ERROR_NOT_FOUND | IOT_TLS_ERR_BASE); + + TLS_MUTEX_LOCK(); + + if ((p_instance->instance_id < NRF_TLS_MAX_INSTANCE_COUNT) && + (m_interface[p_instance->instance_id] != NULL)) + { + interface_t * const p_interface = m_interface[p_instance->instance_id]; + + err_code = app_fifo_read(&p_interface->output_fifo, p_data, p_datalen); + } + + TLS_MUTEX_UNLOCK(); + + return err_code; +} + + +uint32_t nrf_tls_write(nrf_tls_instance_t const * p_instance, + uint8_t const * p_data, + uint32_t * p_datalen) +{ + uint32_t err_code = (NRF_ERROR_NOT_FOUND | IOT_TLS_ERR_BASE); + + TLS_MUTEX_LOCK(); + + if ((p_instance->instance_id < NRF_TLS_MAX_INSTANCE_COUNT) && + (m_interface[p_instance->instance_id] != NULL)) + { + interface_t * const p_interface = m_interface[p_instance->instance_id]; + + int actual_len = (*p_datalen); + + TLS_MUTEX_UNLOCK(); + + actual_len = mbedtls_ssl_write(&p_interface->context, p_data, actual_len); + + TLS_MUTEX_LOCK(); + + if (actual_len < 0) + { + err_code = (NRF_ERROR_INTERNAL | IOT_TLS_ERR_BASE); + + if (actual_len == MBEDTLS_ERR_SSL_CONN_EOF) + { + if (p_interface->context.state < MBEDTLS_SSL_HANDSHAKE_OVER) + { + err_code = NRF_TLS_HANDSHAKE_IN_PROGRESS; + } + } + } + else + { + (* p_datalen) = actual_len; + err_code = NRF_SUCCESS; + } + } + + TLS_MUTEX_UNLOCK(); + + return err_code; +} + + +uint32_t nrf_tls_free(nrf_tls_instance_t const * p_instance) +{ + uint32_t err_code = (NRF_ERROR_NOT_FOUND | IOT_TLS_ERR_BASE); + + TLS_MUTEX_LOCK(); + + if ((p_instance->instance_id < NRF_TLS_MAX_INSTANCE_COUNT) && + (m_interface[p_instance->instance_id] != NULL)) + { + interface_free(p_instance->instance_id); + err_code = NRF_SUCCESS; + } + + TLS_MUTEX_UNLOCK(); + + return err_code; +} + + +void nrf_tls_process(void) +{ + uint32_t index; + + TLS_MUTEX_LOCK(); + + for (index = 0; index < NRF_TLS_MAX_INSTANCE_COUNT; index++) + { + if (m_interface[index] != NULL) + { + interface_continue(m_interface[index]); + } + } + + TLS_MUTEX_UNLOCK(); +} diff --git a/external/nrf_tls/nrf_tls.h b/external/nrf_tls/nrf_tls.h new file mode 100644 index 0000000..a3c0ff7 --- /dev/null +++ b/external/nrf_tls/nrf_tls.h @@ -0,0 +1,307 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file nrf_tls.h + * + * @defgroup iot_nrf_tls TLS on nRF5x + * @ingroup iot_sdk_common + * @{ + * @brief TLS interface on nRF5x. + * + * @details Defines TLS interface for securing UDP/TCP transport using DTLS/TLS respectively. + * The interface integrates TLS library with needed libraries/drivers on the nRF. + * + */ + +#ifndef NRF_TLS_H__ +#define NRF_TLS_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Maximum number of TLS instances to be supported. */ +#define NRF_TLS_INVALID_INSTANCE_IDENTIFIER 0xFFFFFFFF + +/**@brief Initializes the TLS instance. */ +#define NRF_TLS_INTSANCE_INIT(INSTANCE) \ + do \ + { \ + (INSTANCE)->transport_id = NRF_TLS_INVALID_INSTANCE_IDENTIFIER; \ + (INSTANCE)->instance_id = NRF_TLS_INVALID_INSTANCE_IDENTIFIER; \ + }while(0) + +/**@brief Transport type definitions. The type determines whether TLS or DTLS shall be used. */ +typedef enum +{ + NRF_TLS_TYPE_STREAM, /**< TCP transport, TLS to be used for the instance. */ + NRF_TLS_TYPE_DATAGRAM /**< UDP transport, DTLS to be used for the instance. */ +} nrf_transport_type_t; + +/**@brief TLS/DTLS roles definition. */ +typedef enum +{ + NRF_TLS_ROLE_CLIENT, /**< Client role. */ + NRF_TLS_ROLE_SERVER /**< Server role. */ +} nrf_tls_role_t; + +/**@brief TLS Instance identifier*/ +typedef struct +{ + uint32_t transport_id; /**< Identifies the TCP/UDP transport which is being secured. */ + uint32_t instance_id; /**< Identifies the TLS instance. */ +} nrf_tls_instance_t; + +/**@brief Information needed when using Pre-shared key ciphers. */ +typedef struct +{ + const uint8_t * p_identity; /**< Client identity. */ + const uint8_t * p_secret_key; /**< Secret Preshared Key. */ + uint16_t identity_len; /**< Length of the client identity. */ + uint16_t secret_key_len; /**< Length of the preshared key. */ +} nrf_tls_preshared_key_t; + +/**@brief Information provided when using Raw Public key ciphers. */ +typedef struct +{ + const uint8_t * p_private_key; /**< Private key. */ + const uint8_t * p_public_key; /**< Raw public key. */ + uint16_t private_key_len; /**< Length of the private key. */ + uint16_t public_key_len; /**< Length of the raw public key. */ +} nrf_tls_raw_key_t; + +/**@brief Certificate to be used when using certificates for key derivation. */ +typedef struct +{ + const uint8_t * p_private_key; /**< Private key. */ + const uint8_t * p_certificate; /**< Own certificate in PEM format. */ + uint16_t private_key_len; /**< Length of the private key. */ + uint16_t certificate_len; /**< Length of the certificate. */ +} nrf_tls_certificate_t; + +/**@brief Key settings to be used for TLS instance. */ +typedef struct +{ + nrf_tls_certificate_t * p_own_certificate; /**< Own certificate to be used for the instance. Can be NULL. */ + uint8_t * p_ca_cert_pem; /**< CA certificate in PEM formart. */ + uint16_t ca_cert_pem_len; /**< Length of the CA certificate. */ + nrf_tls_preshared_key_t * p_psk; /**< Identitiy and shared secret in case pre-shared key is used. Can be NULL. */ + nrf_tls_raw_key_t * p_raw_key; /**< Public and private key in case RAW keys are used. This method is not currently supported. */ +} nrf_tls_key_settings_t; + +/**@brief Transport write function registered for the instance. + * + * @details Function registered with the interface to write on the transport interface. + * The application shall implement the function registered here to ensure handshake + * messages and encrypted data can be written by the interface/TLS library on the + * transport. + * + * @param[in] p_instance Identifies the instance on which transport write is requested. + * Shall not be NULL. + * @param[in] p_data Pointer to data to be written on the instance. + * Shall not be NULL. + * @param[in] datalen Length of data to be written on the transport. + * + * @retval NRF_SUCCESS If the procedure was successful, else an error code indicating reason + * for failure. + */ +typedef uint32_t (*nrf_tls_output_t)(nrf_tls_instance_t const * p_instance, + uint8_t const * p_data, + uint32_t datalen); + +/**@brief Options when requesting an TLS instance. */ +typedef struct +{ + nrf_tls_output_t output_fn; /**< Function registered to deliver output of TLS operations on a TLS interface. Shall not be NULL. */ + uint8_t transport_type; /**< Indicates type of transport being secured. @ref nrf_transport_type_t for possible transports. */ + uint8_t role; /**< Indicates role to be played, server or client. @ref nrf_tls_role_t for possible roles. */ + nrf_tls_key_settings_t * p_key_settings; /**< Provide key configurations/certificates here. */ +} nrf_tls_options_t; + +/**@brief Initialize TLS interface. + * + * @details This function initializes TLS interface. Initialization includes initializing the TLS + * library, RNG driver, and any other dependencies. This API shall be called before using + * any other APIs of the interface. + * + * @retval NRF_SUCCESS If the procedure is successful, else, an error code indicating + * reason for failure. If the procedure fails, the application shall + * not proceed with using other APIs of the interface. + */ +uint32_t nrf_tls_init(void); + + +/**@brief Allocate an TLS/DTLS instance. + * + * @details This function allocates an instance for TLS/DTLS. Options indicate whether DTLS/TLS will + * be used and role is server or client. + * + * @param[inout] p_instance Instance with transport id set by the application to identify the + * transport being secured. If the procedure is successful, the + * instance id is allocated by the interface. The application is + * expected to remember the instance information for all subsequent + * procedures on the transport. + * Shall not be NULL. + * @param[in] p_options Pointer to options that indicate transport type, role, keys etc. + * Output function registered is used write TLS/DTLS data on the + * raw transport (TCP.UDP) for the instance. + * Shall not be NULL. + * @note + * + * @retval NRF_SUCCESS If the procedure is successful, else, an error code indicating + * reason for failure. If the procedure succeeds, the application + * shall use the instance allocated for all subsequent procedures on + * the instance. + */ +uint32_t nrf_tls_alloc(nrf_tls_instance_t * p_instance, + nrf_tls_options_t const * p_options); + + +/**@brief Free the TLS/DTLS instance. + * + * @details This function frees the instance allocated for TLS/DTLS. All sessions, buffered data +* related to instance are freed as well by this API. + * + * @param[in] p_instance Identifies the instance being freed. + * Shall not be NULL. + * + * @retval NRF_SUCCESS If the procedure is successful, else, an error code indicating + * reason for failure. If the procedure succeeds, the application + * shall use the instance allocated for all subsequent procedures on + * the instance. + */ +uint32_t nrf_tls_free(nrf_tls_instance_t const * p_instance); + + +/**@brief Write data on the TLS/DTLS instance. + * + * @details This function writes data on the TLS/DTLS instance. The requested data is encrypted + * and padded based on cipher configuration and selected cipher during handshake. + * If no sessions exists already with the peer, a handshake is initiated automatically + * by the interface, if the role played on the instance is a client role. Requested data to + * be written is buffered until a session is established. + * + * @param[in] p_instance Identifies the instance on which write is requested. + * Shall not be NULL. + * @param[in] p_data Pointer to data to be written on the instance. + * Shall not be NULL. + * @param[inout] p_datalen Pointer to size of data to be written. The actual size written can + * be smaller than requested and is indicated here if the procedure is + * successful. The application shall check for the actual size written + * and make subsequent requests in case the right was partial. + * Shall not be NULL. + * + * @retval NRF_SUCCESS If the procedure is successful, else, an error code indicating + * reason for failure. If the procedure succeeds, the application + * shall check for the actual size written and make subsequent + * requests in case the right was partial. + */ +uint32_t nrf_tls_write(nrf_tls_instance_t const * p_instance, + uint8_t const * p_data, + uint32_t * p_datalen); + + +/**@brief Read data from the TLS/DTLS instance. + * + * @details This function reads data from the TLS/DTLS interface. The read data is + * decrypted based on cipher configuration and selected cipher during handshake. + * If no data is available on the instance, the API indicates so with an error code. + * It is possible to request size of data that can be read by passing a NULL parameter on + * the data. + * + * @param[in] p_instance Identifies the instance on which read is requested. + * Shall not be NULL. + * @param[in] p_data Pointer to data where read data is to be copied. + * Can be NULL. In case, this parameter is NULL, size of bytes that + * are available to read is returned in the p_datalen parameter. + * @param[inout] p_datalen Pointer to size of data to be read. The application shall ensure that + * the memory pointed to by p_data parameter is the size indicated. + * The actual size read can be smaller than requested and is indicated + * here if the procedure is successful. The application should check for +* the actual size read. + * Shall not be NULL. + * + * @retval NRF_SUCCESS If the procedure is successful, else, an error code indicating + * reason for failure. If the procedure succeeds, the application + * should check for the actual size read. + */ +uint32_t nrf_tls_read(nrf_tls_instance_t const * p_instance, + uint8_t * p_data, + uint32_t * p_datalen); + + +/**@brief Function to input data read on the transport to the TLS library. + * + * @details Function to input data read on the transport to TLS library for further processing. + * Further processing could include advancing the handshake or decrypting the received + * data based on the state of TLS session. + * + * @param[in] p_instance Identifies the instance on which transport write is requested. + * Shall not be NULL. + * @param[in] p_data Pointer to data to be processed on the instance. + * Shall not be NULL. + * @param[in] datalen Length of data to be written on the transport. + * + * @retval NRF_SUCCESS If the procedure was successful, else an error code indicating reason + * for failure. + */ +uint32_t nrf_tls_input(nrf_tls_instance_t const * p_instance, + uint8_t const * p_data, + uint32_t datalen); + + +/**@brief Function to continue TLS/DTLS operation after a busy state on transport. + * + * @details The transport writes requested by the TLS interface may return failure if transport + * data flow was off. In order to resume and retry the operations, this function shall be + * called periodically. This function shall be called in order to ensure TLS interface + * and the library behaves as expected. + */ +void nrf_tls_process(void); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_TLS_H__ + +/** @} */ diff --git a/external/segger_rtt/SEGGER_RTT.c b/external/segger_rtt/SEGGER_RTT.c new file mode 100644 index 0000000..0fcbc70 --- /dev/null +++ b/external/segger_rtt/SEGGER_RTT.c @@ -0,0 +1,1744 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH & Co. KG * +* The Embedded Experts * +********************************************************************** +* * +* (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH & Co. KG * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 6.18a * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.c +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. +Revision: $Rev: 6852 $ + +Additional information: + Type "int" is assumed to be 32-bits in size + H->T Host to target communication + T->H Target to host communication + + RTT channel 0 is always present and reserved for Terminal usage. + Name is fixed to "Terminal" + + Effective buffer size: SizeOfBuffer - 1 + + WrOff == RdOff: Buffer is empty + WrOff == (RdOff - 1): Buffer is full + WrOff > RdOff: Free space includes wrap-around + WrOff < RdOff: Used space includes wrap-around + (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0): + Buffer full and wrap-around after next byte + + +---------------------------------------------------------------------- +*/ + +#include "SEGGER_RTT.h" + +#include // for memcpy + +/********************************************************************* +* +* Configuration, default values +* +********************************************************************** +*/ + +#ifndef BUFFER_SIZE_UP + #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host +#endif + +#ifndef BUFFER_SIZE_DOWN + #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) +#endif + +#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS + #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target +#endif + +#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS + #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target +#endif + +#ifndef SEGGER_RTT_BUFFER_SECTION + #if defined(SEGGER_RTT_SECTION) + #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION + #endif +#endif + +#ifndef SEGGER_RTT_ALIGNMENT + #define SEGGER_RTT_ALIGNMENT 0 +#endif + +#ifndef SEGGER_RTT_BUFFER_ALIGNMENT + #define SEGGER_RTT_BUFFER_ALIGNMENT 0 +#endif + +#ifndef SEGGER_RTT_MODE_DEFAULT + #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP +#endif + +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK() +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK() +#endif + +#ifndef STRLEN + #define STRLEN(a) strlen((a)) +#endif + +#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP + #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 +#endif + +#ifndef SEGGER_RTT_MEMCPY + #ifdef MEMCPY + #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) MEMCPY((pDest), (pSrc), (NumBytes)) + #else + #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) + #endif +#endif + +#ifndef MIN + #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX + #define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif +// +// For some environments, NULL may not be defined until certain headers are included +// +#ifndef NULL + #define NULL 0 +#endif + +/********************************************************************* +* +* Defines, fixed +* +********************************************************************** +*/ +#if (defined __ICCARM__) || (defined __ICCRX__) + #define RTT_PRAGMA(P) _Pragma(#P) +#endif + +#if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT + #if (defined __GNUC__) + #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) + #elif (defined __ICCARM__) || (defined __ICCRX__) + #define PRAGMA(A) _Pragma(#A) +#define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \ + Var + #elif (defined __CC_ARM) + #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) + #else + #error "Alignment not supported for this compiler." + #endif +#else + #define SEGGER_RTT_ALIGN(Var, Alignment) Var +#endif + +#if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION) + #if (defined __GNUC__) + #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var + #elif (defined __ICCARM__) || (defined __ICCRX__) +#define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \ + Var + #elif (defined __CC_ARM) + #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var + #else + #error "Section placement not supported for this compiler." + #endif +#else + #define SEGGER_RTT_PUT_SECTION(Var, Section) Var +#endif + + +#if SEGGER_RTT_ALIGNMENT + #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT) +#else + #define SEGGER_RTT_CB_ALIGN(Var) Var +#endif + +#if SEGGER_RTT_BUFFER_ALIGNMENT + #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT) +#else + #define SEGGER_RTT_BUFFER_ALIGN(Var) Var +#endif + + +#if defined(SEGGER_RTT_SECTION) + #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION) +#else + #define SEGGER_RTT_PUT_CB_SECTION(Var) Var +#endif + +#if defined(SEGGER_RTT_BUFFER_SECTION) + #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION) +#else + #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var +#endif + +/********************************************************************* +* +* Static const data +* +********************************************************************** +*/ + +static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + +/********************************************************************* +* +* Static data +* +********************************************************************** +*/ +// +// RTT Control Block and allocate buffers for channel 0 +// +SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT)); + +SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP])); +SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN])); + +static char _ActiveTerminal; + +/********************************************************************* +* +* Static functions +* +********************************************************************** +*/ + +/********************************************************************* +* +* _DoInit() +* +* Function description +* Initializes the control block an buffers. +* May only be called via INIT() to avoid overriding settings. +* +*/ +#define INIT() do { \ + if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ + } while (0) +static void _DoInit(void) { + SEGGER_RTT_CB* p; + // + // Initialize control block + // + p = &_SEGGER_RTT; + p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; + p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; + // + // Initialize up buffer 0 + // + p->aUp[0].sName = "Terminal"; + p->aUp[0].pBuffer = _acUpBuffer; + p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); + p->aUp[0].RdOff = 0u; + p->aUp[0].WrOff = 0u; + p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Initialize down buffer 0 + // + p->aDown[0].sName = "Terminal"; + p->aDown[0].pBuffer = _acDownBuffer; + p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); + p->aDown[0].RdOff = 0u; + p->aDown[0].WrOff = 0u; + p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Finish initialization of the control block. + // Copy Id string in three steps to make sure "SEGGER RTT" is not found + // in initializer memory (usually flash) by J-Link + // + strcpy(&p->acID[7], "RTT"); + strcpy(&p->acID[0], "SEGGER"); + p->acID[6] = ' '; +} + +/********************************************************************* +* +* _WriteBlocking() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* The caller is responsible for managing the write chunk sizes as +* _WriteBlocking() will block until all data has been posted successfully. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* >= 0 - Number of bytes written into buffer. +*/ +static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { + unsigned NumBytesToWrite; + unsigned NumBytesWritten; + unsigned RdOff; + unsigned WrOff; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + char* pDst; +#endif + // + // Write data to buffer and handle wrap-around if necessary + // + NumBytesWritten = 0u; + WrOff = pRing->WrOff; + do { + RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime + if (RdOff > WrOff) { + NumBytesToWrite = RdOff - WrOff - 1u; + } else { + NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); + } + NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around + NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + NumBytesWritten += NumBytesToWrite; + NumBytes -= NumBytesToWrite; + WrOff += NumBytesToWrite; + while (NumBytesToWrite--) { + *pDst++ = *pBuffer++; + }; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); + NumBytesWritten += NumBytesToWrite; + pBuffer += NumBytesToWrite; + NumBytes -= NumBytesToWrite; + WrOff += NumBytesToWrite; +#endif + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0u; + } + pRing->WrOff = WrOff; + } while (NumBytes); + // + return NumBytesWritten; +} + +/********************************************************************* +* +* _WriteNoCheck() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* It is callers responsibility to make sure data actually fits in buffer. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Notes +* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking +*/ +static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { + unsigned NumBytesAtOnce; + unsigned WrOff; + unsigned Rem; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + char* pDst; +#endif + + WrOff = pRing->WrOff; + Rem = pRing->SizeOfBuffer - WrOff; + if (Rem > NumBytes) { + // + // All data fits before wrap around + // +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + WrOff += NumBytes; + while (NumBytes--) { + *pDst++ = *pData++; + }; + pRing->WrOff = WrOff; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; +#endif + } else { + // + // We reach the end of the buffer, so need to wrap around + // +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + NumBytesAtOnce = Rem; + while (NumBytesAtOnce--) { + *pDst++ = *pData++; + }; + pDst = pRing->pBuffer; + NumBytesAtOnce = NumBytes - Rem; + while (NumBytesAtOnce--) { + *pDst++ = *pData++; + }; + pRing->WrOff = NumBytes - Rem; +#else + NumBytesAtOnce = Rem; + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); + NumBytesAtOnce = NumBytes - Rem; + SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytesAtOnce); + pRing->WrOff = NumBytesAtOnce; +#endif + } +} + +/********************************************************************* +* +* _PostTerminalSwitch() +* +* Function description +* Switch terminal to the given terminal ID. It is the caller's +* responsibility to ensure the terminal ID is correct and there is +* enough space in the buffer for this to complete successfully. +* +* Parameters +* pRing Ring buffer to post to. +* TerminalId Terminal ID to switch to. +*/ +static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { + char ac[2]; + + ac[0] = 0xFFu; + ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit + _WriteBlocking(pRing, ac, 2u); +} + +/********************************************************************* +* +* _GetAvailWriteSpace() +* +* Function description +* Returns the number of bytes that can be written to the ring +* buffer without blocking. +* +* Parameters +* pRing Ring buffer to check. +* +* Return value +* Number of bytes that are free in the buffer. +*/ +static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { + unsigned RdOff; + unsigned WrOff; + unsigned r; + // + // Avoid warnings regarding volatile access order. It's not a problem + // in this case, but dampen compiler enthusiasm. + // + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + if (RdOff <= WrOff) { + r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; + } else { + r = RdOff - WrOff - 1u; + } + return r; +} + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ +/********************************************************************* +* +* SEGGER_RTT_ReadNoLock() +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* Do not lock against interrupts and multiple access. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { + unsigned NumBytesRem; + unsigned NumBytesRead; + unsigned RdOff; + unsigned WrOff; + unsigned char* pBuffer; + SEGGER_RTT_BUFFER_DOWN* pRing; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + const char* pSrc; +#endif + // + INIT(); + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + pBuffer = (unsigned char*)pData; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + NumBytesRead = 0u; + // + // Read from current read position to wrap-around of buffer, first + // + if (RdOff > WrOff) { + NumBytesRem = pRing->SizeOfBuffer - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pSrc = pRing->pBuffer + RdOff; + NumBytesRead += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + while (NumBytesRem--) { + *pBuffer++ = *pSrc++; + }; +#else + SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; +#endif + // + // Handle wrap-around of buffer + // + if (RdOff == pRing->SizeOfBuffer) { + RdOff = 0u; + } + } + // + // Read remaining items of buffer + // + NumBytesRem = WrOff - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); + if (NumBytesRem > 0u) { +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pSrc = pRing->pBuffer + RdOff; + NumBytesRead += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + while (NumBytesRem--) { + *pBuffer++ = *pSrc++; + }; +#else + SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; +#endif + } + if (NumBytesRead) { + pRing->RdOff = RdOff; + } + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_Read +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { + unsigned NumBytesRead; + // + SEGGER_RTT_LOCK(); + // + // Call the non-locking read function + // + NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteWithOverwriteNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block. +* SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application +* and overwrites data if the data does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, data is overwritten. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +* (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link +* connection reads RTT data. +*/ +void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + char* pDst; +#endif + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer and copy some elements into local variables. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // Check if we will overwrite data and need to adjust the RdOff. + // + if (pRing->WrOff == pRing->RdOff) { + Avail = pRing->SizeOfBuffer - 1u; + } else if ( pRing->WrOff < pRing->RdOff) { + Avail = pRing->RdOff - pRing->WrOff - 1u; + } else { + Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; + } + if (NumBytes > Avail) { + pRing->RdOff += (NumBytes - Avail); + while (pRing->RdOff >= pRing->SizeOfBuffer) { + pRing->RdOff -= pRing->SizeOfBuffer; + } + } + // + // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds + // + Avail = pRing->SizeOfBuffer - pRing->WrOff; + do { + if (Avail > NumBytes) { + // + // Last round + // +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + pRing->WrOff; + Avail = NumBytes; + while (NumBytes--) { + *pDst++ = *pData++; + }; + pRing->WrOff += Avail; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, NumBytes); + pRing->WrOff += NumBytes; +#endif + break; + } else { + // + // Wrap-around necessary, write until wrap-around and reset WrOff + // +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + pRing->WrOff; + NumBytes -= Avail; + while (Avail--) { + *pDst++ = *pData++; + }; + pRing->WrOff = 0; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, Avail); + pData += Avail; + pRing->WrOff = 0; + NumBytes -= Avail; +#endif + Avail = (pRing->SizeOfBuffer - 1); + } + } while (NumBytes); +} + +/********************************************************************* +* +* SEGGER_RTT_WriteSkipNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteSkipNoLock does not lock the application and +* skips all data, if the data does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, all data is dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; + unsigned RdOff; + unsigned WrOff; + unsigned Rem; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + char* pDst; +#endif + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer and copy some elements into local variables. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + // + // Handle the most common cases fastest. + // Which is: + // RdOff <= WrOff -> Space until wrap around is free. + // AND + // WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary. + // + // OR + // + // RdOff > WrOff -> Space until RdOff - 1 is free. + // AND + // WrOff + NumBytes < RdOff -> Data fits into buffer + // + if (RdOff <= WrOff) { + // + // Get space until WrOff will be at wrap around. + // + Avail = pRing->SizeOfBuffer - 1u - WrOff ; + if (Avail >= NumBytes) { +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + WrOff += NumBytes; + while (NumBytes--) { + *pDst++ = *pData++; + }; + pRing->WrOff = WrOff; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; +#endif + return 1; + } + // + // If data did not fit into space until wrap around calculate complete space in buffer. + // + Avail += RdOff; + // + // If there is still no space for the whole of this output, don't bother. + // + if (Avail >= NumBytes) { + // + // OK, we have enough space in buffer. Copy in one or 2 chunks + // + Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer + if (Rem > NumBytes) { +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + WrOff += NumBytes; + while (NumBytes--) { + *pDst++ = *pData++; + }; + pRing->WrOff = WrOff; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; +#endif + } else { + // + // We reach the end of the buffer, so need to wrap around + // +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + NumBytes -= Rem; + WrOff = NumBytes; + do { + *pDst++ = *pData++; + } while (--Rem); + pDst = pRing->pBuffer; + do { + *pDst++ = *pData++; + } while (--NumBytes); + pRing->WrOff = WrOff; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, Rem); + SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytes - Rem); + pRing->WrOff = NumBytes - Rem; +#endif + } + return 1; + } + } else { + Avail = RdOff - WrOff - 1u; + if (Avail >= NumBytes) { +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + WrOff += NumBytes; + while (NumBytes--) { + *pDst++ = *pData++; + }; + pRing->WrOff = WrOff; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; +#endif + return 1; + } + } + // + // If we reach this point no data has been written + // + return 0; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteNoLock does not lock the application. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) Data is stored according to buffer flags. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + unsigned Avail; + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // How we output depends upon the mode... + // + switch (pRing->Flags) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother. + // + Avail = _GetAvailWriteSpace(pRing); + if (Avail < NumBytes) { + Status = 0u; + } else { + Status = NumBytes; + _WriteNoCheck(pRing, pData, NumBytes); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode, trim to what we can output without blocking. + // + Avail = _GetAvailWriteSpace(pRing); + Status = Avail < NumBytes ? Avail : NumBytes; + _WriteNoCheck(pRing, pData, Status); + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + Status = _WriteBlocking(pRing, pData, NumBytes); + break; + default: + Status = 0u; + break; + } + // + // Finish up. + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_Write +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) Data is stored according to buffer flags. +*/ +unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + // + INIT(); + SEGGER_RTT_LOCK(); + // + // Call the non-locking write function + // + Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteString +* +* Function description +* Stores string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* s Pointer to string. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) Data is stored according to buffer flags. +* (2) String passed to this function has to be \0 terminated +* (3) \0 termination character is *not* stored in RTT buffer +*/ +unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { + unsigned Len; + + Len = STRLEN(s); + return SEGGER_RTT_Write(BufferIndex, s, Len); +} + +/********************************************************************* +* +* SEGGER_RTT_PutCharSkipNoLock +* +* Function description +* Stores a single character/byte in SEGGER RTT buffer. +* SEGGER_RTT_PutCharSkipNoLock does not lock the application and +* skips the byte, if it does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* c Byte to be stored. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, the character is dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ + +unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) { + SEGGER_RTT_BUFFER_UP* pRing; + unsigned WrOff; + unsigned Status; + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // Get write position and handle wrap-around if necessary + // + WrOff = pRing->WrOff + 1; + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0; + } + // + // Output byte if free space is available + // + if (WrOff != pRing->RdOff) { + pRing->pBuffer[pRing->WrOff] = c; + pRing->WrOff = WrOff; + Status = 1; + } else { + Status = 0; + } + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_PutCharSkip +* +* Function description +* Stores a single character/byte in SEGGER RTT buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* c Byte to be stored. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, the character is dropped. +*/ + +unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) { + SEGGER_RTT_BUFFER_UP* pRing; + unsigned WrOff; + unsigned Status; + // + // Prepare + // + INIT(); + SEGGER_RTT_LOCK(); + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // Get write position and handle wrap-around if necessary + // + WrOff = pRing->WrOff + 1; + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0; + } + // + // Output byte if free space is available + // + if (WrOff != pRing->RdOff) { + pRing->pBuffer[pRing->WrOff] = c; + pRing->WrOff = WrOff; + Status = 1; + } else { + Status = 0; + } + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return Status; +} + + /********************************************************************* +* +* SEGGER_RTT_PutChar +* +* Function description +* Stores a single character/byte in SEGGER RTT buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* c Byte to be stored. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) Data is stored according to buffer flags. +*/ + +unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) { + SEGGER_RTT_BUFFER_UP* pRing; + unsigned WrOff; + unsigned Status; + // + // Prepare + // + INIT(); + SEGGER_RTT_LOCK(); + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // Get write position and handle wrap-around if necessary + // + WrOff = pRing->WrOff + 1; + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0; + } + // + // Wait for free space if mode is set to blocking + // + if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { + while (WrOff == pRing->RdOff) { + ; + } + } + // + // Output byte if free space is available + // + if (WrOff != pRing->RdOff) { + pRing->pBuffer[pRing->WrOff] = c; + pRing->WrOff = WrOff; + Status = 1; + } else { + Status = 0; + } + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_GetKey +* +* Function description +* Reads one character from the SEGGER RTT buffer. +* Host has previously stored data there. +* +* Return value +* < 0 - No character available (buffer empty). +* >= 0 - Character which has been read. (Possible values: 0 - 255) +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0. +*/ +int SEGGER_RTT_GetKey(void) { + char c; + int r; + + r = (int)SEGGER_RTT_Read(0u, &c, 1u); + if (r == 1) { + r = (int)(unsigned char)c; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_WaitKey +* +* Function description +* Waits until at least one character is avaible in the SEGGER RTT buffer. +* Once a character is available, it is read and this function returns. +* +* Return value +* >=0 - Character which has been read. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +* (2) This function is blocking if no character is present in RTT buffer +*/ +int SEGGER_RTT_WaitKey(void) { + int r; + + do { + r = SEGGER_RTT_GetKey(); + } while (r < 0); + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasKey +* +* Function description +* Checks if at least one character for reading is available in the SEGGER RTT buffer. +* +* Return value +* == 0 - No characters are available to read. +* == 1 - At least one character is available. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +*/ +int SEGGER_RTT_HasKey(void) { + unsigned RdOff; + int r; + + INIT(); + RdOff = _SEGGER_RTT.aDown[0].RdOff; + if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { + r = 1; + } else { + r = 0; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasData +* +* Function description +* Check if there is data from the host in the given buffer. +* +* Return value: +* ==0: No data +* !=0: Data in buffer +* +*/ +unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { + SEGGER_RTT_BUFFER_DOWN* pRing; + unsigned v; + + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + v = pRing->WrOff; + return v - pRing->RdOff; +} + +/********************************************************************* +* +* SEGGER_RTT_AllocDownBuffer +* +* Function description +* Run-time configuration of the next down-buffer (H->T). +* The next buffer, which is not used yet is configured. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. Buffer Index +* < 0 - Error +*/ +int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int BufferIndex; + + INIT(); + SEGGER_RTT_LOCK(); + BufferIndex = 0; + do { + if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) { + break; + } + BufferIndex++; + } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers); + if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) { + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; + _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + } else { + BufferIndex = -1; + } + SEGGER_RTT_UNLOCK(); + return BufferIndex; +} + +/********************************************************************* +* +* SEGGER_RTT_AllocUpBuffer +* +* Function description +* Run-time configuration of the next up-buffer (T->H). +* The next buffer, which is not used yet is configured. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. Buffer Index +* < 0 - Error +*/ +int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int BufferIndex; + + INIT(); + SEGGER_RTT_LOCK(); + BufferIndex = 0; + do { + if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) { + break; + } + BufferIndex++; + } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers); + if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) { + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; + _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + } else { + BufferIndex = -1; + } + SEGGER_RTT_UNLOCK(); + return BufferIndex; +} + +/********************************************************************* +* +* SEGGER_RTT_ConfigUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer (T->H). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. +* < 0 - Error +* +* Additional information +* Buffer 0 is configured on compile-time. +* May only be called once per buffer. +* Buffer name and flags can be reconfigured using the appropriate functions. +*/ +int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(); + if (BufferIndex > 0u) { + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; + _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_ConfigDownBuffer +* +* Function description +* Run-time configuration of a specific down-buffer (H->T). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 O.K. +* < 0 Error +* +* Additional information +* Buffer 0 is configured on compile-time. +* May only be called once per buffer. +* Buffer name and flags can be reconfigured using the appropriate functions. +*/ +int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(); + if (BufferIndex > 0u) { + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; + _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameDownBuffer +* +* Function description +* Run-time configuration of a specific Down-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetFlagsUpBuffer +* +* Function description +* Run-time configuration of specific up-buffer flags (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer. +* Flags Flags to set for the buffer. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetFlagsDownBuffer +* +* Function description +* Run-time configuration of specific Down-buffer flags (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* Flags Flags to set for the buffer. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_Init +* +* Function description +* Initializes the RTT Control Block. +* Should be used in RAM targets, at start of the application. +* +*/ +void SEGGER_RTT_Init (void) { + _DoInit(); +} + +/********************************************************************* +* +* SEGGER_RTT_SetTerminal +* +* Function description +* Sets the terminal to be used for output on channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* +* Return value +* >= 0 O.K. +* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) +*/ +int SEGGER_RTT_SetTerminal (char TerminalId) { + char ac[2]; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; + int r; + // + INIT(); + // + r = 0; + ac[0] = 0xFFU; + if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels + ac[1] = _aTerminalId[(unsigned char)TerminalId]; + pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed + SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing + if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { + _ActiveTerminal = TerminalId; + _WriteBlocking(pRing, ac, 2u); + } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes + Avail = _GetAvailWriteSpace(pRing); + if (Avail >= 2) { + _ActiveTerminal = TerminalId; // Only change active terminal in case of success + _WriteNoCheck(pRing, ac, 2u); + } else { + r = -1; + } + } + SEGGER_RTT_UNLOCK(); + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_TerminalOut +* +* Function description +* Writes a string to the given terminal +* without changing the terminal for channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* s String to be printed on the terminal. +* +* Return value +* >= 0 - Number of bytes written. +* < 0 - Error. +* +*/ +int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) { + int Status; + unsigned FragLen; + unsigned Avail; + SEGGER_RTT_BUFFER_UP* pRing; + // + INIT(); + // + // Validate terminal ID. + // + if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[0]; + // + // Need to be able to change terminal, write data, change back. + // Compute the fixed and variable sizes. + // + FragLen = STRLEN(s); + // + // How we output depends upon the mode... + // + SEGGER_RTT_LOCK(); + Avail = _GetAvailWriteSpace(pRing); + switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother switching terminals at all. + // + if (Avail < (FragLen + 4u)) { + Status = 0; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode and there is not enough space for everything, + // trim the output but always include the terminal switch. If no room + // for terminal switch, skip that totally. + // + if (Avail < 4u) { + Status = -1; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + break; + default: + Status = -1; + break; + } + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + } else { + Status = -1; + } + return Status; +} + + +/*************************** End of file ****************************/ diff --git a/external/segger_rtt/SEGGER_RTT.h b/external/segger_rtt/SEGGER_RTT.h new file mode 100644 index 0000000..8d6814b --- /dev/null +++ b/external/segger_rtt/SEGGER_RTT.h @@ -0,0 +1,251 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH & Co. KG * +* The Embedded Experts * +********************************************************************** +* * +* (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH & Co. KG * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 6.18a * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.h +Purpose : Implementation of SEGGER real-time transfer which allows + real-time communication on targets which support debugger + memory accesses while the CPU is running. +Revision: $Rev: 6849 $ +---------------------------------------------------------------------- +*/ + +#ifndef SEGGER_RTT_H +#define SEGGER_RTT_H + +#include "SEGGER_RTT_Conf.h" + +/********************************************************************* +* +* Defines, fixed +* +********************************************************************** +*/ + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ + +// +// Description for a circular buffer (also called "ring buffer") +// which is used as up-buffer (T->H) +// +typedef struct { + const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" + char* pBuffer; // Pointer to start of buffer + unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. + unsigned WrOff; // Position of next item to be written by either target. + volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. + unsigned Flags; // Contains configuration flags +} SEGGER_RTT_BUFFER_UP; + +// +// Description for a circular buffer (also called "ring buffer") +// which is used as down-buffer (H->T) +// +typedef struct { + const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" + char* pBuffer; // Pointer to start of buffer + unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. + volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. + unsigned RdOff; // Position of next item to be read by target (down-buffer). + unsigned Flags; // Contains configuration flags +} SEGGER_RTT_BUFFER_DOWN; + +// +// RTT control block which describes the number of buffers available +// as well as the configuration for each buffer +// +// +typedef struct { + char acID[16]; // Initialized to "SEGGER RTT" + int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) + int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) + SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host + SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target +} SEGGER_RTT_CB; + +/********************************************************************* +* +* Global data +* +********************************************************************** +*/ +extern SEGGER_RTT_CB _SEGGER_RTT; + +/********************************************************************* +* +* RTT API functions +* +********************************************************************** +*/ +#ifdef __cplusplus + extern "C" { +#endif +int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_GetKey (void); +unsigned SEGGER_RTT_HasData (unsigned BufferIndex); +int SEGGER_RTT_HasKey (void); +void SEGGER_RTT_Init (void); +unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); +unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); +int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName); +int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); +int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags); +int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags); +int SEGGER_RTT_WaitKey (void); +unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); +void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c); +unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c); +unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c); +// +// Function macro for performance optimization +// +#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) + +/********************************************************************* +* +* RTT "Terminal" API functions +* +********************************************************************** +*/ +int SEGGER_RTT_SetTerminal (char TerminalId); +int SEGGER_RTT_TerminalOut (char TerminalId, const char* s); + +/********************************************************************* +* +* RTT printf functions (require SEGGER_RTT_printf.c) +* +********************************************************************** +*/ +int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); +#ifdef __cplusplus + } +#endif + +/********************************************************************* +* +* Defines +* +********************************************************************** +*/ + +// +// Operating modes. Define behavior if buffer is full (not enough space for entire message) +// +#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0U) // Skip. Do not block, output nothing. (Default) +#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1U) // Trim: Do not block, output as much as fits. +#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2U) // Block: Wait until there is space in the buffer. +#define SEGGER_RTT_MODE_MASK (3U) + +// +// Control sequences, based on ANSI. +// Can be used to control color, and clear the screen +// +#define RTT_CTRL_RESET "" // Reset to default colors +#define RTT_CTRL_CLEAR "" // Clear screen, reposition cursor to top left + +#define RTT_CTRL_TEXT_BLACK "" +#define RTT_CTRL_TEXT_RED "" +#define RTT_CTRL_TEXT_GREEN "" +#define RTT_CTRL_TEXT_YELLOW "" +#define RTT_CTRL_TEXT_BLUE "" +#define RTT_CTRL_TEXT_MAGENTA "" +#define RTT_CTRL_TEXT_CYAN "" +#define RTT_CTRL_TEXT_WHITE "" + +#define RTT_CTRL_TEXT_BRIGHT_BLACK "" +#define RTT_CTRL_TEXT_BRIGHT_RED "" +#define RTT_CTRL_TEXT_BRIGHT_GREEN "" +#define RTT_CTRL_TEXT_BRIGHT_YELLOW "" +#define RTT_CTRL_TEXT_BRIGHT_BLUE "" +#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "" +#define RTT_CTRL_TEXT_BRIGHT_CYAN "" +#define RTT_CTRL_TEXT_BRIGHT_WHITE "" + +#define RTT_CTRL_BG_BLACK "" +#define RTT_CTRL_BG_RED "" +#define RTT_CTRL_BG_GREEN "" +#define RTT_CTRL_BG_YELLOW "" +#define RTT_CTRL_BG_BLUE "" +#define RTT_CTRL_BG_MAGENTA "" +#define RTT_CTRL_BG_CYAN "" +#define RTT_CTRL_BG_WHITE "" + +#define RTT_CTRL_BG_BRIGHT_BLACK "" +#define RTT_CTRL_BG_BRIGHT_RED "" +#define RTT_CTRL_BG_BRIGHT_GREEN "" +#define RTT_CTRL_BG_BRIGHT_YELLOW "" +#define RTT_CTRL_BG_BRIGHT_BLUE "" +#define RTT_CTRL_BG_BRIGHT_MAGENTA "" +#define RTT_CTRL_BG_BRIGHT_CYAN "" +#define RTT_CTRL_BG_BRIGHT_WHITE "" + + +#endif + +/*************************** End of file ****************************/ diff --git a/external/segger_rtt/SEGGER_RTT_Conf.h b/external/segger_rtt/SEGGER_RTT_Conf.h new file mode 100644 index 0000000..e0a4921 --- /dev/null +++ b/external/segger_rtt/SEGGER_RTT_Conf.h @@ -0,0 +1,328 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH & Co. KG * +* The Embedded Experts * +********************************************************************** +* * +* (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH & Co. KG * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 6.18a * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_Conf.h +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. +Revision: $Rev: 7020 $ + +*/ + +#ifndef SEGGER_RTT_CONF_H +#define SEGGER_RTT_CONF_H + +#include "nordic_common.h" +#include "app_util_platform.h" +#include "sdk_config.h" + +#ifdef __IAR_SYSTEMS_ICC__ + #include +#endif + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ + +#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS) // Max. number of up-buffers (T->H) available on this target (Default: 3) +#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS) // Max. number of down-buffers (H->T) available on this target (Default: 3) + +#define BUFFER_SIZE_UP (SEGGER_RTT_CONFIG_BUFFER_SIZE_UP) // Size of the buffer for terminal output of target, up to host (Default: 1k) +#define BUFFER_SIZE_DOWN (SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) + +#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) + +#define USE_RTT_ASM (0) // Use assembler version of SEGGER_RTT.c when 1 + +#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_CONFIG_DEFAULT_MODE // Mode for pre-initialized terminal channel (buffer 0) + + +#define SEGGER_RTT_LOCK() CRITICAL_REGION_ENTER() +#define SEGGER_RTT_UNLOCK() CRITICAL_REGION_EXIT() + +/********************************************************************* +* +* RTT memcpy configuration +* +* memcpy() is good for large amounts of data, +* but the overhead is big for small amounts, which are usually stored via RTT. +* With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead. +* +* SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions. +* This is may be required with memory access restrictions, +* such as on Cortex-A devices with MMU. +*/ +#define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop +// +// Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets +// +//#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__)) +// #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes)) +//#endif + +// +// Target is not allowed to perform other RTT operations while string still has not been stored completely. +// Otherwise we would probably end up with a mixed string in the buffer. +// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. +// +// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. +// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. +// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. +// (Higher priority = lower priority number) +// Default value for embOS: 128u +// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +// In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC +// or define SEGGER_RTT_LOCK() to completely disable interrupts. +// + +#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) + +/********************************************************************* +* +* RTT lock configuration for SEGGER Embedded Studio, +* Rowley CrossStudio and GCC +*/ +#ifndef SEGGER_RTT_LOCK +#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__) + #ifdef __ARM_ARCH_6M__ + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs %0, primask \n\t" \ + "mov r1, $1 \n\t" \ + "msr primask, r1 \n\t" \ + : "=r" (LockState) \ + : \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ + : \ + : "r" (LockState) \ + : \ + ); \ + } + + #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs %0, basepri \n\t" \ + "mov r1, %1 \n\t" \ + "msr basepri, r1 \n\t" \ + : "=r" (LockState) \ + : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ + : \ + : "r" (LockState) \ + : \ + ); \ + } + + #elif defined(__ARM_ARCH_7A__) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs r1, CPSR \n\t" \ + "mov %0, r1 \n\t" \ + "orr r1, r1, #0xC0 \n\t" \ + "msr CPSR_c, r1 \n\t" \ + : "=r" (LockState) \ + : \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ + "mrs r1, CPSR \n\t" \ + "bic r1, r1, #0xC0 \n\t" \ + "and r0, r0, #0xC0 \n\t" \ + "orr r1, r1, r0 \n\t" \ + "msr CPSR_c, r1 \n\t" \ + : \ + : "r" (LockState) \ + : "r0", "r1" \ + ); \ + } +#else + #define SEGGER_RTT_LOCK() + #define SEGGER_RTT_UNLOCK() + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for IAR EWARM +*/ +#ifdef __ICCARM__ + #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = __get_PRIMASK(); \ + __set_PRIMASK(1); + + #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ + } + #elif ((defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || (defined (__ARM7M__) && (__CORE__ == __ARM7M__))) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = __get_BASEPRI(); \ + __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); + + #define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for IAR RX +*/ +#ifdef __ICCRX__ + #define SEGGER_RTT_LOCK() { \ + unsigned long LockState; \ + LockState = __get_interrupt_state(); \ + __disable_interrupt(); + + #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \ + } +#endif + +/********************************************************************* +* +* RTT lock configuration for KEIL ARM +*/ +#ifdef __CC_ARM + #if (defined __TARGET_ARCH_6S_M) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + register unsigned char PRIMASK __asm( "primask"); \ + LockState = PRIMASK; \ + PRIMASK = 1u; \ + __schedule_barrier(); + + #define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \ + __schedule_barrier(); \ + } + #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + register unsigned char BASEPRI __asm( "basepri"); \ + LockState = BASEPRI; \ + BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ + __schedule_barrier(); + + #define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \ + __schedule_barrier(); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for TI ARM +*/ +#ifdef __TI_ARM__ + #if defined (__TI_ARM_V6M0__) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = __get_PRIMASK(); \ + __set_PRIMASK(1); + + #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ + } + #elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__)) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = OS_GetBASEPRI(); \ + OS_SetBASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); + + #define SEGGER_RTT_UNLOCK() OS_SetBASEPRI(LockState); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration fallback +*/ +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) +#endif + +#endif // #ifndef SEGGER_RTT_LOCK +#endif +/*************************** End of file ****************************/ diff --git a/external/segger_rtt/SEGGER_RTT_Syscalls_GCC.c b/external/segger_rtt/SEGGER_RTT_Syscalls_GCC.c new file mode 100644 index 0000000..f5a0c2a --- /dev/null +++ b/external/segger_rtt/SEGGER_RTT_Syscalls_GCC.c @@ -0,0 +1,139 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH & Co. KG * +* The Embedded Experts * +********************************************************************** +* * +* (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH & Co. KG * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 6.18a * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_Syscalls_GCC.c +Purpose : Low-level functions for using printf() via RTT in GCC. + To use RTT for printf output, include this file in your + application. +Revision: $Rev: 4351 $ +---------------------------------------------------------------------- +*/ +#include "sdk_config.h" +#if !defined(RETARGET_ENABLED) || RETARGET_ENABLED == 0 +#if defined(NRF_LOG_USES_RTT) && NRF_LOG_USES_RTT == 1 +#if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM) + +#include // required for _write_r +#include "SEGGER_RTT.h" + + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ +// +// If necessary define the _reent struct +// to match the one passed by the used standard library. +// +struct _reent; + +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ +int _write(int file, char *ptr, int len); +_ssize_t _write_r _PARAMS ((struct _reent *, int, const void *, size_t)); + +/********************************************************************* +* +* Global functions +* +********************************************************************** +*/ + +/********************************************************************* +* +* _write() +* +* Function description +* Low-level write function. +* libc subroutines will use this system routine for output to all files, +* including stdout. +* Write data via RTT. +*/ +int _write(int file, char *ptr, int len) { + (void) file; /* Not used, avoid warning */ + SEGGER_RTT_Write(0, ptr, len); + return len; +} + +/********************************************************************* +* +* _write_r() +* +* Function description +* Low-level reentrant write function. +* libc subroutines will use this system routine for output to all files, +* including stdout. +* Write data via RTT. +*/ +_ssize_t _write_r _PARAMS((struct _reent *r, int file, const void *ptr, size_t len)) { + (void) file; /* Not used, avoid warning */ + (void) r; /* Not used, avoid warning */ + SEGGER_RTT_Write(0, ptr, len); + return len; +} + +#endif // #if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM) +#endif // defined(NRF_LOG_USES_RTT) && NRF_LOG_USES_RTT == 1 +#endif // !defined(RETARGET_ENABLED) || RETARGET_ENABLED == 0 +/****** End Of File *************************************************/ diff --git a/external/segger_rtt/SEGGER_RTT_Syscalls_IAR.c b/external/segger_rtt/SEGGER_RTT_Syscalls_IAR.c new file mode 100644 index 0000000..24dca83 --- /dev/null +++ b/external/segger_rtt/SEGGER_RTT_Syscalls_IAR.c @@ -0,0 +1,122 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH & Co. KG * +* The Embedded Experts * +********************************************************************** +* * +* (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH & Co. KG * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 6.18a * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_Syscalls_IAR.c +Purpose : Low-level functions for using printf() via RTT in IAR. + To use RTT for printf output, include this file in your + application and set the Library Configuration to Normal. +Revision: $Rev: 4351 $ +---------------------------------------------------------------------- +*/ +#include "sdk_config.h" +#if !defined(RETARGET_ENABLED) || RETARGET_ENABLED == 0 +#ifdef __IAR_SYSTEMS_ICC__ + +#include +#include "SEGGER_RTT.h" +#pragma module_name = "?__write" + +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ +size_t __write(int handle, const unsigned char * buffer, size_t size); + +/********************************************************************* +* +* Global functions +* +********************************************************************** +*/ +/********************************************************************* +* +* __write() +* +* Function description +* Low-level write function. +* Standard library subroutines will use this system routine +* for output to all files, including stdout. +* Write data via RTT. +*/ +size_t __write(int handle, const unsigned char * buffer, size_t size) { + (void) handle; /* Not used, avoid warning */ + SEGGER_RTT_Write(0, (const char*)buffer, size); + return size; +} + +/********************************************************************* +* +* __write_buffered() +* +* Function description +* Low-level write function. +* Standard library subroutines will use this system routine +* for output to all files, including stdout. +* Write data via RTT. +*/ +size_t __write_buffered(int handle, const unsigned char * buffer, size_t size) { + (void) handle; /* Not used, avoid warning */ + SEGGER_RTT_Write(0, (const char*)buffer, size); + return size; +} + +#endif // #ifdef __IAR_SYSTEMS_ICC__ +#endif // #if !defined(RETARGET_ENABLED) || RETARGET_ENABLED == 0 +/****** End Of File *************************************************/ diff --git a/external/segger_rtt/SEGGER_RTT_Syscalls_KEIL.c b/external/segger_rtt/SEGGER_RTT_Syscalls_KEIL.c new file mode 100644 index 0000000..1f9f4f7 --- /dev/null +++ b/external/segger_rtt/SEGGER_RTT_Syscalls_KEIL.c @@ -0,0 +1,383 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH & Co. KG * +* The Embedded Experts * +********************************************************************** +* * +* (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH & Co. KG * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 6.18a * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : RTT_Syscalls_KEIL.c +Purpose : Retargeting module for KEIL MDK-CM3. + Low-level functions for using printf() via RTT +Revision: $Rev: 4351 $ +---------------------------------------------------------------------- +*/ +#include "sdk_config.h" +#if !defined(RETARGET_ENABLED) || RETARGET_ENABLED == 0 +#ifdef __CC_ARM + +#include +#include +#include +#include +#include + +#include "SEGGER_RTT.h" +/********************************************************************* +* +* #pragmas +* +********************************************************************** +*/ +#if defined(NRF_LOG_ENABLED) && NRF_LOG_ENABLED == 1 + #pragma import(__use_no_semihosting) +#endif + +#ifdef _MICROLIB + #pragma import(__use_full_stdio) +#endif + +/********************************************************************* +* +* Defines non-configurable +* +********************************************************************** +*/ + +/* Standard IO device handles - arbitrary, but any real file system handles must be + less than 0x8000. */ +#define STDIN 0x8001 // Standard Input Stream +#define STDOUT 0x8002 // Standard Output Stream +#define STDERR 0x8003 // Standard Error Stream + +/********************************************************************* +* +* Public const +* +********************************************************************** +*/ +//const char __stdin_name[] = "STDIN"; +const char __stdout_name[] = "STDOUT"; +const char __stderr_name[] = "STDERR"; + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ + +/********************************************************************* +* +* _ttywrch +* +* Function description: +* Outputs a character to the console +* +* Parameters: +* c - character to output +* +*/ +void _ttywrch(int c) { + fputc(c, stdout); // stdout + fflush(stdout); +} + +/********************************************************************* +* +* _sys_open +* +* Function description: +* Opens the device/file in order to do read/write operations +* +* Parameters: +* sName - sName of the device/file to open +* OpenMode - This parameter is currently ignored +* +* Return value: +* != 0 - Handle to the object to open, otherwise +* == 0 -"device" is not handled by this module +* +*/ +FILEHANDLE _sys_open(const char * sName, int OpenMode) { + (void)OpenMode; + // Register standard Input Output devices. + if (strcmp(sName, __stdout_name) == 0) { + return (STDOUT); + } else if (strcmp(sName, __stderr_name) == 0) { + return (STDERR); + } else + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_close +* +* Function description: +* Closes the handle to the open device/file +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* +* Return value: +* 0 - device/file closed +* +*/ +int _sys_close(FILEHANDLE hFile) { + (void)hFile; + return 0; // Not implemented +} + +/********************************************************************* +* +* _sys_write +* +* Function description: +* Writes the data to an open handle. +* Currently this function only outputs data to the console +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* pBuffer - Pointer to the data that shall be written +* NumBytes - Number of bytes to write +* Mode - The Mode that shall be used +* +* Return value: +* Number of bytes *not* written to the file/device +* +*/ +int _sys_write(FILEHANDLE hFile, const unsigned char * pBuffer, unsigned NumBytes, int Mode) { + int r = 0; + + (void)Mode; + if (hFile == STDOUT) { + return NumBytes - SEGGER_RTT_Write(0, (const char*)pBuffer, NumBytes); + } + return r; +} + +/********************************************************************* +* +* _sys_read +* +* Function description: +* Reads data from an open handle. +* Currently this modules does nothing. +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* pBuffer - Pointer to buffer to store the read data +* NumBytes - Number of bytes to read +* Mode - The Mode that shall be used +* +* Return value: +* Number of bytes read from the file/device +* +*/ +int _sys_read(FILEHANDLE hFile, unsigned char * pBuffer, unsigned NumBytes, int Mode) { + (void)hFile; + (void)pBuffer; + (void)NumBytes; + (void)Mode; + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_istty +* +* Function description: +* This function shall return whether the opened file +* is a console device or not. +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* +* Return value: +* 1 - Device is a console +* 0 - Device is not a console +* +*/ +int _sys_istty(FILEHANDLE hFile) { + if (hFile > 0x8000) { + return (1); + } + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_seek +* +* Function description: +* Seeks via the file to a specific position +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* Pos - +* +* Return value: +* int - +* +*/ +int _sys_seek(FILEHANDLE hFile, long Pos) { + (void)hFile; + (void)Pos; + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_ensure +* +* Function description: +* +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* +* Return value: +* int - +* +*/ +int _sys_ensure(FILEHANDLE hFile) { + (void)hFile; + return (-1); // Not implemented +} + +/********************************************************************* +* +* _sys_flen +* +* Function description: +* Returns the length of the opened file handle +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* +* Return value: +* Length of the file +* +*/ +long _sys_flen(FILEHANDLE hFile) { + (void)hFile; + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_tmpnam +* +* Function description: +* This function converts the file number fileno for a temporary +* file to a unique filename, for example, tmp0001. +* +* Parameters: +* pBuffer - Pointer to a buffer to store the name +* FileNum - file number to convert +* MaxLen - Size of the buffer +* +* Return value: +* 1 - Error +* 0 - Success +* +*/ +int _sys_tmpnam(char * pBuffer, int FileNum, unsigned MaxLen) { + (void)pBuffer; + (void)FileNum; + (void)MaxLen; + return (1); // Not implemented +} + +/********************************************************************* +* +* _sys_command_string +* +* Function description: +* This function shall execute a system command. +* +* Parameters: +* cmd - Pointer to the command string +* len - Length of the string +* +* Return value: +* == NULL - Command was not successfully executed +* == sCmd - Command was passed successfully +* +*/ +char * _sys_command_string(char * cmd, int len) { + (void)len; + return cmd; // Not implemented +} + +/********************************************************************* +* +* _sys_exit +* +* Function description: +* This function is called when the application returns from main +* +* Parameters: +* ReturnCode - Return code from the main function +* +* +*/ +void _sys_exit(int ReturnCode) { + (void)ReturnCode; + while (1); // Not implemented +} + +#endif // __CC_ARM +#endif // !defined(RETARGET_ENABLED) || RETARGET_ENABLED == 0 +/*************************** End of file ****************************/ diff --git a/external/segger_rtt/SEGGER_RTT_Syscalls_SES.c b/external/segger_rtt/SEGGER_RTT_Syscalls_SES.c new file mode 100644 index 0000000..2088cc9 --- /dev/null +++ b/external/segger_rtt/SEGGER_RTT_Syscalls_SES.c @@ -0,0 +1,264 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH & Co. KG * +* The Embedded Experts * +********************************************************************** +* * +* (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH & Co. KG * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 6.18a * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_Syscalls_SES.c +Purpose : Reimplementation of printf, puts and __getchar using RTT + in SEGGER Embedded Studio. + To use RTT for printf output, include this file in your + application. +Revision: $Rev: 4351 $ +---------------------------------------------------------------------- +*/ +#include "sdk_config.h" +#if !defined(RETARGET_ENABLED) || RETARGET_ENABLED == 0 +#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) + +#include "SEGGER_RTT.h" +#include +#include +#include "limits.h" +#include "__libc.h" +#include "__vfprintf.h" + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ +// +// Select string formatting implementation. +// +// RTT printf formatting +// - Configurable stack usage. (SEGGER_RTT_PRINTF_BUFFER_SIZE in SEGGER_RTT_Conf.h) +// - No maximum string length. +// - Limited conversion specifiers and flags. (See SEGGER_RTT_printf.c) +// Standard library printf formatting +// - Configurable formatting capabilities. +// - Full conversion specifier and flag support. +// - Maximum string length has to be known or (slightly) slower character-wise output. +// +// #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 // Use standard library formatting +// #define PRINTF_USE_SEGGER_RTT_FORMATTING 1 // Use RTT formatting +// +#ifndef PRINTF_USE_SEGGER_RTT_FORMATTING + #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 +#endif +// +// If using standard library formatting, +// select maximum output string buffer size or character-wise output. +// +// #define PRINTF_BUFFER_SIZE 0 // Use character-wise output +// #define PRINTF_BUFFER_SIZE 128 // Default maximum string length +// +#ifndef PRINTF_BUFFER_SIZE + #define PRINTF_BUFFER_SIZE 128 +#endif + +#if PRINTF_USE_SEGGER_RTT_FORMATTING // Use SEGGER RTT formatting implementation +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); + +/********************************************************************* +* +* Global functions, printf +* +********************************************************************** +*/ +/********************************************************************* +* +* printf() +* +* Function description +* print a formatted string using RTT and SEGGER RTT formatting. +*/ +int printf(const char *fmt,...) { + int n; + va_list args; + + va_start (args, fmt); + n = SEGGER_RTT_vprintf(0, fmt, &args); + va_end(args); + return n; +} + +#elif PRINTF_BUFFER_SIZE == 0 // Use standard library formatting with character-wise output + +/********************************************************************* +* +* Static functions +* +********************************************************************** +*/ +static int _putchar(int x, __printf_tag_ptr ctx) { + (void)ctx; + SEGGER_RTT_Write(0, (char *)&x, 1); + return x; +} + +/********************************************************************* +* +* Global functions, printf +* +********************************************************************** +*/ +/********************************************************************* +* +* printf() +* +* Function description +* print a formatted string character-wise, using RTT and standard +* library formatting. +*/ +int printf(const char *fmt, ...) { + int n; + va_list args; + __printf_t iod; + + va_start(args, fmt); + iod.string = 0; + iod.maxchars = INT_MAX; + iod.output_fn = _putchar; + SEGGER_RTT_LOCK(); + n = __vfprintf(&iod, fmt, args); + SEGGER_RTT_UNLOCK(); + va_end(args); + return n; +} + +#else // Use standard library formatting with static buffer + +/********************************************************************* +* +* Global functions, printf +* +********************************************************************** +*/ +/********************************************************************* +* +* printf() +* +* Function description +* print a formatted string using RTT and standard library formatting. +*/ +int printf(const char *fmt,...) { + int n; + char aBuffer[PRINTF_BUFFER_SIZE]; + va_list args; + + va_start (args, fmt); + n = vsnprintf(aBuffer, sizeof(aBuffer), fmt, args); + if (n > (int)sizeof(aBuffer)) { + SEGGER_RTT_Write(0, aBuffer, sizeof(aBuffer)); + } else if (n > 0) { + SEGGER_RTT_Write(0, aBuffer, n); + } + va_end(args); + return n; +} +#endif + +/********************************************************************* +* +* Global functions +* +********************************************************************** +*/ +/********************************************************************* +* +* puts() +* +* Function description +* print a string using RTT. +*/ +int puts(const char *s) { + return SEGGER_RTT_WriteString(0, s); +} + +/********************************************************************* +* +* __putchar() +* +* Function description +* Write one character via RTT. +*/ +int __putchar(int x, __printf_tag_ptr ctx) { + (void)ctx; + SEGGER_RTT_Write(0, (char *)&x, 1); + return x; +} + +/********************************************************************* +* +* __getchar() +* +* Function description +* Wait for and get a character via RTT. +*/ +int __getchar() { + return SEGGER_RTT_WaitKey(); +} + +#endif +#endif +/****** End Of File *************************************************/ diff --git a/external/segger_rtt/SEGGER_RTT_printf.c b/external/segger_rtt/SEGGER_RTT_printf.c new file mode 100644 index 0000000..e284ea0 --- /dev/null +++ b/external/segger_rtt/SEGGER_RTT_printf.c @@ -0,0 +1,515 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH & Co. KG * +* The Embedded Experts * +********************************************************************** +* * +* (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* conditions are met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this list of conditions and the following disclaimer. * +* * +* o Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the following * +* disclaimer in the documentation and/or other materials provided * +* with the distribution. * +* * +* o Neither the name of SEGGER Microcontroller GmbH & Co. KG * +* nor the names of its contributors may be used to endorse or * +* promote products derived from this software without specific * +* prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 6.18a * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_printf.c +Purpose : Replacement for printf to write formatted data via RTT +Revision: $Rev: 4351 $ +---------------------------------------------------------------------- +*/ +#include "SEGGER_RTT.h" +#include "SEGGER_RTT_Conf.h" + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ + +#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE + #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64) +#endif + +#include +#include + + +#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) +#define FORMAT_FLAG_PAD_ZERO (1u << 1) +#define FORMAT_FLAG_PRINT_SIGN (1u << 2) +#define FORMAT_FLAG_ALTERNATE (1u << 3) + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ + +typedef struct { + char* pBuffer; + unsigned BufferSize; + unsigned Cnt; + + int ReturnValue; + + unsigned RTTBufferIndex; +} SEGGER_RTT_PRINTF_DESC; + +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); + +/********************************************************************* +* +* Static code +* +********************************************************************** +*/ +/********************************************************************* +* +* _StoreChar +*/ +static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) { + unsigned Cnt; + + Cnt = p->Cnt; + if ((Cnt + 1u) <= p->BufferSize) { + *(p->pBuffer + Cnt) = c; + p->Cnt = Cnt + 1u; + p->ReturnValue++; + } + // + // Write part of string, when the buffer is full + // + if (p->Cnt == p->BufferSize) { + if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) { + p->ReturnValue = -1; + } else { + p->Cnt = 0u; + } + } +} + +/********************************************************************* +* +* _PrintUnsigned +*/ +static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { + static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + unsigned Div; + unsigned Digit; + unsigned Number; + unsigned Width; + char c; + + Number = v; + Digit = 1u; + // + // Get actual field width + // + Width = 1u; + while (Number >= Base) { + Number = (Number / Base); + Width++; + } + if (NumDigits > Width) { + Width = NumDigits; + } + // + // Print leading chars if necessary + // + if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) { + if (FieldWidth != 0u) { + if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) { + c = '0'; + } else { + c = ' '; + } + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, c); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Compute Digit. + // Loop until Digit has the value of the highest digit required. + // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. + // + while (1) { + if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned) + NumDigits--; + } else { + Div = v / Digit; + if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done + break; + } + } + Digit *= Base; + } + // + // Output digits + // + do { + Div = v / Digit; + v -= Div * Digit; + _StoreChar(pBufferDesc, _aV2C[Div]); + if (pBufferDesc->ReturnValue < 0) { + break; + } + Digit /= Base; + } while (Digit); + // + // Print trailing spaces if necessary + // + if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, ' '); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + } +} + +/********************************************************************* +* +* _PrintInt +*/ +static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { + unsigned Width; + int Number; + + Number = (v < 0) ? -v : v; + + // + // Get actual field width + // + Width = 1u; + while (Number >= (int)Base) { + Number = (Number / (int)Base); + Width++; + } + if (NumDigits > Width) { + Width = NumDigits; + } + if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) { + FieldWidth--; + } + + // + // Print leading spaces if necessary + // + if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, ' '); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + // + // Print sign if necessary + // + if (pBufferDesc->ReturnValue >= 0) { + if (v < 0) { + v = -v; + _StoreChar(pBufferDesc, '-'); + } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) { + _StoreChar(pBufferDesc, '+'); + } else { + + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Print leading zeros if necessary + // + if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, '0'); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Print number without sign + // + _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags); + } + } + } +} + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ +/********************************************************************* +* +* SEGGER_RTT_vprintf +* +* Function description +* Stores a formatted string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") +* sFormat Pointer to format string +* pParamList Pointer to the list of arguments for the format string +* +* Return values +* >= 0: Number of bytes which have been stored in the "Up"-buffer. +* < 0: Error +*/ +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) { + char c; + SEGGER_RTT_PRINTF_DESC BufferDesc; + int v; + unsigned NumDigits; + unsigned FormatFlags; + unsigned FieldWidth; + char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE]; + + BufferDesc.pBuffer = acBuffer; + BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE; + BufferDesc.Cnt = 0u; + BufferDesc.RTTBufferIndex = BufferIndex; + BufferDesc.ReturnValue = 0; + + do { + c = *sFormat; + sFormat++; + if (c == 0u) { + break; + } + if (c == '%') { + // + // Filter out flags + // + FormatFlags = 0u; + v = 1; + do { + c = *sFormat; + switch (c) { + case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break; + case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break; + case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break; + case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break; + default: v = 0; break; + } + } while (v); + // + // filter out field with + // + FieldWidth = 0u; + do { + c = *sFormat; + if ((c < '0') || (c > '9')) { + break; + } + sFormat++; + FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0'); + } while (1); + + // + // Filter out precision (number of digits to display) + // + NumDigits = 0u; + c = *sFormat; + if (c == '.') { + sFormat++; + do { + c = *sFormat; + if ((c < '0') || (c > '9')) { + break; + } + sFormat++; + NumDigits = NumDigits * 10u + ((unsigned)c - '0'); + } while (1); + } + // + // Filter out length modifier + // + c = *sFormat; + do { + if ((c == 'l') || (c == 'h')) { + sFormat++; + c = *sFormat; + } else { + break; + } + } while (1); + // + // Handle specifiers + // + switch (c) { + case 'c': { + char c0; + v = va_arg(*pParamList, int); + c0 = (char)v; + _StoreChar(&BufferDesc, c0); + break; + } + case 'd': + v = va_arg(*pParamList, int); + _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); + break; + case 'u': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags); + break; + case 'x': + case 'X': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags); + break; + case 's': + { + const char * s = va_arg(*pParamList, const char *); + do { + c = *s; + s++; + if (c == '\0') { + break; + } + _StoreChar(&BufferDesc, c); + } while (BufferDesc.ReturnValue >= 0); + } + break; + case 'p': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u); + break; + case '%': + _StoreChar(&BufferDesc, '%'); + break; + default: + break; + } + sFormat++; + } else { + _StoreChar(&BufferDesc, c); + } + } while (BufferDesc.ReturnValue >= 0); + + if (BufferDesc.ReturnValue > 0) { + // + // Write remaining data, if any + // + if (BufferDesc.Cnt != 0u) { + SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt); + } + BufferDesc.ReturnValue += (int)BufferDesc.Cnt; + } + return BufferDesc.ReturnValue; +} + +/********************************************************************* +* +* SEGGER_RTT_printf +* +* Function description +* Stores a formatted string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") +* sFormat Pointer to format string, followed by the arguments for conversion +* +* Return values +* >= 0: Number of bytes which have been stored in the "Up"-buffer. +* < 0: Error +* +* Notes +* (1) Conversion specifications have following syntax: +* %[flags][FieldWidth][.Precision]ConversionSpecifier +* (2) Supported flags: +* -: Left justify within the field width +* +: Always print sign extension for signed conversions +* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision +* Supported conversion specifiers: +* c: Print the argument as one char +* d: Print the argument as a signed integer +* u: Print the argument as an unsigned integer +* x: Print the argument as an hexadecimal integer +* s: Print the string pointed to by the argument +* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.) +*/ +int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) { + int r; + va_list ParamList; + + va_start(ParamList, sFormat); + r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList); + va_end(ParamList); + return r; +} +/*************************** End of file ****************************/ diff --git a/external/segger_rtt/license/license.txt b/external/segger_rtt/license/license.txt new file mode 100644 index 0000000..1fe5b11 --- /dev/null +++ b/external/segger_rtt/license/license.txt @@ -0,0 +1,38 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** diff --git a/external/utf_converter/LICENSE b/external/utf_converter/LICENSE new file mode 100644 index 0000000..fdee8ad --- /dev/null +++ b/external/utf_converter/LICENSE @@ -0,0 +1,9 @@ +Copyright (c) 2016 Pietro Gagliardi + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(this is called the MIT License or Expat License; see http://www.opensource.org/licenses/MIT) diff --git a/external/utf_converter/utf.c b/external/utf_converter/utf.c new file mode 100644 index 0000000..e76afe7 --- /dev/null +++ b/external/utf_converter/utf.c @@ -0,0 +1,350 @@ +// utf by pietro gagliardi (andlabs) — https://github.com/andlabs/utf/ +// 10 november 2016 +#include "utf.h" + +// this code imitates Go's unicode/utf8 and unicode/utf16 +// the biggest difference is that a rune is unsigned instead of signed (because Go guarantees what a right shift on a signed number will do, whereas C does not) +// it is also an imitation so we can license it under looser terms than the Go source +#define badrune 0xFFFD + +// encoded must be at most 4 bytes +// TODO clean this code up somehow +size_t utf8EncodeRune(uint32_t rune, char *encoded) +{ + uint8_t b; + uint8_t c = 0; + uint8_t d = 0; + uint8_t e = 0; + size_t n; + + // not in the valid range for Unicode + if (rune > 0x10FFFF) + rune = badrune; + // surrogate runes cannot be encoded + if (rune >= 0xD800 && rune < 0xE000) + rune = badrune; + + if (rune < 0x80) { // ASCII bytes represent themselves + b = (uint8_t) (rune & 0xFF); + n = 1; + goto done; + } + if (rune < 0x800) { // two-byte encoding + c = (uint8_t) (rune & 0x3F); + c |= 0x80; + rune >>= 6; + b = (uint8_t) (rune & 0x1F); + b |= 0xC0; + n = 2; + goto done; + } + if (rune < 0x10000) { // three-byte encoding + d = (uint8_t) (rune & 0x3F); + d |= 0x80; + rune >>= 6; + c = (uint8_t) (rune & 0x3F); + c |= 0x80; + rune >>= 6; + b = (uint8_t) (rune & 0x0F); + b |= 0xE0; + n = 3; + goto done; + } + // otherwise use a four-byte encoding + e = (uint8_t) (rune & 0x3F); + e |= 0x80; + rune >>= 6; + d = (uint8_t) (rune & 0x3F); + d |= 0x80; + rune >>= 6; + c = (uint8_t) (rune & 0x3F); + c |= 0x80; + rune >>= 6; + b = (uint8_t) (rune & 0x07); + b |= 0xF0; + n = 4; + +done: + encoded[0] = b; + if (n > 1) + encoded[1] = c; + if (n > 2) + encoded[2] = d; + if (n > 3) + encoded[3] = e; + return n; +} + +const char *utf8DecodeRune(const char *s, size_t nElem, uint32_t *rune) +{ + uint8_t b, c; + uint8_t lowestAllowed, highestAllowed; + size_t i, expected; + int bad; + + b = (uint8_t) (*s); + if (b < 0x80) { // ASCII bytes represent themselves + *rune = b; + s++; + return s; + } + // 0xC0 and 0xC1 cover 2-byte overlong equivalents + // 0xF5 to 0xFD cover values > 0x10FFFF + // 0xFE and 0xFF were never defined (always illegal) + if (b < 0xC2 || b > 0xF4) { // invalid + *rune = badrune; + s++; + return s; + } + + // this determines the range of allowed first continuation bytes + lowestAllowed = 0x80; + highestAllowed = 0xBF; + switch (b) { + case 0xE0: + // disallow 3-byte overlong equivalents + lowestAllowed = 0xA0; + break; + case 0xED: + // disallow surrogate characters + highestAllowed = 0x9F; + break; + case 0xF0: + // disallow 4-byte overlong equivalents + lowestAllowed = 0x90; + break; + case 0xF4: + // disallow values > 0x10FFFF + highestAllowed = 0x8F; + break; + } + + // and this determines how many continuation bytes are expected + expected = 1; + if (b >= 0xE0) + expected++; + if (b >= 0xF0) + expected++; + if (nElem != 0) { // are there enough bytes? + nElem--; + if (nElem < expected) { // nope + *rune = badrune; + s++; + return s; + } + } + + // ensure that everything is correct + // if not, **only** consume the initial byte + bad = 0; + for (i = 0; i < expected; i++) { + c = (uint8_t) (s[1 + i]); + if (c < lowestAllowed || c > highestAllowed) { + bad = 1; + break; + } + // the old lowestAllowed and highestAllowed is only for the first continuation byte + lowestAllowed = 0x80; + highestAllowed = 0xBF; + } + if (bad) { + *rune = badrune; + s++; + return s; + } + + // now do the topmost bits + if (b < 0xE0) + *rune = b & 0x1F; + else if (b < 0xF0) + *rune = b & 0x0F; + else + *rune = b & 0x07; + s++; // we can finally move on + + // now do the continuation bytes + for (; expected; expected--) { + c = (uint8_t) (*s); + s++; + c &= 0x3F; // strip continuation bits + *rune <<= 6; + *rune |= c; + } + + return s; +} + +// encoded must have at most 2 elements +size_t utf16EncodeRune(uint32_t rune, uint16_t *encoded) +{ + uint16_t low, high; + + // not in the valid range for Unicode + if (rune > 0x10FFFF) + rune = badrune; + // surrogate runes cannot be encoded + if (rune >= 0xD800 && rune < 0xE000) + rune = badrune; + + if (rune < 0x10000) { + encoded[0] = (uint16_t) rune; + return 1; + } + + rune -= 0x10000; + low = (uint16_t) (rune & 0x3FF); + rune >>= 10; + high = (uint16_t) (rune & 0x3FF); + encoded[0] = high | 0xD800; + encoded[1] = low | 0xDC00; + return 2; +} + +// TODO see if this can be cleaned up somehow +const uint16_t *utf16DecodeRune(const uint16_t *s, size_t nElem, uint32_t *rune) +{ + uint16_t high, low; + + if (*s < 0xD800 || *s >= 0xE000) { + // self-representing character + *rune = *s; + s++; + return s; + } + if (*s >= 0xDC00) { + // out-of-order surrogates + *rune = badrune; + s++; + return s; + } + if (nElem == 1) { // not enough elements + *rune = badrune; + s++; + return s; + } + high = *s; + high &= 0x3FF; + if (s[1] < 0xDC00 || s[1] >= 0xE000) { + // bad surrogate pair + *rune = badrune; + s++; + return s; + } + s++; + low = *s; + s++; + low &= 0x3FF; + *rune = high; + *rune <<= 10; + *rune |= low; + *rune += 0x10000; + return s; +} + +// TODO find a way to reduce the code in all of these somehow +// TODO find a way to remove u as well +size_t utf8RuneCount(const char *s, size_t nElem) +{ + size_t len; + uint32_t rune; + + if (nElem != 0) { + const char *t, *u; + + len = 0; + t = s; + while (nElem != 0) { + u = utf8DecodeRune(t, nElem, &rune); + len++; + nElem -= u - t; + t = u; + } + return len; + } + len = 0; + while (*s) { + s = utf8DecodeRune(s, nElem, &rune); + len++; + } + return len; +} + +size_t utf8UTF16Count(const char *s, size_t nElem) +{ + size_t len; + uint32_t rune; + uint16_t encoded[2]; + + if (nElem != 0) { + const char *t, *u; + + len = 0; + t = s; + while (nElem != 0) { + u = utf8DecodeRune(t, nElem, &rune); + len += utf16EncodeRune(rune, encoded); + nElem -= u - t; + t = u; + } + return len; + } + len = 0; + while (*s) { + s = utf8DecodeRune(s, nElem, &rune); + len += utf16EncodeRune(rune, encoded); + } + return len; +} + +size_t utf16RuneCount(const uint16_t *s, size_t nElem) +{ + size_t len; + uint32_t rune; + + if (nElem != 0) { + const uint16_t *t, *u; + + len = 0; + t = s; + while (nElem != 0) { + u = utf16DecodeRune(t, nElem, &rune); + len++; + nElem -= u - t; + t = u; + } + return len; + } + len = 0; + while (*s) { + s = utf16DecodeRune(s, nElem, &rune); + len++; + } + return len; +} + +size_t utf16UTF8Count(const uint16_t *s, size_t nElem) +{ + size_t len; + uint32_t rune; + char encoded[4]; + + if (nElem != 0) { + const uint16_t *t, *u; + + len = 0; + t = s; + while (nElem != 0) { + u = utf16DecodeRune(t, nElem, &rune); + len += utf8EncodeRune(rune, encoded); + nElem -= u - t; + t = u; + } + return len; + } + len = 0; + while (*s) { + s = utf16DecodeRune(s, nElem, &rune); + len += utf8EncodeRune(rune, encoded); + } + return len; +} diff --git a/external/utf_converter/utf.h b/external/utf_converter/utf.h new file mode 100644 index 0000000..b810a49 --- /dev/null +++ b/external/utf_converter/utf.h @@ -0,0 +1,61 @@ +// utf by pietro gagliardi (andlabs) — https://github.com/andlabs/utf/ +// 10 november 2016 + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +// if nElem == 0, assume the buffer has no upper limit and is '\0' terminated +// otherwise, assume buffer is NOT '\0' terminated but is bounded by nElem *elements* + +extern size_t utf8EncodeRune(uint32_t rune, char *encoded); +extern const char *utf8DecodeRune(const char *s, size_t nElem, uint32_t *rune); +extern size_t utf16EncodeRune(uint32_t rune, uint16_t *encoded); +extern const uint16_t *utf16DecodeRune(const uint16_t *s, size_t nElem, uint32_t *rune); + +extern size_t utf8RuneCount(const char *s, size_t nElem); +extern size_t utf8UTF16Count(const char *s, size_t nElem); +extern size_t utf16RuneCount(const uint16_t *s, size_t nElem); +extern size_t utf16UTF8Count(const uint16_t *s, size_t nElem); + +#ifdef __cplusplus +} + +// Provide overloads on Windows for using these functions with wchar_t and WCHAR when wchar_t is a keyword in C++ mode (the default). +// Otherwise, you'd need to cast to pass a wchar_t pointer, WCHAR pointer, or equivalent to these functions. +// We use __wchar_t to be independent of the setting; see https://blogs.msdn.microsoft.com/oldnewthing/20161201-00/?p=94836 (ironically posted one day after I initially wrote this code!). +// TODO check this on MinGW-w64 +// TODO check this under /Wall +// TODO C-style casts enough? or will that fail in /Wall? +// TODO same for UniChar/unichar on Mac? if both are unsigned then we have nothing to worry about +#if defined(_MSC_VER) + +inline size_t utf16EncodeRune(uint32_t rune, __wchar_t *encoded) +{ + return utf16EncodeRune(rune, reinterpret_cast(encoded)); +} + +inline const __wchar_t *utf16DecodeRune(const __wchar_t *s, size_t nElem, uint32_t *rune) +{ + const uint16_t *ret; + + ret = utf16DecodeRune(reinterpret_cast(s), nElem, rune); + return reinterpret_cast(ret); +} + +inline size_t utf16RuneCount(const __wchar_t *s, size_t nElem) +{ + return utf16RuneCount(reinterpret_cast(s), nElem); +} + +inline size_t utf16UTF8Count(const __wchar_t *s, size_t nElem) +{ + return utf16UTF8Count(reinterpret_cast(s), nElem); +} + +#endif + +#endif diff --git a/integration/nrfx/legacy/apply_old_config.h b/integration/nrfx/legacy/apply_old_config.h new file mode 100644 index 0000000..8bf6a4f --- /dev/null +++ b/integration/nrfx/legacy/apply_old_config.h @@ -0,0 +1,1391 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef APPLY_OLD_CONFIG_H__ +#define APPLY_OLD_CONFIG_H__ + +//------------------------------------------------------------------------------ +// Peripheral Resource Sharing (PRS) + +#if defined(PERIPHERAL_RESOURCE_SHARING_ENABLED) + +#define NRFX_PRS_ENABLED PERIPHERAL_RESOURCE_SHARING_ENABLED +#define NRFX_PRS_BOX_0_ENABLED PERIPHERAL_RESOURCE_SHARING_ENABLED +#define NRFX_PRS_BOX_1_ENABLED PERIPHERAL_RESOURCE_SHARING_ENABLED +#define NRFX_PRS_BOX_2_ENABLED PERIPHERAL_RESOURCE_SHARING_ENABLED +#define NRFX_PRS_BOX_3_ENABLED PERIPHERAL_RESOURCE_SHARING_ENABLED +#define NRFX_PRS_BOX_4_ENABLED PERIPHERAL_RESOURCE_SHARING_ENABLED + +#if defined(COMMON_CONFIG_LOG_ENABLED) +#undef NRFX_PRS_CONFIG_LOG_ENABLED +#define NRFX_PRS_CONFIG_LOG_ENABLED COMMON_CONFIG_LOG_ENABLED +#endif +#if defined(COMMON_CONFIG_LOG_LEVEL) +#undef NRFX_PRS_CONFIG_LOG_LEVEL +#define NRFX_PRS_CONFIG_LOG_LEVEL COMMON_CONFIG_LOG_LEVEL +#endif +#if defined(COMMON_CONFIG_INFO_COLOR) +#undef NRFX_PRS_CONFIG_INFO_COLOR +#define NRFX_PRS_CONFIG_INFO_COLOR COMMON_CONFIG_INFO_COLOR +#endif +#if defined(COMMON_CONFIG_DEBUG_COLOR) +#undef NRFX_PRS_CONFIG_DEBUG_COLOR +#define NRFX_PRS_CONFIG_DEBUG_COLOR COMMON_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(PERIPHERAL_RESOURCE_SHARING_ENABLED) + +//------------------------------------------------------------------------------ +// CLOCK + +#if defined(NRF_CLOCK_ENABLED) + +#if defined(CLOCK_CONFIG_LF_CAL_ENABLED) && defined(CLOCK_CONFIG_LF_SRC) +#if (CLOCK_CONFIG_LF_SRC == CLOCK_LFCLKSRC_SRC_RC) +#define NRFX_CLOCK_CONFIG_LF_CAL_ENABLED 1 +#endif +#endif + +#undef NRFX_CLOCK_ENABLED +#define NRFX_CLOCK_ENABLED NRF_CLOCK_ENABLED + +#if defined(CLOCK_CONFIG_LF_SRC) +#undef NRFX_CLOCK_CONFIG_LF_SRC +#define NRFX_CLOCK_CONFIG_LF_SRC CLOCK_CONFIG_LF_SRC +#endif +#if defined(CLOCK_CONFIG_IRQ_PRIORITY) +#undef NRFX_CLOCK_CONFIG_IRQ_PRIORITY +#define NRFX_CLOCK_CONFIG_IRQ_PRIORITY CLOCK_CONFIG_IRQ_PRIORITY +#endif + +#if defined(CLOCK_CONFIG_LOG_ENABLED) +#undef NRFX_CLOCK_CONFIG_LOG_ENABLED +#define NRFX_CLOCK_CONFIG_LOG_ENABLED CLOCK_CONFIG_LOG_ENABLED +#endif +#if defined(CLOCK_CONFIG_LOG_LEVEL) +#undef NRFX_CLOCK_CONFIG_LOG_LEVEL +#define NRFX_CLOCK_CONFIG_LOG_LEVEL CLOCK_CONFIG_LOG_LEVEL +#endif +#if defined(CLOCK_CONFIG_INFO_COLOR) +#undef NRFX_CLOCK_CONFIG_INFO_COLOR +#define NRFX_CLOCK_CONFIG_INFO_COLOR CLOCK_CONFIG_INFO_COLOR +#endif +#if defined(CLOCK_CONFIG_DEBUG_COLOR) +#undef NRFX_CLOCK_CONFIG_DEBUG_COLOR +#define NRFX_CLOCK_CONFIG_DEBUG_COLOR CLOCK_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(NRF_CLOCK_ENABLED) + +//------------------------------------------------------------------------------ +// COMP + +#if defined(COMP_ENABLED) + +#undef NRFX_COMP_ENABLED +#define NRFX_COMP_ENABLED COMP_ENABLED + +#if defined(COMP_CONFIG_REF) +#undef NRFX_COMP_CONFIG_REF +#define NRFX_COMP_CONFIG_REF COMP_CONFIG_REF +#endif +#if defined(COMP_CONFIG_MAIN_MODE) +#undef NRFX_COMP_CONFIG_MAIN_MODE +#define NRFX_COMP_CONFIG_MAIN_MODE COMP_CONFIG_MAIN_MODE +#endif +#if defined(COMP_CONFIG_SPEED_MODE) +#undef NRFX_COMP_CONFIG_SPEED_MODE +#define NRFX_COMP_CONFIG_SPEED_MODE COMP_CONFIG_SPEED_MODE +#endif +#if defined(COMP_CONFIG_HYST) +#undef NRFX_COMP_CONFIG_HYST +#define NRFX_COMP_CONFIG_HYST COMP_CONFIG_HYST +#endif +#if defined(COMP_CONFIG_ISOURCE) +#undef NRFX_COMP_CONFIG_ISOURCE +#define NRFX_COMP_CONFIG_ISOURCE COMP_CONFIG_ISOURCE +#endif +#if defined(COMP_CONFIG_INPUT) +#undef NRFX_COMP_CONFIG_INPUT +#define NRFX_COMP_CONFIG_INPUT COMP_CONFIG_INPUT +#endif +#if defined(COMP_CONFIG_IRQ_PRIORITY) +#undef NRFX_COMP_CONFIG_IRQ_PRIORITY +#define NRFX_COMP_CONFIG_IRQ_PRIORITY COMP_CONFIG_IRQ_PRIORITY +#endif + +#if defined(COMP_CONFIG_LOG_ENABLED) +#undef NRFX_COMP_CONFIG_LOG_ENABLED +#define NRFX_COMP_CONFIG_LOG_ENABLED COMP_CONFIG_LOG_ENABLED +#endif +#if defined(COMP_CONFIG_LOG_LEVEL) +#undef NRFX_COMP_CONFIG_LOG_LEVEL +#define NRFX_COMP_CONFIG_LOG_LEVEL COMP_CONFIG_LOG_LEVEL +#endif +#if defined(COMP_CONFIG_INFO_COLOR) +#undef NRFX_COMP_CONFIG_INFO_COLOR +#define NRFX_COMP_CONFIG_INFO_COLOR COMP_CONFIG_INFO_COLOR +#endif +#if defined(COMP_CONFIG_DEBUG_COLOR) +#undef NRFX_COMP_CONFIG_DEBUG_COLOR +#define NRFX_COMP_CONFIG_DEBUG_COLOR COMP_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(COMP_ENABLED) + +//------------------------------------------------------------------------------ +// GPIOTE + +#if defined(GPIOTE_ENABLED) + +#undef NRFX_GPIOTE_ENABLED +#define NRFX_GPIOTE_ENABLED GPIOTE_ENABLED + +#if defined(GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS) +#undef NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS +#define NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS +#endif + +#if defined(GPIOTE_CONFIG_IRQ_PRIORITY) +#undef NRFX_GPIOTE_CONFIG_IRQ_PRIORITY +#define NRFX_GPIOTE_CONFIG_IRQ_PRIORITY GPIOTE_CONFIG_IRQ_PRIORITY +#endif + +#if defined(GPIOTE_CONFIG_LOG_ENABLED) +#undef NRFX_GPIOTE_CONFIG_LOG_ENABLED +#define NRFX_GPIOTE_CONFIG_LOG_ENABLED GPIOTE_CONFIG_LOG_ENABLED +#endif +#if defined(GPIOTE_CONFIG_LOG_LEVEL) +#undef NRFX_GPIOTE_CONFIG_LOG_LEVEL +#define NRFX_GPIOTE_CONFIG_LOG_LEVEL GPIOTE_CONFIG_LOG_LEVEL +#endif +#if defined(GPIOTE_CONFIG_INFO_COLOR) +#undef NRFX_GPIOTE_CONFIG_INFO_COLOR +#define NRFX_GPIOTE_CONFIG_INFO_COLOR GPIOTE_CONFIG_INFO_COLOR +#endif +#if defined(GPIOTE_CONFIG_DEBUG_COLOR) +#undef NRFX_GPIOTE_CONFIG_DEBUG_COLOR +#define NRFX_GPIOTE_CONFIG_DEBUG_COLOR GPIOTE_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(GPIOTE_ENABLED) + +//------------------------------------------------------------------------------ +// I2S + +#if defined(I2S_ENABLED) + +#undef NRFX_I2S_ENABLED +#define NRFX_I2S_ENABLED I2S_ENABLED + +#if defined(I2S_CONFIG_SCK_PIN) +#undef NRFX_I2S_CONFIG_SCK_PIN +#define NRFX_I2S_CONFIG_SCK_PIN I2S_CONFIG_SCK_PIN +#endif +#if defined(I2S_CONFIG_LRCK_PIN) +#undef NRFX_I2S_CONFIG_LRCK_PIN +#define NRFX_I2S_CONFIG_LRCK_PIN I2S_CONFIG_LRCK_PIN +#endif +#if defined(I2S_CONFIG_MCK_PIN) +#undef NRFX_I2S_CONFIG_MCK_PIN +#define NRFX_I2S_CONFIG_MCK_PIN I2S_CONFIG_MCK_PIN +#endif +#if defined(I2S_CONFIG_SDOUT_PIN) +#undef NRFX_I2S_CONFIG_SDOUT_PIN +#define NRFX_I2S_CONFIG_SDOUT_PIN I2S_CONFIG_SDOUT_PIN +#endif +#if defined(I2S_CONFIG_SDIN_PIN) +#undef NRFX_I2S_CONFIG_SDIN_PIN +#define NRFX_I2S_CONFIG_SDIN_PIN I2S_CONFIG_SDIN_PIN +#endif + +#if defined(I2S_CONFIG_MASTER) +#undef NRFX_I2S_CONFIG_MASTER +#define NRFX_I2S_CONFIG_MASTER I2S_CONFIG_MASTER +#endif +#if defined(I2S_CONFIG_FORMAT) +#undef NRFX_I2S_CONFIG_FORMAT +#define NRFX_I2S_CONFIG_FORMAT I2S_CONFIG_FORMAT +#endif +#if defined(I2S_CONFIG_ALIGN) +#undef NRFX_I2S_CONFIG_ALIGN +#define NRFX_I2S_CONFIG_ALIGN I2S_CONFIG_ALIGN +#endif +#if defined(I2S_CONFIG_SWIDTH) +#undef NRFX_I2S_CONFIG_SWIDTH +#define NRFX_I2S_CONFIG_SWIDTH I2S_CONFIG_SWIDTH +#endif +#if defined(I2S_CONFIG_CHANNELS) +#undef NRFX_I2S_CONFIG_CHANNELS +#define NRFX_I2S_CONFIG_CHANNELS I2S_CONFIG_CHANNELS +#endif +#if defined(I2S_CONFIG_MCK_SETUP) +#undef NRFX_I2S_CONFIG_MCK_SETUP +#define NRFX_I2S_CONFIG_MCK_SETUP I2S_CONFIG_MCK_SETUP +#endif +#if defined(I2S_CONFIG_RATIO) +#undef NRFX_I2S_CONFIG_RATIO +#define NRFX_I2S_CONFIG_RATIO I2S_CONFIG_RATIO +#endif +#if defined(I2S_CONFIG_IRQ_PRIORITY) +#undef NRFX_I2S_CONFIG_IRQ_PRIORITY +#define NRFX_I2S_CONFIG_IRQ_PRIORITY I2S_CONFIG_IRQ_PRIORITY +#endif + +#if defined(I2S_CONFIG_LOG_ENABLED) +#undef NRFX_I2S_CONFIG_LOG_ENABLED +#define NRFX_I2S_CONFIG_LOG_ENABLED I2S_CONFIG_LOG_ENABLED +#endif +#if defined(I2S_CONFIG_LOG_LEVEL) +#undef NRFX_I2S_CONFIG_LOG_LEVEL +#define NRFX_I2S_CONFIG_LOG_LEVEL I2S_CONFIG_LOG_LEVEL +#endif +#if defined(I2S_CONFIG_INFO_COLOR) +#undef NRFX_I2S_CONFIG_INFO_COLOR +#define NRFX_I2S_CONFIG_INFO_COLOR I2S_CONFIG_INFO_COLOR +#endif +#if defined(I2S_CONFIG_DEBUG_COLOR) +#undef NRFX_I2S_CONFIG_DEBUG_COLOR +#define NRFX_I2S_CONFIG_DEBUG_COLOR I2S_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(I2S_ENABLED) + +//------------------------------------------------------------------------------ +// LPCOMP + +#if defined(LPCOMP_ENABLED) + +#undef NRFX_LPCOMP_ENABLED +#define NRFX_LPCOMP_ENABLED LPCOMP_ENABLED + +#if defined(LPCOMP_CONFIG_REFERENCE) +#undef NRFX_LPCOMP_CONFIG_REFERENCE +#define NRFX_LPCOMP_CONFIG_REFERENCE LPCOMP_CONFIG_REFERENCE +#endif +#if defined(LPCOMP_CONFIG_DETECTION) +#undef NRFX_LPCOMP_CONFIG_DETECTION +#define NRFX_LPCOMP_CONFIG_DETECTION LPCOMP_CONFIG_DETECTION +#endif +#if defined(LPCOMP_CONFIG_INPUT) +#undef NRFX_LPCOMP_CONFIG_INPUT +#define NRFX_LPCOMP_CONFIG_INPUT LPCOMP_CONFIG_INPUT +#endif +#if defined(LPCOMP_CONFIG_HYST) +#undef NRFX_LPCOMP_CONFIG_HYST +#define NRFX_LPCOMP_CONFIG_HYST LPCOMP_CONFIG_HYST +#endif +#if defined(LPCOMP_CONFIG_IRQ_PRIORITY) +#undef NRFX_LPCOMP_CONFIG_IRQ_PRIORITY +#define NRFX_LPCOMP_CONFIG_IRQ_PRIORITY LPCOMP_CONFIG_IRQ_PRIORITY +#endif + +#if defined(LPCOMP_CONFIG_LOG_ENABLED) +#undef NRFX_LPCOMP_CONFIG_LOG_ENABLED +#define NRFX_LPCOMP_CONFIG_LOG_ENABLED LPCOMP_CONFIG_LOG_ENABLED +#endif +#if defined(LPCOMP_CONFIG_LOG_LEVEL) +#undef NRFX_LPCOMP_CONFIG_LOG_LEVEL +#define NRFX_LPCOMP_CONFIG_LOG_LEVEL LPCOMP_CONFIG_LOG_LEVEL +#endif +#if defined(LPCOMP_CONFIG_INFO_COLOR) +#undef NRFX_LPCOMP_CONFIG_INFO_COLOR +#define NRFX_LPCOMP_CONFIG_INFO_COLOR LPCOMP_CONFIG_INFO_COLOR +#endif +#if defined(LPCOMP_CONFIG_DEBUG_COLOR) +#undef NRFX_LPCOMP_CONFIG_DEBUG_COLOR +#define NRFX_LPCOMP_CONFIG_DEBUG_COLOR LPCOMP_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(LPCOMP_ENABLED) + +//------------------------------------------------------------------------------ +// PDM + +#if defined(PDM_ENABLED) + +#undef NRFX_PDM_ENABLED +#define NRFX_PDM_ENABLED PDM_ENABLED + +#if defined(PDM_CONFIG_MODE) +#undef NRFX_PDM_CONFIG_MODE +#define NRFX_PDM_CONFIG_MODE PDM_CONFIG_MODE +#endif +#if defined(PDM_CONFIG_EDGE) +#undef NRFX_PDM_CONFIG_EDGE +#define NRFX_PDM_CONFIG_EDGE PDM_CONFIG_EDGE +#endif +#if defined(PDM_CONFIG_CLOCK_FREQ) +#undef NRFX_PDM_CONFIG_CLOCK_FREQ +#define NRFX_PDM_CONFIG_CLOCK_FREQ PDM_CONFIG_CLOCK_FREQ +#endif +#if defined(PDM_CONFIG_IRQ_PRIORITY) +#undef NRFX_PDM_CONFIG_IRQ_PRIORITY +#define NRFX_PDM_CONFIG_IRQ_PRIORITY PDM_CONFIG_IRQ_PRIORITY +#endif + +#if defined(PDM_CONFIG_LOG_ENABLED) +#undef NRFX_PDM_CONFIG_LOG_ENABLED +#define NRFX_PDM_CONFIG_LOG_ENABLED PDM_CONFIG_LOG_ENABLED +#endif +#if defined(PDM_CONFIG_LOG_LEVEL) +#undef NRFX_PDM_CONFIG_LOG_LEVEL +#define NRFX_PDM_CONFIG_LOG_LEVEL PDM_CONFIG_LOG_LEVEL +#endif +#if defined(PDM_CONFIG_INFO_COLOR) +#undef NRFX_PDM_CONFIG_INFO_COLOR +#define NRFX_PDM_CONFIG_INFO_COLOR PDM_CONFIG_INFO_COLOR +#endif +#if defined(PDM_CONFIG_DEBUG_COLOR) +#undef NRFX_PDM_CONFIG_DEBUG_COLOR +#define NRFX_PDM_CONFIG_DEBUG_COLOR PDM_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(PDM_ENABLED) + +//------------------------------------------------------------------------------ +// POWER + +#if defined(POWER_ENABLED) + +#undef NRFX_POWER_ENABLED +#define NRFX_POWER_ENABLED POWER_ENABLED + +#if defined(POWER_CONFIG_IRQ_PRIORITY) +#undef NRFX_POWER_CONFIG_IRQ_PRIORITY +#define NRFX_POWER_CONFIG_IRQ_PRIORITY POWER_CONFIG_IRQ_PRIORITY +#endif + +#if defined(POWER_CONFIG_DEFAULT_DCDCEN) +#undef NRFX_POWER_CONFIG_DEFAULT_DCDCEN +#define NRFX_POWER_CONFIG_DEFAULT_DCDCEN POWER_CONFIG_DEFAULT_DCDCEN +#endif +#if defined(POWER_CONFIG_DEFAULT_DCDCENHV) +#undef NRFX_POWER_CONFIG_DEFAULT_DCDCENHV +#define NRFX_POWER_CONFIG_DEFAULT_DCDCENHV POWER_CONFIG_DEFAULT_DCDCENHV +#endif + +#endif // defined(POWER_ENABLED) + +//------------------------------------------------------------------------------ +// PPI + +#if defined(PPI_ENABLED) + +#undef NRFX_PPI_ENABLED +#define NRFX_PPI_ENABLED PPI_ENABLED + +#if defined(PPI_CONFIG_LOG_ENABLED) +#undef NRFX_PPI_CONFIG_LOG_ENABLED +#define NRFX_PPI_CONFIG_LOG_ENABLED PPI_CONFIG_LOG_ENABLED +#endif +#if defined(PPI_CONFIG_LOG_LEVEL) +#undef NRFX_PPI_CONFIG_LOG_LEVEL +#define NRFX_PPI_CONFIG_LOG_LEVEL PPI_CONFIG_LOG_LEVEL +#endif +#if defined(PPI_CONFIG_INFO_COLOR) +#undef NRFX_PPI_CONFIG_INFO_COLOR +#define NRFX_PPI_CONFIG_INFO_COLOR PPI_CONFIG_INFO_COLOR +#endif +#if defined(PPI_CONFIG_DEBUG_COLOR) +#undef NRFX_PPI_CONFIG_DEBUG_COLOR +#define NRFX_PPI_CONFIG_DEBUG_COLOR PPI_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(PPI_ENABLED) + +//------------------------------------------------------------------------------ +// PWM + +#if defined(PWM_ENABLED) + +#undef NRFX_PWM_ENABLED +#define NRFX_PWM_ENABLED PWM_ENABLED + +#if defined(PWM0_ENABLED) +#undef NRFX_PWM0_ENABLED +#define NRFX_PWM0_ENABLED PWM0_ENABLED +#endif +#if defined(PWM1_ENABLED) +#undef NRFX_PWM1_ENABLED +#define NRFX_PWM1_ENABLED PWM1_ENABLED +#endif +#if defined(PWM2_ENABLED) +#undef NRFX_PWM2_ENABLED +#define NRFX_PWM2_ENABLED PWM2_ENABLED +#endif +#if defined(PWM3_ENABLED) +#undef NRFX_PWM3_ENABLED +#define NRFX_PWM3_ENABLED PWM3_ENABLED +#endif + +#if defined(PWM_DEFAULT_CONFIG_OUT0_PIN) +#undef NRFX_PWM_DEFAULT_CONFIG_OUT0_PIN +#define NRFX_PWM_DEFAULT_CONFIG_OUT0_PIN PWM_DEFAULT_CONFIG_OUT0_PIN +#endif +#if defined(PWM_DEFAULT_CONFIG_OUT1_PIN) +#undef NRFX_PWM_DEFAULT_CONFIG_OUT1_PIN +#define NRFX_PWM_DEFAULT_CONFIG_OUT1_PIN PWM_DEFAULT_CONFIG_OUT1_PIN +#endif +#if defined(PWM_DEFAULT_CONFIG_OUT2_PIN) +#undef NRFX_PWM_DEFAULT_CONFIG_OUT2_PIN +#define NRFX_PWM_DEFAULT_CONFIG_OUT2_PIN PWM_DEFAULT_CONFIG_OUT2_PIN +#endif +#if defined(PWM_DEFAULT_CONFIG_OUT3_PIN) +#undef NRFX_PWM_DEFAULT_CONFIG_OUT3_PIN +#define NRFX_PWM_DEFAULT_CONFIG_OUT3_PIN PWM_DEFAULT_CONFIG_OUT3_PIN +#endif +#if defined(PWM_DEFAULT_CONFIG_BASE_CLOCK) +#undef NRFX_PWM_DEFAULT_CONFIG_BASE_CLOCK +#define NRFX_PWM_DEFAULT_CONFIG_BASE_CLOCK PWM_DEFAULT_CONFIG_BASE_CLOCK +#endif +#if defined(PWM_DEFAULT_CONFIG_COUNT_MODE) +#undef NRFX_PWM_DEFAULT_CONFIG_COUNT_MODE +#define NRFX_PWM_DEFAULT_CONFIG_COUNT_MODE PWM_DEFAULT_CONFIG_COUNT_MODE +#endif +#if defined(PWM_DEFAULT_CONFIG_TOP_VALUE) +#undef NRFX_PWM_DEFAULT_CONFIG_TOP_VALUE +#define NRFX_PWM_DEFAULT_CONFIG_TOP_VALUE PWM_DEFAULT_CONFIG_TOP_VALUE +#endif +#if defined(PWM_DEFAULT_CONFIG_LOAD_MODE) +#undef NRFX_PWM_DEFAULT_CONFIG_LOAD_MODE +#define NRFX_PWM_DEFAULT_CONFIG_LOAD_MODE PWM_DEFAULT_CONFIG_LOAD_MODE +#endif +#if defined(PWM_DEFAULT_CONFIG_STEP_MODE) +#undef NRFX_PWM_DEFAULT_CONFIG_STEP_MODE +#define NRFX_PWM_DEFAULT_CONFIG_STEP_MODE PWM_DEFAULT_CONFIG_STEP_MODE +#endif +#if defined(PWM_DEFAULT_CONFIG_IRQ_PRIORITY) +#undef NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY PWM_DEFAULT_CONFIG_IRQ_PRIORITY +#endif + +#if defined(PWM_CONFIG_LOG_ENABLED) +#undef NRFX_PWM_CONFIG_LOG_ENABLED +#define NRFX_PWM_CONFIG_LOG_ENABLED PWM_CONFIG_LOG_ENABLED +#endif +#if defined(PWM_CONFIG_LOG_LEVEL) +#undef NRFX_PWM_CONFIG_LOG_LEVEL +#define NRFX_PWM_CONFIG_LOG_LEVEL PWM_CONFIG_LOG_LEVEL +#endif +#if defined(PWM_CONFIG_INFO_COLOR) +#undef NRFX_PWM_CONFIG_INFO_COLOR +#define NRFX_PWM_CONFIG_INFO_COLOR PWM_CONFIG_INFO_COLOR +#endif +#if defined(PWM_CONFIG_DEBUG_COLOR) +#undef NRFX_PWM_CONFIG_DEBUG_COLOR +#define NRFX_PWM_CONFIG_DEBUG_COLOR PWM_CONFIG_DEBUG_COLOR +#endif + +#if defined(PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED) +#undef NRFX_PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED +#define NRFX_PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED +#endif +#if defined(PWM_NRF52_ANOMALY_109_EGU_INSTANCE) +#undef NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE +#define NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE PWM_NRF52_ANOMALY_109_EGU_INSTANCE +#endif + +#endif // defined(PWM_ENABLED) + +//------------------------------------------------------------------------------ +// QDEC + +#if defined(QDEC_ENABLED) + +#undef NRFX_QDEC_ENABLED +#define NRFX_QDEC_ENABLED QDEC_ENABLED + +#if defined(QDEC_CONFIG_REPORTPER) +#undef NRFX_QDEC_CONFIG_REPORTPER +#define NRFX_QDEC_CONFIG_REPORTPER QDEC_CONFIG_REPORTPER +#endif +#if defined(QDEC_CONFIG_SAMPLEPER) +#undef NRFX_QDEC_CONFIG_SAMPLEPER +#define NRFX_QDEC_CONFIG_SAMPLEPER QDEC_CONFIG_SAMPLEPER +#endif +#if defined(QDEC_CONFIG_PIO_A) +#undef NRFX_QDEC_CONFIG_PIO_A +#define NRFX_QDEC_CONFIG_PIO_A QDEC_CONFIG_PIO_A +#endif +#if defined(QDEC_CONFIG_PIO_B) +#undef NRFX_QDEC_CONFIG_PIO_B +#define NRFX_QDEC_CONFIG_PIO_B QDEC_CONFIG_PIO_B +#endif +#if defined(QDEC_CONFIG_PIO_LED) +#undef NRFX_QDEC_CONFIG_PIO_LED +#define NRFX_QDEC_CONFIG_PIO_LED QDEC_CONFIG_PIO_LED +#endif +#if defined(QDEC_CONFIG_LEDPRE) +#undef NRFX_QDEC_CONFIG_LEDPRE +#define NRFX_QDEC_CONFIG_LEDPRE QDEC_CONFIG_LEDPRE +#endif +#if defined(QDEC_CONFIG_LEDPOL) +#undef NRFX_QDEC_CONFIG_LEDPOL +#define NRFX_QDEC_CONFIG_LEDPOL QDEC_CONFIG_LEDPOL +#endif +#if defined(QDEC_CONFIG_DBFEN) +#undef NRFX_QDEC_CONFIG_DBFEN +#define NRFX_QDEC_CONFIG_DBFEN QDEC_CONFIG_DBFEN +#endif +#if defined(QDEC_CONFIG_SAMPLE_INTEN) +#undef NRFX_QDEC_CONFIG_SAMPLE_INTEN +#define NRFX_QDEC_CONFIG_SAMPLE_INTEN QDEC_CONFIG_SAMPLE_INTEN +#endif +#if defined(QDEC_CONFIG_IRQ_PRIORITY) +#undef NRFX_QDEC_CONFIG_IRQ_PRIORITY +#define NRFX_QDEC_CONFIG_IRQ_PRIORITY QDEC_CONFIG_IRQ_PRIORITY +#endif + +#if defined(QDEC_CONFIG_LOG_ENABLED) +#undef NRFX_QDEC_CONFIG_LOG_ENABLED +#define NRFX_QDEC_CONFIG_LOG_ENABLED QDEC_CONFIG_LOG_ENABLED +#endif +#if defined(QDEC_CONFIG_LOG_LEVEL) +#undef NRFX_QDEC_CONFIG_LOG_LEVEL +#define NRFX_QDEC_CONFIG_LOG_LEVEL QDEC_CONFIG_LOG_LEVEL +#endif +#if defined(QDEC_CONFIG_INFO_COLOR) +#undef NRFX_QDEC_CONFIG_INFO_COLOR +#define NRFX_QDEC_CONFIG_INFO_COLOR QDEC_CONFIG_INFO_COLOR +#endif +#if defined(QDEC_CONFIG_DEBUG_COLOR) +#undef NRFX_QDEC_CONFIG_DEBUG_COLOR +#define NRFX_QDEC_CONFIG_DEBUG_COLOR QDEC_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(QDEC_ENABLED) + +//------------------------------------------------------------------------------ +// QSPI + +#if defined(QSPI_ENABLED) + +#undef NRFX_QSPI_ENABLED +#define NRFX_QSPI_ENABLED QSPI_ENABLED + +#if defined(QSPI_CONFIG_SCK_DELAY) +#undef NRFX_QSPI_CONFIG_SCK_DELAY +#define NRFX_QSPI_CONFIG_SCK_DELAY QSPI_CONFIG_SCK_DELAY +#endif +#if defined(QSPI_CONFIG_XIP_OFFSET) +#undef NRFX_QSPI_CONFIG_XIP_OFFSET +#define NRFX_QSPI_CONFIG_XIP_OFFSET QSPI_CONFIG_XIP_OFFSET +#endif +#if defined(QSPI_CONFIG_READOC) +#undef NRFX_QSPI_CONFIG_READOC +#define NRFX_QSPI_CONFIG_READOC QSPI_CONFIG_READOC +#endif +#if defined(QSPI_CONFIG_WRITEOC) +#undef NRFX_QSPI_CONFIG_WRITEOC +#define NRFX_QSPI_CONFIG_WRITEOC QSPI_CONFIG_WRITEOC +#endif +#if defined(QSPI_CONFIG_ADDRMODE) +#undef NRFX_QSPI_CONFIG_ADDRMODE +#define NRFX_QSPI_CONFIG_ADDRMODE QSPI_CONFIG_ADDRMODE +#endif +#if defined(QSPI_CONFIG_MODE) +#undef NRFX_QSPI_CONFIG_MODE +#define NRFX_QSPI_CONFIG_MODE QSPI_CONFIG_MODE +#endif +#if defined(QSPI_CONFIG_FREQUENCY) +#undef NRFX_QSPI_CONFIG_FREQUENCY +#define NRFX_QSPI_CONFIG_FREQUENCY QSPI_CONFIG_FREQUENCY +#endif +#if defined(QSPI_CONFIG_IRQ_PRIORITY) +#undef NRFX_QSPI_CONFIG_IRQ_PRIORITY +#define NRFX_QSPI_CONFIG_IRQ_PRIORITY QSPI_CONFIG_IRQ_PRIORITY +#endif + +#if defined(QSPI_PIN_SCK) +#undef NRFX_QSPI_PIN_SCK +#define NRFX_QSPI_PIN_SCK QSPI_PIN_SCK +#endif +#if defined(QSPI_PIN_CSN) +#undef NRFX_QSPI_PIN_CSN +#define NRFX_QSPI_PIN_CSN QSPI_PIN_CSN +#endif +#if defined(QSPI_PIN_IO0) +#undef NRFX_QSPI_PIN_IO0 +#define NRFX_QSPI_PIN_IO0 QSPI_PIN_IO0 +#endif +#if defined(QSPI_PIN_IO0) +#undef NRFX_QSPI_PIN_IO0 +#define NRFX_QSPI_PIN_IO0 QSPI_PIN_IO0 +#endif +#if defined(QSPI_PIN_IO1) +#undef NRFX_QSPI_PIN_IO1 +#define NRFX_QSPI_PIN_IO1 QSPI_PIN_IO1 +#endif +#if defined(QSPI_PIN_IO2) +#undef NRFX_QSPI_PIN_IO2 +#define NRFX_QSPI_PIN_IO2 QSPI_PIN_IO2 +#endif +#if defined(QSPI_PIN_IO3) +#undef NRFX_QSPI_PIN_IO3 +#define NRFX_QSPI_PIN_IO3 QSPI_PIN_IO3 +#endif + +#endif // defined(QSPI_ENABLED) + +//------------------------------------------------------------------------------ +// RNG + +#if defined(RNG_ENABLED) + +#undef NRFX_RNG_ENABLED +#define NRFX_RNG_ENABLED RNG_ENABLED + +#if defined(RNG_CONFIG_ERROR_CORRECTION) +#undef NRFX_RNG_CONFIG_ERROR_CORRECTION +#define NRFX_RNG_CONFIG_ERROR_CORRECTION RNG_CONFIG_ERROR_CORRECTION +#endif + +#if defined(RNG_CONFIG_IRQ_PRIORITY) +#undef NRFX_RNG_CONFIG_IRQ_PRIORITY +#define NRFX_RNG_CONFIG_IRQ_PRIORITY RNG_CONFIG_IRQ_PRIORITY +#endif + +#if defined(RNG_CONFIG_LOG_ENABLED) +#undef NRFX_RNG_CONFIG_LOG_ENABLED +#define NRFX_RNG_CONFIG_LOG_ENABLED RNG_CONFIG_LOG_ENABLED +#endif +#if defined(RNG_CONFIG_LOG_LEVEL) +#undef NRFX_RNG_CONFIG_LOG_LEVEL +#define NRFX_RNG_CONFIG_LOG_LEVEL RNG_CONFIG_LOG_LEVEL +#endif +#if defined(RNG_CONFIG_INFO_COLOR) +#undef NRFX_RNG_CONFIG_INFO_COLOR +#define NRFX_RNG_CONFIG_INFO_COLOR RNG_CONFIG_INFO_COLOR +#endif +#if defined(RNG_CONFIG_DEBUG_COLOR) +#undef NRFX_RNG_CONFIG_DEBUG_COLOR +#define NRFX_RNG_CONFIG_DEBUG_COLOR RNG_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(RNG_ENABLED) + +//------------------------------------------------------------------------------ +// RTC + +#if defined(RTC_ENABLED) + +#undef NRFX_RTC_ENABLED +#define NRFX_RTC_ENABLED RTC_ENABLED + +#if defined(RTC0_ENABLED) +#undef NRFX_RTC0_ENABLED +#define NRFX_RTC0_ENABLED RTC0_ENABLED +#endif +#if defined(RTC1_ENABLED) +#undef NRFX_RTC1_ENABLED +#define NRFX_RTC1_ENABLED RTC1_ENABLED +#endif +#if defined(RTC2_ENABLED) +#undef NRFX_RTC2_ENABLED +#define NRFX_RTC2_ENABLED RTC2_ENABLED +#endif + +#if defined(RTC_DEFAULT_CONFIG_FREQUENCY) +#undef NRFX_RTC_DEFAULT_CONFIG_FREQUENCY +#define NRFX_RTC_DEFAULT_CONFIG_FREQUENCY RTC_DEFAULT_CONFIG_FREQUENCY +#endif +#if defined(RTC_DEFAULT_CONFIG_RELIABLE) +#undef NRFX_RTC_DEFAULT_CONFIG_RELIABLE +#define NRFX_RTC_DEFAULT_CONFIG_RELIABLE RTC_DEFAULT_CONFIG_RELIABLE +#endif +#if defined(RTC_DEFAULT_CONFIG_IRQ_PRIORITY) +#undef NRFX_RTC_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_RTC_DEFAULT_CONFIG_IRQ_PRIORITY RTC_DEFAULT_CONFIG_IRQ_PRIORITY +#endif + +#if defined(NRF_MAXIMUM_LATENCY_US) +#undef NRFX_RTC_MAXIMUM_LATENCY_US +#define NRFX_RTC_MAXIMUM_LATENCY_US NRF_MAXIMUM_LATENCY_US +#endif + +#if defined(RTC_CONFIG_LOG_ENABLED) +#undef NRFX_RTC_CONFIG_LOG_ENABLED +#define NRFX_RTC_CONFIG_LOG_ENABLED RTC_CONFIG_LOG_ENABLED +#endif +#if defined(RTC_CONFIG_LOG_LEVEL) +#undef NRFX_RTC_CONFIG_LOG_LEVEL +#define NRFX_RTC_CONFIG_LOG_LEVEL RTC_CONFIG_LOG_LEVEL +#endif +#if defined(RTC_CONFIG_INFO_COLOR) +#undef NRFX_RTC_CONFIG_INFO_COLOR +#define NRFX_RTC_CONFIG_INFO_COLOR RTC_CONFIG_INFO_COLOR +#endif +#if defined(RTC_CONFIG_DEBUG_COLOR) +#undef NRFX_RTC_CONFIG_DEBUG_COLOR +#define NRFX_RTC_CONFIG_DEBUG_COLOR RTC_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(RTC_ENABLED) + +//------------------------------------------------------------------------------ +// SAADC + +#if defined(SAADC_ENABLED) + +#undef NRFX_SAADC_ENABLED +#define NRFX_SAADC_ENABLED SAADC_ENABLED + +#if defined(SAADC_CONFIG_RESOLUTION) +#undef NRFX_SAADC_CONFIG_RESOLUTION +#define NRFX_SAADC_CONFIG_RESOLUTION SAADC_CONFIG_RESOLUTION +#endif +#if defined(SAADC_CONFIG_OVERSAMPLE) +#undef NRFX_SAADC_CONFIG_OVERSAMPLE +#define NRFX_SAADC_CONFIG_OVERSAMPLE SAADC_CONFIG_OVERSAMPLE +#endif +#if defined(SAADC_CONFIG_LP_MODE) +#undef NRFX_SAADC_CONFIG_LP_MODE +#define NRFX_SAADC_CONFIG_LP_MODE SAADC_CONFIG_LP_MODE +#endif +#if defined(SAADC_CONFIG_IRQ_PRIORITY) +#undef NRFX_SAADC_CONFIG_IRQ_PRIORITY +#define NRFX_SAADC_CONFIG_IRQ_PRIORITY SAADC_CONFIG_IRQ_PRIORITY +#endif + +#if defined(SAADC_CONFIG_LOG_ENABLED) +#undef NRFX_SAADC_CONFIG_LOG_ENABLED +#define NRFX_SAADC_CONFIG_LOG_ENABLED SAADC_CONFIG_LOG_ENABLED +#endif +#if defined(SAADC_CONFIG_LOG_LEVEL) +#undef NRFX_SAADC_CONFIG_LOG_LEVEL +#define NRFX_SAADC_CONFIG_LOG_LEVEL SAADC_CONFIG_LOG_LEVEL +#endif +#if defined(SAADC_CONFIG_INFO_COLOR) +#undef NRFX_SAADC_CONFIG_INFO_COLOR +#define NRFX_SAADC_CONFIG_INFO_COLOR SAADC_CONFIG_INFO_COLOR +#endif +#if defined(SAADC_CONFIG_DEBUG_COLOR) +#undef NRFX_SAADC_CONFIG_DEBUG_COLOR +#define NRFX_SAADC_CONFIG_DEBUG_COLOR SAADC_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(SAADC_ENABLED) + +//------------------------------------------------------------------------------ +// SPI + +#if defined(SPI_ENABLED) + +#undef NRFX_SPI_ENABLED +#define NRFX_SPI_ENABLED \ + (SPI_ENABLED && (NRFX_SPI0_ENABLED || NRFX_SPI1_ENABLED || NRFX_SPI2_ENABLED)) +#undef NRFX_SPIM_ENABLED +#define NRFX_SPIM_ENABLED \ + (SPI_ENABLED && (NRFX_SPIM0_ENABLED || NRFX_SPIM1_ENABLED || NRFX_SPIM2_ENABLED)) + +#if defined(SPI_PRESENT) && !defined(SPIM_PRESENT) + +#undef NRFX_SPI0_ENABLED +#define NRFX_SPI0_ENABLED SPI0_ENABLED +#undef NRFX_SPIM0_ENABLED +#define NRFX_SPIM0_ENABLED 0 + +#undef NRFX_SPI1_ENABLED +#define NRFX_SPI1_ENABLED SPI1_ENABLED +#undef NRFX_SPIM1_ENABLED +#define NRFX_SPIM1_ENABLED 0 + +#undef NRFX_SPI2_ENABLED +#define NRFX_SPI2_ENABLED SPI2_ENABLED +#undef NRFX_SPIM2_ENABLED +#define NRFX_SPIM2_ENABLED 0 + +#elif !defined(SPI_PRESENT) && defined(SPIM_PRESENT) + +#undef NRFX_SPI0_ENABLED +#define NRFX_SPI0_ENABLED 0 +#undef NRFX_SPIM0_ENABLED +#define NRFX_SPIM0_ENABLED SPI0_ENABLED + +#undef NRFX_SPI1_ENABLED +#define NRFX_SPI1_ENABLED 0 +#undef NRFX_SPIM1_ENABLED +#define NRFX_SPIM1_ENABLED SPI1_ENABLED + +#undef NRFX_SPI2_ENABLED +#define NRFX_SPI2_ENABLED 0 +#undef NRFX_SPIM2_ENABLED +#define NRFX_SPIM2_ENABLED SPI2_ENABLED + +#else // -> defined(SPI_PRESENT) && defined(SPIM_PRESENT) + +#undef NRFX_SPI0_ENABLED +#define NRFX_SPI0_ENABLED (SPI0_ENABLED && !SPI0_USE_EASY_DMA) +#undef NRFX_SPIM0_ENABLED +#define NRFX_SPIM0_ENABLED (SPI0_ENABLED && SPI0_USE_EASY_DMA) + +#undef NRFX_SPI1_ENABLED +#define NRFX_SPI1_ENABLED (SPI1_ENABLED && !SPI1_USE_EASY_DMA) +#undef NRFX_SPIM1_ENABLED +#define NRFX_SPIM1_ENABLED (SPI1_ENABLED && SPI1_USE_EASY_DMA) + +#undef NRFX_SPI2_ENABLED +#define NRFX_SPI2_ENABLED (SPI2_ENABLED && !SPI2_USE_EASY_DMA) +#undef NRFX_SPIM2_ENABLED +#define NRFX_SPIM2_ENABLED (SPI2_ENABLED && SPI2_USE_EASY_DMA) + +#endif // -> defined(SPI_PRESENT) && defined(SPIM_PRESENT) + +#if defined(NRF_SPI_DRV_MISO_PULLUP_CFG) +#undef NRFX_SPI_MISO_PULL_CFG +#define NRFX_SPI_MISO_PULL_CFG NRF_SPI_DRV_MISO_PULLUP_CFG +#undef NRFX_SPIM_MISO_PULL_CFG +#define NRFX_SPIM_MISO_PULL_CFG NRF_SPI_DRV_MISO_PULLUP_CFG +#endif + +#if defined(SPI_DEFAULT_CONFIG_IRQ_PRIORITY) +#undef NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY SPI_DEFAULT_CONFIG_IRQ_PRIORITY +#undef NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY SPI_DEFAULT_CONFIG_IRQ_PRIORITY +#endif + +#if defined(SPI_CONFIG_LOG_ENABLED) +#undef NRFX_SPI_CONFIG_LOG_ENABLED +#define NRFX_SPI_CONFIG_LOG_ENABLED SPI_CONFIG_LOG_ENABLED +#undef NRFX_SPIM_CONFIG_LOG_ENABLED +#define NRFX_SPIM_CONFIG_LOG_ENABLED SPI_CONFIG_LOG_ENABLED +#endif +#if defined(SPI_CONFIG_LOG_LEVEL) +#undef NRFX_SPI_CONFIG_LOG_LEVEL +#define NRFX_SPI_CONFIG_LOG_LEVEL SPI_CONFIG_LOG_LEVEL +#undef NRFX_SPIM_CONFIG_LOG_LEVEL +#define NRFX_SPIM_CONFIG_LOG_LEVEL SPI_CONFIG_LOG_LEVEL +#endif +#if defined(SPI_CONFIG_INFO_COLOR) +#undef NRFX_SPI_CONFIG_INFO_COLOR +#define NRFX_SPI_CONFIG_INFO_COLOR SPI_CONFIG_INFO_COLOR +#undef NRFX_SPIM_CONFIG_INFO_COLOR +#define NRFX_SPIM_CONFIG_INFO_COLOR SPI_CONFIG_INFO_COLOR +#endif +#if defined(SPI_CONFIG_DEBUG_COLOR) +#undef NRFX_SPI_CONFIG_DEBUG_COLOR +#define NRFX_SPI_CONFIG_DEBUG_COLOR SPI_CONFIG_DEBUG_COLOR +#undef NRFX_SPIM_CONFIG_DEBUG_COLOR +#define NRFX_SPIM_CONFIG_DEBUG_COLOR SPI_CONFIG_DEBUG_COLOR +#endif + +#if defined(SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED) +#undef NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED +#define NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED +#endif + +#endif // defined(SPI_ENABLED) + +//------------------------------------------------------------------------------ +// SPIS + +#if defined(SPIS_ENABLED) + +#undef NRFX_SPIS_ENABLED +#define NRFX_SPIS_ENABLED SPIS_ENABLED + +#if defined(SPIS0_ENABLED) +#undef NRFX_SPIS0_ENABLED +#define NRFX_SPIS0_ENABLED SPIS0_ENABLED +#endif +#if defined(SPIS1_ENABLED) +#undef NRFX_SPIS1_ENABLED +#define NRFX_SPIS1_ENABLED SPIS1_ENABLED +#endif +#if defined(SPIS2_ENABLED) +#undef NRFX_SPIS2_ENABLED +#define NRFX_SPIS2_ENABLED SPIS2_ENABLED +#endif + +#if defined(SPIS_DEFAULT_CONFIG_IRQ_PRIORITY) +#undef NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY SPIS_DEFAULT_CONFIG_IRQ_PRIORITY +#endif +#if defined(SPIS_DEFAULT_MODE) +#undef NRFX_SPIS_DEFAULT_MODE +#define NRFX_SPIS_DEFAULT_MODE SPIS_DEFAULT_MODE +#endif +#if defined(SPIS_DEFAULT_BIT_ORDER) +#undef NRFX_SPIS_DEFAULT_BIT_ORDER +#define NRFX_SPIS_DEFAULT_BIT_ORDER SPIS_DEFAULT_BIT_ORDER +#endif +#if defined(SPIS_DEFAULT_DEF) +#undef NRFX_SPIS_DEFAULT_DEF +#define NRFX_SPIS_DEFAULT_DEF SPIS_DEFAULT_DEF +#endif +#if defined(SPIS_DEFAULT_ORC) +#undef NRFX_SPIS_DEFAULT_ORC +#define NRFX_SPIS_DEFAULT_ORC SPIS_DEFAULT_ORC +#endif + +#if defined(SPIS_CONFIG_LOG_ENABLED) +#undef NRFX_SPIS_CONFIG_LOG_ENABLED +#define NRFX_SPIS_CONFIG_LOG_ENABLED SPIS_CONFIG_LOG_ENABLED +#endif +#if defined(SPIS_CONFIG_LOG_LEVEL) +#undef NRFX_SPIS_CONFIG_LOG_LEVEL +#define NRFX_SPIS_CONFIG_LOG_LEVEL SPIS_CONFIG_LOG_LEVEL +#endif +#if defined(SPIS_CONFIG_INFO_COLOR) +#undef NRFX_SPIS_CONFIG_INFO_COLOR +#define NRFX_SPIS_CONFIG_INFO_COLOR SPIS_CONFIG_INFO_COLOR +#endif +#if defined(SPIS_CONFIG_DEBUG_COLOR) +#undef NRFX_SPIS_CONFIG_DEBUG_COLOR +#define NRFX_SPIS_CONFIG_DEBUG_COLOR SPIS_CONFIG_DEBUG_COLOR +#endif + +#if defined(SPIS_NRF52_ANOMALY_109_WORKAROUND_ENABLED) +#undef NRFX_SPIS_NRF52_ANOMALY_109_WORKAROUND_ENABLED +#define NRFX_SPIS_NRF52_ANOMALY_109_WORKAROUND_ENABLED SPIS_NRF52_ANOMALY_109_WORKAROUND_ENABLED +#endif + +#endif // defined(SPIS_ENABLED) + +//------------------------------------------------------------------------------ +// SWI + +#if defined(SWI_DISABLE0) +#undef NRFX_SWI0_DISABLED +#define NRFX_SWI0_DISABLED 1 +#endif +#if defined(SWI_DISABLE1) +#undef NRFX_SWI1_DISABLED +#define NRFX_SWI1_DISABLED 1 +#endif +#if defined(SWI_DISABLE2) +#undef NRFX_SWI2_DISABLED +#define NRFX_SWI2_DISABLED 1 +#endif +#if defined(SWI_DISABLE3) +#undef NRFX_SWI3_DISABLED +#define NRFX_SWI3_DISABLED 1 +#endif +#if defined(SWI_DISABLE4) +#undef NRFX_SWI4_DISABLED +#define NRFX_SWI4_DISABLED 1 +#endif +#if defined(SWI_DISABLE5) +#undef NRFX_SWI5_DISABLED +#define NRFX_SWI5_DISABLED 1 +#endif + +#if defined(EGU_ENABLED) +#undef NRFX_EGU_ENABLED +#define NRFX_EGU_ENABLED EGU_ENABLED +#endif + +#if defined(SWI_CONFIG_LOG_ENABLED) +#undef NRFX_SWI_CONFIG_LOG_ENABLED +#define NRFX_SWI_CONFIG_LOG_ENABLED SWI_CONFIG_LOG_ENABLED +#endif +#if defined(SWI_CONFIG_LOG_LEVEL) +#undef NRFX_SWI_CONFIG_LOG_LEVEL +#define NRFX_SWI_CONFIG_LOG_LEVEL SWI_CONFIG_LOG_LEVEL +#endif +#if defined(SWI_CONFIG_INFO_COLOR) +#undef NRFX_SWI_CONFIG_INFO_COLOR +#define NRFX_SWI_CONFIG_INFO_COLOR SWI_CONFIG_INFO_COLOR +#endif +#if defined(SWI_CONFIG_DEBUG_COLOR) +#undef NRFX_SWI_CONFIG_DEBUG_COLOR +#define NRFX_SWI_CONFIG_DEBUG_COLOR SWI_CONFIG_DEBUG_COLOR +#endif + +//------------------------------------------------------------------------------ +// SysTick + +#if defined(SYSTICK_ENABLED) + +#undef NRFX_SYSTICK_ENABLED +#define NRFX_SYSTICK_ENABLED SYSTICK_ENABLED + +#endif // defined(SYSTICK_ENABLED) + +//------------------------------------------------------------------------------ +// TIMER + +#if defined(TIMER_ENABLED) + +#undef NRFX_TIMER_ENABLED +#define NRFX_TIMER_ENABLED TIMER_ENABLED + +#if defined(TIMER0_ENABLED) +#undef NRFX_TIMER0_ENABLED +#define NRFX_TIMER0_ENABLED TIMER0_ENABLED +#endif +#if defined(TIMER1_ENABLED) +#undef NRFX_TIMER1_ENABLED +#define NRFX_TIMER1_ENABLED TIMER1_ENABLED +#endif +#if defined(TIMER2_ENABLED) +#undef NRFX_TIMER2_ENABLED +#define NRFX_TIMER2_ENABLED TIMER2_ENABLED +#endif +#if defined(TIMER3_ENABLED) +#undef NRFX_TIMER3_ENABLED +#define NRFX_TIMER3_ENABLED TIMER3_ENABLED +#endif +#if defined(TIMER4_ENABLED) +#undef NRFX_TIMER4_ENABLED +#define NRFX_TIMER4_ENABLED TIMER4_ENABLED +#endif + +#if defined(TIMER_DEFAULT_CONFIG_FREQUENCY) +#undef NRFX_TIMER_DEFAULT_CONFIG_FREQUENCY +#define NRFX_TIMER_DEFAULT_CONFIG_FREQUENCY TIMER_DEFAULT_CONFIG_FREQUENCY +#endif +#if defined(TIMER_DEFAULT_CONFIG_MODE) +#undef NRFX_TIMER_DEFAULT_CONFIG_MODE +#define NRFX_TIMER_DEFAULT_CONFIG_MODE TIMER_DEFAULT_CONFIG_MODE +#endif +#if defined(TIMER_DEFAULT_CONFIG_BIT_WIDTH) +#undef NRFX_TIMER_DEFAULT_CONFIG_BIT_WIDTH +#define NRFX_TIMER_DEFAULT_CONFIG_BIT_WIDTH TIMER_DEFAULT_CONFIG_BIT_WIDTH +#endif +#if defined(TIMER_DEFAULT_CONFIG_IRQ_PRIORITY) +#undef NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY TIMER_DEFAULT_CONFIG_IRQ_PRIORITY +#endif + +#if defined(TIMER_CONFIG_LOG_ENABLED) +#undef NRFX_TIMER_CONFIG_LOG_ENABLED +#define NRFX_TIMER_CONFIG_LOG_ENABLED TIMER_CONFIG_LOG_ENABLED +#endif +#if defined(TIMER_CONFIG_LOG_LEVEL) +#undef NRFX_TIMER_CONFIG_LOG_LEVEL +#define NRFX_TIMER_CONFIG_LOG_LEVEL TIMER_CONFIG_LOG_LEVEL +#endif +#if defined(TIMER_CONFIG_INFO_COLOR) +#undef NRFX_TIMER_CONFIG_INFO_COLOR +#define NRFX_TIMER_CONFIG_INFO_COLOR TIMER_CONFIG_INFO_COLOR +#endif +#if defined(TIMER_CONFIG_DEBUG_COLOR) +#undef NRFX_TIMER_CONFIG_DEBUG_COLOR +#define NRFX_TIMER_CONFIG_DEBUG_COLOR TIMER_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(TIMER_ENABLED) + +//------------------------------------------------------------------------------ +// TWI +#define TWI_ONLY ( defined(TWI_PRESENT) && !defined(TWIM_PRESENT)) +#define TWIM_ONLY (!defined(TWI_PRESENT) && defined(TWIM_PRESENT)) +#define TWI_AND_TWIM ( defined(TWI_PRESENT) && defined(TWIM_PRESENT)) + +#if defined(TWI_ENABLED) + +#undef NRFX_TWI_ENABLED +#define NRFX_TWI_ENABLED (TWI_ENABLED && (NRFX_TWI0_ENABLED || NRFX_TWI1_ENABLED)) +#undef NRFX_TWIM_ENABLED +#define NRFX_TWIM_ENABLED (TWI_ENABLED && (NRFX_TWIM0_ENABLED || NRFX_TWIM1_ENABLED)) + +#if defined(TWI_PRESENT) && !defined(TWIM_PRESENT) + +#undef NRFX_TWI0_ENABLED +#define NRFX_TWI0_ENABLED TWI0_ENABLED +#undef NRFX_TWIM0_ENABLED +#define NRFX_TWIM0_ENABLED 0 + +#undef NRFX_TWI1_ENABLED +#define NRFX_TWI1_ENABLED TWI1_ENABLED +#undef NRFX_TWIM1_ENABLED +#define NRFX_TWIM1_ENABLED 0 + +#elif !defined(TWI_PRESENT) && defined(TWIM_PRESENT) + +#undef NRFX_TWI0_ENABLED +#define NRFX_TWI0_ENABLED 0 +#undef NRFX_TWIM0_ENABLED +#define NRFX_TWIM0_ENABLED TWI0_ENABLED + +#undef NRFX_TWI1_ENABLED +#define NRFX_TWI1_ENABLED 0 +#undef NRFX_TWIM1_ENABLED +#define NRFX_TWIM1_ENABLED TWI1_ENABLED + +#else // -> defined(TWI_PRESENT) && defined(TWIM_PRESENT) + +#undef NRFX_TWI0_ENABLED +#define NRFX_TWI0_ENABLED (TWI0_ENABLED && !TWI0_USE_EASY_DMA) +#undef NRFX_TWIM0_ENABLED +#define NRFX_TWIM0_ENABLED (TWI0_ENABLED && TWI0_USE_EASY_DMA) + +#undef NRFX_TWI1_ENABLED +#define NRFX_TWI1_ENABLED (TWI1_ENABLED && !TWI1_USE_EASY_DMA) +#undef NRFX_TWIM1_ENABLED +#define NRFX_TWIM1_ENABLED (TWI1_ENABLED && TWI1_USE_EASY_DMA) + +#endif // -> defined(TWI_PRESENT) && defined(TWIM_PRESENT) + +#if defined(TWI_DEFAULT_CONFIG_FREQUENCY) +#undef NRFX_TWI_DEFAULT_CONFIG_FREQUENCY +#define NRFX_TWI_DEFAULT_CONFIG_FREQUENCY TWI_DEFAULT_CONFIG_FREQUENCY +#undef NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY +#define NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY TWI_DEFAULT_CONFIG_FREQUENCY +#endif +#if defined(TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT) +#undef NRFX_TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT +#define NRFX_TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT +#undef NRFX_TWIM_DEFAULT_CONFIG_HOLD_BUS_UNINIT +#define NRFX_TWIM_DEFAULT_CONFIG_HOLD_BUS_UNINIT TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT +#endif +#if defined(TWI_DEFAULT_CONFIG_IRQ_PRIORITY) +#undef NRFX_TWI_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_TWI_DEFAULT_CONFIG_IRQ_PRIORITY TWI_DEFAULT_CONFIG_IRQ_PRIORITY +#undef NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY TWI_DEFAULT_CONFIG_IRQ_PRIORITY +#endif + +#if defined(TWI_CONFIG_LOG_ENABLED) +#undef NRFX_TWI_CONFIG_LOG_ENABLED +#define NRFX_TWI_CONFIG_LOG_ENABLED TWI_CONFIG_LOG_ENABLED +#undef NRFX_TWIM_CONFIG_LOG_ENABLED +#define NRFX_TWIM_CONFIG_LOG_ENABLED TWI_CONFIG_LOG_ENABLED +#endif +#if defined(TWI_CONFIG_LOG_LEVEL) +#undef NRFX_TWI_CONFIG_LOG_LEVEL +#define NRFX_TWI_CONFIG_LOG_LEVEL TWI_CONFIG_LOG_LEVEL +#undef NRFX_TWIM_CONFIG_LOG_LEVEL +#define NRFX_TWIM_CONFIG_LOG_LEVEL TWI_CONFIG_LOG_LEVEL +#endif +#if defined(TWI_CONFIG_INFO_COLOR) +#undef NRFX_TWI_CONFIG_INFO_COLOR +#define NRFX_TWI_CONFIG_INFO_COLOR TWI_CONFIG_INFO_COLOR +#undef NRFX_TWIM_CONFIG_INFO_COLOR +#define NRFX_TWIM_CONFIG_INFO_COLOR TWI_CONFIG_INFO_COLOR +#endif +#if defined(TWI_CONFIG_DEBUG_COLOR) +#undef NRFX_TWI_CONFIG_DEBUG_COLOR +#define NRFX_TWI_CONFIG_DEBUG_COLOR TWI_CONFIG_DEBUG_COLOR +#undef NRFX_TWIM_CONFIG_DEBUG_COLOR +#define NRFX_TWIM_CONFIG_DEBUG_COLOR TWI_CONFIG_DEBUG_COLOR +#endif + +#if defined(TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED) +#undef NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED +#define NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED +#endif + +#endif // defined(TWI_ENABLED) + +//------------------------------------------------------------------------------ +// TWIS + +#if defined(TWIS_ENABLED) + +#undef NRFX_TWIS_ENABLED +#define NRFX_TWIS_ENABLED TWIS_ENABLED + +#if defined(TWIS0_ENABLED) +#undef NRFX_TWIS0_ENABLED +#define NRFX_TWIS0_ENABLED TWIS0_ENABLED +#endif +#if defined(TWIS1_ENABLED) +#undef NRFX_TWIS1_ENABLED +#define NRFX_TWIS1_ENABLED TWIS1_ENABLED +#endif + +#if defined(TWIS_ASSUME_INIT_AFTER_RESET_ONLY) +#undef NRFX_TWIS_ASSUME_INIT_AFTER_RESET_ONLY +#define NRFX_TWIS_ASSUME_INIT_AFTER_RESET_ONLY TWIS_ASSUME_INIT_AFTER_RESET_ONLY +#endif +#if defined(TWIS_NO_SYNC_MODE) +#undef NRFX_TWIS_NO_SYNC_MODE +#define NRFX_TWIS_NO_SYNC_MODE TWIS_NO_SYNC_MODE +#endif + +#if defined(TWIS_DEFAULT_CONFIG_ADDR0) +#undef NRFX_TWIS_DEFAULT_CONFIG_ADDR0 +#define NRFX_TWIS_DEFAULT_CONFIG_ADDR0 TWIS_DEFAULT_CONFIG_ADDR0 +#endif +#if defined(TWIS_DEFAULT_CONFIG_ADDR1) +#undef NRFX_TWIS_DEFAULT_CONFIG_ADDR1 +#define NRFX_TWIS_DEFAULT_CONFIG_ADDR1 TWIS_DEFAULT_CONFIG_ADDR1 +#endif +#if defined(TWIS_DEFAULT_CONFIG_SCL_PULL) +#undef NRFX_TWIS_DEFAULT_CONFIG_SCL_PULL +#define NRFX_TWIS_DEFAULT_CONFIG_SCL_PULL TWIS_DEFAULT_CONFIG_SCL_PULL +#endif +#if defined(TWIS_DEFAULT_CONFIG_SDA_PULL) +#undef NRFX_TWIS_DEFAULT_CONFIG_SDA_PULL +#define NRFX_TWIS_DEFAULT_CONFIG_SDA_PULL TWIS_DEFAULT_CONFIG_SDA_PULL +#endif +#if defined(TWIS_DEFAULT_CONFIG_IRQ_PRIORITY) +#undef NRFX_TWIS_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_TWIS_DEFAULT_CONFIG_IRQ_PRIORITY TWIS_DEFAULT_CONFIG_IRQ_PRIORITY +#endif + +#if defined(TWIS_CONFIG_LOG_ENABLED) +#undef NRFX_TWIS_CONFIG_LOG_ENABLED +#define NRFX_TWIS_CONFIG_LOG_ENABLED TWIS_CONFIG_LOG_ENABLED +#endif +#if defined(TWIS_CONFIG_LOG_LEVEL) +#undef NRFX_TWIS_CONFIG_LOG_LEVEL +#define NRFX_TWIS_CONFIG_LOG_LEVEL TWIS_CONFIG_LOG_LEVEL +#endif +#if defined(TWIS_CONFIG_INFO_COLOR) +#undef NRFX_TWIS_CONFIG_INFO_COLOR +#define NRFX_TWIS_CONFIG_INFO_COLOR TWIS_CONFIG_INFO_COLOR +#endif +#if defined(TWIS_CONFIG_DEBUG_COLOR) +#undef NRFX_TWIS_CONFIG_DEBUG_COLOR +#define NRFX_TWIS_CONFIG_DEBUG_COLOR TWIS_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(TWIS_ENABLED) + +//------------------------------------------------------------------------------ +// UART + +#if defined(UART_ENABLED) + +#undef NRFX_UART_ENABLED +#define NRFX_UART_ENABLED (UART_ENABLED && NRFX_UART0_ENABLED) +#undef NRFX_UARTE_ENABLED +#define NRFX_UARTE_ENABLED (UART_ENABLED && (NRFX_UARTE0_ENABLED || NRFX_UARTE1_ENABLED)) + +#if defined(UART0_ENABLED) +#undef NRFX_UART0_ENABLED +#define NRFX_UART0_ENABLED (UART0_ENABLED && UART_LEGACY_SUPPORT) +#undef NRFX_UARTE0_ENABLED +#define NRFX_UARTE0_ENABLED (UART0_ENABLED && UART_EASY_DMA_SUPPORT) +#endif +#if defined(UART1_ENABLED) +#undef NRFX_UARTE1_ENABLED +#define NRFX_UARTE1_ENABLED (UART1_ENABLED && UART_EASY_DMA_SUPPORT) +#endif + +#if defined(UART_DEFAULT_CONFIG_HWFC) +#undef NRFX_UART_DEFAULT_CONFIG_HWFC +#define NRFX_UART_DEFAULT_CONFIG_HWFC UART_DEFAULT_CONFIG_HWFC +#undef NRFX_UARTE_DEFAULT_CONFIG_HWFC +#define NRFX_UARTE_DEFAULT_CONFIG_HWFC UART_DEFAULT_CONFIG_HWFC +#endif +#if defined(UART_DEFAULT_CONFIG_PARITY) +#undef NRFX_UART_DEFAULT_CONFIG_PARITY +#define NRFX_UART_DEFAULT_CONFIG_PARITY UART_DEFAULT_CONFIG_PARITY +#undef NRFX_UARTE_DEFAULT_CONFIG_PARITY +#define NRFX_UARTE_DEFAULT_CONFIG_PARITY UART_DEFAULT_CONFIG_PARITY +#endif +#if defined(UART_DEFAULT_CONFIG_BAUDRATE) +#undef NRFX_UART_DEFAULT_CONFIG_BAUDRATE +#define NRFX_UART_DEFAULT_CONFIG_BAUDRATE UART_DEFAULT_CONFIG_BAUDRATE +#undef NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE +#define NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE UART_DEFAULT_CONFIG_BAUDRATE +#endif +#if defined(UART_DEFAULT_CONFIG_IRQ_PRIORITY) +#undef NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY UART_DEFAULT_CONFIG_IRQ_PRIORITY +#undef NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY UART_DEFAULT_CONFIG_IRQ_PRIORITY +#endif + +#if defined(UART_CONFIG_LOG_ENABLED) +#undef NRFX_UART_CONFIG_LOG_ENABLED +#define NRFX_UART_CONFIG_LOG_ENABLED UART_CONFIG_LOG_ENABLED +#undef NRFX_UARTE_CONFIG_LOG_ENABLED +#define NRFX_UARTE_CONFIG_LOG_ENABLED UART_CONFIG_LOG_ENABLED +#endif +#if defined(UART_CONFIG_LOG_LEVEL) +#undef NRFX_UART_CONFIG_LOG_LEVEL +#define NRFX_UART_CONFIG_LOG_LEVEL UART_CONFIG_LOG_LEVEL +#undef NRFX_UARTE_CONFIG_LOG_LEVEL +#define NRFX_UARTE_CONFIG_LOG_LEVEL UART_CONFIG_LOG_LEVEL +#endif +#if defined(UART_CONFIG_INFO_COLOR) +#undef NRFX_UART_CONFIG_INFO_COLOR +#define NRFX_UART_CONFIG_INFO_COLOR UART_CONFIG_INFO_COLOR +#undef NRFX_UARTE_CONFIG_INFO_COLOR +#define NRFX_UARTE_CONFIG_INFO_COLOR UART_CONFIG_INFO_COLOR +#endif +#if defined(UART_CONFIG_DEBUG_COLOR) +#undef NRFX_UART_CONFIG_DEBUG_COLOR +#define NRFX_UART_CONFIG_DEBUG_COLOR UART_CONFIG_DEBUG_COLOR +#undef NRFX_UARTE_CONFIG_DEBUG_COLOR +#define NRFX_UARTE_CONFIG_DEBUG_COLOR UART_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(UART_ENABLED) + +//------------------------------------------------------------------------------ +// WDT + +#if defined(WDT_ENABLED) + +#undef NRFX_WDT_ENABLED +#define NRFX_WDT_ENABLED WDT_ENABLED + +#if defined(WDT_CONFIG_BEHAVIOUR) +#undef NRFX_WDT_CONFIG_BEHAVIOUR +#define NRFX_WDT_CONFIG_BEHAVIOUR WDT_CONFIG_BEHAVIOUR +#endif +#if defined(WDT_CONFIG_RELOAD_VALUE) +#undef NRFX_WDT_CONFIG_RELOAD_VALUE +#define NRFX_WDT_CONFIG_RELOAD_VALUE WDT_CONFIG_RELOAD_VALUE +#endif +#if defined(WDT_CONFIG_IRQ_PRIORITY) +#undef NRFX_WDT_CONFIG_IRQ_PRIORITY +#define NRFX_WDT_CONFIG_IRQ_PRIORITY WDT_CONFIG_IRQ_PRIORITY +#endif + +#if defined(WDT_CONFIG_LOG_ENABLED) +#undef NRFX_WDT_CONFIG_LOG_ENABLED +#define NRFX_WDT_CONFIG_LOG_ENABLED WDT_CONFIG_LOG_ENABLED +#endif +#if defined(WDT_CONFIG_LOG_LEVEL) +#undef NRFX_WDT_CONFIG_LOG_LEVEL +#define NRFX_WDT_CONFIG_LOG_LEVEL WDT_CONFIG_LOG_LEVEL +#endif +#if defined(WDT_CONFIG_INFO_COLOR) +#undef NRFX_WDT_CONFIG_INFO_COLOR +#define NRFX_WDT_CONFIG_INFO_COLOR WDT_CONFIG_INFO_COLOR +#endif +#if defined(WDT_CONFIG_DEBUG_COLOR) +#undef NRFX_WDT_CONFIG_DEBUG_COLOR +#define NRFX_WDT_CONFIG_DEBUG_COLOR WDT_CONFIG_DEBUG_COLOR +#endif + +#endif // defined(WDT_ENABLED) + +#endif // APPLY_OLD_CONFIG_H__ diff --git a/integration/nrfx/legacy/nrf_drv_clock.c b/integration/nrfx/legacy/nrf_drv_clock.c new file mode 100644 index 0000000..b918335 --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_clock.c @@ -0,0 +1,618 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include "nrf_drv_clock.h" + +#if NRF_MODULE_ENABLED(NRF_CLOCK) + +#ifdef SOFTDEVICE_PRESENT +#include "nrf_sdh.h" +#include "nrf_sdh_soc.h" +#endif + +#include + +#define NRF_LOG_MODULE_NAME clock +#if CLOCK_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL CLOCK_CONFIG_LOG_LEVEL + #define NRF_LOG_INFO_COLOR CLOCK_CONFIG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR CLOCK_CONFIG_DEBUG_COLOR +#else //CLOCK_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL 0 +#endif //CLOCK_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define EVT_TO_STR(event) \ + (event == NRF_CLOCK_EVENT_HFCLKSTARTED ? "NRF_CLOCK_EVENT_HFCLKSTARTED" : \ + (event == NRF_CLOCK_EVENT_LFCLKSTARTED ? "NRF_CLOCK_EVENT_LFCLKSTARTED" : \ + (event == NRF_CLOCK_EVENT_DONE ? "NRF_CLOCK_EVENT_DONE" : \ + (event == NRF_CLOCK_EVENT_CTTO ? "NRF_CLOCK_EVENT_CTTO" : \ + "UNKNOWN EVENT")))) + + +/*lint -save -e652 */ +#define NRF_CLOCK_LFCLK_RC CLOCK_LFCLKSRC_SRC_RC +#define NRF_CLOCK_LFCLK_Xtal CLOCK_LFCLKSRC_SRC_Xtal +#define NRF_CLOCK_LFCLK_Synth CLOCK_LFCLKSRC_SRC_Synth +/*lint -restore */ + +#if (CLOCK_CONFIG_LF_SRC == NRF_CLOCK_LFCLK_RC) && !defined(SOFTDEVICE_PRESENT) +#define CALIBRATION_SUPPORT 1 +#else +#define CALIBRATION_SUPPORT 0 +#endif +typedef enum +{ + CAL_STATE_IDLE, + CAL_STATE_CT, + CAL_STATE_HFCLK_REQ, + CAL_STATE_CAL, + CAL_STATE_ABORT, +} nrf_drv_clock_cal_state_t; + +/**@brief CLOCK control block. */ +typedef struct +{ + bool module_initialized; /*< Indicate the state of module */ + volatile bool hfclk_on; /*< High-frequency clock state. */ + volatile bool lfclk_on; /*< Low-frequency clock state. */ + volatile uint32_t hfclk_requests; /*< High-frequency clock request counter. */ + volatile nrf_drv_clock_handler_item_t * p_hf_head; + volatile uint32_t lfclk_requests; /*< Low-frequency clock request counter. */ + volatile nrf_drv_clock_handler_item_t * p_lf_head; +#if CALIBRATION_SUPPORT + nrf_drv_clock_handler_item_t cal_hfclk_started_handler_item; + nrf_drv_clock_event_handler_t cal_done_handler; + volatile nrf_drv_clock_cal_state_t cal_state; +#endif // CALIBRATION_SUPPORT +} nrf_drv_clock_cb_t; + +static nrf_drv_clock_cb_t m_clock_cb; + +static void clock_irq_handler(nrfx_clock_evt_type_t evt); + +static void lfclk_stop(void) +{ +#if CALIBRATION_SUPPORT + nrfx_clock_calibration_timer_stop(); +#endif + +#ifdef SOFTDEVICE_PRESENT + // If LFCLK is requested to stop while SD is still enabled, + // it indicates an error in the application. + // Enabling SD should increment the LFCLK request. + ASSERT(!nrf_sdh_is_enabled()); +#endif // SOFTDEVICE_PRESENT + + // LFCLK can be started independently by the watchdog and cannot be stopped + // by the CLOCK peripheral. This code handles this situation and prevents LFCLK to be stopped. + // Otherwise driver can stuck when waiting for the operation to complete. + if (!nrf_wdt_started()) + { + nrfx_clock_lfclk_stop(); + m_clock_cb.lfclk_on = false; + } +} + +static void hfclk_start(void) +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + (void)sd_clock_hfclk_request(); + return; + } +#endif // SOFTDEVICE_PRESENT + + nrfx_clock_hfclk_start(); +} + +static void hfclk_stop(void) +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + (void)sd_clock_hfclk_release(); + m_clock_cb.hfclk_on = false; + return; + } +#endif // SOFTDEVICE_PRESENT + + nrfx_clock_hfclk_stop(); + m_clock_cb.hfclk_on = false; +} + +bool nrf_drv_clock_init_check(void) +{ + return m_clock_cb.module_initialized; +} + +ret_code_t nrf_drv_clock_init(void) +{ + ret_code_t err_code = NRF_SUCCESS; + if (m_clock_cb.module_initialized) + { + err_code = NRF_ERROR_MODULE_ALREADY_INITIALIZED; + } + else + { + m_clock_cb.p_hf_head = NULL; + m_clock_cb.hfclk_requests = 0; + m_clock_cb.p_lf_head = NULL; + m_clock_cb.lfclk_requests = 0; + err_code = nrfx_clock_init(clock_irq_handler); +#ifdef SOFTDEVICE_PRESENT + if (!nrf_sdh_is_enabled()) +#endif + { + nrfx_clock_enable(); + } + +#if CALIBRATION_SUPPORT + m_clock_cb.cal_state = CAL_STATE_IDLE; +#endif + + m_clock_cb.module_initialized = true; + } + + if (nrf_wdt_started()) + { + m_clock_cb.lfclk_on = true; + } + + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +void nrf_drv_clock_uninit(void) +{ + ASSERT(m_clock_cb.module_initialized); + nrfx_clock_disable(); + nrfx_clock_uninit(); + + m_clock_cb.module_initialized = false; +} + +static void item_enqueue(nrf_drv_clock_handler_item_t ** p_head, + nrf_drv_clock_handler_item_t * p_item) +{ + nrf_drv_clock_handler_item_t * p_next = *p_head; + while (p_next) + { + if (p_next == p_item) + { + return; + } + p_next = p_next->p_next; + } + + p_item->p_next = (*p_head ? *p_head : NULL); + *p_head = p_item; +} + +static nrf_drv_clock_handler_item_t * item_dequeue(nrf_drv_clock_handler_item_t ** p_head) +{ + nrf_drv_clock_handler_item_t * p_item = *p_head; + if (p_item) + { + *p_head = p_item->p_next; + } + return p_item; +} + +void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item) +{ + ASSERT(m_clock_cb.module_initialized); + + if (m_clock_cb.lfclk_on) + { + if (p_handler_item) + { + p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_LFCLK_STARTED); + } + CRITICAL_REGION_ENTER(); + ++(m_clock_cb.lfclk_requests); + CRITICAL_REGION_EXIT(); + } + else + { + CRITICAL_REGION_ENTER(); + if (p_handler_item) + { + item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head, + p_handler_item); + } + if (m_clock_cb.lfclk_requests == 0) + { + nrfx_clock_lfclk_start(); + } + ++(m_clock_cb.lfclk_requests); + CRITICAL_REGION_EXIT(); + } + + ASSERT(m_clock_cb.lfclk_requests > 0); +} + +void nrf_drv_clock_lfclk_release(void) +{ + ASSERT(m_clock_cb.module_initialized); + ASSERT(m_clock_cb.lfclk_requests > 0); + + CRITICAL_REGION_ENTER(); + --(m_clock_cb.lfclk_requests); + if (m_clock_cb.lfclk_requests == 0) + { + lfclk_stop(); + } + CRITICAL_REGION_EXIT(); +} + +bool nrf_drv_clock_lfclk_is_running(void) +{ + ASSERT(m_clock_cb.module_initialized); + +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + return true; + } +#endif // SOFTDEVICE_PRESENT + + return nrfx_clock_lfclk_is_running(); +} + +void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item) +{ + ASSERT(m_clock_cb.module_initialized); + + if (m_clock_cb.hfclk_on) + { + if (p_handler_item) + { + p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + } + CRITICAL_REGION_ENTER(); + ++(m_clock_cb.hfclk_requests); + CRITICAL_REGION_EXIT(); + } + else + { + CRITICAL_REGION_ENTER(); + if (p_handler_item) + { + item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head, + p_handler_item); + } + if (m_clock_cb.hfclk_requests == 0) + { + hfclk_start(); + } + ++(m_clock_cb.hfclk_requests); + CRITICAL_REGION_EXIT(); + } + + ASSERT(m_clock_cb.hfclk_requests > 0); +} + +void nrf_drv_clock_hfclk_release(void) +{ + ASSERT(m_clock_cb.module_initialized); + ASSERT(m_clock_cb.hfclk_requests > 0); + + CRITICAL_REGION_ENTER(); + --(m_clock_cb.hfclk_requests); + if (m_clock_cb.hfclk_requests == 0) + { + hfclk_stop(); + } + CRITICAL_REGION_EXIT(); +} + +bool nrf_drv_clock_hfclk_is_running(void) +{ + ASSERT(m_clock_cb.module_initialized); + +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + uint32_t is_running; + UNUSED_VARIABLE(sd_clock_hfclk_is_running(&is_running)); + return (is_running ? true : false); + } +#endif // SOFTDEVICE_PRESENT + + return nrfx_clock_hfclk_is_running(); +} + +#if CALIBRATION_SUPPORT +static void clock_calibration_hf_started(nrf_drv_clock_evt_type_t event) +{ + if (m_clock_cb.cal_state == CAL_STATE_ABORT) + { + nrf_drv_clock_hfclk_release(); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED); + } + } + else + { + ASSERT(event == NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + if (nrfx_clock_calibration_start() != NRFX_SUCCESS) + { + ASSERT(false); + } + } +} +#endif // CALIBRATION_SUPPORT + +ret_code_t nrf_drv_clock_calibration_start(uint8_t interval, nrf_drv_clock_event_handler_t handler) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + ASSERT(m_clock_cb.cal_state == CAL_STATE_IDLE); + if (m_clock_cb.lfclk_on == false) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else if (m_clock_cb.cal_state == CAL_STATE_IDLE) + { + m_clock_cb.cal_done_handler = handler; + m_clock_cb.cal_hfclk_started_handler_item.event_handler = clock_calibration_hf_started; + if (interval == 0) + { + m_clock_cb.cal_state = CAL_STATE_HFCLK_REQ; + nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item); + } + else + { + m_clock_cb.cal_state = CAL_STATE_CT; + nrfx_clock_calibration_timer_start(interval); + } + } + else + { + err_code = NRF_ERROR_BUSY; + } + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + UNUSED_PARAMETER(interval); + UNUSED_PARAMETER(handler); + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +ret_code_t nrf_drv_clock_calibration_abort(void) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + CRITICAL_REGION_ENTER(); + switch (m_clock_cb.cal_state) + { + case CAL_STATE_CT: + nrfx_clock_calibration_timer_stop(); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED); + } + break; + case CAL_STATE_HFCLK_REQ: + /* fall through. */ + case CAL_STATE_CAL: + m_clock_cb.cal_state = CAL_STATE_ABORT; + break; + default: + break; + } + CRITICAL_REGION_EXIT(); + + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + ASSERT(m_clock_cb.module_initialized); + *p_is_calibrating = (m_clock_cb.cal_state != CAL_STATE_IDLE); + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + UNUSED_PARAMETER(p_is_calibrating); + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +__STATIC_INLINE void clock_clk_started_notify(nrf_drv_clock_evt_type_t evt_type) +{ + nrf_drv_clock_handler_item_t **p_head; + if (evt_type == NRF_DRV_CLOCK_EVT_HFCLK_STARTED) + { + p_head = (nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head; + } + else + { + p_head = (nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head; + } + + while (1) + { + nrf_drv_clock_handler_item_t * p_item = item_dequeue(p_head); + if (!p_item) + { + break; + } + + p_item->event_handler(evt_type); + } +} + +static void clock_irq_handler(nrfx_clock_evt_type_t evt) +{ + if (evt == NRFX_CLOCK_EVT_HFCLK_STARTED) + { + m_clock_cb.hfclk_on = true; + clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + } + if (evt == NRFX_CLOCK_EVT_LFCLK_STARTED) + { + m_clock_cb.lfclk_on = true; + clock_clk_started_notify(NRF_DRV_CLOCK_EVT_LFCLK_STARTED); + } +#if CALIBRATION_SUPPORT + if (evt == NRFX_CLOCK_EVT_CTTO) + { + nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item); + } + + if (evt == NRFX_CLOCK_EVT_CAL_DONE) + { + nrf_drv_clock_hfclk_release(); + bool aborted = (m_clock_cb.cal_state == CAL_STATE_ABORT); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(aborted ? + NRF_DRV_CLOCK_EVT_CAL_ABORTED : NRF_DRV_CLOCK_EVT_CAL_DONE); + } + } +#endif // CALIBRATION_SUPPORT +} + +#ifdef SOFTDEVICE_PRESENT +/** + * @brief SoftDevice SoC event handler. + * + * @param[in] evt_id SoC event. + * @param[in] p_context Context. + */ +static void soc_evt_handler(uint32_t evt_id, void * p_context) +{ + if (evt_id == NRF_EVT_HFCLKSTARTED) + { + m_clock_cb.hfclk_on = true; + clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + } +} +NRF_SDH_SOC_OBSERVER(m_soc_evt_observer, CLOCK_CONFIG_SOC_OBSERVER_PRIO, soc_evt_handler, NULL); + +/** + * @brief SoftDevice enable/disable state handler. + * + * @param[in] state State. + * @param[in] p_context Context. + */ +static void sd_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context) +{ + switch (state) + { + case NRF_SDH_EVT_STATE_ENABLE_PREPARE: + NVIC_DisableIRQ(POWER_CLOCK_IRQn); + break; + + case NRF_SDH_EVT_STATE_ENABLED: + CRITICAL_REGION_ENTER(); + /* Make sure that nrf_drv_clock module is initialized */ + if (!m_clock_cb.module_initialized) + { + (void)nrf_drv_clock_init(); + } + /* SD is one of the LFCLK requesters, but it will enable it by itself. */ + ++(m_clock_cb.lfclk_requests); + m_clock_cb.lfclk_on = true; + CRITICAL_REGION_EXIT(); + break; + + case NRF_SDH_EVT_STATE_DISABLED: + /* Reinit interrupts */ + ASSERT(m_clock_cb.module_initialized); + nrfx_clock_enable(); + + /* SD leaves LFCLK enabled - disable it if it is no longer required. */ + nrf_drv_clock_lfclk_release(); + break; + + default: + break; + } +} + +NRF_SDH_STATE_OBSERVER(m_sd_state_observer, CLOCK_CONFIG_STATE_OBSERVER_PRIO) = +{ + .handler = sd_state_evt_handler, + .p_context = NULL, +}; + +#endif // SOFTDEVICE_PRESENT + +#undef NRF_CLOCK_LFCLK_RC +#undef NRF_CLOCK_LFCLK_Xtal +#undef NRF_CLOCK_LFCLK_Synth + +#endif // NRF_MODULE_ENABLED(NRF_CLOCK) diff --git a/integration/nrfx/legacy/nrf_drv_clock.h b/integration/nrfx/legacy/nrf_drv_clock.h new file mode 100644 index 0000000..72cee8c --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_clock.h @@ -0,0 +1,297 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_DRV_CLOCK_H__ +#define NRF_DRV_CLOCK_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_clock Clock driver - legacy layer + * @{ + * @ingroup nrf_clock + * + * @brief Layer providing compatibility with the former API. + */ + +/** + * @brief Clock events. + */ +typedef enum +{ + NRF_DRV_CLOCK_EVT_HFCLK_STARTED, ///< HFCLK has been started. + NRF_DRV_CLOCK_EVT_LFCLK_STARTED, ///< LFCLK has been started. + NRF_DRV_CLOCK_EVT_CAL_DONE, ///< Calibration is done. + NRF_DRV_CLOCK_EVT_CAL_ABORTED, ///< Calibration has been aborted. +} nrf_drv_clock_evt_type_t; + +/** + * @brief Clock event handler. + * + * @param[in] event Event. + */ +typedef void (*nrf_drv_clock_event_handler_t)(nrf_drv_clock_evt_type_t event); + +// Forward declaration of the nrf_drv_clock_handler_item_t type. +typedef struct nrf_drv_clock_handler_item_s nrf_drv_clock_handler_item_t; + +struct nrf_drv_clock_handler_item_s +{ + nrf_drv_clock_handler_item_t * p_next; ///< A pointer to the next handler that should be called when the clock is started. + nrf_drv_clock_event_handler_t event_handler; ///< Function to be called when the clock is started. +}; + +/** + * @brief Function for checking if driver is already initialized + * + * @retval true Driver is initialized + * @retval false Driver is uninitialized + */ +bool nrf_drv_clock_init_check(void); + +/** + * @brief Function for initializing the nrf_drv_clock module. + * + * After initialization, the module is in power off state (clocks are not requested). + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED If the driver was already initialized. + */ +ret_code_t nrf_drv_clock_init(void); + +/** + * @brief Function for uninitializing the clock module. + * + */ +void nrf_drv_clock_uninit(void); + +/** + * @brief Function for requesting the LFCLK. + * + * The low-frequency clock can be requested by different modules + * or contexts. The driver ensures that the clock will be started only when it is requested + * the first time. If the clock is not ready but it was already started, the handler item that is + * provided as an input parameter is added to the list of handlers that will be notified + * when the clock is started. If the clock is already enabled, user callback is called from the + * current context. + * + * The first request will start the selected LFCLK source. If an event handler is + * provided, it will be called once the LFCLK is started. If the LFCLK was already started at this + * time, the event handler will be called from the context of this function. Additionally, + * the @ref nrf_drv_clock_lfclk_is_running function can be polled to check if the clock has started. + * + * @note When a SoftDevice is enabled, the LFCLK is always running and the driver cannot control it. + * + * @note The handler item provided by the user cannot be an automatic variable. + * + * @param[in] p_handler_item A pointer to the event handler structure. + */ +void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item); + +/** + * @brief Function for releasing the LFCLK. + * + * If there are no more requests, the LFCLK source will be stopped. + * + * @note When a SoftDevice is enabled, the LFCLK is always running. + */ +void nrf_drv_clock_lfclk_release(void); + +/** + * @brief Function for checking the LFCLK state. + * + * @retval true If the LFCLK is running. + * @retval false If the LFCLK is not running. + */ +bool nrf_drv_clock_lfclk_is_running(void); + +/** + * @brief Function for requesting the high-accuracy source HFCLK. + * + * The high-accuracy source + * can be requested by different modules or contexts. The driver ensures that the high-accuracy + * clock will be started only when it is requested the first time. If the clock is not ready + * but it was already started, the handler item that is provided as an input parameter is added + * to the list of handlers that will be notified when the clock is started. + * + * If an event handler is provided, it will be called once the clock is started. If the clock was already + * started at this time, the event handler will be called from the context of this function. Additionally, + * the @ref nrf_drv_clock_hfclk_is_running function can be polled to check if the clock has started. + * + * @note If a SoftDevice is running, the clock is managed by the SoftDevice and all requests are handled by + * the SoftDevice. This function cannot be called from all interrupt priority levels in that case. + * @note The handler item provided by the user cannot be an automatic variable. + * + * @param[in] p_handler_item A pointer to the event handler structure. + */ +void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item); + +/** + * @brief Function for releasing the high-accuracy source HFCLK. + * + * If there are no more requests, the high-accuracy source will be released. + */ +void nrf_drv_clock_hfclk_release(void); + +/** + * @brief Function for checking the HFCLK state. + * + * @retval true If the HFCLK is running (for \nRFXX XTAL source). + * @retval false If the HFCLK is not running. + */ +bool nrf_drv_clock_hfclk_is_running(void); + +/** + * @brief Function for starting a single calibration process. + * + * This function can also delay the start of calibration by a user-specified value. The delay will use + * a low-power timer that is part of the CLOCK module. @ref nrf_drv_clock_is_calibrating can be called to + * check if calibration is still in progress. If a handler is provided, the user can be notified when + * calibration is completed. The ext calibration can be started from the handler context. + * + * The calibration process consists of three phases: + * - Delay (optional) + * - Requesting the high-accuracy HFCLK + * - Hardware-supported calibration + * + * @param[in] delay Time after which the calibration will be started (in 0.25 s units). + * @param[in] handler NULL or user function to be called when calibration is completed or aborted. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + * @retval NRF_ERROR_INVALID_STATE If the low-frequency clock is off. + * @retval NRF_ERROR_BUSY If calibration is in progress. + */ +ret_code_t nrf_drv_clock_calibration_start(uint8_t delay, nrf_drv_clock_event_handler_t handler); + +/** + * @brief Function for aborting calibration. + * + * This function aborts on-going calibration. If calibration was started, it cannot be stopped. If a handler + * was provided by @ref nrf_drv_clock_calibration_start, this handler will be called once + * aborted calibration is completed. @ref nrf_drv_clock_is_calibrating can also be used to check + * if the system is calibrating. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + */ +ret_code_t nrf_drv_clock_calibration_abort(void); + +/** + * @brief Function for checking if calibration is in progress. + * + * This function indicates that the system is + * in calibration if it is in any of the calibration process phases (see @ref nrf_drv_clock_calibration_start). + * + * @param[out] p_is_calibrating True if calibration is in progress, false if not. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + */ +ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating); + +/**@brief Function for returning a requested task address for the clock driver module. + * + * @param[in] task One of the peripheral tasks. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_task_addr(nrf_clock_task_t task); + +/**@brief Function for returning a requested event address for the clock driver module. + * + * @param[in] event One of the peripheral events. + * + * @return Event address. + */ +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_event_addr(nrf_clock_event_t event); + + +#ifdef SOFTDEVICE_PRESENT +/** + * @brief Function called by the SoftDevice handler if an @ref NRF_SOC_EVTS event is received from the SoftDevice. + * + * @param[in] evt_id One of NRF_SOC_EVTS values. + */ +void nrf_drv_clock_on_soc_event(uint32_t evt_id); + +/** + * @brief Function called by the SoftDevice handler when the SoftDevice has been enabled. + * + * This function is called just after the SoftDevice has been properly enabled. + * Its main purpose is to mark that LFCLK has been requested by SD. + */ +void nrf_drv_clock_on_sd_enable(void); + +/** + * @brief Function called by the SoftDevice handler when the SoftDevice has been disabled. + * + * This function is called just after the SoftDevice has been properly disabled. + * It has two purposes: + * 1. Releases the LFCLK from the SD. + * 2. Reinitializes an interrupt after the SD releases POWER_CLOCK_IRQ. + */ +void nrf_drv_clock_on_sd_disable(void); + +#endif +/** + *@} + **/ + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_task_addr(nrf_clock_task_t task) +{ + return nrf_clock_task_address_get(task); +} + +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_event_addr(nrf_clock_event_t event) +{ + return nrf_clock_event_address_get(event); +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_CLOCK_H__ diff --git a/integration/nrfx/legacy/nrf_drv_common.h b/integration/nrfx/legacy/nrf_drv_common.h new file mode 100644 index 0000000..2264a2f --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_common.h @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_COMMON_H__ +#define NRF_DRV_COMMON_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define INTERRUPT_PRIORITY_VALIDATION(pri) STATIC_ASSERT(INTERRUPT_PRIORITY_IS_VALID((pri))) +#define INTERRUPT_PRIORITY_ASSERT(pri) ASSERT(INTERRUPT_PRIORITY_IS_VALID((pri))) + +#define nrf_drv_irq_handler_t nrfx_irq_handler_t +#define nrf_drv_bitpos_to_event nrfx_bitpos_to_event +#define nrf_drv_event_to_bitpos nrfx_event_to_bitpos +#define nrf_drv_get_IRQn nrfx_get_irq_number +#define nrf_drv_is_in_RAM nrfx_is_in_ram + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_COMMON_H__ diff --git a/integration/nrfx/legacy/nrf_drv_gpiote.h b/integration/nrfx/legacy/nrf_drv_gpiote.h new file mode 100644 index 0000000..8974c9b --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_gpiote.h @@ -0,0 +1,139 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_DRV_GPIOTE_H__ +#define NRF_DRV_GPIOTE_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_gpiote GPIOTE driver - legacy layer + * @{ + * @ingroup nrf_gpiote + * @brief Layer providing compatibility with the former API. + */ + +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_gpiote_in_config_t nrf_drv_gpiote_in_config_t; +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_gpiote_pin_t nrf_drv_gpiote_pin_t; +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_gpiote_out_config_t nrf_drv_gpiote_out_config_t; +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_gpiote_evt_handler_t nrf_drv_gpiote_evt_handler_t; + +/** @brief Macro for forwarding the new implementation. */ +#define GPIOTE_CONFIG_IN_SENSE_LOTOHI NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI +/** @brief Macro for forwarding the new implementation. */ +#define GPIOTE_CONFIG_IN_SENSE_HITOLO NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO +/** @brief Macro for forwarding the new implementation. */ +#define GPIOTE_CONFIG_IN_SENSE_TOGGLE NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE +/** @brief Macro for forwarding the new implementation. */ +#define GPIOTE_RAW_CONFIG_IN_SENSE_LOTOHI NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_LOTOHI +/** @brief Macro for forwarding the new implementation. */ +#define GPIOTE_RAW_CONFIG_IN_SENSE_HITOLO NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_HITOLO +/** @brief Macro for forwarding the new implementation. */ +#define GPIOTE_RAW_CONFIG_IN_SENSE_TOGGLE NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_TOGGLE +/** @brief Macro for forwarding the new implementation. */ +#define GPIOTE_CONFIG_OUT_SIMPLE NRFX_GPIOTE_CONFIG_OUT_SIMPLE +/** @brief Macro for forwarding the new implementation. */ +#define GPIOTE_CONFIG_OUT_TASK_LOW NRFX_GPIOTE_CONFIG_OUT_TASK_LOW +/** @brief Macro for forwarding the new implementation. */ +#define GPIOTE_CONFIG_OUT_TASK_HIGH NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH +/** @brief Macro for forwarding the new implementation. */ +#define GPIOTE_CONFIG_OUT_TASK_TOGGLE NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_init nrfx_gpiote_init +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_is_init nrfx_gpiote_is_init +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_uninit nrfx_gpiote_uninit +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_out_init nrfx_gpiote_out_init +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_out_uninit nrfx_gpiote_out_uninit +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_out_set nrfx_gpiote_out_set +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_out_clear nrfx_gpiote_out_clear +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_out_toggle nrfx_gpiote_out_toggle +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_out_task_enable nrfx_gpiote_out_task_enable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_out_task_disable nrfx_gpiote_out_task_disable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_out_task_addr_get nrfx_gpiote_out_task_addr_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_in_init nrfx_gpiote_in_init +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_in_uninit nrfx_gpiote_in_uninit +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_in_event_enable nrfx_gpiote_in_event_enable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_in_event_disable nrfx_gpiote_in_event_disable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_in_is_set nrfx_gpiote_in_is_set +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_in_event_addr_get nrfx_gpiote_in_event_addr_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_set_task_addr_get nrfx_gpiote_set_task_addr_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_clr_task_addr_get nrfx_gpiote_clr_task_addr_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_out_task_force nrfx_gpiote_out_task_force +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_out_task_trigger nrfx_gpiote_out_task_trigger +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_set_task_trigger nrfx_gpiote_set_task_trigger +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_gpiote_clr_task_trigger nrfx_gpiote_clr_task_trigger + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif //NRF_DRV_GPIOTE_H__ diff --git a/integration/nrfx/legacy/nrf_drv_power.c b/integration/nrfx/legacy/nrf_drv_power.c new file mode 100644 index 0000000..e4ebb25 --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_power.c @@ -0,0 +1,417 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(POWER) +#include "nrf_drv_power.h" +#include +#ifdef SOFTDEVICE_PRESENT +#include "nrf_sdh.h" +#include "nrf_sdh_soc.h" +#endif + +#include + +// The structure with default configuration data. +static const nrfx_power_config_t m_drv_power_config_default = +{ + .dcdcen = NRFX_POWER_CONFIG_DEFAULT_DCDCEN, +#if NRF_POWER_HAS_VDDH + .dcdcenhv = NRFX_POWER_CONFIG_DEFAULT_DCDCENHV, +#endif +}; + +static bool m_initialized; + +bool nrf_drv_power_init_check(void) +{ + return m_initialized; +} + +ret_code_t nrf_drv_power_init(nrf_drv_power_config_t const * p_config) +{ + if (m_initialized) + { + return NRF_ERROR_MODULE_ALREADY_INITIALIZED; + } + +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + return NRF_ERROR_INVALID_STATE; + } +#endif + if (p_config == NULL) + { + p_config = &m_drv_power_config_default; + } + + ret_code_t err_code = nrfx_power_init(p_config); + if (err_code == NRFX_SUCCESS) + { + m_initialized = true; + } + return err_code; +} + +void nrf_drv_power_uninit() +{ + nrfx_power_uninit(); + nrf_drv_power_pof_uninit(); +#if NRF_POWER_HAS_SLEEPEVT + nrf_drv_power_sleepevt_uninit(); +#endif +#if NRF_POWER_HAS_USBREG + nrf_drv_power_usbevt_uninit(); +#endif + m_initialized = false; +} + +ret_code_t nrf_drv_power_pof_init(nrf_drv_power_pofwarn_config_t const * p_config) +{ + ret_code_t err_code = NRF_SUCCESS; + nrfx_power_pof_init(p_config); +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + /* Currently when SD is enabled - the configuration can be changed + * in very limited range. + * It is the SoftDevice limitation. + */ +#if NRF_POWER_HAS_VDDH + if (p_config->thrvddh != nrf_power_pofcon_vddh_get()) + { + /* Cannot change THRVDDH with current SD API */ + return NRF_ERROR_INVALID_STATE; + } +#endif + if (p_config->thr != nrf_power_pofcon_get(NULL)) + { + /* Only limited number of THR values are supported and + * the values taken by SD is different than the one in hardware + */ + uint8_t thr; + switch(p_config->thr) + { + case NRF_POWER_POFTHR_V21: + thr = NRF_POWER_THRESHOLD_V21; + break; + case NRF_POWER_POFTHR_V23: + thr = NRF_POWER_THRESHOLD_V23; + break; + case NRF_POWER_POFTHR_V25: + thr = NRF_POWER_THRESHOLD_V25; + break; + case NRF_POWER_POFTHR_V27: + thr = NRF_POWER_THRESHOLD_V27; + break; + default: + /* Cannot configure */ + nrfx_power_pof_uninit(); + return NRF_ERROR_INVALID_STATE; + } + err_code = sd_power_pof_threshold_set(thr); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + } + err_code = sd_power_pof_enable(true); + } + else +#endif /* SOFTDEVICE_PRESENT */ + { + nrfx_power_pof_enable(p_config); + } + return err_code; +} + +void nrf_drv_power_pof_uninit() +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + ret_code_t err_code = sd_power_pof_enable(false); + ASSERT(err_code == NRF_SUCCESS); + UNUSED_VARIABLE(err_code); //handle no-debug case + } + else +#endif + { + nrfx_power_pof_disable(); + } + nrfx_power_pof_uninit(); +} + +#if NRF_POWER_HAS_SLEEPEVT +ret_code_t nrf_drv_power_sleepevt_init(nrf_drv_power_sleepevt_config_t const * p_config) +{ + if (p_config->handler != NULL) + { +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + if ((p_config->en_enter) || (p_config->en_exit)) + { + return NRF_ERROR_INVALID_STATE; + } + } + else +#endif + { + nrfx_power_sleepevt_enable(p_config); + } + } + return NRF_SUCCESS; +} + +void nrf_drv_power_sleepevt_uninit(void) +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + /* Nothing to do */ + } + else +#endif + { + nrfx_power_sleepevt_disable(); + } + nrfx_power_sleepevt_uninit(); +} +#endif /* NRF_POWER_HAS_SLEEPEVT */ + +#if NRF_POWER_HAS_USBREG + +#ifdef SOFTDEVICE_PRESENT +static ret_code_t nrf_drv_power_sd_usbevt_enable(bool enable) +{ + ret_code_t err_code; + err_code = sd_power_usbdetected_enable(enable); + ASSERT(err_code == NRF_SUCCESS); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = sd_power_usbpwrrdy_enable(enable); + ASSERT(err_code == NRF_SUCCESS); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = sd_power_usbremoved_enable(enable); + ASSERT(err_code == NRF_SUCCESS); + return err_code; +} +#endif // SOFTDEVICE_PRESENT + +ret_code_t nrf_drv_power_usbevt_init(nrf_drv_power_usbevt_config_t const * p_config) +{ + nrf_drv_power_usbevt_uninit(); + nrfx_power_usbevt_init(p_config); +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + ret_code_t err_code = nrf_drv_power_sd_usbevt_enable(true); + ASSERT(err_code == NRF_SUCCESS); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + uint32_t regstatus; + err_code = sd_power_usbregstatus_get(®status); + ASSERT(err_code == NRF_SUCCESS); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + if (regstatus & POWER_USBREGSTATUS_VBUSDETECT_Msk) + { + nrfx_power_usb_event_handler_t usbevt_handler = nrfx_power_usb_handler_get(); + ASSERT(usbevt_handler != NULL); + usbevt_handler(NRFX_POWER_USB_EVT_DETECTED); + } + } + else +#endif + { + nrfx_power_usbevt_enable(); + } + return NRF_SUCCESS; +} + +void nrf_drv_power_usbevt_uninit(void) +{ +#ifdef SOFTDEVICE_PRESENT + CRITICAL_REGION_ENTER(); + if (nrf_sdh_is_enabled()) + { + ret_code_t err_code = nrf_drv_power_sd_usbevt_enable(false); + ASSERT(err_code == NRF_SUCCESS); + UNUSED_VARIABLE(err_code); + } + else +#endif + { + nrfx_power_usbevt_disable(); + } +#ifdef SOFTDEVICE_PRESENT + CRITICAL_REGION_EXIT(); +#endif + nrfx_power_usbevt_uninit(); +} +#endif /* NRF_POWER_HAS_USBREG */ + +#ifdef SOFTDEVICE_PRESENT +static void nrf_drv_power_sdh_soc_evt_handler(uint32_t evt_id, void * p_context); +static void nrf_drv_power_sdh_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context); + +NRF_SDH_SOC_OBSERVER(m_soc_observer, POWER_CONFIG_SOC_OBSERVER_PRIO, + nrf_drv_power_sdh_soc_evt_handler, NULL); + +NRF_SDH_STATE_OBSERVER(m_sd_observer, POWER_CONFIG_STATE_OBSERVER_PRIO) = +{ + .handler = nrf_drv_power_sdh_state_evt_handler, + .p_context = NULL +}; + +static void nrf_drv_power_sdh_soc_evt_handler(uint32_t evt_id, void * p_context) +{ + if (evt_id == NRF_EVT_POWER_FAILURE_WARNING) + { + nrfx_power_pofwarn_event_handler_t pofwarn_handler = nrfx_power_pof_handler_get(); + /* Cannot be null if event is enabled */ + ASSERT(pofwarn_handler != NULL); + pofwarn_handler(); + } + +#if NRF_POWER_HAS_USBREG + nrfx_power_usb_event_handler_t usbevt_handler = nrfx_power_usb_handler_get(); + if (usbevt_handler != NULL) + { + switch (evt_id) + { + case NRF_EVT_POWER_USB_POWER_READY: + usbevt_handler(NRFX_POWER_USB_EVT_READY); + break; + + case NRF_EVT_POWER_USB_DETECTED: + usbevt_handler(NRFX_POWER_USB_EVT_DETECTED); + break; + + case NRF_EVT_POWER_USB_REMOVED: + usbevt_handler(NRFX_POWER_USB_EVT_REMOVED); + break; + + default: + break; + + } + } +#endif +} + +static void nrf_drv_power_on_sd_enable(void) +{ + ASSERT(m_initialized); /* This module has to be enabled first */ + CRITICAL_REGION_ENTER(); + if (nrfx_power_pof_handler_get() != NULL) + { + ret_code_t err_code = sd_power_pof_enable(true); + ASSERT(err_code == NRF_SUCCESS); + UNUSED_VARIABLE(err_code); //handle no-debug case + } + CRITICAL_REGION_EXIT(); + +#if NRF_POWER_HAS_USBREG + if (nrfx_power_usb_handler_get() != NULL) + { + ret_code_t err_code = nrf_drv_power_sd_usbevt_enable(true); + ASSERT(err_code == NRF_SUCCESS); + UNUSED_VARIABLE(err_code); //handle no-debug case + } +#endif +} + +static void nrf_drv_power_on_sd_disable(void) +{ + /* Reinit interrupts */ + ASSERT(m_initialized); + NRFX_IRQ_PRIORITY_SET(POWER_CLOCK_IRQn, CLOCK_CONFIG_IRQ_PRIORITY); + NRFX_IRQ_ENABLE(POWER_CLOCK_IRQn); + if (nrfx_power_pof_handler_get() != NULL) + { + nrf_power_int_enable(NRF_POWER_INT_POFWARN_MASK); + } + +#if NRF_POWER_HAS_USBREG + if (nrfx_power_usb_handler_get() != NULL) + { + nrf_power_int_enable( + NRF_POWER_INT_USBDETECTED_MASK | + NRF_POWER_INT_USBREMOVED_MASK | + NRF_POWER_INT_USBPWRRDY_MASK); + } +#endif +} + +static void nrf_drv_power_sdh_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context) +{ + switch (state) + { + case NRF_SDH_EVT_STATE_ENABLED: + nrf_drv_power_on_sd_enable(); + break; + + case NRF_SDH_EVT_STATE_DISABLED: + nrf_drv_power_on_sd_disable(); + break; + + default: + break; + } +} + +#endif // SOFTDEVICE_PRESENT +#endif //POWER_ENABLED diff --git a/integration/nrfx/legacy/nrf_drv_power.h b/integration/nrfx/legacy/nrf_drv_power.h new file mode 100644 index 0000000..e039b2c --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_power.h @@ -0,0 +1,232 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_POWER_H__ +#define NRF_DRV_POWER_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_power POWER driver - legacy layer + * @{ + * @ingroup nrf_power + * + * @brief Layer providing compatibility with the former API. + */ + +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_power_config_t nrf_drv_power_config_t; +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_power_pofwarn_config_t nrf_drv_power_pofwarn_config_t; +#if NRF_POWER_HAS_SLEEPEVT || defined(__SDK_DOXYGEN__) +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_power_sleepevt_config_t nrf_drv_power_sleepevt_config_t; +#endif +#if NRF_POWER_HAS_USBREG || defined(__SDK_DOXYGEN__) +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_power_usbevt_config_t nrf_drv_power_usbevt_config_t; +#endif + +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_MODE_CONSTLAT NRFX_POWER_MODE_CONSTLAT +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_MODE_LOWPWR NRFX_POWER_MODE_LOWPWR +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_mode_t nrfx_power_mode_t +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_SLEEP_EVT_ENTER NRFX_POWER_SLEEP_EVT_ENTER +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_SLEEP_EVT_EXIT NRFX_POWER_SLEEP_EVT_EXIT +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_sleep_evt_t nrfx_power_sleep_evt_t +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_USB_EVT_DETECTED NRFX_POWER_USB_EVT_DETECTED +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_USB_EVT_REMOVED NRFX_POWER_USB_EVT_REMOVED +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_USB_EVT_READY NRFX_POWER_USB_EVT_READY +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_usb_evt_t nrfx_power_usb_evt_t +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_USB_STATE_DISCONNECTED NRFX_POWER_USB_STATE_DISCONNECTED +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_USB_STATE_CONNECTED NRFX_POWER_USB_STATE_CONNECTED +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_POWER_USB_STATE_READY NRFX_POWER_USB_STATE_READY +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_usb_state_t nrfx_power_usb_state_t +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_pofwarn_event_handler_t nrfx_power_pofwarn_event_handler_t +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_sleep_event_handler_t nrfx_power_sleep_event_handler_t +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_usb_event_handler_t nrfx_power_usb_event_handler_t + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_power_usbstatus_get nrfx_power_usbstatus_get + +/** + * @brief Function for checking if driver is already initialized + * + * This function is used to check whether common POWER_CLOCK interrupt + * should be disabled or not if @ref nrf_drv_clock tries to disable the interrupt. + * + * @retval true Driver is initialized + * @retval false Driver is uninitialized + * + * @sa nrf_drv_power_uninit + */ +bool nrf_drv_power_init_check(void); + +/** + * @brief Initialize power module driver + * + * Enabled power module driver would process all the interrupts from power system. + * + * @param[in] p_config Driver configuration. Can be NULL - the default configuration + * from @em sdk_config.h file would be used then. + * + * @retval NRF_ERROR_INVALID_STATE Power driver has to be enabled + * before SoftDevice. + * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED Module is initialized already. + * @retval NRF_SUCCESS Successfully initialized. + */ +ret_code_t nrf_drv_power_init(nrf_drv_power_config_t const * p_config); + +/** + * @brief Unintialize power module driver + * + * Disables all the interrupt handling in the module. + * + * @sa nrf_drv_power_init + */ +void nrf_drv_power_uninit(void); + +/** + * @brief Initialize power failure comparator + * + * Configures and setups the power failure comparator and enables it. + * + * @param[in] p_config Configuration with values and event handler. + * If event handler is set to NULL, interrupt would be disabled. + * + * @retval NRF_ERROR_INVALID_STATE POF is initialized when SD is enabled and + * the configuration differs from the old one and + * is not possible to be set using SD interface. + * @retval NRF_SUCCESS Successfully initialized and configured. + */ +ret_code_t nrf_drv_power_pof_init(nrf_drv_power_pofwarn_config_t const * p_config); + +/** + * @brief Turn off the power failure comparator + * + * Disables and clears the settings of the power failure comparator. + */ +void nrf_drv_power_pof_uninit(void); + +#if NRF_POWER_HAS_SLEEPEVT || defined(__SDK_DOXYGEN__) + +/** + * @brief Initialize sleep entering and exiting events processing + * + * Configures and setups the sleep event processing. + * + * @param[in] p_config Configuration with values and event handler. + * + * @sa nrf_drv_power_sleepevt_uninit + * + * @note Sleep events are not available when SoftDevice is enabled. + * @note If sleep event is enabled when SoftDevice is initialized, sleep events + * would be automatically disabled - it is the limitation of the + * SoftDevice itself. + * + * @retval NRF_ERROR_INVALID_STATE This event cannot be initialized + * when SD is enabled. + * @retval NRF_SUCCESS Successfully initialized and configured. + */ +ret_code_t nrf_drv_power_sleepevt_init(nrf_drv_power_sleepevt_config_t const * p_config); + +/** + * @brief Uninitialize sleep entering and exiting events processing + * + * @sa nrf_drv_power_sleepevt_init + */ +void nrf_drv_power_sleepevt_uninit(void); + +#endif // NRF_POWER_HAS_SLEEPEVT || defined(__SDK_DOXYGEN__) + +#if NRF_POWER_HAS_USBREG || defined(__SDK_DOXYGEN__) + +/** + * @brief Initialize USB power event processing + * + * Configures and setups the USB power event processing. + * + * @param[in] p_config Configuration with values and event handler. + * + * @sa nrf_drv_power_usbevt_uninit + * + * @retval NRF_ERROR_INVALID_STATE This event cannot be initialized + * when SD is enabled and SD does not support + * USB power events. + * @retval NRF_SUCCESS Successfully initialized and configured. + */ +ret_code_t nrf_drv_power_usbevt_init(nrf_drv_power_usbevt_config_t const * p_config); + +/** + * @brief Uninitalize USB power event processing + * + * @sa nrf_drv_power_usbevt_init + */ +void nrf_drv_power_usbevt_uninit(void); + +#endif // NRF_POWER_HAS_USBREG || defined(__SDK_DOXYGEN__) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_POWER_H__ diff --git a/integration/nrfx/legacy/nrf_drv_ppi.c b/integration/nrfx/legacy/nrf_drv_ppi.c new file mode 100644 index 0000000..07a3e9b --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_ppi.c @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_drv_ppi.h" + +static nrfx_drv_state_t m_drv_state; /**< Driver state */ + +ret_code_t nrf_drv_ppi_init(void) +{ + if (m_drv_state == NRFX_DRV_STATE_UNINITIALIZED) + { + m_drv_state = NRFX_DRV_STATE_INITIALIZED; + } + else + { + return NRF_ERROR_MODULE_ALREADY_INITIALIZED; + } + return NRF_SUCCESS; +} + +ret_code_t nrf_drv_ppi_uninit(void) +{ + if (m_drv_state == NRFX_DRV_STATE_UNINITIALIZED) + { + return NRF_ERROR_INVALID_STATE; + } + + m_drv_state = NRFX_DRV_STATE_UNINITIALIZED; + nrfx_ppi_free_all(); + return NRF_SUCCESS; +} + diff --git a/integration/nrfx/legacy/nrf_drv_ppi.h b/integration/nrfx/legacy/nrf_drv_ppi.h new file mode 100644 index 0000000..e3c38e0 --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_ppi.h @@ -0,0 +1,130 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_PPI_H__ +#define NRF_DRV_PPI_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_ppi PPI driver - legacy layer + * @{ + * @ingroup nrf_ppi + * + * @brief @tagAPI52 Layer providing compatibility with the former API. + */ + +/** @brief Macro for forwarding the new implementation. */ +#define NRF_PPI_ALL_APP_CHANNELS_MASK NRFX_PPI_ALL_APP_CHANNELS_MASK +/** @brief Macro for forwarding the new implementation. */ +#define NRF_PPI_PROG_APP_CHANNELS_MASK NRFX_PPI_PROG_APP_CHANNELS_MASK +/** @brief Macro for forwarding the new implementation. */ +#define NRF_PPI_ALL_APP_GROUPS_MASK NRFX_PPI_ALL_APP_GROUPS_MASK + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_channel_alloc nrfx_ppi_channel_alloc +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_channel_free nrfx_ppi_channel_free +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_channel_assign nrfx_ppi_channel_assign +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_channel_fork_assign nrfx_ppi_channel_fork_assign +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_channel_enable nrfx_ppi_channel_enable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_channel_disable nrfx_ppi_channel_disable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_channel_to_mask nrfx_ppi_channel_to_mask +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_channels_include_in_group nrfx_ppi_channels_include_in_group +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_channel_include_in_group nrfx_ppi_channel_include_in_group +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_channels_remove_from_group nrfx_ppi_channels_remove_from_group +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_channel_remove_from_group nrfx_ppi_channel_remove_from_group + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_group_alloc nrfx_ppi_group_alloc +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_group_free nrfx_ppi_group_free +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_group_clear nrfx_ppi_group_clear +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_group_enable nrfx_ppi_group_enable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_group_disable nrfx_ppi_group_disable + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_task_addr_get nrfx_ppi_task_addr_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_task_addr_group_enable_get nrfx_ppi_task_addr_group_enable_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_ppi_task_addr_group_disable_get nrfx_ppi_task_addr_group_disable_get + +/** + * @brief Function for initializing PPI module. + * + * @retval NRF_SUCCESS If the module was successfully initialized. + * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED If the module has already been initialized. + */ +ret_code_t nrf_drv_ppi_init(void); + +/** + * @brief Function for uninitializing the PPI module. + * + * This function also disables all channels and clears the channel groups. + * + * @retval NRF_SUCCESS If the module was successfully uninitialized. + * @retval NRF_ERROR_INVALID_STATE If the module has not been initialized yet. + */ +ret_code_t nrf_drv_ppi_uninit(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_PPI_H__ diff --git a/integration/nrfx/legacy/nrf_drv_pwm.h b/integration/nrfx/legacy/nrf_drv_pwm.h new file mode 100644 index 0000000..e19a32c --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_pwm.h @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_PWM_H__ +#define NRF_DRV_PWM_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_pwm PWM driver - legacy layer + * @{ + * @ingroup nrf_pwm + * + * @brief @tagAPI52 Layer providing compatibility with the former API. + */ + +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_pwm_t nrf_drv_pwm_t; +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_pwm_config_t nrf_drv_pwm_config_t; + +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_PWM_INSTANCE NRFX_PWM_INSTANCE +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_PWM_PIN_NOT_USED NRFX_PWM_PIN_NOT_USED +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_PWM_PIN_INVERTED NRFX_PWM_PIN_INVERTED +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_PWM_DEFAULT_CONFIG NRFX_PWM_DEFAULT_CONFIG + +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_PWM_FLAG_STOP NRFX_PWM_FLAG_STOP +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_PWM_FLAG_LOOP NRFX_PWM_FLAG_LOOP +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ0 NRFX_PWM_FLAG_SIGNAL_END_SEQ0 +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ1 NRFX_PWM_FLAG_SIGNAL_END_SEQ1 +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_PWM_FLAG_NO_EVT_FINISHED NRFX_PWM_FLAG_NO_EVT_FINISHED +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_PWM_FLAG_START_VIA_TASK NRFX_PWM_FLAG_START_VIA_TASK +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_flag_t nrfx_pwm_flag_t +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_PWM_EVT_FINISHED NRFX_PWM_EVT_FINISHED +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_PWM_EVT_END_SEQ0 NRFX_PWM_EVT_END_SEQ0 +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_PWM_EVT_END_SEQ1 NRFX_PWM_EVT_END_SEQ1 +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_PWM_EVT_STOPPED NRFX_PWM_EVT_STOPPED +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_evt_type_t nrfx_pwm_evt_type_t +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_handler_t nrfx_pwm_handler_t + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_init nrfx_pwm_init +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_uninit nrfx_pwm_uninit +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_simple_playback nrfx_pwm_simple_playback +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_complex_playback nrfx_pwm_complex_playback +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_step nrfx_pwm_step +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_stop nrfx_pwm_stop +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_is_stopped nrfx_pwm_is_stopped +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_sequence_update nrfx_pwm_sequence_update +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_sequence_values_update nrfx_pwm_sequence_values_update +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_sequence_length_update nrfx_pwm_sequence_length_update +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_sequence_repeats_update nrfx_pwm_sequence_repeats_update +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_sequence_end_delay_update nrfx_pwm_sequence_end_delay_update + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_task_address_get nrfx_pwm_task_address_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_pwm_event_address_get nrfx_pwm_event_address_get + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_PWM_H__ diff --git a/integration/nrfx/legacy/nrf_drv_rng.c b/integration/nrfx/legacy/nrf_drv_rng.c new file mode 100644 index 0000000..df74d7b --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_rng.c @@ -0,0 +1,283 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(RNG) + +#include +#include +#include "nrf_drv_rng.h" +#include "nordic_common.h" +#include "app_util_platform.h" +#include "nrf_assert.h" +#include "nrf_queue.h" + +#ifdef SOFTDEVICE_PRESENT + #include "nrf_sdh.h" +#endif // SOFTDEVICE_PRESENT + +#define NRF_LOG_MODULE_NAME rng + +#if RNG_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL RNG_CONFIG_LOG_LEVEL + #define NRF_LOG_INFO_COLOR RNG_CONFIG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR RNG_CONFIG_DEBUG_COLOR +#else //RNG_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL 0 +#endif //RNG_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +typedef struct +{ + nrfx_drv_state_t state; + nrf_drv_rng_config_t config; +} nrf_drv_rng_cb_t; + +static nrf_drv_rng_cb_t m_rng_cb; +NRF_QUEUE_DEF(uint8_t, m_rand_pool, RNG_CONFIG_POOL_SIZE, NRF_QUEUE_MODE_OVERFLOW); +static const nrf_drv_rng_config_t m_default_config = NRF_DRV_RNG_DEFAULT_CONFIG; + +#ifdef SOFTDEVICE_PRESENT + #define SD_RAND_POOL_SIZE (64) + + STATIC_ASSERT(RNG_CONFIG_POOL_SIZE == SD_RAND_POOL_SIZE); + + #define NRF_DRV_RNG_LOCK() CRITICAL_REGION_ENTER() + #define NRF_DRV_RNG_RELEASE() CRITICAL_REGION_EXIT() + #define NRF_DRV_RNG_SD_IS_ENABLED() nrf_sdh_is_enabled() +#else + #define NRF_DRV_RNG_LOCK() do { } while (0) + #define NRF_DRV_RNG_RELEASE() do { } while (0) + #define NRF_DRV_RNG_SD_IS_ENABLED() false +#endif // SOFTDEVICE_PRESENT + + +static void nrfx_rng_handler(uint8_t rng_val) +{ + NRF_DRV_RNG_LOCK(); + if (!NRF_DRV_RNG_SD_IS_ENABLED()) + { + UNUSED_RETURN_VALUE(nrf_queue_push(&m_rand_pool, &rng_val)); + + if (nrf_queue_is_full(&m_rand_pool)) + { + nrfx_rng_stop(); + } + + NRF_LOG_DEBUG("Event: NRF_RNG_EVENT_VALRDY."); + } + NRF_DRV_RNG_RELEASE(); + +} + +ret_code_t nrf_drv_rng_init(nrf_drv_rng_config_t const * p_config) +{ + ret_code_t err_code = NRF_SUCCESS; + if (m_rng_cb.state != NRFX_DRV_STATE_UNINITIALIZED) + { + return NRF_ERROR_MODULE_ALREADY_INITIALIZED; + } + + if (p_config == NULL) + { + p_config = &m_default_config; + } + m_rng_cb.config = *p_config; + + NRF_DRV_RNG_LOCK(); + + if (!NRF_DRV_RNG_SD_IS_ENABLED()) + { + err_code = nrfx_rng_init(&m_rng_cb.config, nrfx_rng_handler); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + nrfx_rng_start(); + } + m_rng_cb.state = NRFX_DRV_STATE_INITIALIZED; + + NRF_DRV_RNG_RELEASE(); + + return err_code; +} + +void nrf_drv_rng_uninit(void) +{ + ASSERT(m_rng_cb.state == NRFX_DRV_STATE_INITIALIZED); + + NRF_DRV_RNG_LOCK(); + + if (!NRF_DRV_RNG_SD_IS_ENABLED()) + { + nrfx_rng_stop(); + nrfx_rng_uninit(); + } + + NRF_DRV_RNG_RELEASE(); + + nrf_queue_reset(&m_rand_pool); + m_rng_cb.state = NRFX_DRV_STATE_UNINITIALIZED; + NRF_LOG_INFO("Uninitialized."); +} + +void nrf_drv_rng_bytes_available(uint8_t * p_bytes_available) +{ + ASSERT(m_rng_cb.state == NRFX_DRV_STATE_INITIALIZED); + +#ifdef SOFTDEVICE_PRESENT + if (NRF_DRV_RNG_SD_IS_ENABLED()) + { + if (NRF_SUCCESS == sd_rand_application_bytes_available_get(p_bytes_available)) + { + return; + } + } +#endif // SOFTDEVICE_PRESENT + + *p_bytes_available = nrf_queue_utilization_get(&m_rand_pool); + + NRF_LOG_INFO("Function: %s, available bytes: %d.", (uint32_t)__func__, *p_bytes_available); +} + +ret_code_t nrf_drv_rng_rand(uint8_t * p_buff, uint8_t length) +{ + ret_code_t err_code = NRF_SUCCESS; + ASSERT(m_rng_cb.state == NRFX_DRV_STATE_INITIALIZED); + +#ifdef SOFTDEVICE_PRESENT + do { + bool sd_is_enabled; + NRF_DRV_RNG_LOCK(); + sd_is_enabled = NRF_DRV_RNG_SD_IS_ENABLED(); + if (!sd_is_enabled) +#endif // SOFTDEVICE_PRESENT + { + err_code = nrf_queue_read(&m_rand_pool, p_buff, (uint32_t)length); + nrfx_rng_start(); + } +#ifdef SOFTDEVICE_PRESENT + NRF_DRV_RNG_RELEASE(); + + if (sd_is_enabled) + { + err_code = sd_rand_application_vector_get(p_buff, length); + if (err_code == NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES) + { + err_code = NRF_ERROR_NOT_FOUND; + } + } + } while (err_code == NRF_ERROR_SOFTDEVICE_NOT_ENABLED); +#endif // SOFTDEVICE_PRESENT + ASSERT((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NOT_FOUND)); + +#if defined(RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED) && (RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED != 0) + NRF_LOG_DEBUG("Rand buffer data:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_buff, length); +#endif // RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + + return err_code; +} + +void nrf_drv_rng_block_rand(uint8_t * p_buff, uint32_t length) +{ + ASSERT(m_rng_cb.state == NRFX_DRV_STATE_INITIALIZED); + + while (length) + { + uint32_t len = MIN(length, RNG_CONFIG_POOL_SIZE); + ret_code_t err_code; + + do { + err_code = nrf_drv_rng_rand(p_buff, len); + } while (err_code != NRF_SUCCESS); + + length -= len; + p_buff += len; + } + + NRF_LOG_DEBUG("Rand buffer data:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_buff, length); +} + +#ifdef SOFTDEVICE_PRESENT +static void sd_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context) +{ + switch (state) + { + case NRF_SDH_EVT_STATE_ENABLE_PREPARE: + if (m_rng_cb.state == NRFX_DRV_STATE_INITIALIZED) + { + nrfx_rng_stop(); + nrfx_rng_uninit(); + } + break; + + case NRF_SDH_EVT_STATE_DISABLED: + NRF_DRV_RNG_LOCK(); + if (m_rng_cb.state == NRFX_DRV_STATE_INITIALIZED) + { + ret_code_t err_code = nrfx_rng_init(&m_rng_cb.config, nrfx_rng_handler); + if (err_code != NRF_SUCCESS) + { + ASSERT(false); + } + nrfx_rng_start(); + } + NRF_DRV_RNG_RELEASE(); + break; + + default: + break; + } +} + +NRF_SDH_STATE_OBSERVER(m_sd_state_observer, RNG_CONFIG_STATE_OBSERVER_PRIO) = +{ + .handler = sd_state_evt_handler, + .p_context = NULL, +}; + +#endif // SOFTDEVICE_PRESENT + +#endif // NRF_MODULE_ENABLED(RNG) diff --git a/integration/nrfx/legacy/nrf_drv_rng.h b/integration/nrfx/legacy/nrf_drv_rng.h new file mode 100644 index 0000000..d6def50 --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_rng.h @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_RNG_H__ +#define NRF_DRV_RNG_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_rng RNG driver - legacy layer + * @{ + * @ingroup nrf_rng + * + * @brief Layer providing compatibility with the former API. + */ + +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_rng_config_t nrf_drv_rng_config_t; + +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_RNG_DEFAULT_CONFIG NRFX_RNG_DEFAULT_CONFIG + +/** + * @brief Function for initializing the nrf_drv_rng module. + * + * @param[in] p_config Initial configuration. + * + * @retval NRF_SUCCESS Driver was successfully initialized. + * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED Driver was already initialized. + */ +ret_code_t nrf_drv_rng_init(nrf_drv_rng_config_t const * p_config); + +/** + * @brief Function for uninitializing the nrf_drv_rng module. + */ +void nrf_drv_rng_uninit(void); + +/** + * @brief Function for getting the number of currently available random bytes. + * + * @param[out] p_bytes_available The number of bytes currently available in the pool. + */ +void nrf_drv_rng_bytes_available(uint8_t * p_bytes_available); + +/** + * @brief Function for getting the vector of random numbers. + * + * @param[out] p_buff Pointer to uint8_t buffer for storing the bytes. + * @param[in] length Number of bytes to take from the pool and place in p_buff. + * + * @retval NRF_SUCCESS If the requested bytes were written to p_buff. + * @retval NRF_ERROR_NOT_FOUND If no bytes were written to the buffer because there were + * not enough bytes available in the pool. + */ +ret_code_t nrf_drv_rng_rand(uint8_t * p_buff, uint8_t length); + +/** + * @brief Blocking function for getting an arbitrary array of random numbers. + * + * @note This function may execute for a substantial amount of time depending on the length + * of the buffer required and on the state of the current internal pool of random numbers. + * + * @param[out] p_buff Pointer to uint8_t buffer for storing the bytes. + * @param[in] length Number of bytes place in p_buff. + */ +void nrf_drv_rng_block_rand(uint8_t * p_buff, uint32_t length); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_RNG_H__ diff --git a/integration/nrfx/legacy/nrf_drv_rtc.h b/integration/nrfx/legacy/nrf_drv_rtc.h new file mode 100644 index 0000000..29c216a --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_rtc.h @@ -0,0 +1,129 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_RTC_H__ +#define NRF_DRV_RTC_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_rtc RTC driver - legacy layer + * @{ + * @ingroup nrf_rtc + * + * @brief Layer providing compatibility with the former API. + */ + +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_rtc_t nrf_drv_rtc_t; +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_rtc_config_t nrf_drv_rtc_config_t; + +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_RTC_INSTANCE NRFX_RTC_INSTANCE +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_RTC_DEFAULT_CONFIG NRFX_RTC_DEFAULT_CONFIG +/** @brief Macro for forwarding the new implementation. */ +#define RTC_US_TO_TICKS NRFX_RTC_US_TO_TICKS + +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_RTC_INT_COMPARE0 NRFX_RTC_INT_COMPARE0 +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_RTC_INT_COMPARE1 NRFX_RTC_INT_COMPARE1 +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_RTC_INT_COMPARE2 NRFX_RTC_INT_COMPARE2 +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_RTC_INT_COMPARE3 NRFX_RTC_INT_COMPARE3 +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_RTC_INT_TICK NRFX_RTC_INT_TICK +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_RTC_INT_OVERFLOW NRFX_RTC_INT_OVERFLOW +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_int_type_t nrfx_rtc_int_type_t +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_handler_t nrfx_rtc_handler_t + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_init nrfx_rtc_init +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_uninit nrfx_rtc_uninit +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_enable nrfx_rtc_enable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_disable nrfx_rtc_disable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_cc_set nrfx_rtc_cc_set +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_cc_disable nrfx_rtc_cc_disable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_tick_enable nrfx_rtc_tick_enable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_tick_disable nrfx_rtc_tick_disable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_overflow_enable nrfx_rtc_overflow_enable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_overflow_disable nrfx_rtc_overflow_disable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_max_ticks_get nrfx_rtc_max_ticks_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_int_disable nrfx_rtc_int_disable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_int_enable nrfx_rtc_int_enable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_counter_get nrfx_rtc_counter_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_counter_clear nrfx_rtc_counter_clear + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_task_address_get nrfx_rtc_task_address_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_rtc_event_address_get nrfx_rtc_event_address_get + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_RTC_H__ diff --git a/integration/nrfx/legacy/nrf_drv_saadc.h b/integration/nrfx/legacy/nrf_drv_saadc.h new file mode 100644 index 0000000..35b1ab6 --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_saadc.h @@ -0,0 +1,143 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_SAADC_H__ +#define NRF_DRV_SAADC_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_saadc SAADC driver - legacy layer + * @{ + * @ingroup nrf_saadc + * + * @brief @tagAPI52 Layer providing compatibility with the former API. + */ + +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_saadc_config_t nrf_drv_saadc_config_t; + +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_SAADC_EVT_DONE NRFX_SAADC_EVT_DONE +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_SAADC_EVT_LIMIT NRFX_SAADC_EVT_LIMIT +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_SAADC_EVT_CALIBRATEDONE NRFX_SAADC_EVT_CALIBRATEDONE +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_evt_type_t nrfx_saadc_evt_type_t +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_done_evt_t nrfx_saadc_done_evt_t +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_limit_evt_t nrfx_saadc_limit_evt_t +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_evt_t nrfx_saadc_evt_t +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_event_handler_t nrfx_saadc_event_handler_t + +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_SAADC_LIMITH_DISABLED NRFX_SAADC_LIMITH_DISABLED +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_SAADC_LIMITL_DISABLED NRFX_SAADC_LIMITL_DISABLED +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_SAADC_DEFAULT_CONFIG NRFX_SAADC_DEFAULT_CONFIG +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE \ + NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL \ + NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_uninit nrfx_saadc_uninit +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_channel_init nrfx_saadc_channel_init +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_channel_uninit nrfx_saadc_channel_uninit +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_sample nrfx_saadc_sample +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_sample_convert nrfx_saadc_sample_convert +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_buffer_convert nrfx_saadc_buffer_convert +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_calibrate_offset nrfx_saadc_calibrate_offset +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_is_busy nrfx_saadc_is_busy +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_abort nrfx_saadc_abort +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_limits_set nrfx_saadc_limits_set + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_saadc_sample_task_get nrfx_saadc_sample_task_get + +/** + * @brief Function for initializing the SAADC. + * + * @param[in] p_config Pointer to the structure with initial configuration. + * If NULL, the default one is used. + * @param[in] event_handler Event handler provided by the user. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the driver is already initialized. + * @retval NRF_ERROR_INVALID_PARAM If event_handler is NULL. + */ +__STATIC_INLINE ret_code_t nrf_drv_saadc_init(nrf_drv_saadc_config_t const * p_config, + nrf_drv_saadc_event_handler_t event_handler) +{ + if (p_config == NULL) + { + static const nrfx_saadc_config_t default_config = NRFX_SAADC_DEFAULT_CONFIG; + p_config = &default_config; + } + return nrfx_saadc_init(p_config, event_handler); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_SAADC_H__ diff --git a/integration/nrfx/legacy/nrf_drv_spi.c b/integration/nrfx/legacy/nrf_drv_spi.c new file mode 100644 index 0000000..63f1d1e --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_spi.c @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_drv_spi.h" + +#ifdef SPIM_PRESENT +#define INSTANCE_COUNT SPIM_COUNT +#else +#define INSTANCE_COUNT SPI_COUNT +#endif + +static nrf_drv_spi_evt_handler_t m_handlers[INSTANCE_COUNT]; +static void * m_contexts[INSTANCE_COUNT]; + +#ifdef SPIM_PRESENT +static void spim_evt_handler(nrfx_spim_evt_t const * p_event, + void * p_context) +{ + uint32_t inst_idx = (uint32_t)p_context; + nrf_drv_spi_evt_t const event = + { + .type = (nrf_drv_spi_evt_type_t)p_event->type, + .data = + { + .done = + { + .p_tx_buffer = p_event->xfer_desc.p_tx_buffer, + .tx_length = p_event->xfer_desc.tx_length, + .p_rx_buffer = p_event->xfer_desc.p_rx_buffer, + .rx_length = p_event->xfer_desc.rx_length, + } + } + }; + m_handlers[inst_idx](&event, m_contexts[inst_idx]); +} +#endif // SPIM_PRESENT + +#ifdef SPI_PRESENT +static void spi_evt_handler(nrfx_spi_evt_t const * p_event, + void * p_context) +{ + uint32_t inst_idx = (uint32_t)p_context; + nrf_drv_spi_evt_t const event = + { + .type = (nrf_drv_spi_evt_type_t)p_event->type, + .data = + { + .done = + { + .p_tx_buffer = p_event->xfer_desc.p_tx_buffer, + .tx_length = p_event->xfer_desc.tx_length, + .p_rx_buffer = p_event->xfer_desc.p_rx_buffer, + .rx_length = p_event->xfer_desc.rx_length, + } + } + }; + m_handlers[inst_idx](&event, m_contexts[inst_idx]); +} +#endif // SPI_PRESENT + +ret_code_t nrf_drv_spi_init(nrf_drv_spi_t const * const p_instance, + nrf_drv_spi_config_t const * p_config, + nrf_drv_spi_evt_handler_t handler, + void * p_context) +{ + uint32_t inst_idx = p_instance->inst_idx; + m_handlers[inst_idx] = handler; + m_contexts[inst_idx] = p_context; + + ret_code_t result = 0; + if (NRF_DRV_SPI_USE_SPIM) + { +#ifdef SPIM_PRESENT + nrfx_spim_config_t config_spim = NRFX_SPIM_DEFAULT_CONFIG; + config_spim.sck_pin = p_config->sck_pin; + config_spim.mosi_pin = p_config->mosi_pin; + config_spim.miso_pin = p_config->miso_pin; + config_spim.ss_pin = p_config->ss_pin; + config_spim.irq_priority = p_config->irq_priority; + config_spim.orc = p_config->orc; + config_spim.frequency = (nrf_spim_frequency_t)p_config->frequency; + config_spim.mode = (nrf_spim_mode_t)p_config->mode; + config_spim.bit_order = (nrf_spim_bit_order_t)p_config->bit_order; + result = nrfx_spim_init(&p_instance->u.spim, + &config_spim, + handler ? spim_evt_handler : NULL, + (void *)inst_idx); +#endif + } + else if (NRF_DRV_SPI_USE_SPI) + { + result = nrfx_spi_init(&p_instance->u.spi, + (nrfx_spi_config_t const *)p_config, + handler ? spi_evt_handler : NULL, + (void *)inst_idx); + } + return result; +} diff --git a/integration/nrfx/legacy/nrf_drv_spi.h b/integration/nrfx/legacy/nrf_drv_spi.h new file mode 100644 index 0000000..54077da --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_spi.h @@ -0,0 +1,615 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_SPI_H__ +#define NRF_DRV_SPI_H__ + +#include +#ifdef SPIM_PRESENT + #include +#else + // Compilers (at least the smart ones) will remove the SPIM related code + // (blocks starting with "if (NRF_DRV_SPI_USE_SPIM)") when it is not used, + // but to perform the compilation they need the following definitions. + #define nrfx_spim_init(...) 0 + #define nrfx_spim_uninit(...) + #define nrfx_spim_start_task_get(...) 0 + #define nrfx_spim_end_event_get(...) 0 + #define nrfx_spim_abort(...) +#endif + +#ifdef SPI_PRESENT + #include +#else + // Compilers (at least the smart ones) will remove the SPI related code + // (blocks starting with "if (NRF_DRV_SPI_USE_SPI)") when it is not used, + // but to perform the compilation they need the following definitions. + #define nrfx_spi_init(...) 0 + #define nrfx_spi_uninit(...) + #define nrfx_spi_start_task_get(...) 0 + #define nrfx_spi_end_event_get(...) 0 + #define nrfx_spi_abort(...) + + // This part is for old modules that use directly SPI HAL definitions + // (to make them compilable for chips that have only SPIM). + #define NRF_SPI_FREQ_125K NRF_SPIM_FREQ_125K + #define NRF_SPI_FREQ_250K NRF_SPIM_FREQ_250K + #define NRF_SPI_FREQ_500K NRF_SPIM_FREQ_500K + #define NRF_SPI_FREQ_1M NRF_SPIM_FREQ_1M + #define NRF_SPI_FREQ_2M NRF_SPIM_FREQ_2M + #define NRF_SPI_FREQ_4M NRF_SPIM_FREQ_4M + #define NRF_SPI_FREQ_8M NRF_SPIM_FREQ_8M + #define NRF_SPI_MODE_0 NRF_SPIM_MODE_0 + #define NRF_SPI_MODE_1 NRF_SPIM_MODE_1 + #define NRF_SPI_MODE_2 NRF_SPIM_MODE_2 + #define NRF_SPI_MODE_3 NRF_SPIM_MODE_3 + #define NRF_SPI_BIT_ORDER_MSB_FIRST NRF_SPIM_BIT_ORDER_MSB_FIRST + #define NRF_SPI_BIT_ORDER_LSB_FIRST NRF_SPIM_BIT_ORDER_LSB_FIRST +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_spi SPI master driver + * @{ + * @ingroup nrf_spi + * @brief Layer providing compatibility with the former API. + */ + +/** + * @brief SPI master driver instance data structure. + */ +typedef struct +{ + uint8_t inst_idx; + union + { +#ifdef SPIM_PRESENT + nrfx_spim_t spim; +#endif +#ifdef SPI_PRESENT + nrfx_spi_t spi; +#endif + } u; + bool use_easy_dma; +} nrf_drv_spi_t; + +/** + * @brief Macro for creating an SPI master driver instance. + */ +#define NRF_DRV_SPI_INSTANCE(id) NRF_DRV_SPI_INSTANCE_(id) +#define NRF_DRV_SPI_INSTANCE_(id) NRF_DRV_SPI_INSTANCE_ ## id +#if NRFX_CHECK(NRFX_SPIM0_ENABLED) + #define NRF_DRV_SPI_INSTANCE_0 \ + { 0, { .spim = NRFX_SPIM_INSTANCE(0) }, true } +#elif NRFX_CHECK(NRFX_SPI0_ENABLED) + #define NRF_DRV_SPI_INSTANCE_0 \ + { 0, { .spi = NRFX_SPI_INSTANCE(0) }, false } +#endif +#if NRFX_CHECK(NRFX_SPIM1_ENABLED) + #define NRF_DRV_SPI_INSTANCE_1 \ + { 1, { .spim = NRFX_SPIM_INSTANCE(1) }, true } +#elif NRFX_CHECK(NRFX_SPI1_ENABLED) + #define NRF_DRV_SPI_INSTANCE_1 \ + { 1, { .spi = NRFX_SPI_INSTANCE(1) }, false } +#endif +#if NRFX_CHECK(NRFX_SPIM2_ENABLED) + #define NRF_DRV_SPI_INSTANCE_2 \ + { 2, { .spim = NRFX_SPIM_INSTANCE(2) }, true } +#elif NRFX_CHECK(NRFX_SPI2_ENABLED) + #define NRF_DRV_SPI_INSTANCE_2 \ + { 2, { .spi = NRFX_SPI_INSTANCE(2) }, false } +#endif + +/** + * @brief This value can be provided instead of a pin number for signals MOSI, + * MISO, and Slave Select to specify that the given signal is not used and + * therefore does not need to be connected to a pin. + */ +#define NRF_DRV_SPI_PIN_NOT_USED 0xFF + +/** + * @brief SPI data rates. + */ +typedef enum +{ + NRF_DRV_SPI_FREQ_125K = NRF_SPI_FREQ_125K, ///< 125 kbps. + NRF_DRV_SPI_FREQ_250K = NRF_SPI_FREQ_250K, ///< 250 kbps. + NRF_DRV_SPI_FREQ_500K = NRF_SPI_FREQ_500K, ///< 500 kbps. + NRF_DRV_SPI_FREQ_1M = NRF_SPI_FREQ_1M, ///< 1 Mbps. + NRF_DRV_SPI_FREQ_2M = NRF_SPI_FREQ_2M, ///< 2 Mbps. + NRF_DRV_SPI_FREQ_4M = NRF_SPI_FREQ_4M, ///< 4 Mbps. + NRF_DRV_SPI_FREQ_8M = NRF_SPI_FREQ_8M ///< 8 Mbps. +} nrf_drv_spi_frequency_t; + +/** + * @brief SPI modes. + */ +typedef enum +{ + NRF_DRV_SPI_MODE_0 = NRF_SPI_MODE_0, ///< SCK active high, sample on leading edge of clock. + NRF_DRV_SPI_MODE_1 = NRF_SPI_MODE_1, ///< SCK active high, sample on trailing edge of clock. + NRF_DRV_SPI_MODE_2 = NRF_SPI_MODE_2, ///< SCK active low, sample on leading edge of clock. + NRF_DRV_SPI_MODE_3 = NRF_SPI_MODE_3 ///< SCK active low, sample on trailing edge of clock. +} nrf_drv_spi_mode_t; + +/** + * @brief SPI bit orders. + */ +typedef enum +{ + NRF_DRV_SPI_BIT_ORDER_MSB_FIRST = NRF_SPI_BIT_ORDER_MSB_FIRST, ///< Most significant bit shifted out first. + NRF_DRV_SPI_BIT_ORDER_LSB_FIRST = NRF_SPI_BIT_ORDER_LSB_FIRST ///< Least significant bit shifted out first. +} nrf_drv_spi_bit_order_t; + +/** + * @brief SPI master driver instance configuration structure. + */ +typedef struct +{ + uint8_t sck_pin; ///< SCK pin number. + uint8_t mosi_pin; ///< MOSI pin number (optional). + /**< Set to @ref NRF_DRV_SPI_PIN_NOT_USED + * if this signal is not needed. */ + uint8_t miso_pin; ///< MISO pin number (optional). + /**< Set to @ref NRF_DRV_SPI_PIN_NOT_USED + * if this signal is not needed. */ + uint8_t ss_pin; ///< Slave Select pin number (optional). + /**< Set to @ref NRF_DRV_SPI_PIN_NOT_USED + * if this signal is not needed. The driver + * supports only active low for this signal. + * If the signal should be active high, + * it must be controlled externally. */ + uint8_t irq_priority; ///< Interrupt priority. + uint8_t orc; ///< Over-run character. + /**< This character is used when all bytes from the TX buffer are sent, + but the transfer continues due to RX. */ + nrf_drv_spi_frequency_t frequency; ///< SPI frequency. + nrf_drv_spi_mode_t mode; ///< SPI mode. + nrf_drv_spi_bit_order_t bit_order; ///< SPI bit order. +} nrf_drv_spi_config_t; + +/** + * @brief SPI master instance default configuration. + */ +#define NRF_DRV_SPI_DEFAULT_CONFIG \ +{ \ + .sck_pin = NRF_DRV_SPI_PIN_NOT_USED, \ + .mosi_pin = NRF_DRV_SPI_PIN_NOT_USED, \ + .miso_pin = NRF_DRV_SPI_PIN_NOT_USED, \ + .ss_pin = NRF_DRV_SPI_PIN_NOT_USED, \ + .irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY, \ + .orc = 0xFF, \ + .frequency = NRF_DRV_SPI_FREQ_4M, \ + .mode = NRF_DRV_SPI_MODE_0, \ + .bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST, \ +} + +#define NRF_DRV_SPI_FLAG_TX_POSTINC (1UL << 0) /**< TX buffer address incremented after transfer. */ +#define NRF_DRV_SPI_FLAG_RX_POSTINC (1UL << 1) /**< RX buffer address incremented after transfer. */ +#define NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER (1UL << 2) /**< Interrupt after each transfer is suppressed, and the event handler is not called. */ +#define NRF_DRV_SPI_FLAG_HOLD_XFER (1UL << 3) /**< Set up the transfer but do not start it. */ +#define NRF_DRV_SPI_FLAG_REPEATED_XFER (1UL << 4) /**< Flag indicating that the transfer will be executed multiple times. */ + +/** + * @brief Single transfer descriptor structure. + */ +typedef struct +{ + uint8_t const * p_tx_buffer; ///< Pointer to TX buffer. + uint8_t tx_length; ///< TX buffer length. + uint8_t * p_rx_buffer; ///< Pointer to RX buffer. + uint8_t rx_length; ///< RX buffer length. +}nrf_drv_spi_xfer_desc_t; + +/** + * @brief Macro for setting up single transfer descriptor. + * + * This macro is for internal use only. + */ +#define NRF_DRV_SPI_SINGLE_XFER(p_tx, tx_len, p_rx, rx_len) \ + { \ + .p_tx_buffer = (uint8_t const *)(p_tx), \ + .tx_length = (tx_len), \ + .p_rx_buffer = (p_rx), \ + .rx_length = (rx_len), \ + } + +/** + * @brief Macro for setting duplex TX RX transfer. + */ +#define NRF_DRV_SPI_XFER_TRX(p_tx_buf, tx_length, p_rx_buf, rx_length) \ + NRF_DRV_SPI_SINGLE_XFER(p_tx_buf, tx_length, p_rx_buf, rx_length) + +/** + * @brief Macro for setting TX transfer. + */ +#define NRF_DRV_SPI_XFER_TX(p_buf, length) \ + NRF_DRV_SPI_SINGLE_XFER(p_buf, length, NULL, 0) + +/** + * @brief Macro for setting RX transfer. + */ +#define NRF_DRV_SPI_XFER_RX(p_buf, length) \ + NRF_DRV_SPI_SINGLE_XFER(NULL, 0, p_buf, length) + +/** + * @brief SPI master driver event types, passed to the handler routine provided + * during initialization. + */ +typedef enum +{ + NRF_DRV_SPI_EVENT_DONE, ///< Transfer done. +} nrf_drv_spi_evt_type_t; + +typedef struct +{ + nrf_drv_spi_evt_type_t type; ///< Event type. + union + { + nrf_drv_spi_xfer_desc_t done; ///< Event data for DONE event. + } data; +} nrf_drv_spi_evt_t; + +/** + * @brief SPI master driver event handler type. + */ +typedef void (* nrf_drv_spi_evt_handler_t)(nrf_drv_spi_evt_t const * p_event, + void * p_context); + + +/** + * @brief Function for initializing the SPI master driver instance. + * + * This function configures and enables the specified peripheral. + * + * @note MISO pin has pull down enabled. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_config Pointer to the structure with the initial configuration. + * + * @param handler Event handler provided by the user. If NULL, transfers + * will be performed in blocking mode. + * @param p_context Context passed to event handler. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the driver was already initialized. + * @retval NRF_ERROR_BUSY If some other peripheral with the same + * instance ID is already in use. This is + * possible only if PERIPHERAL_RESOURCE_SHARING_ENABLED + * is set to a value other than zero. + */ +ret_code_t nrf_drv_spi_init(nrf_drv_spi_t const * const p_instance, + nrf_drv_spi_config_t const * p_config, + nrf_drv_spi_evt_handler_t handler, + void * p_context); + +/** + * @brief Function for uninitializing the SPI master driver instance. + * + * @note Configuration of pins is kept. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_spi_uninit(nrf_drv_spi_t const * const p_instance); + +/** + * @brief Function for starting the SPI data transfer. + * + * If an event handler was provided in the @ref nrf_drv_spi_init call, this function + * returns immediately and the handler is called when the transfer is done. + * Otherwise, the transfer is performed in blocking mode, which means that this function + * returns when the transfer is finished. + * + * @note Peripherals using EasyDMA (for example, SPIM) require the transfer buffers + * to be placed in the Data RAM region. If they are not and an SPIM instance is + * used, this function will fail with the error code NRF_ERROR_INVALID_ADDR. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_tx_buffer Pointer to the transmit buffer. Can be NULL + * if there is nothing to send. + * @param tx_buffer_length Length of the transmit buffer. + * @param[in] p_rx_buffer Pointer to the receive buffer. Can be NULL + * if there is nothing to receive. + * @param rx_buffer_length Length of the receive buffer. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_BUSY If a previously started transfer has not finished + * yet. + * @retval NRF_ERROR_INVALID_ADDR If the provided buffers are not placed in the Data + * RAM region. + */ +__STATIC_INLINE +ret_code_t nrf_drv_spi_transfer(nrf_drv_spi_t const * const p_instance, + uint8_t const * p_tx_buffer, + uint8_t tx_buffer_length, + uint8_t * p_rx_buffer, + uint8_t rx_buffer_length); + +/** + * @brief Function for starting the SPI data transfer with additional option flags. + * + * Function enables customizing the transfer by using option flags. + * + * Additional options are provided using the flags parameter: + * + * - @ref NRF_DRV_SPI_FLAG_TX_POSTINC and @ref NRF_DRV_SPI_FLAG_RX_POSTINC: + * Post-incrementation of buffer addresses. Supported only by SPIM. + * - @ref NRF_DRV_SPI_FLAG_HOLD_XFER: Driver is not starting the transfer. Use this + * flag if the transfer is triggered externally by PPI. Supported only by SPIM. Use + * @ref nrf_drv_spi_start_task_get to get the address of the start task. + * - @ref NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER: No user event handler after transfer + * completion. This also means no interrupt at the end of the transfer. Supported only by SPIM. + * If @ref NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER is used, the driver does not set the instance into + * busy state, so you must ensure that the next transfers are set up when SPIM is not active. + * @ref nrf_drv_spi_end_event_get function can be used to detect end of transfer. Option can be used + * together with @ref NRF_DRV_SPI_FLAG_REPEATED_XFER to prepare a sequence of SPI transfers + * without interruptions. + * - @ref NRF_DRV_SPI_FLAG_REPEATED_XFER: Prepare for repeated transfers. You can set + * up a number of transfers that will be triggered externally (for example by PPI). An example is + * a TXRX transfer with the options @ref NRF_DRV_SPI_FLAG_RX_POSTINC, + * @ref NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER, and @ref NRF_DRV_SPI_FLAG_REPEATED_XFER. After the + * transfer is set up, a set of transfers can be triggered by PPI that will read, for example, + * the same register of an external component and put it into a RAM buffer without any interrupts. + * @ref nrf_drv_spi_end_event_get can be used to get the address of the END event, which can be + * used to count the number of transfers. If @ref NRF_DRV_SPI_FLAG_REPEATED_XFER is used, + * the driver does not set the instance into busy state, so you must ensure that the next + * transfers are set up when SPIM is not active. Supported only by SPIM. + * @note Function is intended to be used only in non-blocking mode. + * + * @param p_instance Pointer to the driver instance structure. + * @param p_xfer_desc Pointer to the transfer descriptor. + * @param flags Transfer options (0 for default settings). + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_BUSY If the driver is not ready for a new transfer. + * @retval NRF_ERROR_NOT_SUPPORTED If the provided parameters are not supported. + * @retval NRF_ERROR_INVALID_ADDR If the provided buffers are not placed in the Data + * RAM region. + */ +__STATIC_INLINE +ret_code_t nrf_drv_spi_xfer(nrf_drv_spi_t const * const p_instance, + nrf_drv_spi_xfer_desc_t const * p_xfer_desc, + uint32_t flags); + +/** + * @brief Function for returning the address of a SPIM start task. + * + * This function should be used if @ref nrf_drv_spi_xfer was called with the flag @ref NRF_DRV_SPI_FLAG_HOLD_XFER. + * In that case, the transfer is not started by the driver, but it must be started externally by PPI. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @return Start task address. + */ +__STATIC_INLINE +uint32_t nrf_drv_spi_start_task_get(nrf_drv_spi_t const * p_instance); + +/** + * @brief Function for returning the address of a END SPIM event. + * + * A END event can be used to detect the end of a transfer if the @ref NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER + * option is used. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @return END event address. + */ +__STATIC_INLINE +uint32_t nrf_drv_spi_end_event_get(nrf_drv_spi_t const * p_instance); + +/** + * @brief Function for aborting ongoing transfer. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_spi_abort(nrf_drv_spi_t const * p_instance); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +#if defined(SPI_PRESENT) && !defined(SPIM_PRESENT) +#define NRF_DRV_SPI_WITH_SPI +#elif !defined(SPI_PRESENT) && defined(SPIM_PRESENT) +#define NRF_DRV_SPI_WITH_SPIM +#else +#if (NRFX_CHECK(SPI0_ENABLED) && NRFX_CHECK(SPI0_USE_EASY_DMA)) || \ + (NRFX_CHECK(SPI1_ENABLED) && NRFX_CHECK(SPI1_USE_EASY_DMA)) || \ + (NRFX_CHECK(SPI2_ENABLED) && NRFX_CHECK(SPI2_USE_EASY_DMA)) + #define NRF_DRV_SPI_WITH_SPIM +#endif +#if (NRFX_CHECK(SPI0_ENABLED) && !NRFX_CHECK(SPI0_USE_EASY_DMA)) || \ + (NRFX_CHECK(SPI1_ENABLED) && !NRFX_CHECK(SPI1_USE_EASY_DMA)) || \ + (NRFX_CHECK(SPI2_ENABLED) && !NRFX_CHECK(SPI2_USE_EASY_DMA)) + #define NRF_DRV_SPI_WITH_SPI +#endif +#endif +#if defined(NRF_DRV_SPI_WITH_SPIM) && defined(NRF_DRV_SPI_WITH_SPI) + #define NRF_DRV_SPI_USE_SPIM (p_instance->use_easy_dma) +#elif defined(NRF_DRV_SPI_WITH_SPIM) + #define NRF_DRV_SPI_USE_SPIM true +#else + #define NRF_DRV_SPI_USE_SPIM false +#endif +#define NRF_DRV_SPI_USE_SPI (!NRF_DRV_SPI_USE_SPIM) + +__STATIC_INLINE +void nrf_drv_spi_uninit(nrf_drv_spi_t const * p_instance) +{ + if (NRF_DRV_SPI_USE_SPIM) + { + nrfx_spim_uninit(&p_instance->u.spim); + } + else if (NRF_DRV_SPI_USE_SPI) + { + nrfx_spi_uninit(&p_instance->u.spi); + } +} + +__STATIC_INLINE +ret_code_t nrf_drv_spi_transfer(nrf_drv_spi_t const * const p_instance, + uint8_t const * p_tx_buffer, + uint8_t tx_buffer_length, + uint8_t * p_rx_buffer, + uint8_t rx_buffer_length) +{ + ret_code_t result = 0; + if (NRF_DRV_SPI_USE_SPIM) + { + #ifdef SPIM_PRESENT + nrfx_spim_xfer_desc_t const spim_xfer_desc = + { + .p_tx_buffer = p_tx_buffer, + .tx_length = tx_buffer_length, + .p_rx_buffer = p_rx_buffer, + .rx_length = rx_buffer_length, + }; + result = nrfx_spim_xfer(&p_instance->u.spim, &spim_xfer_desc, 0); + #endif + } + else if (NRF_DRV_SPI_USE_SPI) + { + #ifdef SPI_PRESENT + nrfx_spi_xfer_desc_t const spi_xfer_desc = + { + .p_tx_buffer = p_tx_buffer, + .tx_length = tx_buffer_length, + .p_rx_buffer = p_rx_buffer, + .rx_length = rx_buffer_length, + }; + result = nrfx_spi_xfer(&p_instance->u.spi, &spi_xfer_desc, 0); + #endif + } + return result; +} + +__STATIC_INLINE +ret_code_t nrf_drv_spi_xfer(nrf_drv_spi_t const * const p_instance, + nrf_drv_spi_xfer_desc_t const * p_xfer_desc, + uint32_t flags) +{ + ret_code_t result = 0; + if (NRF_DRV_SPI_USE_SPIM) + { + #ifdef SPIM_PRESENT + nrfx_spim_xfer_desc_t const spim_xfer_desc = + { + .p_tx_buffer = p_xfer_desc->p_tx_buffer, + .tx_length = p_xfer_desc->tx_length, + .p_rx_buffer = p_xfer_desc->p_rx_buffer, + .rx_length = p_xfer_desc->rx_length, + }; + result = nrfx_spim_xfer(&p_instance->u.spim, &spim_xfer_desc, flags); + #endif + } + else if (NRF_DRV_SPI_USE_SPI) + { + #ifdef SPI_PRESENT + nrfx_spi_xfer_desc_t const spi_xfer_desc = + { + .p_tx_buffer = p_xfer_desc->p_tx_buffer, + .tx_length = p_xfer_desc->tx_length, + .p_rx_buffer = p_xfer_desc->p_rx_buffer, + .rx_length = p_xfer_desc->rx_length, + }; + result = nrfx_spi_xfer(&p_instance->u.spi, &spi_xfer_desc, flags); + #endif + } + return result; +} + +__STATIC_INLINE +uint32_t nrf_drv_spi_start_task_get(nrf_drv_spi_t const * p_instance) +{ + uint32_t result = 0; + if (NRF_DRV_SPI_USE_SPIM) + { + result = nrfx_spim_start_task_get(&p_instance->u.spim); + } + else if (NRF_DRV_SPI_USE_SPI) + { + NRFX_ASSERT(false); // not supported + result = 0; + } + return result; +} + +__STATIC_INLINE +uint32_t nrf_drv_spi_end_event_get(nrf_drv_spi_t const * p_instance) +{ + uint32_t result = 0; + if (NRF_DRV_SPI_USE_SPIM) + { + result = nrfx_spim_end_event_get(&p_instance->u.spim); + } + else if (NRF_DRV_SPI_USE_SPI) + { + NRFX_ASSERT(false); // not supported + result = 0; + } + return result; +} + +__STATIC_INLINE +void nrf_drv_spi_abort(nrf_drv_spi_t const * p_instance) +{ + if (NRF_DRV_SPI_USE_SPIM) + { + nrfx_spim_abort(&p_instance->u.spim); + } + else if (NRF_DRV_SPI_USE_SPI) + { + nrfx_spi_abort(&p_instance->u.spi); + } +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_SPI_H__ diff --git a/integration/nrfx/legacy/nrf_drv_timer.h b/integration/nrfx/legacy/nrf_drv_timer.h new file mode 100644 index 0000000..642cad4 --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_timer.h @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_TIMER_H__ +#define NRF_DRV_TIMER_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_timer TIMER driver - legacy layer + * @{ + * @ingroup nrf_timer + * + * @brief Layer providing compatibility with the former API. + */ + +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_timer_t nrf_drv_timer_t; +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_timer_config_t nrf_drv_timer_config_t; + +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_TIMER_INSTANCE NRFX_TIMER_INSTANCE +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_TIMER_DEFAULT_CONFIG NRFX_TIMER_DEFAULT_CONFIG + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_timer_event_handler_t nrfx_timer_event_handler_t + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_init nrfx_timer_init +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_uninit nrfx_timer_uninit +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_enable nrfx_timer_enable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_disable nrfx_timer_disable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_is_enabled nrfx_timer_is_enabled +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_pause nrfx_timer_pause +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_resume nrfx_timer_resume +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_clear nrfx_timer_clear +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_increment nrfx_timer_increment +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_capture nrfx_timer_capture +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_capture_get nrfx_timer_capture_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_compare nrfx_timer_compare +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_extended_compare nrfx_timer_extended_compare +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_us_to_ticks nrfx_timer_us_to_ticks +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_ms_to_ticks nrfx_timer_ms_to_ticks +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_compare_int_enable nrfx_timer_compare_int_enable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_compare_int_disable nrfx_timer_compare_int_disable + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_task_address_get nrfx_timer_task_address_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_capture_task_address_get nrfx_timer_capture_task_address_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_event_address_get nrfx_timer_event_address_get +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_timer_compare_event_address_get nrfx_timer_compare_event_address_get + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_TIMER_H__ diff --git a/integration/nrfx/legacy/nrf_drv_twi.c b/integration/nrfx/legacy/nrf_drv_twi.c new file mode 100644 index 0000000..cf424d4 --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_twi.c @@ -0,0 +1,192 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_drv_twi.h" +#include +#include + +#ifdef TWIM_PRESENT +#define INSTANCE_COUNT TWIM_COUNT +#else +#define INSTANCE_COUNT TWI_COUNT +#endif + +#define SCL_PIN_INIT_CONF \ + ( (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \ + | (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \ + | (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \ + | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \ + | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos)) + +#define SDA_PIN_INIT_CONF SCL_PIN_INIT_CONF + +#define SDA_PIN_UNINIT_CONF \ + ( (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \ + | (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) \ + | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) \ + | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) \ + | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos)) + +#define SCL_PIN_UNINIT_CONF SDA_PIN_UNINIT_CONF + +#define SCL_PIN_INIT_CONF_CLR \ + ( (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \ + | (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \ + | (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \ + | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \ + | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos)) + +#define SDA_PIN_INIT_CONF_CLR SCL_PIN_INIT_CONF_CLR + +static nrf_drv_twi_evt_handler_t m_handlers[INSTANCE_COUNT]; +static void * m_contexts[INSTANCE_COUNT]; + +static void twi_clear_bus(nrf_drv_twi_config_t const * p_config) +{ + NRF_GPIO->PIN_CNF[p_config->scl] = SCL_PIN_INIT_CONF; + NRF_GPIO->PIN_CNF[p_config->sda] = SDA_PIN_INIT_CONF; + + nrf_gpio_pin_set(p_config->scl); + nrf_gpio_pin_set(p_config->sda); + + NRF_GPIO->PIN_CNF[p_config->scl] = SCL_PIN_INIT_CONF_CLR; + NRF_GPIO->PIN_CNF[p_config->sda] = SDA_PIN_INIT_CONF_CLR; + + nrf_delay_us(4); + + for (int i = 0; i < 9; i++) + { + if (nrf_gpio_pin_read(p_config->sda)) + { + if (i == 0) + { + return; + } + else + { + break; + } + } + nrf_gpio_pin_clear(p_config->scl); + nrf_delay_us(4); + nrf_gpio_pin_set(p_config->scl); + nrf_delay_us(4); + } + nrf_gpio_pin_clear(p_config->sda); + nrf_delay_us(4); + nrf_gpio_pin_set(p_config->sda); +} + +#ifdef TWIM_PRESENT +static void twim_evt_handler(nrfx_twim_evt_t const * p_event, + void * p_context) +{ + uint32_t inst_idx = (uint32_t)p_context; + nrf_drv_twi_evt_t const event = + { + .type = (nrf_drv_twi_evt_type_t)p_event->type, + .xfer_desc = + { + .type = (nrf_drv_twi_xfer_type_t)p_event->xfer_desc.type, + .address = p_event->xfer_desc.address, + .primary_length = p_event->xfer_desc.primary_length, + .secondary_length = p_event->xfer_desc.secondary_length, + .p_primary_buf = p_event->xfer_desc.p_primary_buf, + .p_secondary_buf = p_event->xfer_desc.p_secondary_buf, + } + }; + m_handlers[inst_idx](&event, m_contexts[inst_idx]); +} +#endif // TWIM_PRESENT + +#ifdef TWI_PRESENT +static void twi_evt_handler(nrfx_twi_evt_t const * p_event, + void * p_context) +{ + uint32_t inst_idx = (uint32_t)p_context; + nrf_drv_twi_evt_t const event = + { + .type = (nrf_drv_twi_evt_type_t)p_event->type, + .xfer_desc = + { + .type = (nrf_drv_twi_xfer_type_t)p_event->xfer_desc.type, + .address = p_event->xfer_desc.address, + .primary_length = p_event->xfer_desc.primary_length, + .secondary_length = p_event->xfer_desc.secondary_length, + .p_primary_buf = p_event->xfer_desc.p_primary_buf, + .p_secondary_buf = p_event->xfer_desc.p_secondary_buf, + } + }; + m_handlers[inst_idx](&event, m_contexts[inst_idx]); +} +#endif // TWI_PRESENT + +ret_code_t nrf_drv_twi_init(nrf_drv_twi_t const * p_instance, + nrf_drv_twi_config_t const * p_config, + nrf_drv_twi_evt_handler_t event_handler, + void * p_context) +{ + uint32_t inst_idx = p_instance->inst_idx; + m_handlers[inst_idx] = event_handler; + m_contexts[inst_idx] = p_context; + + if(p_config->clear_bus_init) + { + /* Send clocks (max 9) until slave device back from stuck mode */ + twi_clear_bus(p_config); + } + + ret_code_t result = 0; + if (NRF_DRV_TWI_USE_TWIM) + { + result = nrfx_twim_init(&p_instance->u.twim, + (nrfx_twim_config_t const *)p_config, + event_handler ? twim_evt_handler : NULL, + (void *)inst_idx); + } + else if (NRF_DRV_TWI_USE_TWI) + { + result = nrfx_twi_init(&p_instance->u.twi, + (nrfx_twi_config_t const *)p_config, + event_handler ? twi_evt_handler : NULL, + (void *)inst_idx); + } + return result; +} diff --git a/integration/nrfx/legacy/nrf_drv_twi.h b/integration/nrfx/legacy/nrf_drv_twi.h new file mode 100644 index 0000000..06d7b29 --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_twi.h @@ -0,0 +1,686 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_TWI_H__ +#define NRF_DRV_TWI_H__ + +#include +#ifdef TWIM_PRESENT + #include +#else + // Compilers (at least the smart ones) will remove the TWIM related code + // (blocks starting with "if (NRF_DRV_TWI_USE_TWIM)") when it is not used, + // but to perform the compilation they need the following definitions. + #define nrfx_twim_init(...) 0 + #define nrfx_twim_uninit(...) + #define nrfx_twim_enable(...) + #define nrfx_twim_disable(...) + #define nrfx_twim_tx(...) 0 + #define nrfx_twim_rx(...) 0 + #define nrfx_twim_is_busy(...) 0 + #define nrfx_twim_start_task_get(...) 0 + #define nrfx_twim_stopped_event_get(...) 0 +#endif + +#ifdef TWI_PRESENT + #include +#else + // Compilers (at least the smart ones) will remove the TWI related code + // (blocks starting with "if (NRF_DRV_TWI_USE_TWI)") when it is not used, + // but to perform the compilation they need the following definitions. + #define nrfx_twi_init(...) 0 + #define nrfx_twi_uninit(...) + #define nrfx_twi_enable(...) + #define nrfx_twi_disable(...) + #define nrfx_twi_tx(...) 0 + #define nrfx_twi_rx(...) 0 + #define nrfx_twi_is_busy(...) 0 + #define nrfx_twi_data_count_get(...) 0 + #define nrfx_twi_stopped_event_get(...) 0 + + // This part is for old modules that use directly TWI HAL definitions + // (to make them compilable for chips that have only TWIM). + #define NRF_TWI_ERROR_ADDRESS_NACK NRF_TWIM_ERROR_ADDRESS_NACK + #define NRF_TWI_ERROR_DATA_NACK NRF_TWIM_ERROR_DATA_NACK + #define NRF_TWI_FREQ_100K NRF_TWIM_FREQ_100K + #define NRF_TWI_FREQ_250K NRF_TWIM_FREQ_250K + #define NRF_TWI_FREQ_400K NRF_TWIM_FREQ_400K +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_twi TWI driver - legacy layer + * @{ + * @ingroup nrf_twi + * @brief Layer providing compatibility with the former API. + */ + +/** + * @brief Structure for the TWI master driver instance. + */ +typedef struct +{ + uint8_t inst_idx; + union + { +#ifdef TWIM_PRESENT + nrfx_twim_t twim; +#endif +#ifdef TWI_PRESENT + nrfx_twi_t twi; +#endif + } u; + bool use_easy_dma; +} nrf_drv_twi_t; + +/** + * @brief Macro for creating a TWI master driver instance. + */ +#define NRF_DRV_TWI_INSTANCE(id) NRF_DRV_TWI_INSTANCE_(id) +#define NRF_DRV_TWI_INSTANCE_(id) NRF_DRV_TWI_INSTANCE_ ## id +#if NRFX_CHECK(NRFX_TWIM0_ENABLED) + #define NRF_DRV_TWI_INSTANCE_0 \ + { 0, { .twim = NRFX_TWIM_INSTANCE(0) }, true } +#elif NRFX_CHECK(NRFX_TWI0_ENABLED) + #define NRF_DRV_TWI_INSTANCE_0 \ + { 0, { .twi = NRFX_TWI_INSTANCE(0) }, false } +#endif +#if NRFX_CHECK(NRFX_TWIM1_ENABLED) + #define NRF_DRV_TWI_INSTANCE_1 \ + { 1, { .twim = NRFX_TWIM_INSTANCE(1) }, true } +#elif NRFX_CHECK(NRFX_TWI1_ENABLED) + #define NRF_DRV_TWI_INSTANCE_1 \ + { 1, { .twi = NRFX_TWI_INSTANCE(1) }, false } +#endif + +/** + * @brief TWI master clock frequency. + */ +typedef enum +{ + NRF_DRV_TWI_FREQ_100K = NRF_TWI_FREQ_100K , ///< 100 kbps. + NRF_DRV_TWI_FREQ_250K = NRF_TWI_FREQ_250K , ///< 250 kbps. + NRF_DRV_TWI_FREQ_400K = NRF_TWI_FREQ_400K ///< 400 kbps. +} nrf_drv_twi_frequency_t; + +/** + * @brief Structure for the TWI master driver instance configuration. + */ +typedef struct +{ + uint32_t scl; ///< SCL pin number. + uint32_t sda; ///< SDA pin number. + nrf_drv_twi_frequency_t frequency; ///< TWI frequency. + uint8_t interrupt_priority; ///< Interrupt priority. + bool clear_bus_init; ///< Clear bus during init. + bool hold_bus_uninit; ///< Hold pull up state on gpio pins after uninit. +} nrf_drv_twi_config_t; + +/** + * @brief TWI master driver instance default configuration. + */ +#define NRF_DRV_TWI_DEFAULT_CONFIG \ +{ \ + .frequency = (nrf_drv_twi_frequency_t)TWI_DEFAULT_CONFIG_FREQUENCY, \ + .scl = 31, \ + .sda = 31, \ + .interrupt_priority = TWI_DEFAULT_CONFIG_IRQ_PRIORITY, \ + .clear_bus_init = TWI_DEFAULT_CONFIG_CLR_BUS_INIT, \ + .hold_bus_uninit = TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT, \ +} + +#define NRF_DRV_TWI_FLAG_TX_POSTINC (1UL << 0) /**< TX buffer address incremented after transfer. */ +#define NRF_DRV_TWI_FLAG_RX_POSTINC (1UL << 1) /**< RX buffer address incremented after transfer. */ +#define NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER (1UL << 2) /**< Interrupt after each transfer is suppressed, and the event handler is not called. */ +#define NRF_DRV_TWI_FLAG_HOLD_XFER (1UL << 3) /**< Set up the transfer but do not start it. */ +#define NRF_DRV_TWI_FLAG_REPEATED_XFER (1UL << 4) /**< Flag indicating that the transfer will be executed multiple times. */ +#define NRF_DRV_TWI_FLAG_TX_NO_STOP (1UL << 5) /**< Flag indicating that the TX transfer will not end with a stop condition. */ + +/** + * @brief TWI master driver event types. + */ +typedef enum +{ + NRF_DRV_TWI_EVT_DONE, ///< Transfer completed event. + NRF_DRV_TWI_EVT_ADDRESS_NACK, ///< Error event: NACK received after sending the address. + NRF_DRV_TWI_EVT_DATA_NACK ///< Error event: NACK received after sending a data byte. +} nrf_drv_twi_evt_type_t; + +/** + * @brief TWI master driver transfer types. + */ +typedef enum +{ + NRF_DRV_TWI_XFER_TX, ///< TX transfer. + NRF_DRV_TWI_XFER_RX, ///< RX transfer. + NRF_DRV_TWI_XFER_TXRX, ///< TX transfer followed by RX transfer with repeated start. + NRF_DRV_TWI_XFER_TXTX ///< TX transfer followed by TX transfer with repeated start. +} nrf_drv_twi_xfer_type_t; + +/** + * @brief Structure for a TWI transfer descriptor. + */ +typedef struct +{ + nrf_drv_twi_xfer_type_t type; ///< Type of transfer. + uint8_t address; ///< Slave address. + uint8_t primary_length; ///< Number of bytes transferred. + uint8_t secondary_length; ///< Number of bytes transferred. + uint8_t * p_primary_buf; ///< Pointer to transferred data. + uint8_t * p_secondary_buf; ///< Pointer to transferred data. +} nrf_drv_twi_xfer_desc_t; + + +/**@brief Macro for setting the TX transfer descriptor. */ +#define NRF_DRV_TWI_XFER_DESC_TX(addr, p_data, length) \ + { \ + .type = NRF_DRV_TWI_XFER_TX, \ + .address = addr, \ + .primary_length = length, \ + .p_primary_buf = p_data, \ + } + +/**@brief Macro for setting the RX transfer descriptor. */ +#define NRF_DRV_TWI_XFER_DESC_RX(addr, p_data, length) \ + { \ + .type = NRF_DRV_TWI_XFER_RX, \ + .address = addr, \ + .primary_length = length, \ + .p_primary_buf = p_data, \ + } + +/**@brief Macro for setting the TXRX transfer descriptor. */ +#define NRF_DRV_TWI_XFER_DESC_TXRX(addr, p_tx, tx_len, p_rx, rx_len) \ + { \ + .type = NRF_DRV_TWI_XFER_TXRX, \ + .address = addr, \ + .primary_length = tx_len, \ + .secondary_length = rx_len, \ + .p_primary_buf = p_tx, \ + .p_secondary_buf = p_rx, \ + } + +/**@brief Macro for setting the TXTX transfer descriptor. */ +#define NRF_DRV_TWI_XFER_DESC_TXTX(addr, p_tx, tx_len, p_tx2, tx_len2) \ + { \ + .type = NRF_DRV_TWI_XFER_TXTX, \ + .address = addr, \ + .primary_length = tx_len, \ + .secondary_length = tx_len2, \ + .p_primary_buf = p_tx, \ + .p_secondary_buf = p_tx2, \ + } + +/** + * @brief Structure for a TWI event. + */ +typedef struct +{ + nrf_drv_twi_evt_type_t type; ///< Event type. + nrf_drv_twi_xfer_desc_t xfer_desc; ///< Transfer details. +} nrf_drv_twi_evt_t; + +/** + * @brief TWI event handler prototype. + */ +typedef void (* nrf_drv_twi_evt_handler_t)(nrf_drv_twi_evt_t const * p_event, + void * p_context); + +/** + * @brief Function for initializing the TWI driver instance. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_config Initial configuration. + * @param[in] event_handler Event handler provided by the user. If NULL, blocking mode is enabled. + * @param[in] p_context Context passed to event handler. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the driver is in invalid state. + * @retval NRF_ERROR_BUSY If some other peripheral with the same + * instance ID is already in use. This is + * possible only if PERIPHERAL_RESOURCE_SHARING_ENABLED + * is set to a value other than zero. + */ +ret_code_t nrf_drv_twi_init(nrf_drv_twi_t const * p_instance, + nrf_drv_twi_config_t const * p_config, + nrf_drv_twi_evt_handler_t event_handler, + void * p_context); + +/** + * @brief Function for uninitializing the TWI instance. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_twi_uninit(nrf_drv_twi_t const * p_instance); + +/** + * @brief Function for enabling the TWI instance. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_twi_enable(nrf_drv_twi_t const * p_instance); + +/** + * @brief Function for disabling the TWI instance. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_twi_disable(nrf_drv_twi_t const * p_instance); + +/** + * @brief Function for sending data to a TWI slave. + * + * The transmission will be stopped when an error occurs. If a transfer is ongoing, + * the function returns the error code @ref NRF_ERROR_BUSY. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] address Address of a specific slave device (only 7 LSB). + * @param[in] p_data Pointer to a transmit buffer. + * @param[in] length Number of bytes to send. + * @param[in] no_stop If set, the stop condition is not generated on the bus + * after the transfer has completed successfully (allowing + * for a repeated start in the next transfer). + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_BUSY If the driver is not ready for a new transfer. + * @retval NRF_ERROR_INTERNAL If an error was detected by hardware. + * @retval NRF_ERROR_INVALID_ADDR If the EasyDMA is used and memory adress in not in RAM. + * @retval NRF_ERROR_DRV_TWI_ERR_ANACK If NACK received after sending the address in polling mode. + * @retval NRF_ERROR_DRV_TWI_ERR_DNACK If NACK received after sending a data byte in polling mode. + */ +__STATIC_INLINE +ret_code_t nrf_drv_twi_tx(nrf_drv_twi_t const * p_instance, + uint8_t address, + uint8_t const * p_data, + uint8_t length, + bool no_stop); + +/** + * @brief Function for reading data from a TWI slave. + * + * The transmission will be stopped when an error occurs. If a transfer is ongoing, + * the function returns the error code @ref NRF_ERROR_BUSY. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] address Address of a specific slave device (only 7 LSB). + * @param[in] p_data Pointer to a receive buffer. + * @param[in] length Number of bytes to be received. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_BUSY If the driver is not ready for a new transfer. + * @retval NRF_ERROR_INTERNAL If an error was detected by hardware. + * @retval NRF_ERROR_DRV_TWI_ERR_OVERRUN If the unread data was replaced by new data + * @retval NRF_ERROR_DRV_TWI_ERR_ANACK If NACK received after sending the address in polling mode. + * @retval NRF_ERROR_DRV_TWI_ERR_DNACK If NACK received after sending a data byte in polling mode. + */ +__STATIC_INLINE +ret_code_t nrf_drv_twi_rx(nrf_drv_twi_t const * p_instance, + uint8_t address, + uint8_t * p_data, + uint8_t length); + +/** + * @brief Function for preparing a TWI transfer. + * + * The following transfer types can be configured (@ref nrf_drv_twi_xfer_desc_t::type): + * - @ref NRF_DRV_TWI_XFER_TXRX: Write operation followed by a read operation (without STOP condition in between). + * - @ref NRF_DRV_TWI_XFER_TXTX: Write operation followed by a write operation (without STOP condition in between). + * - @ref NRF_DRV_TWI_XFER_TX: Write operation (with or without STOP condition). + * - @ref NRF_DRV_TWI_XFER_RX: Read operation (with STOP condition). + * + * Additional options are provided using the flags parameter: + * - @ref NRF_DRV_TWI_FLAG_TX_POSTINC and @ref NRF_DRV_TWI_FLAG_RX_POSTINC: Post-incrementation of buffer addresses. Supported only by TWIM. + * - @ref NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER: No user event handler after transfer completion. In most cases, this also means no interrupt at the end of the transfer. + * - @ref NRF_DRV_TWI_FLAG_HOLD_XFER: Driver is not starting the transfer. Use this flag if the transfer is triggered externally by PPI. Supported only by TWIM. + * Use @ref nrf_drv_twi_start_task_get to get the address of the start task. + * - @ref NRF_DRV_TWI_FLAG_REPEATED_XFER: Prepare for repeated transfers. You can set up a number of transfers that will be triggered externally (for example by PPI). + * An example is a TXRX transfer with the options @ref NRF_DRV_TWI_FLAG_RX_POSTINC, @ref NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER, and @ref NRF_DRV_TWI_FLAG_REPEATED_XFER. + * After the transfer is set up, a set of transfers can be triggered by PPI that will read, for example, the same register of an + * external component and put it into a RAM buffer without any interrupts. @ref nrf_drv_twi_stopped_event_get can be used to get the + * address of the STOPPED event, which can be used to count the number of transfers. If @ref NRF_DRV_TWI_FLAG_REPEATED_XFER is used, + * the driver does not set the driver instance into busy state, so you must ensure that the next transfers are set up + * when TWIM is not active. Supported only by TWIM. + * - @ref NRF_DRV_TWI_FLAG_TX_NO_STOP: No stop condition after TX transfer. + * + * @note + * Some flag combinations are invalid: + * - @ref NRF_DRV_TWI_FLAG_TX_NO_STOP with @ref nrf_drv_twi_xfer_desc_t::type different than @ref NRF_DRV_TWI_XFER_TX + * - @ref NRF_DRV_TWI_FLAG_REPEATED_XFER with @ref nrf_drv_twi_xfer_desc_t::type set to @ref NRF_DRV_TWI_XFER_TXTX + * + * If @ref nrf_drv_twi_xfer_desc_t::type is set to @ref NRF_DRV_TWI_XFER_TX and the @ref NRF_DRV_TWI_FLAG_TX_NO_STOP and @ref NRF_DRV_TWI_FLAG_REPEATED_XFER + * flags are set, two tasks must be used to trigger a transfer: TASKS_RESUME followed by TASKS_STARTTX. If no stop condition is generated, + * TWIM is in SUSPENDED state. Therefore, it must be resumed before the transfer can be started. + * + * @note + * This function should be used only if the instance is configured to work in non-blocking mode. If the function is used in blocking mode, the driver asserts. + * @note If you are using this function with TWI, the only supported flag is @ref NRF_DRV_TWI_FLAG_TX_NO_STOP. All other flags require TWIM. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_xfer_desc Pointer to the transfer descriptor. + * @param[in] flags Transfer options (0 for default settings). + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_BUSY If the driver is not ready for a new transfer. + * @retval NRF_ERROR_NOT_SUPPORTED If the provided parameters are not supported. + * @retval NRF_ERROR_INTERNAL If an error was detected by hardware. + * @retval NRF_ERROR_INVALID_ADDR If the EasyDMA is used and memory adress in not in RAM + * @retval NRF_ERROR_DRV_TWI_ERR_OVERRUN If the unread data was replaced by new data (TXRX and RX) + * @retval NRF_ERROR_DRV_TWI_ERR_ANACK If NACK received after sending the address. + * @retval NRF_ERROR_DRV_TWI_ERR_DNACK If NACK received after sending a data byte. + */ +__STATIC_INLINE +ret_code_t nrf_drv_twi_xfer(nrf_drv_twi_t const * p_instance, + nrf_drv_twi_xfer_desc_t const * p_xfer_desc, + uint32_t flags); + +/** + * @brief Function for checking the TWI driver state. + * + * @param[in] p_instance TWI instance. + * + * @retval true If the TWI driver is currently busy performing a transfer. + * @retval false If the TWI driver is ready for a new transfer. + */ +__STATIC_INLINE +bool nrf_drv_twi_is_busy(nrf_drv_twi_t const * p_instance); + +/** + * @brief Function for getting the transferred data count. + * + * This function provides valid results only in legacy mode. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @return Data count. + */ +__STATIC_INLINE +uint32_t nrf_drv_twi_data_count_get(nrf_drv_twi_t const * const p_instance); + +/** + * @brief Function for returning the address of a TWI/TWIM start task. + * + * This function should be used if @ref nrf_drv_twi_xfer was called with the flag @ref NRF_DRV_TWI_FLAG_HOLD_XFER. + * In that case, the transfer is not started by the driver, but it must be started externally by PPI. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] xfer_type Transfer type used in the last call of the @ref nrf_drv_twi_xfer function. + * + * @return Start task address (TX or RX) depending on the value of xfer_type. + */ +__STATIC_INLINE +uint32_t nrf_drv_twi_start_task_get(nrf_drv_twi_t const * p_instance, nrf_drv_twi_xfer_type_t xfer_type); + +/** + * @brief Function for returning the address of a STOPPED TWI/TWIM event. + * + * A STOPPED event can be used to detect the end of a transfer if the @ref NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER + * option is used. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @return STOPPED event address. + */ +__STATIC_INLINE +uint32_t nrf_drv_twi_stopped_event_get(nrf_drv_twi_t const * p_instance); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +#if defined(TWI_PRESENT) && !defined(TWIM_PRESENT) +#define NRF_DRV_TWI_WITH_TWI +#elif !defined(TWI_PRESENT) && defined(TWIM_PRESENT) +#define NRF_DRV_TWI_WITH_TWIM +#else +#if (NRFX_CHECK(TWI0_ENABLED) && NRFX_CHECK(TWI0_USE_EASY_DMA)) || \ + (NRFX_CHECK(TWI1_ENABLED) && NRFX_CHECK(TWI1_USE_EASY_DMA)) + #define NRF_DRV_TWI_WITH_TWIM +#endif +#if (NRFX_CHECK(TWI0_ENABLED) && !NRFX_CHECK(TWI0_USE_EASY_DMA)) || \ + (NRFX_CHECK(TWI1_ENABLED) && !NRFX_CHECK(TWI1_USE_EASY_DMA)) + #define NRF_DRV_TWI_WITH_TWI +#endif +#endif +#if defined(NRF_DRV_TWI_WITH_TWIM) && defined(NRF_DRV_TWI_WITH_TWI) + #define NRF_DRV_TWI_USE_TWIM (p_instance->use_easy_dma) +#elif defined(NRF_DRV_TWI_WITH_TWIM) + #define NRF_DRV_TWI_USE_TWIM true +#else + #define NRF_DRV_TWI_USE_TWIM false +#endif +#define NRF_DRV_TWI_USE_TWI (!NRF_DRV_TWI_USE_TWIM) + +__STATIC_INLINE +void nrf_drv_twi_uninit(nrf_drv_twi_t const * p_instance) +{ + if (NRF_DRV_TWI_USE_TWIM) + { + nrfx_twim_uninit(&p_instance->u.twim); + } + else if (NRF_DRV_TWI_USE_TWI) + { + nrfx_twi_uninit(&p_instance->u.twi); + } +} + +__STATIC_INLINE +void nrf_drv_twi_enable(nrf_drv_twi_t const * p_instance) +{ + if (NRF_DRV_TWI_USE_TWIM) + { + nrfx_twim_enable(&p_instance->u.twim); + } + else if (NRF_DRV_TWI_USE_TWI) + { + nrfx_twi_enable(&p_instance->u.twi); + } +} + +__STATIC_INLINE +void nrf_drv_twi_disable(nrf_drv_twi_t const * p_instance) +{ + if (NRF_DRV_TWI_USE_TWIM) + { + nrfx_twim_disable(&p_instance->u.twim); + } + else if (NRF_DRV_TWI_USE_TWI) + { + nrfx_twi_disable(&p_instance->u.twi); + } +} + +__STATIC_INLINE +ret_code_t nrf_drv_twi_tx(nrf_drv_twi_t const * p_instance, + uint8_t address, + uint8_t const * p_data, + uint8_t length, + bool no_stop) +{ + ret_code_t result = 0; + if (NRF_DRV_TWI_USE_TWIM) + { + result = nrfx_twim_tx(&p_instance->u.twim, + address, p_data, length, no_stop); + } + else if (NRF_DRV_TWI_USE_TWI) + { + result = nrfx_twi_tx(&p_instance->u.twi, + address, p_data, length, no_stop); + } + return result; +} + +__STATIC_INLINE +ret_code_t nrf_drv_twi_rx(nrf_drv_twi_t const * p_instance, + uint8_t address, + uint8_t * p_data, + uint8_t length) +{ + ret_code_t result = 0; + if (NRF_DRV_TWI_USE_TWIM) + { + result = nrfx_twim_rx(&p_instance->u.twim, + address, p_data, length); + } + else if (NRF_DRV_TWI_USE_TWI) + { + result = nrfx_twi_rx(&p_instance->u.twi, + address, p_data, length); + } + return result; +} + +__STATIC_INLINE +ret_code_t nrf_drv_twi_xfer(nrf_drv_twi_t const * p_instance, + nrf_drv_twi_xfer_desc_t const * p_xfer_desc, + uint32_t flags) +{ + ret_code_t result = 0; + if (NRF_DRV_TWI_USE_TWIM) + { + #ifdef TWIM_PRESENT + nrfx_twim_xfer_desc_t const twim_xfer_desc = + { + .type = (nrfx_twim_xfer_type_t)p_xfer_desc->type, + .address = p_xfer_desc->address, + .primary_length = p_xfer_desc->primary_length, + .secondary_length = p_xfer_desc->secondary_length, + .p_primary_buf = p_xfer_desc->p_primary_buf, + .p_secondary_buf = p_xfer_desc->p_secondary_buf, + }; + result = nrfx_twim_xfer(&p_instance->u.twim, &twim_xfer_desc, flags); + #endif + } + else if (NRF_DRV_TWI_USE_TWI) + { + #ifdef TWI_PRESENT + nrfx_twi_xfer_desc_t const twi_xfer_desc = + { + .type = (nrfx_twi_xfer_type_t)p_xfer_desc->type, + .address = p_xfer_desc->address, + .primary_length = p_xfer_desc->primary_length, + .secondary_length = p_xfer_desc->secondary_length, + .p_primary_buf = p_xfer_desc->p_primary_buf, + .p_secondary_buf = p_xfer_desc->p_secondary_buf, + }; + result = nrfx_twi_xfer(&p_instance->u.twi, &twi_xfer_desc, flags); + #endif + } + return result; +} + +__STATIC_INLINE +bool nrf_drv_twi_is_busy(nrf_drv_twi_t const * p_instance) +{ + bool result = 0; + if (NRF_DRV_TWI_USE_TWIM) + { + result = nrfx_twim_is_busy(&p_instance->u.twim); + } + else if (NRF_DRV_TWI_USE_TWI) + { + result = nrfx_twi_is_busy(&p_instance->u.twi); + } + return result; +} + +__STATIC_INLINE +uint32_t nrf_drv_twi_data_count_get(nrf_drv_twi_t const * const p_instance) +{ + uint32_t result = 0; + if (NRF_DRV_TWI_USE_TWIM) + { + NRFX_ASSERT(false); // not supported + result = 0; + } + else if (NRF_DRV_TWI_USE_TWI) + { + result = nrfx_twi_data_count_get(&p_instance->u.twi); + } + return result; +} + +__STATIC_INLINE +uint32_t nrf_drv_twi_start_task_get(nrf_drv_twi_t const * p_instance, + nrf_drv_twi_xfer_type_t xfer_type) +{ + uint32_t result = 0; + if (NRF_DRV_TWI_USE_TWIM) + { + result = nrfx_twim_start_task_get(&p_instance->u.twim, + (nrfx_twim_xfer_type_t)xfer_type); + } + else if (NRF_DRV_TWI_USE_TWI) + { + NRFX_ASSERT(false); // not supported + result = 0; + } + return result; +} + +__STATIC_INLINE +uint32_t nrf_drv_twi_stopped_event_get(nrf_drv_twi_t const * p_instance) +{ + uint32_t result = 0; + if (NRF_DRV_TWI_USE_TWIM) + { + result = nrfx_twim_stopped_event_get(&p_instance->u.twim); + } + else if (NRF_DRV_TWI_USE_TWI) + { + result = nrfx_twi_stopped_event_get(&p_instance->u.twi); + } + return result; +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_TWI_H__ diff --git a/integration/nrfx/legacy/nrf_drv_uart.c b/integration/nrfx/legacy/nrf_drv_uart.c new file mode 100644 index 0000000..c7c0902 --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_uart.c @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_drv_uart.h" + +#ifdef UARTE_PRESENT +#define INSTANCE_COUNT UARTE_COUNT +#else +#define INSTANCE_COUNT UART_COUNT +#endif + +static nrf_uart_event_handler_t m_handlers[INSTANCE_COUNT]; +static void * m_contexts[INSTANCE_COUNT]; + +#if defined(UARTE_PRESENT) && defined(UART_PRESENT) +uint8_t nrf_drv_uart_use_easy_dma[INSTANCE_COUNT]; +#endif + +#if defined(NRF_DRV_UART_WITH_UARTE) +static void uarte_evt_handler(nrfx_uarte_event_t const * p_event, + void * p_context) +{ + uint32_t inst_idx = (uint32_t)p_context; + nrf_drv_uart_event_t event = + { + .type = (nrf_drv_uart_evt_type_t)p_event->type, + .data = + { + .error = + { + .rxtx = + { + .p_data = p_event->data.error.rxtx.p_data, + .bytes = p_event->data.error.rxtx.bytes, + }, + .error_mask = p_event->data.error.error_mask, + } + } + }; + m_handlers[inst_idx](&event, m_contexts[inst_idx]); +} +#endif // defined(NRF_DRV_UART_WITH_UARTE) + +#if defined(NRF_DRV_UART_WITH_UART) +static void uart_evt_handler(nrfx_uart_event_t const * p_event, + void * p_context) +{ + uint32_t inst_idx = (uint32_t)p_context; + nrf_drv_uart_event_t event = + { + .type = (nrf_drv_uart_evt_type_t)p_event->type, + .data = + { + .error = + { + .rxtx = + { + .p_data = p_event->data.error.rxtx.p_data, + .bytes = p_event->data.error.rxtx.bytes, + }, + .error_mask = p_event->data.error.error_mask, + } + } + }; + m_handlers[inst_idx](&event, m_contexts[inst_idx]); +} +#endif // defined(NRF_DRV_UART_WITH_UART) + +ret_code_t nrf_drv_uart_init(nrf_drv_uart_t const * p_instance, + nrf_drv_uart_config_t const * p_config, + nrf_uart_event_handler_t event_handler) +{ + uint32_t inst_idx = p_instance->inst_idx; + m_handlers[inst_idx] = event_handler; + m_contexts[inst_idx] = p_config->p_context; + +#if defined(NRF_DRV_UART_WITH_UARTE) && defined(NRF_DRV_UART_WITH_UART) +#ifdef NRF52840_XXAA + if (inst_idx == 1) + { + ASSERT(p_config->use_easy_dma); + } +#endif + nrf_drv_uart_use_easy_dma[inst_idx] = p_config->use_easy_dma; +#endif + + nrf_drv_uart_config_t config = *p_config; + config.p_context = (void *)inst_idx; + + ret_code_t result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_init(&p_instance->uarte, + (nrfx_uarte_config_t const *)&config, + event_handler ? uarte_evt_handler : NULL); + } + else if (NRF_DRV_UART_USE_UART) + { + result = nrfx_uart_init(&p_instance->uart, + (nrfx_uart_config_t const *)&config, + event_handler ? uart_evt_handler : NULL); + } + return result; +} diff --git a/integration/nrfx/legacy/nrf_drv_uart.h b/integration/nrfx/legacy/nrf_drv_uart.h new file mode 100644 index 0000000..b2202b5 --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_uart.h @@ -0,0 +1,660 @@ +/** + * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_UART_H__ +#define NRF_DRV_UART_H__ + +#include + +#if defined(UARTE_PRESENT) && NRFX_CHECK(NRFX_UARTE_ENABLED) + #define NRF_DRV_UART_WITH_UARTE +#endif +#if defined(UART_PRESENT) && NRFX_CHECK(NRFX_UART_ENABLED) + #define NRF_DRV_UART_WITH_UART +#endif + +#if defined(NRF_DRV_UART_WITH_UARTE) + #include + #define NRF_DRV_UART_CREATE_UARTE(id) \ + .uarte = NRFX_UARTE_INSTANCE(id), +#else + // Compilers (at least the smart ones) will remove the UARTE related code + // (blocks starting with "if (NRF_DRV_UART_USE_UARTE)") when it is not used, + // but to perform the compilation they need the following definitions. + #define nrfx_uarte_init(...) 0 + #define nrfx_uarte_uninit(...) + #define nrfx_uarte_task_address_get(...) 0 + #define nrfx_uarte_event_address_get(...) 0 + #define nrfx_uarte_tx(...) 0 + #define nrfx_uarte_tx_in_progress(...) 0 + #define nrfx_uarte_tx_abort(...) + #define nrfx_uarte_rx(...) 0 + #define nrfx_uarte_rx_ready(...) 0 + #define nrfx_uarte_rx_abort(...) + #define nrfx_uarte_errorsrc_get(...) 0 + #define NRF_DRV_UART_CREATE_UARTE(id) +#endif + +#if defined(NRF_DRV_UART_WITH_UART) + #include + + #define NRF_DRV_UART_CREATE_UART(id) _NRF_DRV_UART_CREATE_UART(id) + #define _NRF_DRV_UART_CREATE_UART(id) NRF_DRV_UART_CREATE_UART_##id + #define NRF_DRV_UART_CREATE_UART_0 \ + .uart = NRFX_UART_INSTANCE(0), + #define NRF_DRV_UART_CREATE_UART_1 \ + .uart = { .p_reg = NULL }, + +#else + // Compilers (at least the smart ones) will remove the UART related code + // (blocks starting with "if (NRF_DRV_UART_USE_UART)") when it is not used, + // but to perform the compilation they need the following definitions. + #define nrfx_uart_init(...) 0 + #define nrfx_uart_uninit(...) + #define nrfx_uart_task_address_get(...) 0 + #define nrfx_uart_event_address_get(...) 0 + #define nrfx_uart_tx(...) 0 + #define nrfx_uart_tx_in_progress(...) 0 + #define nrfx_uart_tx_abort(...) + #define nrfx_uart_rx(...) 0 + #define nrfx_uart_rx_enable(...) + #define nrfx_uart_rx_disable(...) + #define nrfx_uart_rx_ready(...) 0 + #define nrfx_uart_rx_abort(...) + #define nrfx_uart_errorsrc_get(...) 0 + #define NRF_DRV_UART_CREATE_UART(id) + + // This part is for old modules that use directly UART HAL definitions + // (to make them compilable for chips that have only UARTE). + #define NRF_UART_BAUDRATE_1200 NRF_UARTE_BAUDRATE_1200 + #define NRF_UART_BAUDRATE_2400 NRF_UARTE_BAUDRATE_2400 + #define NRF_UART_BAUDRATE_4800 NRF_UARTE_BAUDRATE_4800 + #define NRF_UART_BAUDRATE_9600 NRF_UARTE_BAUDRATE_9600 + #define NRF_UART_BAUDRATE_14400 NRF_UARTE_BAUDRATE_14400 + #define NRF_UART_BAUDRATE_19200 NRF_UARTE_BAUDRATE_19200 + #define NRF_UART_BAUDRATE_28800 NRF_UARTE_BAUDRATE_28800 + #define NRF_UART_BAUDRATE_38400 NRF_UARTE_BAUDRATE_38400 + #define NRF_UART_BAUDRATE_57600 NRF_UARTE_BAUDRATE_57600 + #define NRF_UART_BAUDRATE_76800 NRF_UARTE_BAUDRATE_76800 + #define NRF_UART_BAUDRATE_115200 NRF_UARTE_BAUDRATE_115200 + #define NRF_UART_BAUDRATE_230400 NRF_UARTE_BAUDRATE_230400 + #define NRF_UART_BAUDRATE_250000 NRF_UARTE_BAUDRATE_250000 + #define NRF_UART_BAUDRATE_460800 NRF_UARTE_BAUDRATE_460800 + #define NRF_UART_BAUDRATE_921600 NRF_UARTE_BAUDRATE_921600 + #define NRF_UART_BAUDRATE_1000000 NRF_UARTE_BAUDRATE_1000000 + typedef nrf_uarte_baudrate_t nrf_uart_baudrate_t; + #define NRF_UART_ERROR_OVERRUN_MASK NRF_UARTE_ERROR_OVERRUN_MASK + #define NRF_UART_ERROR_PARITY_MASK NRF_UARTE_ERROR_PARITY_MASK + #define NRF_UART_ERROR_FRAMING_MASK NRF_UARTE_ERROR_PARITY_MASK + #define NRF_UART_ERROR_BREAK_MASK NRF_UARTE_ERROR_BREAK_MASK + typedef nrf_uarte_error_mask_t nrf_uart_error_mask_t; + #define NRF_UART_HWFC_DISABLED NRF_UARTE_HWFC_DISABLED + #define NRF_UART_HWFC_ENABLED NRF_UARTE_HWFC_ENABLED + typedef nrf_uarte_hwfc_t nrf_uart_hwfc_t; + #define NRF_UART_PARITY_EXCLUDED NRF_UARTE_PARITY_EXCLUDED + #define NRF_UART_PARITY_INCLUDED NRF_UARTE_PARITY_INCLUDED + typedef nrf_uarte_parity_t nrf_uart_parity_t; + typedef nrf_uarte_task_t nrf_uart_task_t; + typedef nrf_uarte_event_t nrf_uart_event_t; + #define NRF_UART_PSEL_DISCONNECTED NRF_UARTE_PSEL_DISCONNECTED + #define nrf_uart_event_clear(...) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_uart UART driver - legacy layer + * @{ + * @ingroup nrf_uart + * @brief Layer providing compatibility with the former API. + */ + +/** + * @brief Structure for the UART driver instance. + */ +typedef struct +{ + uint8_t inst_idx; +#if defined(NRF_DRV_UART_WITH_UARTE) + nrfx_uarte_t uarte; +#endif +#if defined(NRF_DRV_UART_WITH_UART) + nrfx_uart_t uart; +#endif +} nrf_drv_uart_t; + +/** + * @brief Macro for creating an UART driver instance. + */ +#define NRF_DRV_UART_INSTANCE(id) \ +{ \ + .inst_idx = id, \ + NRF_DRV_UART_CREATE_UARTE(id) \ + NRF_DRV_UART_CREATE_UART(id) \ +} + +/** + * @brief Types of UART driver events. + */ +typedef enum +{ + NRF_DRV_UART_EVT_TX_DONE, ///< Requested TX transfer completed. + NRF_DRV_UART_EVT_RX_DONE, ///< Requested RX transfer completed. + NRF_DRV_UART_EVT_ERROR, ///< Error reported by UART peripheral. +} nrf_drv_uart_evt_type_t; + +/**@brief Structure for UART configuration. */ +typedef struct +{ + uint32_t pseltxd; ///< TXD pin number. + uint32_t pselrxd; ///< RXD pin number. + uint32_t pselcts; ///< CTS pin number. + uint32_t pselrts; ///< RTS pin number. + void * p_context; ///< Context passed to interrupt handler. + nrf_uart_hwfc_t hwfc; ///< Flow control configuration. + nrf_uart_parity_t parity; ///< Parity configuration. + nrf_uart_baudrate_t baudrate; ///< Baudrate. + uint8_t interrupt_priority; ///< Interrupt priority. +#if defined(NRF_DRV_UART_WITH_UARTE) && defined(NRF_DRV_UART_WITH_UART) + bool use_easy_dma; +#endif +} nrf_drv_uart_config_t; + +#if defined(NRF_DRV_UART_WITH_UARTE) && defined(NRF_DRV_UART_WITH_UART) +extern uint8_t nrf_drv_uart_use_easy_dma[]; +#define NRF_DRV_UART_DEFAULT_CONFIG_USE_EASY_DMA .use_easy_dma = true, +#else +#define NRF_DRV_UART_DEFAULT_CONFIG_USE_EASY_DMA +#endif + +/**@brief UART default configuration. */ +#define NRF_DRV_UART_DEFAULT_CONFIG \ +{ \ + .pseltxd = NRF_UART_PSEL_DISCONNECTED, \ + .pselrxd = NRF_UART_PSEL_DISCONNECTED, \ + .pselcts = NRF_UART_PSEL_DISCONNECTED, \ + .pselrts = NRF_UART_PSEL_DISCONNECTED, \ + .p_context = NULL, \ + .hwfc = (nrf_uart_hwfc_t)UART_DEFAULT_CONFIG_HWFC, \ + .parity = (nrf_uart_parity_t)UART_DEFAULT_CONFIG_PARITY, \ + .baudrate = (nrf_uart_baudrate_t)UART_DEFAULT_CONFIG_BAUDRATE, \ + .interrupt_priority = UART_DEFAULT_CONFIG_IRQ_PRIORITY, \ + NRF_DRV_UART_DEFAULT_CONFIG_USE_EASY_DMA \ +} + +/**@brief Structure for UART transfer completion event. */ +typedef struct +{ + uint8_t * p_data; ///< Pointer to memory used for transfer. + uint8_t bytes; ///< Number of bytes transfered. +} nrf_drv_uart_xfer_evt_t; + +/**@brief Structure for UART error event. */ +typedef struct +{ + nrf_drv_uart_xfer_evt_t rxtx; ///< Transfer details includes number of bytes transfered. + uint32_t error_mask;///< Mask of error flags that generated the event. +} nrf_drv_uart_error_evt_t; + +/**@brief Structure for UART event. */ +typedef struct +{ + nrf_drv_uart_evt_type_t type; ///< Event type. + union + { + nrf_drv_uart_xfer_evt_t rxtx; ///< Data provided for transfer completion events. + nrf_drv_uart_error_evt_t error;///< Data provided for error event. + } data; +} nrf_drv_uart_event_t; + +/** + * @brief UART interrupt event handler. + * + * @param[in] p_event Pointer to event structure. Event is allocated on the stack so it is available + * only within the context of the event handler. + * @param[in] p_context Context passed to interrupt handler, set on initialization. + */ +typedef void (*nrf_uart_event_handler_t)(nrf_drv_uart_event_t * p_event, void * p_context); + +/** + * @brief Function for initializing the UART driver. + * + * This function configures and enables UART. After this function GPIO pins are controlled by UART. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_config Initial configuration. + * @param[in] event_handler Event handler provided by the user. If not provided driver works in + * blocking mode. + * + * @retval NRFX_SUCCESS If initialization was successful. + * @retval NRFX_ERROR_INVALID_STATE If driver is already initialized. + */ +ret_code_t nrf_drv_uart_init(nrf_drv_uart_t const * p_instance, + nrf_drv_uart_config_t const * p_config, + nrf_uart_event_handler_t event_handler); + +/** + * @brief Function for uninitializing the UART driver. + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_uart_uninit(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for getting the address of a specific UART task. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] task Task. + * + * @return Task address. + */ +__STATIC_INLINE +uint32_t nrf_drv_uart_task_address_get(nrf_drv_uart_t const * p_instance, + nrf_uart_task_t task); + +/** + * @brief Function for getting the address of a specific UART event. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] event Event. + * + * @return Event address. + */ +__STATIC_INLINE +uint32_t nrf_drv_uart_event_address_get(nrf_drv_uart_t const * p_instance, + nrf_uart_event_t event); + +/** + * @brief Function for sending data over UART. + * + * If an event handler was provided in nrf_drv_uart_init() call, this function + * returns immediately and the handler is called when the transfer is done. + * Otherwise, the transfer is performed in blocking mode, i.e. this function + * returns when the transfer is finished. Blocking mode is not using interrupt so + * there is no context switching inside the function. + * + * @note Peripherals using EasyDMA (i.e. UARTE) require that the transfer buffers + * are placed in the Data RAM region. If they are not and UARTE instance is + * used, this function will fail with error code NRFX_ERROR_INVALID_ADDR. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_data Pointer to data. + * @param[in] length Number of bytes to send. + * + * @retval NRFX_SUCCESS If initialization was successful. + * @retval NRFX_ERROR_BUSY If driver is already transferring. + * @retval NRFX_ERROR_FORBIDDEN If the transfer was aborted from a different context + * (blocking mode only, also see @ref nrf_drv_uart_rx_disable). + * @retval NRFX_ERROR_INVALID_ADDR If p_data does not point to RAM buffer (UARTE only). + */ +__STATIC_INLINE +ret_code_t nrf_drv_uart_tx(nrf_drv_uart_t const * p_instance, + uint8_t const * const p_data, + uint8_t length); + +/** + * @brief Function for checking if UART is currently transmitting. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval true If UART is transmitting. + * @retval false If UART is not transmitting. + */ +__STATIC_INLINE +bool nrf_drv_uart_tx_in_progress(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for aborting any ongoing transmission. + * @note @ref NRF_DRV_UART_EVT_TX_DONE event will be generated in non-blocking mode. Event will + * contain number of bytes sent until abort was called. If Easy DMA is not used event will be + * called from the function context. If Easy DMA is used it will be called from UART interrupt + * context. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_uart_tx_abort(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for receiving data over UART. + * + * If an event handler was provided in the nrf_drv_uart_init() call, this function + * returns immediately and the handler is called when the transfer is done. + * Otherwise, the transfer is performed in blocking mode, i.e. this function + * returns when the transfer is finished. Blocking mode is not using interrupt so + * there is no context switching inside the function. + * The receive buffer pointer is double buffered in non-blocking mode. The secondary + * buffer can be set immediately after starting the transfer and will be filled + * when the primary buffer is full. The double buffering feature allows + * receiving data continuously. + * + * @note Peripherals using EasyDMA (i.e. UARTE) require that the transfer buffers + * are placed in the Data RAM region. If they are not and UARTE driver instance + * is used, this function will fail with error code NRFX_ERROR_INVALID_ADDR. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_data Pointer to data. + * @param[in] length Number of bytes to receive. + * + * @retval NRFX_SUCCESS If initialization was successful. + * @retval NRFX_ERROR_BUSY If the driver is already receiving + * (and the secondary buffer has already been set + * in non-blocking mode). + * @retval NRFX_ERROR_FORBIDDEN If the transfer was aborted from a different context + * (blocking mode only, also see @ref nrf_drv_uart_rx_disable). + * @retval NRFX_ERROR_INTERNAL If UART peripheral reported an error. + * @retval NRFX_ERROR_INVALID_ADDR If p_data does not point to RAM buffer (UARTE only). + */ +__STATIC_INLINE +ret_code_t nrf_drv_uart_rx(nrf_drv_uart_t const * p_instance, + uint8_t * p_data, + uint8_t length); + + + +/** + * @brief Function for testing the receiver state in blocking mode. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval true If the receiver has at least one byte of data to get. + * @retval false If the receiver is empty. + */ +__STATIC_INLINE +bool nrf_drv_uart_rx_ready(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for enabling the receiver. + * + * UART has a 6-byte-long RX FIFO and it is used to store incoming data. If a user does not call the + * UART receive function before the FIFO is filled, an overrun error will appear. Enabling the receiver + * without specifying an RX buffer is supported only in UART mode (without Easy DMA). The receiver must be + * explicitly closed by the user @sa nrf_drv_uart_rx_disable. This function asserts if the mode is wrong. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_uart_rx_enable(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for disabling the receiver. + * + * This function must be called to close the receiver after it has been explicitly enabled by + * @sa nrf_drv_uart_rx_enable. The feature is supported only in UART mode (without Easy DMA). The function + * asserts if mode is wrong. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_uart_rx_disable(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for aborting any ongoing reception. + * @note @ref NRF_DRV_UART_EVT_RX_DONE event will be generated in non-blocking mode. The event will + * contain the number of bytes received until abort was called. The event is called from UART interrupt + * context. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE +void nrf_drv_uart_rx_abort(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for reading error source mask. Mask contains values from @ref nrf_uart_error_mask_t. + * @note Function should be used in blocking mode only. In case of non-blocking mode, an error event is + * generated. Function clears error sources after reading. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval Mask of reported errors. + */ +__STATIC_INLINE +uint32_t nrf_drv_uart_errorsrc_get(nrf_drv_uart_t const * p_instance); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +#if defined(NRF_DRV_UART_WITH_UARTE) && defined(NRF_DRV_UART_WITH_UART) + #define NRF_DRV_UART_USE_UARTE (nrf_drv_uart_use_easy_dma[p_instance->inst_idx]) +#elif defined(NRF_DRV_UART_WITH_UARTE) + #define NRF_DRV_UART_USE_UARTE true +#else + #define NRF_DRV_UART_USE_UARTE false +#endif +#define NRF_DRV_UART_USE_UART (!NRF_DRV_UART_USE_UARTE) + +__STATIC_INLINE +void nrf_drv_uart_uninit(nrf_drv_uart_t const * p_instance) +{ + if (NRF_DRV_UART_USE_UARTE) + { + nrfx_uarte_uninit(&p_instance->uarte); + } + else if (NRF_DRV_UART_USE_UART) + { + nrfx_uart_uninit(&p_instance->uart); + } +} + +__STATIC_INLINE +uint32_t nrf_drv_uart_task_address_get(nrf_drv_uart_t const * p_instance, + nrf_uart_task_t task) +{ + uint32_t result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_task_address_get(&p_instance->uarte, + (nrf_uarte_task_t)task); + } + else if (NRF_DRV_UART_USE_UART) + { + result = nrfx_uart_task_address_get(&p_instance->uart, task); + } + return result; +} + +__STATIC_INLINE +uint32_t nrf_drv_uart_event_address_get(nrf_drv_uart_t const * p_instance, + nrf_uart_event_t event) +{ + uint32_t result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_event_address_get(&p_instance->uarte, + (nrf_uarte_event_t)event); + } + else if (NRF_DRV_UART_USE_UART) + { + result = nrfx_uart_event_address_get(&p_instance->uart, event); + } + return result; +} + +__STATIC_INLINE +ret_code_t nrf_drv_uart_tx(nrf_drv_uart_t const * p_instance, + uint8_t const * p_data, + uint8_t length) +{ + uint32_t result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_tx(&p_instance->uarte, + p_data, + length); + } + else if (NRF_DRV_UART_USE_UART) + { + result = nrfx_uart_tx(&p_instance->uart, + p_data, + length); + } + return result; +} + +__STATIC_INLINE +bool nrf_drv_uart_tx_in_progress(nrf_drv_uart_t const * p_instance) +{ + bool result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_tx_in_progress(&p_instance->uarte); + } + else if (NRF_DRV_UART_USE_UART) + { + result = nrfx_uart_tx_in_progress(&p_instance->uart); + } + return result; +} + +__STATIC_INLINE +void nrf_drv_uart_tx_abort(nrf_drv_uart_t const * p_instance) +{ + if (NRF_DRV_UART_USE_UARTE) + { + nrfx_uarte_tx_abort(&p_instance->uarte); + } + else if (NRF_DRV_UART_USE_UART) + { + nrfx_uart_tx_abort(&p_instance->uart); + } +} + +__STATIC_INLINE +ret_code_t nrf_drv_uart_rx(nrf_drv_uart_t const * p_instance, + uint8_t * p_data, + uint8_t length) +{ + uint32_t result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_rx(&p_instance->uarte, + p_data, + length); + } + else if (NRF_DRV_UART_USE_UART) + { + result = nrfx_uart_rx(&p_instance->uart, + p_data, + length); + } + return result; +} + +__STATIC_INLINE +bool nrf_drv_uart_rx_ready(nrf_drv_uart_t const * p_instance) +{ + bool result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_rx_ready(&p_instance->uarte); + } + else if (NRF_DRV_UART_USE_UART) + { + result = nrfx_uart_rx_ready(&p_instance->uart); + } + return result; +} + +__STATIC_INLINE +void nrf_drv_uart_rx_enable(nrf_drv_uart_t const * p_instance) +{ + if (NRF_DRV_UART_USE_UARTE) + { + NRFX_ASSERT(false); // not supported + } + else if (NRF_DRV_UART_USE_UART) + { + nrfx_uart_rx_enable(&p_instance->uart); + } +} + +__STATIC_INLINE +void nrf_drv_uart_rx_disable(nrf_drv_uart_t const * p_instance) +{ + if (NRF_DRV_UART_USE_UARTE) + { + NRFX_ASSERT(false); // not supported + } + else if (NRF_DRV_UART_USE_UART) + { + nrfx_uart_rx_disable(&p_instance->uart); + } +} + +__STATIC_INLINE +void nrf_drv_uart_rx_abort(nrf_drv_uart_t const * p_instance) +{ + if (NRF_DRV_UART_USE_UARTE) + { + nrfx_uarte_rx_abort(&p_instance->uarte); + } + else if (NRF_DRV_UART_USE_UART) + { + nrfx_uart_rx_abort(&p_instance->uart); + } +} + +__STATIC_INLINE +uint32_t nrf_drv_uart_errorsrc_get(nrf_drv_uart_t const * p_instance) +{ + uint32_t result = 0; + if (NRF_DRV_UART_USE_UARTE) + { + result = nrfx_uarte_errorsrc_get(&p_instance->uarte); + } + else if (NRF_DRV_UART_USE_UART) + { + nrf_uart_event_clear(p_instance->uart.p_reg, NRF_UART_EVENT_ERROR); + result = nrfx_uart_errorsrc_get(&p_instance->uart); + } + return result; +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_UART_H__ diff --git a/integration/nrfx/legacy/nrf_drv_wdt.h b/integration/nrfx/legacy/nrf_drv_wdt.h new file mode 100644 index 0000000..007669e --- /dev/null +++ b/integration/nrfx/legacy/nrf_drv_wdt.h @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_DRV_WDT_H__ +#define NRF_DRV_WDT_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_wdt WDT driver - legacy layer + * @{ + * @ingroup nrf_wdt + * + * @brief A layer providing compatibility with former API. + */ + +/** @brief Type definition for forwarding the new implementation. */ +typedef nrfx_wdt_config_t nrf_drv_wdt_config_t; + +/** @brief Macro for forwarding the new implementation. */ +#define NRF_DRV_WDT_DEAFULT_CONFIG NRFX_WDT_DEAFULT_CONFIG + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_wdt_event_handler_t nrfx_wdt_event_handler_t +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_wdt_channel_id nrfx_wdt_channel_id + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_wdt_channel_alloc nrfx_wdt_channel_alloc +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_wdt_enable nrfx_wdt_enable +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_wdt_feed nrfx_wdt_feed +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_wdt_channel_feed nrfx_wdt_channel_feed + +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_wdt_ppi_task_addr nrfx_wdt_ppi_task_addr +/** @brief Macro for forwarding the new implementation. */ +#define nrf_drv_wdt_ppi_event_addr nrfx_wdt_ppi_event_addr + +/** + * @brief This function initializes watchdog. + * + * @param[in] p_config Pointer to the structure with initial configuration. Default + * configuration used if NULL. + * @param[in] wdt_event_handler Specifies event handler provided by user. + * + * @note Function asserts if wdt_event_handler is NULL. + * + * @return NRF_SUCCESS on success, otherwise an error code. + */ +__STATIC_INLINE ret_code_t nrf_drv_wdt_init(nrf_drv_wdt_config_t const * p_config, + nrf_wdt_event_handler_t wdt_event_handler) +{ + if (p_config == NULL) + { + static const nrfx_wdt_config_t default_config = NRFX_WDT_DEAFULT_CONFIG; + p_config = &default_config; + } + return nrfx_wdt_init(p_config, wdt_event_handler); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_WDT_H__ diff --git a/integration/nrfx/nrfx_config.h b/integration/nrfx/nrfx_config.h new file mode 100644 index 0000000..02e7bda --- /dev/null +++ b/integration/nrfx/nrfx_config.h @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRFX_CONFIG_H__ +#define NRFX_CONFIG_H__ + +// TODO - temporary redirection +#include + +#endif // NRFX_CONFIG_H__ diff --git a/integration/nrfx/nrfx_glue.h b/integration/nrfx/nrfx_glue.h new file mode 100644 index 0000000..c637edd --- /dev/null +++ b/integration/nrfx/nrfx_glue.h @@ -0,0 +1,338 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRFX_GLUE_H__ +#define NRFX_GLUE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrfx_glue nrfx_glue.h + * @{ + * @ingroup nrfx + * + * @brief This file contains macros that should be implemented according to + * the needs of the host environment into which @em nrfx is integrated. + */ + +#include + +#include + +//------------------------------------------------------------------------------ + +#include +/** + * @brief Macro for placing a runtime assertion. + * + * @param expression Expression to evaluate. + */ +#define NRFX_ASSERT(expression) ASSERT(expression) + +#include +/** + * @brief Macro for placing a compile time assertion. + * + * @param expression Expression to evaluate. + */ +#define NRFX_STATIC_ASSERT(expression) STATIC_ASSERT(expression) + +//------------------------------------------------------------------------------ + +#ifdef NRF51 +#ifdef SOFTDEVICE_PRESENT +#define INTERRUPT_PRIORITY_IS_VALID(pri) (((pri) == 1) || ((pri) == 3)) +#else +#define INTERRUPT_PRIORITY_IS_VALID(pri) ((pri) < 4) +#endif //SOFTDEVICE_PRESENT +#else +#ifdef SOFTDEVICE_PRESENT +#define INTERRUPT_PRIORITY_IS_VALID(pri) ((((pri) > 1) && ((pri) < 4)) || \ + (((pri) > 4) && ((pri) < 8))) +#else +#define INTERRUPT_PRIORITY_IS_VALID(pri) ((pri) < 8) +#endif //SOFTDEVICE_PRESENT +#endif //NRF52 + +/** + * @brief Macro for setting the priority of a specific IRQ. + * + * @param irq_number IRQ number. + * @param priority Priority to set. + */ +#define NRFX_IRQ_PRIORITY_SET(irq_number, priority) \ + _NRFX_IRQ_PRIORITY_SET(irq_number, priority) +static inline void _NRFX_IRQ_PRIORITY_SET(IRQn_Type irq_number, + uint8_t priority) +{ + ASSERT(INTERRUPT_PRIORITY_IS_VALID(priority)); + NVIC_SetPriority(irq_number, priority); +} + +/** + * @brief Macro for enabling a specific IRQ. + * + * @param irq_number IRQ number. + */ +#define NRFX_IRQ_ENABLE(irq_number) _NRFX_IRQ_ENABLE(irq_number) +static inline void _NRFX_IRQ_ENABLE(IRQn_Type irq_number) +{ + NVIC_EnableIRQ(irq_number); +} + +/** + * @brief Macro for checking if a specific IRQ is enabled. + * + * @param irq_number IRQ number. + * + * @retval true If the IRQ is enabled. + * @retval false Otherwise. + */ +#define NRFX_IRQ_IS_ENABLED(irq_number) _NRFX_IRQ_IS_ENABLED(irq_number) +static inline bool _NRFX_IRQ_IS_ENABLED(IRQn_Type irq_number) +{ + return 0 != (NVIC->ISER[irq_number / 32] & (1UL << (irq_number % 32))); +} + +/** + * @brief Macro for disabling a specific IRQ. + * + * @param irq_number IRQ number. + */ +#define NRFX_IRQ_DISABLE(irq_number) _NRFX_IRQ_DISABLE(irq_number) +static inline void _NRFX_IRQ_DISABLE(IRQn_Type irq_number) +{ + NVIC_DisableIRQ(irq_number); +} + +/** + * @brief Macro for setting a specific IRQ as pending. + * + * @param irq_number IRQ number. + */ +#define NRFX_IRQ_PENDING_SET(irq_number) _NRFX_IRQ_PENDING_SET(irq_number) +static inline void _NRFX_IRQ_PENDING_SET(IRQn_Type irq_number) +{ + NVIC_SetPendingIRQ(irq_number); +} + +/** + * @brief Macro for clearing the pending status of a specific IRQ. + * + * @param irq_number IRQ number. + */ +#define NRFX_IRQ_PENDING_CLEAR(irq_number) _NRFX_IRQ_PENDING_CLEAR(irq_number) +static inline void _NRFX_IRQ_PENDING_CLEAR(IRQn_Type irq_number) +{ + NVIC_ClearPendingIRQ(irq_number); +} + +/** + * @brief Macro for checking the pending status of a specific IRQ. + * + * @retval true If the IRQ is pending. + * @retval false Otherwise. + */ +#define NRFX_IRQ_IS_PENDING(irq_number) _NRFX_IRQ_IS_PENDING(irq_number) +static inline bool _NRFX_IRQ_IS_PENDING(IRQn_Type irq_number) +{ + return (NVIC_GetPendingIRQ(irq_number) == 1); +} + +#include +#include +/** + * @brief Macro for entering into a critical section. + */ +#define NRFX_CRITICAL_SECTION_ENTER() CRITICAL_REGION_ENTER() + +/** + * @brief Macro for exiting from a critical section. + */ +#define NRFX_CRITICAL_SECTION_EXIT() CRITICAL_REGION_EXIT() + +//------------------------------------------------------------------------------ + +/** + * @brief When set to a non-zero value, this macro specifies that + * @ref nrfx_coredep_delay_us uses a precise DWT-based solution. + * A compilation error is generated if the DWT unit is not present + * in the SoC used. + */ +#define NRFX_DELAY_DWT_BASED 0 + +#include + +#define NRFX_DELAY_US(us_time) nrfx_coredep_delay_us(us_time) + +//------------------------------------------------------------------------------ + +#include + +/** + * @brief Atomic 32 bit unsigned type. + */ +#define nrfx_atomic_t nrfx_atomic_u32_t + +/** + * @brief Stores value to an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value to store. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_STORE(p_data, value) nrfx_atomic_u32_fetch_store(p_data, value) + +/** + * @brief Performs logical OR operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of OR operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_OR(p_data, value) nrfx_atomic_u32_fetch_or(p_data, value) + +/** + * @brief Performs logical AND operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of AND operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_AND(p_data, value) nrfx_atomic_u32_fetch_and(p_data, value) + +/** + * @brief Performs logical XOR operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of XOR operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_XOR(p_data, value) nrfx_atomic_u32_fetch_xor(p_data, value) + +/** + * @brief Performs logical ADD operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of ADD operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_ADD(p_data, value) nrfx_atomic_u32_fetch_add(p_data, value) + +/** + * @brief Performs logical SUB operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of SUB operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_SUB(p_data, value) nrfx_atomic_u32_fetch_sub(p_data, value) + +//------------------------------------------------------------------------------ +#ifndef NRFX_CUSTOM_ERROR_CODES + +#include +/** + * @brief When set to a non-zero value, this macro specifies that the + * @ref nrfx_error_codes and the @ref ret_code_t type itself are defined + * in a customized way and the default definitions from @c + * should not be used. + */ +#define NRFX_CUSTOM_ERROR_CODES 1 + +typedef ret_code_t nrfx_err_t; + +#define NRFX_SUCCESS NRF_SUCCESS +#define NRFX_ERROR_INTERNAL NRF_ERROR_INTERNAL +#define NRFX_ERROR_NO_MEM NRF_ERROR_NO_MEM +#define NRFX_ERROR_NOT_SUPPORTED NRF_ERROR_NOT_SUPPORTED +#define NRFX_ERROR_INVALID_PARAM NRF_ERROR_INVALID_PARAM +#define NRFX_ERROR_INVALID_STATE NRF_ERROR_INVALID_STATE +#define NRFX_ERROR_INVALID_LENGTH NRF_ERROR_INVALID_LENGTH +#define NRFX_ERROR_TIMEOUT NRF_ERROR_TIMEOUT +#define NRFX_ERROR_FORBIDDEN NRF_ERROR_FORBIDDEN +#define NRFX_ERROR_NULL NRF_ERROR_NULL +#define NRFX_ERROR_INVALID_ADDR NRF_ERROR_INVALID_ADDR +#define NRFX_ERROR_BUSY NRF_ERROR_BUSY +#define NRFX_ERROR_ALREADY_INITIALIZED NRF_ERROR_MODULE_ALREADY_INITIALIZED + +#define NRFX_ERROR_DRV_TWI_ERR_OVERRUN NRF_ERROR_DRV_TWI_ERR_OVERRUN +#define NRFX_ERROR_DRV_TWI_ERR_ANACK NRF_ERROR_DRV_TWI_ERR_ANACK +#define NRFX_ERROR_DRV_TWI_ERR_DNACK NRF_ERROR_DRV_TWI_ERR_DNACK + +#endif // NRFX_CUSTOM_ERROR_CODES +//------------------------------------------------------------------------------ + +#include +/** + * @brief Bitmask defining PPI channels reserved to be used outside of nrfx. + */ +#define NRFX_PPI_CHANNELS_USED NRF_PPI_CHANNELS_USED + +/** + * @brief Bitmask defining PPI groups reserved to be used outside of nrfx. + */ +#define NRFX_PPI_GROUPS_USED NRF_PPI_GROUPS_USED + +/** + * @brief Bitmask defining SWI instances reserved to be used outside of nrfx. + */ +#define NRFX_SWI_USED NRF_SWI_USED + +/** + * @brief Bitmask defining TIMER instances reserved to be used outside of nrfx. + */ +#define NRFX_TIMERS_USED NRF_TIMERS_USED + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRFX_GLUE_H__ diff --git a/integration/nrfx/nrfx_log.h b/integration/nrfx/nrfx_log.h new file mode 100644 index 0000000..7b2440f --- /dev/null +++ b/integration/nrfx/nrfx_log.h @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRFX_LOG_H__ +#define NRFX_LOG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(NRFX_LOG_MODULE) +#define NRF_LOG_MODULE_NAME NRFX_LOG_MODULE + +#define NRFX_CONFIG_ENTRY(x) CONCAT_3(NRFX_, NRFX_LOG_MODULE, x) + +#if NRFX_CHECK(NRFX_CONFIG_ENTRY(_CONFIG_LOG_ENABLED)) +#define NRF_LOG_LEVEL NRFX_CONFIG_ENTRY(_CONFIG_LOG_LEVEL) +#define NRF_LOG_INFO_COLOR NRFX_CONFIG_ENTRY(_CONFIG_INFO_COLOR) +#define NRF_LOG_DEBUG_COLOR NRFX_CONFIG_ENTRY(_CONFIG_DEBUG_COLOR) +#else +#define NRF_LOG_LEVEL 0 +#endif +#endif // defined(NRFX_LOG_MODULE) + +#include + +#if defined(NRFX_LOG_MODULE) +NRF_LOG_MODULE_REGISTER(); +#endif + +#define TEST_MACRO_INFO(...) NRF_LOG_INFO(__VA_ARGS__) +/** + * @defgroup nrfx_log nrfx_log.h + * @{ + * @ingroup nrfx + * + * @brief This file contains macros that should be implemented according to + * the needs of the host environment into which @em nrfx is integrated. + */ + +/** + * @brief Macro for logging a message with the severity level ERROR. + */ +#define NRFX_LOG_ERROR(...) NRF_LOG_ERROR(__VA_ARGS__) + +/** + * @brief Macro for logging a message with the severity level WARNING. + */ +#define NRFX_LOG_WARNING(...) NRF_LOG_WARNING(__VA_ARGS__) + +/** + * @brief Macro for logging a message with the severity level INFO. + */ +#define NRFX_LOG_INFO(...) TEST_MACRO_INFO(__VA_ARGS__) + +/** + * @brief Macro for logging a message with the severity level DEBUG. + */ +#define NRFX_LOG_DEBUG(...) NRF_LOG_DEBUG(__VA_ARGS__) + + +/** + * @brief Macro for logging a memory dump with the severity level ERROR. + * + * @param[in] p_memory Pointer to the memory region to be dumped. + * @param[in] length Length of the memory region in bytes. + */ +#define NRFX_LOG_HEXDUMP_ERROR(p_memory, length) \ + NRF_LOG_HEXDUMP_ERROR(p_memory, length) + +/** + * @brief Macro for logging a memory dump with the severity level WARNING. + * + * @param[in] p_memory Pointer to the memory region to be dumped. + * @param[in] length Length of the memory region in bytes. + */ +#define NRFX_LOG_HEXDUMP_WARNING(p_memory, length) \ + NRF_LOG_HEXDUMP_WARNING(p_memory, length) + +/** + * @brief Macro for logging a memory dump with the severity level INFO. + * + * @param[in] p_memory Pointer to the memory region to be dumped. + * @param[in] length Length of the memory region in bytes. + */ +#define NRFX_LOG_HEXDUMP_INFO(p_memory, length) \ + NRF_LOG_HEXDUMP_INFO(p_memory, length) + +/** + * @brief Macro for logging a memory dump with the severity level DEBUG. + * + * @param[in] p_memory Pointer to the memory region to be dumped. + * @param[in] length Length of the memory region in bytes. + */ +#define NRFX_LOG_HEXDUMP_DEBUG(p_memory, length) \ + NRF_LOG_HEXDUMP_DEBUG(p_memory, length) + + +/** + * @brief Macro for getting the textual representation of a given error code. + * + * @param[in] error_code Error code. + * + * @return String containing the textual representation of the error code. + */ +#define NRFX_LOG_ERROR_STRING_GET(error_code) \ + NRF_LOG_ERROR_STRING_GET(error_code) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRFX_LOG_H__ diff --git a/modules/nrfx/CHANGELOG.md b/modules/nrfx/CHANGELOG.md new file mode 100644 index 0000000..f8568a6 --- /dev/null +++ b/modules/nrfx/CHANGELOG.md @@ -0,0 +1,300 @@ +# Changelog +All notable changes to this project are documented in this file. + +## [1.9.0] - 2021-07-15 +### Added +- Added high-drive pin configuration in the QSPI driver. +- Added report period setting of 1 sample in the QDEC HAL. + +### Changed +- Updated MDK to version 8.40.3. + +### Fixed +- Fixed register access sequence in the COMP driver. +- Fixed memory corruption when uninitialized channel was freed in the GPIOTE driver. +- Fixed a race condition in the NFCT driver when starting the transfer. + +## [1.8.6] - 2020-08-31 +### Added +- Implemented workaround for anomaly 223 in the USBD driver. + +### Changed +- Updated MDK to version 8.35.0. + +## [1.8.5] - 2020-07-09 +### Added +- Implemented workaround for anomaly 211 in the USBD driver. + +### Changed +- Updated MDK to version 8.32.3. + +## [1.8.4] - 2020-04-27 +- Fixed an issue in the NFCT driver where the FIELDDETECTED event would be ignored and the FIELDLOST event would be processed twice. The driver now properly handles FIELDDETECTED and FIELDLOST events. + +## [1.8.3] - 2020-03-20 +### Added +- Added documentation pages for nRF52820. +- Added possibility to use the nRF52833 DK in development for nRF52820. LEDs and buttons in this DK use GPIOs that are not present in the actual nRF52820 device, so accesses to these need special handling in the GPIO HAL. + +### Fixed +- Fixed assertions that check input pin selections in the legacy SAADC driver. Now the VDDHDIV5 setting is handled properly. +- Fixed the number of machine cycles per single delay loop for nRF52820 in the nrfx_coredep module. + +## [1.8.2] - 2020-03-05 +### Added +- Added support for nRF52820. +- Added new implementation of the SAADC driver. The new version is enabled when the NRFX_SAADC_API_V2 symbol is defined, otherwise the legacy one is used. +- Introduced the NRFX_TWIM_NO_SPURIOUS_STOP_CHECK flag in the TWIM driver. +- Added function for getting the configuration of shortcuts in the TWIM HAL. +- Implemented workaround for nRF9160 anomaly 23 in the UARTE driver. + +### Changed +- Updated MDK to version 8.32.1. +- Improved the UARTE driver to consume less current after the driver uninitialization. Now all clocks are disabled properly. +- Improved the GPIOTE driver robustness by setting the LATCH functionality to be used by default. +- Improved handling of spurious STOP condition in the TWIM driver. +- Removed support for revision Engineering A of nRF52840 in the USBD driver. + +### Fixed +- Fixed assertions that check write addresses in the NVMC driver. Now the UICR memory region is handled properly. +- Fixed an issue in the TWI driver that would make the driver stuck when a premature STOP condition was generated by a slave device. The driver now handles this situation properly and signals that a bus error occurred. +- Fixed the stopping procedure in the PWM driver. Previously in very specific circumstances the PWM output might be not stopped at all or might be immediately restarted. +- Fixed a race condition in the CLOCK driver when requested clock was stopped during ramp-up from high priority interrupt. +- Fixed assertions that check pin numbers in the GPIO HAL and GPIOTE driver. Now noncontiguous groups of available pin numbers are handled properly. + +## [1.8.1] - 2019-10-21 +### Added +- Added functions in the GPIOTE driver for getting task or event for the specified GPIO pin. + +### Changed +- Updated MDK to version 8.27.1. +- Moved the nrfx_gppi helper from helpers/nrfx_gppi/ to helpers/. +- Changed the interrupt initialization in the GPIOTE driver, so that mapping of the GPIOTEx_IRQn enumeration values is no longer needed for nRF9160. + +## [1.8.0] - 2019-08-27 +### Added +- Added support for nRF52833. +- Added bus recovery feature in the TWI and TWIM drivers. +- Added the nrfx_gppi helper layer to facilitate developing generic code that can utilize PPI or DPPI, depending on which interface is available in a given SoC. + +### Changed +- Updated MDK to version 8.27.0. + +### Fixed +- Fixed an issue in the TWIM driver that would make the driver stuck when a premature STOP condition was generated by a slave device. The driver now handles this situation properly and signals that a bus error occurred. +- Fixed a frame timing bug in the NFCT driver. Previously, the timing of the SENS_RES response could be violated after the NFCT peripheral was put to the Sleep state with the SLP_REQ command. + +## [1.7.2] - 2019-07-25 +### Added +- Added functions in the DPPI, GPIOTE, PPI, RTC, and TIMER HALs for getting tasks and events specified by index. +- Added the possibility of suspending transfers in the TWI driver. This allows combining several transfers into one continuous TWI transaction. +- Added termination of transfers at deinitialization of the UARTE driver. +- Added buffer alignment checks in the QSPI driver. +- Introduced the NRFX_OFFSETOF macro that duplicates the functionality of the built-in offsetof() mechanism, but can be used without issues also with non-constant expressions. +- Added an alternative way of ending the DMA transfer loop in the USBD driver. +- Added the CTSTARTED and CTSTOPPED events to the CLOCK HAL. + +### Changed +- Removed an assertion that prevented setting the data payload size of isochronous endpoints to zero, to fulfill requirements of the USB 2.0 specification, paragraph 5.6.3. +- Declared the tx_buffer_length field in the UART driver's control block as volatile to prevent issues in case of compilation with high optimization level. + +### Fixed +- Fixed an incorrect conversion of frequency values in the RADIO HAL. +- Fixed an incorrectly enabled interrupt in the QSPI driver. +- Corrected the LFCLK source selection values in the template configuration file for nRF9160. +- Fixed support for external LFCLK sources for nRF52811. + +## [1.7.1] - 2019-04-08 +### Added +- Added functions in the NVMC driver for getting the flash page size, the count of pages and the total flash size. + +### Fixed +- Fixed handling of short unaligned write requests (1 or 2 bytes in length) in the nrfx_nvmc_bytes_write() function. + +## [1.7.0] - 2019-03-29 +### Added +- Added drivers for NVMC and TEMP. +- Added HALs: AAR and FICR. +- Added support for the custom instruction long frame mode in the QSPI driver. + +### Changed +- Reworked HAL for NVMC. Now it can be used for all SoCs supported by nrfx. +- Reworked HAL for TEMP. +- Improved documentation. Now it is more precise and can be generated without warnings with newer versions of doxygen. +- Improved the UARTE driver to consume less current after the TX operation. Now at the end of the transmission the transmitter is turned off by the STOPTX task. +- Improved C++ support in drivers. Now fields in structures are filled up in the correct order. +- Changed to size_t the type used for holding the amount of data in the TWIS driver. + +### Fixed +- Fixed a race condition in the USBD driver. It could occur when an IN transfer was interrupted by an OUT transaction, which in turn was interrupted by a process with a higher priority. + +## [1.6.2] - 2019-02-12 +### Added +- Added the possibility to use the macro NRFX_COREDEP_DELAY_US_LOOP_CYCLES to specify the number of cycles consumed by one iteration of the internal loop in the function nrfx_coredep_delay_us(). + +### Changed +- Updated MDK to version 8.24.1. + +## [1.6.1] - 2019-01-29 +### Fixed +- Fixed an issue in the NFCT driver that caused a performance loss on nRF52832. The interrupt configuration is now properly restored after the NRFX_NFCT_EVT_FIELD_LOST event. + +## [1.6.0] - 2019-01-18 +### Added +- Added support for nRF52811. +- Added support for the legacy peripherals SPI, TWI, and UART in nRF52810. +- Added support for SAMPLERATE in nrf_saadc.h. +- Added clearing of the STOPPED event in the nrfx_saadc_init() function to prevent driver deadlock in some cases. +- Added HALs: BPROT, MPU, MWU. +- Added function for reading the pin input buffer configuration in the GPIO HAL. +- Implemented workaround for nRF9160 anomaly 1 in the I2S driver. + +### Changed +- Improved handling of hardware anomalies in the USBD driver. +- Updated MDK to version 8.23.1. + +### Fixed +- Fixed the condition in NRFX_WAIT_FOR in the nrfx_saadc_abort() function. The macro now correctly waits for a stop of the driver. +- Fixed the pending interrupt clearing in NVIC in the nrfx_usbd_stop() function. The driver now correctly handles power management. +- Fixed the case when nrfx_uarte_tx_in_progress() function would return an incorrect value. The driver now correctly updates the tx_buffer_length variable internally. + +## [1.5.0] - 2018-12-12 +### Added +- Added support for nRF9160. +- Added allocator for DPPI. +- Added HALs: DPPI, KMU, REGULATORS, SPU, VMC. +- Added support for DPPI subscription and publishing in HALs related to nRF9160. +- Added support for instances 2 and 3 in SPIS, TWIM, TWIS, and UARTE drivers. + +### Changed +- Updated MDK to version 8.21.1. + +### Fixed +- Corrected NRFX_I2S_CONFIG_RATIO value in nrfx_config.h. It now correctly uses supported value. + +## [1.4.0] - 2018-11-30 +### Added +- Added the nrfx_is_word_aligned() function for checking whether an address is word-aligned. +- Added HAL for ACL. +- Added functions for disabling and re-enabling interrupts in the SWI driver. +- Added possibility to completely remove interrupt handling from the WDT driver. + +### Changed +- Updated the documentation for the nrfx_uarte_rx() function. It now correctly reflects the actual behavior of the function. + +### Fixed +- Corrected the type of the nrfx_uarte_xfer_evt_t structure field that holds the amount of transferred bytes. +- Corrected the way of disabling interrupts in the NFCT driver when moving the peripheral to the disabled state. +- Fixed a typo in the name of the bmRequest field in the nrfx_usbd_setup_t structure. The new correct name is bRequest. +- Fixed the nrfx_ppi_channel_fork_assign() function. It now accepts also pre-programmed channels. +- Fixed handling of long custom instruction responses in the QSPI driver. +- Fixed a bug affecting the conversion of time to ticks in the TIMER HAL. + +## [1.3.1] - 2018-09-28 +### Fixed +- Corrected the type of nrfx_usbd_ep_status_get() return value. +- Corrected calls to undefined macros in NFCT and USBD drivers. + +## [1.3.0] - 2018-09-21 +### Added +- Added HAL and driver for NFCT. +- Added driver for USBD. +- Added function for setting the burst mode in the SAADC HAL. +- Added the NRFX_ARRAY_SIZE macro. + +### Changed +- Moved the implementation of nrfx_power_clock_irq_handler() to nrfx_power.c, removed nrfx_power_clock.c. + +### Fixed +- Replaced ARRAY_SIZE macro calls with NRFX_ARRAY_SIZE ones. + +## [1.2.0] - 2018-09-06 +### Added +- Added function for checking if a specific channel is enabled in the GPIOTE HAL. +- Added support for using the QDEC driver without LED. +- Added functions for modifying only the event endpoint or only the task endpoint in the PPI HAL. +- Added function for reading the pin pull configuration in the GPIO HAL. + +### Changed +- Corrected ISOSPLIT enumerator names in the USBD HAL. + +### Fixed +- Fixed a double buffering bug that occurred in the UARTE driver after the RX abort. +- Fixed the TXRX transfers in the TWIM driver. They can now be started after transfers that are not ended with the stop condition. + +## [1.1.0] - 2018-06-15 +### Added +- Implemented workaround for nRF52832 and nRF52840 anomaly 194 in the I2S driver. +- Implemented workaround for nRF52840 anomaly 195 in the SPIM driver. +- Added HALs for CCM, ECB, and RADIO. +- Extended HALs for GPIO, PPI, SAADC, and USBD. +- Added support for external LFCLK sources. + +### Changed +- Corrected handling of transfer lengths in the TWI driver. +- Updated MDK to version 8.17.0. + +### Fixed +- Fixed logging in the PPI driver. +- Fixed SPIM interrupt definition for nRF52810. +- Fixed Slave Select configuration in the SPIM driver. +- Corrected default settings for NRF_SPIM3. +- Fixed a typo in the UARTE TXDRDY event definition. +- Corrected the TIMEOUT event clearing in the WDT interrupt handler. + +## [1.0.0] - 2018-03-21 +### Added +- Added the NRFX_WAIT_FOR macro to improve the time-out functionality in QSPI and SAADC drivers. +- Added glue layer macros for checking and modifying the pending status of interrupts. +- Added new enumeration values for interrupts and events in the UARTE HAL. +- Implemented workarounds for nRF52 anomalies 192 and 201 in the CLOCK driver. +- Implemented workaround for nRF52840 anomaly 122 in the QSPI driver. +- Implemented workaround for nRF52840 anomaly 198 in the SPIM driver. + +### Changed +- Updated MDK to 8.16.0. +- Extended input pin configuration in the GPIOTE driver. +- Unified the way of checking if a required event handler was provided. Now, all drivers do it with assertions. +- Changed the RNG bias correction configuration option to be enabled by default. +- Refactored the ADC driver and HAL. +- Corrected assertions in the TIMER driver to make it usable in debug version with PPI. +- Improved buffer handling in the I2S driver. The API of the driver has been slightly modified. +- Enhanced SPIS driver API: added the "p_context" parameter, allowed NULL pointers for zero-length buffers. + +### Fixed +- Fixed result value casting in the TEMP HAL. +- Fixed types of conversion result and buffer size in the ADC HAL and driver. +- Fixed time-out in the SAADC driver in abort function. + +## [0.8.0] - 2017-12-20 +### Added +- Added XIP support in the QSPI driver. +- Implemented Errata 132 in the CLOCK driver. +- Added function for checking if a TIMER instance is enabled. +- Added extended SPIM support. + +### Changed +- Updated MDK to 8.15.0. Introduced Segger Embedded Studio startup files. +- Updated drivers: COMP, PWM, QDEC, SAADC, SPIS, TIMER, TWI, TWIS. +- Changed the type used for transfer lengths to 'size_t' in drivers: SPI, SPIM, SPIS, TWI, TWIM, TWIS, UART, UARTE. Introduced checking of EasyDMA transfers limits. +- Updated HALs: COMP, NVMC, UART, UARTE, USBD. +- Updated template files and documentation of configuration options. + +### Fixed +- Fixed TWI and TWIM drivers so that they now support GPIOs from all ports. +- Fixed definitions related to compare channels in the TIMER HAL. + +### Removed +- Removed the possibility of passing NULL instead of configuration to get default settings during drivers initialization. +- Removed support for UART1 and PRS box #5. + +## [0.7.0] - 2017-10-20 +### Added +- This CHANGELOG.md file. +- README.md file with simple description and explanations. +- HAL for: ADC, CLOCK, COMP, ECB, EGU, GPIO, GPIOTE, I2S, LPCOMP, NVMC, PDM, POWER, PPI, PWM, QDEC, QSPI, RNG, RTC, SAADC, SPI, SPIM, SPIS, ARM(R) SysTick, TEMP, TIMER, TWI, TWIM, TWIS, UART, UARTE, USBD, WDT. +- Drivers for: ADC, CLOCK, COMP, GPIOTE, I2S, LPCOMP, PDM, POWER, PWM, QDEC, QSPI, RNG, RTC, SAADC, SPI, SPIM, SPIS, ARM(R) SysTick, TIMER, TWI, TWIM, TWIS, UART, UARTE, WDT. +- Allocators for: PPI, SWI/EGU. +- MDK in version 8.14.0. +- Offline documentation for every added driver and simple integration description. +- Template integration files. diff --git a/modules/nrfx/LICENSE b/modules/nrfx/LICENSE new file mode 100644 index 0000000..2eefa1b --- /dev/null +++ b/modules/nrfx/LICENSE @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ diff --git a/modules/nrfx/README.md b/modules/nrfx/README.md new file mode 100644 index 0000000..5fc13e3 --- /dev/null +++ b/modules/nrfx/README.md @@ -0,0 +1,45 @@ +# nrfx + +## Overview + +nrfx is a standalone set of drivers for peripherals present in Nordic +Semiconductor's SoCs. It originated as an extract from the nRF5 SDK. +The intention was to provide drivers that can be used in various environments +without the necessity to integrate other parts of the SDK into them. +For the user's convenience, the drivers come with the MDK package. This package +contains definitions of register structures and bitfields for all supported +SoCs, as well as startup and initialization files for them. + +## Supported SoCs + +* nRF51 Series +* nRF52810 +* nRF52811 +* nRF52820 +* nRF52832 +* nRF52833 +* nRF52840 +* nRF9160 + +## Directories + +``` + . + ├── doc # Project documentation files + ├── drivers # nrfx driver files + │ └── include # nrfx driver headers + │ └── src # nrfx driver sources + ├── hal # Hardware Access Layer files + ├── helpers # nrfx driver helper files + ├── mdk # nRF MDK files + ├── soc # SoC specific files + └── templates # Templates of nrfx integration files +``` + +## Generating documentation + +nrfx documentation is available in the `doc\html` folder of the release package. + +You can also generate documentation yourself from the source code. To do it, install doxygen +and run one of the scripts: `generate_html_doc.bat` or `generate_html_doc.sh`. Generated +documentation will be stored in the `doc\html` directory. Use `index.html` to open it. diff --git a/modules/nrfx/doc/buildfiles/extra_stylesheet.css b/modules/nrfx/doc/buildfiles/extra_stylesheet.css new file mode 100644 index 0000000..3b53f26 --- /dev/null +++ b/modules/nrfx/doc/buildfiles/extra_stylesheet.css @@ -0,0 +1,506 @@ +.appliesto {background-color:#3D578C;color:#fff} + +div.header +{ + background-image:none; + background-color: #FFF; + border-bottom: 0px; +} + +body, table, div, p, dl { + font-size: 16px; + font-family: Open Sans, Calibri, Arial, Sans-Serif; + color: #474747; + line-height: 20px; + +} + +a.code { + color: #1c99c7; +} + +a.el { + font-weight: normal; +} + +.contents a:visited, a:visited.code { + color: #16779a; +} + +.title { + font-size: 1.34em +} + +h1 { + font-size: 1.25em +} + +h2 { + font-size: 1.15em +} + +h3 { + font-size: 1.05em +} + +h4 { + font-size: 1em +} + +table.memberdecls, table.directory, table.memname { + margin:0px; + border:0px; + -moz-box-shadow: 0 0px 0px #d1d1d1; + -webkit-box-shadow: 0 0px 0px #d1d1d1; + box-shadow: 0 0px 0px #d1d1d1; +} + +table.memberdecls tr { + padding-left:0px; +} + +table.memberdecls tr:hover td, table.memname tr:hover td { + background: inherit; +} + +table.directory tr.even, table.directory tr.odd { + background: inherit; +} + +table.memberdecls td, table.directory td, table.directory td.desc { + border:0px; + padding: 2px 0px 0px; +} + +table.memberdecls td.memSeparator { + background-color:#inherit; + padding:2px; + border-bottom: 1px dotted #DEE4F0; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: inherit; +} + +div.levels { + display:none; +} + +table.retval { +border:#ccc 1px solid; +} + + +table.memname td, table.params td, table.retval td { +padding:5px; +border:0px; +} + +div.fragment div.line { +font-size: 14px; +line-height:18px; +} + +table.fieldtable, table.params, table.retval { + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.fieldtable th { + border:none; + border-bottom:1px solid #A8B8D9; +} + +table.blank, table.blank tr th, table.blank tr td { + border:none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.blank tr:hover td { + background: #ffffff; +} + + +#projectlogo +{ + text-align: left; + vertical-align: middle; + border-collapse: separate; +} + +#projectname +{ + font-size: 40px; + font-family: Open Sans, Calibri, Arial, Sans-Serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font-size: 30px; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + border-bottom: 1px solid #e0e0e0; +} + +.label a, .item a +{ + border-bottom: none; + +} + +#nav-tree { + background-image: none; + background-color: #FAFAFA; +} + +div.contents { + margin-left: 30px; + margin-right: 30px; + +} + +div.header { + margin-left: 20px; +} + +table td.doclinks a { + font-size: 12px; + font-style: italic; + color: #e97c25; + border: 1px solid #e97c25; + padding: 2px 5px; + text-decoration: none; +} + +table td.docselected a { + background: #e97c25; + color: #fff; +} + +table td.doclinkintro { + font-size: 12px; + font-style: italic; +} + + +/* nordic.css */ +.p { + margin-top: .3em; +} + +/* fix for table spacing */ +td p.p { + margin: 0em; + padding: 0px; +} +dt.line_sep { + border-top: solid #c9c9c9 1px; + padding-top: 5px; + +} + +a +{ + color: #1c99c7; + text-decoration: none; + border-bottom: 1px #e5e5e5 solid; + +} + +a:visited +{ + color: #16779a; +} +a:hover +{ + color: #none; + text-decoration: underline; + border: none; +} + +a:active +{ + +} + +ul.ul { + margin-top: 4px; + margin-bottom: 10px; +} + + +a[href*='.pdf'] { +background:transparent url(./pdf.png) center left no-repeat; +padding-left:22px; +line-height:18px; +} + + +a[href*='.zip'] { +background:transparent url(./zip_s.png) center left no-repeat; +padding-left:22px; +line-height:18px; +} + +a[href*='.exe'] { +background:transparent url(./execute_s.png) center left no-repeat; +padding-left:22px; +line-height:18px; +} + +a[href*='.msi'] { +background:transparent url(./msi_s.png) center left no-repeat; +padding-left:22px; +line-height:18px; +} + +table a:link { + color: #1c99c7; + text-decoration: none; + border-bottom: 1px #e5e5e5 solid; +} +table a:visited { + color: #16779a; +} +table a:active, +table a:hover { + color: #none; + text-decoration: underline; + border: none; +} +table { + font-family:Calibri, Arial, Sans-Serif; + color:#474747; + font-size:16px; + margin-left: auto; + margin-right: auto; + border:#ccc 1px solid; + + + -moz-box-shadow: 0 1px 2px #d1d1d1; + -webkit-box-shadow: 0 1px 2px #d1d1d1; + box-shadow: 0 1px 2px #d1d1d1; +} +table th { + color: #000; + font-size: 18px; + font-weight: bold; + text-align: left; + padding:10px 15px 10px 10px; + border-top:1px solid #7eceed; + border-bottom:1px solid #7eceed; + border-right:1px solid #7eceed; + border-left:1px solid #7eceed; + + background: #7eceed; + background: -webkit-gradient(linear, left top, left bottom, from(#7eceed), to(#7eceed)); + background: -moz-linear-gradient(top, #7eceed, #7eceed); +} + +table th.center { + text-align: center; +} +table tr { + text-align: left; + +} +table td { + padding:5px 5px 5px 10px; + border-top: 1px solid #ffffff; + border-bottom:1px solid #e0e0e0; + border-left: 1px solid #e0e0e0; + border-right: 1px solid #e0e0e0; + +} +table tr:hover td { + background: #ebebeb; + background: -webkit-gradient(linear, left top, left bottom, from(#f2f2f2), to(#f0f0f0)); + background: -moz-linear-gradient(top, #f2f2f2, #f0f0f0); +} + + + + +img { + border: 0; + margin-left: auto; + margin-right: auto; + max-width:100%; +} + + +/* make svg files scale in IE. compatible with Dita OT v2.0 +img:not(.png) { + width: 100%; + margin-left: auto; + margin-right: auto; +} +*/ + + +/* make svg files scale in IE */ +embed.image:not(.png):not(.gif):not(.jpg) { + width: 100%; + margin-left: auto; + margin-right: auto; + margin-bottom: 15px; +} + +svg { + position: absolute; + top: 0; + left: 0; + +} + +caption { + caption-side: bottom; + text-align: center; + font-size: 100%; + font-weight: bold; + margin-top: 15px; + margin-bottom: 35px; + + } + +figdesc { + caption-side: bottom; + text-align: center; + font-size: 100%; + font-weight: bold; + margin-top: 15px; + margin-bottom: 20px; + + } + +/* to get figure captions to appear below the image and center */ + +div.fig { + display: table; + width: 100%; + margin-top: 10px; + margin-bottom: 55px; +} + +div.fig span.figcap { + display:table-footer-group; + text-align:center; + font-size: 100%; + font-weight: bold; + margin-top: 10px; + margin-bottom: 20px; + font-style: normal; +} +div.fig div.imagecenter { + display:table-row-group; +} + + +/* fix to hide borders in image maps (Chrome only) */ +img.map, map area{ + outline: none; +} + + +/* fix placement of ® */ +sup { + line-height: 1em; +} + +.sdkversion span { + font-size: 12px; + font-style: italic; + color: #e97c25; + border: 1px solid #e97c25; + padding: 2px 5px; +} + +.sdkversion { + text-align: right; +} + +.whichSDs span,.whichnRF span { + font-size: 12px; + font-style: italic; + color: #e97c25; + border: 1px solid #e97c25; + padding: 2px 5px; + } + +.whichSDs.nRF52 span,.whichnRF.nRF52 span { + color: #e97c25; + border-color: #e97c25; +} + +.whichSDs.nRF52840 span,.whichnRF.nRF52840 span { + color: #0081B7; + border-color: #0081B7; +} + +.whichSDs.nRF51 span,.whichnRF.nRF51 span { + color: #7f7f7f; + border-color: #7f7f7f; +} + +div.whichnRF { + padding-bottom: 5px; +} + +span.whichnRF{ + font-size: 12px; + font-style: italic; + color: #e97c25; + border: 1px solid #e97c25; + padding: 2px 5px; +} + +span.whichnRF.nRF52 { + color: #e97c25; + border-color: #e97c25; +} + +span.whichnRF.nRF52840 { + color: #0081B7; + border-color: #0081B7; +} + +span.whichnRF.nRF51 { + color: #7f7f7f; + border-color: #7f7f7f; +} + +.orange { + color: #e97c25; +} + +hr { + margin-top:20px; + border-top:1px solid #8EA7B0; +} + + +.directory td.entry { + white-space: normal; + width:50%; +} + +/* overrides */ +.topicfooter { + text-align: right; +// margin-top: 1px; + padding-right: 10px; + box-shadow: inset 0px 1px 0px 0px #e0e0e0; + font-size: 13px; +} + diff --git a/modules/nrfx/doc/buildfiles/favicon.ico b/modules/nrfx/doc/buildfiles/favicon.ico new file mode 100644 index 0000000..0bd6cc0 Binary files /dev/null and b/modules/nrfx/doc/buildfiles/favicon.ico differ diff --git a/modules/nrfx/doc/buildfiles/footer.html b/modules/nrfx/doc/buildfiles/footer.html new file mode 100644 index 0000000..974fce9 --- /dev/null +++ b/modules/nrfx/doc/buildfiles/footer.html @@ -0,0 +1,10 @@ + + + diff --git a/modules/nrfx/doc/buildfiles/header.html b/modules/nrfx/doc/buildfiles/header.html new file mode 100644 index 0000000..1c3b27e --- /dev/null +++ b/modules/nrfx/doc/buildfiles/header.html @@ -0,0 +1,58 @@ + + + + + + + +$projectname $projectnumber: $title +$title + + + +$treeview +$search +$mathjax + +$extrastylesheet + + + + + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + +
    +
    $projectname +  $projectnumber +
    +
    $projectbrief
    +
    +
    $projectbrief
    +
    $searchbox
    +
    + + diff --git a/modules/nrfx/doc/buildfiles/layout.xml b/modules/nrfx/doc/buildfiles/layout.xml new file mode 100644 index 0000000..3bd29b7 --- /dev/null +++ b/modules/nrfx/doc/buildfiles/layout.xml @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/nrfx/doc/buildfiles/nordic_small.png b/modules/nrfx/doc/buildfiles/nordic_small.png new file mode 100644 index 0000000..9ebfb7b Binary files /dev/null and b/modules/nrfx/doc/buildfiles/nordic_small.png differ diff --git a/modules/nrfx/doc/drv_supp_matrix.dox b/modules/nrfx/doc/drv_supp_matrix.dox new file mode 100644 index 0000000..74da4c5 --- /dev/null +++ b/modules/nrfx/doc/drv_supp_matrix.dox @@ -0,0 +1,55 @@ +/** +@page nrfx_drv_supp_matrix Driver support matrix +The following matrix shows which drivers are supported by specific Nordic SoCs. +@{ + +Driver | nRF51 Series | nRF52810/nRF52811 | nRF52820 | nRF52832 | nRF52833 | nRF52840 | nRF9160 | +-----------------|--------------|-------------------| -------------| -------------| -------------| -------------| -------------| +@ref nrf_aar |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_adc |@tagGreenTick |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross | +@ref nrf_acl |@tagRedCross |@tagRedCross |@tagGreenTick |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_bprot |@tagRedCross |@tagGreenTick |@tagRedCross |@tagGreenTick |@tagRedCross |@tagRedCross |@tagRedCross | +@ref nrf_ccm |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_clock |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_comp |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_dppi |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagGreenTick | +@ref nrf_ecb |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_ficr |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_gpio |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_gpiote |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_i2s |@tagRedCross |@tagRedCross |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_kmu |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagGreenTick | +@ref nrf_lpcomp |@tagGreenTick |@tagRedCross |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_mpu |@tagGreenTick |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross | +@ref nrf_mwu |@tagRedCross |@tagRedCross |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_nfct |@tagRedCross |@tagRedCross |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_nvmc |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_pdm |@tagRedCross |@tagGreenTick |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_power |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_ppi |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_pwm |@tagRedCross |@tagGreenTick |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_qdec |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_qspi |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagGreenTick |@tagRedCross | +@ref nrf_radio |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_rng |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_rtc |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_saadc |@tagRedCross |@tagGreenTick |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_spi |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_spim |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_spis |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_spu |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagGreenTick | +@ref nrf_systick |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_swi_egu |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_temp |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_timer |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_twi |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_twim |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_twis |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_uart |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_uarte |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | +@ref nrf_usbd |@tagRedCross |@tagRedCross |@tagGreenTick |@tagRedCross |@tagGreenTick |@tagGreenTick |@tagRedCross | +@ref nrf_vmc |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagRedCross |@tagGreenTick | +@ref nrf_wdt |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick |@tagGreenTick | + +@} +*/ diff --git a/modules/nrfx/doc/generate_html_doc.bat b/modules/nrfx/doc/generate_html_doc.bat new file mode 100644 index 0000000..f63b3e7 --- /dev/null +++ b/modules/nrfx/doc/generate_html_doc.bat @@ -0,0 +1,2 @@ +del html\*.* /Q +doxygen nrfx.doxyfile diff --git a/modules/nrfx/doc/generate_html_doc.sh b/modules/nrfx/doc/generate_html_doc.sh new file mode 100644 index 0000000..9cc608c --- /dev/null +++ b/modules/nrfx/doc/generate_html_doc.sh @@ -0,0 +1,2 @@ +rm -rf html +doxygen nrfx.doxyfile diff --git a/modules/nrfx/doc/main_page.dox b/modules/nrfx/doc/main_page.dox new file mode 100644 index 0000000..6ff79d7 --- /dev/null +++ b/modules/nrfx/doc/main_page.dox @@ -0,0 +1,89 @@ +/** +@mainpage Introduction + +@em nrfx is a standalone set of drivers for peripherals present in Nordic +Semiconductor's SoCs. It originated as an extract from the nRF5 SDK. +The intention was to provide drivers that can be used in various environments +without the necessity to integrate other parts of the SDK into them. +For the user's convenience, the drivers come with the MDK package. This package +contains definitions of register structures and bitfields for all supported +SoCs, as well as startup and initialization files for them. + +Refer to the @ref nrfx_drv_supp_matrix to check which drivers are suitable +for a given SoC. + +@section nrfx_integration Integration + +The purpose of @em nrfx is to make it possible to use the same set of peripheral +drivers in various environments, from RTOSes to bare metal applications. +Hence, for a given host environment, a light integration layer must be provided +that implements certain specific routines, like interrupt management, critical +sections, assertions, or logging. This is done by filling a predefined set of +macros with proper implementations (or keeping some empty if desired) in files +named: +- @ref nrfx_glue +- @ref nrfx_log + +Templates of these files are provided +in the templates subfolder. Their customized +versions can be placed in any location within the host environment that the +used compiler can access via include paths. + +In addition, the following locations should be specified as include paths +([nrfx] stands for the @em nrfx root folder location): +@code +[nrfx]/ +[nrfx]/drivers/include +[nrfx]/mdk +@endcode + +@section nrfx_irq_handlers IRQ handlers + +The IRQ handlers in all drivers are implemented as ordinary API functions +named "nrfx_*_irq_handler". They can be bound to some structures or called in +a specific way according to the requirements of the host environment. +To install the handlers in the standard MDK way, you must only add the following +line to the @ref nrfx_glue file: + +@code +#include +@endcode + +This will cause the preprocessor to properly rename all the IRQ handler +functions so that the linker could install them in the vector table. + +@section nrfx_configuration Configuration + +The drivers use both dynamic (run time) and static (compile time) configuration. + +Dynamic configuration is done by specifying desired options in configuration +structures passed to the drivers during their initialization. +Refer to the API reference for a given driver to see the members of its +configuration structure. + +Static configuration allows enabling and disabling (excluding their code from +compilation) particular drivers or in some cases their specific features, +defining default parameters for dynamic configuration, parametrization of +logging in particular drivers. It is done by specifying desired values of macros +in a file named: + +- nrfx_config.h + +This file, similarly to the integration files mentioned above, can be placed +in any suitable location within the host environment. +The templates subfolder contains templates of +configuration files for all currently supported Nordic SoCs placed in respective +subfolders. +Refer to the "driver configuration" section in the API reference for a given +driver for more information regarding configuration options available for it. + +@section nrfx_additional_reqs Additional requirements + +Nordic SoCs are based on ARM® Cortex™-M series processors. Before you can +start developing with @em nrfx, you must add the CMSIS header files to include +paths during the compilation process. Download these files from the following +website: + +- ARM® CMSIS repository +(CMSIS/Include directory) +*/ diff --git a/modules/nrfx/doc/nrf51_series.dox b/modules/nrfx/doc/nrf51_series.dox new file mode 100644 index 0000000..3f8201f --- /dev/null +++ b/modules/nrfx/doc/nrf51_series.dox @@ -0,0 +1,56 @@ +/** +@page nrf51_series_drivers nRF51 Series Drivers +@{ + +@ref nrf_aar + +@ref nrf_adc + +@ref nrf_ccm + +@ref nrf_clock + +@ref nrf_ecb + +@ref nrf_ficr + +@ref nrf_gpio + +@ref nrf_gpiote + +@ref nrf_lpcomp + +@ref nrf_mpu + +@ref nrf_nvmc + +@ref nrf_power + +@ref nrf_ppi + +@ref nrf_qdec + +@ref nrf_radio + +@ref nrf_rng + +@ref nrf_rtc + +@ref nrf_spi + +@ref nrf_spis + +@ref nrf_swi_egu + +@ref nrf_temp + +@ref nrf_timer + +@ref nrf_twi + +@ref nrf_uart + +@ref nrf_wdt + +@} +*/ diff --git a/modules/nrfx/doc/nrf52810.dox b/modules/nrfx/doc/nrf52810.dox new file mode 100644 index 0000000..6aba434 --- /dev/null +++ b/modules/nrfx/doc/nrf52810.dox @@ -0,0 +1,70 @@ +/** +@page nrf52810_drivers nRF52810/nRF52811 Drivers +@{ + +@ref nrf_aar + +@ref nrf_bprot + +@ref nrf_ccm + +@ref nrf_clock + +@ref nrf_comp + +@ref nrf_ecb + +@ref nrf_ficr + +@ref nrf_gpio + +@ref nrf_gpiote + +@ref nrf_nvmc + +@ref nrf_pdm + +@ref nrf_power + +@ref nrf_ppi + +@ref nrf_pwm + +@ref nrf_qdec + +@ref nrf_radio + +@ref nrf_rng + +@ref nrf_rtc + +@ref nrf_saadc + +@ref nrf_spi + +@ref nrf_spim + +@ref nrf_spis + +@ref nrf_systick + +@ref nrf_swi_egu + +@ref nrf_temp + +@ref nrf_timer + +@ref nrf_twi + +@ref nrf_twim + +@ref nrf_twis + +@ref nrf_uart + +@ref nrf_uarte + +@ref nrf_wdt + +@} +*/ diff --git a/modules/nrfx/doc/nrf52820.dox b/modules/nrfx/doc/nrf52820.dox new file mode 100644 index 0000000..a858b12 --- /dev/null +++ b/modules/nrfx/doc/nrf52820.dox @@ -0,0 +1,66 @@ +/** +@page nrf52820_drivers nRF52820 Drivers +@{ + +@ref nrf_aar + +@ref nrf_acl + +@ref nrf_ccm + +@ref nrf_clock + +@ref nrf_comp + +@ref nrf_ecb + +@ref nrf_ficr + +@ref nrf_gpio + +@ref nrf_gpiote + +@ref nrf_nvmc + +@ref nrf_power + +@ref nrf_ppi + +@ref nrf_qdec + +@ref nrf_radio + +@ref nrf_rng + +@ref nrf_rtc + +@ref nrf_spi + +@ref nrf_spim + +@ref nrf_spis + +@ref nrf_systick + +@ref nrf_swi_egu + +@ref nrf_temp + +@ref nrf_timer + +@ref nrf_twi + +@ref nrf_twim + +@ref nrf_twis + +@ref nrf_uart + +@ref nrf_uarte + +@ref nrf_usbd + +@ref nrf_wdt + +@} +*/ diff --git a/modules/nrfx/doc/nrf52832.dox b/modules/nrfx/doc/nrf52832.dox new file mode 100644 index 0000000..58f3bbd --- /dev/null +++ b/modules/nrfx/doc/nrf52832.dox @@ -0,0 +1,78 @@ +/** +@page nrf52832_drivers nRF52832 Drivers +@{ + +@ref nrf_aar + +@ref nrf_bprot + +@ref nrf_ccm + +@ref nrf_clock + +@ref nrf_comp + +@ref nrf_ecb + +@ref nrf_ficr + +@ref nrf_gpio + +@ref nrf_gpiote + +@ref nrf_i2s + +@ref nrf_lpcomp + +@ref nrf_mwu + +@ref nrf_nfct + +@ref nrf_nvmc + +@ref nrf_pdm + +@ref nrf_power + +@ref nrf_ppi + +@ref nrf_pwm + +@ref nrf_qdec + +@ref nrf_radio + +@ref nrf_rng + +@ref nrf_rtc + +@ref nrf_saadc + +@ref nrf_spi + +@ref nrf_spim + +@ref nrf_spis + +@ref nrf_systick + +@ref nrf_swi_egu + +@ref nrf_temp + +@ref nrf_timer + +@ref nrf_twi + +@ref nrf_twim + +@ref nrf_twis + +@ref nrf_uart + +@ref nrf_uarte + +@ref nrf_wdt + +@} +*/ diff --git a/modules/nrfx/doc/nrf52833.dox b/modules/nrfx/doc/nrf52833.dox new file mode 100644 index 0000000..d2637d9 --- /dev/null +++ b/modules/nrfx/doc/nrf52833.dox @@ -0,0 +1,80 @@ +/** +@page nrf52833_drivers nRF52833 Drivers +@{ + +@ref nrf_aar + +@ref nrf_acl + +@ref nrf_ccm + +@ref nrf_clock + +@ref nrf_comp + +@ref nrf_ecb + +@ref nrf_ficr + +@ref nrf_gpio + +@ref nrf_gpiote + +@ref nrf_i2s + +@ref nrf_lpcomp + +@ref nrf_mwu + +@ref nrf_nfct + +@ref nrf_nvmc + +@ref nrf_pdm + +@ref nrf_power + +@ref nrf_ppi + +@ref nrf_pwm + +@ref nrf_qdec + +@ref nrf_radio + +@ref nrf_rng + +@ref nrf_rtc + +@ref nrf_saadc + +@ref nrf_spi + +@ref nrf_spim + +@ref nrf_spis + +@ref nrf_systick + +@ref nrf_swi_egu + +@ref nrf_temp + +@ref nrf_timer + +@ref nrf_twi + +@ref nrf_twim + +@ref nrf_twis + +@ref nrf_uart + +@ref nrf_uarte + +@ref nrf_usbd + +@ref nrf_wdt + +@} +*/ diff --git a/modules/nrfx/doc/nrf52840.dox b/modules/nrfx/doc/nrf52840.dox new file mode 100644 index 0000000..7e9b51e --- /dev/null +++ b/modules/nrfx/doc/nrf52840.dox @@ -0,0 +1,82 @@ +/** +@page nrf52840_drivers nRF52840 Drivers +@{ + +@ref nrf_aar + +@ref nrf_acl + +@ref nrf_ccm + +@ref nrf_clock + +@ref nrf_comp + +@ref nrf_ecb + +@ref nrf_ficr + +@ref nrf_gpio + +@ref nrf_gpiote + +@ref nrf_i2s + +@ref nrf_lpcomp + +@ref nrf_mwu + +@ref nrf_nfct + +@ref nrf_nvmc + +@ref nrf_pdm + +@ref nrf_power + +@ref nrf_ppi + +@ref nrf_pwm + +@ref nrf_qdec + +@ref nrf_qspi + +@ref nrf_radio + +@ref nrf_rng + +@ref nrf_rtc + +@ref nrf_saadc + +@ref nrf_spi + +@ref nrf_spim + +@ref nrf_spis + +@ref nrf_systick + +@ref nrf_swi_egu + +@ref nrf_temp + +@ref nrf_timer + +@ref nrf_twi + +@ref nrf_twim + +@ref nrf_twis + +@ref nrf_uart + +@ref nrf_uarte + +@ref nrf_usbd + +@ref nrf_wdt + +@} +*/ diff --git a/modules/nrfx/doc/nrf9160.dox b/modules/nrfx/doc/nrf9160.dox new file mode 100644 index 0000000..fd929ad --- /dev/null +++ b/modules/nrfx/doc/nrf9160.dox @@ -0,0 +1,54 @@ +/** +@page nrf9160_drivers nRF9160 drivers +@{ + +@ref nrf_clock + +@ref nrf_systick + +@ref nrf_dppi + +@ref nrf_ficr + +@ref nrf_gpio + +@ref nrf_gpiote + +@ref nrf_i2s + +@ref nrf_kmu + +@ref nrf_nvmc + +@ref nrf_pdm + +@ref nrf_power + +@ref nrf_pwm + +@ref nrf_rtc + +@ref nrf_saadc + +@ref nrf_spim + +@ref nrf_spis + +@ref nrf_spu + +@ref nrf_swi_egu + +@ref nrf_timer + +@ref nrf_twim + +@ref nrf_twis + +@ref nrf_uarte + +@ref nrf_vmc + +@ref nrf_wdt + +@} +*/ diff --git a/modules/nrfx/doc/nrfx.doxyfile b/modules/nrfx/doc/nrfx.doxyfile new file mode 100644 index 0000000..2669410 --- /dev/null +++ b/modules/nrfx/doc/nrfx.doxyfile @@ -0,0 +1,2505 @@ +# Doxyfile 1.8.14 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "nrfx" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +### EDIT THIS ### + +PROJECT_NUMBER = "1.9" + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +### EDIT THIS ### + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = buildfiles/nordic_small.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +### EDIT THIS ### + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +#ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = .. + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. + +ALIASES = "tagGreenTick=@htmlonly
    @endhtmlonly" \ + "tagRedCross=@htmlonly
    @endhtmlonly" \ + "linkProductSpecification52=[nRF52840 Product Specification](http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52/dita/nrf52/chips/nrf52840_ps.html) or [nRF52832 Product Specification](http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52/dita/nrf52/chips/nrf52832_ps.html)" + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 0. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +#TOC_INCLUDE_HEADINGS = 0 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +#GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +#HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +#SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = NO + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = buildfiles/layout.xml + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +#WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = warnings_nrfx.txt + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +### EDIT THIS ### + +INPUT = ../helpers \ + ../drivers \ + ../hal \ + ../soc \ + ../templates \ + config_dox \ + . + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. + +FILE_PATTERNS = *.h \ + *.dox + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +#SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = NO + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse-libclang=ON option for CMake. +# The default value is: NO. + +#CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +#CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files +# were built. This is equivalent to specifying the "-p" option to a clang tool, +# such as clang-check. These options will then be passed to the parser. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse-libclang=ON option for CMake. +# The default value is: 0. + +#CLANG_COMPILATION_DATABASE_PATH = 0 + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = NO + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = buildfiles/header.html + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = buildfiles/footer.html + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = buildfiles/extra_stylesheet.css + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = buildfiles/favicon.ico + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 196 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 46 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 92 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +#HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: https://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://doc.qt.io/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = YES + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = com.nordic.infocenter.nrfx + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +### EDIT THIS ### + +DISABLE_INDEX = YES + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 1 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +#MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /